2015-02-20 17:35:42 +00:00
|
|
|
/*
|
|
|
|
Copyright 2015 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 (
|
|
|
|
"encoding/json"
|
2015-03-26 20:34:18 +00:00
|
|
|
"errors"
|
2015-03-26 19:22:04 +00:00
|
|
|
"fmt"
|
2015-02-20 17:35:42 +00:00
|
|
|
"path/filepath"
|
|
|
|
"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"
|
|
|
|
)
|
|
|
|
|
|
|
|
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-02-20 17:35:42 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var _ = Describe("kubectl", func() {
|
2015-03-05 04:35:51 +00:00
|
|
|
var c *client.Client
|
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-03-02 18:15:34 +00:00
|
|
|
})
|
2015-02-20 17:35:42 +00:00
|
|
|
|
2015-03-13 16:26:41 +00:00
|
|
|
Describe("update-demo", func() {
|
|
|
|
var (
|
2015-03-31 23:36:31 +00:00
|
|
|
updateDemoRoot = filepath.Join(testContext.RepoRoot, "examples/update-demo/v1beta1")
|
2015-03-13 16:26:41 +00:00
|
|
|
nautilusPath = filepath.Join(updateDemoRoot, "nautilus-rc.yaml")
|
|
|
|
kittenPath = filepath.Join(updateDemoRoot, "kitten-rc.yaml")
|
|
|
|
)
|
|
|
|
|
|
|
|
It("should create and stop a replication controller", func() {
|
|
|
|
defer cleanup(nautilusPath, updateDemoSelector)
|
|
|
|
|
|
|
|
By("creating a replication controller")
|
|
|
|
runKubectl("create", "-f", nautilusPath)
|
2015-03-26 20:34:18 +00:00
|
|
|
validateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg"))
|
2015-03-13 16:26:41 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
It("should scale a replication controller", func() {
|
|
|
|
defer cleanup(nautilusPath, updateDemoSelector)
|
|
|
|
|
|
|
|
By("creating a replication controller")
|
|
|
|
runKubectl("create", "-f", nautilusPath)
|
2015-03-26 20:34:18 +00:00
|
|
|
validateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg"))
|
2015-03-13 16:26:41 +00:00
|
|
|
By("scaling down the replication controller")
|
|
|
|
runKubectl("resize", "rc", "update-demo-nautilus", "--replicas=1")
|
2015-03-26 20:34:18 +00:00
|
|
|
validateController(c, nautilusImage, 1, "update-demo", updateDemoSelector, getUDData("nautilus.jpg"))
|
2015-03-13 16:26:41 +00:00
|
|
|
By("scaling up the replication controller")
|
|
|
|
runKubectl("resize", "rc", "update-demo-nautilus", "--replicas=2")
|
2015-03-26 20:34:18 +00:00
|
|
|
validateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg"))
|
2015-03-13 16:26:41 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
It("should do a rolling update of a replication controller", func() {
|
|
|
|
// Cleanup all resources in case we fail somewhere in the middle
|
|
|
|
defer cleanup(updateDemoRoot, updateDemoSelector)
|
|
|
|
|
|
|
|
By("creating the initial replication controller")
|
|
|
|
runKubectl("create", "-f", nautilusPath)
|
2015-03-26 20:34:18 +00:00
|
|
|
validateController(c, nautilusImage, 2, "update-demo", updateDemoSelector, getUDData("nautilus.jpg"))
|
2015-03-27 23:24:59 +00:00
|
|
|
By("rolling-update to new replication controller")
|
|
|
|
runKubectl("rolling-update", "update-demo-nautilus", "--update-period=1s", "-f", kittenPath)
|
2015-03-26 20:34:18 +00:00
|
|
|
validateController(c, kittenImage, 2, "update-demo", updateDemoSelector, getUDData("kitten.jpg"))
|
2015-03-13 16:26:41 +00:00
|
|
|
})
|
2015-02-20 17:35:42 +00:00
|
|
|
})
|
|
|
|
|
2015-03-13 16:26:41 +00:00
|
|
|
Describe("guestbook", func() {
|
2015-03-31 23:36:31 +00:00
|
|
|
var guestbookPath = filepath.Join(testContext.RepoRoot, "examples/guestbook")
|
2015-03-13 16:26:41 +00:00
|
|
|
|
|
|
|
It("should create and stop a working application", func() {
|
|
|
|
defer cleanup(guestbookPath, frontendSelector, redisMasterSelector, redisSlaveSelector)
|
2015-02-20 17:35:42 +00:00
|
|
|
|
2015-03-13 16:26:41 +00:00
|
|
|
By("creating all guestbook components")
|
|
|
|
runKubectl("create", "-f", guestbookPath)
|
2015-02-20 17:35:42 +00:00
|
|
|
|
2015-03-13 16:26:41 +00:00
|
|
|
By("validating guestbook app")
|
|
|
|
validateGuestbookApp(c)
|
|
|
|
})
|
2015-02-20 17:35:42 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
|
2015-03-13 16:26:41 +00:00
|
|
|
func validateGuestbookApp(c *client.Client) {
|
2015-03-18 14:16:26 +00:00
|
|
|
Logf("Waiting for frontend to serve content.")
|
|
|
|
if !waitForGuestbookResponse(c, "get", "", `{"data": ""}`, guestbookStartupTimeout) {
|
|
|
|
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.")
|
|
|
|
if !waitForGuestbookResponse(c, "set", "TestEntry", `{"message": "Updated"}`, guestbookResponseTimeout) {
|
|
|
|
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.")
|
|
|
|
if !waitForGuestbookResponse(c, "get", "", `{"data": "TestEntry"}`, guestbookResponseTimeout) {
|
|
|
|
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.
|
|
|
|
func waitForGuestbookResponse(c *client.Client, cmd, arg, expectedResponse string, timeout time.Duration) bool {
|
|
|
|
for start := time.Now(); time.Since(start) < timeout; time.Sleep(5 * time.Second) {
|
|
|
|
res, err := makeRequestToGuestbook(c, cmd, arg)
|
|
|
|
if err == nil && res == expectedResponse {
|
|
|
|
return true
|
|
|
|
}
|
2015-03-13 16:26:41 +00:00
|
|
|
}
|
2015-03-18 14:16:26 +00:00
|
|
|
return false
|
2015-03-13 16:26:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func makeRequestToGuestbook(c *client.Client, cmd, value string) (string, error) {
|
|
|
|
result, err := c.Get().
|
|
|
|
Prefix("proxy").
|
2015-04-02 20:15:39 +00:00
|
|
|
Namespace(api.NamespaceDefault).
|
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.
|
|
|
|
func getUDData(jpgExpected string) func(*client.Client, string) error {
|
|
|
|
|
|
|
|
// 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-02 20:15:39 +00:00
|
|
|
Namespace(api.NamespaceDefault).
|
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
|
|
|
}
|