Skip to content

Commit 4a1ccf7

Browse files
committed
e2e: validate decomposing usage
Signed-off-by: Hasan Turken <[email protected]>
1 parent 6244e03 commit 4a1ccf7

File tree

8 files changed

+386
-0
lines changed

8 files changed

+386
-0
lines changed

internal/controller/apiextensions/usage/reconciler_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ func TestReconcile(t *testing.T) {
533533
MockGet: test.NewMockGetFn(nil, func(obj client.Object) error {
534534
if o, ok := obj.(*v1alpha1.Usage); ok {
535535
o.SetDeletionTimestamp(&now)
536+
o.SetLabels(map[string]string{xcrd.LabelKeyNamePrefixForComposed: "some-composite"})
536537
o.Spec.Of.ResourceRef = &v1alpha1.ResourceRef{Name: "used"}
537538
o.Spec.By = &v1alpha1.Resource{
538539
APIVersion: "v1",
@@ -565,6 +566,47 @@ func TestReconcile(t *testing.T) {
565566
err: errors.Wrap(errBoom, errGetUsing),
566567
},
567568
},
569+
"ShouldNotGetUsingOnDeleteIfNotComposed": {
570+
reason: "We should not get using resource on delete if the usage is not composed.",
571+
args: args{
572+
mgr: &fake.Manager{},
573+
opts: []ReconcilerOption{
574+
WithClientApplicator(xpresource.ClientApplicator{
575+
Client: &test.MockClient{
576+
MockGet: test.NewMockGetFn(nil, func(obj client.Object) error {
577+
if o, ok := obj.(*v1alpha1.Usage); ok {
578+
o.SetDeletionTimestamp(&now)
579+
o.Spec.Of.ResourceRef = &v1alpha1.ResourceRef{Name: "used"}
580+
o.Spec.By = &v1alpha1.Resource{
581+
APIVersion: "v1",
582+
Kind: "AnotherKind",
583+
ResourceRef: &v1alpha1.ResourceRef{Name: "using"},
584+
}
585+
return nil
586+
}
587+
if o, ok := obj.(*composed.Unstructured); ok {
588+
if o.GetName() == "using" {
589+
return errors.New("unexpected call, should not get using resource")
590+
}
591+
return nil
592+
}
593+
return errors.New("unexpected object type")
594+
}),
595+
MockList: test.NewMockListFn(nil),
596+
MockUpdate: test.NewMockUpdateFn(nil),
597+
},
598+
}),
599+
WithSelectorResolver(fakeSelectorResolver{
600+
resourceSelectorFn: func(_ context.Context, _ *v1alpha1.Usage) error {
601+
return nil
602+
},
603+
}),
604+
WithFinalizer(xpresource.FinalizerFns{RemoveFinalizerFn: func(_ context.Context, _ xpresource.Object) error {
605+
return nil
606+
}}),
607+
},
608+
},
609+
},
568610
"CannotListUsagesOnDelete": {
569611
reason: "We should return an error if we cannot list usages on delete.",
570612
args: args{
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: nop.example.org/v1alpha1
2+
kind: NopResource
3+
metadata:
4+
namespace: default
5+
name: test
6+
spec:
7+
coolField: "I'm cool!"
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
apiVersion: apiextensions.crossplane.io/v1
2+
kind: Composition
3+
metadata:
4+
name: xnopresources.nop.example.org
5+
spec:
6+
compositeTypeRef:
7+
apiVersion: nop.example.org/v1alpha1
8+
kind: XNopResource
9+
mode: Pipeline
10+
pipeline:
11+
- step: be-a-dummy
12+
functionRef:
13+
name: function-dummy
14+
input:
15+
apiVersion: dummy.fn.crossplane.io/v1beta1
16+
kind: Response
17+
# This is a YAML-serialized RunFunctionResponse. function-dummy will
18+
# overlay the desired state on any that was passed into it.
19+
response:
20+
desired:
21+
composite:
22+
resource:
23+
status:
24+
coolerField: "I'M COOLER!"
25+
resources:
26+
used-resource:
27+
resource:
28+
apiVersion: nop.crossplane.io/v1alpha1
29+
kind: NopResource
30+
metadata:
31+
labels:
32+
usage: used
33+
spec:
34+
forProvider:
35+
conditionAfter:
36+
- conditionType: "Synced"
37+
conditionStatus: "True"
38+
time: "5s"
39+
- conditionType: "Ready"
40+
conditionStatus: "True"
41+
time: "10s"
42+
using-resource:
43+
resource:
44+
apiVersion: nop.crossplane.io/v1alpha1
45+
kind: NopResource
46+
metadata:
47+
# We are delaying deletion of using resource with this finalizer. This is to ensure that the used resource is
48+
# not deleted before the using resource. Imagine a scenario where a Release resource using a Cluster resource
49+
# where we expect the Cluster resource not to be deleted until the Release resource is deleted. We are mimicking
50+
# this behavior with the help of a finalizer on a NopResource.
51+
finalizers:
52+
- delay-deletion-of-using-resource
53+
labels:
54+
usage: using
55+
spec:
56+
forProvider:
57+
conditionAfter:
58+
- conditionType: "Synced"
59+
conditionStatus: "True"
60+
time: "5s"
61+
- conditionType: "Ready"
62+
conditionStatus: "True"
63+
time: "10s"
64+
usage-resource-updated:
65+
resource:
66+
apiVersion: apiextensions.crossplane.io/v1alpha1
67+
kind: Usage
68+
metadata:
69+
labels:
70+
version: updated
71+
spec:
72+
replayDeletion: true
73+
of:
74+
apiVersion: nop.crossplane.io/v1alpha1
75+
kind: NopResource
76+
resourceSelector:
77+
matchControllerRef: true
78+
matchLabels:
79+
usage: used
80+
by:
81+
apiVersion: nop.crossplane.io/v1alpha1
82+
kind: NopResource
83+
resourceSelector:
84+
matchControllerRef: true
85+
matchLabels:
86+
usage: using
87+
results:
88+
- severity: SEVERITY_NORMAL
89+
message: "I am doing a compose!"
90+
- step: detect-readiness
91+
functionRef:
92+
name: function-auto-ready
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
apiVersion: apiextensions.crossplane.io/v1
2+
kind: Composition
3+
metadata:
4+
name: xnopresources.nop.example.org
5+
spec:
6+
compositeTypeRef:
7+
apiVersion: nop.example.org/v1alpha1
8+
kind: XNopResource
9+
mode: Pipeline
10+
pipeline:
11+
- step: be-a-dummy
12+
functionRef:
13+
name: function-dummy
14+
input:
15+
apiVersion: dummy.fn.crossplane.io/v1beta1
16+
kind: Response
17+
# This is a YAML-serialized RunFunctionResponse. function-dummy will
18+
# overlay the desired state on any that was passed into it.
19+
response:
20+
desired:
21+
resources:
22+
used-resource:
23+
resource:
24+
apiVersion: nop.crossplane.io/v1alpha1
25+
kind: NopResource
26+
metadata:
27+
labels:
28+
usage: used
29+
spec:
30+
forProvider:
31+
conditionAfter:
32+
- conditionType: "Synced"
33+
conditionStatus: "True"
34+
time: "5s"
35+
- conditionType: "Ready"
36+
conditionStatus: "True"
37+
time: "10s"
38+
using-resource:
39+
resource:
40+
apiVersion: nop.crossplane.io/v1alpha1
41+
kind: NopResource
42+
metadata:
43+
# We are delaying deletion of using resource with this finalizer. This is to ensure that the used resource is
44+
# not deleted before the using resource. Imagine a scenario where a Release resource using a Cluster resource
45+
# where we expect the Cluster resource not to be deleted until the Release resource is deleted. We are mimicking
46+
# this behavior with the help of a finalizer on a NopResource.
47+
finalizers:
48+
- delay-deletion-of-using-resource
49+
labels:
50+
usage: using
51+
spec:
52+
forProvider:
53+
conditionAfter:
54+
- conditionType: "Synced"
55+
conditionStatus: "True"
56+
time: "5s"
57+
- conditionType: "Ready"
58+
conditionStatus: "True"
59+
time: "10s"
60+
usage-resource:
61+
resource:
62+
apiVersion: apiextensions.crossplane.io/v1alpha1
63+
kind: Usage
64+
metadata:
65+
labels:
66+
version: initial
67+
spec:
68+
of:
69+
apiVersion: nop.crossplane.io/v1alpha1
70+
kind: NopResource
71+
resourceSelector:
72+
matchControllerRef: true
73+
matchLabels:
74+
usage: used
75+
by:
76+
apiVersion: nop.crossplane.io/v1alpha1
77+
kind: NopResource
78+
resourceSelector:
79+
matchControllerRef: true
80+
matchLabels:
81+
usage: using
82+
results:
83+
- severity: SEVERITY_NORMAL
84+
message: "I am doing a compose!"
85+
- step: detect-readiness
86+
functionRef:
87+
name: function-auto-ready
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
apiVersion: apiextensions.crossplane.io/v1
2+
kind: CompositeResourceDefinition
3+
metadata:
4+
name: xnopresources.nop.example.org
5+
spec:
6+
group: nop.example.org
7+
names:
8+
kind: XNopResource
9+
plural: xnopresources
10+
claimNames:
11+
kind: NopResource
12+
plural: nopresources
13+
connectionSecretKeys:
14+
- test
15+
versions:
16+
- name: v1alpha1
17+
served: true
18+
referenceable: true
19+
schema:
20+
openAPIV3Schema:
21+
type: object
22+
properties:
23+
spec:
24+
type: object
25+
properties:
26+
coolField:
27+
type: string
28+
required:
29+
- coolField
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
# We intentionally use v1beta1 here, to make sure it still works.
3+
apiVersion: pkg.crossplane.io/v1beta1
4+
kind: Function
5+
metadata:
6+
name: function-dummy
7+
spec:
8+
# NOTE(negz): This is currently manually pushed. See README.md at
9+
# https://github.com/crossplane-contrib/function-dummy.
10+
# NOTE(negz): This version of the function uses meta.pkg.crossplane.io/v1beta1
11+
# and is built with an old SDK that only serves v1beta1 RPCs. This is
12+
# intentional. We want to make sure Crossplane is backward compatible with
13+
# older v1beta1 functions.
14+
package: xpkg.upbound.io/crossplane-contrib/function-dummy:v0.2.1
15+
---
16+
apiVersion: pkg.crossplane.io/v1
17+
kind: Function
18+
metadata:
19+
name: function-auto-ready
20+
spec:
21+
# TODO(negz): This function should use meta.pkg.crossplane.io/v1 metadata.
22+
# It supports the new v1 RPCs but it can't be built using v1 metadata until
23+
# https://github.com/crossplane/crossplane/issues/5971 is fixed.
24+
package: xpkg.upbound.io/crossplane-contrib/function-auto-ready:v0.3.0
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: pkg.crossplane.io/v1
2+
kind: Provider
3+
metadata:
4+
name: provider-nop
5+
spec:
6+
package: xpkg.upbound.io/crossplane-contrib/provider-nop:v0.3.0
7+
ignoreCrossplaneConstraints: true

0 commit comments

Comments
 (0)