<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package auth

import (
	"context"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"time"

	certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	v1beta1client "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
	"k8s.io/client-go/util/cert"
	"k8s.io/kubernetes/test/e2e/framework"
	"k8s.io/kubernetes/test/utils"

	"github.com/onsi/ginkgo"
)

var _ = SIGDescribe("Certificates API", func() {
	f := framework.NewDefaultFramework("certificates")

	ginkgo.It("should support building a client with a CSR", func() {
		const commonName = "tester-csr"

		pk, err := utils.NewPrivateKey()
		framework.ExpectNoError(err)

		pkder := x509.MarshalPKCS1PrivateKey(pk)
		pkpem := pem.EncodeToMemory(&pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: pkder,
		})

		csrb, err := cert.MakeCSR(pk, &pkix.Name{CommonName: commonName, Organization: []string{"system:masters"}}, nil, nil)
		framework.ExpectNoError(err)

		csr := &certificatesv1beta1.CertificateSigningRequest{
			ObjectMeta: metav1.ObjectMeta{
				GenerateName: commonName + "-",
			},
			Spec: certificatesv1beta1.CertificateSigningRequestSpec{
				Request: csrb,
				Usages: []certificatesv1beta1.KeyUsage{
					certificatesv1beta1.UsageSigning,
					certificatesv1beta1.UsageKeyEncipherment,
					certificatesv1beta1.UsageClientAuth,
				},
			},
		}
		csrs := f.ClientSet.CertificatesV1beta1().CertificateSigningRequests()

		framework.Logf("creating CSR")
		csr, err = csrs.Create(context.TODO(), csr, metav1.CreateOptions{})
		framework.ExpectNoError(err)

		csrName := csr.Name

		framework.Logf("approving CSR")
		framework.ExpectNoError(wait.Poll(5*time.Second, time.Minute, func() (bool, error) {
			csr.Status.Conditions = []certificatesv1beta1.CertificateSigningRequestCondition{
				{
					Type:    certificatesv1beta1.CertificateApproved,
					Reason:  "E2E",
					Message: "Set from an e2e test",
				},
			}
			csr, err = csrs.UpdateApproval(context.TODO(), csr, metav1.UpdateOptions{})
			if err != nil {
				csr, _ = csrs.Get(context.TODO(), csrName, metav1.GetOptions{})
				framework.Logf("err updating approval: %v", err)
				return false, nil
			}
			return true, nil
		}))

		framework.Logf("waiting for CSR to be signed")
		framework.ExpectNoError(wait.Poll(5*time.Second, time.Minute, func() (bool, error) {
			csr, err = csrs.Get(context.TODO(), csrName, metav1.GetOptions{})
			if err != nil {
				framework.Logf("error getting csr: %v", err)
				return false, nil
			}
			if len(csr.Status.Certificate) == 0 {
				framework.Logf("csr not signed yet")
				return false, nil
			}
			return true, nil
		}))

		framework.Logf("testing the client")
		rcfg, err := framework.LoadConfig()
		framework.ExpectNoError(err)

		rcfg.TLSClientConfig.CertData = csr.Status.Certificate
		rcfg.TLSClientConfig.KeyData = pkpem
		rcfg.TLSClientConfig.CertFile = ""
		rcfg.BearerToken = ""
		rcfg.AuthProvider = nil
		rcfg.Username = ""
		rcfg.Password = ""

		newClient, err := v1beta1client.NewForConfig(rcfg)
		framework.ExpectNoError(err)
		framework.ExpectNoError(newClient.CertificateSigningRequests().Delete(context.TODO(), csrName, metav1.DeleteOptions{}))
	})
})
<commit_msg>Add CertificateSigningRequest API coverage tests<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package auth

import (
	"context"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"time"

	certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
	rbacv1 "k8s.io/api/rbac/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	types "k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/apimachinery/pkg/watch"
	certificatesclient "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/util/cert"
	"k8s.io/kubernetes/test/e2e/framework"
	"k8s.io/kubernetes/test/utils"

	"github.com/onsi/ginkgo"
)

var _ = SIGDescribe("Certificates API", func() {
	f := framework.NewDefaultFramework("certificates")

	/*
		Release: v1.19
		Testname: CertificateSigningRequest API Client Certificate
		Description:
		- The certificatesigningrequests resource must accept a request for a certificate signed by kubernetes.io/kube-apiserver-client.
		- The issued certificate must be valid as a client certificate used to authenticate to the kube-apiserver.
	*/
	ginkgo.It("should support building a client with a CSR", func() {
		const commonName = "tester-csr"

		csrClient := f.ClientSet.CertificatesV1beta1().CertificateSigningRequests()

		pk, err := utils.NewPrivateKey()
		framework.ExpectNoError(err)

		pkder := x509.MarshalPKCS1PrivateKey(pk)
		pkpem := pem.EncodeToMemory(&pem.Block{
			Type:  "RSA PRIVATE KEY",
			Bytes: pkder,
		})

		csrb, err := cert.MakeCSR(pk, &pkix.Name{CommonName: commonName}, nil, nil)
		framework.ExpectNoError(err)

		apiserverClientSigner := certificatesv1beta1.KubeAPIServerClientSignerName
		csrTemplate := &certificatesv1beta1.CertificateSigningRequest{
			ObjectMeta: metav1.ObjectMeta{
				GenerateName: commonName + "-",
			},
			Spec: certificatesv1beta1.CertificateSigningRequestSpec{
				Request: csrb,
				Usages: []certificatesv1beta1.KeyUsage{
					certificatesv1beta1.UsageDigitalSignature,
					certificatesv1beta1.UsageKeyEncipherment,
					certificatesv1beta1.UsageClientAuth,
				},
				SignerName: &apiserverClientSigner,
			},
		}

		// Grant permissions to the new user
		clusterRole, err := f.ClientSet.RbacV1().ClusterRoles().Create(context.TODO(), &rbacv1.ClusterRole{
			ObjectMeta: metav1.ObjectMeta{GenerateName: commonName + "-"},
			Rules:      []rbacv1.PolicyRule{{Verbs: []string{"create"}, APIGroups: []string{"certificates.k8s.io"}, Resources: []string{"certificatesigningrequests"}}},
		}, metav1.CreateOptions{})
		if err != nil {
			// Tolerate RBAC not being enabled
			framework.Logf("error granting permissions to %s, create certificatesigningrequests permissions must be granted out of band: %v", commonName, err)
		} else {
			defer func() {
				framework.ExpectNoError(f.ClientSet.RbacV1().ClusterRoles().Delete(context.TODO(), clusterRole.Name, metav1.DeleteOptions{}))
			}()
		}

		clusterRoleBinding, err := f.ClientSet.RbacV1().ClusterRoleBindings().Create(context.TODO(), &rbacv1.ClusterRoleBinding{
			ObjectMeta: metav1.ObjectMeta{GenerateName: commonName + "-"},
			RoleRef:    rbacv1.RoleRef{APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole", Name: clusterRole.Name},
			Subjects:   []rbacv1.Subject{{APIGroup: "rbac.authorization.k8s.io", Kind: "User", Name: commonName}},
		}, metav1.CreateOptions{})
		if err != nil {
			// Tolerate RBAC not being enabled
			framework.Logf("error granting permissions to %s, create certificatesigningrequests permissions must be granted out of band: %v", commonName, err)
		} else {
			defer func() {
				framework.ExpectNoError(f.ClientSet.RbacV1().ClusterRoleBindings().Delete(context.TODO(), clusterRoleBinding.Name, metav1.DeleteOptions{}))
			}()
		}

		framework.Logf("creating CSR")
		csr, err := csrClient.Create(context.TODO(), csrTemplate, metav1.CreateOptions{})
		framework.ExpectNoError(err)
		defer func() {
			framework.ExpectNoError(csrClient.Delete(context.TODO(), csr.Name, metav1.DeleteOptions{}))
		}()

		framework.Logf("approving CSR")
		framework.ExpectNoError(wait.Poll(5*time.Second, time.Minute, func() (bool, error) {
			csr.Status.Conditions = []certificatesv1beta1.CertificateSigningRequestCondition{
				{
					Type:    certificatesv1beta1.CertificateApproved,
					Reason:  "E2E",
					Message: "Set from an e2e test",
				},
			}
			csr, err = csrClient.UpdateApproval(context.TODO(), csr, metav1.UpdateOptions{})
			if err != nil {
				csr, _ = csrClient.Get(context.TODO(), csr.Name, metav1.GetOptions{})
				framework.Logf("err updating approval: %v", err)
				return false, nil
			}
			return true, nil
		}))

		framework.Logf("waiting for CSR to be signed")
		framework.ExpectNoError(wait.Poll(5*time.Second, time.Minute, func() (bool, error) {
			csr, err = csrClient.Get(context.TODO(), csr.Name, metav1.GetOptions{})
			if err != nil {
				framework.Logf("error getting csr: %v", err)
				return false, nil
			}
			if len(csr.Status.Certificate) == 0 {
				framework.Logf("csr not signed yet")
				return false, nil
			}
			return true, nil
		}))

		framework.Logf("testing the client")
		rcfg, err := framework.LoadConfig()
		framework.ExpectNoError(err)
		rcfg = rest.AnonymousClientConfig(rcfg)
		rcfg.TLSClientConfig.CertData = csr.Status.Certificate
		rcfg.TLSClientConfig.KeyData = pkpem

		newClient, err := certificatesclient.NewForConfig(rcfg)
		framework.ExpectNoError(err)

		framework.Logf("creating CSR as new client")
		newCSR, err := newClient.CertificateSigningRequests().Create(context.TODO(), csrTemplate, metav1.CreateOptions{})
		framework.ExpectNoError(err)
		defer func() {
			framework.ExpectNoError(csrClient.Delete(context.TODO(), newCSR.Name, metav1.DeleteOptions{}))
		}()
		framework.ExpectEqual(newCSR.Spec.Username, commonName)
	})

	/*
		Release: v1.19
		Testname: CertificateSigningRequest API
		Description:
		- The certificates.k8s.io API group MUST exists in the /apis discovery document.
		- The certificates.k8s.io/v1beta1 API group/version MUST exist in the /apis/certificates.k8s.io discovery document.
		- The certificatesigningrequests, certificatesigningrequests/approval, and certificatesigningrequests/status
		  resources MUST exist in the /apis/certificates.k8s.io/v1beta1 discovery document.
		- The certificatesigningrequests resource must support create, get, list, watch, update, patch, delete, and deletecollection.
		- The certificatesigningrequests/approval resource must support get, update, patch.
		- The certificatesigningrequests/status resource must support get, update, patch.
	*/
	ginkgo.It("should support CSR API operations [Privileged:ClusterAdmin]", func() {

		// Setup
		csrVersion := "v1beta1"
		csrClient := f.ClientSet.CertificatesV1beta1().CertificateSigningRequests()
		csrResource := certificatesv1beta1.SchemeGroupVersion.WithResource("certificatesigningrequests")

		pk, err := utils.NewPrivateKey()
		framework.ExpectNoError(err)

		csrData, err := cert.MakeCSR(pk, &pkix.Name{CommonName: "e2e.example.com"}, []string{"e2e.example.com"}, nil)
		framework.ExpectNoError(err)

		certificateData, _, err := cert.GenerateSelfSignedCertKey("e2e.example.com", nil, []string{"e2e.example.com"})
		framework.ExpectNoError(err)
		certificateDataJSON, err := json.Marshal(certificateData)
		framework.ExpectNoError(err)

		signerName := "example.com/e2e-" + f.UniqueName
		csrTemplate := &certificatesv1beta1.CertificateSigningRequest{
			ObjectMeta: metav1.ObjectMeta{GenerateName: "e2e-example-csr-"},
			Spec: certificatesv1beta1.CertificateSigningRequestSpec{
				Request:    csrData,
				SignerName: &signerName,
				Usages:     []certificatesv1beta1.KeyUsage{certificatesv1beta1.UsageDigitalSignature, certificatesv1beta1.UsageKeyEncipherment, certificatesv1beta1.UsageServerAuth},
			},
		}

		// Discovery

		ginkgo.By("getting /apis")
		{
			discoveryGroups, err := f.ClientSet.Discovery().ServerGroups()
			framework.ExpectNoError(err)
			found := false
			for _, group := range discoveryGroups.Groups {
				if group.Name == certificatesv1beta1.GroupName {
					for _, version := range group.Versions {
						if version.Version == csrVersion {
							found = true
							break
						}
					}
				}
			}
			framework.ExpectEqual(found, true, fmt.Sprintf("expected certificates API group/version, got %#v", discoveryGroups.Groups))
		}

		ginkgo.By("getting /apis/certificates.k8s.io")
		{
			group := &metav1.APIGroup{}
			err := f.ClientSet.Discovery().RESTClient().Get().AbsPath("/apis/certificates.k8s.io").Do(context.TODO()).Into(group)
			framework.ExpectNoError(err)
			found := false
			for _, version := range group.Versions {
				if version.Version == csrVersion {
					found = true
					break
				}
			}
			framework.ExpectEqual(found, true, fmt.Sprintf("expected certificates API version, got %#v", group.Versions))
		}

		ginkgo.By("getting /apis/certificates.k8s.io/" + csrVersion)
		{
			resources, err := f.ClientSet.Discovery().ServerResourcesForGroupVersion(certificatesv1beta1.SchemeGroupVersion.String())
			framework.ExpectNoError(err)
			foundCSR, foundApproval, foundStatus := false, false, false
			for _, resource := range resources.APIResources {
				switch resource.Name {
				case "certificatesigningrequests":
					foundCSR = true
				case "certificatesigningrequests/approval":
					foundApproval = true
				case "certificatesigningrequests/status":
					foundStatus = true
				}
			}
			framework.ExpectEqual(foundCSR, true, fmt.Sprintf("expected certificatesigningrequests, got %#v", resources.APIResources))
			framework.ExpectEqual(foundApproval, true, fmt.Sprintf("expected certificatesigningrequests/approval, got %#v", resources.APIResources))
			framework.ExpectEqual(foundStatus, true, fmt.Sprintf("expected certificatesigningrequests/status, got %#v", resources.APIResources))
		}

		// Main resource create/read/update/watch operations

		ginkgo.By("creating")
		_, err = csrClient.Create(context.TODO(), csrTemplate, metav1.CreateOptions{})
		framework.ExpectNoError(err)
		_, err = csrClient.Create(context.TODO(), csrTemplate, metav1.CreateOptions{})
		framework.ExpectNoError(err)
		createdCSR, err := csrClient.Create(context.TODO(), csrTemplate, metav1.CreateOptions{})
		framework.ExpectNoError(err)

		ginkgo.By("getting")
		gottenCSR, err := csrClient.Get(context.TODO(), createdCSR.Name, metav1.GetOptions{})
		framework.ExpectNoError(err)
		framework.ExpectEqual(gottenCSR.UID, createdCSR.UID)

		ginkgo.By("listing")
		csrs, err := csrClient.List(context.TODO(), metav1.ListOptions{FieldSelector: "spec.signerName=" + signerName})
		framework.ExpectNoError(err)
		framework.ExpectEqual(len(csrs.Items), 3, "filtered list should have 3 items")

		ginkgo.By("watching")
		framework.Logf("starting watch")
		csrWatch, err := csrClient.Watch(context.TODO(), metav1.ListOptions{ResourceVersion: csrs.ResourceVersion, FieldSelector: "metadata.name=" + createdCSR.Name})
		framework.ExpectNoError(err)

		ginkgo.By("patching")
		patchedCSR, err := csrClient.Patch(context.TODO(), createdCSR.Name, types.MergePatchType, []byte(`{"metadata":{"annotations":{"patched":"true"}}}`), metav1.PatchOptions{})
		framework.ExpectNoError(err)
		framework.ExpectEqual(patchedCSR.Annotations["patched"], "true", "patched object should have the applied annotation")

		ginkgo.By("updating")
		csrToUpdate := patchedCSR.DeepCopy()
		csrToUpdate.Annotations["updated"] = "true"
		updatedCSR, err := csrClient.Update(context.TODO(), csrToUpdate, metav1.UpdateOptions{})
		framework.ExpectNoError(err)
		framework.ExpectEqual(updatedCSR.Annotations["updated"], "true", "updated object should have the applied annotation")

		framework.Logf("waiting for watch events with expected annotations")
		for sawAnnotations := false; !sawAnnotations; {
			select {
			case evt, ok := <-csrWatch.ResultChan():
				framework.ExpectEqual(ok, true, "watch channel should not close")
				framework.ExpectEqual(evt.Type, watch.Modified)
				watchedCSR, isCSR := evt.Object.(*certificatesv1beta1.CertificateSigningRequest)
				framework.ExpectEqual(isCSR, true, fmt.Sprintf("expected CSR, got %T", evt.Object))
				if watchedCSR.Annotations["patched"] == "true" {
					framework.Logf("saw patched and updated annotations")
					sawAnnotations = true
					csrWatch.Stop()
				} else {
					framework.Logf("missing expected annotations, waiting: %#v", watchedCSR.Annotations)
				}
			case <-time.After(wait.ForeverTestTimeout):
				framework.Fail("timed out waiting for watch event")
			}
		}

		// /approval subresource operations

		ginkgo.By("getting /approval")
		gottenApproval, err := f.DynamicClient.Resource(csrResource).Get(context.TODO(), createdCSR.Name, metav1.GetOptions{}, "approval")
		framework.ExpectNoError(err)
		framework.ExpectEqual(gottenApproval.GetObjectKind().GroupVersionKind(), certificatesv1beta1.SchemeGroupVersion.WithKind("CertificateSigningRequest"))
		framework.ExpectEqual(gottenApproval.GetUID(), createdCSR.UID)

		ginkgo.By("patching /approval")
		patchedApproval, err := csrClient.Patch(context.TODO(), createdCSR.Name, types.MergePatchType,
			[]byte(`{"metadata":{"annotations":{"patchedapproval":"true"}},"status":{"conditions":[{"type":"ApprovalPatch","status":"True","reason":"e2e"}]}}`),
			metav1.PatchOptions{}, "approval")
		framework.ExpectNoError(err)
		framework.ExpectEqual(len(patchedApproval.Status.Conditions), 1, fmt.Sprintf("patched object should have the applied condition, got %#v", patchedApproval.Status.Conditions))
		framework.ExpectEqual(string(patchedApproval.Status.Conditions[0].Type), "ApprovalPatch", fmt.Sprintf("patched object should have the applied condition, got %#v", patchedApproval.Status.Conditions))
		framework.ExpectEqual(patchedApproval.Annotations["patchedapproval"], "true", "patched object should have the applied annotation")

		ginkgo.By("updating /approval")
		approvalToUpdate := patchedApproval.DeepCopy()
		approvalToUpdate.Status.Conditions = append(approvalToUpdate.Status.Conditions, certificatesv1beta1.CertificateSigningRequestCondition{
			Type:    certificatesv1beta1.CertificateApproved,
			Reason:  "E2E",
			Message: "Set from an e2e test",
		})
		updatedApproval, err := csrClient.UpdateApproval(context.TODO(), approvalToUpdate, metav1.UpdateOptions{})
		framework.ExpectNoError(err)
		framework.ExpectEqual(len(updatedApproval.Status.Conditions), 2, fmt.Sprintf("updated object should have the applied condition, got %#v", updatedApproval.Status.Conditions))
		framework.ExpectEqual(updatedApproval.Status.Conditions[1].Type, certificatesv1beta1.CertificateApproved, fmt.Sprintf("updated object should have the approved condition, got %#v", updatedApproval.Status.Conditions))

		// /status subresource operations

		ginkgo.By("getting /status")
		gottenStatus, err := f.DynamicClient.Resource(csrResource).Get(context.TODO(), createdCSR.Name, metav1.GetOptions{}, "status")
		framework.ExpectNoError(err)
		framework.ExpectEqual(gottenStatus.GetObjectKind().GroupVersionKind(), certificatesv1beta1.SchemeGroupVersion.WithKind("CertificateSigningRequest"))
		framework.ExpectEqual(gottenStatus.GetUID(), createdCSR.UID)

		ginkgo.By("patching /status")
		patchedStatus, err := csrClient.Patch(context.TODO(), createdCSR.Name, types.MergePatchType,
			[]byte(`{"metadata":{"annotations":{"patchedstatus":"true"}},"status":{"certificate":`+string(certificateDataJSON)+`}}`),
			metav1.PatchOptions{}, "status")
		framework.ExpectNoError(err)
		framework.ExpectEqual(patchedStatus.Status.Certificate, certificateData, "patched object should have the applied certificate")
		framework.ExpectEqual(patchedStatus.Annotations["patchedstatus"], "true", "patched object should have the applied annotation")

		ginkgo.By("updating /status")
		statusToUpdate := patchedStatus.DeepCopy()
		statusToUpdate.Status.Conditions = append(statusToUpdate.Status.Conditions, certificatesv1beta1.CertificateSigningRequestCondition{
			Type:    "StatusUpdate",
			Reason:  "E2E",
			Message: "Set from an e2e test",
		})
		updatedStatus, err := csrClient.UpdateStatus(context.TODO(), statusToUpdate, metav1.UpdateOptions{})
		framework.ExpectNoError(err)
		framework.ExpectEqual(len(updatedStatus.Status.Conditions), len(statusToUpdate.Status.Conditions), fmt.Sprintf("updated object should have the applied condition, got %#v", updatedStatus.Status.Conditions))
		framework.ExpectEqual(string(updatedStatus.Status.Conditions[len(updatedStatus.Status.Conditions)-1].Type), "StatusUpdate", fmt.Sprintf("updated object should have the approved condition, got %#v", updatedStatus.Status.Conditions))

		// main resource delete operations

		ginkgo.By("deleting")
		err = csrClient.Delete(context.TODO(), createdCSR.Name, metav1.DeleteOptions{})
		framework.ExpectNoError(err)
		_, err = csrClient.Get(context.TODO(), createdCSR.Name, metav1.GetOptions{})
		framework.ExpectEqual(apierrors.IsNotFound(err), true, fmt.Sprintf("expected 404, got %#v", err))
		csrs, err = csrClient.List(context.TODO(), metav1.ListOptions{FieldSelector: "spec.signerName=" + signerName})
		framework.ExpectNoError(err)
		framework.ExpectEqual(len(csrs.Items), 2, "filtered list should have 2 items")

		ginkgo.By("deleting a collection")
		err = csrClient.DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{FieldSelector: "spec.signerName=" + signerName})
		framework.ExpectNoError(err)
		csrs, err = csrClient.List(context.TODO(), metav1.ListOptions{FieldSelector: "spec.signerName=" + signerName})
		framework.ExpectNoError(err)
		framework.ExpectEqual(len(csrs.Items), 0, "filtered list should have 0 items")
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package e2e_node

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"k8s.io/kubernetes/pkg/api"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/kubelet/server/stats"

	"github.com/davecgh/go-spew/spew"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Kubelet", func() {
	var cl *client.Client
	BeforeEach(func() {
		// Setup the apiserver client
		cl = client.NewOrDie(&client.Config{Host: *apiServerAddress})
	})

	Describe("pod scheduling", func() {
		Context("when scheduling a busybox command in a pod", func() {
			It("it should return succes", func() {
				pod := &api.Pod{
					ObjectMeta: api.ObjectMeta{
						Name:      "busybox",
						Namespace: api.NamespaceDefault,
					},
					Spec: api.PodSpec{
						// Force the Pod to schedule to the node without a scheduler running
						NodeName: *nodeName,
						// Don't restart the Pod since it is expected to exit
						RestartPolicy: api.RestartPolicyNever,
						Containers: []api.Container{
							{
								Image:   "gcr.io/google_containers/busybox",
								Name:    "busybox",
								Command: []string{"echo", "'Hello World'"},
							},
						},
					},
				}
				_, err := cl.Pods(api.NamespaceDefault).Create(pod)
				Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
			})

			It("it should print the output to logs", func() {
				Eventually(func() string {
					rc, err := cl.Pods(api.NamespaceDefault).GetLogs("busybox", &api.PodLogOptions{}).Stream()
					if err != nil {
						return ""
					}
					defer rc.Close()
					buf := new(bytes.Buffer)
					buf.ReadFrom(rc)
					return buf.String()
				}, time.Second*30, time.Second*4).Should(Equal("'Hello World'\n"))
			})

			It("it should be possible to delete", func() {
				err := cl.Pods(api.NamespaceDefault).Delete("busybox", &api.DeleteOptions{})
				Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
			})
		})
	})

	Describe("metrics api", func() {
		statsPrefix := "stats-busybox-"
		podNames := []string{}
		podCount := 2
		for i := 0; i < podCount; i++ {
			podNames = append(podNames, fmt.Sprintf("%s%v", statsPrefix, i))
		}
		BeforeEach(func() {
			for _, podName := range podNames {
				createPod(cl, podName, []api.Container{
					{
						Image:   "gcr.io/google_containers/busybox",
						Command: []string{"sh", "-c", "echo 'Hello World' | tee ~/file | tee /test-empty-dir-mnt | sleep 60"},
						Name:    podName + containerSuffix,
						VolumeMounts: []api.VolumeMount{
							{MountPath: "/test-empty-dir-mnt", Name: "test-empty-dir"},
						},
					},
				}, []api.Volume{
					// TODO: Test secret volumes
					// TODO: Test hostpath volumes
					{Name: "test-empty-dir", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
				})
			}

			// Sleep long enough for cadvisor to see the pod and calculate all of its metrics
			time.Sleep(60 * time.Second)
		})

		Context("when querying /stats/summary", func() {
			It("it should report resource usage through the stats api", func() {
				By("Returning stats summary")
				resp, err := http.Get(*kubeletAddress + "/stats/summary")
				now := time.Now()
				Expect(err).To(BeNil(), fmt.Sprintf("Failed to get /stats/summary"))
				summary := stats.Summary{}
				contentsBytes, err := ioutil.ReadAll(resp.Body)
				Expect(err).To(BeNil(), fmt.Sprintf("Failed to read /stats/summary: %+v", resp))
				contents := string(contentsBytes)
				decoder := json.NewDecoder(strings.NewReader(contents))
				err = decoder.Decode(&summary)
				Expect(err).To(BeNil(), fmt.Sprintf("Failed to parse /stats/summary to go struct: %+v", resp))

				By("Having the correct time")
				Expect(summary.Time.Time).To(BeTemporally("~", now, 20*time.Second))

				By("Having resources for node")
				Expect(summary.Node.NodeName).To(Equal(*nodeName))
				Expect(summary.Node.CPU.UsageCoreNanoSeconds).NotTo(BeNil())
				Expect(*summary.Node.CPU.UsageCoreNanoSeconds).NotTo(BeZero())

				Expect(summary.Node.Memory.UsageBytes).NotTo(BeNil())
				Expect(*summary.Node.Memory.UsageBytes).NotTo(BeZero())

				Expect(summary.Node.Memory.WorkingSetBytes).NotTo(BeNil())
				Expect(*summary.Node.Memory.WorkingSetBytes).NotTo(BeZero())

				Expect(summary.Node.Fs.AvailableBytes).NotTo(BeNil())
				Expect(*summary.Node.Fs.AvailableBytes).NotTo(BeZero())
				Expect(summary.Node.Fs.CapacityBytes).NotTo(BeNil())
				Expect(*summary.Node.Fs.CapacityBytes).NotTo(BeZero())
				Expect(summary.Node.Fs.UsedBytes).NotTo(BeNil())
				Expect(*summary.Node.Fs.UsedBytes).NotTo(BeZero())

				//				TODO: Enable these once system containers are working on all distros
				//				See issue #20993
				//				By("Having resources for kubelet and runtime system containers")
				//				sysContainers := map[string]stats.ContainerStats{}
				//				sysContainersList := []string{}
				//				for _, container := range summary.Node.SystemContainers {
				//					sysContainers[container.Name] = container
				//					sysContainersList = append(sysContainersList, container.Name)
				//					ExpectContainerStatsNotEmpty(&container)
				//				}
				//				Expect(sysContainersList).To(ConsistOf("kubelet", "runtime"))

				// Verify Pods Stats are present
				podsList := []string{}
				By("Having resources for pods")
				for _, pod := range summary.Pods {
					if !strings.HasPrefix(pod.PodRef.Name, statsPrefix) {
						// Ignore pods created outside this test
						continue
					}

					podsList = append(podsList, pod.PodRef.Name)

					Expect(pod.Containers).To(HaveLen(1))
					container := pod.Containers[0]
					Expect(container.Name).To(Equal(pod.PodRef.Name + containerSuffix))

					ExpectContainerStatsNotEmpty(&container)

					// emptydir volume
					volumeNames := []string{}
					for _, vs := range pod.VolumeStats {
						Expect(vs.CapacityBytes).NotTo(BeZero())
						Expect(vs.AvailableBytes).NotTo(BeZero())
						Expect(vs.UsedBytes).NotTo(BeZero())
						volumeNames = append(volumeNames, vs.Name)
					}
					Expect(volumeNames).To(ConsistOf("test-empty-dir"))

					// fs usage (not for system containers)
					Expect(container.Rootfs).NotTo(BeNil(), spew.Sdump(container))
					Expect(container.Rootfs.AvailableBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Rootfs.AvailableBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Rootfs.CapacityBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Rootfs.CapacityBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Rootfs.UsedBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Rootfs.UsedBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Logs).NotTo(BeNil(), spew.Sdump(container))
					Expect(container.Logs.AvailableBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Logs.AvailableBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Logs.CapacityBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Logs.CapacityBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Logs.UsedBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Logs.UsedBytes).NotTo(BeZero(), spew.Sdump(container))

				}
				Expect(podsList).To(ConsistOf(podNames))
			})
		})

		AfterEach(func() {
			for _, podName := range podNames {
				err := cl.Pods(api.NamespaceDefault).Delete(podName, &api.DeleteOptions{})
				Expect(err).To(BeNil(), fmt.Sprintf("Error deleting Pod %v", podName))
			}
		})
	})
})

func ExpectContainerStatsNotEmpty(container *stats.ContainerStats) {
	// TODO: Test Network

	Expect(container.CPU).NotTo(BeNil(), spew.Sdump(container))
	Expect(container.CPU.UsageCoreNanoSeconds).NotTo(BeNil(), spew.Sdump(container))
	Expect(*container.CPU.UsageCoreNanoSeconds).NotTo(BeZero(), spew.Sdump(container))

	Expect(container.Memory).NotTo(BeNil(), spew.Sdump(container))
	Expect(container.Memory.UsageBytes).NotTo(BeNil(), spew.Sdump(container))
	Expect(*container.Memory.UsageBytes).NotTo(BeZero(), spew.Sdump(container))
	Expect(container.Memory.WorkingSetBytes).NotTo(BeNil(), spew.Sdump(container))
	Expect(*container.Memory.WorkingSetBytes).NotTo(BeZero(), spew.Sdump(container))
}

const (
	containerSuffix = "-c"
)

func createPod(cl *client.Client, podName string, containers []api.Container, volumes []api.Volume) {
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      podName,
			Namespace: api.NamespaceDefault,
		},
		Spec: api.PodSpec{
			// Force the Pod to schedule to the node without a scheduler running
			NodeName: *nodeName,
			// Don't restart the Pod since it is expected to exit
			RestartPolicy: api.RestartPolicyNever,
			Containers:    containers,
			Volumes:       volumes,
		},
	}
	_, err := cl.Pods(api.NamespaceDefault).Create(pod)
	Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
}
<commit_msg>Revert "node e2e tests - disable testing metrics for system containers"<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package e2e_node

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"k8s.io/kubernetes/pkg/api"
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/kubelet/server/stats"

	"github.com/davecgh/go-spew/spew"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Kubelet", func() {
	var cl *client.Client
	BeforeEach(func() {
		// Setup the apiserver client
		cl = client.NewOrDie(&client.Config{Host: *apiServerAddress})
	})

	Describe("pod scheduling", func() {
		Context("when scheduling a busybox command in a pod", func() {
			It("it should return succes", func() {
				pod := &api.Pod{
					ObjectMeta: api.ObjectMeta{
						Name:      "busybox",
						Namespace: api.NamespaceDefault,
					},
					Spec: api.PodSpec{
						// Force the Pod to schedule to the node without a scheduler running
						NodeName: *nodeName,
						// Don't restart the Pod since it is expected to exit
						RestartPolicy: api.RestartPolicyNever,
						Containers: []api.Container{
							{
								Image:   "gcr.io/google_containers/busybox",
								Name:    "busybox",
								Command: []string{"echo", "'Hello World'"},
							},
						},
					},
				}
				_, err := cl.Pods(api.NamespaceDefault).Create(pod)
				Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
			})

			It("it should print the output to logs", func() {
				Eventually(func() string {
					rc, err := cl.Pods(api.NamespaceDefault).GetLogs("busybox", &api.PodLogOptions{}).Stream()
					if err != nil {
						return ""
					}
					defer rc.Close()
					buf := new(bytes.Buffer)
					buf.ReadFrom(rc)
					return buf.String()
				}, time.Second*30, time.Second*4).Should(Equal("'Hello World'\n"))
			})

			It("it should be possible to delete", func() {
				err := cl.Pods(api.NamespaceDefault).Delete("busybox", &api.DeleteOptions{})
				Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
			})
		})
	})

	Describe("metrics api", func() {
		statsPrefix := "stats-busybox-"
		podNames := []string{}
		podCount := 2
		for i := 0; i < podCount; i++ {
			podNames = append(podNames, fmt.Sprintf("%s%v", statsPrefix, i))
		}
		BeforeEach(func() {
			for _, podName := range podNames {
				createPod(cl, podName, []api.Container{
					{
						Image:   "gcr.io/google_containers/busybox",
						Command: []string{"sh", "-c", "echo 'Hello World' | tee ~/file | tee /test-empty-dir-mnt | sleep 60"},
						Name:    podName + containerSuffix,
						VolumeMounts: []api.VolumeMount{
							{MountPath: "/test-empty-dir-mnt", Name: "test-empty-dir"},
						},
					},
				}, []api.Volume{
					// TODO: Test secret volumes
					// TODO: Test hostpath volumes
					{Name: "test-empty-dir", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
				})
			}

			// Sleep long enough for cadvisor to see the pod and calculate all of its metrics
			time.Sleep(60 * time.Second)
		})

		Context("when querying /stats/summary", func() {
			It("it should report resource usage through the stats api", func() {
				By("Returning stats summary")
				resp, err := http.Get(*kubeletAddress + "/stats/summary")
				now := time.Now()
				Expect(err).To(BeNil(), fmt.Sprintf("Failed to get /stats/summary"))
				summary := stats.Summary{}
				contentsBytes, err := ioutil.ReadAll(resp.Body)
				Expect(err).To(BeNil(), fmt.Sprintf("Failed to read /stats/summary: %+v", resp))
				contents := string(contentsBytes)
				decoder := json.NewDecoder(strings.NewReader(contents))
				err = decoder.Decode(&summary)
				Expect(err).To(BeNil(), fmt.Sprintf("Failed to parse /stats/summary to go struct: %+v", resp))

				By("Having the correct time")
				Expect(summary.Time.Time).To(BeTemporally("~", now, 20*time.Second))

				By("Having resources for node")
				Expect(summary.Node.NodeName).To(Equal(*nodeName))
				Expect(summary.Node.CPU.UsageCoreNanoSeconds).NotTo(BeNil())
				Expect(*summary.Node.CPU.UsageCoreNanoSeconds).NotTo(BeZero())

				Expect(summary.Node.Memory.UsageBytes).NotTo(BeNil())
				Expect(*summary.Node.Memory.UsageBytes).NotTo(BeZero())

				Expect(summary.Node.Memory.WorkingSetBytes).NotTo(BeNil())
				Expect(*summary.Node.Memory.WorkingSetBytes).NotTo(BeZero())

				Expect(summary.Node.Fs.AvailableBytes).NotTo(BeNil())
				Expect(*summary.Node.Fs.AvailableBytes).NotTo(BeZero())
				Expect(summary.Node.Fs.CapacityBytes).NotTo(BeNil())
				Expect(*summary.Node.Fs.CapacityBytes).NotTo(BeZero())
				Expect(summary.Node.Fs.UsedBytes).NotTo(BeNil())
				Expect(*summary.Node.Fs.UsedBytes).NotTo(BeZero())

				By("Having resources for kubelet and runtime system containers")
				sysContainers := map[string]stats.ContainerStats{}
				sysContainersList := []string{}
				for _, container := range summary.Node.SystemContainers {
					sysContainers[container.Name] = container
					sysContainersList = append(sysContainersList, container.Name)
					ExpectContainerStatsNotEmpty(&container)
				}
				Expect(sysContainersList).To(ConsistOf("kubelet", "runtime"))

				// Verify Pods Stats are present
				podsList := []string{}
				By("Having resources for pods")
				for _, pod := range summary.Pods {
					if !strings.HasPrefix(pod.PodRef.Name, statsPrefix) {
						// Ignore pods created outside this test
						continue
					}

					podsList = append(podsList, pod.PodRef.Name)

					Expect(pod.Containers).To(HaveLen(1))
					container := pod.Containers[0]
					Expect(container.Name).To(Equal(pod.PodRef.Name + containerSuffix))

					ExpectContainerStatsNotEmpty(&container)

					// emptydir volume
					volumeNames := []string{}
					for _, vs := range pod.VolumeStats {
						Expect(vs.CapacityBytes).NotTo(BeZero())
						Expect(vs.AvailableBytes).NotTo(BeZero())
						Expect(vs.UsedBytes).NotTo(BeZero())
						volumeNames = append(volumeNames, vs.Name)
					}
					Expect(volumeNames).To(ConsistOf("test-empty-dir"))

					// fs usage (not for system containers)
					Expect(container.Rootfs).NotTo(BeNil(), spew.Sdump(container))
					Expect(container.Rootfs.AvailableBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Rootfs.AvailableBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Rootfs.CapacityBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Rootfs.CapacityBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Rootfs.UsedBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Rootfs.UsedBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Logs).NotTo(BeNil(), spew.Sdump(container))
					Expect(container.Logs.AvailableBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Logs.AvailableBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Logs.CapacityBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Logs.CapacityBytes).NotTo(BeZero(), spew.Sdump(container))
					Expect(container.Logs.UsedBytes).NotTo(BeNil(), spew.Sdump(container))
					Expect(*container.Logs.UsedBytes).NotTo(BeZero(), spew.Sdump(container))

				}
				Expect(podsList).To(ConsistOf(podNames))
			})
		})

		AfterEach(func() {
			for _, podName := range podNames {
				err := cl.Pods(api.NamespaceDefault).Delete(podName, &api.DeleteOptions{})
				Expect(err).To(BeNil(), fmt.Sprintf("Error deleting Pod %v", podName))
			}
		})
	})
})

func ExpectContainerStatsNotEmpty(container *stats.ContainerStats) {
	// TODO: Test Network

	Expect(container.CPU).NotTo(BeNil(), spew.Sdump(container))
	Expect(container.CPU.UsageCoreNanoSeconds).NotTo(BeNil(), spew.Sdump(container))
	Expect(*container.CPU.UsageCoreNanoSeconds).NotTo(BeZero(), spew.Sdump(container))

	Expect(container.Memory).NotTo(BeNil(), spew.Sdump(container))
	Expect(container.Memory.UsageBytes).NotTo(BeNil(), spew.Sdump(container))
	Expect(*container.Memory.UsageBytes).NotTo(BeZero(), spew.Sdump(container))
	Expect(container.Memory.WorkingSetBytes).NotTo(BeNil(), spew.Sdump(container))
	Expect(*container.Memory.WorkingSetBytes).NotTo(BeZero(), spew.Sdump(container))
}

const (
	containerSuffix = "-c"
)

func createPod(cl *client.Client, podName string, containers []api.Container, volumes []api.Volume) {
	pod := &api.Pod{
		ObjectMeta: api.ObjectMeta{
			Name:      podName,
			Namespace: api.NamespaceDefault,
		},
		Spec: api.PodSpec{
			// Force the Pod to schedule to the node without a scheduler running
			NodeName: *nodeName,
			// Don't restart the Pod since it is expected to exit
			RestartPolicy: api.RestartPolicyNever,
			Containers:    containers,
			Volumes:       volumes,
		},
	}
	_, err := cl.Pods(api.NamespaceDefault).Create(pod)
	Expect(err).To(BeNil(), fmt.Sprintf("Error creating Pod %v", err))
}
<|endoftext|>


<commit_before>package auth

import (
	"crypto/hmac"
	"crypto/sha256"
	"fmt"
)

// GenerateClientToken generates client token based on project secret key and provided
// connection parameters such as user ID, timestamp and info JSON string.
func GenerateClientToken(secretKey, projectKey, user, timestamp, info string) string {
	token := hmac.New(sha256.New, []byte(secretKey))
	token.Write([]byte(projectKey))
	token.Write([]byte(user))
	token.Write([]byte(timestamp))
	token.Write([]byte(info))
	return fmt.Sprintf("%02x", token.Sum(nil))
}

// CheckClientToken validates correctness of provided (by client connection) token
// comparing it with generated one
func CheckClientToken(secretKey, projectKey, user, timestamp, info, providedToken string) bool {
	token := GenerateClientToken(secretKey, projectKey, user, timestamp, info)
	return hmac.Equal([]byte(token), []byte(providedToken))
}

// GenerateApiSign generates sign which is used to sign HTTP API requests
func GenerateApiSign(secretKey, projectKey, encodedData string) string {
	sign := hmac.New(sha256.New, []byte(secretKey))
	sign.Write([]byte(projectKey))
	sign.Write([]byte(encodedData))
	return fmt.Sprintf("%02x", sign.Sum(nil))
}

// CheckApiSign validates correctness of provided (in HTTP API request) sign
// comparing it with generated one
func CheckApiSign(secretKey, projectKey, encodedData, providedSign string) bool {
	sign := GenerateApiSign(secretKey, projectKey, encodedData)
	return hmac.Equal([]byte(sign), []byte(providedSign))
}

// GenerateChannelSign generates sign which is used to prove permission of
// client to subscribe on private channel
func GenerateChannelSign(secretKey, client, channel, channelData string) string {
	sign := hmac.New(sha256.New, []byte(secretKey))
	sign.Write([]byte(client))
	sign.Write([]byte(channel))
	sign.Write([]byte(channelData))
	return fmt.Sprintf("%02x", sign.Sum(nil))
}

// CheckChannelSign validates a correctness of provided (in subscribe client command)
// sign comparing it with generated one
func CheckChannelSign(secretKey, client, channel, channelData, providedSign string) bool {
	sign := GenerateChannelSign(secretKey, client, channel, channelData)
	return hmac.Equal([]byte(sign), []byte(providedSign))
}
<commit_msg>check token and sign length before generating reference one<commit_after>package auth

import (
	"crypto/hmac"
	"crypto/sha256"
	"fmt"
)

// Centrifugo uses sha256 as digest algorithm for HMAC tokens and signs
// so all correct tokens must be of fixed length set by HMACLength.
const (
	HMACLength = 64
)

// GenerateClientToken generates client token based on project secret key and provided
// connection parameters such as user ID, timestamp and info JSON string.
func GenerateClientToken(secretKey, projectKey, user, timestamp, info string) string {
	token := hmac.New(sha256.New, []byte(secretKey))
	token.Write([]byte(projectKey))
	token.Write([]byte(user))
	token.Write([]byte(timestamp))
	token.Write([]byte(info))
	return fmt.Sprintf("%02x", token.Sum(nil))
}

// CheckClientToken validates correctness of provided (by client connection) token
// comparing it with generated one
func CheckClientToken(secretKey, projectKey, user, timestamp, info, providedToken string) bool {
	if len(providedToken) != HMACLength {
		return false
	}
	token := GenerateClientToken(secretKey, projectKey, user, timestamp, info)
	return hmac.Equal([]byte(token), []byte(providedToken))
}

// GenerateApiSign generates sign which is used to sign HTTP API requests
func GenerateApiSign(secretKey, projectKey, encodedData string) string {
	sign := hmac.New(sha256.New, []byte(secretKey))
	sign.Write([]byte(projectKey))
	sign.Write([]byte(encodedData))
	return fmt.Sprintf("%02x", sign.Sum(nil))
}

// CheckApiSign validates correctness of provided (in HTTP API request) sign
// comparing it with generated one
func CheckApiSign(secretKey, projectKey, encodedData, providedSign string) bool {
	if len(providedSign) != HMACLength {
		return false
	}
	sign := GenerateApiSign(secretKey, projectKey, encodedData)
	return hmac.Equal([]byte(sign), []byte(providedSign))
}

// GenerateChannelSign generates sign which is used to prove permission of
// client to subscribe on private channel
func GenerateChannelSign(secretKey, client, channel, channelData string) string {
	sign := hmac.New(sha256.New, []byte(secretKey))
	sign.Write([]byte(client))
	sign.Write([]byte(channel))
	sign.Write([]byte(channelData))
	return fmt.Sprintf("%02x", sign.Sum(nil))
}

// CheckChannelSign validates a correctness of provided (in subscribe client command)
// sign comparing it with generated one
func CheckChannelSign(secretKey, client, channel, channelData, providedSign string) bool {
	if len(providedSign) != HMACLength {
		return false
	}
	sign := GenerateChannelSign(secretKey, client, channel, channelData)
	return hmac.Equal([]byte(sign), []byte(providedSign))
}
<|endoftext|>


<commit_before>// Copyright 2018 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package k8sTest

import (
	"fmt"

	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"
	. "github.com/onsi/gomega"
)

// ExpectKubeDNSReady is a wrapper around helpers/WaitKubeDNS. It asserts that
// the error returned by that function is nil.
func ExpectKubeDNSReady(vm *helpers.Kubectl) {
	err := vm.WaitKubeDNS()
	ExpectWithOffset(1, err).Should(BeNil(), "kube-dns was not able to get into ready state")

	err = vm.KubeDNSPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "kube-dns service not ready")
}

// ExpectCiliumReady is a wrapper around helpers/WaitForPods. It asserts that
// the error returned by that function is nil.
func ExpectCiliumReady(vm *helpers.Kubectl) {
	err := vm.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 600)
	ExpectWithOffset(1, err).Should(BeNil(), "cilium was not able to get into ready state")

	err = vm.CiliumPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "cilium pre-flight checks failed")
}

// ExpectAllPodsTerminated is a wrapper around helpers/WaitCleanAllTerminatingPods.
// It asserts that the error returned by that function is nil.
func ExpectAllPodsTerminated(vm *helpers.Kubectl) {
	err := vm.WaitCleanAllTerminatingPods(helpers.HelperTimeout)
	ExpectWithOffset(1, err).To(BeNil(), "terminating containers are not deleted after timeout")
}

// ExpectCEPUpdates is a wrapper around helpers/WaitCEPReady.
// It asserts that the error returned by that function is nil.
func ExpectCEPUpdates(vm *helpers.Kubectl) {
	err := vm.WaitCEPReady()
	ExpectWithOffset(1, err).To(BeNil(), "CEP does not updated correctly")
}

// ExpectETCDOperatorReady is a wrapper around helpers/WaitForNPods. It asserts
// the error returned by that function is nil.
func ExpectETCDOperatorReady(vm *helpers.Kubectl) {
	// Etcd operator creates 5 nodes (1 cilium-etcd-operator + 1 etcd-operator + 3 etcd nodes),
	// the new pods are added when the previous is ready,
	// so we need to wait until 5 pods are in ready state.
	// This is to avoid cases where a few pods are ready, but the
	// new one is not created yet.
	By("Waiting for all etcd-operator pods are ready")

	err := vm.WaitforNPods(helpers.KubeSystemNamespace, "-l io.cilium/app=etcd-operator", 5, 600)
	warningMessage := ""
	if err != nil {
		res := vm.Exec(fmt.Sprintf(
			"%s -n %s get pods -l io.cilium/app=etcd-operator",
			helpers.KubectlCmd, helpers.KubeSystemNamespace))
		warningMessage = res.Output().String()
	}
	Expect(err).To(BeNil(), "etcd-operator is not ready after timeout, pods status:\n %s", warningMessage)
}

// ExpectCiliumPreFlightInstallReady is a wrapper around helpers/WaitForNPods.
// It asserts the error returned by that function is nil.
func ExpectCiliumPreFlightInstallReady(vm *helpers.Kubectl) {
	By("Waiting for all cilium pre-flight pods to be ready")

	err := vm.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium-pre-flight-check", 600)
	warningMessage := ""
	if err != nil {
		res := vm.Exec(fmt.Sprintf(
			"%s -n %s get pods -l k8s-app=cilium-pre-flight-check",
			helpers.KubectlCmd, helpers.KubeSystemNamespace))
		warningMessage = res.Output().String()
	}
	Expect(err).To(BeNil(), "cilium pre-flight check is not ready after timeout, pods status:\n %s", warningMessage)
}

// ProvisionInfraPods deploys DNS, etcd-operator, and cilium into the kubernetes
// cluster of which vm is a member.
func ProvisionInfraPods(vm *helpers.Kubectl) {
	By("Installing DNS Deployment")
	_ = vm.Apply(helpers.DNSDeployment())

	By("Deploying etcd-operator")
	err := vm.DeployETCDOperator()
	Expect(err).To(BeNil(), "Unable to deploy etcd operator")

	By("Installing Cilium")
	err = vm.CiliumInstall(helpers.CiliumDefaultDSPatch, helpers.CiliumConfigMapPatch)
	Expect(err).To(BeNil(), "Cilium cannot be installed")

	ExpectCiliumReady(vm)
	ExpectETCDOperatorReady(vm)
	ExpectKubeDNSReady(vm)
}
<commit_msg>test: Optimize ExpectETCDOperatorReady<commit_after>// Copyright 2018 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package k8sTest

import (
	"fmt"

	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"
	. "github.com/onsi/gomega"
)

// ExpectKubeDNSReady is a wrapper around helpers/WaitKubeDNS. It asserts that
// the error returned by that function is nil.
func ExpectKubeDNSReady(vm *helpers.Kubectl) {
	err := vm.WaitKubeDNS()
	ExpectWithOffset(1, err).Should(BeNil(), "kube-dns was not able to get into ready state")

	err = vm.KubeDNSPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "kube-dns service not ready")
}

// ExpectCiliumReady is a wrapper around helpers/WaitForPods. It asserts that
// the error returned by that function is nil.
func ExpectCiliumReady(vm *helpers.Kubectl) {
	err := vm.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 600)
	ExpectWithOffset(1, err).Should(BeNil(), "cilium was not able to get into ready state")

	err = vm.CiliumPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "cilium pre-flight checks failed")
}

// ExpectAllPodsTerminated is a wrapper around helpers/WaitCleanAllTerminatingPods.
// It asserts that the error returned by that function is nil.
func ExpectAllPodsTerminated(vm *helpers.Kubectl) {
	err := vm.WaitCleanAllTerminatingPods(helpers.HelperTimeout)
	ExpectWithOffset(1, err).To(BeNil(), "terminating containers are not deleted after timeout")
}

// ExpectCEPUpdates is a wrapper around helpers/WaitCEPReady.
// It asserts that the error returned by that function is nil.
func ExpectCEPUpdates(vm *helpers.Kubectl) {
	err := vm.WaitCEPReady()
	ExpectWithOffset(1, err).To(BeNil(), "CEP does not updated correctly")
}

// ExpectETCDOperatorReady is a wrapper around helpers/WaitForNPods. It asserts
// the error returned by that function is nil.
func ExpectETCDOperatorReady(vm *helpers.Kubectl) {
	// Etcd operator creates 5 nodes (1 cilium-etcd-operator + 1 etcd-operator + 3 etcd nodes),
	// the new pods are added when the previous is ready,
	// At a minimum, we need to wait for 3 pods:
	//  - cilium-etcd-operator
	//  - etcd-operator
	//  - 1st etcd node
	By("Waiting for all etcd-operator pods are ready")

	err := vm.WaitforNPods(helpers.KubeSystemNamespace, "-l io.cilium/app=etcd-operator", 3, 600)
	warningMessage := ""
	if err != nil {
		res := vm.Exec(fmt.Sprintf(
			"%s -n %s get pods -l io.cilium/app=etcd-operator",
			helpers.KubectlCmd, helpers.KubeSystemNamespace))
		warningMessage = res.Output().String()
	}
	Expect(err).To(BeNil(), "etcd-operator is not ready after timeout, pods status:\n %s", warningMessage)
}

// ExpectCiliumPreFlightInstallReady is a wrapper around helpers/WaitForNPods.
// It asserts the error returned by that function is nil.
func ExpectCiliumPreFlightInstallReady(vm *helpers.Kubectl) {
	By("Waiting for all cilium pre-flight pods to be ready")

	err := vm.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium-pre-flight-check", 600)
	warningMessage := ""
	if err != nil {
		res := vm.Exec(fmt.Sprintf(
			"%s -n %s get pods -l k8s-app=cilium-pre-flight-check",
			helpers.KubectlCmd, helpers.KubeSystemNamespace))
		warningMessage = res.Output().String()
	}
	Expect(err).To(BeNil(), "cilium pre-flight check is not ready after timeout, pods status:\n %s", warningMessage)
}

// ProvisionInfraPods deploys DNS, etcd-operator, and cilium into the kubernetes
// cluster of which vm is a member.
func ProvisionInfraPods(vm *helpers.Kubectl) {
	By("Installing DNS Deployment")
	_ = vm.Apply(helpers.DNSDeployment())

	By("Deploying etcd-operator")
	err := vm.DeployETCDOperator()
	Expect(err).To(BeNil(), "Unable to deploy etcd operator")

	By("Installing Cilium")
	err = vm.CiliumInstall(helpers.CiliumDefaultDSPatch, helpers.CiliumConfigMapPatch)
	Expect(err).To(BeNil(), "Cilium cannot be installed")

	ExpectCiliumReady(vm)
	ExpectETCDOperatorReady(vm)
	ExpectKubeDNSReady(vm)
}
<|endoftext|>


<commit_before>// Copyright 2018-2020 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package k8sTest

import (
	"fmt"
	"time"

	"github.com/cilium/cilium/test/config"
	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"
	. "github.com/onsi/gomega"
)

var longTimeout = 10 * time.Minute

// ExpectKubeDNSReady is a wrapper around helpers/WaitKubeDNS. It asserts that
// the error returned by that function is nil.
func ExpectKubeDNSReady(vm *helpers.Kubectl) {
	By("Waiting for kube-dns to be ready")
	err := vm.WaitKubeDNS()
	ExpectWithOffset(1, err).Should(BeNil(), "kube-dns was not able to get into ready state")

	By("Running kube-dns preflight check")
	err = vm.KubeDNSPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "kube-dns service not ready")
}

// ExpectCiliumReady is a wrapper around helpers/WaitForPods. It asserts that
// the error returned by that function is nil.
func ExpectCiliumReady(vm *helpers.Kubectl) {
	err := vm.WaitForCiliumReadiness()
	Expect(err).To(BeNil(), "Timeout while waiting for Cilium to become ready")

	err = vm.CiliumPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "cilium pre-flight checks failed")
}

// ExpectCiliumOperatorReady is a wrapper around helpers/WaitForPods. It asserts that
// the error returned by that function is nil.
func ExpectCiliumOperatorReady(vm *helpers.Kubectl) {
	By("Waiting for cilium-operator to be ready")
	err := vm.WaitforPods(helpers.CiliumNamespace, "-l name=cilium-operator", longTimeout)
	ExpectWithOffset(1, err).Should(BeNil(), "Cilium operator was not able to get into ready state")
}

// ExpectAllPodsTerminated is a wrapper around helpers/WaitCleanAllTerminatingPods.
// It asserts that the error returned by that function is nil.
func ExpectAllPodsTerminated(vm *helpers.Kubectl) {
	err := vm.WaitCleanAllTerminatingPods(helpers.HelperTimeout)
	ExpectWithOffset(1, err).To(BeNil(), "terminating containers are not deleted after timeout")
}

// ExpectCiliumPreFlightInstallReady is a wrapper around helpers/WaitForNPods.
// It asserts the error returned by that function is nil.
func ExpectCiliumPreFlightInstallReady(vm *helpers.Kubectl) {
	By("Waiting for all cilium pre-flight pods to be ready")

	err := vm.WaitforPods(helpers.CiliumNamespace, "-l k8s-app=cilium-pre-flight-check", longTimeout)
	warningMessage := ""
	if err != nil {
		res := vm.Exec(fmt.Sprintf(
			"%s -n %s get pods -l k8s-app=cilium-pre-flight-check",
			helpers.KubectlCmd, helpers.CiliumNamespace))
		warningMessage = res.Output().String()
	}
	Expect(err).To(BeNil(), "cilium pre-flight check is not ready after timeout, pods status:\n %s", warningMessage)
}

// DeployCiliumAndDNS deploys DNS and cilium into the kubernetes cluster
func DeployCiliumAndDNS(vm *helpers.Kubectl, ciliumFilename string) {
	DeployCiliumOptionsAndDNS(vm, ciliumFilename, map[string]string{"global.debug.verbose": "flow"})
}

func redeployCilium(vm *helpers.Kubectl, ciliumFilename string, options map[string]string) {
	By("Installing Cilium")
	err := vm.CiliumInstall(ciliumFilename, options)
	Expect(err).To(BeNil(), "Cilium cannot be installed")

	err = vm.WaitForCiliumReadiness()
	Expect(err).To(BeNil(), "Timeout while waiting for Cilium to become ready")
}

// RedeployCilium reinstantiates the Cilium DS and ensures it is running.
//
// This helper is only appropriate for reconfiguring Cilium in the middle of
// an existing testsuite that calls DeployCiliumAndDNS(...).
func RedeployCilium(vm *helpers.Kubectl, ciliumFilename string, options map[string]string) {
	redeployCilium(vm, ciliumFilename, options)
	ExpectCiliumReady(vm)
	ExpectCiliumOperatorReady(vm)
}

// DeployCiliumOptionsAndDNS deploys DNS and cilium with options into the kubernetes cluster
func DeployCiliumOptionsAndDNS(vm *helpers.Kubectl, ciliumFilename string, options map[string]string) {
	redeployCilium(vm, ciliumFilename, options)

	By("Installing DNS Deployment")
	switch helpers.GetCurrentIntegration() {
	case helpers.CIIntegrationMicrok8s:
		By(fmt.Sprintf("%s (hint: %s)",
			"Assuming that microk8s already has DNS deployed...",
			"Use 'microk8s.enable dns' to create deployment"))
	case helpers.CIIntegrationGKE:
		By("Restarting all kube-system pods")
		if res := vm.DeleteResource("pod", fmt.Sprintf("-n %s --all", helpers.KubeSystemNamespace)); !res.WasSuccessful() {
			log.Warningf("Unable to delete kube-system pods: %s", res.OutputPrettyPrint())
		}
	default:
		vm.ApplyDefault(helpers.DNSDeployment(vm.BasePath()))
		By("Restarting DNS Pods")
		if res := vm.DeleteResource("pod", fmt.Sprintf("-n %s -l k8s-app=kube-dns", helpers.KubeSystemNamespace)); !res.WasSuccessful() {
			log.Warningf("Unable to delete DNS pods: %s", res.OutputPrettyPrint())
		}
	}

	switch helpers.GetCurrentIntegration() {
	case helpers.CIIntegrationFlannel:
		By("Installing Flannel")
		vm.ApplyDefault(vm.GetFilePath("../examples/kubernetes/addons/flannel/flannel.yaml"))
	default:
	}

	ExpectCiliumReady(vm)
	ExpectCiliumOperatorReady(vm)
	ExpectKubeDNSReady(vm)

	switch helpers.GetCurrentIntegration() {
	case helpers.CIIntegrationGKE:
		err := vm.WaitforPods(helpers.KubeSystemNamespace, "", longTimeout)
		ExpectWithOffset(1, err).Should(BeNil(), "kube-system pods were not able to get into ready state after restart")
	}
}

// SkipIfBenchmark will skip the test if benchmark is not specified
func SkipIfBenchmark() {
	if !config.CiliumTestConfig.Benchmarks {
		Skip("Benchmarks are skipped, specify -cilium.Benchmarks")
	}
}

// SkipIfIntegration will skip a test if it's running with any of the specified
// integration.
func SkipIfIntegration(integration string) {
	if helpers.IsIntegration(integration) {
		Skip(fmt.Sprintf(
			"This feature is not supported in Cilium %q mode. Skipping test.",
			integration))
	}
}

// SkipItIfNoKubeProxy will skip It if kube-proxy is disabled (= NodePort BPF is
// enabled)
func SkipItIfNoKubeProxy() {
	if !helpers.RunsWithKubeProxy() {
		Skip("kube-proxy is disabled (NodePort BPF is enabled). Skipping test.")
	}
}

func deleteETCDOperator(kubectl *helpers.Kubectl) {
	// Do not assert on success in AfterEach intentionally to avoid
	// incomplete teardown.
	_ = kubectl.DeleteResource("deploy", fmt.Sprintf("-n %s -l io.cilium/app=etcd-operator", helpers.CiliumNamespace))
	_ = kubectl.DeleteResource("pod", fmt.Sprintf("-n %s -l io.cilium/app=etcd-operator", helpers.CiliumNamespace))
	_ = kubectl.WaitCleanAllTerminatingPods(helpers.HelperTimeout)
}
<commit_msg>test: Remove duplicate invocation of WaitForCiliumReadiness()<commit_after>// Copyright 2018-2020 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package k8sTest

import (
	"fmt"
	"time"

	"github.com/cilium/cilium/test/config"
	. "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"
	. "github.com/onsi/gomega"
)

var longTimeout = 10 * time.Minute

// ExpectKubeDNSReady is a wrapper around helpers/WaitKubeDNS. It asserts that
// the error returned by that function is nil.
func ExpectKubeDNSReady(vm *helpers.Kubectl) {
	By("Waiting for kube-dns to be ready")
	err := vm.WaitKubeDNS()
	ExpectWithOffset(1, err).Should(BeNil(), "kube-dns was not able to get into ready state")

	By("Running kube-dns preflight check")
	err = vm.KubeDNSPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "kube-dns service not ready")
}

// ExpectCiliumReady is a wrapper around helpers/WaitForPods. It asserts that
// the error returned by that function is nil.
func ExpectCiliumReady(vm *helpers.Kubectl) {
	err := vm.WaitForCiliumReadiness()
	Expect(err).To(BeNil(), "Timeout while waiting for Cilium to become ready")

	err = vm.CiliumPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "cilium pre-flight checks failed")
}

// ExpectCiliumOperatorReady is a wrapper around helpers/WaitForPods. It asserts that
// the error returned by that function is nil.
func ExpectCiliumOperatorReady(vm *helpers.Kubectl) {
	By("Waiting for cilium-operator to be ready")
	err := vm.WaitforPods(helpers.CiliumNamespace, "-l name=cilium-operator", longTimeout)
	ExpectWithOffset(1, err).Should(BeNil(), "Cilium operator was not able to get into ready state")
}

// ExpectAllPodsTerminated is a wrapper around helpers/WaitCleanAllTerminatingPods.
// It asserts that the error returned by that function is nil.
func ExpectAllPodsTerminated(vm *helpers.Kubectl) {
	err := vm.WaitCleanAllTerminatingPods(helpers.HelperTimeout)
	ExpectWithOffset(1, err).To(BeNil(), "terminating containers are not deleted after timeout")
}

// ExpectCiliumPreFlightInstallReady is a wrapper around helpers/WaitForNPods.
// It asserts the error returned by that function is nil.
func ExpectCiliumPreFlightInstallReady(vm *helpers.Kubectl) {
	By("Waiting for all cilium pre-flight pods to be ready")

	err := vm.WaitforPods(helpers.CiliumNamespace, "-l k8s-app=cilium-pre-flight-check", longTimeout)
	warningMessage := ""
	if err != nil {
		res := vm.Exec(fmt.Sprintf(
			"%s -n %s get pods -l k8s-app=cilium-pre-flight-check",
			helpers.KubectlCmd, helpers.CiliumNamespace))
		warningMessage = res.Output().String()
	}
	Expect(err).To(BeNil(), "cilium pre-flight check is not ready after timeout, pods status:\n %s", warningMessage)
}

// DeployCiliumAndDNS deploys DNS and cilium into the kubernetes cluster
func DeployCiliumAndDNS(vm *helpers.Kubectl, ciliumFilename string) {
	DeployCiliumOptionsAndDNS(vm, ciliumFilename, map[string]string{"global.debug.verbose": "flow"})
}

func redeployCilium(vm *helpers.Kubectl, ciliumFilename string, options map[string]string) {
	By("Installing Cilium")
	err := vm.CiliumInstall(ciliumFilename, options)
	Expect(err).To(BeNil(), "Cilium cannot be installed")

	err = vm.WaitForCiliumReadiness()
	Expect(err).To(BeNil(), "Timeout while waiting for Cilium to become ready")
}

// RedeployCilium reinstantiates the Cilium DS and ensures it is running.
//
// This helper is only appropriate for reconfiguring Cilium in the middle of
// an existing testsuite that calls DeployCiliumAndDNS(...).
func RedeployCilium(vm *helpers.Kubectl, ciliumFilename string, options map[string]string) {
	redeployCilium(vm, ciliumFilename, options)
	err := vm.CiliumPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "cilium pre-flight checks failed")
	ExpectCiliumOperatorReady(vm)
}

// DeployCiliumOptionsAndDNS deploys DNS and cilium with options into the kubernetes cluster
func DeployCiliumOptionsAndDNS(vm *helpers.Kubectl, ciliumFilename string, options map[string]string) {
	redeployCilium(vm, ciliumFilename, options)

	By("Installing DNS Deployment")
	switch helpers.GetCurrentIntegration() {
	case helpers.CIIntegrationMicrok8s:
		By(fmt.Sprintf("%s (hint: %s)",
			"Assuming that microk8s already has DNS deployed...",
			"Use 'microk8s.enable dns' to create deployment"))
	case helpers.CIIntegrationGKE:
		By("Restarting all kube-system pods")
		if res := vm.DeleteResource("pod", fmt.Sprintf("-n %s --all", helpers.KubeSystemNamespace)); !res.WasSuccessful() {
			log.Warningf("Unable to delete kube-system pods: %s", res.OutputPrettyPrint())
		}
	default:
		vm.ApplyDefault(helpers.DNSDeployment(vm.BasePath()))
		By("Restarting DNS Pods")
		if res := vm.DeleteResource("pod", fmt.Sprintf("-n %s -l k8s-app=kube-dns", helpers.KubeSystemNamespace)); !res.WasSuccessful() {
			log.Warningf("Unable to delete DNS pods: %s", res.OutputPrettyPrint())
		}
	}

	switch helpers.GetCurrentIntegration() {
	case helpers.CIIntegrationFlannel:
		By("Installing Flannel")
		vm.ApplyDefault(vm.GetFilePath("../examples/kubernetes/addons/flannel/flannel.yaml"))
	default:
	}

	err := vm.CiliumPreFlightCheck()
	ExpectWithOffset(1, err).Should(BeNil(), "cilium pre-flight checks failed")
	ExpectCiliumOperatorReady(vm)
	ExpectKubeDNSReady(vm)

	switch helpers.GetCurrentIntegration() {
	case helpers.CIIntegrationGKE:
		err := vm.WaitforPods(helpers.KubeSystemNamespace, "", longTimeout)
		ExpectWithOffset(1, err).Should(BeNil(), "kube-system pods were not able to get into ready state after restart")
	}
}

// SkipIfBenchmark will skip the test if benchmark is not specified
func SkipIfBenchmark() {
	if !config.CiliumTestConfig.Benchmarks {
		Skip("Benchmarks are skipped, specify -cilium.Benchmarks")
	}
}

// SkipIfIntegration will skip a test if it's running with any of the specified
// integration.
func SkipIfIntegration(integration string) {
	if helpers.IsIntegration(integration) {
		Skip(fmt.Sprintf(
			"This feature is not supported in Cilium %q mode. Skipping test.",
			integration))
	}
}

// SkipItIfNoKubeProxy will skip It if kube-proxy is disabled (= NodePort BPF is
// enabled)
func SkipItIfNoKubeProxy() {
	if !helpers.RunsWithKubeProxy() {
		Skip("kube-proxy is disabled (NodePort BPF is enabled). Skipping test.")
	}
}

func deleteETCDOperator(kubectl *helpers.Kubectl) {
	// Do not assert on success in AfterEach intentionally to avoid
	// incomplete teardown.
	_ = kubectl.DeleteResource("deploy", fmt.Sprintf("-n %s -l io.cilium/app=etcd-operator", helpers.CiliumNamespace))
	_ = kubectl.DeleteResource("pod", fmt.Sprintf("-n %s -l io.cilium/app=etcd-operator", helpers.CiliumNamespace))
	_ = kubectl.WaitCleanAllTerminatingPods(helpers.HelperTimeout)
}
<|endoftext|>


<commit_before>package internal

import "fmt"

// -ldflags "-X github.com/matrix-org/dendrite/internal.branch=master"
var branch string

// -ldflags "-X github.com/matrix-org/dendrite/internal.build=alpha"
var build string

const (
	VersionMajor = 0
	VersionMinor = 1
	VersionPatch = 0
	VersionTag   = "" // example: "rc1"
)

func VersionString() string {
	version := fmt.Sprintf("%d.%d.%d%s", VersionMajor, VersionMinor, VersionPatch, VersionTag)
	if branch != "" {
		version += fmt.Sprintf("-%s", branch)
	}
	if build != "" {
		version += fmt.Sprintf("+%s", build)
	}
	return version
}
<commit_msg>Better semver compliance for version reporting<commit_after>package internal

import (
	"fmt"
	"strings"
)

// the final version string
var version string

// -ldflags "-X github.com/matrix-org/dendrite/internal.branch=master"
var branch string

// -ldflags "-X github.com/matrix-org/dendrite/internal.build=alpha"
var build string

const (
	VersionMajor = 0
	VersionMinor = 1
	VersionPatch = 0
	VersionTag   = "" // example: "rc1"
)

func VersionString() string {
	return version
}

func init() {
	version = fmt.Sprintf("%d.%d.%d", VersionMajor, VersionMinor, VersionPatch)
	if VersionTag != "" {
		version += "-" + VersionTag
	}
	parts := []string{}
	if build != "" {
		parts = append(parts, build)
	}
	if branch != "" {
		parts = append(parts, branch)
	}
	if len(parts) > 0 {
		version += "+" + strings.Join(parts, ".")
	}
}
<|endoftext|>


<commit_before>package io

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"strings"

	"github.com/matematik7/codejam-go/integer"
)

func CompareOutput(correctFn string, output io.Reader, input *BufferedInput) {
	msgs := []string{}

	correctF, err := os.Open(correctFn)
	if err != nil {
		log.Fatalln("Error opening correct file:", err)
	}
	defer correctF.Close()

	correctScanner := bufio.NewScanner(correctF)
	outputScanner := bufio.NewScanner(output)

	for i := 1; i <= input.T; i++ {
		if !correctScanner.Scan() {
			log.Fatalln("Error scanning correct:", correctScanner.Err())
		}
		if !outputScanner.Scan() {
			log.Fatalln("Error scanning output:", outputScanner.Err())
		}

		if correctScanner.Text() != outputScanner.Text() {
			caseString := fmt.Sprintf("Case #%d: ", i)
			correctString := strings.TrimPrefix(correctScanner.Text(), caseString)
			outputString := strings.TrimPrefix(outputScanner.Text(), caseString)
			msg := fmt.Sprint(caseString, "correct: ", correctString, ", output: ", outputString, ", input: ", input.InputProviders[i-1].Data)

			msgs = append(msgs, msg)
		}
	}

	if len(msgs) > 0 {
		fmt.Printf("%d differences comapred with %s:\n", len(msgs), correctFn)
		for _, msg := range msgs {
			fmt.Println(msg[:integer.Min(len(msg), 100)])
		}
	}
}
<commit_msg>Changed print to log<commit_after>package io

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"strings"

	"github.com/matematik7/codejam-go/integer"
)

func CompareOutput(correctFn string, output io.Reader, input *BufferedInput) {
	msgs := []string{}

	correctF, err := os.Open(correctFn)
	if err != nil {
		log.Fatalln("Error opening correct file:", err)
	}
	defer correctF.Close()

	correctScanner := bufio.NewScanner(correctF)
	outputScanner := bufio.NewScanner(output)

	for i := 1; i <= input.T; i++ {
		if !correctScanner.Scan() {
			log.Fatalln("Error scanning correct:", correctScanner.Err())
		}
		if !outputScanner.Scan() {
			log.Fatalln("Error scanning output:", outputScanner.Err())
		}

		if correctScanner.Text() != outputScanner.Text() {
			caseString := fmt.Sprintf("Case #%d: ", i)
			correctString := strings.TrimPrefix(correctScanner.Text(), caseString)
			outputString := strings.TrimPrefix(outputScanner.Text(), caseString)
			msg := fmt.Sprint(caseString, "correct: ", correctString, ", output: ", outputString, ", input: ", input.InputProviders[i-1].Data)

			msgs = append(msgs, msg)
		}
	}

	if len(msgs) > 0 {
		log.Printf("%d differences comapred with %s:\n", len(msgs), correctFn)
		for _, msg := range msgs {
			log.Println(msg[:integer.Min(len(msg), 100)])
		}
	}
}
<|endoftext|>


<commit_before>package amqptools

import (
	"errors"

	"github.com/streadway/amqp"
)

type SynchronousPublisher struct {
	connection *amqp.Connection
	channel    *amqp.Channel
	pubAcks    chan uint64
	pubNacks   chan uint64
	chanClose  chan *amqp.Error
}

func NewSynchronousPublisher(connectionUri string) (*SynchronousPublisher, error) {
	var err error

	publisher := &SynchronousPublisher{}

	if publisher.connection, err = amqp.Dial(connectionUri); err != nil {
		return nil, err
	}

	if publisher.channel, err = publisher.connection.Channel(); err != nil {
		return nil, err
	}

	publisher.pubAcks, publisher.pubNacks = publisher.channel.NotifyConfirm(make(chan uint64), make(chan uint64))
	publisher.chanClose = publisher.channel.NotifyClose(make(chan *amqp.Error))

	if err = publisher.channel.Confirm(false); err != nil {
		return nil, err
	}

	return publisher, nil
}

func (me *SynchronousPublisher) Publish(message *amqp.Publishing, exchange, routingKey string, mandatory, immediate bool) error {
	var err error

	if err = me.channel.Publish(exchange, routingKey, mandatory, immediate, *message); err != nil {
		return err
	}

	select {
	case err = <-me.chanClose:
		return err
	case <-me.pubAcks:
		return nil
	case <-me.pubNacks:
		return errors.New("Received basic.nack")
	}

	return nil
}

func (me *SynchronousPublisher) Close() {
	me.channel.Close()
	me.connection.Close()
}
<commit_msg>Removing unused file<commit_after><|endoftext|>


<commit_before>/*
guest-exec - run command inside vm

Old command version syntax:
        { "execute": "guest-exec", "arguments": {
            "command": string // required, base64 encoded command name to execute with args including newline
          }
        }

New command version syntax (preferred):
        { "execute": "guest-exec", "arguments": {
            "path": string, // required, command name to execute
            "arg": string, // optional, arguments to executed command
            "env": string, // optional, environment to executed command
            "input": string, // optional, base64 encoded string
            "capture-output": bool // optional, capture stdout/stderr
          }
        }
*/
package guest_exec

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"os/exec"
	"strings"
	"syscall"

	"github.com/vtolstov/qemu-ga/qga"
)

func init() {
	qga.RegisterCommand(&qga.Command{
		Name:    "guest-exec",
		Func:    fnGuestExec,
		Enabled: true,
		Returns: true,
	})
}

func fnGuestExec(req *qga.Request) *qga.Response {
	res := &qga.Response{Id: req.Id}

	reqData1 := struct {
		Command string `json:"command"`
	}{}
	reqData2 := struct {
		Path   string `json:"path"`
		Arg    string `json:"arg,omitempty"`
		Env    string `json:"env,omitempty"`
		Input  string `json:"input-data,omitempty"`
		Output bool   `json:"capture-output"`
	}{}

	var errStr []string

	if err := json.Unmarshal(req.RawArgs, &reqData2); err != nil {
		errStr = append(errStr, err.Error())
	}
	if reqData2.Path != "" {
		goto exec2
	}

	if err := json.Unmarshal(req.RawArgs, &reqData1); err != nil {
		errStr = append(errStr, err.Error())
	}
	if reqData1.Command != "" {
		goto exec1
	}

	if len(errStr) > 0 {
		res.Error = &Error{Code: -1, Desc: strings.Join(errStr, ";")}
	} else {
		res.Error = &Error{Code: -1, Desc: "missing required argument"}
	}
	return res

exec1:
	return fnGuestExec1(req)
exec2:
	return fnGuestExec2(req)
}

func fnGuestExec1(req *qga.Request) *qga.Response {
	res := &qga.Response{Id: req.Id}

	resData := struct {
		ExitCode int
		Output   string
	}{}

	reqData := struct {
		Command string `json:"command"`
	}{}

	err := json.Unmarshal(req.RawArgs, &reqData)
	if err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}

	if reqData.Command == "" {
		res.Error = &Error{Code: -1, Desc: "empty command to guest-exec"}
		return res
	}
	cmdline, err := base64.StdEncoding.DecodeString(reqData.Command)
	if err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}

	output, err := exec.Command("sh", "-c", string(cmdline)).CombinedOutput()
	if err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}

	resData.Output = base64.StdEncoding.EncodeToString(output)
	resData.ExitCode = 0
	res.Return = resData
	return res
}

func fnGuestExec2(req *qga.Request) *qga.Response {
	res := &qga.Response{Id: req.Id}

	stdIn := bytes.NewBuffer(nil)
	stdOut := bytes.NewBuffer(nil)
	stdErr := bytes.NewBuffer(nil)

	resData := struct {
		Pid int `json:"pid"`
	}{}

	reqData := struct {
		Path   string `json:"path"`
		Args   string `json:"arg,omitempty"`
		Env    string `json:"env,omitempty"`
		Input  string `json:"input-data,omitempty"`
		Output bool   `json:"capture-output"`
	}{}

	err := json.Unmarshal(req.RawArgs, &reqData)
	if err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}
	if reqData.Path == "" {
		res.Error = &Error{Code: -1, Desc: "empty command to guest-exec"}
		return res
	}
	cmd := &exec.Cmd{
		Path: reqData.Path,
		Args: strings.Split(reqData.Args, " "),
		Env:  strings.Split(reqData.Env, " "),
		Dir:  "/",
		SysProcAttr: &syscall.SysProcAttr{
			Setsid: true,
		},
	}

	if reqData.Input != "" {
		inData, err := base64.StdEncoding.DecodeString(reqData.Input)
		if err != nil {
			res.Error = &Error{Code: -1, Desc: err.Error()}
			return res
		}
		stdIn.Write(inData)
		cmd.Stdin = stdIn
	}
	if reqData.Output {
		cmd.Stdout = stdOut
		cmd.Stderr = stdErr
	}

	if err = cmd.Start(); err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}

	execStatuses[cmd.Process.Pid] = &qga.ExecStatus{
		Exited: false,
	}
	resData.Pid = cmd.Process.Pid
	res.Return = resData

	go fnExecWait(cmd, stdOut, stdErr)

	return res
}

func fnExecWait(cmd *exec.Cmd, stdOut *bytes.Buffer, stdErr *bytes.Buffer) {
	var code int

	s, ok := execStatuses[cmd.Process.Pid]
	if !ok {
		return
	}
	if err := cmd.Wait(); err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				code = status.ExitStatus()
			}
		}
	} else {
		code = 0
	}

	s.ExitCode = &code
	s.Exited = cmd.ProcessState.Exited()
	if stdOut.Len() > 16*1024*1024 {
		s.OutTrunc = true
		stdOut.Truncate(16 * 1024 * 1024)
	}
	s.OutData = base64.StdEncoding.EncodeToString(stdOut.Bytes())
	stdOut.Reset()
	if stdErr.Len() > 16*1024*1024 {
		s.ErrTrunc = true
		stdErr.Truncate(16 * 1024 * 1024)
	}
	s.ErrData = base64.StdEncoding.EncodeToString(stdErr.Bytes())
	stdErr.Reset()
}
<commit_msg>use default env<commit_after>/*
guest-exec - run command inside vm

Old command version syntax:
        { "execute": "guest-exec", "arguments": {
            "command": string // required, base64 encoded command name to execute with args including newline
          }
        }

New command version syntax (preferred):
        { "execute": "guest-exec", "arguments": {
            "path": string, // required, command name to execute
            "arg": string, // optional, arguments to executed command
            "env": string, // optional, environment to executed command
            "input": string, // optional, base64 encoded string
            "capture-output": bool // optional, capture stdout/stderr
          }
        }
*/
package guest_exec

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"os"
	"os/exec"
	"strings"
	"syscall"

	"github.com/vtolstov/qemu-ga/qga"
)

func init() {
	qga.RegisterCommand(&qga.Command{
		Name:    "guest-exec",
		Func:    fnGuestExec,
		Enabled: true,
		Returns: true,
	})
}

func fnGuestExec(req *qga.Request) *qga.Response {
	res := &qga.Response{Id: req.Id}

	reqData1 := struct {
		Command string `json:"command"`
	}{}
	reqData2 := struct {
		Path   string `json:"path"`
		Arg    string `json:"arg,omitempty"`
		Env    string `json:"env,omitempty"`
		Input  string `json:"input-data,omitempty"`
		Output bool   `json:"capture-output"`
	}{}

	var errStr []string

	if err := json.Unmarshal(req.RawArgs, &reqData2); err != nil {
		errStr = append(errStr, err.Error())
	}
	if reqData2.Path != "" {
		goto exec2
	}

	if err := json.Unmarshal(req.RawArgs, &reqData1); err != nil {
		errStr = append(errStr, err.Error())
	}
	if reqData1.Command != "" {
		goto exec1
	}

	if len(errStr) > 0 {
		res.Error = &Error{Code: -1, Desc: strings.Join(errStr, ";")}
	} else {
		res.Error = &Error{Code: -1, Desc: "missing required argument"}
	}
	return res

exec1:
	return fnGuestExec1(req)
exec2:
	return fnGuestExec2(req)
}

func fnGuestExec1(req *qga.Request) *qga.Response {
	res := &qga.Response{Id: req.Id}

	resData := struct {
		ExitCode int
		Output   string
	}{}

	reqData := struct {
		Command string `json:"command"`
	}{}

	err := json.Unmarshal(req.RawArgs, &reqData)
	if err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}

	if reqData.Command == "" {
		res.Error = &Error{Code: -1, Desc: "empty command to guest-exec"}
		return res
	}
	cmdline, err := base64.StdEncoding.DecodeString(reqData.Command)
	if err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}

	output, err := exec.Command("sh", "-c", string(cmdline)).CombinedOutput()
	if err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}

	resData.Output = base64.StdEncoding.EncodeToString(output)
	resData.ExitCode = 0
	res.Return = resData
	return res
}

func fnGuestExec2(req *qga.Request) *qga.Response {
	res := &qga.Response{Id: req.Id}

	stdIn := bytes.NewBuffer(nil)
	stdOut := bytes.NewBuffer(nil)
	stdErr := bytes.NewBuffer(nil)

	resData := struct {
		Pid int `json:"pid"`
	}{}

	reqData := struct {
		Path   string `json:"path"`
		Args   string `json:"arg,omitempty"`
		Env    string `json:"env,omitempty"`
		Input  string `json:"input-data,omitempty"`
		Output bool   `json:"capture-output"`
	}{}

	err := json.Unmarshal(req.RawArgs, &reqData)
	if err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}
	if reqData.Path == "" {
		res.Error = &Error{Code: -1, Desc: "empty command to guest-exec"}
		return res
	}

	path, err := exec.LookPath(reqData.Path)
	if err != nil {
		path = reqData.Path
	}

	env := os.Environ()
	env = append(env, strings.Split(reqData.Env, " ")...)

	cmd := &exec.Cmd{
		Path: path,
		Args: strings.Split(reqData.Args, " "),
		Env:  env,
		Dir:  "/",
		SysProcAttr: &syscall.SysProcAttr{
			Setsid: true,
		},
	}

	if reqData.Input != "" {
		inData, err := base64.StdEncoding.DecodeString(reqData.Input)
		if err != nil {
			res.Error = &Error{Code: -1, Desc: err.Error()}
			return res
		}
		stdIn.Write(inData)
		cmd.Stdin = stdIn
	}
	if reqData.Output {
		cmd.Stdout = stdOut
		cmd.Stderr = stdErr
	}

	if err = cmd.Start(); err != nil {
		res.Error = &Error{Code: -1, Desc: err.Error()}
		return res
	}

	execStatuses[cmd.Process.Pid] = &qga.ExecStatus{
		Exited: false,
	}
	resData.Pid = cmd.Process.Pid
	res.Return = resData

	go fnExecWait(cmd, stdOut, stdErr)

	return res
}

func fnExecWait(cmd *exec.Cmd, stdOut *bytes.Buffer, stdErr *bytes.Buffer) {
	var code int

	s, ok := execStatuses[cmd.Process.Pid]
	if !ok {
		return
	}
	if err := cmd.Wait(); err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				code = status.ExitStatus()
			}
		}
	} else {
		code = 0
	}

	s.ExitCode = &code
	s.Exited = cmd.ProcessState.Exited()
	if stdOut.Len() > 16*1024*1024 {
		s.OutTrunc = true
		stdOut.Truncate(16 * 1024 * 1024)
	}
	s.OutData = base64.StdEncoding.EncodeToString(stdOut.Bytes())
	stdOut.Reset()
	if stdErr.Len() > 16*1024*1024 {
		s.ErrTrunc = true
		stdErr.Truncate(16 * 1024 * 1024)
	}
	s.ErrData = base64.StdEncoding.EncodeToString(stdErr.Bytes())
	stdErr.Reset()
}
<|endoftext|>


<commit_before>package arbitrary

import (
	"fmt"
)

func (arb T) phonenumber_canada() string {

	var areacode string
	{
		var areacodes []string = []string{
			"604",
			"250",
			"778",
			"236",
			"672",
		}

		areacode = areacodes[arb.randomness.Intn(len(areacodes))]
	}

	var localpart1 string
	{
		localpart1 = fmt.Sprint(arb.randomness.Intn(1000))
	}

	var localpart2 string
	{
		localpart2 = fmt.Sprint(arb.randomness.Intn(10000))
	}

	var format string
	{
		var formats []string = []string{
			"%s-%s%s",
			"%s-%s-%s",
			"%s %s %s",
			"%s %s%s",
			"(%s) %s%s",
			"(%s)%s%s",
			"(%s) %s-%s",
			"(%s)%s-%s",
			"(%s) %s %s",
			"(%s)%s %s",
			"%s/%s-%s",
			"+1%s%s%s",
			"+1-%s-%s-%s",
			"+1 %s %s %s",
		}

		format = formats[arb.randomness.Intn(len(formats))]
	}

	var result string
	{
		fmt.Sprintf(format, areacode, localpart1, localpart2)
	}

	return result
}

<commit_msg>phone number, plus other changes<commit_after>package arbitrary

import (
	"fmt"
)

func (arb T) phonenumber_canada() string {

	var areacode string
	{
		var areacodes []string = []string{
			// alberta
			"403",
			"780",
			"587",
			"825",
			"368",

			// british columnbia
			"604",
			"250",
			"778",
			"236",
			"672",

			// manitoba
			"204",
			"413",

			// new brunswick
			"506",

			// newfoundland and labrador
			"709",

			// nova scotia and prince edward island
			"782",
			"902",

			// ontario
			"226",
			"249",
			"289",
			"343",
			"365",
			"416",
			"437",
			"519",
			"548",
			"613",
			"647",
			"705",
			"807",
			"905",

			// quebec
			"367",
			"418",
			"581",
			"438",
			"450",
			"514",
			"613",
			"581",
			"819",

			// saskatchewan
			"306",
			"639",

			// yukon, northwest territories and nunavut
			"867",
		}

		areacode = areacodes[arb.randomness.Intn(len(areacodes))]
	}

	var localpart1 string
	{
		localpart1 = fmt.Sprint(arb.randomness.Intn(1000))
	}

	var localpart2 string
	{
		localpart2 = fmt.Sprint(arb.randomness.Intn(10000))
	}

	var format string
	{
		var formats []string = []string{
			"%s-%s%s",
			"%s-%s-%s",
			"%s %s %s",
			"%s %s%s",
			"(%s) %s%s",
			"(%s)%s%s",
			"(%s) %s-%s",
			"(%s)%s-%s",
			"(%s) %s %s",
			"(%s)%s %s",
			"%s/%s-%s",
			"+1%s%s%s",
			"+1-%s-%s-%s",
			"+1 %s %s %s",
		}

		format = formats[arb.randomness.Intn(len(formats))]
	}

	var result string
	{
		result = fmt.Sprintf(format, areacode, localpart1, localpart2)
	}

	return result
}

<|endoftext|>


<commit_before>package utils

import (
	"time"
	"fmt"
	"net/http"
)

const (
	ISODate           string = "2006-01-02"
	ISODateTime       string = "2006-01-02 15:04:05"
	ISODateTimestamp  string = "2006-01-02 15:04:05.000"
	ISODateTimeZ      string = "2006-01-02 15:04:05Z07:00"
	ISODateTimestampZ string = "2006-01-02 15:04:05.000Z07:00"
	DMY               string = "02/01/2006"
	DMYTime           string = "02/01/2006 15:04:05"
	UTCDateTime       string = "UTC"
	UTCDateTimestamp  string = "UTCTimestamp"
	DateOffset        string = "Z07:00"
)

func IsISODate(sval string) bool {
	_, err := String2date(sval, ISODate)

	if err != nil {
		return false
	}

	return true
}

func IsISODateTime(sval string) bool {
	_, err := String2date(sval, ISODateTime)

	if err != nil {
		return false
	}

	return true
}

func DateFromISODateTime(sval string) (time.Time, error) {
	return String2date(sval, ISODateTime)
}

func Date2string(val time.Time, format string) string {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime:
		return val.Format(format)
	case UTCDateTime:
		return val.UTC().Format(ISODateTimeZ)
	case UTCDateTimestamp:
		return val.UTC().Format(ISODateTimestampZ)
	default:
		return ""
	}
}

func String2date(sval string, format string) (time.Time, error) {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime, DateOffset:
		t, err := time.Parse(format, sval)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	default:
		return time.Now(), fmt.Errorf("Unknown datetime format \"%s\"", format)
	}
}

func Server2ClientDmy(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMY)
}

func Server2ClientDmyTime(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMYTime)
}

func Server2ClientLocal(r *http.Request, serverTime time.Time) time.Time {
	timeOffset := 0

	cookie, err := r.Cookie("time_zone_offset")
	if err != nil && err != http.ErrNoCookie {
		return serverTime.UTC()
	} else if err == http.ErrNoCookie {
		timeOffset = 0
	} else {
		timeOffset = String2int(cookie.Value)
	}

	return serverTime.UTC().Add(time.Duration(-1*timeOffset) * time.Minute)
}
<commit_msg>Parse date at current location<commit_after>package utils

import (
	"time"
	"fmt"
	"net/http"
)

const (
	ISODate           string = "2006-01-02"
	ISODateTime       string = "2006-01-02 15:04:05"
	ISODateTimestamp  string = "2006-01-02 15:04:05.000"
	ISODateTimeZ      string = "2006-01-02 15:04:05Z07:00"
	ISODateTimestampZ string = "2006-01-02 15:04:05.000Z07:00"
	DMY               string = "02/01/2006"
	DMYTime           string = "02/01/2006 15:04:05"
	UTCDateTime       string = "UTC"
	UTCDateTimestamp  string = "UTCTimestamp"
	DateOffset        string = "Z07:00"
)

func IsISODate(sval string) bool {
	_, err := String2date(sval, ISODate)

	if err != nil {
		return false
	}

	return true
}

func IsISODateTime(sval string) bool {
	_, err := String2date(sval, ISODateTime)

	if err != nil {
		return false
	}

	return true
}

func DateFromISODateTime(sval string) (time.Time, error) {
	return String2date(sval, ISODateTime)
}

func Date2string(val time.Time, format string) string {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime:
		return val.Format(format)
	case UTCDateTime:
		return val.UTC().Format(ISODateTimeZ)
	case UTCDateTimestamp:
		return val.UTC().Format(ISODateTimestampZ)
	default:
		return ""
	}
}

func String2date(sval string, format string) (time.Time, error) {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime, DateOffset:
		loc, err := time.LoadLocation("Local")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(format, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	default:
		return time.Now(), fmt.Errorf("Unknown datetime format \"%s\"", format)
	}
}

func Server2ClientDmy(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMY)
}

func Server2ClientDmyTime(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMYTime)
}

func Server2ClientLocal(r *http.Request, serverTime time.Time) time.Time {
	timeOffset := 0

	cookie, err := r.Cookie("time_zone_offset")
	if err != nil && err != http.ErrNoCookie {
		return serverTime.UTC()
	} else if err == http.ErrNoCookie {
		timeOffset = 0
	} else {
		timeOffset = String2int(cookie.Value)
	}

	return serverTime.UTC().Add(time.Duration(-1*timeOffset) * time.Minute)
}
<|endoftext|>