Skip to content

Commit 304deb6

Browse files
committed
Add e2e-tests for applying crd and cr at the same time
1 parent a85e842 commit 304deb6

File tree

5 files changed

+322
-19
lines changed

5 files changed

+322
-19
lines changed

test/e2e/apply_and_destroy_test.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,8 @@ func applyAndDestroyTest(c client.Client, inventoryName, namespaceName string) {
6767

6868
By("Destroy resources")
6969
destroyer := newDestroyer()
70-
err = destroyer.Initialize()
71-
Expect(err).NotTo(HaveOccurred())
7270

73-
destroyCh := destroyer.Run(inv)
74-
75-
var destroyerEvents []event.Event
76-
for e := range destroyCh {
77-
Expect(e.Type).NotTo(Equal(event.ErrorType))
78-
destroyerEvents = append(destroyerEvents, e)
79-
}
71+
destroyerEvents := runCollectNoErr(destroyer.Run(inv))
8072
err = verifyEvents([]expEvent{
8173
{
8274
eventType: event.DeleteType,

test/e2e/common_test.go

Lines changed: 120 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"k8s.io/apimachinery/pkg/runtime"
1515
"sigs.k8s.io/cli-utils/pkg/apply/event"
1616
"sigs.k8s.io/cli-utils/pkg/common"
17+
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
1718
"sigs.k8s.io/cli-utils/pkg/object"
1819
)
1920

@@ -100,7 +101,10 @@ func updateReplicas(u *unstructured.Unstructured, replicas int) *unstructured.Un
100101
type expEvent struct {
101102
eventType event.Type
102103

103-
applyEvent *expApplyEvent
104+
applyEvent *expApplyEvent
105+
statusEvent *expStatusEvent
106+
pruneEvent *expPruneEvent
107+
deleteEvent *expDeleteEvent
104108
}
105109

106110
type expApplyEvent struct {
@@ -110,6 +114,27 @@ type expApplyEvent struct {
110114
error error
111115
}
112116

117+
type expStatusEvent struct {
118+
statusEventType event.StatusEventType
119+
identifier object.ObjMetadata
120+
status status.Status
121+
error error
122+
}
123+
124+
type expPruneEvent struct {
125+
pruneEventType event.PruneEventType
126+
operation event.PruneEventOperation
127+
identifier object.ObjMetadata
128+
error error
129+
}
130+
131+
type expDeleteEvent struct {
132+
deleteEventType event.DeleteEventType
133+
operation event.DeleteEventOperation
134+
identifier object.ObjMetadata
135+
error error
136+
}
137+
113138
func verifyEvents(expEvents []expEvent, events []event.Event) error {
114139
expEventIndex := 0
115140
for i := range events {
@@ -127,6 +152,10 @@ func verifyEvents(expEvents []expEvent, events []event.Event) error {
127152

128153
var nilIdentifier = object.ObjMetadata{}
129154

155+
// nolint:gocyclo
156+
// TODO(mortent): This function is pretty complex and with quite a bit of
157+
// duplication. We should see if there is a better way to provide a flexible
158+
// way to verify that we go the expected events.
130159
func isMatch(ee expEvent, e event.Event) bool {
131160
if ee.eventType != e.Type {
132161
return false
@@ -136,6 +165,7 @@ func isMatch(ee expEvent, e event.Event) bool {
136165
switch e.Type {
137166
case event.ApplyType:
138167
aee := ee.applyEvent
168+
// If no more information is specified, we consider it a match.
139169
if aee == nil {
140170
return true
141171
}
@@ -146,13 +176,13 @@ func isMatch(ee expEvent, e event.Event) bool {
146176
}
147177

148178
if aee.applyEventType == event.ApplyEventResourceUpdate {
149-
if aee.operation != ae.Operation {
150-
return false
179+
if aee.identifier != nilIdentifier {
180+
if aee.identifier != ae.Identifier {
181+
return false
182+
}
151183
}
152-
}
153184

154-
if aee.identifier != nilIdentifier {
155-
if aee.identifier != ae.Identifier {
185+
if aee.operation != ae.Operation {
156186
return false
157187
}
158188
}
@@ -161,6 +191,90 @@ func isMatch(ee expEvent, e event.Event) bool {
161191
return ae.Error != nil
162192
}
163193
return ae.Error == nil
194+
195+
case event.StatusType:
196+
see := ee.statusEvent
197+
if see == nil {
198+
return true
199+
}
200+
se := e.StatusEvent
201+
202+
if see.statusEventType != se.Type {
203+
return false
204+
}
205+
206+
if see.statusEventType == event.StatusEventResourceUpdate {
207+
if see.identifier != nilIdentifier {
208+
if see.identifier != se.Resource.Identifier {
209+
return false
210+
}
211+
}
212+
213+
if see.status != se.Resource.Status {
214+
return false
215+
}
216+
217+
if see.error != nil {
218+
return se.Resource.Error != nil
219+
}
220+
return se.Resource.Error == nil
221+
}
222+
223+
case event.PruneType:
224+
pee := ee.pruneEvent
225+
if pee == nil {
226+
return true
227+
}
228+
pe := e.PruneEvent
229+
230+
if pee.pruneEventType != pe.Type {
231+
return false
232+
}
233+
234+
if pee.pruneEventType == event.PruneEventResourceUpdate {
235+
if pee.identifier != nilIdentifier {
236+
if pee.identifier != pe.Identifier {
237+
return false
238+
}
239+
}
240+
241+
if pee.operation != pe.Operation {
242+
return false
243+
}
244+
}
245+
246+
if pee.error != nil {
247+
return pe.Error != nil
248+
}
249+
return pe.Error == nil
250+
251+
case event.DeleteType:
252+
dee := ee.deleteEvent
253+
if dee == nil {
254+
return true
255+
}
256+
de := e.DeleteEvent
257+
258+
if dee.deleteEventType != de.Type {
259+
return false
260+
}
261+
262+
if dee.deleteEventType == event.DeleteEventResourceUpdate {
263+
if dee.identifier != nilIdentifier {
264+
if dee.identifier != de.Identifier {
265+
return false
266+
}
267+
}
268+
269+
if dee.operation != de.Operation {
270+
return false
271+
}
272+
}
273+
274+
if dee.error != nil {
275+
return de.Error != nil
276+
}
277+
return de.Error == nil
164278
}
165279
return true
166280
}

test/e2e/crd_test.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// Copyright 2020 The Kubernetes Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package e2e
5+
6+
import (
7+
"context"
8+
"strings"
9+
"time"
10+
11+
. "github.com/onsi/ginkgo"
12+
. "github.com/onsi/gomega"
13+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
14+
"sigs.k8s.io/cli-utils/pkg/apply"
15+
"sigs.k8s.io/cli-utils/pkg/apply/event"
16+
"sigs.k8s.io/cli-utils/pkg/inventory"
17+
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
18+
"sigs.k8s.io/cli-utils/pkg/object"
19+
"sigs.k8s.io/controller-runtime/pkg/client"
20+
"sigs.k8s.io/kustomize/kyaml/yaml"
21+
)
22+
23+
func crdTest(_ client.Client, inventoryName, namespaceName string) {
24+
By("apply a set of resources that includes both a crd and a cr")
25+
applier := newApplier()
26+
27+
inv := inventory.WrapInventoryInfoObj(cmInventoryManifest(inventoryName, namespaceName, "test"))
28+
29+
resources := []*unstructured.Unstructured{
30+
deploymentManifest(namespaceName),
31+
manifestToUnstructured(cr),
32+
manifestToUnstructured(crd),
33+
}
34+
35+
ch := applier.Run(context.TODO(), inv, resources, apply.Options{
36+
ReconcileTimeout: 2 * time.Minute,
37+
EmitStatusEvents: true,
38+
})
39+
40+
var applierEvents []event.Event
41+
for e := range ch {
42+
Expect(e.Type).NotTo(Equal(event.ErrorType))
43+
applierEvents = append(applierEvents, e)
44+
}
45+
err := verifyEvents([]expEvent{
46+
{
47+
eventType: event.ApplyType,
48+
applyEvent: &expApplyEvent{
49+
applyEventType: event.ApplyEventResourceUpdate,
50+
operation: event.Created,
51+
identifier: object.UnstructuredToObjMeta(manifestToUnstructured(crd)),
52+
error: nil,
53+
},
54+
},
55+
{
56+
eventType: event.StatusType,
57+
statusEvent: &expStatusEvent{
58+
statusEventType: event.StatusEventResourceUpdate,
59+
identifier: object.UnstructuredToObjMeta(manifestToUnstructured(crd)),
60+
status: status.CurrentStatus,
61+
error: nil,
62+
},
63+
},
64+
{
65+
eventType: event.ApplyType,
66+
applyEvent: &expApplyEvent{
67+
applyEventType: event.ApplyEventResourceUpdate,
68+
operation: event.Created,
69+
},
70+
},
71+
{
72+
eventType: event.ApplyType,
73+
applyEvent: &expApplyEvent{
74+
applyEventType: event.ApplyEventResourceUpdate,
75+
operation: event.Created,
76+
},
77+
},
78+
}, applierEvents)
79+
Expect(err).ToNot(HaveOccurred())
80+
81+
By("destroy the resources, including the crd")
82+
destroyer := newDestroyer()
83+
destroyerEvents := runCollectNoErr(destroyer.Run(inv))
84+
err = verifyEvents([]expEvent{
85+
{
86+
eventType: event.DeleteType,
87+
deleteEvent: &expDeleteEvent{
88+
deleteEventType: event.DeleteEventResourceUpdate,
89+
operation: event.Deleted,
90+
error: nil,
91+
},
92+
},
93+
{
94+
eventType: event.DeleteType,
95+
deleteEvent: &expDeleteEvent{
96+
deleteEventType: event.DeleteEventResourceUpdate,
97+
operation: event.Deleted,
98+
error: nil,
99+
},
100+
},
101+
{
102+
eventType: event.DeleteType,
103+
deleteEvent: &expDeleteEvent{
104+
deleteEventType: event.DeleteEventResourceUpdate,
105+
operation: event.Deleted,
106+
// TODO(mortent): The identifier isn't populated in the Delete
107+
// events. This should be fixed.
108+
// identifier: object.UnstructuredToObjMeta(manifestToUnstructured(crd)),
109+
error: nil,
110+
},
111+
},
112+
}, destroyerEvents)
113+
Expect(err).ToNot(HaveOccurred())
114+
}
115+
116+
var crd = []byte(strings.TrimSpace(`
117+
apiVersion: apiextensions.k8s.io/v1
118+
kind: CustomResourceDefinition
119+
metadata:
120+
name: examples.cli-utils.example.io
121+
spec:
122+
conversion:
123+
strategy: None
124+
group: cli-utils.example.io
125+
names:
126+
kind: Example
127+
listKind: ExampleList
128+
plural: examples
129+
singular: example
130+
scope: Cluster
131+
versions:
132+
- name: v1alpha1
133+
schema:
134+
openAPIV3Schema:
135+
description: Example for cli-utils e2e tests
136+
properties:
137+
apiVersion:
138+
type: string
139+
kind:
140+
type: string
141+
metadata:
142+
type: object
143+
spec:
144+
description: Example for cli-utils e2e tests
145+
properties:
146+
replicas:
147+
description: Number of replicas
148+
type: integer
149+
required:
150+
- replicas
151+
type: object
152+
type: object
153+
served: true
154+
storage: true
155+
subresources: {}
156+
`))
157+
158+
var cr = []byte(strings.TrimSpace(`
159+
apiVersion: cli-utils.example.io/v1alpha1
160+
kind: Example
161+
metadata:
162+
name: example-cr
163+
spec:
164+
replicas: 4
165+
`))
166+
167+
func manifestToUnstructured(manifest []byte) *unstructured.Unstructured {
168+
u := make(map[string]interface{})
169+
err := yaml.Unmarshal(manifest, &u)
170+
if err != nil {
171+
panic(err)
172+
}
173+
return &unstructured.Unstructured{
174+
Object: u,
175+
}
176+
}

0 commit comments

Comments
 (0)