...

Source file src/sigs.k8s.io/cli-utils/pkg/apply/task/inv_set_task.go

Documentation: sigs.k8s.io/cli-utils/pkg/apply/task

     1  // Copyright 2021 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package task
     5  
     6  import (
     7  	"k8s.io/klog/v2"
     8  	"sigs.k8s.io/cli-utils/pkg/apply/event"
     9  	"sigs.k8s.io/cli-utils/pkg/apply/taskrunner"
    10  	"sigs.k8s.io/cli-utils/pkg/common"
    11  	"sigs.k8s.io/cli-utils/pkg/inventory"
    12  	"sigs.k8s.io/cli-utils/pkg/object"
    13  )
    14  
    15  // InvSetTask encapsulates structures necessary to set the
    16  // inventory references at the end of the apply/prune.
    17  type InvSetTask struct {
    18  	TaskName      string
    19  	InvClient     inventory.Client
    20  	InvInfo       inventory.Info
    21  	PrevInventory object.ObjMetadataSet
    22  	DryRun        common.DryRunStrategy
    23  }
    24  
    25  func (i *InvSetTask) Name() string {
    26  	return i.TaskName
    27  }
    28  
    29  func (i *InvSetTask) Action() event.ResourceAction {
    30  	return event.InventoryAction
    31  }
    32  
    33  func (i *InvSetTask) Identifiers() object.ObjMetadataSet {
    34  	return object.ObjMetadataSet{}
    35  }
    36  
    37  // Start sets (creates or replaces) the inventory.
    38  //
    39  // The guiding principal is that anything in the cluster should be in the
    40  // inventory, unless it was explicitly abandoned.
    41  //
    42  // This task must run after all the apply and prune tasks have completed.
    43  //
    44  // Added objects:
    45  // - Applied resources (successful)
    46  //
    47  // Retained objects:
    48  // - Applied resources (filtered/skipped)
    49  // - Applied resources (failed)
    50  // - Deleted resources (filtered/skipped) that were not abandoned
    51  // - Deleted resources (failed)
    52  // - Abandoned resources (failed)
    53  //
    54  // Removed objects:
    55  // - Deleted resources (successful)
    56  // - Abandoned resources (successful)
    57  func (i *InvSetTask) Start(taskContext *taskrunner.TaskContext) {
    58  	go func() {
    59  		klog.V(2).Infof("inventory set task starting (name: %q)", i.Name())
    60  		invObjs := object.ObjMetadataSet{}
    61  
    62  		// TODO: Just use InventoryManager.Store()
    63  		im := taskContext.InventoryManager()
    64  
    65  		// If an object applied successfully, keep or add it to the inventory.
    66  		appliedObjs := im.SuccessfulApplies()
    67  		klog.V(4).Infof("set inventory %d successful applies", len(appliedObjs))
    68  		invObjs = invObjs.Union(appliedObjs)
    69  
    70  		// If an object failed to apply and was previously stored in the inventory,
    71  		// then keep it in the inventory so it can be applied/pruned next time.
    72  		// This will remove new resources that failed to apply from the inventory,
    73  		// because even tho they were added by InvAddTask, the PrevInventory
    74  		// represents the inventory before the pipeline has run.
    75  		applyFailures := i.PrevInventory.Intersection(im.FailedApplies())
    76  		klog.V(4).Infof("keep in inventory %d failed applies", len(applyFailures))
    77  		invObjs = invObjs.Union(applyFailures)
    78  
    79  		// If an object skipped apply and was previously stored in the inventory,
    80  		// then keep it in the inventory so it can be applied/pruned next time.
    81  		// It's likely that all the skipped applies are already in the inventory,
    82  		// because the apply filters all currently depend on cluster state,
    83  		// but we're doing the intersection anyway just to be sure.
    84  		applySkips := i.PrevInventory.Intersection(im.SkippedApplies())
    85  		klog.V(4).Infof("keep in inventory %d skipped applies", len(applySkips))
    86  		invObjs = invObjs.Union(applySkips)
    87  
    88  		// If an object failed to delete and was previously stored in the inventory,
    89  		// then keep it in the inventory so it can be applied/pruned next time.
    90  		// It's likely that all the delete failures are already in the inventory,
    91  		// because the set of resources to prune comes from the inventory,
    92  		// but we're doing the intersection anyway just to be sure.
    93  		pruneFailures := i.PrevInventory.Intersection(im.FailedDeletes())
    94  		klog.V(4).Infof("set inventory %d failed prunes", len(pruneFailures))
    95  		invObjs = invObjs.Union(pruneFailures)
    96  
    97  		// If an object skipped delete and was previously stored in the inventory,
    98  		// then keep it in the inventory so it can be applied/pruned next time.
    99  		// It's likely that all the skipped deletes are already in the inventory,
   100  		// because the set of resources to prune comes from the inventory,
   101  		// but we're doing the intersection anyway just to be sure.
   102  		pruneSkips := i.PrevInventory.Intersection(im.SkippedDeletes())
   103  		klog.V(4).Infof("keep in inventory %d skipped prunes", len(pruneSkips))
   104  		invObjs = invObjs.Union(pruneSkips)
   105  
   106  		// If an object is abandoned, then remove it from the inventory.
   107  		abandonedObjects := taskContext.AbandonedObjects()
   108  		klog.V(4).Infof("remove from inventory %d abandoned objects", len(abandonedObjects))
   109  		invObjs = invObjs.Diff(abandonedObjects)
   110  
   111  		// If an object is invalid and was previously stored in the inventory,
   112  		// then keep it in the inventory so it can be applied/pruned next time.
   113  		invalidObjects := i.PrevInventory.Intersection(taskContext.InvalidObjects())
   114  		klog.V(4).Infof("keep in inventory %d invalid objects", len(invalidObjects))
   115  		invObjs = invObjs.Union(invalidObjects)
   116  
   117  		klog.V(4).Infof("get the apply status for %d objects", len(invObjs))
   118  		objStatus := taskContext.InventoryManager().Inventory().Status.Objects
   119  
   120  		klog.V(4).Infof("set inventory %d total objects", len(invObjs))
   121  		err := i.InvClient.Replace(i.InvInfo, invObjs, objStatus, i.DryRun)
   122  
   123  		klog.V(2).Infof("inventory set task completing (name: %q)", i.Name())
   124  		taskContext.TaskChannel() <- taskrunner.TaskResult{Err: err}
   125  	}()
   126  }
   127  
   128  // Cancel is not supported by the InvSetTask.
   129  func (i *InvSetTask) Cancel(_ *taskrunner.TaskContext) {}
   130  
   131  // StatusUpdate is not supported by the InvSetTask.
   132  func (i *InvSetTask) StatusUpdate(_ *taskrunner.TaskContext, _ object.ObjMetadata) {}
   133  

View as plain text