mirror of https://github.com/fluxcd/cli-utils.git
127 lines
5.1 KiB
Go
127 lines
5.1 KiB
Go
// Copyright 2021 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package task
|
|
|
|
import (
|
|
"k8s.io/klog/v2"
|
|
"sigs.k8s.io/cli-utils/pkg/apply/event"
|
|
"sigs.k8s.io/cli-utils/pkg/apply/taskrunner"
|
|
"sigs.k8s.io/cli-utils/pkg/common"
|
|
"sigs.k8s.io/cli-utils/pkg/inventory"
|
|
"sigs.k8s.io/cli-utils/pkg/object"
|
|
)
|
|
|
|
// InvSetTask encapsulates structures necessary to set the
|
|
// inventory references at the end of the apply/prune.
|
|
type InvSetTask struct {
|
|
TaskName string
|
|
InvClient inventory.InventoryClient
|
|
InvInfo inventory.InventoryInfo
|
|
PrevInventory object.ObjMetadataSet
|
|
DryRun common.DryRunStrategy
|
|
}
|
|
|
|
func (i *InvSetTask) Name() string {
|
|
return i.TaskName
|
|
}
|
|
|
|
func (i *InvSetTask) Action() event.ResourceAction {
|
|
return event.InventoryAction
|
|
}
|
|
|
|
func (i *InvSetTask) Identifiers() object.ObjMetadataSet {
|
|
return object.ObjMetadataSet{}
|
|
}
|
|
|
|
// Start sets (creates or replaces) the inventory.
|
|
//
|
|
// The guiding principal is that anything in the cluster should be in the
|
|
// inventory, unless it was explicitly abandoned.
|
|
//
|
|
// This task must run after all the apply and prune tasks have completed.
|
|
//
|
|
// Added objects:
|
|
// - Applied resources (successful)
|
|
//
|
|
// Retained objects:
|
|
// - Applied resources (filtered/skipped)
|
|
// - Applied resources (failed)
|
|
// - Deleted resources (filtered/skipped) that were not abandoned
|
|
// - Deleted resources (failed)
|
|
// - Abandoned resources (failed)
|
|
//
|
|
// Removed objects:
|
|
// - Deleted resources (successful)
|
|
// - Abandoned resources (successful)
|
|
func (i *InvSetTask) Start(taskContext *taskrunner.TaskContext) {
|
|
go func() {
|
|
klog.V(2).Infof("inventory set task starting (name: %q)", i.Name())
|
|
invObjs := object.ObjMetadataSet{}
|
|
|
|
// If an object applied successfully, keep or add it to the inventory.
|
|
appliedObjs := taskContext.SuccessfulApplies()
|
|
klog.V(4).Infof("set inventory %d successful applies", len(appliedObjs))
|
|
invObjs = invObjs.Union(appliedObjs)
|
|
|
|
// If an object failed to apply and was previously stored in the inventory,
|
|
// then keep it in the inventory so it can be applied/pruned next time.
|
|
// This will remove new resources that failed to apply from the inventory,
|
|
// because even tho they were added by InvAddTask, the PrevInventory
|
|
// represents the inventory before the pipeline has run.
|
|
applyFailures := i.PrevInventory.Intersection(taskContext.FailedApplies())
|
|
klog.V(4).Infof("keep in inventory %d failed applies", len(applyFailures))
|
|
invObjs = invObjs.Union(applyFailures)
|
|
|
|
// If an object skipped apply and was previously stored in the inventory,
|
|
// then keep it in the inventory so it can be applied/pruned next time.
|
|
// It's likely that all the skipped applies are already in the inventory,
|
|
// because the apply filters all currently depend on cluster state,
|
|
// but we're doing the intersection anyway just to be sure.
|
|
applySkips := i.PrevInventory.Intersection(taskContext.SkippedApplies())
|
|
klog.V(4).Infof("keep in inventory %d skipped applies", len(applySkips))
|
|
invObjs = invObjs.Union(applySkips)
|
|
|
|
// If an object failed to delete and was previously stored in the inventory,
|
|
// then keep it in the inventory so it can be applied/pruned next time.
|
|
// It's likely that all the delete failures are already in the inventory,
|
|
// because the set of resources to prune comes from the inventory,
|
|
// but we're doing the intersection anyway just to be sure.
|
|
pruneFailures := i.PrevInventory.Intersection(taskContext.FailedDeletes())
|
|
klog.V(4).Infof("set inventory %d failed prunes", len(pruneFailures))
|
|
invObjs = invObjs.Union(pruneFailures)
|
|
|
|
// If an object skipped delete and was previously stored in the inventory,
|
|
// then keep it in the inventory so it can be applied/pruned next time.
|
|
// It's likely that all the skipped deletes are already in the inventory,
|
|
// because the set of resources to prune comes from the inventory,
|
|
// but we're doing the intersection anyway just to be sure.
|
|
pruneSkips := i.PrevInventory.Intersection(taskContext.SkippedDeletes())
|
|
klog.V(4).Infof("keep in inventory %d skipped prunes", len(pruneSkips))
|
|
invObjs = invObjs.Union(pruneSkips)
|
|
|
|
// If an object is abandoned, then remove it from the inventory.
|
|
abandonedObjects := taskContext.AbandonedObjects()
|
|
klog.V(4).Infof("remove from inventory %d abandoned objects", len(abandonedObjects))
|
|
invObjs = invObjs.Diff(abandonedObjects)
|
|
|
|
// If an object is invalid and was previously stored in the inventory,
|
|
// then keep it in the inventory so it can be applied/pruned next time.
|
|
invalidObjects := i.PrevInventory.Intersection(taskContext.InvalidObjects())
|
|
klog.V(4).Infof("keep in inventory %d invalid objects", len(invalidObjects))
|
|
invObjs = invObjs.Union(invalidObjects)
|
|
|
|
klog.V(4).Infof("set inventory %d total objects", len(invObjs))
|
|
err := i.InvClient.Replace(i.InvInfo, invObjs, i.DryRun)
|
|
|
|
klog.V(2).Infof("inventory set task completing (name: %q)", i.Name())
|
|
taskContext.TaskChannel() <- taskrunner.TaskResult{Err: err}
|
|
}()
|
|
}
|
|
|
|
// Cancel is not supported by the InvSetTask.
|
|
func (i *InvSetTask) Cancel(_ *taskrunner.TaskContext) {}
|
|
|
|
// StatusUpdate is not supported by the InvSetTask.
|
|
func (i *InvSetTask) StatusUpdate(_ *taskrunner.TaskContext, _ object.ObjMetadata) {}
|