From 44510e11ac4f9d6300bef780bc46ec24f1752eb1 Mon Sep 17 00:00:00 2001 From: Robert Rati Date: Fri, 30 Jan 2015 15:29:18 -0500 Subject: [PATCH 1/5] Renamed the pod_update file to pods #3941 --- test/e2e/{pod_update.go => pods.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/e2e/{pod_update.go => pods.go} (100%) diff --git a/test/e2e/pod_update.go b/test/e2e/pods.go similarity index 100% rename from test/e2e/pod_update.go rename to test/e2e/pods.go From e47b98db29899cb096406df4753af0ddfa0623c9 Mon Sep 17 00:00:00 2001 From: Robert Rati Date: Fri, 30 Jan 2015 15:59:13 -0500 Subject: [PATCH 2/5] Converted TestPodUpdate to native ginkgo syntax #3941 --- test/e2e/pods.go | 142 +++++++++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 66 deletions(-) diff --git a/test/e2e/pods.go b/test/e2e/pods.go index 4b5666d4dd7..c7d2b28937b 100644 --- a/test/e2e/pods.go +++ b/test/e2e/pods.go @@ -17,6 +17,7 @@ limitations under the License. package e2e import ( + "fmt" "strconv" "time" @@ -24,85 +25,94 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" - "github.com/golang/glog" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) -func TestPodUpdate(c *client.Client) bool { - podClient := c.Pods(api.NamespaceDefault) +var _ = Describe("Pods", func() { + var ( + c *client.Client + ) - name := "pod-update-" + string(util.NewUUID()) - value := strconv.Itoa(time.Now().Nanosecond()) - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: name, - Labels: map[string]string{ - "name": "foo", - "time": value, + BeforeEach(func() { + c = loadClientOrDie() + }) + + It("should be updated", func() { + podClient := c.Pods(api.NamespaceDefault) + + By("creating the pod") + name := "pod-update-" + string(util.NewUUID()) + value := strconv.Itoa(time.Now().Nanosecond()) + pod := &api.Pod{ + ObjectMeta: api.ObjectMeta{ + Name: name, + Labels: map[string]string{ + "name": "foo", + "time": value, + }, }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "nginx", - Image: "dockerfile/nginx", - Ports: []api.Port{{ContainerPort: 80, HostPort: 8080}}, - LivenessProbe: &api.Probe{ - Handler: api.Handler{ - HTTPGet: &api.HTTPGetAction{ - Path: "/index.html", - Port: util.NewIntOrStringFromInt(8080), + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: "nginx", + Image: "dockerfile/nginx", + Ports: []api.Port{{ContainerPort: 80, HostPort: 8080}}, + LivenessProbe: &api.Probe{ + Handler: api.Handler{ + HTTPGet: &api.HTTPGetAction{ + Path: "/index.html", + Port: util.NewIntOrStringFromInt(8080), + }, }, + InitialDelaySeconds: 30, }, - InitialDelaySeconds: 30, }, }, }, - }, - } - _, err := podClient.Create(pod) - if err != nil { - glog.Errorf("Failed to create pod: %v", err) - return false - } - defer podClient.Delete(pod.Name) - waitForPodRunning(c, pod.Name) - pods, err := podClient.List(labels.SelectorFromSet(labels.Set(map[string]string{"time": value}))) - if len(pods.Items) != 1 { - glog.Errorf("Failed to find the correct pod") - return false - } + } - podOut, err := podClient.Get(pod.Name) - if err != nil { - glog.Errorf("Failed to get pod: %v", err) - return false - } - value = "time" + value - pod.Labels["time"] = value - pod.ResourceVersion = podOut.ResourceVersion - pod.UID = podOut.UID - pod, err = podClient.Update(pod) - if err != nil { - glog.Errorf("Failed to update pod: %v", err) - return false - } - waitForPodRunning(c, pod.Name) - pods, err = podClient.List(labels.SelectorFromSet(labels.Set(map[string]string{"time": value}))) - if len(pods.Items) != 1 { - glog.Errorf("Failed to find the correct pod after update.") - return false - } - glog.Infof("pod update OK") - return true -} + By("submitting the pod to kubernetes") + _, err := podClient.Create(pod) + if err != nil { + Fail(fmt.Sprintf("Failed to create pod: %v", err)) + } + defer func() { + By("deleting the pod") + defer GinkgoRecover() + podClient.Delete(pod.Name) + }() -var _ = Describe("TestPodUpdate", func() { - It("should pass", func() { - // TODO: Instead of OrDie, client should Fail the test if there's a problem. - // In general tests should Fail() instead of glog.Fatalf(). - Expect(TestPodUpdate(loadClientOrDie())).To(BeTrue()) + By("waiting for the pod to start running") + waitForPodRunning(c, pod.Name) + + By("verifying the pod is in kubernetes") + pods, err := podClient.List(labels.SelectorFromSet(labels.Set(map[string]string{"time": value}))) + Expect(len(pods.Items)).To(Equal(1)) + + By("retrieving the pod") + podOut, err := podClient.Get(pod.Name) + if err != nil { + Fail(fmt.Sprintf("Failed to get pod: %v", err)) + } + + By("updating the pod") + value = "time" + value + pod.Labels["time"] = value + pod.ResourceVersion = podOut.ResourceVersion + pod.UID = podOut.UID + pod, err = podClient.Update(pod) + if err != nil { + Fail(fmt.Sprintf("Failed to update pod: %v", err)) + } + + By("waiting for the updated pod to start running") + waitForPodRunning(c, pod.Name) + + By("verifying the updated pod is in kubernetes") + pods, err = podClient.List(labels.SelectorFromSet(labels.Set(map[string]string{"time": value}))) + Expect(len(pods.Items)).To(Equal(1)) + fmt.Println("pod update OK") }) }) From eb5d340851354d9de8f1df97f673ab36f6d26519 Mon Sep 17 00:00:00 2001 From: Robert Rati Date: Fri, 30 Jan 2015 16:00:03 -0500 Subject: [PATCH 3/5] Added a submit/remove test to pods #3941 --- test/e2e/pods.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/e2e/pods.go b/test/e2e/pods.go index c7d2b28937b..cc84d22df1e 100644 --- a/test/e2e/pods.go +++ b/test/e2e/pods.go @@ -39,6 +39,42 @@ var _ = Describe("Pods", func() { c = loadClientOrDie() }) + It("should be submitted and removed", func() { + podClient := c.Pods(api.NamespaceDefault) + + By("loading the pod json") + pod := loadPodOrDie(assetPath("api", "examples", "pod.json")) + value := strconv.Itoa(time.Now().Nanosecond()) + pod.Name = pod.Name + "-" + randomSuffix() + pod.Labels["time"] = value + pod.Spec.Containers[0].Ports[0].HostPort = 0 + + By("submitting the pod to kubernetes") + _, err := podClient.Create(pod) + if err != nil { + Fail(fmt.Sprintf("Failed to create pod: %v", err)) + } + defer func() { + // We call defer here in case there is a problem with + // the test so we can ensure that we clean up after + // ourselves + defer GinkgoRecover() + podClient.Delete(pod.Name) + }() + + By("verifying the pod is in kubernetes") + pods, err := podClient.List(labels.SelectorFromSet(labels.Set(map[string]string{"time": value}))) + if err != nil { + Fail(fmt.Sprintf("Failed to query for pods: %v", err)) + } + Expect(len(pods.Items)).To(Equal(1)) + + By("deleting the pod") + podClient.Delete(pod.Name) + pods, err = podClient.List(labels.SelectorFromSet(labels.Set(map[string]string{"time": value}))) + Expect(len(pods.Items)).To(Equal(0)) + }) + It("should be updated", func() { podClient := c.Pods(api.NamespaceDefault) From da2594710aa5de3468c937f664b4f0153826c710 Mon Sep 17 00:00:00 2001 From: Robert Rati Date: Mon, 2 Feb 2015 09:02:37 -0500 Subject: [PATCH 4/5] Converted TestPodHasServiceEnvVars to native ginkgo syntax #3941 --- test/e2e/pod_has_service_env_vars.go | 280 +++++++++++++-------------- 1 file changed, 139 insertions(+), 141 deletions(-) diff --git a/test/e2e/pod_has_service_env_vars.go b/test/e2e/pod_has_service_env_vars.go index e4584e4a546..1e5213b80b3 100644 --- a/test/e2e/pod_has_service_env_vars.go +++ b/test/e2e/pod_has_service_env_vars.go @@ -17,156 +17,154 @@ limitations under the License. package e2e import ( - "strings" + "fmt" "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" - "github.com/golang/glog" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) -// TestPodHasServiceEnvVars checks that kubelets and scheduler send events about pods scheduling and running. -func TestPodHasServiceEnvVars(c *client.Client) bool { - // Make a pod that will be a service. - // This pod serves its hostname via HTTP. - serverPod := parsePodOrDie(`{ - "kind": "Pod", - "apiVersion": "v1beta1", - "id": "srv", - "desiredState": { - "manifest": { - "version": "v1beta1", - "id": "srv", - "containers": [{ - "name": "srv", - "image": "kubernetes/serve_hostname", - "ports": [{ - "containerPort": 9376, - "hostPort": 8080 - }] - }] - } - }, - "labels": { - "name": "srv" - } - }`) - _, err := c.Pods(api.NamespaceDefault).Create(serverPod) - if err != nil { - glog.Errorf("Failed to create serverPod: %v", err) - return false - } - defer c.Pods(api.NamespaceDefault).Delete(serverPod.Name) - waitForPodRunning(c, serverPod.Name) - - // This service exposes pod p's port 8080 as a service on port 8765 - svc := parseServiceOrDie(`{ - "id": "fooservice", - "kind": "Service", - "apiVersion": "v1beta1", - "port": 8765, - "containerPort": 8080, - "selector": { - "name": "p" - } - }`) - if err != nil { - glog.Errorf("Failed to delete service: %v", err) - return false - } - time.Sleep(2) - _, err = c.Services(api.NamespaceDefault).Create(svc) - if err != nil { - glog.Errorf("Failed to create service: %v", err) - return false - } - defer c.Services(api.NamespaceDefault).Delete(svc.Name) - - // TODO: we don't have a way to wait for a service to be "running". - // If this proves flaky, then we will need to retry the clientPod or insert a sleep. - - // Make a client pod that verifies that it has the service environment variables. - clientPod := parsePodOrDie(`{ - "apiVersion": "v1beta1", - "kind": "Pod", - "id": "env3", - "desiredState": { - "manifest": { - "version": "v1beta1", - "id": "env3", - "restartPolicy": { "never": {} }, - "containers": [{ - "name": "env3cont", - "image": "busybox", - "command": ["sh", "-c", "env"] - }] - } - }, - "labels": { "name": "env3" } - }`) - _, err = c.Pods(api.NamespaceDefault).Create(clientPod) - if err != nil { - glog.Errorf("Failed to create pod: %v", err) - return false - } - defer c.Pods(api.NamespaceDefault).Delete(clientPod.Name) - - // Wait for client pod to complete. - success := waitForPodSuccess(c, clientPod.Name, clientPod.Spec.Containers[0].Name) - if !success { - glog.Errorf("Failed to run client pod to detect service env vars.") - } - - // Grab its logs. Get host first. - clientPodStatus, err := c.Pods(api.NamespaceDefault).Get(clientPod.Name) - if err != nil { - glog.Errorf("Failed to get clientPod to know host: %v", err) - return false - } - glog.Infof("Trying to get logs from host %s pod %s container %s: %v", - clientPodStatus.Status.Host, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name, err) - logs, err := c.Get(). - Prefix("proxy"). - Resource("minions"). - Name(clientPodStatus.Status.Host). - Suffix("containerLogs", api.NamespaceDefault, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name). - Do(). - Raw() - if err != nil { - glog.Errorf("Failed to get logs from host %s pod %s container %s: %v", - clientPodStatus.Status.Host, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name, err) - return false - } - glog.Info("clientPod logs:", string(logs)) - - toFind := []string{ - "FOOSERVICE_SERVICE_HOST=", - "FOOSERVICE_SERVICE_PORT=", - "FOOSERVICE_PORT=", - "FOOSERVICE_PORT_8765_TCP_PORT=", - "FOOSERVICE_PORT_8765_TCP_PROTO=", - "FOOSERVICE_PORT_8765_TCP=", - "FOOSERVICE_PORT_8765_TCP_ADDR=", - } - - for _, m := range toFind { - if !strings.Contains(string(logs), m) { - glog.Errorf("Unable to find env var %q in client env vars.", m) - success = false - } - } - - // We could try a wget the service from the client pod. But services.sh e2e test covers that pretty well. - return success -} - var _ = Describe("TestPodHasServiceEnvVars", func() { - It("should pass", func() { - // TODO: Instead of OrDie, client should Fail the test if there's a problem. - // In general tests should Fail() instead of glog.Fatalf(). - Expect(TestPodHasServiceEnvVars(loadClientOrDie())).To(BeTrue()) + var ( + c *client.Client + ) + + BeforeEach(func() { + c = loadClientOrDie() + }) + + It("should contain environment variables for services", func() { + // Make a pod that will be a service. + // This pod serves its hostname via HTTP. + serverPod := parsePodOrDie(`{ + "kind": "Pod", + "apiVersion": "v1beta1", + "id": "srv", + "desiredState": { + "manifest": { + "version": "v1beta1", + "id": "srv", + "containers": [{ + "name": "srv", + "image": "kubernetes/serve_hostname", + "ports": [{ + "containerPort": 9376, + "hostPort": 8080 + }] + }] + } + }, + "labels": { + "name": "srv" + } + }`) + _, err := c.Pods(api.NamespaceDefault).Create(serverPod) + if err != nil { + Fail(fmt.Sprintf("Failed to create serverPod: %v", err)) + } + defer func() { + defer GinkgoRecover() + c.Pods(api.NamespaceDefault).Delete(serverPod.Name) + }() + waitForPodRunning(c, serverPod.Name) + + // This service exposes pod p's port 8080 as a service on port 8765 + svc := parseServiceOrDie(`{ + "id": "fooservice", + "kind": "Service", + "apiVersion": "v1beta1", + "port": 8765, + "containerPort": 8080, + "selector": { + "name": "p" + } + }`) + if err != nil { + Fail(fmt.Sprintf("Failed to delete service: %v", err)) + } + time.Sleep(2) + _, err = c.Services(api.NamespaceDefault).Create(svc) + if err != nil { + Fail(fmt.Sprintf("Failed to create service: %v", err)) + } + defer func() { + defer GinkgoRecover() + c.Services(api.NamespaceDefault).Delete(svc.Name) + }() + + // TODO: we don't have a way to wait for a service to be "running". // If this proves flaky, then we will need to retry the clientPod or insert a sleep. + + // Make a client pod that verifies that it has the service environment variables. + clientPod := parsePodOrDie(`{ + "apiVersion": "v1beta1", + "kind": "Pod", + "id": "env3", + "desiredState": { + "manifest": { + "version": "v1beta1", + "id": "env3", + "restartPolicy": { "never": {} }, + "containers": [{ + "name": "env3cont", + "image": "busybox", + "command": ["sh", "-c", "env"] + }] + } + }, + "labels": { "name": "env3" } + }`) + _, err = c.Pods(api.NamespaceDefault).Create(clientPod) + if err != nil { + Fail(fmt.Sprintf("Failed to create pod: %v", err)) + } + defer func() { + defer GinkgoRecover() + c.Pods(api.NamespaceDefault).Delete(clientPod.Name) + }() + + // Wait for client pod to complete. + success := waitForPodSuccess(c, clientPod.Name, clientPod.Spec.Containers[0].Name) + if !success { + Fail(fmt.Sprintf("Failed to run client pod to detect service env vars.")) + } + + // Grab its logs. Get host first. + clientPodStatus, err := c.Pods(api.NamespaceDefault).Get(clientPod.Name) + if err != nil { + Fail(fmt.Sprintf("Failed to get clientPod to know host: %v", err)) + } + By(fmt.Sprintf("Trying to get logs from host %s pod %s container %s: %v", + clientPodStatus.Status.Host, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name, err)) + logs, err := c.Get(). + Prefix("proxy"). + Resource("minions"). + Name(clientPodStatus.Status.Host). + Suffix("containerLogs", api.NamespaceDefault, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name). + Do(). + Raw() + if err != nil { + Fail(fmt.Sprintf("Failed to get logs from host %s pod %s container %s: %v", + clientPodStatus.Status.Host, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name, err)) + } + fmt.Sprintf("clientPod logs:%v\n", string(logs)) + + toFind := []string{ + "FOOSERVICE_SERVICE_HOST=", + "FOOSERVICE_SERVICE_PORT=", + "FOOSERVICE_PORT=", + "FOOSERVICE_PORT_8765_TCP_PORT=", + "FOOSERVICE_PORT_8765_TCP_PROTO=", + "FOOSERVICE_PORT_8765_TCP=", + "FOOSERVICE_PORT_8765_TCP_ADDR=", + } + + for _, m := range toFind { + Expect(string(logs)).To(ContainSubstring(m), "%q in client env vars", m) + } + + // We could try a wget the service from the client pod. But services.sh e2e test covers that pretty well. }) }) From 3a562b18a7ed39c151513962760baf27d388baf7 Mon Sep 17 00:00:00 2001 From: Robert Rati Date: Mon, 2 Feb 2015 09:11:06 -0500 Subject: [PATCH 5/5] Moved TestPodHasServiceEnvVars into the pods test suite and deleted the original file #3941 --- test/e2e/pod_has_service_env_vars.go | 170 --------------------------- test/e2e/pods.go | 132 +++++++++++++++++++++ 2 files changed, 132 insertions(+), 170 deletions(-) delete mode 100644 test/e2e/pod_has_service_env_vars.go diff --git a/test/e2e/pod_has_service_env_vars.go b/test/e2e/pod_has_service_env_vars.go deleted file mode 100644 index 1e5213b80b3..00000000000 --- a/test/e2e/pod_has_service_env_vars.go +++ /dev/null @@ -1,170 +0,0 @@ -/* -Copyright 2014 Google Inc. All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package e2e - -import ( - "fmt" - "time" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/client" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("TestPodHasServiceEnvVars", func() { - var ( - c *client.Client - ) - - BeforeEach(func() { - c = loadClientOrDie() - }) - - It("should contain environment variables for services", func() { - // Make a pod that will be a service. - // This pod serves its hostname via HTTP. - serverPod := parsePodOrDie(`{ - "kind": "Pod", - "apiVersion": "v1beta1", - "id": "srv", - "desiredState": { - "manifest": { - "version": "v1beta1", - "id": "srv", - "containers": [{ - "name": "srv", - "image": "kubernetes/serve_hostname", - "ports": [{ - "containerPort": 9376, - "hostPort": 8080 - }] - }] - } - }, - "labels": { - "name": "srv" - } - }`) - _, err := c.Pods(api.NamespaceDefault).Create(serverPod) - if err != nil { - Fail(fmt.Sprintf("Failed to create serverPod: %v", err)) - } - defer func() { - defer GinkgoRecover() - c.Pods(api.NamespaceDefault).Delete(serverPod.Name) - }() - waitForPodRunning(c, serverPod.Name) - - // This service exposes pod p's port 8080 as a service on port 8765 - svc := parseServiceOrDie(`{ - "id": "fooservice", - "kind": "Service", - "apiVersion": "v1beta1", - "port": 8765, - "containerPort": 8080, - "selector": { - "name": "p" - } - }`) - if err != nil { - Fail(fmt.Sprintf("Failed to delete service: %v", err)) - } - time.Sleep(2) - _, err = c.Services(api.NamespaceDefault).Create(svc) - if err != nil { - Fail(fmt.Sprintf("Failed to create service: %v", err)) - } - defer func() { - defer GinkgoRecover() - c.Services(api.NamespaceDefault).Delete(svc.Name) - }() - - // TODO: we don't have a way to wait for a service to be "running". // If this proves flaky, then we will need to retry the clientPod or insert a sleep. - - // Make a client pod that verifies that it has the service environment variables. - clientPod := parsePodOrDie(`{ - "apiVersion": "v1beta1", - "kind": "Pod", - "id": "env3", - "desiredState": { - "manifest": { - "version": "v1beta1", - "id": "env3", - "restartPolicy": { "never": {} }, - "containers": [{ - "name": "env3cont", - "image": "busybox", - "command": ["sh", "-c", "env"] - }] - } - }, - "labels": { "name": "env3" } - }`) - _, err = c.Pods(api.NamespaceDefault).Create(clientPod) - if err != nil { - Fail(fmt.Sprintf("Failed to create pod: %v", err)) - } - defer func() { - defer GinkgoRecover() - c.Pods(api.NamespaceDefault).Delete(clientPod.Name) - }() - - // Wait for client pod to complete. - success := waitForPodSuccess(c, clientPod.Name, clientPod.Spec.Containers[0].Name) - if !success { - Fail(fmt.Sprintf("Failed to run client pod to detect service env vars.")) - } - - // Grab its logs. Get host first. - clientPodStatus, err := c.Pods(api.NamespaceDefault).Get(clientPod.Name) - if err != nil { - Fail(fmt.Sprintf("Failed to get clientPod to know host: %v", err)) - } - By(fmt.Sprintf("Trying to get logs from host %s pod %s container %s: %v", - clientPodStatus.Status.Host, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name, err)) - logs, err := c.Get(). - Prefix("proxy"). - Resource("minions"). - Name(clientPodStatus.Status.Host). - Suffix("containerLogs", api.NamespaceDefault, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name). - Do(). - Raw() - if err != nil { - Fail(fmt.Sprintf("Failed to get logs from host %s pod %s container %s: %v", - clientPodStatus.Status.Host, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name, err)) - } - fmt.Sprintf("clientPod logs:%v\n", string(logs)) - - toFind := []string{ - "FOOSERVICE_SERVICE_HOST=", - "FOOSERVICE_SERVICE_PORT=", - "FOOSERVICE_PORT=", - "FOOSERVICE_PORT_8765_TCP_PORT=", - "FOOSERVICE_PORT_8765_TCP_PROTO=", - "FOOSERVICE_PORT_8765_TCP=", - "FOOSERVICE_PORT_8765_TCP_ADDR=", - } - - for _, m := range toFind { - Expect(string(logs)).To(ContainSubstring(m), "%q in client env vars", m) - } - - // We could try a wget the service from the client pod. But services.sh e2e test covers that pretty well. - }) -}) diff --git a/test/e2e/pods.go b/test/e2e/pods.go index cc84d22df1e..64f760acc55 100644 --- a/test/e2e/pods.go +++ b/test/e2e/pods.go @@ -151,4 +151,136 @@ var _ = Describe("Pods", func() { Expect(len(pods.Items)).To(Equal(1)) fmt.Println("pod update OK") }) + + It("should contain environment variables for services", func() { + // Make a pod that will be a service. + // This pod serves its hostname via HTTP. + serverPod := parsePodOrDie(`{ + "kind": "Pod", + "apiVersion": "v1beta1", + "id": "srv", + "desiredState": { + "manifest": { + "version": "v1beta1", + "id": "srv", + "containers": [{ + "name": "srv", + "image": "kubernetes/serve_hostname", + "ports": [{ + "containerPort": 9376, + "hostPort": 8080 + }] + }] + } + }, + "labels": { + "name": "srv" + } + }`) + _, err := c.Pods(api.NamespaceDefault).Create(serverPod) + if err != nil { + Fail(fmt.Sprintf("Failed to create serverPod: %v", err)) + } + defer func() { + defer GinkgoRecover() + c.Pods(api.NamespaceDefault).Delete(serverPod.Name) + }() + waitForPodRunning(c, serverPod.Name) + + // This service exposes pod p's port 8080 as a service on port 8765 + svc := parseServiceOrDie(`{ + "id": "fooservice", + "kind": "Service", + "apiVersion": "v1beta1", + "port": 8765, + "containerPort": 8080, + "selector": { + "name": "p" + } + }`) + if err != nil { + Fail(fmt.Sprintf("Failed to delete service: %v", err)) + } + time.Sleep(2) + _, err = c.Services(api.NamespaceDefault).Create(svc) + if err != nil { + Fail(fmt.Sprintf("Failed to create service: %v", err)) + } + defer func() { + defer GinkgoRecover() + c.Services(api.NamespaceDefault).Delete(svc.Name) + }() + + // TODO: we don't have a way to wait for a service to be "running". // If this proves flaky, then we will need to retry the clientPod or insert a sleep. + + // Make a client pod that verifies that it has the service environment variables. + clientPod := parsePodOrDie(`{ + "apiVersion": "v1beta1", + "kind": "Pod", + "id": "env3", + "desiredState": { + "manifest": { + "version": "v1beta1", + "id": "env3", + "restartPolicy": { "never": {} }, + "containers": [{ + "name": "env3cont", + "image": "busybox", + "command": ["sh", "-c", "env"] + }] + } + }, + "labels": { "name": "env3" } + }`) + _, err = c.Pods(api.NamespaceDefault).Create(clientPod) + if err != nil { + Fail(fmt.Sprintf("Failed to create pod: %v", err)) + } + defer func() { + defer GinkgoRecover() + c.Pods(api.NamespaceDefault).Delete(clientPod.Name) + }() + + // Wait for client pod to complete. + success := waitForPodSuccess(c, clientPod.Name, clientPod.Spec.Containers[0].Name) + if !success { + Fail(fmt.Sprintf("Failed to run client pod to detect service env vars.")) + } + + // Grab its logs. Get host first. + clientPodStatus, err := c.Pods(api.NamespaceDefault).Get(clientPod.Name) + if err != nil { + Fail(fmt.Sprintf("Failed to get clientPod to know host: %v", err)) + } + By(fmt.Sprintf("Trying to get logs from host %s pod %s container %s: %v", + clientPodStatus.Status.Host, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name, err)) + logs, err := c.Get(). + Prefix("proxy"). + Resource("minions"). + Name(clientPodStatus.Status.Host). + Suffix("containerLogs", api.NamespaceDefault, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name). + Do(). + Raw() + if err != nil { + Fail(fmt.Sprintf("Failed to get logs from host %s pod %s container %s: %v", + clientPodStatus.Status.Host, clientPodStatus.Name, clientPodStatus.Spec.Containers[0].Name, err)) + } + fmt.Sprintf("clientPod logs:%v\n", string(logs)) + + toFind := []string{ + "FOOSERVICE_SERVICE_HOST=", + "FOOSERVICE_SERVICE_PORT=", + "FOOSERVICE_PORT=", + "FOOSERVICE_PORT_8765_TCP_PORT=", + "FOOSERVICE_PORT_8765_TCP_PROTO=", + "FOOSERVICE_PORT_8765_TCP=", + "FOOSERVICE_PORT_8765_TCP_ADDR=", + } + + for _, m := range toFind { + Expect(string(logs)).To(ContainSubstring(m), "%q in client env vars", m) + } + + // We could try a wget the service from the client pod. But services.sh e2e test covers that pretty well. + }) })