@@ -103,6 +103,8 @@ func (cic *ClusterClient) Merge(localInv Info, objs object.ObjMetadataSet, dryRu
103103 if err != nil {
104104 return pruneIds , err
105105 }
106+
107+ // Inventory does not exist on the cluster.
106108 if clusterInv == nil {
107109 // Wrap inventory object and store the inventory in it.
108110 var status []actuation.ObjectStatus
@@ -113,60 +115,41 @@ func (cic *ClusterClient) Merge(localInv Info, objs object.ObjMetadataSet, dryRu
113115 if err := inv .Store (objs , status ); err != nil {
114116 return nil , err
115117 }
116- invInfo , err := inv .GetObject ()
117- if err != nil {
118- return nil , err
119- }
120118 klog .V (4 ).Infof ("creating initial inventory object with %d objects" , len (objs ))
121- createdObj , err := cic .createInventoryObj (invInfo , dryRun )
122- if err != nil {
123- return nil , err
124- }
125- // Status update requires the latest ResourceVersion
126- invInfo .SetResourceVersion (createdObj .GetResourceVersion ())
127- if err := cic .updateStatus (invInfo , dryRun ); err != nil {
128- return nil , err
129- }
130- } else {
131- // Update existing cluster inventory with merged union of objects
132- clusterObjs , err := cic .GetClusterObjs (localInv )
133- if err != nil {
134- return pruneIds , err
135- }
136- pruneIds = clusterObjs .Diff (objs )
137- unionObjs := clusterObjs .Union (objs )
138- var status []actuation.ObjectStatus
139- if cic .statusPolicy == StatusPolicyAll {
140- status = getObjStatus (pruneIds , unionObjs )
141- }
142- klog .V (4 ).Infof ("num objects to prune: %d" , len (pruneIds ))
143- klog .V (4 ).Infof ("num merged objects to store in inventory: %d" , len (unionObjs ))
144- wrappedInv := cic .InventoryFactoryFunc (clusterInv )
145- if err = wrappedInv .Store (unionObjs , status ); err != nil {
146- return pruneIds , err
147- }
148- clusterInv , err = wrappedInv .GetObject ()
149- if err != nil {
150- return pruneIds , err
151- }
119+
152120 if dryRun .ClientOrServerDryRun () {
153- return pruneIds , nil
154- }
155- if ! objs .Equal (clusterObjs ) {
156- klog .V (4 ).Infof ("update cluster inventory: %s/%s" , clusterInv .GetNamespace (), clusterInv .GetName ())
157- appliedObj , err := cic .applyInventoryObj (clusterInv , dryRun )
158- if err != nil {
159- return pruneIds , err
160- }
161- // Status update requires the latest ResourceVersion
162- clusterInv .SetResourceVersion (appliedObj .GetResourceVersion ())
163- }
164- if err := cic .updateStatus (clusterInv , dryRun ); err != nil {
165- return pruneIds , err
121+ klog .V (4 ).Infof ("dry-run create inventory object: not created" )
122+ return nil , nil
166123 }
124+
125+ err = inv .Apply (cic .dc , cic .mapper , cic .statusPolicy )
126+ return nil , err
127+ }
128+
129+ // Update existing cluster inventory with merged union of objects
130+ clusterObjs , err := cic .GetClusterObjs (localInv )
131+ if err != nil {
132+ return pruneIds , err
133+ }
134+ pruneIds = clusterObjs .Diff (objs )
135+ unionObjs := clusterObjs .Union (objs )
136+ var status []actuation.ObjectStatus
137+ if cic .statusPolicy == StatusPolicyAll {
138+ status = getObjStatus (pruneIds , unionObjs )
139+ }
140+ klog .V (4 ).Infof ("num objects to prune: %d" , len (pruneIds ))
141+ klog .V (4 ).Infof ("num merged objects to store in inventory: %d" , len (unionObjs ))
142+ wrappedInv := cic .InventoryFactoryFunc (clusterInv )
143+ if err = wrappedInv .Store (unionObjs , status ); err != nil {
144+ return pruneIds , err
167145 }
168146
169- return pruneIds , nil
147+ if dryRun .ClientOrServerDryRun () {
148+ klog .V (4 ).Infof ("dry-run create inventory object: not created" )
149+ return pruneIds , nil
150+ }
151+ err = wrappedInv .Apply (cic .dc , cic .mapper , cic .statusPolicy )
152+ return pruneIds , err
170153}
171154
172155// Replace stores the passed objects in the cluster inventory object, or
@@ -178,49 +161,49 @@ func (cic *ClusterClient) Replace(localInv Info, objs object.ObjMetadataSet, sta
178161 klog .V (4 ).Infoln ("dry-run replace inventory object: not applied" )
179162 return nil
180163 }
181- clusterObjs , err := cic .GetClusterObjs (localInv )
182- if err != nil {
183- return fmt .Errorf ("failed to read inventory objects from cluster: %w" , err )
184- }
185164 clusterInv , err := cic .GetClusterInventoryInfo (localInv )
186165 if err != nil {
187166 return fmt .Errorf ("failed to read inventory from cluster: %w" , err )
188167 }
189- clusterInv , err = cic .replaceInventory (clusterInv , objs , status )
168+
169+ clusterObjs , err := cic .GetClusterObjs (localInv )
170+ if err != nil {
171+ return fmt .Errorf ("failed to read inventory objects from cluster: %w" , err )
172+ }
173+
174+ clusterInv , wrappedInv , err := cic .replaceInventory (clusterInv , objs , status )
190175 if err != nil {
191176 return err
192177 }
178+
193179 if ! objs .Equal (clusterObjs ) {
194180 klog .V (4 ).Infof ("replace cluster inventory: %s/%s" , clusterInv .GetNamespace (), clusterInv .GetName ())
195181 klog .V (4 ).Infof ("replace cluster inventory %d objects" , len (objs ))
196- appliedObj , err := cic . applyInventoryObj ( clusterInv , dryRun )
197- if err != nil {
182+
183+ if err := wrappedInv . ApplyWithPrune ( cic . dc , cic . mapper , cic . statusPolicy , objs ); err != nil {
198184 return fmt .Errorf ("failed to write updated inventory to cluster: %w" , err )
199185 }
200- // Status update requires the latest ResourceVersion
201- clusterInv .SetResourceVersion (appliedObj .GetResourceVersion ())
202- }
203- if err := cic .updateStatus (clusterInv , dryRun ); err != nil {
204- return err
205186 }
187+
206188 return nil
207189}
208190
209191// replaceInventory stores the passed objects into the passed inventory object.
210192func (cic * ClusterClient ) replaceInventory (inv * unstructured.Unstructured , objs object.ObjMetadataSet ,
211- status []actuation.ObjectStatus ) (* unstructured.Unstructured , error ) {
193+ status []actuation.ObjectStatus ) (* unstructured.Unstructured , Storage , error ) {
212194 if cic .statusPolicy == StatusPolicyNone {
213195 status = nil
214196 }
215197 wrappedInv := cic .InventoryFactoryFunc (inv )
216198 if err := wrappedInv .Store (objs , status ); err != nil {
217- return nil , err
199+ return nil , nil , err
218200 }
219201 clusterInv , err := wrappedInv .GetObject ()
220202 if err != nil {
221- return nil , err
203+ return nil , nil , err
222204 }
223- return clusterInv , nil
205+
206+ return clusterInv , wrappedInv , nil
224207}
225208
226209// DeleteInventoryObj deletes the inventory object from the cluster.
@@ -364,26 +347,6 @@ func (cic *ClusterClient) GetClusterInventoryObjs(inv Info) (object.Unstructured
364347 return clusterInvObjects , err
365348}
366349
367- // applyInventoryObj applies the passed inventory object to the APIServer.
368- func (cic * ClusterClient ) applyInventoryObj (obj * unstructured.Unstructured , dryRun common.DryRunStrategy ) (* unstructured.Unstructured , error ) {
369- if dryRun .ClientOrServerDryRun () {
370- klog .V (4 ).Infof ("dry-run apply inventory object: not applied" )
371- return obj .DeepCopy (), nil
372- }
373- if obj == nil {
374- return nil , fmt .Errorf ("attempting apply a nil inventory object" )
375- }
376-
377- mapping , err := cic .getMapping (obj )
378- if err != nil {
379- return nil , err
380- }
381-
382- klog .V (4 ).Infof ("replacing inventory object: %s/%s" , obj .GetNamespace (), obj .GetName ())
383- return cic .dc .Resource (mapping .Resource ).Namespace (obj .GetNamespace ()).
384- Update (context .TODO (), obj , metav1.UpdateOptions {})
385- }
386-
387350// createInventoryObj creates the passed inventory object on the APIServer.
388351func (cic * ClusterClient ) createInventoryObj (obj * unstructured.Unstructured , dryRun common.DryRunStrategy ) (* unstructured.Unstructured , error ) {
389352 if dryRun .ClientOrServerDryRun () {
@@ -463,62 +426,6 @@ func (cic *ClusterClient) getMapping(obj *unstructured.Unstructured) (*meta.REST
463426 return cic .mapper .RESTMapping (obj .GroupVersionKind ().GroupKind (), obj .GroupVersionKind ().Version )
464427}
465428
466- func (cic * ClusterClient ) updateStatus (obj * unstructured.Unstructured , dryRun common.DryRunStrategy ) error {
467- if cic .statusPolicy != StatusPolicyAll {
468- klog .V (4 ).Infof ("inventory status update skipped (StatusPolicy: %s)" , cic .statusPolicy )
469- return nil
470- }
471- if dryRun .ClientOrServerDryRun () {
472- klog .V (4 ).Infof ("dry-run update inventory status: not updated" )
473- return nil
474- }
475- status , found , _ := unstructured .NestedMap (obj .UnstructuredContent (), "status" )
476- if ! found {
477- return nil
478- }
479- mapping , err := cic .mapper .RESTMapping (obj .GroupVersionKind ().GroupKind ())
480- if err != nil {
481- return nil
482- }
483- hasStatus , err := cic .hasSubResource (obj .GetAPIVersion (), mapping .Resource .Resource , "status" )
484- if err != nil {
485- return err
486- }
487- if ! hasStatus {
488- klog .V (4 ).Infof ("skip updating inventory status" )
489- return nil
490- }
491-
492- klog .V (4 ).Infof ("update inventory status" )
493- resource := cic .dc .Resource (mapping .Resource ).Namespace (obj .GetNamespace ())
494- meta := metav1.TypeMeta {
495- Kind : obj .GetKind (),
496- APIVersion : obj .GetAPIVersion (),
497- }
498- if err = unstructured .SetNestedMap (obj .Object , status , "status" ); err != nil {
499- return err
500- }
501- if _ , err = resource .UpdateStatus (context .TODO (), obj , metav1.UpdateOptions {TypeMeta : meta }); err != nil {
502- return fmt .Errorf ("failed to write updated inventory status to cluster: %w" , err )
503- }
504- return nil
505- }
506-
507- // hasSubResource checks if a resource has the given subresource using the discovery client.
508- func (cic * ClusterClient ) hasSubResource (groupVersion , resource , subresource string ) (bool , error ) {
509- resources , err := cic .discoveryClient .ServerResourcesForGroupVersion (groupVersion )
510- if err != nil {
511- return false , err
512- }
513-
514- for _ , r := range resources .APIResources {
515- if r .Name == fmt .Sprintf ("%s/%s" , resource , subresource ) {
516- return true , nil
517- }
518- }
519- return false , nil
520- }
521-
522429// getObjStatus returns the list of object status
523430// at the beginning of an apply process.
524431func getObjStatus (pruneIds , unionIds []object.ObjMetadata ) []actuation.ObjectStatus {
0 commit comments