mirror of https://github.com/fluxcd/cli-utils.git
fix: Make DependencyFilter handle DryRun
DryRun skips WaitEvents. So the DependencyFilter needs to skip checking for reconciliation if DryRun is enabled.
This commit is contained in:
parent
5c6134aeac
commit
0f7f95b24a
|
|
@ -142,7 +142,8 @@ func (a *Applier) Run(ctx context.Context, invInfo inventory.Info, objects objec
|
||||||
},
|
},
|
||||||
filter.DependencyFilter{
|
filter.DependencyFilter{
|
||||||
TaskContext: taskContext,
|
TaskContext: taskContext,
|
||||||
Strategy: actuation.ActuationStrategyApply,
|
ActuationStrategy: actuation.ActuationStrategyApply,
|
||||||
|
DryRunStrategy: options.DryRunStrategy,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Build list of prune validation filters.
|
// Build list of prune validation filters.
|
||||||
|
|
@ -157,7 +158,8 @@ func (a *Applier) Run(ctx context.Context, invInfo inventory.Info, objects objec
|
||||||
},
|
},
|
||||||
filter.DependencyFilter{
|
filter.DependencyFilter{
|
||||||
TaskContext: taskContext,
|
TaskContext: taskContext,
|
||||||
Strategy: actuation.ActuationStrategyDelete,
|
ActuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
|
DryRunStrategy: options.DryRunStrategy,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Build list of apply mutators.
|
// Build list of apply mutators.
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,8 @@ func (d *Destroyer) Run(ctx context.Context, invInfo inventory.Info, options Des
|
||||||
},
|
},
|
||||||
filter.DependencyFilter{
|
filter.DependencyFilter{
|
||||||
TaskContext: taskContext,
|
TaskContext: taskContext,
|
||||||
Strategy: actuation.ActuationStrategyDelete,
|
ActuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
|
DryRunStrategy: options.DryRunStrategy,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
taskBuilder := &solver.TaskQueueBuilder{
|
taskBuilder := &solver.TaskQueueBuilder{
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"sigs.k8s.io/cli-utils/pkg/apis/actuation"
|
"sigs.k8s.io/cli-utils/pkg/apis/actuation"
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply/taskrunner"
|
"sigs.k8s.io/cli-utils/pkg/apply/taskrunner"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/common"
|
||||||
"sigs.k8s.io/cli-utils/pkg/object"
|
"sigs.k8s.io/cli-utils/pkg/object"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -25,7 +26,8 @@ const (
|
||||||
// object can be applied or deleted based on the status of it's dependencies.
|
// object can be applied or deleted based on the status of it's dependencies.
|
||||||
type DependencyFilter struct {
|
type DependencyFilter struct {
|
||||||
TaskContext *taskrunner.TaskContext
|
TaskContext *taskrunner.TaskContext
|
||||||
Strategy actuation.ActuationStrategy
|
ActuationStrategy actuation.ActuationStrategy
|
||||||
|
DryRunStrategy common.DryRunStrategy
|
||||||
}
|
}
|
||||||
|
|
||||||
const DependencyFilterName = "DependencyFilter"
|
const DependencyFilterName = "DependencyFilter"
|
||||||
|
|
@ -40,7 +42,7 @@ func (dnrf DependencyFilter) Name() string {
|
||||||
func (dnrf DependencyFilter) Filter(obj *unstructured.Unstructured) (bool, string, error) {
|
func (dnrf DependencyFilter) Filter(obj *unstructured.Unstructured) (bool, string, error) {
|
||||||
id := object.UnstructuredToObjMetadata(obj)
|
id := object.UnstructuredToObjMetadata(obj)
|
||||||
|
|
||||||
switch dnrf.Strategy {
|
switch dnrf.ActuationStrategy {
|
||||||
case actuation.ActuationStrategyApply:
|
case actuation.ActuationStrategyApply:
|
||||||
// For apply, check dependencies (outgoing)
|
// For apply, check dependencies (outgoing)
|
||||||
for _, depID := range dnrf.TaskContext.Graph().Dependencies(id) {
|
for _, depID := range dnrf.TaskContext.Graph().Dependencies(id) {
|
||||||
|
|
@ -64,7 +66,7 @@ func (dnrf DependencyFilter) Filter(obj *unstructured.Unstructured) (bool, strin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("invalid filter strategy: %q", dnrf.Strategy))
|
panic(fmt.Sprintf("invalid filter strategy: %q", dnrf.ActuationStrategy))
|
||||||
}
|
}
|
||||||
return false, "", nil
|
return false, "", nil
|
||||||
}
|
}
|
||||||
|
|
@ -91,9 +93,9 @@ func (dnrf DependencyFilter) filterByRelationStatus(id object.ObjMetadata, relat
|
||||||
|
|
||||||
// Dependencies must have the same actuation strategy.
|
// Dependencies must have the same actuation strategy.
|
||||||
// If there is a mismatch, skip both.
|
// If there is a mismatch, skip both.
|
||||||
if status.Strategy != dnrf.Strategy {
|
if status.Strategy != dnrf.ActuationStrategy {
|
||||||
return true, fmt.Sprintf("%s skipped because %s is scheduled for %s: %q",
|
return true, fmt.Sprintf("%s skipped because %s is scheduled for %s: %q",
|
||||||
strings.ToLower(dnrf.Strategy.String()),
|
strings.ToLower(dnrf.ActuationStrategy.String()),
|
||||||
strings.ToLower(relationship.String()),
|
strings.ToLower(relationship.String()),
|
||||||
strings.ToLower(status.Strategy.String()),
|
strings.ToLower(status.Strategy.String()),
|
||||||
id), nil
|
id), nil
|
||||||
|
|
@ -103,7 +105,7 @@ func (dnrf DependencyFilter) filterByRelationStatus(id object.ObjMetadata, relat
|
||||||
case actuation.ActuationPending:
|
case actuation.ActuationPending:
|
||||||
// If actuation is still pending, dependency sorting is probably broken.
|
// If actuation is still pending, dependency sorting is probably broken.
|
||||||
return false, "", fmt.Errorf("premature %s: %s %s actuation %s: %q",
|
return false, "", fmt.Errorf("premature %s: %s %s actuation %s: %q",
|
||||||
strings.ToLower(dnrf.Strategy.String()),
|
strings.ToLower(dnrf.ActuationStrategy.String()),
|
||||||
strings.ToLower(relationship.String()),
|
strings.ToLower(relationship.String()),
|
||||||
strings.ToLower(status.Strategy.String()),
|
strings.ToLower(status.Strategy.String()),
|
||||||
strings.ToLower(status.Actuation.String()),
|
strings.ToLower(status.Actuation.String()),
|
||||||
|
|
@ -112,7 +114,7 @@ func (dnrf DependencyFilter) filterByRelationStatus(id object.ObjMetadata, relat
|
||||||
// Skip!
|
// Skip!
|
||||||
return true, fmt.Sprintf("%s %s actuation %s: %q",
|
return true, fmt.Sprintf("%s %s actuation %s: %q",
|
||||||
strings.ToLower(relationship.String()),
|
strings.ToLower(relationship.String()),
|
||||||
strings.ToLower(dnrf.Strategy.String()),
|
strings.ToLower(dnrf.ActuationStrategy.String()),
|
||||||
strings.ToLower(status.Actuation.String()),
|
strings.ToLower(status.Actuation.String()),
|
||||||
id), nil
|
id), nil
|
||||||
case actuation.ActuationSucceeded:
|
case actuation.ActuationSucceeded:
|
||||||
|
|
@ -124,11 +126,17 @@ func (dnrf DependencyFilter) filterByRelationStatus(id object.ObjMetadata, relat
|
||||||
id)
|
id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DryRun skips WaitTasks, so reconcile status can be ignored
|
||||||
|
if dnrf.DryRunStrategy.ClientOrServerDryRun() {
|
||||||
|
// Don't skip!
|
||||||
|
return false, "", nil
|
||||||
|
}
|
||||||
|
|
||||||
switch status.Reconcile {
|
switch status.Reconcile {
|
||||||
case actuation.ReconcilePending:
|
case actuation.ReconcilePending:
|
||||||
// If reconcile is still pending, dependency sorting is probably broken.
|
// If reconcile is still pending, dependency sorting is probably broken.
|
||||||
return false, "", fmt.Errorf("premature %s: %s %s reconcile %s: %q",
|
return false, "", fmt.Errorf("premature %s: %s %s reconcile %s: %q",
|
||||||
strings.ToLower(dnrf.Strategy.String()),
|
strings.ToLower(dnrf.ActuationStrategy.String()),
|
||||||
strings.ToLower(relationship.String()),
|
strings.ToLower(relationship.String()),
|
||||||
strings.ToLower(status.Strategy.String()),
|
strings.ToLower(status.Strategy.String()),
|
||||||
strings.ToLower(status.Reconcile.String()),
|
strings.ToLower(status.Reconcile.String()),
|
||||||
|
|
@ -137,7 +145,7 @@ func (dnrf DependencyFilter) filterByRelationStatus(id object.ObjMetadata, relat
|
||||||
// Skip!
|
// Skip!
|
||||||
return true, fmt.Sprintf("%s %s reconcile %s: %q",
|
return true, fmt.Sprintf("%s %s reconcile %s: %q",
|
||||||
strings.ToLower(relationship.String()),
|
strings.ToLower(relationship.String()),
|
||||||
strings.ToLower(dnrf.Strategy.String()),
|
strings.ToLower(dnrf.ActuationStrategy.String()),
|
||||||
strings.ToLower(status.Reconcile.String()),
|
strings.ToLower(status.Reconcile.String()),
|
||||||
id), nil
|
id), nil
|
||||||
case actuation.ReconcileSucceeded:
|
case actuation.ReconcileSucceeded:
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"sigs.k8s.io/cli-utils/pkg/apis/actuation"
|
"sigs.k8s.io/cli-utils/pkg/apis/actuation"
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply/taskrunner"
|
"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/inventory"
|
||||||
"sigs.k8s.io/cli-utils/pkg/object"
|
"sigs.k8s.io/cli-utils/pkg/object"
|
||||||
)
|
)
|
||||||
|
|
@ -43,7 +44,8 @@ var idB = object.ObjMetadata{
|
||||||
|
|
||||||
func TestDependencyFilter(t *testing.T) {
|
func TestDependencyFilter(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
strategy actuation.ActuationStrategy
|
dryRunStrategy common.DryRunStrategy
|
||||||
|
actuationStrategy actuation.ActuationStrategy
|
||||||
contextSetup func(*taskrunner.TaskContext)
|
contextSetup func(*taskrunner.TaskContext)
|
||||||
id object.ObjMetadata
|
id object.ObjMetadata
|
||||||
expectedFiltered bool
|
expectedFiltered bool
|
||||||
|
|
@ -51,7 +53,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError error
|
expectedError error
|
||||||
}{
|
}{
|
||||||
"apply A (no deps)": {
|
"apply A (no deps)": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.InventoryManager().AddPendingApply(idA)
|
taskContext.InventoryManager().AddPendingApply(idA)
|
||||||
|
|
@ -62,7 +64,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"apply A (A -> B) when B is invalid": {
|
"apply A (A -> B) when B is invalid": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idInvalid)
|
taskContext.Graph().AddVertex(idInvalid)
|
||||||
|
|
@ -76,7 +78,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"apply A (A -> B) before B is applied": {
|
"apply A (A -> B) before B is applied": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -88,7 +90,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: fmt.Errorf("premature apply: dependency apply actuation pending: %q", idB),
|
expectedError: fmt.Errorf("premature apply: dependency apply actuation pending: %q", idB),
|
||||||
},
|
},
|
||||||
"apply A (A -> B) before B is reconciled": {
|
"apply A (A -> B) before B is reconciled": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -105,7 +107,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: fmt.Errorf("premature apply: dependency apply reconcile pending: %q", idB),
|
expectedError: fmt.Errorf("premature apply: dependency apply reconcile pending: %q", idB),
|
||||||
},
|
},
|
||||||
"apply A (A -> B) after B is reconciled": {
|
"apply A (A -> B) after B is reconciled": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -124,7 +126,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"apply A (A -> B) after B apply failed": {
|
"apply A (A -> B) after B apply failed": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -143,7 +145,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"apply A (A -> B) after B apply skipped": {
|
"apply A (A -> B) after B apply skipped": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -162,7 +164,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"apply A (A -> B) after B reconcile failed": {
|
"apply A (A -> B) after B reconcile failed": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -181,7 +183,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"apply A (A -> B) after B reconcile timeout": {
|
"apply A (A -> B) after B reconcile timeout": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -201,7 +203,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
},
|
},
|
||||||
// artificial use case: reconcile should only be skipped if apply failed or was skipped
|
// artificial use case: reconcile should only be skipped if apply failed or was skipped
|
||||||
"apply A (A -> B) after B reconcile skipped": {
|
"apply A (A -> B) after B reconcile skipped": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -220,7 +222,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"apply A (A -> B) when B delete pending": {
|
"apply A (A -> B) when B delete pending": {
|
||||||
strategy: actuation.ActuationStrategyApply,
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -234,7 +236,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"delete B (no deps)": {
|
"delete B (no deps)": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
taskContext.InventoryManager().AddPendingDelete(idB)
|
taskContext.InventoryManager().AddPendingDelete(idB)
|
||||||
|
|
@ -245,7 +247,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"delete B (A -> B) when A is invalid": {
|
"delete B (A -> B) when A is invalid": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idInvalid)
|
taskContext.Graph().AddVertex(idInvalid)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -259,7 +261,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"delete B (A -> B) before A is deleted": {
|
"delete B (A -> B) before A is deleted": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -271,7 +273,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: fmt.Errorf("premature delete: dependent delete actuation pending: %q", idA),
|
expectedError: fmt.Errorf("premature delete: dependent delete actuation pending: %q", idA),
|
||||||
},
|
},
|
||||||
"delete B (A -> B) before A is reconciled": {
|
"delete B (A -> B) before A is reconciled": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -288,7 +290,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: fmt.Errorf("premature delete: dependent delete reconcile pending: %q", idA),
|
expectedError: fmt.Errorf("premature delete: dependent delete reconcile pending: %q", idA),
|
||||||
},
|
},
|
||||||
"delete B (A -> B) after A is reconciled": {
|
"delete B (A -> B) after A is reconciled": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -307,7 +309,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"delete B (A -> B) after A delete failed": {
|
"delete B (A -> B) after A delete failed": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -326,7 +328,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"delete B (A -> B) after A delete skipped": {
|
"delete B (A -> B) after A delete skipped": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -346,7 +348,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
},
|
},
|
||||||
// artificial use case: delete reconcile can't fail, only timeout
|
// artificial use case: delete reconcile can't fail, only timeout
|
||||||
"delete B (A -> B) after A reconcile failed": {
|
"delete B (A -> B) after A reconcile failed": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -365,7 +367,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"delete B (A -> B) after A reconcile timeout": {
|
"delete B (A -> B) after A reconcile timeout": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -385,7 +387,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
},
|
},
|
||||||
// artificial use case: reconcile should only be skipped if delete failed or was skipped
|
// artificial use case: reconcile should only be skipped if delete failed or was skipped
|
||||||
"delete B (A -> B) after A reconcile skipped": {
|
"delete B (A -> B) after A reconcile skipped": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -404,7 +406,7 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
"delete B (A -> B) when A apply succeeded": {
|
"delete B (A -> B) when A apply succeeded": {
|
||||||
strategy: actuation.ActuationStrategyDelete,
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
taskContext.Graph().AddVertex(idA)
|
taskContext.Graph().AddVertex(idA)
|
||||||
taskContext.Graph().AddVertex(idB)
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
|
@ -422,6 +424,46 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
expectedReason: fmt.Sprintf("delete skipped because dependent is scheduled for apply: %q", idA),
|
expectedReason: fmt.Sprintf("delete skipped because dependent is scheduled for apply: %q", idA),
|
||||||
expectedError: nil,
|
expectedError: nil,
|
||||||
},
|
},
|
||||||
|
"DryRun: apply A (A -> B) when B apply reconcile pending": {
|
||||||
|
dryRunStrategy: common.DryRunClient,
|
||||||
|
actuationStrategy: actuation.ActuationStrategyApply,
|
||||||
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
|
taskContext.Graph().AddVertex(idA)
|
||||||
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
taskContext.Graph().AddEdge(idA, idB)
|
||||||
|
taskContext.InventoryManager().AddPendingApply(idA)
|
||||||
|
taskContext.InventoryManager().SetObjectStatus(actuation.ObjectStatus{
|
||||||
|
ObjectReference: inventory.ObjectReferenceFromObjMetadata(idB),
|
||||||
|
Strategy: actuation.ActuationStrategyApply,
|
||||||
|
Actuation: actuation.ActuationSucceeded,
|
||||||
|
Reconcile: actuation.ReconcilePending,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
id: idA,
|
||||||
|
expectedFiltered: false,
|
||||||
|
expectedReason: "",
|
||||||
|
expectedError: nil,
|
||||||
|
},
|
||||||
|
"DryRun: delete B (A -> B) when A delete reconcile pending": {
|
||||||
|
dryRunStrategy: common.DryRunClient,
|
||||||
|
actuationStrategy: actuation.ActuationStrategyDelete,
|
||||||
|
contextSetup: func(taskContext *taskrunner.TaskContext) {
|
||||||
|
taskContext.Graph().AddVertex(idA)
|
||||||
|
taskContext.Graph().AddVertex(idB)
|
||||||
|
taskContext.Graph().AddEdge(idA, idB)
|
||||||
|
taskContext.InventoryManager().AddPendingDelete(idB)
|
||||||
|
taskContext.InventoryManager().SetObjectStatus(actuation.ObjectStatus{
|
||||||
|
ObjectReference: inventory.ObjectReferenceFromObjMetadata(idA),
|
||||||
|
Strategy: actuation.ActuationStrategyDelete,
|
||||||
|
Actuation: actuation.ActuationSucceeded,
|
||||||
|
Reconcile: actuation.ReconcilePending,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
id: idB,
|
||||||
|
expectedFiltered: false,
|
||||||
|
expectedReason: "",
|
||||||
|
expectedError: nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
|
|
@ -431,7 +473,8 @@ func TestDependencyFilter(t *testing.T) {
|
||||||
|
|
||||||
filter := DependencyFilter{
|
filter := DependencyFilter{
|
||||||
TaskContext: taskContext,
|
TaskContext: taskContext,
|
||||||
Strategy: tc.strategy,
|
ActuationStrategy: tc.actuationStrategy,
|
||||||
|
DryRunStrategy: tc.dryRunStrategy,
|
||||||
}
|
}
|
||||||
obj := defaultObj.DeepCopy()
|
obj := defaultObj.DeepCopy()
|
||||||
obj.SetGroupVersionKind(tc.id.GroupKind.WithVersion("v1"))
|
obj.SetGroupVersionKind(tc.id.GroupKind.WithVersion("v1"))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,301 @@
|
||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package e2e
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/apply"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/apply/event"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/common"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/inventory"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/object"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/testutil"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func dryRunTest(ctx context.Context, c client.Client, invConfig InventoryConfig, inventoryName, namespaceName string) {
|
||||||
|
By("Apply with DryRun")
|
||||||
|
applier := invConfig.ApplierFactoryFunc()
|
||||||
|
inventoryID := fmt.Sprintf("%s-%s", inventoryName, namespaceName)
|
||||||
|
|
||||||
|
inventoryInfo := createInventoryInfo(invConfig, inventoryName, namespaceName, inventoryID)
|
||||||
|
|
||||||
|
namespace1Name := fmt.Sprintf("%s-ns1", namespaceName)
|
||||||
|
|
||||||
|
fields := struct{ Namespace string }{Namespace: namespace1Name}
|
||||||
|
namespace1Obj := templateToUnstructured(namespaceTemplate, fields)
|
||||||
|
podBObj := templateToUnstructured(podBTemplate, fields)
|
||||||
|
|
||||||
|
// Dependency order: podB -> namespace1
|
||||||
|
// Apply order: namespace1, podB
|
||||||
|
resources := []*unstructured.Unstructured{
|
||||||
|
namespace1Obj,
|
||||||
|
podBObj,
|
||||||
|
}
|
||||||
|
|
||||||
|
applierEvents := runCollect(applier.Run(ctx, inventoryInfo, resources, apply.ApplierOptions{
|
||||||
|
ReconcileTimeout: 2 * time.Minute,
|
||||||
|
EmitStatusEvents: true,
|
||||||
|
DryRunStrategy: common.DryRunClient,
|
||||||
|
}))
|
||||||
|
|
||||||
|
expEvents := []testutil.ExpEvent{
|
||||||
|
{
|
||||||
|
// InitTask
|
||||||
|
EventType: event.InitType,
|
||||||
|
InitEvent: &testutil.ExpInitEvent{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// InvAddTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
GroupName: "inventory-add-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// InvAddTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
GroupName: "inventory-add-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// ApplyTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.ApplyAction,
|
||||||
|
GroupName: "apply-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Create namespace
|
||||||
|
EventType: event.ApplyType,
|
||||||
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
|
GroupName: "apply-0",
|
||||||
|
Operation: event.Created,
|
||||||
|
Identifier: object.UnstructuredToObjMetadata(namespace1Obj),
|
||||||
|
Error: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// ApplyTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.ApplyAction,
|
||||||
|
GroupName: "apply-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// ApplyTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.ApplyAction,
|
||||||
|
GroupName: "apply-1",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Create pod
|
||||||
|
EventType: event.ApplyType,
|
||||||
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
|
GroupName: "apply-1",
|
||||||
|
Operation: event.Created,
|
||||||
|
Identifier: object.UnstructuredToObjMetadata(podBObj),
|
||||||
|
Error: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// ApplyTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.ApplyAction,
|
||||||
|
GroupName: "apply-1",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// No Wait Tasks for Dry Run
|
||||||
|
{
|
||||||
|
// InvSetTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
GroupName: "inventory-set-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// InvSetTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
GroupName: "inventory-set-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
received := testutil.EventsToExpEvents(applierEvents)
|
||||||
|
|
||||||
|
// handle required async NotFound StatusEvent for pod
|
||||||
|
expected := testutil.ExpEvent{
|
||||||
|
EventType: event.StatusType,
|
||||||
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
|
Identifier: object.UnstructuredToObjMetadata(podBObj),
|
||||||
|
Status: status.NotFoundStatus,
|
||||||
|
Error: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
received, matches := testutil.RemoveEqualEvents(received, expected)
|
||||||
|
Expect(matches).To(BeNumerically(">=", 1), "unexpected number of %q status events for namespace", status.NotFoundStatus)
|
||||||
|
|
||||||
|
// handle required async NotFound StatusEvent for namespace
|
||||||
|
expected = testutil.ExpEvent{
|
||||||
|
EventType: event.StatusType,
|
||||||
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
|
Identifier: object.UnstructuredToObjMetadata(namespace1Obj),
|
||||||
|
Status: status.NotFoundStatus,
|
||||||
|
Error: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
received, matches = testutil.RemoveEqualEvents(received, expected)
|
||||||
|
Expect(matches).To(BeNumerically(">=", 1), "unexpected number of %q status events for pod", status.NotFoundStatus)
|
||||||
|
|
||||||
|
Expect(received).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
|
By("Verify pod NotFound")
|
||||||
|
assertUnstructuredDoesNotExist(ctx, c, podBObj)
|
||||||
|
|
||||||
|
By("Verify inventory NotFound")
|
||||||
|
invConfig.InvNotExistsFunc(ctx, c, inventoryName, namespaceName, inventoryID)
|
||||||
|
|
||||||
|
By("Apply")
|
||||||
|
runWithNoErr(applier.Run(ctx, inventoryInfo, resources, apply.ApplierOptions{
|
||||||
|
ReconcileTimeout: 2 * time.Minute,
|
||||||
|
}))
|
||||||
|
|
||||||
|
By("Verify pod created")
|
||||||
|
assertUnstructuredExists(ctx, c, podBObj)
|
||||||
|
|
||||||
|
By("Verify inventory size")
|
||||||
|
invConfig.InvSizeVerifyFunc(ctx, c, inventoryName, namespaceName, inventoryID, 2)
|
||||||
|
|
||||||
|
By("Destroy with DryRun")
|
||||||
|
destroyer := invConfig.DestroyerFactoryFunc()
|
||||||
|
|
||||||
|
destroyerEvents := runCollect(destroyer.Run(ctx, inventoryInfo, apply.DestroyerOptions{
|
||||||
|
InventoryPolicy: inventory.PolicyAdoptIfNoInventory,
|
||||||
|
EmitStatusEvents: true,
|
||||||
|
DryRunStrategy: common.DryRunClient,
|
||||||
|
}))
|
||||||
|
|
||||||
|
expEvents = []testutil.ExpEvent{
|
||||||
|
{
|
||||||
|
// InitTask
|
||||||
|
EventType: event.InitType,
|
||||||
|
InitEvent: &testutil.ExpInitEvent{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// PruneTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.DeleteAction,
|
||||||
|
GroupName: "prune-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Delete pod
|
||||||
|
EventType: event.DeleteType,
|
||||||
|
DeleteEvent: &testutil.ExpDeleteEvent{
|
||||||
|
GroupName: "prune-0",
|
||||||
|
Operation: event.Deleted,
|
||||||
|
Identifier: object.UnstructuredToObjMetadata(podBObj),
|
||||||
|
Error: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// PruneTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.DeleteAction,
|
||||||
|
GroupName: "prune-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// PruneTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.DeleteAction,
|
||||||
|
GroupName: "prune-1",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Delete namespace
|
||||||
|
EventType: event.DeleteType,
|
||||||
|
DeleteEvent: &testutil.ExpDeleteEvent{
|
||||||
|
GroupName: "prune-1",
|
||||||
|
Operation: event.Deleted,
|
||||||
|
Identifier: object.UnstructuredToObjMetadata(namespace1Obj),
|
||||||
|
Error: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// PruneTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.DeleteAction,
|
||||||
|
GroupName: "prune-1",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// No Wait Tasks for Dry Run
|
||||||
|
{
|
||||||
|
// DeleteInvTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
GroupName: "delete-inventory-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// DeleteInvTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
GroupName: "delete-inventory-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Expect(testutil.EventsToExpEvents(destroyerEvents)).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
|
By("Verify pod still exists")
|
||||||
|
assertUnstructuredExists(ctx, c, podBObj)
|
||||||
|
|
||||||
|
By("Destroy")
|
||||||
|
runWithNoErr(destroyer.Run(ctx, inventoryInfo, apply.DestroyerOptions{
|
||||||
|
InventoryPolicy: inventory.PolicyAdoptIfNoInventory,
|
||||||
|
}))
|
||||||
|
|
||||||
|
By("Verify pod deleted")
|
||||||
|
assertUnstructuredDoesNotExist(ctx, c, podBObj)
|
||||||
|
|
||||||
|
By("Verify inventory deleted")
|
||||||
|
invConfig.InvNotExistsFunc(ctx, c, inventoryName, namespaceName, inventoryID)
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,7 @@ type applierFactoryFunc func() *apply.Applier
|
||||||
type destroyerFactoryFunc func() *apply.Destroyer
|
type destroyerFactoryFunc func() *apply.Destroyer
|
||||||
type invSizeVerifyFunc func(ctx context.Context, c client.Client, name, namespace, id string, count int)
|
type invSizeVerifyFunc func(ctx context.Context, c client.Client, name, namespace, id string, count int)
|
||||||
type invCountVerifyFunc func(ctx context.Context, c client.Client, namespace string, count int)
|
type invCountVerifyFunc func(ctx context.Context, c client.Client, namespace string, count int)
|
||||||
|
type invNotExistsFunc func(ctx context.Context, c client.Client, name, namespace, id string)
|
||||||
|
|
||||||
type InventoryConfig struct {
|
type InventoryConfig struct {
|
||||||
Strategy inventory.Strategy
|
Strategy inventory.Strategy
|
||||||
|
|
@ -45,6 +46,7 @@ type InventoryConfig struct {
|
||||||
DestroyerFactoryFunc destroyerFactoryFunc
|
DestroyerFactoryFunc destroyerFactoryFunc
|
||||||
InvSizeVerifyFunc invSizeVerifyFunc
|
InvSizeVerifyFunc invSizeVerifyFunc
|
||||||
InvCountVerifyFunc invCountVerifyFunc
|
InvCountVerifyFunc invCountVerifyFunc
|
||||||
|
InvNotExistsFunc invNotExistsFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -61,6 +63,7 @@ var inventoryConfigs = map[string]InventoryConfig{
|
||||||
DestroyerFactoryFunc: newDefaultInvDestroyer,
|
DestroyerFactoryFunc: newDefaultInvDestroyer,
|
||||||
InvSizeVerifyFunc: defaultInvSizeVerifyFunc,
|
InvSizeVerifyFunc: defaultInvSizeVerifyFunc,
|
||||||
InvCountVerifyFunc: defaultInvCountVerifyFunc,
|
InvCountVerifyFunc: defaultInvCountVerifyFunc,
|
||||||
|
InvNotExistsFunc: defaultInvNotExistsFunc,
|
||||||
},
|
},
|
||||||
CustomTypeInvConfig: {
|
CustomTypeInvConfig: {
|
||||||
Strategy: inventory.NameStrategy,
|
Strategy: inventory.NameStrategy,
|
||||||
|
|
@ -70,6 +73,7 @@ var inventoryConfigs = map[string]InventoryConfig{
|
||||||
DestroyerFactoryFunc: newCustomInvDestroyer,
|
DestroyerFactoryFunc: newCustomInvDestroyer,
|
||||||
InvSizeVerifyFunc: customInvSizeVerifyFunc,
|
InvSizeVerifyFunc: customInvSizeVerifyFunc,
|
||||||
InvCountVerifyFunc: customInvCountVerifyFunc,
|
InvCountVerifyFunc: customInvCountVerifyFunc,
|
||||||
|
InvNotExistsFunc: customInvNotExistsFunc,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,6 +167,10 @@ var _ = Describe("Applier", func() {
|
||||||
applyAndDestroyTest(ctx, c, invConfig, inventoryName, namespace.GetName())
|
applyAndDestroyTest(ctx, c, invConfig, inventoryName, namespace.GetName())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("DryRun", func() {
|
||||||
|
dryRunTest(ctx, c, invConfig, inventoryName, namespace.GetName())
|
||||||
|
})
|
||||||
|
|
||||||
It("Deletion Prevention", func() {
|
It("Deletion Prevention", func() {
|
||||||
deletionPreventionTest(ctx, c, invConfig, inventoryName, namespace.GetName())
|
deletionPreventionTest(ctx, c, invConfig, inventoryName, namespace.GetName())
|
||||||
})
|
})
|
||||||
|
|
@ -340,6 +348,15 @@ func newDefaultInvDestroyer() *apply.Destroyer {
|
||||||
return newDestroyerFromInvFactory(inventory.ClusterClientFactory{})
|
return newDestroyerFromInvFactory(inventory.ClusterClientFactory{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func defaultInvNotExistsFunc(ctx context.Context, c client.Client, name, namespace, id string) {
|
||||||
|
var cmList v1.ConfigMapList
|
||||||
|
err := c.List(ctx, &cmList,
|
||||||
|
client.MatchingLabels(map[string]string{common.InventoryLabel: id}),
|
||||||
|
client.InNamespace(namespace))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(cmList.Items).To(HaveLen(0), "expected inventory list to be empty")
|
||||||
|
}
|
||||||
|
|
||||||
func defaultInvSizeVerifyFunc(ctx context.Context, c client.Client, name, namespace, id string, count int) {
|
func defaultInvSizeVerifyFunc(ctx context.Context, c client.Client, name, namespace, id string, count int) {
|
||||||
var cmList v1.ConfigMapList
|
var cmList v1.ConfigMapList
|
||||||
err := c.List(ctx, &cmList,
|
err := c.List(ctx, &cmList,
|
||||||
|
|
@ -376,6 +393,14 @@ func newFactory() util.Factory {
|
||||||
return util.NewFactory(matchVersionKubeConfigFlags)
|
return util.NewFactory(matchVersionKubeConfigFlags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func customInvNotExistsFunc(ctx context.Context, c client.Client, name, namespace, id string) {
|
||||||
|
var u unstructured.Unstructured
|
||||||
|
u.SetGroupVersionKind(customprovider.InventoryGVK)
|
||||||
|
u.SetName(name)
|
||||||
|
u.SetNamespace(namespace)
|
||||||
|
assertUnstructuredDoesNotExist(ctx, c, &u)
|
||||||
|
}
|
||||||
|
|
||||||
func customInvSizeVerifyFunc(ctx context.Context, c client.Client, name, namespace, _ string, count int) {
|
func customInvSizeVerifyFunc(ctx context.Context, c client.Client, name, namespace, _ string, count int) {
|
||||||
var u unstructured.Unstructured
|
var u unstructured.Unstructured
|
||||||
u.SetGroupVersionKind(customprovider.InventoryGVK)
|
u.SetGroupVersionKind(customprovider.InventoryGVK)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue