2015-02-20 17:35:42 +00:00
|
|
|
/*
|
2015-05-01 16:19:44 +00:00
|
|
|
Copyright 2015 The Kubernetes Authors All rights reserved.
|
2015-02-20 17:35:42 +00:00
|
|
|
|
|
|
|
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 (
|
|
|
|
"encoding/json"
|
2015-03-26 20:34:18 +00:00
|
|
|
"errors"
|
2015-03-26 19:22:04 +00:00
|
|
|
"fmt"
|
2015-06-30 16:43:37 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2015-02-20 17:35:42 +00:00
|
|
|
"path/filepath"
|
2015-06-30 16:43:37 +00:00
|
|
|
"regexp"
|
2015-02-20 17:35:42 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2015-04-02 20:15:39 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
2015-03-05 04:35:51 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
|
|
|
|
2015-02-20 17:35:42 +00:00
|
|
|
. "github.com/onsi/ginkgo"
|
2015-04-30 02:53:09 +00:00
|
|
|
. "github.com/onsi/gomega"
|
2015-02-20 17:35:42 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2015-03-31 17:25:20 +00:00
|
|
|
nautilusImage = "gcr.io/google_containers/update-demo:nautilus"
|
|
|
|
kittenImage = "gcr.io/google_containers/update-demo:kitten"
|
2015-03-13 16:26:41 +00:00
|
|
|
updateDemoSelector = "name=update-demo"
|
|
|
|
updateDemoContainer = "update-demo"
|
|
|
|
frontendSelector = "name=frontend"
|
|
|
|
redisMasterSelector = "name=redis-master"
|
|
|
|
redisSlaveSelector = "name=redis-slave"
|
|
|
|
kubectlProxyPort = 8011
|
2015-03-18 14:16:26 +00:00
|
|
|
guestbookStartupTimeout = 10 * time.Minute
|
2015-03-24 12:59:45 +00:00
|
|
|
guestbookResponseTimeout = 3 * time.Minute
|
2015-06-30 16:43:37 +00:00
|
|
|
simplePodSelector = "name=nginx"
|
|
|
|
simplePodName = "nginx"
|
|
|
|
nginxDefaultOutput = "Welcome to nginx!"
|
|
|
|
simplePodPort = 80
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
portForwardRegexp = regexp.MustCompile("Forwarding from 127.0.0.1:([0-9]+) -> 80")
|
2015-02-20 17:35:42 +00:00
|
|
|
)
|
|
|
|
|
2015-06-03 03:23:44 +00:00
|
|
|
var _ = Describe("Kubectl client", func() {
|
2015-05-19 16:13:08 +00:00
|
|
|
defer GinkgoRecover()
|
2015-03-05 04:35:51 +00:00
|
|
|
var c *client.Client
|
2015-04-30 02:53:09 +00:00
|
|
|
var ns string
|
|
|
|
var testingNs *api.Namespace
|
2015-03-02 18:15:34 +00:00
|
|
|
BeforeEach(func() {
|
2015-03-05 04:35:51 +00:00
|
|
|
var err error
|
|
|
|
c, err = loadClient()
|
|
|
|
expectNoError(err)
|
2015-06-03 03:25:28 +00:00
|
|
|
testingNs, err = createTestingNS("kubectl", c)
|
2015-04-30 02:53:09 +00:00
|
|
|
ns = testingNs.Name
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
|
|
|
|
AfterEach(func() {
|
|
|
|
By(fmt.Sprintf("Destroying namespace for this suite %v", ns))
|
|
|
|
if err := c.Namespaces().Delete(ns); err != nil {
|
|
|
|
Failf("Couldn't delete ns %s", err)
|
|
|
|
}
|
2015-03-02 18:15:34 +00:00
|
|
|
})
|
2015-02-20 17:35:42 +00:00
|
|
|
|
2015-06-03 03:23:44 +00:00
|
|
|
Describe("Update Demo", func() {
|
2015-05-19 16:13:08 +00:00
|
|
|
var updateDemoRoot, nautilusPath, kittenPath string
|
|
|
|
BeforeEach(func() {
|
2015-07-14 22:57:41 +00:00
|
|
|
updateDemoRoot = filepath.Join(testContext.RepoRoot, "docs/user-guide/update-demo")
|
2015-05-19 16:13:08 +00:00
|
|
|
nautilusPath = filepath.Join(updateDemoRoot, "nautilus-rc.yaml")
|
|
|
|
kittenPath = filepath.Join(updateDemoRoot, "kitten-rc.yaml")
|
|
|
|
})
|
2015-03-13 16:26:41 +00:00
|
|
|
|
|
|
|
It("should create and stop a replication controller", func() {
|
2015-05-15 09:39:30 +00:00
|
|
|
defer cleanup(nautilusPath, ns, updateDemoSelector)
|
2015-03-13 16:26:41 +00:00
|
|
|
|
|
|
|
By("creating a replication controller")
|
2015-04-30 02:53:09 +00:00
|
|
|
runKubectl("create", "-f", nautilusPath, fmt.Sprintf("--namespace=%v", ns))
|
|
|
|
validateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns)
|
2015-03-13 16:26:41 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
It("should scale a replication controller", func() {
|
2015-05-15 09:39:30 +00:00
|
|
|
defer cleanup(nautilusPath, ns, updateDemoSelector)
|
2015-03-13 16:26:41 +00:00
|
|
|
|
|
|
|
By("creating a replication controller")
|
2015-04-30 02:53:09 +00:00
|
|
|
runKubectl("create", "-f", nautilusPath, fmt.Sprintf("--namespace=%v", ns))
|
|
|
|
validateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns)
|
2015-03-13 16:26:41 +00:00
|
|
|
By("scaling down the replication controller")
|
2015-05-21 21:10:25 +00:00
|
|
|
runKubectl("scale", "rc", "update-demo-nautilus", "--replicas=1", fmt.Sprintf("--namespace=%v", ns))
|
2015-04-30 02:53:09 +00:00
|
|
|
validateController(c, nautilusImage, 1, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns)
|
2015-03-13 16:26:41 +00:00
|
|
|
By("scaling up the replication controller")
|
2015-05-21 21:10:25 +00:00
|
|
|
runKubectl("scale", "rc", "update-demo-nautilus", "--replicas=2", fmt.Sprintf("--namespace=%v", ns))
|
2015-04-30 02:53:09 +00:00
|
|
|
validateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns)
|
2015-03-13 16:26:41 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
It("should do a rolling update of a replication controller", func() {
|
|
|
|
By("creating the initial replication controller")
|
2015-04-30 02:53:09 +00:00
|
|
|
runKubectl("create", "-f", nautilusPath, fmt.Sprintf("--namespace=%v", ns))
|
|
|
|
validateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg", ns), ns)
|
2015-03-27 23:24:59 +00:00
|
|
|
By("rolling-update to new replication controller")
|
2015-04-30 02:53:09 +00:00
|
|
|
runKubectl("rolling-update", "update-demo-nautilus", "--update-period=1s", "-f", kittenPath, fmt.Sprintf("--namespace=%v", ns))
|
2015-06-23 03:58:48 +00:00
|
|
|
validateController(c, kittenImage, 2, "update-demo", updateDemoSelector, getUDData("kitten.jpg", ns), ns)
|
2015-05-15 03:10:32 +00:00
|
|
|
// Everything will hopefully be cleaned up when the namespace is deleted.
|
2015-03-13 16:26:41 +00:00
|
|
|
})
|
2015-02-20 17:35:42 +00:00
|
|
|
})
|
|
|
|
|
2015-06-03 03:23:44 +00:00
|
|
|
Describe("Guestbook application", func() {
|
2015-05-19 16:13:08 +00:00
|
|
|
var guestbookPath string
|
2015-06-22 21:14:54 +00:00
|
|
|
|
2015-05-19 16:13:08 +00:00
|
|
|
BeforeEach(func() {
|
|
|
|
guestbookPath = filepath.Join(testContext.RepoRoot, "examples/guestbook")
|
2015-06-22 21:14:54 +00:00
|
|
|
|
|
|
|
// requires ExternalLoadBalancer support
|
|
|
|
SkipUnlessProviderIs("gce", "gke", "aws")
|
2015-05-19 16:13:08 +00:00
|
|
|
})
|
2015-03-13 16:26:41 +00:00
|
|
|
|
|
|
|
It("should create and stop a working application", func() {
|
2015-05-15 09:39:30 +00:00
|
|
|
defer cleanup(guestbookPath, ns, frontendSelector, redisMasterSelector, redisSlaveSelector)
|
2015-02-20 17:35:42 +00:00
|
|
|
|
2015-03-13 16:26:41 +00:00
|
|
|
By("creating all guestbook components")
|
2015-04-30 02:53:09 +00:00
|
|
|
runKubectl("create", "-f", guestbookPath, fmt.Sprintf("--namespace=%v", ns))
|
2015-02-20 17:35:42 +00:00
|
|
|
|
2015-03-13 16:26:41 +00:00
|
|
|
By("validating guestbook app")
|
2015-04-30 02:53:09 +00:00
|
|
|
validateGuestbookApp(c, ns)
|
2015-03-13 16:26:41 +00:00
|
|
|
})
|
2015-02-20 17:35:42 +00:00
|
|
|
})
|
|
|
|
|
2015-06-30 16:43:37 +00:00
|
|
|
Describe("Simple pod", func() {
|
|
|
|
var podPath string
|
|
|
|
|
|
|
|
BeforeEach(func() {
|
2015-07-14 22:57:41 +00:00
|
|
|
podPath = filepath.Join(testContext.RepoRoot, "docs/user-guide/pod.yaml")
|
2015-06-30 16:43:37 +00:00
|
|
|
By("creating the pod")
|
|
|
|
runKubectl("create", "-f", podPath, fmt.Sprintf("--namespace=%v", ns))
|
|
|
|
checkPodsRunningReady(c, ns, []string{simplePodName}, podStartTimeout)
|
|
|
|
|
|
|
|
})
|
|
|
|
AfterEach(func() {
|
|
|
|
cleanup(podPath, ns, simplePodSelector)
|
|
|
|
})
|
|
|
|
|
|
|
|
It("should support exec", func() {
|
|
|
|
By("executing a command in the container")
|
|
|
|
execOutput := runKubectl("exec", fmt.Sprintf("--namespace=%v", ns), simplePodName, "echo", "running", "in", "container")
|
|
|
|
expectedExecOutput := "running in container"
|
|
|
|
if execOutput != expectedExecOutput {
|
|
|
|
Failf("Unexpected kubectl exec output. Wanted '%s', got '%s'", execOutput, expectedExecOutput)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
It("should support port-forward", func() {
|
|
|
|
By("forwarding the container port to a local port")
|
|
|
|
cmd := kubectlCmd("port-forward", fmt.Sprintf("--namespace=%v", ns), "-p", simplePodName, fmt.Sprintf(":%d", simplePodPort))
|
|
|
|
defer func() {
|
|
|
|
if err := cmd.Process.Kill(); err != nil {
|
|
|
|
Logf("ERROR failed to kill kubectl port-forward command! The process may leak")
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
// This is somewhat ugly but is the only way to retrieve the port that was picked
|
|
|
|
// by the port-forward command. We don't want to hard code the port as we have no
|
|
|
|
// way of guaranteeing we can pick one that isn't in use, particularly on Jenkins.
|
|
|
|
Logf("starting port-forward command and streaming output")
|
|
|
|
stdout, stderr, err := startCmdAndStreamOutput(cmd)
|
|
|
|
if err != nil {
|
|
|
|
Failf("Failed to start port-forward command: %v", err)
|
|
|
|
}
|
|
|
|
defer stdout.Close()
|
|
|
|
defer stderr.Close()
|
|
|
|
|
|
|
|
buf := make([]byte, 128)
|
|
|
|
var n int
|
|
|
|
Logf("reading from `kubectl port-forward` command's stderr")
|
|
|
|
if n, err = stderr.Read(buf); err != nil {
|
|
|
|
Failf("Failed to read from kubectl port-forward stderr: %v", err)
|
|
|
|
}
|
|
|
|
portForwardOutput := string(buf[:n])
|
|
|
|
match := portForwardRegexp.FindStringSubmatch(portForwardOutput)
|
|
|
|
if len(match) != 2 {
|
|
|
|
Failf("Failed to parse kubectl port-forward output: %s", portForwardOutput)
|
|
|
|
}
|
|
|
|
By("curling local port output")
|
|
|
|
localAddr := fmt.Sprintf("http://localhost:%s", match[1])
|
|
|
|
body, err := curl(localAddr)
|
|
|
|
if err != nil {
|
|
|
|
Failf("Failed http.Get of forwarded port (%s): %v", localAddr, err)
|
|
|
|
}
|
|
|
|
if !strings.Contains(body, nginxDefaultOutput) {
|
|
|
|
Failf("Container port output missing expected value. Wanted:'%s', got: %s", nginxDefaultOutput, body)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2015-07-09 00:14:28 +00:00
|
|
|
Describe("Kubectl label", func() {
|
|
|
|
var podPath string
|
|
|
|
var nsFlag string
|
|
|
|
BeforeEach(func() {
|
2015-07-14 22:57:41 +00:00
|
|
|
podPath = filepath.Join(testContext.RepoRoot, "docs/user-guide/pod.yaml")
|
2015-07-09 00:14:28 +00:00
|
|
|
By("creating the pod")
|
|
|
|
nsFlag = fmt.Sprintf("--namespace=%v", ns)
|
|
|
|
runKubectl("create", "-f", podPath, nsFlag)
|
|
|
|
checkPodsRunningReady(c, ns, []string{simplePodName}, podStartTimeout)
|
|
|
|
})
|
|
|
|
AfterEach(func() {
|
|
|
|
cleanup(podPath, ns, simplePodSelector)
|
|
|
|
})
|
|
|
|
|
|
|
|
It("should update the label on a resource", func() {
|
|
|
|
labelName := "testing-label"
|
|
|
|
labelValue := "testing-label-value"
|
|
|
|
|
|
|
|
By("adding the label " + labelName + " with value " + labelValue + " to a pod")
|
|
|
|
runKubectl("label", "pods", simplePodName, labelName+"="+labelValue, nsFlag)
|
|
|
|
By("verifying the pod has the label " + labelName + " with the value " + labelValue)
|
|
|
|
output := runKubectl("get", "pod", simplePodName, "-L", labelName, nsFlag)
|
|
|
|
if !strings.Contains(output, labelValue) {
|
|
|
|
Failf("Failed updating label " + labelName + " to the pod " + simplePodName)
|
|
|
|
}
|
|
|
|
|
|
|
|
By("removing the label " + labelName + " of a pod")
|
|
|
|
runKubectl("label", "pods", simplePodName, labelName+"-", nsFlag)
|
|
|
|
By("verifying the pod doesn't have the label " + labelName)
|
|
|
|
output = runKubectl("get", "pod", simplePodName, "-L", labelName, nsFlag)
|
|
|
|
if strings.Contains(output, labelValue) {
|
|
|
|
Failf("Failed removing label " + labelName + " of the pod " + simplePodName)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2015-07-14 09:37:30 +00:00
|
|
|
Describe("Kubectl expose", func() {
|
|
|
|
It("should create services for rc", func() {
|
|
|
|
mkpath := func(file string) string {
|
|
|
|
return filepath.Join(testContext.RepoRoot, "examples/guestbook-go", file)
|
|
|
|
}
|
|
|
|
controllerJson := mkpath("redis-master-controller.json")
|
|
|
|
nsFlag := fmt.Sprintf("--namespace=%v", ns)
|
|
|
|
|
|
|
|
redisPort := 6379
|
|
|
|
serviceTimeout := 30 * time.Second
|
|
|
|
|
|
|
|
By("creating Redis RC")
|
|
|
|
runKubectl("create", "-f", controllerJson, nsFlag)
|
|
|
|
forEachPod(c, ns, "app", "redis", func(pod api.Pod) {
|
|
|
|
lookForStringInLog(ns, pod.Name, "redis-master", "The server is now ready to accept connections", podStartTimeout)
|
|
|
|
})
|
|
|
|
validateService := func(name string, servicePort int, timeout time.Duration) {
|
|
|
|
endpointFound := false
|
|
|
|
for t := time.Now(); time.Since(t) < timeout; time.Sleep(poll) {
|
|
|
|
endpoints, err := c.Endpoints(ns).Get(name)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
ipToPort := getPortsByIp(endpoints.Subsets)
|
|
|
|
if len(ipToPort) != 1 {
|
|
|
|
Logf("No IP found, retrying")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for _, port := range ipToPort {
|
|
|
|
if port[0] != redisPort {
|
|
|
|
Failf("Wrong endpoint port: %d", port[0])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
endpointFound = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if !endpointFound {
|
|
|
|
Failf("1 endpoint is expected")
|
|
|
|
}
|
|
|
|
service, err := c.Services(ns).Get(name)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
if len(service.Spec.Ports) != 1 {
|
|
|
|
Failf("1 port is expected")
|
|
|
|
}
|
|
|
|
port := service.Spec.Ports[0]
|
|
|
|
if port.Port != servicePort {
|
|
|
|
Failf("Wrong service port: %d", port.Port)
|
|
|
|
}
|
|
|
|
if port.TargetPort.IntVal != redisPort {
|
|
|
|
Failf("Wrong target port: %d")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
By("exposing RC")
|
|
|
|
runKubectl("expose", "rc", "redis-master", "--name=rm2", "--port=1234", fmt.Sprintf("--target-port=%d", redisPort), nsFlag)
|
|
|
|
waitForService(c, ns, "rm2", true, poll, serviceTimeout)
|
|
|
|
validateService("rm2", 1234, serviceTimeout)
|
|
|
|
|
|
|
|
By("exposing service")
|
|
|
|
runKubectl("expose", "service", "rm2", "--name=rm3", "--port=2345", fmt.Sprintf("--target-port=%d", redisPort), nsFlag)
|
|
|
|
waitForService(c, ns, "rm3", true, poll, serviceTimeout)
|
|
|
|
validateService("rm3", 2345, serviceTimeout)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2015-07-13 12:06:00 +00:00
|
|
|
Describe("Kubectl logs", func() {
|
|
|
|
It("should find a string in pod logs", func() {
|
|
|
|
mkpath := func(file string) string {
|
|
|
|
return filepath.Join(testContext.RepoRoot, "examples/guestbook-go", file)
|
|
|
|
}
|
|
|
|
controllerJson := mkpath("redis-master-controller.json")
|
|
|
|
nsFlag := fmt.Sprintf("--namespace=%v", ns)
|
|
|
|
By("creating Redis RC")
|
|
|
|
runKubectl("create", "-f", controllerJson, nsFlag)
|
|
|
|
By("checking logs")
|
|
|
|
forEachPod(c, ns, "app", "redis", func(pod api.Pod) {
|
|
|
|
_, err := lookForStringInLog(ns, pod.Name, "redis-master", "The server is now ready to accept connections", podStartTimeout)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("Kubectl patch", func() {
|
|
|
|
It("should add annotations for pods in rc", func() {
|
|
|
|
mkpath := func(file string) string {
|
|
|
|
return filepath.Join(testContext.RepoRoot, "examples/guestbook-go", file)
|
|
|
|
}
|
|
|
|
controllerJson := mkpath("redis-master-controller.json")
|
|
|
|
nsFlag := fmt.Sprintf("--namespace=%v", ns)
|
|
|
|
By("creating Redis RC")
|
|
|
|
runKubectl("create", "-f", controllerJson, nsFlag)
|
|
|
|
By("patching all pods")
|
|
|
|
forEachPod(c, ns, "app", "redis", func(pod api.Pod) {
|
|
|
|
runKubectl("patch", "pod", pod.Name, nsFlag, "-p", "{\"metadata\":{\"annotations\":{\"x\":\"y\"}}}")
|
|
|
|
})
|
|
|
|
|
|
|
|
By("checking annotations")
|
|
|
|
forEachPod(c, ns, "app", "redis", func(pod api.Pod) {
|
|
|
|
found := false
|
|
|
|
for key, val := range pod.Annotations {
|
|
|
|
if key == "x" && val == "y" {
|
|
|
|
found = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
Failf("Added annation not found")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2015-02-20 17:35:42 +00:00
|
|
|
})
|
|
|
|
|
2015-06-30 16:43:37 +00:00
|
|
|
func curl(addr string) (string, error) {
|
|
|
|
resp, err := http.Get(addr)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return string(body[:]), nil
|
|
|
|
}
|
|
|
|
|
2015-04-30 02:53:09 +00:00
|
|
|
func validateGuestbookApp(c *client.Client, ns string) {
|
2015-03-18 14:16:26 +00:00
|
|
|
Logf("Waiting for frontend to serve content.")
|
2015-04-30 02:53:09 +00:00
|
|
|
if !waitForGuestbookResponse(c, "get", "", `{"data": ""}`, guestbookStartupTimeout, ns) {
|
2015-03-18 14:16:26 +00:00
|
|
|
Failf("Frontend service did not start serving content in %v seconds.", guestbookStartupTimeout.Seconds())
|
2015-03-13 16:26:41 +00:00
|
|
|
}
|
|
|
|
|
2015-03-18 14:16:26 +00:00
|
|
|
Logf("Trying to add a new entry to the guestbook.")
|
2015-04-30 02:53:09 +00:00
|
|
|
if !waitForGuestbookResponse(c, "set", "TestEntry", `{"message": "Updated"}`, guestbookResponseTimeout, ns) {
|
2015-03-18 14:16:26 +00:00
|
|
|
Failf("Cannot added new entry in %v seconds.", guestbookResponseTimeout.Seconds())
|
2015-03-13 16:26:41 +00:00
|
|
|
}
|
|
|
|
|
2015-03-18 14:16:26 +00:00
|
|
|
Logf("Verifying that added entry can be retrieved.")
|
2015-04-30 02:53:09 +00:00
|
|
|
if !waitForGuestbookResponse(c, "get", "", `{"data": "TestEntry"}`, guestbookResponseTimeout, ns) {
|
2015-03-18 14:16:26 +00:00
|
|
|
Failf("Entry to guestbook wasn't correctly added in %v seconds.", guestbookResponseTimeout.Seconds())
|
2015-03-13 16:26:41 +00:00
|
|
|
}
|
2015-03-18 14:16:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns whether received expected response from guestbook on time.
|
2015-04-30 02:53:09 +00:00
|
|
|
func waitForGuestbookResponse(c *client.Client, cmd, arg, expectedResponse string, timeout time.Duration, ns string) bool {
|
2015-05-19 18:17:32 +00:00
|
|
|
for start := time.Now(); time.Since(start) < timeout; time.Sleep(5 * time.Second) {
|
2015-04-30 02:53:09 +00:00
|
|
|
res, err := makeRequestToGuestbook(c, cmd, arg, ns)
|
2015-03-18 14:16:26 +00:00
|
|
|
if err == nil && res == expectedResponse {
|
2015-05-19 18:17:32 +00:00
|
|
|
return true
|
2015-03-18 14:16:26 +00:00
|
|
|
}
|
2015-05-19 18:17:32 +00:00
|
|
|
}
|
|
|
|
return false
|
2015-03-13 16:26:41 +00:00
|
|
|
}
|
|
|
|
|
2015-04-30 02:53:09 +00:00
|
|
|
func makeRequestToGuestbook(c *client.Client, cmd, value string, ns string) (string, error) {
|
2015-03-13 16:26:41 +00:00
|
|
|
result, err := c.Get().
|
|
|
|
Prefix("proxy").
|
2015-04-30 02:53:09 +00:00
|
|
|
Namespace(ns).
|
2015-03-13 16:26:41 +00:00
|
|
|
Resource("services").
|
|
|
|
Name("frontend").
|
|
|
|
Suffix("/index.php").
|
|
|
|
Param("cmd", cmd).
|
|
|
|
Param("key", "messages").
|
|
|
|
Param("value", value).
|
|
|
|
Do().
|
|
|
|
Raw()
|
|
|
|
return string(result), err
|
|
|
|
}
|
|
|
|
|
2015-03-26 20:34:18 +00:00
|
|
|
type updateDemoData struct {
|
|
|
|
Image string
|
2015-03-26 19:22:04 +00:00
|
|
|
}
|
|
|
|
|
2015-03-26 20:34:18 +00:00
|
|
|
// getUDData creates a validator function based on the input string (i.e. kitten.jpg).
|
|
|
|
// For example, if you send "kitten.jpg", this function veridies that the image jpg = kitten.jpg
|
|
|
|
// in the container's json field.
|
2015-04-30 02:53:09 +00:00
|
|
|
func getUDData(jpgExpected string, ns string) func(*client.Client, string) error {
|
2015-03-26 20:34:18 +00:00
|
|
|
|
|
|
|
// getUDData validates data.json in the update-demo (returns nil if data is ok).
|
|
|
|
return func(c *client.Client, podID string) error {
|
|
|
|
Logf("validating pod %s", podID)
|
|
|
|
body, err := c.Get().
|
|
|
|
Prefix("proxy").
|
2015-04-30 02:53:09 +00:00
|
|
|
Namespace(ns).
|
2015-03-26 20:34:18 +00:00
|
|
|
Resource("pods").
|
|
|
|
Name(podID).
|
|
|
|
Suffix("data.json").
|
|
|
|
Do().
|
|
|
|
Raw()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2015-03-26 19:22:04 +00:00
|
|
|
}
|
2015-03-26 20:34:18 +00:00
|
|
|
Logf("got data: %s", body)
|
|
|
|
var data updateDemoData
|
|
|
|
if err := json.Unmarshal(body, &data); err != nil {
|
|
|
|
return err
|
2015-03-26 19:22:04 +00:00
|
|
|
}
|
2015-03-26 20:34:18 +00:00
|
|
|
Logf("Unmarshalled json jpg/img => %s , expecting %s .", data, jpgExpected)
|
|
|
|
if strings.Contains(data.Image, jpgExpected) {
|
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
return errors.New(fmt.Sprintf("data served up in container is innaccurate, %s didn't contain %s", data, jpgExpected))
|
2015-03-26 19:22:04 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-20 17:35:42 +00:00
|
|
|
}
|