<commit_before>// Copyright 2017-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 (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"path"
	"strings"
	"sync"
	"time"

	"github.com/cilium/cilium/api/v1/models"
	"github.com/cilium/cilium/test/helpers"
	"github.com/cilium/cilium/test/helpers/policygen"

	"github.com/Jeffail/gabs"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var (
	configMap       = "ConfigMap"
	endpointTimeout = (60 * time.Second)
)

var _ = Describe("NightlyEpsMeasurement", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var once sync.Once
	var ciliumPath string

	endpointCount := 45
	endpointsTimeout := endpointTimeout * time.Duration(endpointCount)
	manifestPath := "tmp.yaml"
	vagrantManifestPath := path.Join(helpers.BasePath, manifestPath)
	var lastServer int
	var err error

	initialize := func() {
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		ciliumPath = kubectl.ManifestGet("cilium_ds.yaml")
		kubectl.Apply(ciliumPath)

		_, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 600)
		Expect(err).Should(BeNil())

		err = kubectl.WaitKubeDNS()
		Expect(err).Should(BeNil())

		// Sometimes PolicyGen has a lot of pods running around without delete
		// it. Using this we are sure that we delete before this test start
		kubectl.Exec(fmt.Sprintf(
			"%s delete --all pods,svc,cnp -n %s", helpers.KubectlCmd, helpers.DefaultNamespace))

		err = kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating containers are not deleted after timeout")
	}

	BeforeEach(func() {
		once.Do(initialize)
	})

	AfterEach(func() {
		if CurrentGinkgoTestDescription().Failed {
			ciliumPod, _ := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, helpers.K8s1)
			kubectl.CiliumReport(helpers.KubeSystemNamespace, ciliumPod, []string{
				"cilium service list",
				"cilium endpoint list"})
		}
		err := kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating containers are not deleted after timeout")

		kubectl.Delete(vagrantManifestPath)
		kubectl.WaitCleanAllTerminatingPods()
	})

	deployEndpoints := func() {
		_, lastServer, err = helpers.GenerateManifestForEndpoints(endpointCount, manifestPath)
		ExpectWithOffset(1, err).Should(BeNil(), "Manifest cannot be created correctly")
		res := kubectl.Apply(vagrantManifestPath)
		res.ExpectSuccess("cannot apply eps manifest :%s", res.GetDebugMessage())
	}

	getServices := func() map[string]string {
		// getServices returns a map of services, where service name is the key
		// and the ClusterIP is the value.
		services, err := kubectl.Get(helpers.DefaultNamespace, fmt.Sprintf("services -l zgroup=testapp")).Filter(
			`{range .items[*]}{.metadata.name}{"="}{.spec.clusterIP}{"\n"}{end}`)
		ExpectWithOffset(1, err).To(BeNil(), "cannot retrieve testapp services")
		result := make(map[string]string)
		for _, line := range strings.Split(services.String(), "\n") {
			vals := strings.Split(line, "=")
			if len(vals) == 2 {
				result[vals[0]] = vals[1]
			}
		}
		return result
	}

	Measure("The endpoint creation", func(b Benchmarker) {
		desiredState := string(models.EndpointStateReady)

		deployEndpoints()
		waitForPodsTime := b.Time("Wait for pods", func() {
			pods, err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", endpointTimeout)
			Expect(err).Should(BeNil(),
				"Cannot retrieve %d pods in %d seconds", endpointCount, endpointsTimeout)
			Expect(pods).Should(BeTrue())
		})

		log.WithFields(logrus.Fields{"pod creation time": waitForPodsTime}).Info("")

		ciliumPods, err := kubectl.GetCiliumPods(helpers.KubeSystemNamespace)
		Expect(err).To(BeNil(), "Cannot retrieve cilium pods")

		runtime := b.Time("Endpoint creation", func() {
			Eventually(func() bool {
				count := 0
				for _, pod := range ciliumPods {
					status := kubectl.CiliumEndpointsStatus(pod)
					result := map[string]int{}
					for _, state := range status {
						result[state]++
					}
					count += result[desiredState]
					logger.WithFields(logrus.Fields{
						"status": result,
						"pod":    pod,
					}).Info("Cilium endpoint status")
				}
				return count >= endpointCount
			}, endpointsTimeout, 3*time.Second).Should(BeTrue())
		})
		log.WithFields(logrus.Fields{"endpoint creation time": runtime}).Info("")

		services := getServices()
		Expect(len(services)).To(BeNumerically(">", 0), "Was not able to get services")

		pods, err := kubectl.GetPodNames(helpers.DefaultNamespace, "zgroup=testapp")
		Expect(err).To(BeNil(), "cannot retrieve pods names")

		By("Testing if http requests to multiple endpoints do not timeout")
		for i := 0; i < 5; i++ {
			for _, pod := range pods {
				for service, ip := range services {
					b.Time("Curl to service", func() {
						_, err := kubectl.ExecPodCmd(
							helpers.DefaultNamespace, pod,
							helpers.CurlFail(fmt.Sprintf("http://%s:80/", ip)))
						Expect(err).To(BeNil(), "Cannot curl from %s to service %s on  ip %s", pod, service, ip)
					})
				}

			}
		}

	}, 1)

	Context("Nightly Policies", func() {
		numPods := 20
		bunchPods := 5
		podsCreated := 0

		AfterEach(func() {
			kubectl.Exec(fmt.Sprintf(
				"%s delete --all pods,svc,cnp -n %s", helpers.KubectlCmd, helpers.DefaultNamespace))
		})

		Measure(fmt.Sprintf("Applying policies to %d pods in a group of %d", numPods, bunchPods), func(b Benchmarker) {
			testDef := func() {
				logger.Errorf("Creating %d new pods, total created are %d", numPods, podsCreated)
				testSpecGroup := policygen.TestSpecsGroup{}
				for i := 0; i < bunchPods; i++ {
					testSpec := policygen.GetBasicTestSpec()
					testSpecGroup = append(testSpecGroup, &testSpec)
				}

				By("Creating endpoints")

				endpoints := b.Time("Runtime", func() {
					testSpecGroup.CreateAndApplyManifests(kubectl)
				})
				b.RecordValue("Endpoint Creation in seconds", endpoints.Seconds())
				By("Apply Policies")

				policy := b.Time("policy", func() {
					testSpecGroup.CreateAndApplyCNP(kubectl)
				})
				b.RecordValue("Policy Creation in seconds", policy.Seconds())

				By("Connectivity Test")
				conn := b.Time("connTest", func() {
					testSpecGroup.ConnectivityTest()
				})

				b.RecordValue("Connectivity test in seconds", conn.Seconds())
			}

			for podsCreated < numPods {
				testDef()
				podsCreated = podsCreated + bunchPods
			}
		}, 1)
	})
})

var _ = Describe("NightlyExamples", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var once sync.Once
	var ciliumPath string
	var demoPath string
	var l3Policy string
	var appService = "app1-service"
	var apps []string

	initialize := func() {
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
		kubectl.Delete(ciliumPath)

		apps = []string{helpers.App1, helpers.App2, helpers.App3}

		demoPath = kubectl.ManifestGet("demo.yaml")
		l3Policy = kubectl.ManifestGet("l3_l4_policy.yaml")
	}

	BeforeEach(func() {
		once.Do(initialize)
	})

	AfterEach(func() {
		kubectl.Delete(demoPath)
		kubectl.Delete(l3Policy)

		err := kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating containers are not deleted after timeout")
	})

	It("Check Kubernetes Example is working correctly", func() {
		var path = "../examples/kubernetes/cilium.yaml"
		var result bytes.Buffer
		newCiliumDSName := fmt.Sprintf("cilium_ds_%s.json", helpers.MakeUID())

		objects, err := helpers.DecodeYAMLOrJSON(path)
		Expect(err).To(BeNil())

		for _, object := range objects {
			data, err := json.Marshal(object)
			Expect(err).To(BeNil())

			jsonObj, err := gabs.ParseJSON(data)
			Expect(err).To(BeNil())

			value, _ := jsonObj.Path("kind").Data().(string)
			if value == configMap {
				jsonObj.SetP("---\nendpoints:\n- http://k8s1:9732\n", "data.etcd-config")
				jsonObj.SetP("true", "data.debug")
			}

			result.WriteString(jsonObj.String())
		}

		fp, err := os.Create(newCiliumDSName)
		defer fp.Close()
		Expect(err).To(BeNil())

		fmt.Fprint(fp, result.String())

		kubectl.Apply(helpers.GetFilePath(newCiliumDSName)).ExpectSuccess()
		defer kubectl.Delete(helpers.GetFilePath(newCiliumDSName))
		status, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 300)
		Expect(status).Should(BeTrue())
		Expect(err).Should(BeNil())

		kubectl.Apply(demoPath).ExpectSuccess()
		_, err = kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", 300)
		Expect(err).Should(BeNil())

		_, err = kubectl.CiliumPolicyAction(helpers.KubeSystemNamespace, l3Policy, helpers.KubectlApply, 300)
		Expect(err).Should(BeNil())

		appPods := helpers.GetAppPods(apps, helpers.DefaultNamespace, kubectl, "id")

		clusterIP, _, err := kubectl.GetServiceHostPort(helpers.DefaultNamespace, appService)
		Expect(err).Should(BeNil())

		_, err = kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App2],
			helpers.CurlFail(fmt.Sprintf("http://%s/public", clusterIP)))
		Expect(err).Should(BeNil())

		_, err = kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App3],
			helpers.CurlFail(fmt.Sprintf("http://%s/public", clusterIP)))
		Expect(err).Should(HaveOccurred())
	})
})
<commit_msg>Ginkgo: Add a test to check cilium image updates<commit_after>// Copyright 2017-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 (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"path"
	"strings"
	"sync"
	"time"

	"github.com/cilium/cilium/api/v1/models"
	"github.com/cilium/cilium/test/helpers"
	"github.com/cilium/cilium/test/helpers/policygen"

	"github.com/Jeffail/gabs"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var (
	configMap       = "ConfigMap"
	endpointTimeout = (60 * time.Second)
)

var _ = Describe("NightlyEpsMeasurement", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var once sync.Once
	var ciliumPath string

	endpointCount := 45
	endpointsTimeout := endpointTimeout * time.Duration(endpointCount)
	manifestPath := "tmp.yaml"
	vagrantManifestPath := path.Join(helpers.BasePath, manifestPath)
	var lastServer int
	var err error

	initialize := func() {
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		ciliumPath = kubectl.ManifestGet("cilium_ds.yaml")
		kubectl.Apply(ciliumPath)

		_, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 600)
		Expect(err).Should(BeNil())

		err = kubectl.WaitKubeDNS()
		Expect(err).Should(BeNil())

		// Sometimes PolicyGen has a lot of pods running around without delete
		// it. Using this we are sure that we delete before this test start
		kubectl.Exec(fmt.Sprintf(
			"%s delete --all pods,svc,cnp -n %s", helpers.KubectlCmd, helpers.DefaultNamespace))

		err = kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating containers are not deleted after timeout")
	}

	BeforeEach(func() {
		once.Do(initialize)
	})

	AfterEach(func() {
		if CurrentGinkgoTestDescription().Failed {
			ciliumPod, _ := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, helpers.K8s1)
			kubectl.CiliumReport(helpers.KubeSystemNamespace, ciliumPod, []string{
				"cilium service list",
				"cilium endpoint list"})
		}
		err := kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating containers are not deleted after timeout")

		kubectl.Delete(vagrantManifestPath)
		kubectl.WaitCleanAllTerminatingPods()
	})

	deployEndpoints := func() {
		_, lastServer, err = helpers.GenerateManifestForEndpoints(endpointCount, manifestPath)
		ExpectWithOffset(1, err).Should(BeNil(), "Manifest cannot be created correctly")
		res := kubectl.Apply(vagrantManifestPath)
		res.ExpectSuccess("cannot apply eps manifest :%s", res.GetDebugMessage())
	}

	getServices := func() map[string]string {
		// getServices returns a map of services, where service name is the key
		// and the ClusterIP is the value.
		services, err := kubectl.Get(helpers.DefaultNamespace, fmt.Sprintf("services -l zgroup=testapp")).Filter(
			`{range .items[*]}{.metadata.name}{"="}{.spec.clusterIP}{"\n"}{end}`)
		ExpectWithOffset(1, err).To(BeNil(), "cannot retrieve testapp services")
		result := make(map[string]string)
		for _, line := range strings.Split(services.String(), "\n") {
			vals := strings.Split(line, "=")
			if len(vals) == 2 {
				result[vals[0]] = vals[1]
			}
		}
		return result
	}

	Measure("The endpoint creation", func(b Benchmarker) {
		desiredState := string(models.EndpointStateReady)

		deployEndpoints()
		waitForPodsTime := b.Time("Wait for pods", func() {
			pods, err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", endpointTimeout)
			Expect(err).Should(BeNil(),
				"Cannot retrieve %d pods in %d seconds", endpointCount, endpointsTimeout)
			Expect(pods).Should(BeTrue())
		})

		log.WithFields(logrus.Fields{"pod creation time": waitForPodsTime}).Info("")

		ciliumPods, err := kubectl.GetCiliumPods(helpers.KubeSystemNamespace)
		Expect(err).To(BeNil(), "Cannot retrieve cilium pods")

		runtime := b.Time("Endpoint creation", func() {
			Eventually(func() bool {
				count := 0
				for _, pod := range ciliumPods {
					status := kubectl.CiliumEndpointsStatus(pod)
					result := map[string]int{}
					for _, state := range status {
						result[state]++
					}
					count += result[desiredState]
					logger.WithFields(logrus.Fields{
						"status": result,
						"pod":    pod,
					}).Info("Cilium endpoint status")
				}
				return count >= endpointCount
			}, endpointsTimeout, 3*time.Second).Should(BeTrue())
		})
		log.WithFields(logrus.Fields{"endpoint creation time": runtime}).Info("")

		services := getServices()
		Expect(len(services)).To(BeNumerically(">", 0), "Was not able to get services")

		pods, err := kubectl.GetPodNames(helpers.DefaultNamespace, "zgroup=testapp")
		Expect(err).To(BeNil(), "cannot retrieve pods names")

		By("Testing if http requests to multiple endpoints do not timeout")
		for i := 0; i < 5; i++ {
			for _, pod := range pods {
				for service, ip := range services {
					b.Time("Curl to service", func() {
						_, err := kubectl.ExecPodCmd(
							helpers.DefaultNamespace, pod,
							helpers.CurlFail(fmt.Sprintf("http://%s:80/", ip)))
						Expect(err).To(BeNil(), "Cannot curl from %s to service %s on  ip %s", pod, service, ip)
					})
				}

			}
		}

	}, 1)

	Context("Nightly Policies", func() {
		numPods := 20
		bunchPods := 5
		podsCreated := 0

		AfterEach(func() {
			kubectl.Exec(fmt.Sprintf(
				"%s delete --all pods,svc,cnp -n %s", helpers.KubectlCmd, helpers.DefaultNamespace))
		})

		Measure(fmt.Sprintf("Applying policies to %d pods in a group of %d", numPods, bunchPods), func(b Benchmarker) {
			testDef := func() {
				logger.Errorf("Creating %d new pods, total created are %d", numPods, podsCreated)
				testSpecGroup := policygen.TestSpecsGroup{}
				for i := 0; i < bunchPods; i++ {
					testSpec := policygen.GetBasicTestSpec()
					testSpecGroup = append(testSpecGroup, &testSpec)
				}

				By("Creating endpoints")

				endpoints := b.Time("Runtime", func() {
					testSpecGroup.CreateAndApplyManifests(kubectl)
				})
				b.RecordValue("Endpoint Creation in seconds", endpoints.Seconds())
				By("Apply Policies")

				policy := b.Time("policy", func() {
					testSpecGroup.CreateAndApplyCNP(kubectl)
				})
				b.RecordValue("Policy Creation in seconds", policy.Seconds())

				By("Connectivity Test")
				conn := b.Time("connTest", func() {
					testSpecGroup.ConnectivityTest()
				})

				b.RecordValue("Connectivity test in seconds", conn.Seconds())
			}

			for podsCreated < numPods {
				testDef()
				podsCreated = podsCreated + bunchPods
			}
		}, 1)
	})
})

var _ = Describe("NightlyExamples", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var once sync.Once
	var ciliumPath string
	var demoPath string
	var l3Policy, l7Policy string
	var appService = "app1-service"
	var apps []string

	initialize := func() {
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
		kubectl.Delete(ciliumPath)

		apps = []string{helpers.App1, helpers.App2, helpers.App3}

		demoPath = kubectl.ManifestGet("demo.yaml")
		l3Policy = kubectl.ManifestGet("l3_l4_policy.yaml")
		l7Policy = kubectl.ManifestGet("l7_policy.yaml")
	}

	BeforeEach(func() {
		once.Do(initialize)
	})

	AfterEach(func() {
		if CurrentGinkgoTestDescription().Failed {
			ciliumPod, _ := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, helpers.K8s1)
			kubectl.CiliumReport(helpers.KubeSystemNamespace, ciliumPod, []string{
				"cilium service list",
				"cilium endpoint list"})
		}

		kubectl.Delete(demoPath)
		kubectl.Delete(l3Policy)
		kubectl.Delete(l7Policy)

		err := kubectl.WaitCleanAllTerminatingPods()
		Expect(err).To(BeNil(), "Terminating containers are not deleted after timeout")
	})

	Context("Cilium DS from example", func() {
		InstallExampleCilium := func() {
			var path = "../examples/kubernetes/cilium.yaml"
			var result bytes.Buffer
			newCiliumDSName := fmt.Sprintf("cilium_ds_%s.json", helpers.MakeUID())

			objects, err := helpers.DecodeYAMLOrJSON(path)
			Expect(err).To(BeNil())

			for _, object := range objects {
				data, err := json.Marshal(object)
				Expect(err).To(BeNil())

				jsonObj, err := gabs.ParseJSON(data)
				Expect(err).To(BeNil())

				value, _ := jsonObj.Path("kind").Data().(string)
				if value == configMap {
					jsonObj.SetP("---\nendpoints:\n- http://k8s1:9732\n", "data.etcd-config")
					jsonObj.SetP("true", "data.debug")
				}

				result.WriteString(jsonObj.String())
			}

			fp, err := os.Create(newCiliumDSName)
			defer fp.Close()
			Expect(err).To(BeNil())

			fmt.Fprint(fp, result.String())

			kubectl.Apply(helpers.GetFilePath(newCiliumDSName)).ExpectSuccess(
				"cannot apply cilium example daemonset")

			status, err := kubectl.WaitforPods(
				helpers.KubeSystemNamespace, "-l k8s-app=cilium", 300)
			Expect(status).Should(BeTrue(), "Cilium is not ready after timeout")
			Expect(err).Should(BeNil(), "Cilium is not ready after timeout")
		}

		waitEndpointReady := func() {
			ciliumPods, err := kubectl.GetCiliumPods(helpers.KubeSystemNamespace)
			Expect(err).To(BeNil(), "cannot retrieve cilium pods")
			for _, pod := range ciliumPods {
				ExpectWithOffset(1, kubectl.CiliumEndpointWait(pod)).To(BeTrue(),
					"Pods are not ready in pod %v", pod)
			}
		}

		AfterEach(func() {
			kubectl.Exec(fmt.Sprintf(
				"%s -n %s delete ds cilium",
				helpers.KubectlCmd, helpers.KubeSystemNamespace)).ExpectSuccess(
				"Cilium DS cannot be deleted")
		})

		BeforeEach(func() {
			kubectl.Exec("sudo docker rmi cilium/cilium")
			InstallExampleCilium()
		})

		It("Check Kubernetes Example is working correctly", func() {
			kubectl.Apply(demoPath).ExpectSuccess()
			_, err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", 300)
			Expect(err).Should(BeNil())

			_, err = kubectl.CiliumPolicyAction(
				helpers.KubeSystemNamespace, l3Policy, helpers.KubectlApply, 300)
			Expect(err).Should(BeNil())

			appPods := helpers.GetAppPods(apps, helpers.DefaultNamespace, kubectl, "id")

			clusterIP, _, err := kubectl.GetServiceHostPort(helpers.DefaultNamespace, appService)
			Expect(err).Should(BeNil())

			_, err = kubectl.ExecPodCmd(
				helpers.DefaultNamespace, appPods[helpers.App2],
				helpers.CurlFail(fmt.Sprintf("http://%s/public", clusterIP)))
			Expect(err).Should(BeNil())

			_, err = kubectl.ExecPodCmd(
				helpers.DefaultNamespace, appPods[helpers.App3],
				helpers.CurlFail(fmt.Sprintf("http://%s/public", clusterIP)))
			Expect(err).Should(HaveOccurred())
		})

		It("Updating Cilium stable to master", func() {
			By("Creating some endpoints and L7 policy")
			kubectl.Apply(demoPath).ExpectSuccess()
			_, err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", 300)
			Expect(err).Should(BeNil())

			kubectl.Exec(fmt.Sprintf("%s scale deployment %s --replicas=10",
				helpers.KubectlCmd, helpers.App1)).ExpectSuccess("Cilium DS cannot be deleted")

			_, err = kubectl.CiliumPolicyAction(
				helpers.KubeSystemNamespace, l7Policy, helpers.KubectlApply, 300)
			Expect(err).Should(BeNil(), "cannot import l7 policy")

			waitEndpointReady()

			appPods := getAppPods()
			_, err = kubectl.ExecPodCmd(
				helpers.DefaultNamespace, appPods[helpers.App2],
				helpers.CurlFail(fmt.Sprintf("http://app1-service/public")))
			Expect(err).To(BeNil(), "Cannot curl service")

			By("Updating cilium to master image")

			localImage := "k8s1:5000/cilium/cilium-dev"
			resource := "daemonset/cilium"

			kubectl.Exec(fmt.Sprintf("%s -n %s set image %s cilium-agent=%s",
				helpers.KubectlCmd, helpers.KubeSystemNamespace,
				resource, localImage)).ExpectSuccess(
				"Cannot update image")

			kubectl.Exec(fmt.Sprintf("%s rollout status %s -n %s",
				helpers.KubectlCmd, resource,
				helpers.KubeSystemNamespace)).ExpectSuccess("Cannot rollout the change")

			waitForUpdateImage := func() bool {
				pods, err := kubectl.GetCiliumPods(helpers.KubeSystemNamespace)
				if err != nil {
					return false
				}

				filter := `{.items[*].status.containerStatuses[0].image}`
				data, err := kubectl.GetPods(
					helpers.KubeSystemNamespace, "-l k8s-app=cilium").Filter(filter)
				if err != nil {
					return false
				}
				number := strings.Count(data.String(), localImage)
				if number == len(pods) {
					return true
				}
				logger.Infof("Only '%v' of '%v' cilium pods updated to the new image",
					number, len(pods))
				return false
			}

			err = helpers.WithTimeout(
				waitForUpdateImage,
				"Cilium Pods are not updating correctly",
				&helpers.TimeoutConfig{Timeout: 300})
			Expect(err).To(BeNil(), "Pods are not updating")

			status, err := kubectl.WaitforPods(
				helpers.KubeSystemNamespace, "-l k8s-app=cilium", 300)
			Expect(status).Should(BeTrue())
			Expect(err).Should(BeNil())

			_, err = kubectl.ExecPodCmd(
				helpers.DefaultNamespace, appPods[helpers.App2],
				helpers.CurlFail(fmt.Sprintf("http://app1-service/public")))
			Expect(err).To(BeNil(), "Cannot curl service after update")
		})
	})
})
<|endoftext|>


<commit_before>// Copyright 2017 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 (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"path"
	"strings"
	"time"

	"github.com/cilium/cilium/test/helpers"

	"github.com/Jeffail/gabs"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var (
	configMap = "ConfigMap"
)

var _ = Describe("NightlyK8sEpsMeasurement", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var initialized bool
	var ciliumPath string

	initialize := func() {
		if initialized == true {
			return
		}
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		ciliumPath = kubectl.ManifestGet("cilium_ds.yaml")
		kubectl.Apply(ciliumPath)

		_, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 600)
		Expect(err).Should(BeNil())
		initialized = true
	}

	BeforeEach(func() {
		initialize()
	})

	AfterEach(func() {
		if CurrentGinkgoTestDescription().Failed {
			ciliumPod, _ := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, "k8s1")
			kubectl.CiliumReport("kube-system", ciliumPod, []string{
				"cilium service list",
				"cilium endpoint list"})
		}
	})

	endpointCount := 20
	manifestPath := "tmp.yaml"
	vagrantManifestPath := path.Join(helpers.BasePath, manifestPath)
	var lastServer int

	Measure(fmt.Sprintf("%d endpoint creation", endpointCount), func(b Benchmarker) {
		var err error
		_, lastServer, err = helpers.GenerateManifestForEndpoints(endpointCount, manifestPath)
		Expect(err).Should(BeNil())

		res := kubectl.Apply(vagrantManifestPath)
		res.ExpectSuccess(res.GetDebugMessage())

		waitForPodsTime := b.Time("Wait for pods", func() {
			pods, err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", 300)
			Expect(pods).Should(BeTrue())
			Expect(err).Should(BeNil())
		})
		log.WithFields(logrus.Fields{"pod creation time": waitForPodsTime}).Info("")

		ciliumPod, err := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, helpers.K8s1)
		Expect(err).Should(BeNil())

		ciliumPod2, err := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, helpers.K8s2)
		Expect(err).Should(BeNil())

		pods := []string{ciliumPod, ciliumPod2}

		runtime := b.Time("Endpoint creation", func() {

			Eventually(func() bool {
				count := 0
				for _, pod := range pods {
					output := kubectl.CiliumExec(pod, "cilium endpoint list").Output().String()
					count += strings.Count(output, "ready")
				}

				return count >= endpointCount

			}, 300*time.Second, 3*time.Second).Should(BeTrue())
		})
		log.WithFields(logrus.Fields{"endpoint creation time": runtime}).Info("")

	}, 1)

	It("Should be able to connect from client pods to services while cilium pod is being restarted", func() {
		defer kubectl.Delete(vagrantManifestPath)

		connectivityTestsFinished := make(chan struct{})

		// Run connectivity tests
		go func() {
			concurrency := 5
			sem := make(chan struct{}, concurrency)

			for serverIndex := 0; serverIndex <= lastServer; serverIndex++ {
				for clientIndex := lastServer + 1; clientIndex < endpointCount; clientIndex++ {
					sem <- struct{}{}
					go func(to, from int) {
						defer func() { <-sem }()
						defer GinkgoRecover()

						result := kubectl.TestConnectivityPodService(fmt.Sprintf("app%d", from), fmt.Sprintf("app%d-service", to))
						result.ExpectSuccess(result.GetDebugMessage())

					}(serverIndex, clientIndex)
				}
			}
			// fill the channel to make sure there are no goroutines left
			for i := 0; i < cap(sem); i++ {
				sem <- struct{}{}
			}
			log.Info("Connectivity checks finished")
			connectivityTestsFinished <- struct{}{}
		}()

		// Randomly redeploy cilium agent
	Redeploy:
		for {
			select {
			case <-connectivityTestsFinished:
				break Redeploy
			default:
				res := kubectl.Delete(ciliumPath)
				res.ExpectSuccess(res.GetDebugMessage())

				res = kubectl.Apply(ciliumPath)
				res.ExpectSuccess(res.GetDebugMessage())

				_, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 600)
				Expect(err).Should(BeNil())
			}
		}
	})
})

var _ = Describe("NightlyK8sExamples", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var initialized bool
	var ciliumPath string
	var demoPath string
	var l3Policy string
	var appService = "app1-service"

	initialize := func() {
		if initialized == true {
			return
		}
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
		kubectl.Delete(ciliumPath)

		demoPath = fmt.Sprintf("%s/demo.yaml", kubectl.ManifestsPath())
		l3Policy = fmt.Sprintf("%s/l3_l4_policy.yaml", kubectl.ManifestsPath())
		initialized = true
	}

	BeforeEach(func() {
		initialize()
	})

	AfterEach(func() {
		kubectl.Delete(demoPath)
		kubectl.Delete(l3Policy)
	})

	// getAppPods return a map where the key is the Application name and the
	// value is the pod name
	getAppPods := func() map[string]string {
		appPods := make(map[string]string)
		apps := []string{helpers.App1, helpers.App2, helpers.App3}
		for _, v := range apps {
			res, err := kubectl.GetPodNames(helpers.DefaultNamespace, fmt.Sprintf("id=%s", v))
			Expect(err).Should(BeNil())
			appPods[v] = res[0]
			logger.Infof("PolicyRulesTest: pod=%q assigned to %q", res[0], v)
		}
		return appPods
	}

	It("Check K8s Example is working correctly", func() {
		var path = "../examples/kubernetes/cilium.yaml"
		var result bytes.Buffer
		newCiliumDSName := fmt.Sprintf("cilium_ds_%s.json", helpers.MakeUID())

		objects, err := helpers.DecodeYAMLOrJSON(path)
		Expect(err).To(BeNil())

		for _, object := range objects {
			data, err := json.Marshal(object)
			Expect(err).To(BeNil())

			jsonObj, err := gabs.ParseJSON(data)
			Expect(err).To(BeNil())

			value, _ := jsonObj.Path("kind").Data().(string)
			if value == configMap {
				jsonObj.SetP("---\nendpoints:\n- http://k8s1:9732\n", "data.etcd-config")
				jsonObj.SetP("true", "data.debug")
			}

			result.WriteString(jsonObj.String())
		}

		fp, err := os.Create(newCiliumDSName)
		defer fp.Close()
		Expect(err).To(BeNil())

		fmt.Fprint(fp, result.String())

		kubectl.Apply(helpers.GetFilePath(newCiliumDSName))
		defer kubectl.Delete(helpers.GetFilePath(newCiliumDSName))
		status, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 300)
		Expect(status).Should(BeTrue())
		Expect(err).Should(BeNil())

		kubectl.Apply(demoPath)
		_, err = kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", 300)
		Expect(err).Should(BeNil())

		_, err = kubectl.CiliumImportPolicy(helpers.KubeSystemNamespace, l3Policy, 300)
		Expect(err).Should(BeNil())

		appPods := getAppPods()

		clusterIP, _, err := kubectl.GetServiceHostPort(helpers.DefaultNamespace, appService)
		Expect(err).Should(BeNil())

		_, err = kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App2],
			helpers.CurlFail(fmt.Sprintf("http://%s/public", clusterIP)))
		Expect(err).Should(BeNil())

		_, err = kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App3],
			helpers.CurlFail(fmt.Sprintf("http://%s/public", clusterIP)))
		Expect(err).Should(HaveOccurred())
	})
})
<commit_msg>Ginkgo: Fix name on Nightly Test<commit_after>// Copyright 2017 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 (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"path"
	"strings"
	"time"

	"github.com/cilium/cilium/test/helpers"

	"github.com/Jeffail/gabs"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var (
	configMap = "ConfigMap"
)

var _ = Describe("NightlyK8sEpsMeasurement", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var initialized bool
	var ciliumPath string

	initialize := func() {
		if initialized == true {
			return
		}
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)

		ciliumPath = kubectl.ManifestGet("cilium_ds.yaml")
		kubectl.Apply(ciliumPath)

		_, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 600)
		Expect(err).Should(BeNil())
		initialized = true
	}

	BeforeEach(func() {
		initialize()
	})

	AfterEach(func() {
		if CurrentGinkgoTestDescription().Failed {
			ciliumPod, _ := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, "k8s1")
			kubectl.CiliumReport("kube-system", ciliumPod, []string{
				"cilium service list",
				"cilium endpoint list"})
		}
	})

	endpointCount := 20
	manifestPath := "tmp.yaml"
	vagrantManifestPath := path.Join(helpers.BasePath, manifestPath)
	var lastServer int

	Measure(fmt.Sprintf("%d endpoint creation", endpointCount), func(b Benchmarker) {
		var err error
		_, lastServer, err = helpers.GenerateManifestForEndpoints(endpointCount, manifestPath)
		Expect(err).Should(BeNil())

		res := kubectl.Apply(vagrantManifestPath)
		res.ExpectSuccess(res.GetDebugMessage())

		waitForPodsTime := b.Time("Wait for pods", func() {
			pods, err := kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", 300)
			Expect(pods).Should(BeTrue())
			Expect(err).Should(BeNil())
		})
		log.WithFields(logrus.Fields{"pod creation time": waitForPodsTime}).Info("")

		ciliumPod, err := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, helpers.K8s1)
		Expect(err).Should(BeNil())

		ciliumPod2, err := kubectl.GetCiliumPodOnNode(helpers.KubeSystemNamespace, helpers.K8s2)
		Expect(err).Should(BeNil())

		pods := []string{ciliumPod, ciliumPod2}

		runtime := b.Time("Endpoint creation", func() {

			Eventually(func() bool {
				count := 0
				for _, pod := range pods {
					output := kubectl.CiliumExec(pod, "cilium endpoint list").Output().String()
					count += strings.Count(output, "ready")
				}

				return count >= endpointCount

			}, 300*time.Second, 3*time.Second).Should(BeTrue())
		})
		log.WithFields(logrus.Fields{"endpoint creation time": runtime}).Info("")

	}, 1)

	It("Should be able to connect from client pods to services while cilium pod is being restarted", func() {
		defer kubectl.Delete(vagrantManifestPath)

		connectivityTestsFinished := make(chan struct{})

		// Run connectivity tests
		go func() {
			concurrency := 5
			sem := make(chan struct{}, concurrency)

			for serverIndex := 0; serverIndex <= lastServer; serverIndex++ {
				for clientIndex := lastServer + 1; clientIndex < endpointCount; clientIndex++ {
					sem <- struct{}{}
					go func(to, from int) {
						defer func() { <-sem }()
						defer GinkgoRecover()

						result := kubectl.TestConnectivityPodService(fmt.Sprintf("app%d", from), fmt.Sprintf("app%d-service", to))
						result.ExpectSuccess(result.GetDebugMessage())

					}(serverIndex, clientIndex)
				}
			}
			// fill the channel to make sure there are no goroutines left
			for i := 0; i < cap(sem); i++ {
				sem <- struct{}{}
			}
			log.Info("Connectivity checks finished")
			connectivityTestsFinished <- struct{}{}
		}()

		// Randomly redeploy cilium agent
	Redeploy:
		for {
			select {
			case <-connectivityTestsFinished:
				break Redeploy
			default:
				res := kubectl.Delete(ciliumPath)
				res.ExpectSuccess(res.GetDebugMessage())

				res = kubectl.Apply(ciliumPath)
				res.ExpectSuccess(res.GetDebugMessage())

				_, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 600)
				Expect(err).Should(BeNil())
			}
		}
	})
})

var _ = Describe("NightlyK8sExamples", func() {

	var kubectl *helpers.Kubectl
	var logger *logrus.Entry
	var initialized bool
	var ciliumPath string
	var demoPath string
	var l3Policy string
	var appService = "app1-service"

	initialize := func() {
		if initialized == true {
			return
		}
		logger = log.WithFields(logrus.Fields{"testName": "NightlyK8sEpsMeasurement"})
		logger.Info("Starting")

		kubectl = helpers.CreateKubectl(helpers.K8s1VMName(), logger)
		kubectl.Delete(ciliumPath)

		demoPath = fmt.Sprintf("%s/demo.yaml", kubectl.ManifestsPath())
		l3Policy = fmt.Sprintf("%s/l3_l4_policy.yaml", kubectl.ManifestsPath())
		initialized = true
	}

	BeforeEach(func() {
		initialize()
	})

	AfterEach(func() {
		kubectl.Delete(demoPath)
		kubectl.Delete(l3Policy)
	})

	// getAppPods return a map where the key is the Application name and the
	// value is the pod name
	getAppPods := func() map[string]string {
		appPods := make(map[string]string)
		apps := []string{helpers.App1, helpers.App2, helpers.App3}
		for _, v := range apps {
			res, err := kubectl.GetPodNames(helpers.DefaultNamespace, fmt.Sprintf("id=%s", v))
			Expect(err).Should(BeNil())
			appPods[v] = res[0]
			logger.Infof("PolicyRulesTest: pod=%q assigned to %q", res[0], v)
		}
		return appPods
	}

	It("Check Kubernetes Example is working correctly", func() {
		var path = "../examples/kubernetes/cilium.yaml"
		var result bytes.Buffer
		newCiliumDSName := fmt.Sprintf("cilium_ds_%s.json", helpers.MakeUID())

		objects, err := helpers.DecodeYAMLOrJSON(path)
		Expect(err).To(BeNil())

		for _, object := range objects {
			data, err := json.Marshal(object)
			Expect(err).To(BeNil())

			jsonObj, err := gabs.ParseJSON(data)
			Expect(err).To(BeNil())

			value, _ := jsonObj.Path("kind").Data().(string)
			if value == configMap {
				jsonObj.SetP("---\nendpoints:\n- http://k8s1:9732\n", "data.etcd-config")
				jsonObj.SetP("true", "data.debug")
			}

			result.WriteString(jsonObj.String())
		}

		fp, err := os.Create(newCiliumDSName)
		defer fp.Close()
		Expect(err).To(BeNil())

		fmt.Fprint(fp, result.String())

		kubectl.Apply(helpers.GetFilePath(newCiliumDSName))
		defer kubectl.Delete(helpers.GetFilePath(newCiliumDSName))
		status, err := kubectl.WaitforPods(helpers.KubeSystemNamespace, "-l k8s-app=cilium", 300)
		Expect(status).Should(BeTrue())
		Expect(err).Should(BeNil())

		kubectl.Apply(demoPath)
		_, err = kubectl.WaitforPods(helpers.DefaultNamespace, "-l zgroup=testapp", 300)
		Expect(err).Should(BeNil())

		_, err = kubectl.CiliumImportPolicy(helpers.KubeSystemNamespace, l3Policy, 300)
		Expect(err).Should(BeNil())

		appPods := getAppPods()

		clusterIP, _, err := kubectl.GetServiceHostPort(helpers.DefaultNamespace, appService)
		Expect(err).Should(BeNil())

		_, err = kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App2],
			helpers.CurlFail(fmt.Sprintf("http://%s/public", clusterIP)))
		Expect(err).Should(BeNil())

		_, err = kubectl.ExecPodCmd(
			helpers.DefaultNamespace, appPods[helpers.App3],
			helpers.CurlFail(fmt.Sprintf("http://%s/public", clusterIP)))
		Expect(err).Should(HaveOccurred())
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2021 The Vitess 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 throttle

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

const (
	throttleCheckDuration = 250 * time.Millisecond
)

// Client construct is used by apps who wish to consult with a throttler. It encapsulates the check/throttling/backoff logic
type Client struct {
	throttler *Throttler
	appName   string
	checkType ThrottleCheckType
	flags     CheckFlags

	lastSuccessfulThrottleCheck time.Time
}

// NewProductionClient creates a client suitable for foreground/production jobs, which have normal priority.
func NewProductionClient(throttler *Throttler, appName string, checkType ThrottleCheckType) *Client {
	return &Client{
		throttler: throttler,
		appName:   appName,
		checkType: checkType,
		flags: CheckFlags{
			LowPriority: false,
		},
	}
}

// NewBackgroundClient creates a client suitable for background jobs, which have low priority over productio ntraffic,
// e.g. migration, table pruning, vreplication
func NewBackgroundClient(throttler *Throttler, appName string, checkType ThrottleCheckType) *Client {
	return &Client{
		throttler: throttler,
		appName:   appName,
		checkType: checkType,
		flags: CheckFlags{
			LowPriority: true,
		},
	}
}

// ThrottleCheckOK checks the throttler, and returns 'true' when the throttler is satisfied.
// It does not sleep.
// The function caches results for a brief amount of time, hence it's safe and efficient to
// be called very frequenty.
// The function is not thread safe.
func (c *Client) ThrottleCheckOK(ctx context.Context) (throttleCheckOK bool) {
	if c == nil {
		// no client
		return true
	}
	if c.throttler == nil {
		// no throttler
		return true
	}
	if time.Since(c.lastSuccessfulThrottleCheck) <= throttleCheckDuration {
		// if last check was OK just very recently there is no need to check again
		return true
	}
	// It's time to run a throttler check
	checkResult := c.throttler.CheckByType(ctx, c.appName, "", &c.flags, c.checkType)
	if checkResult.StatusCode != http.StatusOK {
		return false
	}
	c.lastSuccessfulThrottleCheck = time.Now()
	return true

}

// ThrottleCheckOKOrWait checks the throttler; if throttler is satisfied, the function returns 'true' mmediately,
// otherwise it briefly sleeps and returns 'false'.
// The function is not thread safe.
func (c *Client) ThrottleCheckOKOrWait(ctx context.Context) bool {
	ok := c.ThrottleCheckOK(ctx)
	if !ok {
		time.Sleep(throttleCheckDuration)
	}
	return ok
}

// Throttle throttles until the throttler is satisfied, or until context is cancelled.
// The function sleeps between throttle checks.
// The function is not thread safe.
func (c *Client) Throttle(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			return
		default:
		}
		if c.ThrottleCheckOKOrWait(ctx) {
			break
		}
	}
}
<commit_msg>throttle: do not check for time constantly<commit_after>/*
Copyright 2021 The Vitess 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 throttle

import (
	"context"
	"net/http"
	"sync"
	"sync/atomic"
	"time"
)

const (
	throttleCheckDuration = 250 * time.Millisecond
)

var throttleTicks int64
var throttleInit sync.Once

func initThrottleTicker() {
	throttleInit.Do(func() {
		go func() {
			tick := time.NewTicker(throttleCheckDuration)
			defer tick.Stop()
			for range tick.C {
				atomic.AddInt64(&throttleTicks, 1)
			}
		}()
	})
}

// Client construct is used by apps who wish to consult with a throttler. It encapsulates the check/throttling/backoff logic
type Client struct {
	throttler *Throttler
	appName   string
	checkType ThrottleCheckType
	flags     CheckFlags

	lastSuccessfulThrottle int64
}

// NewProductionClient creates a client suitable for foreground/production jobs, which have normal priority.
func NewProductionClient(throttler *Throttler, appName string, checkType ThrottleCheckType) *Client {
	initThrottleTicker()
	return &Client{
		throttler: throttler,
		appName:   appName,
		checkType: checkType,
		flags: CheckFlags{
			LowPriority: false,
		},
	}
}

// NewBackgroundClient creates a client suitable for background jobs, which have low priority over productio ntraffic,
// e.g. migration, table pruning, vreplication
func NewBackgroundClient(throttler *Throttler, appName string, checkType ThrottleCheckType) *Client {
	initThrottleTicker()
	return &Client{
		throttler: throttler,
		appName:   appName,
		checkType: checkType,
		flags: CheckFlags{
			LowPriority: true,
		},
	}
}

// ThrottleCheckOK checks the throttler, and returns 'true' when the throttler is satisfied.
// It does not sleep.
// The function caches results for a brief amount of time, hence it's safe and efficient to
// be called very frequenty.
// The function is not thread safe.
func (c *Client) ThrottleCheckOK(ctx context.Context) (throttleCheckOK bool) {
	if c == nil {
		// no client
		return true
	}
	if c.throttler == nil {
		// no throttler
		return true
	}
	if c.lastSuccessfulThrottle >= atomic.LoadInt64(&throttleTicks) {
		// if last check was OK just very recently there is no need to check again
		return true
	}
	// It's time to run a throttler check
	checkResult := c.throttler.CheckByType(ctx, c.appName, "", &c.flags, c.checkType)
	if checkResult.StatusCode != http.StatusOK {
		return false
	}
	c.lastSuccessfulThrottle = atomic.LoadInt64(&throttleTicks)
	return true

}

// ThrottleCheckOKOrWait checks the throttler; if throttler is satisfied, the function returns 'true' mmediately,
// otherwise it briefly sleeps and returns 'false'.
// The function is not thread safe.
func (c *Client) ThrottleCheckOKOrWait(ctx context.Context) bool {
	ok := c.ThrottleCheckOK(ctx)
	if !ok {
		time.Sleep(throttleCheckDuration)
	}
	return ok
}

// Throttle throttles until the throttler is satisfied, or until context is cancelled.
// The function sleeps between throttle checks.
// The function is not thread safe.
func (c *Client) Throttle(ctx context.Context) {
	for {
		if ctx.Err() != nil {
			return
		}
		if c.ThrottleCheckOKOrWait(ctx) {
			break
		}
	}
}
<|endoftext|>


<commit_before>package fetch

import (
	"bytes"
	"fmt"
	"github.com/disintegration/imaging"
	"github.com/rwcarlsen/goexif/exif"
	"image"
	"image/jpeg"
	"image/png"
	"io"
)

func needsRotation(src io.Reader) (bool, int) {
	metadata, err := exif.Decode(src)
	if err != nil {
		fmt.Println(err.Error())
		return false, 0
	}

	orientation, err := x.Get(exif.Orientation)
	if err != nil {
		fmt.Println(err.Error())
		return false, 0
	}

	angle := 0
	rotate := false

	switch orientation.String() {
	case "6":
		angle = 90
		rotate = true
	case "3":
		angle = 180
		rotate = true
	case "8":
		angle = 270
		rotate = true
	}

	return rotate, angle
}

func Resize(src io.Reader, c *CacheContext) (io.Reader, error) {
	image, format, err := image.Decode(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	buf := new(bytes.Buffer)

	factor := float64(c.Width) / float64(image.Bounds().Size().X)
	height := int(float64(image.Bounds().Size().Y) * factor)

	image = imaging.Resize(image, c.Width, height, imaging.Linear)

	if rotate, angle := needsRotation(src); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	switch format {
	case "jpeg":
		jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}

func CenterCrop(src io.Reader, c *CacheContext) (io.Reader, error) {
	image, format, err := image.Decode(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	if rotate, angle := needsRotation(src); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	buf := new(bytes.Buffer)

	height := image.Bounds().Size().Y
	width := image.Bounds().Size().X

	if width < height {
		image = imaging.CropCenter(image, width, width)
	} else if width > height {
		image = imaging.CropCenter(image, height, height)
	} else {
		image = imaging.CropCenter(image, width, height)
	}

	switch format {
	case "jpeg":
		jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}
<commit_msg>Use bytes.Reader<commit_after>package fetch

import (
	"bytes"
	"fmt"
	"github.com/disintegration/imaging"
	"github.com/rwcarlsen/goexif/exif"
	"image"
	"image/jpeg"
	"image/png"
	"io"
)

func needsRotation(src io.Reader) (bool, int) {
	metadata, err := exif.Decode(src)
	if err != nil {
		fmt.Println(err.Error())
		return false, 0
	}

	orientation, err := x.Get(exif.Orientation)
	if err != nil {
		fmt.Println(err.Error())
		return false, 0
	}

	angle := 0
	rotate := false

	switch orientation.String() {
	case "6":
		angle = 90
		rotate = true
	case "3":
		angle = 180
		rotate = true
	case "8":
		angle = 270
		rotate = true
	}

	return rotate, angle
}

func Resize(src io.Reader, c *CacheContext) (io.Reader, error) {
	data := bytes.Reader(src)

	image, format, err := image.Decode(data)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	buf := new(bytes.Buffer)

	factor := float64(c.Width) / float64(image.Bounds().Size().X)
	height := int(float64(image.Bounds().Size().Y) * factor)

	image = imaging.Resize(image, c.Width, height, imaging.Linear)

	data.Seek(0, 0)

	if rotate, angle := needsRotation(data); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	switch format {
	case "jpeg":
		jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}

func CenterCrop(src io.Reader, c *CacheContext) (io.Reader, error) {
	data := bytes.Reader(src)

	image, format, err := image.Decode(data)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	data.Seek(0, 0)

	if rotate, angle := needsRotation(data); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	buf := new(bytes.Buffer)

	height := image.Bounds().Size().Y
	width := image.Bounds().Size().X

	if width < height {
		image = imaging.CropCenter(image, width, width)
	} else if width > height {
		image = imaging.CropCenter(image, height, height)
	} else {
		image = imaging.CropCenter(image, width, height)
	}

	switch format {
	case "jpeg":
		jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}
<|endoftext|>


<commit_before>package fetch

import (
	"bytes"
	"fmt"
	"github.com/disintegration/imaging"
	"github.com/rwcarlsen/goexif/exif"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"io/ioutil"
)

func needsRotation(src io.Reader) (bool, int) {
	metadata, err := exif.Decode(src)
	if err != nil {
		fmt.Println("Error decoding EXIF data: " + err.Error())
		return false, 0
	}

	orientation, err := metadata.Get(exif.Orientation)
	if err != nil {
		fmt.Println("Error trying to find EXIF orientation: " + err.Error())
		return false, 0
	}

	angle := 0
	rotate := false

	switch orientation.String() {
	case "6":
		angle = 90
		rotate = true
	case "3":
		angle = 180
		rotate = true
	case "8":
		angle = 270
		rotate = true
	}

	return rotate, angle
}

func Resize(src io.Reader, c *CacheContext) (io.Reader, error) {
	raw, err := ioutil.ReadAll(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	data := bytes.NewReader(raw)

	image, format, err := image.Decode(data)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	buf := new(bytes.Buffer)

	factor := float64(c.Width) / float64(image.Bounds().Size().X)
	height := int(float64(image.Bounds().Size().Y) * factor)

	image = imaging.Resize(image, c.Width, height, imaging.Linear)

	if _, err := data.Seek(0, 0); err != nil {
		fmt.Println(err.Error())
	}

	if rotate, angle := needsRotation(data); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	switch format {
	case "jpeg":
		err = jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}

func CenterCrop(src io.Reader, c *CacheContext) (io.Reader, error) {
	raw, err := ioutil.ReadAll(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	data := bytes.NewReader(raw)

	image, format, err := image.Decode(data)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	if _, err := data.Seek(0, 0); err != nil {
		fmt.Println(err.Error())
	}

	if rotate, angle := needsRotation(data); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	buf := new(bytes.Buffer)

	height := image.Bounds().Size().Y
	width := image.Bounds().Size().X

	if width < height {
		image = imaging.CropCenter(image, width, width)
	} else if width > height {
		image = imaging.CropCenter(image, height, height)
	} else {
		image = imaging.CropCenter(image, width, height)
	}

	switch format {
	case "jpeg":
		err = jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}
<commit_msg>Reorder rotation step in resize<commit_after>package fetch

import (
	"bytes"
	"fmt"
	"github.com/disintegration/imaging"
	"github.com/rwcarlsen/goexif/exif"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"io/ioutil"
)

func needsRotation(src io.Reader) (bool, int) {
	metadata, err := exif.Decode(src)
	if err != nil {
		fmt.Println("Error decoding EXIF data: " + err.Error())
		return false, 0
	}

	orientation, err := metadata.Get(exif.Orientation)
	if err != nil {
		fmt.Println("Error trying to find EXIF orientation: " + err.Error())
		return false, 0
	}

	angle := 0
	rotate := false

	switch orientation.String() {
	case "6":
		angle = 90
		rotate = true
	case "3":
		angle = 180
		rotate = true
	case "8":
		angle = 270
		rotate = true
	}

	return rotate, angle
}

func Resize(src io.Reader, c *CacheContext) (io.Reader, error) {
	raw, err := ioutil.ReadAll(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	data := bytes.NewReader(raw)

	image, format, err := image.Decode(data)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	if _, err := data.Seek(0, 0); err != nil {
		fmt.Println(err.Error())
	}

	if rotate, angle := needsRotation(data); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	factor := float64(c.Width) / float64(image.Bounds().Size().X)
	height := int(float64(image.Bounds().Size().Y) * factor)

	image = imaging.Resize(image, c.Width, height, imaging.Linear)

	buf := new(bytes.Buffer)

	switch format {
	case "jpeg":
		err = jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}

func CenterCrop(src io.Reader, c *CacheContext) (io.Reader, error) {
	raw, err := ioutil.ReadAll(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	data := bytes.NewReader(raw)

	image, format, err := image.Decode(data)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	if _, err := data.Seek(0, 0); err != nil {
		fmt.Println(err.Error())
	}

	if rotate, angle := needsRotation(data); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	height := image.Bounds().Size().Y
	width := image.Bounds().Size().X

	if width < height {
		image = imaging.CropCenter(image, width, width)
	} else if width > height {
		image = imaging.CropCenter(image, height, height)
	} else {
		image = imaging.CropCenter(image, width, height)
	}

	buf := new(bytes.Buffer)

	switch format {
	case "jpeg":
		err = jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}
<|endoftext|>


<commit_before>package fetch

import (
	"bytes"
	"fmt"
	"github.com/disintegration/imaging"
	"github.com/rwcarlsen/goexif/exif"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"io/ioutil"
)

func needsRotation(src io.Reader) (bool, int) {
	metadata, err := exif.Decode(src)
	if err != nil {
		return false, 0
	}

	orientation, err := metadata.Get(exif.Orientation)
	if err != nil {
		return false, 0
	}

	angle := 0
	rotate := false

	switch orientation.String() {
	case "6":
		angle = 270
		rotate = true
	case "3":
		angle = 180
		rotate = true
	case "8":
		angle = 90
		rotate = true
	}

	return rotate, angle
}

func getRotatedImage(src io.Reader) (image.Image, string, error) {
	raw, err := ioutil.ReadAll(src)
	if err != nil {
		return nil, "", err
	}

	data := bytes.NewReader(raw)

	image, format, err := image.Decode(data)
	if err != nil {
		return nil, "", err
	}

	if _, err := data.Seek(0, 0); err != nil {
		return nil, "", err
	}

	if rotate, angle := needsRotation(data); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	return image, format, nil
}

func Resize(src io.Reader, c *CacheContext) (io.Reader, error) {
	image, format, err := getRotatedImage(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	factor := float64(c.Width) / float64(image.Bounds().Size().X)
	height := int(float64(image.Bounds().Size().Y) * factor)

	image = imaging.Resize(image, c.Width, height, imaging.Linear)

	buf := new(bytes.Buffer)

	switch format {
	case "jpeg":
		err = jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}

func CenterCrop(src io.Reader, c *CacheContext) (io.Reader, error) {
	image, format, err := image.Decode(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	height := image.Bounds().Size().Y
	width := image.Bounds().Size().X

	if width < height {
		image = imaging.CropCenter(image, width, width)
	} else if width > height {
		image = imaging.CropCenter(image, height, height)
	} else {
		image = imaging.CropCenter(image, width, height)
	}

	buf := new(bytes.Buffer)

	switch format {
	case "jpeg":
		err = jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}
<commit_msg>Don't need to rotate here now<commit_after>package fetch

import (
	"bytes"
	"fmt"
	"github.com/disintegration/imaging"
	"github.com/rwcarlsen/goexif/exif"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"io/ioutil"
)

func needsRotation(src io.Reader) (bool, int) {
	metadata, err := exif.Decode(src)
	if err != nil {
		return false, 0
	}

	orientation, err := metadata.Get(exif.Orientation)
	if err != nil {
		return false, 0
	}

	angle := 0
	rotate := false

	switch orientation.String() {
	case "6":
		angle = 270
		rotate = true
	case "3":
		angle = 180
		rotate = true
	case "8":
		angle = 90
		rotate = true
	}

	return rotate, angle
}

func GetRotatedImage(src io.Reader) (image.Image, string, error) {
	raw, err := ioutil.ReadAll(src)
	if err != nil {
		return nil, "", err
	}

	data := bytes.NewReader(raw)

	image, format, err := image.Decode(data)
	if err != nil {
		return nil, "", err
	}

	if _, err := data.Seek(0, 0); err != nil {
		return nil, "", err
	}

	if rotate, angle := needsRotation(data); rotate {
		switch angle {
		case 90:
			image = imaging.Rotate90(image)
		case 180:
			image = imaging.Rotate180(image)
		case 270:
			image = imaging.Rotate270(image)
		}
	}

	return image, format, nil
}

func Resize(src io.Reader, c *CacheContext) (io.Reader, error) {
	image, format, err := image.Decode(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	factor := float64(c.Width) / float64(image.Bounds().Size().X)
	height := int(float64(image.Bounds().Size().Y) * factor)

	image = imaging.Resize(image, c.Width, height, imaging.Linear)

	buf := new(bytes.Buffer)

	switch format {
	case "jpeg":
		err = jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}

func CenterCrop(src io.Reader, c *CacheContext) (io.Reader, error) {
	image, format, err := image.Decode(src)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	height := image.Bounds().Size().Y
	width := image.Bounds().Size().X

	if width < height {
		image = imaging.CropCenter(image, width, width)
	} else if width > height {
		image = imaging.CropCenter(image, height, height)
	} else {
		image = imaging.CropCenter(image, width, height)
	}

	buf := new(bytes.Buffer)

	switch format {
	case "jpeg":
		err = jpeg.Encode(buf, image, nil)
	case "png":
		err = png.Encode(buf, image)
	}

	return buf, err
}
<|endoftext|>


<commit_before>package generators

import (
	"fmt"

	"github.com/yext/edward/services"
)

type ConfigGenerator func(path string) ([]*services.ServiceConfig, []*services.ServiceGroupConfig, error)

var Generators map[string]ConfigGenerator

func init() {
	Generators = make(map[string]ConfigGenerator)
}

func RegisterGenerator(name string, generator ConfigGenerator) {
	Generators[name] = generator
}

func GenerateServices(path string) ([]*services.ServiceConfig, []*services.ServiceGroupConfig, error) {

	var outServices []*services.ServiceConfig
	var outGroups []*services.ServiceGroupConfig

	err := validateDir(path)
	if err != nil {
		return outServices, outGroups, err
	}

	for name, generator := range Generators {
		s, g, err := generator(path)
		if err != nil {
			fmt.Println("Error in generator", name, ":", err)
		} else {
			outServices = append(outServices, s...)
			outGroups = append(outGroups, g...)
		}
	}

	return outServices, outGroups, nil
}
<commit_msg>Create the generators map on demand to avoid issues with init ordering.<commit_after>package generators

import (
	"fmt"

	"github.com/yext/edward/services"
)

type ConfigGenerator func(path string) ([]*services.ServiceConfig, []*services.ServiceGroupConfig, error)

var Generators map[string]ConfigGenerator

func RegisterGenerator(name string, generator ConfigGenerator) {
	if Generators == nil {
		Generators = make(map[string]ConfigGenerator)
	}
	Generators[name] = generator
}

func GenerateServices(path string) ([]*services.ServiceConfig, []*services.ServiceGroupConfig, error) {

	var outServices []*services.ServiceConfig
	var outGroups []*services.ServiceGroupConfig

	err := validateDir(path)
	if err != nil {
		return outServices, outGroups, err
	}

	for name, generator := range Generators {
		s, g, err := generator(path)
		if err != nil {
			fmt.Println("Error in generator", name, ":", err)
		} else {
			outServices = append(outServices, s...)
			outGroups = append(outGroups, g...)
		}
	}

	return outServices, outGroups, nil
}
<|endoftext|>


<commit_before>// Copyright 2017 The etcd-operator 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 main

import (
	"errors"
	"flag"
	"io"
	"os"
	"path/filepath"
	"time"

	"github.com/sirupsen/logrus"
	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/clientcmd"
)

func main() {
	kubeconfig := flag.String("kubeconfig", "", "kube config file path")
	e2ePodName := flag.String("e2e-podname", "", "e2e test pod's name")
	ns := flag.String("namespace", "default", "e2e test namespace")
	logsDir := flag.String("logs-dir", "_output/logs/", "dir for pods' logs")
	flag.Parse()

	if len(*e2ePodName) == 0 {
		panic("must set --e2e-podname")
	}

	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err)
	}
	kubecli, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err)
	}

	stopCh := make(chan struct{})
	podListWatcher := cache.NewListWatchFromClient(kubecli.CoreV1().RESTClient(), "pods", *ns, fields.Everything())
	_, informer := cache.NewIndexerInformer(podListWatcher, &v1.Pod{}, 0, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			go func(pod *v1.Pod, namespace, logsDir string) {
				watcher, err := kubecli.CoreV1().Pods(namespace).Watch(metav1.SingleObject(metav1.ObjectMeta{Name: pod.Name}))
				if err != nil {
					logrus.Errorf("failed to watch for pod (%s): %v", pod.Name, err)
					return
				}
				// We need to wait Pod Running before collecting its log
				ev, err := watch.Until(100*time.Second, watcher, podRunning)
				if err != nil {
					logrus.Errorf("failed to reach Running for pod (%s): %v", pod.Name, err)
					return
				}
				pod = ev.Object.(*v1.Pod)
				for i := range pod.Spec.Containers {
					go func(c v1.Container) {
						logOption := &v1.PodLogOptions{Follow: true, Container: c.Name}
						req := kubecli.CoreV1().Pods(namespace).GetLogs(pod.Name, logOption)
						readCloser, err := req.Stream()
						if err != nil {
							logrus.Errorf("failed to open stream for pod (%s): %v", pod.Name, err)
							return
						}
						defer readCloser.Close()

						f, err := os.OpenFile(filepath.Join(logsDir, pod.Name+"."+c.Name+".log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
						if err != nil {
							logrus.Errorf("failed to open log file for pod (%s/%s): %v", pod.Name, c.Name, err)
							return
						}
						_, err = io.Copy(f, readCloser)
						if err != nil {
							logrus.Errorf("failed to write log for pod (%s/%s): %v", pod.Name, c.Name, err)
						}
					}(pod.Spec.Containers[i])
				}
			}(obj.(*v1.Pod), *ns, *logsDir)
		},
		UpdateFunc: func(old, new interface{}) {
			pod := new.(*v1.Pod)
			if pod.Name != *e2ePodName {
				return
			}
			// If e2e test pod runs to completion, then stops this program.
			if pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed {
				close(stopCh)
			}
		},
	}, cache.Indexers{})

	logrus.Info("start collecting logs...")
	informer.Run(stopCh)
	logrus.Info("stop collecting logs...")
}

// **NOTE**: Copy from kubernetes.
// podRunning returns true if the pod is running, false if the pod has not yet reached running state,
// returns ErrPodCompleted if the pod has run to completion, or an error in any other case.
func podRunning(event watch.Event) (bool, error) {
	switch event.Type {
	case watch.Deleted:
		return false, errors.New("pod deleted")
	}
	switch t := event.Object.(type) {
	case *v1.Pod:
		switch t.Status.Phase {
		case v1.PodRunning:
			return true, nil
		case v1.PodFailed, v1.PodSucceeded:
			return false, errors.New("pod ran to completion")
		}
	}
	return false, nil
}
<commit_msg>logcollector: stop when pod is terminated (#1750)<commit_after>// Copyright 2017 The etcd-operator 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 main

import (
	"errors"
	"flag"
	"io"
	"os"
	"path/filepath"
	"time"

	"github.com/sirupsen/logrus"
	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/clientcmd"
)

func main() {
	kubeconfig := flag.String("kubeconfig", "", "kube config file path")
	e2ePodName := flag.String("e2e-podname", "", "e2e test pod's name")
	ns := flag.String("namespace", "default", "e2e test namespace")
	logsDir := flag.String("logs-dir", "_output/logs/", "dir for pods' logs")
	flag.Parse()

	if len(*e2ePodName) == 0 {
		panic("must set --e2e-podname")
	}

	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err)
	}
	kubecli, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err)
	}

	stopCh := make(chan struct{})
	podListWatcher := cache.NewListWatchFromClient(kubecli.CoreV1().RESTClient(), "pods", *ns, fields.Everything())
	_, informer := cache.NewIndexerInformer(podListWatcher, &v1.Pod{}, 0, cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			go func(pod *v1.Pod, namespace, logsDir string) {
				watcher, err := kubecli.CoreV1().Pods(namespace).Watch(metav1.SingleObject(metav1.ObjectMeta{Name: pod.Name}))
				if err != nil {
					logrus.Errorf("failed to watch for pod (%s): %v", pod.Name, err)
					return
				}
				// We need to wait Pod Running before collecting its log
				ev, err := watch.Until(100*time.Second, watcher, podRunning)
				if err != nil {
					logrus.Errorf("failed to reach Running for pod (%s): %v", pod.Name, err)
					return
				}
				pod = ev.Object.(*v1.Pod)
				for i := range pod.Spec.Containers {
					go func(c v1.Container) {
						logOption := &v1.PodLogOptions{Follow: true, Container: c.Name}
						req := kubecli.CoreV1().Pods(namespace).GetLogs(pod.Name, logOption)
						readCloser, err := req.Stream()
						if err != nil {
							logrus.Errorf("failed to open stream for pod (%s): %v", pod.Name, err)
							return
						}
						defer readCloser.Close()

						f, err := os.OpenFile(filepath.Join(logsDir, pod.Name+"."+c.Name+".log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
						if err != nil {
							logrus.Errorf("failed to open log file for pod (%s/%s): %v", pod.Name, c.Name, err)
							return
						}
						_, err = io.Copy(f, readCloser)
						if err != nil {
							logrus.Errorf("failed to write log for pod (%s/%s): %v", pod.Name, c.Name, err)
						}
					}(pod.Spec.Containers[i])
				}
			}(obj.(*v1.Pod), *ns, *logsDir)
		},
		UpdateFunc: func(old, new interface{}) {
			pod := new.(*v1.Pod)
			if pod.Name != *e2ePodName {
				return
			}
			// If e2e test pod runs to completion, then stops this program.
			if pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed || pod.DeletionTimestamp != nil {
				close(stopCh)
			}
		},
	}, cache.Indexers{})

	logrus.Info("start collecting logs...")
	informer.Run(stopCh)
	logrus.Info("stop collecting logs...")
}

// **NOTE**: Copy from kubernetes.
// podRunning returns true if the pod is running, false if the pod has not yet reached running state,
// returns ErrPodCompleted if the pod has run to completion, or an error in any other case.
func podRunning(event watch.Event) (bool, error) {
	switch event.Type {
	case watch.Deleted:
		return false, errors.New("pod deleted")
	}
	switch t := event.Object.(type) {
	case *v1.Pod:
		switch t.Status.Phase {
		case v1.PodRunning:
			return true, nil
		case v1.PodFailed, v1.PodSucceeded:
			return false, errors.New("pod ran to completion")
		}
	}
	return false, nil
}
<|endoftext|>


<commit_before>package numbers

import (
	"errors"
	"reflect"
	"testing"
)

// TestFactorsList unit test FactorsList function.
func TestFactorsList(t *testing.T) {
	testCases := []struct {
		input    int
		expected []int
		err      error
	}{
		{2, []int{2}, nil},
		{15, []int{3, 5}, nil},
		{26, []int{2, 13}, nil},
		{37, []int{37}, nil},
		{42, []int{2, 3, 7}, nil},
		{-1, []int(nil), errors.New("no prime factors for numbers below two. received '-1'")},
	}
	for _, test := range testCases {
		observed, err := FactorsList(test.input)
		if err != nil {
			if test.err.Error() != err.Error() {
				t.Error(err)
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for input '%d', expected '%v', got '%v'",
				test.input, test.expected, observed)
		}
	}
}

// BenchmarkFactorList benchmark FactorsList function.
func BenchmarkFactorList(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_, err := FactorsList(1000)
		if err != nil {
			b.Error(err)
		}
	}
}

// TestIsPrime unit test IsPrime function.
func TestIsPrime(t *testing.T) {
	testCases := []struct {
		input    int
		expected bool
	}{
		{-5, false},
		{0, false},
		{2, true},
		{6, false},
		{13, true},
	}
	for _, test := range testCases {
		observed := IsPrime(test.input)
		if observed != test.expected {
			t.Errorf("for input '%d', expected '%t', got '%t'",
				test.input, test.expected, observed)
		}
	}
}

// BenchmarkIsPrime benchmark IsPrime function.
func BenchmarkIsPrime(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_ = IsPrime(1728459)
	}
}

// TestFibonacciGen unit test FibonacciGen function.
func TestFibonacciGen(t *testing.T) {
	testCases := []struct {
		input, expected int
	}{
		{1, 0},
		{2, 1},
		{3, 1},
		{4, 2},
		{5, 3},
		{8, 13},
		{10, 34},
		{12, 89},
	}
	for _, test := range testCases {
		var observed int
		c := FibonacciGen()
		for n := 0; n < test.input; n++ {
			observed = <-c
		}
		if observed != test.expected {
			t.Errorf("for input '%d', expected '%d', got '%d'", test.input, test.expected, observed)
		}
	}
}

// BenchmarkFibonacciGen benchmark FibonacciGen function.
func BenchmarkFibonacciGen(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		c := FibonacciGen()
		for n := 0; n < 10000; n++ {
			_ = <-c
		}
	}
}

// TestNthFibonacci unit test NthFibonacci function.
func TestNthFibonacci(t *testing.T) {
	var testCases = []struct {
		input, expected int
	}{
		{1, 1},
		{5, 5},
		{7, 13},
		{10, 55},
		{19, 4181},
	}
	for _, test := range testCases {
		observed := NthFibonacci(test.input)
		if observed != test.expected {
			t.Errorf("for input '%d', expected '%d', got '%d'",
				test.input, test.expected, observed)
		}
	}
}

// BenchmarkNthFibonacci benchmark NthFibonacci function.
func BenchmarkNthFibonacci(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = NthFibonacci(10000)
	}
}

// TestEvenNumbers unit test EvenNumbers function.
func TestEvenNumbers(t *testing.T) {
	testCases := []struct {
		inputA, inputB int
		expected       []int
		err            error
	}{
		{1, 1, []int(nil), nil},
		{1, 3, []int{2}, nil},
		{4, 8, []int{4, 6, 8}, nil},
		{-4, 8, []int{-4, -2, 0, 2, 4, 6, 8}, nil},
		{-1, -2, []int(nil), errors.New("a must be greater than b. received a '-1' and b '-2'")},
	}
	for _, test := range testCases {
		observed, err := EvenNumbers(test.inputA, test.inputB)
		if err != nil {
			if err.Error() != test.err.Error() {
				t.Error(err)
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for a '%d' and b '%d', expected '%v', got '%v'",
				test.inputA, test.inputB, test.expected, observed)
		}
	}
}

// BenchmarkEvenNumbers benchmark EvenNumbers function.
func BenchmarkEvenNumbers(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_, err := EvenNumbers(1, 100000)
		if err != nil {
			b.Error(err)
		}
	}
}

// TestOddNumbers unit test OddNumbers function.
func TestOddNumbers(t *testing.T) {
	testCases := []struct {
		inputA, inputB int
		expected       []int
		err            error
	}{
		{1, 1, []int{1}, nil},
		{1, 3, []int{1, 3}, nil},
		{4, 8, []int{5, 7}, nil},
		{-4, 8, []int{-3, -1, 1, 3, 5, 7}, nil},
		{-1, -2, []int(nil), errors.New("a must be greater than b. received a '-1' and b '-2'")},
	}
	for _, test := range testCases {
		observed, err := OddNumbers(test.inputA, test.inputB)
		if err != nil {
			if err.Error() != test.err.Error() {
				t.Error(err)
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for a '%d' and b '%d', expected '%v', got '%v'",
				test.inputA, test.inputB, test.expected, observed)
		}
	}
}

// BenchmarkOddNumbers benchmark OddNumbers function.
func BenchmarkOddNumbers(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_, err := OddNumbers(1, 100000)
		if err != nil {
			b.Error(err)
		}
	}
}

// TestNthEven unit test NthEven function.
func TestNthEven(t *testing.T) {
	testCases := []struct {
		input, expected int
		err             error
	}{
		{-1, 0, errors.New("input must be a positive number. received '-1'")},
		{-2, 0, errors.New("input must be a positive number. received '-2'")},
		{1, 0, nil},
		{2, 2, nil},
		{10, 18, nil},
	}
	for _, test := range testCases {
		observed, err := NthEven(test.input)
		if err != nil {
			if err.Error() != test.err.Error() {
				t.Errorf("for input '%d', expected '%s', got '%s'",
					test.input, test.err.Error(), err.Error())
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for input '%d', expected '%v', got '%v'",
				test.input, test.expected, observed)
		}
	}
}

// BenchmarkNthEven benchmark NthEven function.
func BenchmarkNthEven(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_, err := NthEven(100000)
		if err != nil {
			b.Error(err)
		}
	}
}

// TestNthOdd unit test NthOdd function.
func TestNthOdd(t *testing.T) {
	testCases := []struct {
		input, expected int
		err             error
	}{
		{-1, 0, errors.New("input must be a positive number. received '-1'")},
		{-2, 0, errors.New("input must be a positive number. received '-2'")},
		{1, 1, nil},
		{2, 3, nil},
		{10, 19, nil},
	}
	for _, test := range testCases {
		observed, err := NthOdd(test.input)
		if err != nil {
			if err.Error() != test.err.Error() {
				t.Errorf("for input '%d', expected '%s', got '%s'",
					test.input, test.err.Error(), err.Error())
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for input '%d', expected '%v', got '%v'",
				test.input, test.expected, observed)
		}
	}
}
<commit_msg>Add benchmark test for NthOdd function<commit_after>package numbers

import (
	"errors"
	"reflect"
	"testing"
)

// TestFactorsList unit test FactorsList function.
func TestFactorsList(t *testing.T) {
	testCases := []struct {
		input    int
		expected []int
		err      error
	}{
		{2, []int{2}, nil},
		{15, []int{3, 5}, nil},
		{26, []int{2, 13}, nil},
		{37, []int{37}, nil},
		{42, []int{2, 3, 7}, nil},
		{-1, []int(nil), errors.New("no prime factors for numbers below two. received '-1'")},
	}
	for _, test := range testCases {
		observed, err := FactorsList(test.input)
		if err != nil {
			if test.err.Error() != err.Error() {
				t.Error(err)
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for input '%d', expected '%v', got '%v'",
				test.input, test.expected, observed)
		}
	}
}

// BenchmarkFactorList benchmark FactorsList function.
func BenchmarkFactorList(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_, err := FactorsList(1000)
		if err != nil {
			b.Error(err)
		}
	}
}

// TestIsPrime unit test IsPrime function.
func TestIsPrime(t *testing.T) {
	testCases := []struct {
		input    int
		expected bool
	}{
		{-5, false},
		{0, false},
		{2, true},
		{6, false},
		{13, true},
	}
	for _, test := range testCases {
		observed := IsPrime(test.input)
		if observed != test.expected {
			t.Errorf("for input '%d', expected '%t', got '%t'",
				test.input, test.expected, observed)
		}
	}
}

// BenchmarkIsPrime benchmark IsPrime function.
func BenchmarkIsPrime(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_ = IsPrime(1728459)
	}
}

// TestFibonacciGen unit test FibonacciGen function.
func TestFibonacciGen(t *testing.T) {
	testCases := []struct {
		input, expected int
	}{
		{1, 0},
		{2, 1},
		{3, 1},
		{4, 2},
		{5, 3},
		{8, 13},
		{10, 34},
		{12, 89},
	}
	for _, test := range testCases {
		var observed int
		c := FibonacciGen()
		for n := 0; n < test.input; n++ {
			observed = <-c
		}
		if observed != test.expected {
			t.Errorf("for input '%d', expected '%d', got '%d'", test.input, test.expected, observed)
		}
	}
}

// BenchmarkFibonacciGen benchmark FibonacciGen function.
func BenchmarkFibonacciGen(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		c := FibonacciGen()
		for n := 0; n < 10000; n++ {
			_ = <-c
		}
	}
}

// TestNthFibonacci unit test NthFibonacci function.
func TestNthFibonacci(t *testing.T) {
	var testCases = []struct {
		input, expected int
	}{
		{1, 1},
		{5, 5},
		{7, 13},
		{10, 55},
		{19, 4181},
	}
	for _, test := range testCases {
		observed := NthFibonacci(test.input)
		if observed != test.expected {
			t.Errorf("for input '%d', expected '%d', got '%d'",
				test.input, test.expected, observed)
		}
	}
}

// BenchmarkNthFibonacci benchmark NthFibonacci function.
func BenchmarkNthFibonacci(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = NthFibonacci(10000)
	}
}

// TestEvenNumbers unit test EvenNumbers function.
func TestEvenNumbers(t *testing.T) {
	testCases := []struct {
		inputA, inputB int
		expected       []int
		err            error
	}{
		{1, 1, []int(nil), nil},
		{1, 3, []int{2}, nil},
		{4, 8, []int{4, 6, 8}, nil},
		{-4, 8, []int{-4, -2, 0, 2, 4, 6, 8}, nil},
		{-1, -2, []int(nil), errors.New("a must be greater than b. received a '-1' and b '-2'")},
	}
	for _, test := range testCases {
		observed, err := EvenNumbers(test.inputA, test.inputB)
		if err != nil {
			if err.Error() != test.err.Error() {
				t.Error(err)
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for a '%d' and b '%d', expected '%v', got '%v'",
				test.inputA, test.inputB, test.expected, observed)
		}
	}
}

// BenchmarkEvenNumbers benchmark EvenNumbers function.
func BenchmarkEvenNumbers(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_, err := EvenNumbers(1, 100000)
		if err != nil {
			b.Error(err)
		}
	}
}

// TestOddNumbers unit test OddNumbers function.
func TestOddNumbers(t *testing.T) {
	testCases := []struct {
		inputA, inputB int
		expected       []int
		err            error
	}{
		{1, 1, []int{1}, nil},
		{1, 3, []int{1, 3}, nil},
		{4, 8, []int{5, 7}, nil},
		{-4, 8, []int{-3, -1, 1, 3, 5, 7}, nil},
		{-1, -2, []int(nil), errors.New("a must be greater than b. received a '-1' and b '-2'")},
	}
	for _, test := range testCases {
		observed, err := OddNumbers(test.inputA, test.inputB)
		if err != nil {
			if err.Error() != test.err.Error() {
				t.Error(err)
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for a '%d' and b '%d', expected '%v', got '%v'",
				test.inputA, test.inputB, test.expected, observed)
		}
	}
}

// BenchmarkOddNumbers benchmark OddNumbers function.
func BenchmarkOddNumbers(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_, err := OddNumbers(1, 100000)
		if err != nil {
			b.Error(err)
		}
	}
}

// TestNthEven unit test NthEven function.
func TestNthEven(t *testing.T) {
	testCases := []struct {
		input, expected int
		err             error
	}{
		{-1, 0, errors.New("input must be a positive number. received '-1'")},
		{-2, 0, errors.New("input must be a positive number. received '-2'")},
		{1, 0, nil},
		{2, 2, nil},
		{10, 18, nil},
	}
	for _, test := range testCases {
		observed, err := NthEven(test.input)
		if err != nil {
			if err.Error() != test.err.Error() {
				t.Errorf("for input '%d', expected '%s', got '%s'",
					test.input, test.err.Error(), err.Error())
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for input '%d', expected '%v', got '%v'",
				test.input, test.expected, observed)
		}
	}
}

// BenchmarkNthEven benchmark NthEven function.
func BenchmarkNthEven(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_, err := NthEven(100000)
		if err != nil {
			b.Error(err)
		}
	}
}

// TestNthOdd unit test NthOdd function.
func TestNthOdd(t *testing.T) {
	testCases := []struct {
		input, expected int
		err             error
	}{
		{-1, 0, errors.New("input must be a positive number. received '-1'")},
		{-2, 0, errors.New("input must be a positive number. received '-2'")},
		{1, 1, nil},
		{2, 3, nil},
		{10, 19, nil},
	}
	for _, test := range testCases {
		observed, err := NthOdd(test.input)
		if err != nil {
			if err.Error() != test.err.Error() {
				t.Errorf("for input '%d', expected '%s', got '%s'",
					test.input, test.err.Error(), err.Error())
			}
		}
		if !reflect.DeepEqual(observed, test.expected) {
			t.Errorf("for input '%d', expected '%v', got '%v'",
				test.input, test.expected, observed)
		}
	}
}

// BenchmarkNthOdd benchmark NthOdd function.
func BenchmarkNthOdd(b *testing.B) {
	for i := 0; i <= b.N; i++ {
		_, err := NthOdd(100000)
		if err != nil {
			b.Error(err)
		}
	}
}
<|endoftext|>


<commit_before>package client

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path/filepath"
)

// Config holds our client config
var Config map[string]string

// LoadConfig reads or creates our config file at ~/.sendto/config
func LoadConfig() error {

	// Create our files folder to store files to send
	err := createFolder("files")
	if err != nil {
		return err
	}

	// Create our users folder to store public keys downloaded
	err = createFolder("users")
	if err != nil {
		return err
	}

	// Load our config file (or create a new one with one entry - sender identity)
	// First check it exists
	file, err := ioutil.ReadFile(configFilePath())
	if err == nil {
		err = json.Unmarshal(file, &Config)
		if err != nil {
			return err
		}
	}

	// If no config exists create a config and save it
	if len(Config) == 0 {
		err = setupConfig()
		if err != nil {
			return err
		}

		err = SaveConfig()
		if err != nil {
			return err
		}

	}

	return nil
}

// SaveConfig saves our config out to a file at ~/.sendto/config
func SaveConfig() error {
	// Write out a json file representing our config map
	configJSON, err := json.MarshalIndent(Config, "", "\t")
	if err != nil {
		return err
	}

	// Write the config json file
	err = ioutil.WriteFile(configFilePath(), configJSON, os.ModePerm)
	if err != nil {
		return err
	}

	return nil
}

func setupConfig() error {
	Config = make(map[string]string, 0)

	// Get hold of the current user details
	u, err := user.Current()
	if err != nil {
		return err
	}
	Config["sender"] = u.Name
	Config["keyserver"] = "https://sendto.click/users/%s/key.asc"
	Config["server"] = "https://sendto.click"

	fmt.Printf("Setting default config:%v\n", Config)
	return nil
}

func configPath() string {
	usr, err := user.Current()
	if err != nil {
		log.Fatalf("Error loading config: %s\n", err)
		return ""
	}
	return filepath.Join(usr.HomeDir, ".sendto")
}

func configFilePath() string {
	return filepath.Join(configPath(), "config.json")
}

func createFolder(name string) error {
	p := filepath.Join(configPath(), name)
	return os.MkdirAll(p, os.ModeDir|os.ModePerm)
}

// fileExists returns true if this file exists
func fileExists(path string) bool {
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		return false
	}
	return true
}
<commit_msg>Adjusted server url<commit_after>package client

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path/filepath"
)

// Config holds our client config
var Config map[string]string

// LoadConfig reads or creates our config file at ~/.sendto/config
func LoadConfig() error {

	// Create our files folder to store files to send
	err := createFolder("files")
	if err != nil {
		return err
	}

	// Create our users folder to store public keys downloaded
	err = createFolder("users")
	if err != nil {
		return err
	}

	// Load our config file (or create a new one with one entry - sender identity)
	// First check it exists
	file, err := ioutil.ReadFile(configFilePath())
	if err == nil {
		err = json.Unmarshal(file, &Config)
		if err != nil {
			return err
		}
	}

	// If no config exists create a config and save it
	if len(Config) == 0 {
		err = setupConfig()
		if err != nil {
			return err
		}

		err = SaveConfig()
		if err != nil {
			return err
		}

	}

	return nil
}

// SaveConfig saves our config out to a file at ~/.sendto/config
func SaveConfig() error {
	// Write out a json file representing our config map
	configJSON, err := json.MarshalIndent(Config, "", "\t")
	if err != nil {
		return err
	}

	// Write the config json file
	err = ioutil.WriteFile(configFilePath(), configJSON, os.ModePerm)
	if err != nil {
		return err
	}

	return nil
}

func setupConfig() error {
	Config = make(map[string]string, 0)

	// Get hold of the current user details
	u, err := user.Current()
	if err != nil {
		return err
	}
	Config["sender"] = u.Name
	Config["keyserver"] = "https://sendto.click/users/%s/key"
	Config["server"] = "https://sendto.click"

	fmt.Printf("Setting default config:%v\n", Config)
	return nil
}

func configPath() string {
	usr, err := user.Current()
	if err != nil {
		log.Fatalf("Error loading config: %s\n", err)
		return ""
	}
	return filepath.Join(usr.HomeDir, ".sendto")
}

func configFilePath() string {
	return filepath.Join(configPath(), "config.json")
}

func createFolder(name string) error {
	p := filepath.Join(configPath(), name)
	return os.MkdirAll(p, os.ModeDir|os.ModePerm)
}

// fileExists returns true if this file exists
func fileExists(path string) bool {
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package facebook

import "github.com/deiwin/luncher-api/config"

var (
	appIDEnvProperty     = config.NewRequiredEnvProperty("LUNCHER_FACEBOOK_APP_ID")
	appSecretEnvProperty = config.NewRequiredEnvProperty("LUNCHER_FACEBOOK_APP_SECRET")
)

type Config struct {
	AppID     string
	AppSecret string
}

func NewConfig() Config {
	return Config{
		AppID:     appIDEnvProperty.DefaultValue(),
		AppSecret: appSecretEnvProperty.DefaultValue(),
	}
}
<commit_msg>add facebook API version conf<commit_after>package facebook

import "github.com/deiwin/luncher-api/config"

var (
	appIDEnvProperty      = config.NewRequiredEnvProperty("LUNCHER_FACEBOOK_APP_ID")
	appSecretEnvProperty  = config.NewRequiredEnvProperty("LUNCHER_FACEBOOK_APP_SECRET")
	apiVersionEnvProperty = config.NewEnvProperty("LUNCHER_FACEBOOK_API_VERSION", "v2.2")
)

type Config struct {
	AppID      string
	AppSecret  string
	ApiVersion string
}

func NewConfig() Config {
	return Config{
		AppID:      appIDEnvProperty.DefaultValue(),
		AppSecret:  appSecretEnvProperty.DefaultValue(),
		ApiVersion: apiVersionEnvProperty.DefaultValue(),
	}
}
<|endoftext|>


<commit_before>package test

import (
	"sync"
	"testing"
	"time"

	"golang.org/x/net/websocket"

	"github.com/neptulon/neptulon"
)

func TestEcho(t *testing.T) {
	s := neptulon.NewServer("127.0.0.1:3010")
	go s.Start()
	defer s.Close()
	time.Sleep(time.Millisecond)

	var wg sync.WaitGroup
	s.Middleware(func(ctx *neptulon.ReqCtx) error {
		defer wg.Done()
		t.Log("Request received:", ctx.Method)
		ctx.Res = "response-wow!"
		return ctx.Next()
	})

	wg.Add(1)

	origin := "http://127.0.0.1"
	url := "ws://127.0.0.1:3010"
	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		t.Fatal(err)
	}
	if err := websocket.JSON.Send(ws, neptulon.Request{ID: "123", Method: "test"}); err != nil {
		t.Fatal(err)
	}
	var res neptulon.Response
	if err := websocket.JSON.Receive(ws, &res); err != nil {
		t.Fatal(err)
	}
	t.Log("Got response:", res)

	wg.Wait()
}

func TestTLS(t *testing.T) {
	// todo: client cert etc.
}
<commit_msg>add new echo test<commit_after>package test

import (
	"sync"
	"testing"
	"time"

	"golang.org/x/net/websocket"

	"github.com/neptulon/jsonrpc"
	"github.com/neptulon/jsonrpc/middleware"
	"github.com/neptulon/neptulon"
)

type echoMsg struct {
	Message string `json:"message"`
}

func TestEcho(t *testing.T) {
	sh := NewServerHelper(t).Start()
	defer sh.Close()

	rout := sh.GetRouter()
	rout.Request("echo", middleware.Echo)

	ch := sh.GetClientHelper().Connect()
	defer ch.Close()

	ch.SendRequest("echo", echoMsg{Message: "Hello!"}, func(ctx *jsonrpc.ResCtx) error {
		var msg echoMsg
		if err := ctx.Result(&msg); err != nil {
			t.Fatal(err)
		}
		if msg.Message != "Hello!" {
			t.Fatalf("expected: %v got: %v", "Hello!", msg.Message)
		}
		return ctx.Next()
	})
}

func TestEcho(t *testing.T) {
	s := neptulon.NewServer("127.0.0.1:3010")
	go s.Start()
	defer s.Close()
	time.Sleep(time.Millisecond)

	var wg sync.WaitGroup
	s.Middleware(func(ctx *neptulon.ReqCtx) error {
		defer wg.Done()
		t.Log("Request received:", ctx.Method)
		ctx.Res = "response-wow!"
		return ctx.Next()
	})

	wg.Add(1)

	origin := "http://127.0.0.1"
	url := "ws://127.0.0.1:3010"
	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		t.Fatal(err)
	}
	if err := websocket.JSON.Send(ws, neptulon.Request{ID: "123", Method: "test"}); err != nil {
		t.Fatal(err)
	}
	var res neptulon.Response
	if err := websocket.JSON.Receive(ws, &res); err != nil {
		t.Fatal(err)
	}
	t.Log("Got response:", res)

	wg.Wait()
}

func TestTLS(t *testing.T) {
	// todo: client cert etc.
}
<|endoftext|>