diff --git a/test/e2e/cluster_upgrade.go b/test/e2e/cluster_upgrade.go index 8fd43d5b51a..1468fed58d1 100644 --- a/test/e2e/cluster_upgrade.go +++ b/test/e2e/cluster_upgrade.go @@ -25,13 +25,13 @@ import ( clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/util/wait" "k8s.io/kubernetes/test/e2e/chaosmonkey" + "k8s.io/kubernetes/test/e2e/common" "k8s.io/kubernetes/test/e2e/framework" . "github.com/onsi/ginkgo" ) // TODO(mikedanese): Add setup, validate, and teardown for: -// - secrets // - volumes // - persistent volumes var _ = framework.KubeDescribe("Upgrade [Feature:Upgrade]", func() { @@ -48,6 +48,7 @@ var _ = framework.KubeDescribe("Upgrade [Feature:Upgrade]", func() { cm.Register(func(sem *chaosmonkey.Semaphore) { // Close over f. testServiceRemainsUp(f, sem) + testSecretsDuringUpgrade(f, sem) }) cm.Do() }) @@ -64,6 +65,7 @@ var _ = framework.KubeDescribe("Upgrade [Feature:Upgrade]", func() { cm.Register(func(sem *chaosmonkey.Semaphore) { // Close over f. testServiceUpBeforeAndAfter(f, sem) + testSecretsBeforeAndAfterUpgrade(f, sem) }) cm.Do() }) @@ -78,6 +80,7 @@ var _ = framework.KubeDescribe("Upgrade [Feature:Upgrade]", func() { cm.Register(func(sem *chaosmonkey.Semaphore) { // Close over f. testServiceRemainsUp(f, sem) + testSecretsDuringUpgrade(f, sem) }) cm.Do() }) @@ -96,6 +99,7 @@ var _ = framework.KubeDescribe("Upgrade [Feature:Upgrade]", func() { cm.Register(func(sem *chaosmonkey.Semaphore) { // Close over f. testServiceUpBeforeAndAfter(f, sem) + testSecretsBeforeAndAfterUpgrade(f, sem) }) cm.Do() }) @@ -112,6 +116,7 @@ var _ = framework.KubeDescribe("Upgrade [Feature:Upgrade]", func() { cm.Register(func(sem *chaosmonkey.Semaphore) { // Close over f. testServiceRemainsUp(f, sem) + testSecretsDuringUpgrade(f, sem) }) cm.Do() }) @@ -228,3 +233,40 @@ func checkNodesVersions(cs clientset.Interface, want string) error { } return nil } + +func testSecretsBeforeAndAfterUpgrade(f *framework.Framework, sem *chaosmonkey.Semaphore) { + testSecrets(f, sem, false) +} + +func testSecretsDuringUpgrade(f *framework.Framework, sem *chaosmonkey.Semaphore) { + testSecrets(f, sem, true) +} + +func testSecrets(f *framework.Framework, sem *chaosmonkey.Semaphore, testDuringDisruption bool) { + // Setup + pod, expectedOutput := common.DoSecretE2EMultipleVolumesSetup(f) + + // Validate + By("consume secret before upgrade") + common.DoSecretE2EMultipleVolumesValidate(f, pod, expectedOutput) + + sem.Ready() + + if testDuringDisruption { + // Continuously validate + wait.Until(func() { + By("consume secret during upgrade") + common.DoSecretE2EMultipleVolumesValidate(f, pod, expectedOutput) + }, framework.Poll, sem.StopCh) + } else { + // Block until chaosmonkey is done + By("waiting for upgrade to finish without consuming secrets") + <-sem.StopCh + } + + // Validate after upgrade + By("consume secret after upgrade") + common.DoSecretE2EMultipleVolumesValidate(f, pod, expectedOutput) + + // Teardown +} diff --git a/test/e2e/common/secrets.go b/test/e2e/common/secrets.go index 5d3401ca846..5b79712dd14 100644 --- a/test/e2e/common/secrets.go +++ b/test/e2e/common/secrets.go @@ -73,73 +73,7 @@ var _ = framework.KubeDescribe("Secrets", func() { // This test ensures that the same secret can be mounted in multiple // volumes in the same pod. This test case exists to prevent // regressions that break this use-case. - var ( - name = "secret-test-" + string(uuid.NewUUID()) - volumeName = "secret-volume" - volumeMountPath = "/etc/secret-volume" - volumeName2 = "secret-volume-2" - volumeMountPath2 = "/etc/secret-volume-2" - secret = secretForTest(f.Namespace.Name, name) - ) - - By(fmt.Sprintf("Creating secret with name %s", secret.Name)) - var err error - if secret, err = f.ClientSet.Core().Secrets(f.Namespace.Name).Create(secret); err != nil { - framework.Failf("unable to create test secret %s: %v", secret.Name, err) - } - - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod-secrets-" + string(uuid.NewUUID()), - }, - Spec: api.PodSpec{ - Volumes: []api.Volume{ - { - Name: volumeName, - VolumeSource: api.VolumeSource{ - Secret: &api.SecretVolumeSource{ - SecretName: name, - }, - }, - }, - { - Name: volumeName2, - VolumeSource: api.VolumeSource{ - Secret: &api.SecretVolumeSource{ - SecretName: name, - }, - }, - }, - }, - Containers: []api.Container{ - { - Name: "secret-volume-test", - Image: "gcr.io/google_containers/mounttest:0.7", - Args: []string{ - "--file_content=/etc/secret-volume/data-1", - "--file_mode=/etc/secret-volume/data-1"}, - VolumeMounts: []api.VolumeMount{ - { - Name: volumeName, - MountPath: volumeMountPath, - ReadOnly: true, - }, - { - Name: volumeName2, - MountPath: volumeMountPath2, - ReadOnly: true, - }, - }, - }, - }, - RestartPolicy: api.RestartPolicyNever, - }, - } - - f.TestContainerOutput("consume secrets", pod, 0, []string{ - "content of file \"/etc/secret-volume/data-1\": value-1", - "mode of file \"/etc/secret-volume/data-1\": -rw-r--r--", - }) + doSecretE2EMultipleVolumes(f) }) It("should be consumable from pods in env vars [Conformance]", func() { @@ -334,3 +268,82 @@ func doSecretE2EWithMapping(f *framework.Framework, mode *int32) { f.TestContainerOutput("consume secrets", pod, 0, expectedOutput) } + +func DoSecretE2EMultipleVolumesSetup(f *framework.Framework) (*api.Pod, []string) { + var ( + name = "secret-test-" + string(uuid.NewUUID()) + volumeName = "secret-volume" + volumeMountPath = "/etc/secret-volume" + volumeName2 = "secret-volume-2" + volumeMountPath2 = "/etc/secret-volume-2" + secret = secretForTest(f.Namespace.Name, name) + ) + + By(fmt.Sprintf("Creating secret with name %s", secret.Name)) + var err error + if secret, err = f.ClientSet.Core().Secrets(f.Namespace.Name).Create(secret); err != nil { + framework.Failf("unable to create test secret %s: %v", secret.Name, err) + } + + pod := &api.Pod{ + ObjectMeta: api.ObjectMeta{ + Name: "pod-secrets-" + string(uuid.NewUUID()), + }, + Spec: api.PodSpec{ + Volumes: []api.Volume{ + { + Name: volumeName, + VolumeSource: api.VolumeSource{ + Secret: &api.SecretVolumeSource{ + SecretName: name, + }, + }, + }, + { + Name: volumeName2, + VolumeSource: api.VolumeSource{ + Secret: &api.SecretVolumeSource{ + SecretName: name, + }, + }, + }, + }, + Containers: []api.Container{ + { + Name: "secret-volume-test", + Image: "gcr.io/google_containers/mounttest:0.7", + Args: []string{ + "--file_content=/etc/secret-volume/data-1", + "--file_mode=/etc/secret-volume/data-1"}, + VolumeMounts: []api.VolumeMount{ + { + Name: volumeName, + MountPath: volumeMountPath, + ReadOnly: true, + }, + { + Name: volumeName2, + MountPath: volumeMountPath2, + ReadOnly: true, + }, + }, + }, + }, + RestartPolicy: api.RestartPolicyNever, + }, + } + expectedOutput := []string{ + "content of file \"/etc/secret-volume/data-1\": value-1", + "mode of file \"/etc/secret-volume/data-1\": -rw-r--r--", + } + return pod, expectedOutput +} + +func DoSecretE2EMultipleVolumesValidate(f *framework.Framework, pod *api.Pod, expectedOutput []string) { + f.TestContainerOutput("consume secrets", pod, 0, expectedOutput) +} + +func doSecretE2EMultipleVolumes(f *framework.Framework) { + pod, expectedOutput := DoSecretE2EMultipleVolumesSetup(f) + DoSecretE2EMultipleVolumesValidate(f, pod, expectedOutput) +}