Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
Revert "test: catch unexpected modifications by operator"
Browse files Browse the repository at this point in the history
This reverts commit 48a0250.
  • Loading branch information
avalluri committed Sep 27, 2020
1 parent d97dbc2 commit 9b17451
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,11 @@ func TestDeploymentController(t *testing.T) {

testIt := func(t *testing.T, testK8sVersion version.Version) {
type testContext struct {
c client.Client
cs kubernetes.Interface
rc reconcile.Reconciler
evWatcher watch.Interface
events []*corev1.Event
resourceVersions map[string]string
c client.Client
cs kubernetes.Interface
rc reconcile.Reconciler
evWatcher watch.Interface
events []*corev1.Event
}
const (
testNamespace = "test-namespace"
Expand All @@ -210,11 +209,9 @@ func TestDeploymentController(t *testing.T) {
}

setup := func(t *testing.T) *testContext {
tc := &testContext{
c: fake.NewFakeClient(),
cs: cgfake.NewSimpleClientset(),
resourceVersions: map[string]string{},
}
tc := &testContext{}
tc.c = fake.NewFakeClient()
tc.cs = cgfake.NewSimpleClientset()
tc.rc = newReconcileDeployment(tc.c, tc.cs)
tc.evWatcher = tc.rc.(*deployment.ReconcileDeployment).EventBroadcaster().StartEventWatcher(func(ev *corev1.Event) {
// Discard consecutive duplicate events, mimicking the EventAggregator behavior
Expand Down Expand Up @@ -248,20 +245,14 @@ func TestDeploymentController(t *testing.T) {
require.ElementsMatch(t, events, expectedEvents, "events must match")
}

validateDriver := func(t *testing.T, tc *testContext, dep *api.Deployment, expectedEvents []string, wasUpdated bool) {
validateDriver := func(t *testing.T, tc *testContext, dep *api.Deployment, expectedEvents []string) {
// We may have to fill in some defaults, so make a copy first.
dep = dep.DeepCopyObject().(*api.Deployment)
if dep.Spec.Image == "" {
dep.Spec.Image = testDriverImage
}

// If the CR was not updated, then objects should still be the same as they were initially.
rv := tc.resourceVersions
if wasUpdated {
rv = nil
}
_, err := validate.DriverDeployment(tc.c, testK8sVersion, testNamespace, *dep, rv)
require.NoError(t, err, "validate deployment")
require.NoError(t, validate.DriverDeployment(tc.c, testK8sVersion, testNamespace, *dep), "validate deployment")
validateEvents(t, tc, dep, expectedEvents)
}

Expand All @@ -280,7 +271,7 @@ func TestDeploymentController(t *testing.T) {
require.NoError(t, err, "failed to create deployment")

testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})
})

t.Run("deployment with explicit values", func(t *testing.T) {
Expand All @@ -306,7 +297,7 @@ func TestDeploymentController(t *testing.T) {

// Reconcile now should change Phase to running
testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})
})

t.Run("multiple deployments", func(t *testing.T) {
Expand All @@ -329,9 +320,9 @@ func TestDeploymentController(t *testing.T) {
require.NoError(t, err, "failed to create deployment2")

testReconcilePhase(t, tc.rc, tc.c, d1.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep1, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep1, []string{api.EventReasonNew, api.EventReasonRunning})
testReconcilePhase(t, tc.rc, tc.c, d2.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep2, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep2, []string{api.EventReasonNew, api.EventReasonRunning})
})

t.Run("invalid device mode", func(t *testing.T) {
Expand Down Expand Up @@ -363,7 +354,7 @@ func TestDeploymentController(t *testing.T) {
err := tc.c.Create(context.TODO(), dep)
require.NoError(t, err, "failed to create deployment")
testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})
})

t.Run("direct mode", func(t *testing.T) {
Expand All @@ -378,7 +369,7 @@ func TestDeploymentController(t *testing.T) {
err := tc.c.Create(context.TODO(), dep)
require.NoError(t, err, "failed to create deployment")
testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})
})

t.Run("provided private keys", func(t *testing.T) {
Expand All @@ -400,7 +391,7 @@ func TestDeploymentController(t *testing.T) {

// First deployment expected to be successful
testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})
})

t.Run("provided private keys and certificates", func(t *testing.T) {
Expand Down Expand Up @@ -433,7 +424,7 @@ func TestDeploymentController(t *testing.T) {

// First deployment expected to be successful
testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})
})

t.Run("invalid private keys and certificates", func(t *testing.T) {
Expand Down Expand Up @@ -526,13 +517,13 @@ func TestDeploymentController(t *testing.T) {
tc.rc.(*deployment.ReconcileDeployment).AddHook(&hook)

testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})

tc.rc.(*deployment.ReconcileDeployment).RemoveHook(&hook)

// Next reconcile phase should catch the deployment changes
testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, updatedDep, []string{api.EventReasonNew, api.EventReasonRunning}, true)
validateDriver(t, tc, updatedDep, []string{api.EventReasonNew, api.EventReasonRunning})
})

t.Run("updating", func(t *testing.T) {
Expand All @@ -552,11 +543,10 @@ func TestDeploymentController(t *testing.T) {
require.NoError(t, err, "create deployment")

testReconcilePhase(t, tc.rc, tc.c, dep.Name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})

// Reconcile now should keep phase as running.
testReconcilePhase(t, tc.rc, tc.c, dep.Name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateEvents(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})

// Retrieve existing object before updating it.
Expand All @@ -577,7 +567,7 @@ func TestDeploymentController(t *testing.T) {
testReconcilePhase(t, tc.rc, tc.c, dep.Name, false, false, api.DeploymentPhaseRunning)

// Recheck the container resources are updated
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, true)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})
}

t.Run("while running", func(t *testing.T) {
Expand All @@ -603,7 +593,7 @@ func TestDeploymentController(t *testing.T) {
err := tc.c.Create(context.TODO(), dep)
require.NoError(t, err, "failed to create deployment")
testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})

err = tc.c.Get(context.TODO(), client.ObjectKey{Name: d.name}, dep)
require.NoError(t, err, "get deployment")
Expand Down Expand Up @@ -639,16 +629,25 @@ func TestDeploymentController(t *testing.T) {
err = tc.c.Create(context.TODO(), cm2)
require.NoError(t, err, "create configmap: %s", cm2.Name)

defer func() {
err := tc.c.Delete(context.TODO(), cm1)
if err != nil && !errors.IsNotFound(err) {
require.NoErrorf(t, err, "delete configmap: %s", cm1.Name)
}
err = tc.c.Delete(context.TODO(), cm2)
if err != nil && !errors.IsNotFound(err) {
require.NoErrorf(t, err, "delete configmap: %s", cm2.Name)
}
}()

// Use a fresh reconciler to mimic operator restart
tc.rc = newReconcileDeployment(tc.c, tc.cs)

// A fresh reconcile should delete the newly created above ConfigMap
testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning)
err = tc.c.Get(context.TODO(), client.ObjectKey{Name: d.name}, dep)
require.NoError(t, err, "get deployment")
// It is debatable whether the operator should update all objects after
// a restart. Currently it does.
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, true)
validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning})

cm := &corev1.ConfigMap{}
err = tc.c.Get(context.TODO(), client.ObjectKey{Name: cm1.Name, Namespace: testNamespace}, cm)
Expand Down
39 changes: 12 additions & 27 deletions test/e2e/operator/deployment_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool {
if what == nil {
what = []interface{}{"validate driver"}
}

// We cannot check for unexpected object modifications
// by the operator during E2E testing because the app
// controllers themselves will also modify the same
// objects with status changes. We can only test
// that during unit testing.
initialCreation := false

framework.ExpectNoErrorWithOffset(1, validate.DriverDeploymentEventually(ctx, client, k8sver, d.Namespace, deployment, initialCreation), what...)
framework.ExpectNoErrorWithOffset(1, validate.DriverDeploymentEventually(ctx, client, k8sver, d.Namespace, deployment), what...)
framework.Logf("got expected driver deployment %s", deployment.Name)
}

Expand Down Expand Up @@ -205,7 +197,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool {

deployment2 = deploy.CreateDeploymentCR(f, deployment2)
defer deploy.DeleteDeploymentCR(f, deployment2.Name)
validateDriver(deployment1, true /* TODO 2 */, "validate driver #2")
validateDriver(deployment1 /* TODO 2 */, "validate driver #2")
})

It("shall support dots in the name", func() {
Expand All @@ -222,7 +214,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool {

deployment = deploy.CreateDeploymentCR(f, deployment)
defer deploy.DeleteDeploymentCR(f, deployment.Name)
validateDriver(deployment, true)
validateDriver(deployment)
})

It("driver deployment shall be running even after operator exit", func() {
Expand All @@ -231,21 +223,16 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool {
deployment = deploy.CreateDeploymentCR(f, deployment)

defer deploy.DeleteDeploymentCR(f, deployment.Name)
validateDriver(deployment, true)
validateDriver(deployment)

// Stop the operator
stopOperator(c, d)
// restore the deployment so that next test should not effect
defer startOperator(c, d)

// Ensure that the driver is running consistently
resourceVersions := map[string]string{}
Consistently(func() error {
final, err := validate.DriverDeployment(client, k8sver, d.Namespace, deployment, resourceVersions)
if final {
framework.Failf("final error during driver validation after restarting: %v", err)
}
return err
return validate.DriverDeployment(client, k8sver, d.Namespace, deployment)
}, "1m", "20s").ShouldNot(HaveOccurred(), "driver validation failure after restarting")
})

Expand Down Expand Up @@ -296,7 +283,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool {

// Deleting the existing secret should make the deployment succeed.
deleteSecret(sec.Name)
validateDriver(deployment, true)
validateDriver(deployment)
})
})

Expand Down Expand Up @@ -391,7 +378,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool {
deployment = deploy.CreateDeploymentCR(f, deployment)
defer deploy.DeleteDeploymentCR(f, deployment.Name)
deploy.WaitForPMEMDriver(c, deployment.Name, corev1.NamespaceDefault, false /* testing */)
validateDriver(deployment, true)
validateDriver(deployment)

// NOTE(avalluri): As the current operator does not support deploying
// the driver in 'testing' mode, we cannot directely access CSI
Expand Down Expand Up @@ -447,10 +434,8 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool {
validateDriver(deployment, "validate driver before update")

// We have to get a fresh copy before updating it because the
// operator should have modified the status, and only the status.
modifiedDeployment := deploy.GetDeploymentCR(f, deployment.Name)
Expect(modifiedDeployment.Spec).To(Equal(deployment.Spec), "spec unmodified")
Expect(modifiedDeployment.Status.Phase).To(Equal(api.DeploymentPhaseRunning), "deployment phase")
// operator should have modified the status.
deployment = deploy.GetDeploymentCR(f, deployment.Name)

restored := false
if restart {
Expand All @@ -462,15 +447,15 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool {
}()
}

testcase.Mutate(&modifiedDeployment)
deployment = deploy.UpdateDeploymentCR(f, modifiedDeployment)
testcase.Mutate(&deployment)
deployment = deploy.UpdateDeploymentCR(f, deployment)

if restart {
startOperator(c, d)
restored = true
}

validateDriver(modifiedDeployment, "validate driver after update and restart")
validateDriver(deployment, "validate driver after update and restart")
}

It("while running", func() {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/operator/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var _ = deploy.DescribeForSome("driver", func(d *deploy.Deployment) bool {
deployment := d.GetDriverDeployment()
deployment = deploy.GetDeploymentCR(f, deployment.Name)

framework.ExpectNoError(validate.DriverDeploymentEventually(ctx, client, *k8sver, d.Namespace, deployment, true), "validate driver")
framework.ExpectNoError(validate.DriverDeploymentEventually(ctx, client, *k8sver, d.Namespace, deployment), "validate driver")
})

// Just very minimal testing at the moment.
Expand Down
Loading

0 comments on commit 9b17451

Please sign in to comment.