Merge pull request #40747 from krousey/upgrades
Automatic merge from submit-queue Add an upgrade test for secrets. **What this PR does / why we need it**: This PR adds an upgrade test for secrets. It creates a secret and makes sure that pods can consume it before an after an upgrade.
This commit is contained in:
		@@ -31,6 +31,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var upgradeTests = []upgrades.Test{
 | 
					var upgradeTests = []upgrades.Test{
 | 
				
			||||||
	&upgrades.ServiceUpgradeTest{},
 | 
						&upgrades.ServiceUpgradeTest{},
 | 
				
			||||||
 | 
						&upgrades.SecretUpgradeTest{},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ = framework.KubeDescribe("Upgrade [Feature:Upgrade]", func() {
 | 
					var _ = framework.KubeDescribe("Upgrade [Feature:Upgrade]", func() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,6 +49,16 @@ func (f *Framework) PodClient() *PodClient {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Convenience method for getting a pod client interface in an alternative namespace,
 | 
				
			||||||
 | 
					// possibly applying test-suite specific transformations to the pod spec, e.g. for
 | 
				
			||||||
 | 
					// node e2e pod scheduling.
 | 
				
			||||||
 | 
					func (f *Framework) PodClientNS(namespace string) *PodClient {
 | 
				
			||||||
 | 
						return &PodClient{
 | 
				
			||||||
 | 
							f:            f,
 | 
				
			||||||
 | 
							PodInterface: f.ClientSet.Core().Pods(namespace),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PodClient struct {
 | 
					type PodClient struct {
 | 
				
			||||||
	f *Framework
 | 
						f *Framework
 | 
				
			||||||
	v1core.PodInterface
 | 
						v1core.PodInterface
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2110,8 +2110,11 @@ func (f *Framework) MatchContainerOutput(
 | 
				
			|||||||
	containerName string,
 | 
						containerName string,
 | 
				
			||||||
	expectedOutput []string,
 | 
						expectedOutput []string,
 | 
				
			||||||
	matcher func(string, ...interface{}) gomegatypes.GomegaMatcher) error {
 | 
						matcher func(string, ...interface{}) gomegatypes.GomegaMatcher) error {
 | 
				
			||||||
	podClient := f.PodClient()
 | 
						ns := pod.ObjectMeta.Namespace
 | 
				
			||||||
	ns := f.Namespace.Name
 | 
						if ns == "" {
 | 
				
			||||||
 | 
							ns = f.Namespace.Name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						podClient := f.PodClientNS(ns)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	createdPod := podClient.Create(pod)
 | 
						createdPod := podClient.Create(pod)
 | 
				
			||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@ load(
 | 
				
			|||||||
go_library(
 | 
					go_library(
 | 
				
			||||||
    name = "go_default_library",
 | 
					    name = "go_default_library",
 | 
				
			||||||
    srcs = [
 | 
					    srcs = [
 | 
				
			||||||
 | 
					        "secrets.go",
 | 
				
			||||||
        "services.go",
 | 
					        "services.go",
 | 
				
			||||||
        "upgrade.go",
 | 
					        "upgrade.go",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
@@ -18,6 +19,8 @@ go_library(
 | 
				
			|||||||
        "//pkg/api/v1:go_default_library",
 | 
					        "//pkg/api/v1:go_default_library",
 | 
				
			||||||
        "//test/e2e/framework:go_default_library",
 | 
					        "//test/e2e/framework:go_default_library",
 | 
				
			||||||
        "//vendor:github.com/onsi/ginkgo",
 | 
					        "//vendor:github.com/onsi/ginkgo",
 | 
				
			||||||
 | 
					        "//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
 | 
				
			||||||
 | 
					        "//vendor:k8s.io/apimachinery/pkg/util/uuid",
 | 
				
			||||||
        "//vendor:k8s.io/apimachinery/pkg/util/wait",
 | 
					        "//vendor:k8s.io/apimachinery/pkg/util/wait",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										145
									
								
								test/e2e/upgrades/secrets.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								test/e2e/upgrades/secrets.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,145 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2017 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package upgrades
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/uuid"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/v1"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/test/e2e/framework"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						. "github.com/onsi/ginkgo"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SecretUpgradeTest test that a secret is available before and after
 | 
				
			||||||
 | 
					// a cluster upgrade.
 | 
				
			||||||
 | 
					type SecretUpgradeTest struct {
 | 
				
			||||||
 | 
						secret *v1.Secret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Setup creates a secret and then verifies that a pod can consume it.
 | 
				
			||||||
 | 
					func (t *SecretUpgradeTest) Setup(f *framework.Framework) {
 | 
				
			||||||
 | 
						secretName := "upgrade-secret"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Grab a unique namespace so we don't collide.
 | 
				
			||||||
 | 
						ns, err := f.CreateNamespace("secret-upgrade", nil)
 | 
				
			||||||
 | 
						framework.ExpectNoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.secret = &v1.Secret{
 | 
				
			||||||
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
								Namespace: ns.Name,
 | 
				
			||||||
 | 
								Name:      secretName,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Data: map[string][]byte{
 | 
				
			||||||
 | 
								"data": []byte("keep it secret"),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						By("Creating a secret")
 | 
				
			||||||
 | 
						if t.secret, err = f.ClientSet.Core().Secrets(ns.Name).Create(t.secret); err != nil {
 | 
				
			||||||
 | 
							framework.Failf("unable to create test secret %s: %v", t.secret.Name, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						By("Making sure the secret is consumable")
 | 
				
			||||||
 | 
						t.testPod(f)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Test waits for the upgrade to complete, and then verifies that a
 | 
				
			||||||
 | 
					// pod can still consume the secret.
 | 
				
			||||||
 | 
					func (t *SecretUpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade UpgradeType) {
 | 
				
			||||||
 | 
						<-done
 | 
				
			||||||
 | 
						By("Consuming the secret after upgrade")
 | 
				
			||||||
 | 
						t.testPod(f)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Teardown cleans up any remaining resources.
 | 
				
			||||||
 | 
					func (t *SecretUpgradeTest) Teardown(f *framework.Framework) {
 | 
				
			||||||
 | 
						// rely on the namespace deletion to clean up everything
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// testPod creates a pod that consumes a secret and prints it out. The
 | 
				
			||||||
 | 
					// output is then verified.
 | 
				
			||||||
 | 
					func (t *SecretUpgradeTest) testPod(f *framework.Framework) {
 | 
				
			||||||
 | 
						volumeName := "secret-volume"
 | 
				
			||||||
 | 
						volumeMountPath := "/etc/secret-volume"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pod := &v1.Pod{
 | 
				
			||||||
 | 
							ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
								Name:      "pod-secrets-" + string(uuid.NewUUID()),
 | 
				
			||||||
 | 
								Namespace: t.secret.ObjectMeta.Namespace,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							Spec: v1.PodSpec{
 | 
				
			||||||
 | 
								Volumes: []v1.Volume{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Name: volumeName,
 | 
				
			||||||
 | 
										VolumeSource: v1.VolumeSource{
 | 
				
			||||||
 | 
											Secret: &v1.SecretVolumeSource{
 | 
				
			||||||
 | 
												SecretName: t.secret.ObjectMeta.Name,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								Containers: []v1.Container{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Name:  "secret-volume-test",
 | 
				
			||||||
 | 
										Image: "gcr.io/google_containers/mounttest:0.7",
 | 
				
			||||||
 | 
										Args: []string{
 | 
				
			||||||
 | 
											fmt.Sprintf("--file_content=%s/data", volumeMountPath),
 | 
				
			||||||
 | 
											fmt.Sprintf("--file_mode=%s/data", volumeMountPath),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										VolumeMounts: []v1.VolumeMount{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Name:      volumeName,
 | 
				
			||||||
 | 
												MountPath: volumeMountPath,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Name:    "secret-env-test",
 | 
				
			||||||
 | 
										Image:   "gcr.io/google_containers/busybox:1.24",
 | 
				
			||||||
 | 
										Command: []string{"sh", "-c", "env"},
 | 
				
			||||||
 | 
										Env: []v1.EnvVar{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Name: "SECRET_DATA",
 | 
				
			||||||
 | 
												ValueFrom: &v1.EnvVarSource{
 | 
				
			||||||
 | 
													SecretKeyRef: &v1.SecretKeySelector{
 | 
				
			||||||
 | 
														LocalObjectReference: v1.LocalObjectReference{
 | 
				
			||||||
 | 
															Name: t.secret.ObjectMeta.Name,
 | 
				
			||||||
 | 
														},
 | 
				
			||||||
 | 
														Key: "data",
 | 
				
			||||||
 | 
													},
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								RestartPolicy: v1.RestartPolicyNever,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expectedOutput := []string{
 | 
				
			||||||
 | 
							"content of file \"/etc/secret-volume/data\": keep it secret",
 | 
				
			||||||
 | 
							"mode of file \"/etc/secret-volume/data\": -rw-r--r--",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f.TestContainerOutput("volume consume secrets", pod, 0, expectedOutput)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expectedOutput = []string{"SECRET_DATA=keep it secret"}
 | 
				
			||||||
 | 
						f.TestContainerOutput("env consume secrets", pod, 1, expectedOutput)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user