Skip to content

Commit ae4e7b7

Browse files
authored
Add some more tests for ReconcilePolicy at namespace scope (#4869)
1 parent 8c18e28 commit ae4e7b7

7 files changed

+1949
-367
lines changed

v2/internal/controllers/reconcile_policy_test.go

Lines changed: 119 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
. "github.com/onsi/gomega"
1212

13+
corev1 "k8s.io/api/core/v1"
1314
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1415
"sigs.k8s.io/controller-runtime/pkg/client"
1516

@@ -75,14 +76,88 @@ func Test_ReconcilePolicy_UnknownPolicyIsIgnored(t *testing.T) {
7576
tc.Expect(rg.Status.Tags).To(HaveKeyWithValue("tag1", "value1"))
7677
}
7778

78-
func Test_ReconcilePolicy_DetachOnDelete_SkipsDelete(t *testing.T) {
79+
func Test_ReconcilePolicy_SkipsDelete(t *testing.T) {
7980
t.Parallel()
80-
testDeleteSkipped(t, "detach-on-delete")
81+
82+
testCases := []struct {
83+
name string
84+
policy string
85+
onNamespace bool
86+
}{
87+
{
88+
name: "DetachOnDelete_OnResource",
89+
policy: "detach-on-delete",
90+
onNamespace: false,
91+
},
92+
{
93+
name: "Skip_OnResource",
94+
policy: "skip",
95+
onNamespace: false,
96+
},
97+
{
98+
name: "DetachOnDelete_OnNamespace",
99+
policy: "detach-on-delete",
100+
onNamespace: true,
101+
},
102+
{
103+
name: "Skip_OnNamespace",
104+
policy: "skip",
105+
onNamespace: true,
106+
},
107+
}
108+
109+
for _, tc := range testCases {
110+
t.Run(tc.name, func(t *testing.T) {
111+
t.Parallel()
112+
testDeleteSkipped(
113+
t,
114+
deleteSkippedOptions{
115+
policy: tc.policy,
116+
onNamespace: tc.onNamespace,
117+
})
118+
})
119+
}
81120
}
82121

83-
func Test_ReconcilePolicy_Skip_SkipsDelete(t *testing.T) {
122+
func Test_ReconcilePolicy_SkipReconcileAddedToNamespace_ReconcileIsSkipped(t *testing.T) {
84123
t.Parallel()
85-
testDeleteSkipped(t, "skip")
124+
125+
tc := globalTestContext.ForTest(t)
126+
127+
// Create a resource group
128+
rg := tc.CreateTestResourceGroupAndWait()
129+
130+
// check properties
131+
tc.Expect(rg.Status.Location).To(Equal(tc.AzureRegion))
132+
tc.Expect(rg.Status.Properties.ProvisioningState).To(Equal(to.Ptr("Succeeded")))
133+
tc.Expect(rg.Status.Id).ToNot(BeNil())
134+
135+
// Update the namespace to skip reconcile
136+
ns := &corev1.Namespace{}
137+
tc.GetResource(client.ObjectKey{Name: tc.Namespace}, ns)
138+
oldNS := ns.DeepCopy()
139+
ns.Annotations = make(map[string]string)
140+
ns.Annotations["serviceoperator.azure.com/reconcile-policy"] = "skip"
141+
tc.Patch(oldNS, ns)
142+
143+
// Update the tags
144+
old := rg.DeepCopy()
145+
rg.Spec.Tags["tag1"] = "value1"
146+
tc.PatchResourceAndWait(old, rg)
147+
tc.Expect(rg.Status.Tags).ToNot(HaveKey("tag1"))
148+
149+
// Stop skipping reconcile
150+
oldNS = ns.DeepCopy()
151+
delete(ns.Annotations, "serviceoperator.azure.com/reconcile-policy")
152+
tc.Patch(oldNS, ns)
153+
154+
// ensure the tags get updated
155+
objectKey := client.ObjectKeyFromObject(rg)
156+
tc.Eventually(func() map[string]string {
157+
newRG := &resources.ResourceGroup{}
158+
tc.GetResource(objectKey, newRG)
159+
return newRG.Status.Tags
160+
}).Should(HaveKeyWithValue("tag1", "value1"))
86161
}
87162

88163
func Test_ReconcilePolicy_SkippedParentDeleted_ChildIssuesDeleteToAzure(t *testing.T) {
@@ -198,7 +273,12 @@ func Test_ReconcilePolicySkip_CreatesSecretAndConfigMap(t *testing.T) {
198273
tc.Patch(old, acct)
199274
}
200275

201-
func testDeleteSkipped(t *testing.T, policy string) {
276+
type deleteSkippedOptions struct {
277+
policy string
278+
onNamespace bool
279+
}
280+
281+
func testDeleteSkipped(t *testing.T, opts deleteSkippedOptions) {
202282
tc := globalTestContext.ForTest(t)
203283

204284
// Create a resource group
@@ -211,23 +291,33 @@ func testDeleteSkipped(t *testing.T, policy string) {
211291
tc.Expect(rg.Status.Id).ToNot(BeNil())
212292
armId := *rg.Status.Id
213293

214-
if policy == "skip" {
215-
// This is a hack so that we can tell when reconcile has happened to avoid a race in the recording.
216-
// It's only required in the skip case because for detach-on-delete we don't reconcile at all
217-
// See HasReconcilePolicyAnnotationChanged
294+
if !opts.onNamespace {
295+
if opts.policy == "skip" {
296+
// This is a hack so that we can tell when reconcile has happened to avoid a race in the recording.
297+
// It's only required in the skip case because for detach-on-delete we don't reconcile at all
298+
// See HasReconcilePolicyAnnotationChanged
299+
old := rg.DeepCopy()
300+
rg.Status.Conditions[0].ObservedGeneration = -1
301+
tc.PatchStatus(old, rg)
302+
}
303+
304+
// Update to skip reconcile
218305
old := rg.DeepCopy()
219-
rg.Status.Conditions[0].ObservedGeneration = -1
220-
tc.PatchStatus(old, rg)
306+
rg.Annotations["serviceoperator.azure.com/reconcile-policy"] = opts.policy
307+
tc.Patch(old, rg)
308+
// TODO: There may still be a race here where delete in the operator code gets the old cached value without the policy in the detach-on-delete case,
309+
// TODO: since there is no reconcile after the annotation patch (see HasReconcilePolicyAnnotationChanged), so this eventually finishes quickly.
310+
tc.Eventually(rg).Should(tc.Match.BeProvisioned(-1))
311+
} else {
312+
// Update the namespace to skip reconcile
313+
ns := &corev1.Namespace{}
314+
tc.GetResource(client.ObjectKey{Name: tc.Namespace}, ns)
315+
oldNS := ns.DeepCopy()
316+
ns.Annotations = make(map[string]string)
317+
ns.Annotations["serviceoperator.azure.com/reconcile-policy"] = opts.policy
318+
tc.Patch(oldNS, ns)
221319
}
222320

223-
// Update to skip reconcile
224-
old := rg.DeepCopy()
225-
rg.Annotations["serviceoperator.azure.com/reconcile-policy"] = policy
226-
tc.Patch(old, rg)
227-
// TODO: There may still be a race here where delete in the operator code gets the old cached value without the policy in the detach-on-delete case,
228-
// TODO: since there is no reconcile after the annotation patch (see HasReconcilePolicyAnnotationChanged), so this eventually finishes quickly.
229-
tc.Eventually(rg).Should(tc.Match.BeProvisioned(-1))
230-
231321
tc.DeleteResourceAndWait(rg)
232322

233323
// Ensure that the resource group was NOT deleted in Azure
@@ -247,6 +337,16 @@ func testDeleteSkipped(t *testing.T, policy string) {
247337
Spec: rg.Spec,
248338
}
249339
tc.CreateResourceAndWait(newRG)
340+
341+
if opts.onNamespace {
342+
// Remove skip reconcile annotation from the namespace
343+
ns := &corev1.Namespace{}
344+
tc.GetResource(client.ObjectKey{Name: tc.Namespace}, ns)
345+
oldNS := ns.DeepCopy()
346+
delete(ns.Annotations, "serviceoperator.azure.com/reconcile-policy")
347+
tc.Patch(oldNS, ns)
348+
}
349+
250350
// Delete it
251351
tc.DeleteResourceAndWait(newRG)
252352

0 commit comments

Comments
 (0)