Skip to content

Commit c9e7d32

Browse files
committed
Updates prune algorithm to use one inventory object
1 parent 537dfba commit c9e7d32

24 files changed

+1927
-1177
lines changed

examples/alphaTestExamples/MultipleServices.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ the namespace and inventory id used by apply to create inventory objects.
5959
```
6060
kapply init $BASE/mysql > $OUTPUT/status
6161
expectedOutputLine "namespace: default is used for inventory object"
62+
6263
kapply init $BASE/wordpress > $OUTPUT/status
6364
expectedOutputLine "namespace: default is used for inventory object"
6465
```
@@ -79,8 +80,6 @@ expectedOutputLine "deployment.apps/mysql is Current: Deployment is available. R
7980

8081
expectedOutputLine "secret/mysql-pass is Current: Resource is always ready"
8182

82-
expectedOutputLine "configmap/inventory-57005c71 is Current: Resource is always ready"
83-
8483
expectedOutputLine "service/mysql is Current: Service is ready"
8584

8685
# Verify that we have the mysql resources in the cluster.
@@ -97,8 +96,6 @@ And the apply the wordpress service
9796
```
9897
kapply apply $BASE/wordpress --reconcile-timeout=120s > $OUTPUT/status;
9998

100-
expectedOutputLine "configmap/inventory-2fbd5b91 is Current: Resource is always ready"
101-
10299
expectedOutputLine "service/wordpress is Current: Service is ready"
103100

104101
expectedOutputLine "deployment.apps/wordpress is Current: Deployment is available. Replicas: 1"
@@ -117,8 +114,6 @@ expectedOutputLine "service/wordpress deleted"
117114

118115
expectedOutputLine "deployment.apps/wordpress deleted"
119116

120-
expectedOutputLine "configmap/inventory-2fbd5b91 deleted"
121-
122117
# Verify that we still have the mysql resources in the cluster.
123118
kubectl get all --no-headers --selector=app=mysql | wc -l | xargs > $OUTPUT/status
124119
expectedOutputLine "4"

examples/alphaTestExamples/helloapp.md

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ Run preview to check which commands will be executed
162162
```
163163
kapply preview $BASE > $OUTPUT/status
164164

165-
expectedOutputLine "4 resource(s) applied. 4 created, 0 unchanged, 0 configured (preview)"
165+
expectedOutputLine "3 resource(s) applied. 3 created, 0 unchanged, 0 configured (preview)"
166166

167167
# Verify that preview didn't create any resources.
168168
kubectl get all -n hellospace > $OUTPUT/status 2>&1
@@ -178,8 +178,6 @@ expectedOutputLine "deployment.apps/the-deployment is Current: Deployment is ava
178178

179179
expectedOutputLine "service/the-service is Current: Service is ready"
180180

181-
expectedOutputLine "configmap/inventory-5fe947f is Current: Resource is always ready"
182-
183181
expectedOutputLine "configmap/the-map1 is Current: Resource is always ready"
184182

185183
# Verify that we have the pods running in the cluster
@@ -210,14 +208,10 @@ expectedOutputLine "deployment.apps/the-deployment is Current: Deployment is ava
210208

211209
expectedOutputLine "service/the-service is Current: Service is ready"
212210

213-
expectedOutputLine "configmap/inventory-db36ed56 is Current: Resource is always ready"
214-
215211
expectedOutputLine "configmap/the-map2 is Current: Resource is always ready"
216212

217213
expectedOutputLine "configmap/the-map1 pruned"
218214

219-
expectedOutputLine "configmap/inventory-5fe947f pruned"
220-
221215
# Verify that the new configmap has been created and the old one pruned.
222216
kubectl get cm -n hellospace --no-headers | awk '{print $1}' > $OUTPUT/status
223217
expectedOutputLine "the-map2"
@@ -235,13 +229,10 @@ expectedOutputLine "configmap/the-map2 deleted (preview)"
235229

236230
expectedOutputLine "service/the-service deleted (preview)"
237231

238-
expectedOutputLine "configmap/inventory-db36ed56 deleted (preview)"
239-
240232
# Verify that preview all resources are still there after running preview.
241233
kubectl get --no-headers all -n hellospace | wc -l | xargs > $OUTPUT/status
242234
expectedOutputLine "6"
243235

244-
245236
kapply destroy $BASE > $OUTPUT/status;
246237

247238
expectedOutputLine "deployment.apps/the-deployment deleted"
@@ -250,7 +241,5 @@ expectedOutputLine "configmap/the-map2 deleted"
250241

251242
expectedOutputLine "service/the-service deleted"
252243

253-
expectedOutputLine "configmap/inventory-db36ed56 deleted"
254-
255244
kind delete cluster;
256245
```

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
180180
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
181181
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
182182
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
183+
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
183184
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
184185
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
185186
github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7 h1:u4bArs140e9+AfE52mFHOXVFnOSBJBRlzTHrOPLOIhE=
@@ -218,6 +219,7 @@ github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1a
218219
github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o=
219220
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
220221
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
222+
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
221223
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
222224
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
223225
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=

pkg/apply/applier.go

Lines changed: 35 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -157,89 +157,78 @@ func (a *Applier) infoHelperFactory() info.InfoHelper {
157157
return info.NewInfoHelper(a.factory, a.ApplyOptions.Namespace)
158158
}
159159

160-
// prepareObjects handles ordering of resources and sets up the inventory object
161-
// based on the provided inventory object template.
160+
// prepareObjects merges the currently applied objects into the
161+
// set of stored objects in the cluster inventory. In the process, it
162+
// calculates the set of objects to be pruned (pruneIds), and orders the
163+
// resources for the subsequent apply. Returns the sorted resources to
164+
// apply as well as the objects for the prune, or an error if one occurred.
162165
func (a *Applier) prepareObjects(infos []*resource.Info) (*ResourceObjects, error) {
163-
resources, invs := splitInfos(infos)
164-
165-
if len(invs) == 0 {
166-
return nil, inventory.NoInventoryObjError{}
167-
}
168-
if len(invs) > 1 {
169-
return nil, inventory.MultipleInventoryObjError{
170-
InventoryObjectTemplates: invs,
171-
}
166+
localInv, localInfos, err := inventory.SplitInfos(infos)
167+
if err != nil {
168+
return nil, err
172169
}
173-
174-
inv := a.InventoryFactoryFunc(invs[0])
175-
inventoryObject, err := inventory.CreateInventoryObj(inv, resources)
170+
currentObjs, err := object.InfosToObjMetas(localInfos)
176171
if err != nil {
177172
return nil, err
178173
}
179-
180-
// Fetch all previous inventories.
181-
previousInventories, err := a.invClient.GetPreviousInventoryObjects(inventoryObject)
174+
// returns the objects (pruneIds) to prune after apply. The prune
175+
// algorithm requires stopping if the merge is not successful. Otherwise,
176+
// the stored objects in inventory could become inconsistent.
177+
pruneIds, err := a.invClient.Merge(localInv, currentObjs)
182178
if err != nil {
183179
return nil, err
184180
}
185-
186-
sort.Sort(ordering.SortableInfos(resources))
187-
188-
if !validateNamespace(resources) {
181+
// Sort order for applied resources.
182+
sort.Sort(ordering.SortableInfos(localInfos))
183+
// TODO(seans3): Remove this single namespace requirement once we've
184+
// implemented multi-namespace apply.
185+
if !validateNamespace(localInfos) {
189186
return nil, fmt.Errorf("objects have differing namespaces")
190187
}
191-
192188
return &ResourceObjects{
193-
CurrentInventory: inventoryObject,
194-
PreviousInventories: previousInventories,
195-
Resources: resources,
189+
LocalInv: localInv,
190+
Resources: localInfos,
191+
PruneIds: pruneIds,
196192
}, nil
197193
}
198194

199195
// ResourceObjects contains information about the resources that
200196
// will be applied and the existing inventories used to determine
201197
// resources that should be pruned.
202198
type ResourceObjects struct {
203-
CurrentInventory *resource.Info
204-
PreviousInventories []*resource.Info
205-
Resources []*resource.Info
199+
LocalInv *resource.Info
200+
Resources []*resource.Info
201+
PruneIds []object.ObjMetadata
206202
}
207203

208204
// InfosForApply returns the infos representation for all the resources
209205
// that should be applied, including the inventory object. The
210206
// resources will be in sorted order.
211207
func (r *ResourceObjects) InfosForApply() []*resource.Info {
212-
return append([]*resource.Info{r.CurrentInventory}, r.Resources...)
208+
return r.Resources
209+
}
210+
211+
func (r *ResourceObjects) InfosForPrune() []*resource.Info {
212+
return append([]*resource.Info{r.LocalInv}, r.Resources...)
213213
}
214214

215215
// IdsForApply returns the Ids for all resources that should be applied,
216216
// including the inventory object.
217217
func (r *ResourceObjects) IdsForApply() []object.ObjMetadata {
218218
var ids []object.ObjMetadata
219219
for _, info := range r.InfosForApply() {
220-
ids = append(ids, object.InfoToObjMeta(info))
220+
id, err := object.InfoToObjMeta(info)
221+
if err == nil {
222+
ids = append(ids, id)
223+
}
221224
}
222225
return ids
223226
}
224227

225228
// IdsForPrune returns the Ids for all resources that should
226229
// be pruned.
227230
func (r *ResourceObjects) IdsForPrune() []object.ObjMetadata {
228-
inventory, _ := inventory.UnionPastObjs(r.PreviousInventories)
229-
230-
applyIds := make(map[object.ObjMetadata]bool)
231-
for _, id := range r.IdsForApply() {
232-
applyIds[id] = true
233-
}
234-
235-
var ids []object.ObjMetadata
236-
for _, id := range inventory {
237-
if _, found := applyIds[id]; found {
238-
continue
239-
}
240-
ids = append(ids, id)
241-
}
242-
return ids
231+
return r.PruneIds
243232
}
244233

245234
// AllIds returns the Ids for all resources that are relevant. This
@@ -248,23 +237,6 @@ func (r *ResourceObjects) AllIds() []object.ObjMetadata {
248237
return append(r.IdsForApply(), r.IdsForPrune()...)
249238
}
250239

251-
// splitInfos takes a slice of resource.Info objects and splits it
252-
// into one slice that contains the inventory object templates and
253-
// another one that contains the remaining resources.
254-
func splitInfos(infos []*resource.Info) ([]*resource.Info, []*resource.Info) {
255-
inventoryObjectTemplates := make([]*resource.Info, 0)
256-
resources := make([]*resource.Info, 0)
257-
258-
for _, info := range infos {
259-
if inventory.IsInventoryObject(info.Object) {
260-
inventoryObjectTemplates = append(inventoryObjectTemplates, info)
261-
} else {
262-
resources = append(resources, info)
263-
}
264-
}
265-
return resources, inventoryObjectTemplates
266-
}
267-
268240
// Run performs the Apply step. This happens asynchronously with updates
269241
// on progress and any errors are reported back on the event channel.
270242
// Cancelling the operation or setting timeout on how long to Wait
@@ -276,6 +248,7 @@ func splitInfos(infos []*resource.Info) ([]*resource.Info, []*resource.Info) {
276248
func (a *Applier) Run(ctx context.Context, objects []*resource.Info, options Options) <-chan event.Event {
277249
eventChannel := make(chan event.Event)
278250
setDefaults(&options)
251+
a.invClient.SetDryRun(options.DryRun) // client shared with prune, so sets dry-run for prune too.
279252

280253
go func() {
281254
defer close(eventChannel)

0 commit comments

Comments
 (0)