Skip to content

Commit 4983152

Browse files
committed
split inventory and resources in the apply interface
1 parent 79dde05 commit 4983152

File tree

11 files changed

+71
-50
lines changed

11 files changed

+71
-50
lines changed

cmd/apply/cmdapply.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"sigs.k8s.io/cli-utils/cmd/printers"
1818
"sigs.k8s.io/cli-utils/pkg/apply"
1919
"sigs.k8s.io/cli-utils/pkg/common"
20+
"sigs.k8s.io/cli-utils/pkg/inventory"
2021
"sigs.k8s.io/cli-utils/pkg/provider"
2122
"sigs.k8s.io/kustomize/kyaml/setters2"
2223
)
@@ -110,13 +111,17 @@ func (r *ApplyRunner) RunE(cmd *cobra.Command, args []string) error {
110111
if err != nil {
111112
return err
112113
}
114+
inv, objs, err := inventory.SplitUnstructureds(objs)
115+
if err != nil {
116+
return err
117+
}
113118

114119
// Run the applier. It will return a channel where we can receive updates
115120
// to keep track of progress and any issues.
116121
if err := r.Applier.Initialize(); err != nil {
117122
return err
118123
}
119-
ch := r.Applier.Run(context.Background(), objs, apply.Options{
124+
ch := r.Applier.Run(context.Background(), inv, objs, apply.Options{
120125
ServerSideOptions: r.serverSideOptions,
121126
PollInterval: r.period,
122127
ReconcileTimeout: r.reconcileTimeout,

cmd/preview/cmdpreview.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ func (r *PreviewRunner) RunE(cmd *cobra.Command, args []string) error {
100100
if err != nil {
101101
return err
102102
}
103+
inv, objs, err := inventory.SplitUnstructureds(objs)
104+
if err != nil {
105+
return err
106+
}
103107

104108
// if destroy flag is set in preview, transmit it to destroyer DryRunStrategy flag
105109
// and pivot execution to destroy with dry-run
@@ -119,17 +123,13 @@ func (r *PreviewRunner) RunE(cmd *cobra.Command, args []string) error {
119123

120124
// Run the applier. It will return a channel where we can receive updates
121125
// to keep track of progress and any issues.
122-
ch = r.Applier.Run(ctx, objs, apply.Options{
126+
ch = r.Applier.Run(ctx, inv, objs, apply.Options{
123127
EmitStatusEvents: false,
124128
NoPrune: noPrune,
125129
DryRunStrategy: drs,
126130
ServerSideOptions: r.serverSideOptions,
127131
})
128132
} else {
129-
inv, _, err := inventory.SplitUnstructureds(objs)
130-
if err != nil {
131-
return err
132-
}
133133
err = r.Destroyer.Initialize()
134134
if err != nil {
135135
return err

pkg/apply/applier.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package apply
55

66
import (
77
"context"
8+
"fmt"
89
"sort"
910
"time"
1011

@@ -87,15 +88,16 @@ func (a *Applier) Initialize() error {
8788
// calculates the set of objects to be pruned (pruneIds), and orders the
8889
// resources for the subsequent apply. Returns the sorted resources to
8990
// apply as well as the objects for the prune, or an error if one occurred.
90-
func (a *Applier) prepareObjects(objs []*unstructured.Unstructured) (*ResourceObjects, error) {
91-
localInv, localObjs, err := inventory.SplitUnstructureds(objs)
92-
if err != nil {
91+
func (a *Applier) prepareObjects(localInv *unstructured.Unstructured, localObjs []*unstructured.Unstructured) (*ResourceObjects, error) {
92+
if localInv == nil {
93+
return nil, fmt.Errorf("the local inventory can't be nil")
94+
}
95+
if err := inventory.ValidateNoInventory(localObjs); err != nil {
9396
return nil, err
9497
}
95-
9698
// Ensures the namespace exists before applying the inventory object into it.
9799
if invNamespace := inventoryNamespaceInSet(localInv, localObjs); invNamespace != nil {
98-
if err = a.invClient.ApplyInventoryNamespace(invNamespace); err != nil {
100+
if err := a.invClient.ApplyInventoryNamespace(invNamespace); err != nil {
99101
return nil, err
100102
}
101103
}
@@ -128,15 +130,16 @@ type ResourceObjects struct {
128130
PruneIds []object.ObjMetadata
129131
}
130132

131-
// InfosForApply returns the infos representation for all the resources
132-
// that should be applied, including the inventory object. The
133+
// ObjsForApply returns the unstructured representation for all the resources
134+
// that should be applied, not including the inventory object. The
133135
// resources will be in sorted order.
134136
func (r *ResourceObjects) ObjsForApply() []*unstructured.Unstructured {
135137
return r.Resources
136138
}
137139

138-
func (r *ResourceObjects) ObjsForPrune() []*unstructured.Unstructured {
139-
return append([]*unstructured.Unstructured{r.LocalInv}, r.Resources...)
140+
// Inventory returns the unstructured representation of the inventory object.
141+
func (r *ResourceObjects) Inventory() *unstructured.Unstructured {
142+
return r.LocalInv
140143
}
141144

142145
// IdsForApply returns the Ids for all resources that should be applied,
@@ -169,7 +172,7 @@ func (r *ResourceObjects) AllIds() []object.ObjMetadata {
169172
// before all the given resources have been applied to the cluster. Any
170173
// cancellation or timeout will only affect how long we Wait for the
171174
// resources to become current.
172-
func (a *Applier) Run(ctx context.Context, objects []*unstructured.Unstructured, options Options) <-chan event.Event {
175+
func (a *Applier) Run(ctx context.Context, inventory *unstructured.Unstructured, objects []*unstructured.Unstructured, options Options) <-chan event.Event {
173176
eventChannel := make(chan event.Event)
174177
setDefaults(&options)
175178
a.invClient.SetDryRunStrategy(options.DryRunStrategy) // client shared with prune, so sets dry-run for prune too.
@@ -179,7 +182,7 @@ func (a *Applier) Run(ctx context.Context, objects []*unstructured.Unstructured,
179182
// This provides us with a slice of all the objects that will be
180183
// applied to the cluster. This takes care of ordering resources
181184
// and handling the inventory object.
182-
resourceObjects, err := a.prepareObjects(objects)
185+
resourceObjects, err := a.prepareObjects(inventory, objects)
183186
if err != nil {
184187
handleError(eventChannel, err)
185188
return

pkg/apply/applier_test.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ func TestApplier(t *testing.T) {
204204

205205
for tn, tc := range testCases {
206206
t.Run(tn, func(t *testing.T) {
207-
infos, err := createObjs(tc.resources)
207+
inv, infos, err := createObjs(tc.resources)
208208
assert.NoError(t, err)
209209

210210
tf := cmdtesting.NewTestFactory().WithNamespace(tc.namespace)
@@ -231,7 +231,7 @@ func TestApplier(t *testing.T) {
231231
applier.StatusPoller = poller
232232

233233
ctx := context.Background()
234-
eventChannel := applier.Run(ctx, infos, Options{
234+
eventChannel := applier.Run(ctx, inv, infos, Options{
235235
ReconcileTimeout: tc.reconcileTimeout,
236236
EmitStatusEvents: true,
237237
NoPrune: !tc.prune,
@@ -387,6 +387,8 @@ func TestInventoryNamespaceInSet(t *testing.T) {
387387

388388
func TestReadAndPrepareObjects(t *testing.T) {
389389
testCases := map[string]struct {
390+
// local inventory input into applier.prepareObjects
391+
inventory *unstructured.Unstructured
390392
// locally read resources input into applier.prepareObjects
391393
resources []*unstructured.Unstructured
392394
// objects already stored in the cluster inventory
@@ -405,40 +407,41 @@ func TestReadAndPrepareObjects(t *testing.T) {
405407
isError: true,
406408
},
407409
"multiple inventory objects": {
408-
resources: []*unstructured.Unstructured{inventoryObj, inventoryObj},
410+
inventory: inventoryObj,
411+
resources: []*unstructured.Unstructured{inventoryObj},
409412
isError: true,
410413
},
411414
"only inventory object": {
412-
resources: []*unstructured.Unstructured{inventoryObj},
415+
inventory: inventoryObj,
413416
localInv: inventoryObj,
414417
isError: false,
415418
},
416419
"only inventory object, prune one object": {
417-
resources: []*unstructured.Unstructured{inventoryObj},
420+
inventory: inventoryObj,
418421
clusterObjs: []*unstructured.Unstructured{obj1},
419422
localInv: inventoryObj,
420423
pruneObjs: []*unstructured.Unstructured{obj1},
421424
isError: false,
422425
},
423426
"inventory object already at the beginning": {
424-
resources: []*unstructured.Unstructured{inventoryObj, obj1,
425-
clusterScopedObj},
427+
inventory: inventoryObj,
428+
resources: []*unstructured.Unstructured{obj1, clusterScopedObj},
426429
localInv: inventoryObj,
427430
localObjs: []*unstructured.Unstructured{obj1, clusterScopedObj},
428431
isError: false,
429432
},
430433
"inventory object already at the beginning, prune one": {
431-
resources: []*unstructured.Unstructured{inventoryObj, obj1,
432-
clusterScopedObj},
434+
inventory: inventoryObj,
435+
resources: []*unstructured.Unstructured{obj1, clusterScopedObj},
433436
clusterObjs: []*unstructured.Unstructured{obj2},
434437
localInv: inventoryObj,
435438
localObjs: []*unstructured.Unstructured{obj1, clusterScopedObj},
436439
pruneObjs: []*unstructured.Unstructured{obj2},
437440
isError: false,
438441
},
439442
"inventory object not at the beginning": {
440-
resources: []*unstructured.Unstructured{obj1, obj2, inventoryObj,
441-
clusterScopedObj},
443+
inventory: inventoryObj,
444+
resources: []*unstructured.Unstructured{obj1, obj2, clusterScopedObj},
442445
clusterObjs: []*unstructured.Unstructured{obj2},
443446
localInv: inventoryObj,
444447
localObjs: []*unstructured.Unstructured{obj1, obj2, clusterScopedObj},
@@ -454,7 +457,7 @@ func TestReadAndPrepareObjects(t *testing.T) {
454457
fakeInvClient := inventory.NewFakeInventoryClient(clusterObjs)
455458
// Create applier with fake inventory client, and call prepareObjects
456459
applier := &Applier{invClient: fakeInvClient}
457-
resourceObjs, err := applier.prepareObjects(tc.resources)
460+
resourceObjs, err := applier.prepareObjects(tc.inventory, tc.resources)
458461
if !tc.isError && err != nil {
459462
t.Fatalf("unexpected error received: %s", err)
460463
}
@@ -533,17 +536,17 @@ func toIdentifier(t *testing.T, resourceInfo resourceInfo, namespace string) obj
533536
}
534537
}
535538

536-
func createObjs(resources []resourceInfo) ([]*unstructured.Unstructured, error) {
539+
func createObjs(resources []resourceInfo) (*unstructured.Unstructured, []*unstructured.Unstructured, error) {
537540
var objs []*unstructured.Unstructured
538541
for _, ri := range resources {
539542
u := &unstructured.Unstructured{}
540543
err := runtime.DecodeInto(codec, []byte(ri.manifest), u)
541544
if err != nil {
542-
return nil, err
545+
return nil, nil, err
543546
}
544547
objs = append(objs, u)
545548
}
546-
return objs, nil
549+
return inventory.SplitUnstructureds(objs)
547550
}
548551

549552
// The handler interface allows different testcases to provide

pkg/apply/destroyer.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,12 @@ func (d *Destroyer) Run(inv *unstructured.Unstructured) <-chan event.Event {
6666
defer close(ch)
6767
d.invClient.SetDryRunStrategy(d.DryRunStrategy)
6868

69-
// Force a pruning of all cluster resources by clearing out the
70-
// local resources, and sending only the inventory object to the
71-
// prune.
72-
invs := []*unstructured.Unstructured{inv}
73-
7469
// Start the event transformer goroutine so we can transform
7570
// the Prune events emitted from the Prune function to Delete
7671
// Events. That we use Prune to implement destroy is an
7772
// implementation detail and the events should not be Prune events.
7873
tempChannel, completedChannel := runPruneEventTransformer(ch)
79-
err := d.PruneOptions.Prune(invs, sets.NewString(), tempChannel, prune.Options{
74+
err := d.PruneOptions.Prune(inv, nil, sets.NewString(), tempChannel, prune.Options{
8075
DryRunStrategy: d.DryRunStrategy,
8176
PropagationPolicy: metav1.DeletePropagationBackground,
8277
})

pkg/apply/prune/prune.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,8 @@ type Options struct {
8080
// (retrieved from previous inventory objects) but omitted in
8181
// the current apply. Prune also delete all previous inventory
8282
// objects. Returns an error if there was a problem.
83-
func (po *PruneOptions) Prune(localObjs []*unstructured.Unstructured, currentUIDs sets.String,
83+
func (po *PruneOptions) Prune(localInv *unstructured.Unstructured, localObjs []*unstructured.Unstructured, currentUIDs sets.String,
8484
eventChannel chan<- event.Event, o Options) error {
85-
localInv, localObjs, err := inventory.SplitUnstructureds(localObjs)
86-
if err != nil {
87-
return err
88-
}
8985
invNamespace := localInv.GetNamespace()
9086
klog.V(4).Infof("prune local inventory object: %s/%s", invNamespace, localInv.GetName())
9187
clusterObjs, err := po.InvClient.GetClusterObjs(localInv)

pkg/apply/prune/prune_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ func TestPrune(t *testing.T) {
161161
po.InvClient = inventory.NewFakeInventoryClient(clusterObjs)
162162
// Set up the currently applied objects.
163163
currentInventory := createInventoryInfo(tc.currentObjs...)
164-
currentObjs := append(tc.currentObjs, currentInventory)
165164
// Set up the fake dynamic client to recognize all objects, and the RESTMapper.
166165
po.client = fake.NewSimpleDynamicClient(scheme.Scheme,
167166
namespace, pdb, role)
@@ -173,7 +172,7 @@ func TestPrune(t *testing.T) {
173172
err := func() error {
174173
defer close(eventChannel)
175174
// Run the prune and validate.
176-
return po.Prune(currentObjs, populateObjectIds(tc.currentObjs, t), eventChannel, Options{
175+
return po.Prune(currentInventory, tc.currentObjs, populateObjectIds(tc.currentObjs, t), eventChannel, Options{
177176
DryRunStrategy: drs,
178177
})
179178
}()

pkg/apply/solver/solver.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type Options struct {
5151

5252
type resourceObjects interface {
5353
ObjsForApply() []*unstructured.Unstructured
54-
ObjsForPrune() []*unstructured.Unstructured
54+
Inventory() *unstructured.Unstructured
5555
IdsForApply() []object.ObjMetadata
5656
IdsForPrune() []object.ObjMetadata
5757
}
@@ -128,7 +128,8 @@ func (t *TaskQueueSolver) BuildTaskQueue(ro resourceObjects,
128128
if o.Prune {
129129
tasks = append(tasks,
130130
&task.PruneTask{
131-
Objects: ro.ObjsForPrune(),
131+
Objects: ro.ObjsForApply(),
132+
InventoryObject: ro.Inventory(),
132133
PruneOptions: t.PruneOptions,
133134
PropagationPolicy: o.PrunePropagationPolicy,
134135
DryRunStrategy: o.DryRunStrategy,

pkg/apply/solver/solver_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ func getType(task taskrunner.Task) reflect.Type {
309309

310310
type fakeResourceObjects struct {
311311
objsForApply []*unstructured.Unstructured
312+
inventory *unstructured.Unstructured
312313
idsForApply []object.ObjMetadata
313314
idsForPrune []object.ObjMetadata
314315
}
@@ -317,8 +318,8 @@ func (f *fakeResourceObjects) ObjsForApply() []*unstructured.Unstructured {
317318
return f.objsForApply
318319
}
319320

320-
func (f *fakeResourceObjects) ObjsForPrune() []*unstructured.Unstructured {
321-
return f.objsForApply
321+
func (f *fakeResourceObjects) Inventory() *unstructured.Unstructured {
322+
return f.inventory
322323
}
323324

324325
func (f *fakeResourceObjects) IdsForApply() []object.ObjMetadata {

pkg/apply/task/prune_task.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
// set of resources that have just been applied.
1717
type PruneTask struct {
1818
PruneOptions *prune.PruneOptions
19+
InventoryObject *unstructured.Unstructured
1920
Objects []*unstructured.Unstructured
2021
DryRunStrategy common.DryRunStrategy
2122
PropagationPolicy metav1.DeletionPropagation
@@ -28,7 +29,7 @@ type PruneTask struct {
2829
func (p *PruneTask) Start(taskContext *taskrunner.TaskContext) {
2930
go func() {
3031
currentUIDs := taskContext.AllResourceUIDs()
31-
err := p.PruneOptions.Prune(p.Objects,
32+
err := p.PruneOptions.Prune(p.InventoryObject, p.Objects,
3233
currentUIDs, taskContext.EventChannel(), prune.Options{
3334
DryRunStrategy: p.DryRunStrategy,
3435
PropagationPolicy: p.PropagationPolicy,

0 commit comments

Comments
 (0)