@@ -17,7 +17,7 @@ import (
1717 "k8s.io/client-go/dynamic"
1818 "k8s.io/klog"
1919 "k8s.io/kubectl/pkg/cmd/apply"
20- "k8s.io/kubectl/pkg/cmd/delete"
20+ cmddelete "k8s.io/kubectl/pkg/cmd/delete"
2121 "k8s.io/kubectl/pkg/cmd/util"
2222 "k8s.io/kubectl/pkg/util/slice"
2323 applyerror "sigs.k8s.io/cli-utils/pkg/apply/error"
@@ -45,11 +45,13 @@ type applyOptions interface {
4545// ApplyTask applies the given Objects to the cluster
4646// by using the ApplyOptions.
4747type ApplyTask struct {
48- Factory util.Factory
49- InfoHelper info.InfoHelper
50- Mapper meta.RESTMapper
51- Objects []* unstructured.Unstructured
52- CRDs []* unstructured.Unstructured
48+ Factory util.Factory
49+ InfoHelper info.InfoHelper
50+ Mapper meta.RESTMapper
51+ Objects []* unstructured.Unstructured
52+ CRDs []* unstructured.Unstructured
53+ // Used for determining inventory during errors
54+ PrevInventory map [object.ObjMetadata ]bool
5355 DryRunStrategy common.DryRunStrategy
5456 ServerSideOptions common.ServerSideOptions
5557 InventoryPolicy inventory.InventoryPolicy
@@ -80,6 +82,7 @@ func (a *ApplyTask) Start(taskContext *taskrunner.TaskContext) {
8082 // we have a CRD and a CR in the same resource set, but the CRD
8183 // will not actually have been applied when we reach the CR.
8284 if a .DryRunStrategy .ClientOrServerDryRun () {
85+ klog .V (4 ).Infof ("dry-run filtering custom resources..." )
8386 // Find all resources in the set that doesn't exist in the
8487 // RESTMapper, but where we do have the CRD for the type in
8588 // the resource set.
@@ -97,6 +100,7 @@ func (a *ApplyTask) Start(taskContext *taskrunner.TaskContext) {
97100 taskContext .EventChannel () <- createApplyEvent (object .UnstructuredToObjMeta (obj ), event .Created , nil )
98101 }
99102 // Update the resource set to no longer include the CRs.
103+ klog .V (4 ).Infof ("after dry-run filtering custom resources, %d objects left" , len (objs ))
100104 objects = objs
101105 }
102106
@@ -123,7 +127,8 @@ func (a *ApplyTask) Start(taskContext *taskrunner.TaskContext) {
123127 }
124128
125129 klog .V (4 ).Infof ("attempting to apply %d remaining objects" , len (objects ))
126- var infos []* resource.Info
130+ // invInfos stores the objects which should be stored in the final inventory.
131+ invInfos := make (map [object.ObjMetadata ]* resource.Info , len (objects ))
127132 for _ , obj := range objects {
128133 // Set the client and mapping fields on the provided
129134 // info so they can be applied to the cluster.
@@ -144,18 +149,25 @@ func (a *ApplyTask) Start(taskContext *taskrunner.TaskContext) {
144149 if err != nil {
145150 if ! apierrors .IsNotFound (err ) {
146151 if klog .V (4 ) {
147- klog .Errorf ("error retrieving %s/%s from cluster--continue" ,
152+ klog .Errorf ("error (%s) retrieving %s/%s from cluster--continue" ,
153+ err , info .Namespace , info .Name )
154+ }
155+ op := event .Failed
156+ if a .objInCluster (id ) {
157+ // Object in cluster stays in the inventory.
158+ klog .V (4 ).Infof ("%s/%s apply retrieval failure, but in cluster--keep in inventory" ,
148159 info .Namespace , info .Name )
160+ invInfos [id ] = info
161+ op = event .Unchanged
149162 }
150- taskContext .EventChannel () <- createApplyEvent (
151- id ,
152- event .Unchanged ,
153- err )
163+ taskContext .EventChannel () <- createApplyEvent (id , op , err )
154164 taskContext .CaptureResourceFailure (id )
155165 continue
156166 }
157167 }
158- infos = append (infos , info )
168+ // At this point the object was either 1) successfully retrieved from the cluster, or
169+ // 2) returned "Not Found" error (meaning first-time creation). Add to final inventory.
170+ invInfos [id ] = info
159171 canApply , err := inventory .CanApply (a .InvInfo , clusterObj , a .InventoryPolicy )
160172 if ! canApply {
161173 klog .V (5 ).Infof ("can not apply %s/%s--continue" ,
@@ -176,30 +188,30 @@ func (a *ApplyTask) Start(taskContext *taskrunner.TaskContext) {
176188 if klog .V (4 ) {
177189 klog .Errorf ("error applying (%s/%s) %s" , info .Namespace , info .Name , err )
178190 }
191+ // If apply failed and the object is not in the cluster, remove
192+ // it from the final inventory.
193+ if ! a .objInCluster (id ) {
194+ klog .V (5 ).Infof ("not in cluster; removing apply fail object %s/%s from inventory" ,
195+ info .Namespace , info .Name )
196+ delete (invInfos , id )
197+ }
179198 taskContext .EventChannel () <- createApplyEvent (
180199 id , event .Failed , applyerror .NewApplyRunError (err ))
181200 taskContext .CaptureResourceFailure (id )
182201 }
183202 }
184203
185- // Fetch the Generation from all Infos after they have been
186- // applied.
187- for _ , inf := range infos {
188- id , err := object .InfoToObjMeta (inf )
189- if err != nil {
190- continue
191- }
192- if inf .Object != nil {
193- acc , err := meta .Accessor (inf .Object )
204+ // Store objects (and some obj metadata) in the task context
205+ // for the final inventory.
206+ for id , info := range invInfos {
207+ if info .Object != nil {
208+ acc , err := meta .Accessor (info .Object )
194209 if err != nil {
195210 continue
196211 }
197- // Only add a resource if it successfully applied.
198212 uid := acc .GetUID ()
199- if string (uid ) != "" {
200- gen := acc .GetGeneration ()
201- taskContext .ResourceApplied (id , uid , gen )
202- }
213+ gen := acc .GetGeneration ()
214+ taskContext .ResourceApplied (id , uid , gen )
203215 }
204216 }
205217 a .sendTaskResult (taskContext )
@@ -232,7 +244,7 @@ func newApplyOptions(eventChannel chan event.Event, serverSideOptions common.Ser
232244 },
233245 // FilenameOptions are not needed since we don't use the ApplyOptions
234246 // to read manifests.
235- DeleteOptions : & delete .DeleteOptions {},
247+ DeleteOptions : & cmddelete .DeleteOptions {},
236248 PrintFlags : & genericclioptions.PrintFlags {
237249 OutputFormat : & emptyString ,
238250 },
@@ -292,6 +304,16 @@ func (a *ApplyTask) filterCRsWithCRDInSet(objects []*unstructured.Unstructured)
292304 return objs , objsWithCRD , nil
293305}
294306
307+ // objInCluster returns true if the passed object is in the slice of
308+ // previous inventory, because an object in the previous inventory
309+ // exists in the cluster.
310+ func (a * ApplyTask ) objInCluster (obj object.ObjMetadata ) bool {
311+ if _ , found := a .PrevInventory [obj ]; found {
312+ return true
313+ }
314+ return false
315+ }
316+
295317type crdsInfo struct {
296318 crds []crdInfo
297319}
0 commit comments