forked from kubernetes-sigs/cli-utils
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Pass TaskContext into TaskBuilder.Build - Combine dependency graph for apply and prune objects. This is required to catch dependencies that would have been deleted. - Replace graph.SortObjs into DependencyGraph + Sort + HydrateSetList - Replace graph.ReverseSortObjs with ReverseSetList to perform on the combined (apply + prune) set list. - Add planned pending applies and prune to the InventoryManager before executing the task queue. This allows the DependencyFilter to validate against the planned actuation strategy of objects that haven't been applied/pruned yet. - Add the dependency graph to the TaskContext, for the DependencyFilter to use. This can be removed in the future if the filters are managed by the solver. - Make Graph.Sort non-destructive, so the graph can be re-used by the DependencyFilter. - Add Graph.EdgesFrom and EdgesTo for the DependencyFilter to use. This requires storing the reverse edge list. - Add an e2e test for the DependencyFilter - Add an e2e test for the LocalNamespaceFilter Fixes kubernetes-sigs#526 Fixes kubernetes-sigs#528 Fixes kubernetes-sigs#554
- Loading branch information
Showing
15 changed files
with
1,220 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Copyright 2020 The Kubernetes Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package filter | ||
|
||
import ( | ||
"fmt" | ||
|
||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
"sigs.k8s.io/cli-utils/pkg/apis/actuation" | ||
"sigs.k8s.io/cli-utils/pkg/apply/taskrunner" | ||
"sigs.k8s.io/cli-utils/pkg/object" | ||
) | ||
|
||
// DependencyFilter implements ValidationFilter interface to determine if an | ||
// object can be applied or deleted based on the status of it's dependencies. | ||
type DependencyFilter struct { | ||
TaskContext *taskrunner.TaskContext | ||
Strategy actuation.ActuationStrategy | ||
} | ||
|
||
const DependencyFilterName = "DependencyFilter" | ||
|
||
// Name returns the name of the filter for logs and events. | ||
func (dnrf DependencyFilter) Name() string { | ||
return DependencyFilterName | ||
} | ||
|
||
// Filter returns true if the specified object should be skipped because at | ||
// least one of its dependencies is Not Found or Not Reconciled. | ||
func (dnrf DependencyFilter) Filter(obj *unstructured.Unstructured) (bool, string, error) { | ||
id := object.UnstructuredToObjMetadata(obj) | ||
|
||
switch dnrf.Strategy { | ||
case actuation.ActuationStrategyApply: | ||
// For apply, check dependencies (outgoing) | ||
relationship := "dependency" | ||
for _, depID := range dnrf.TaskContext.Graph().EdgesFrom(id) { | ||
filter, reason, err := dnrf.filterByRelationStatus(depID, relationship) | ||
if err != nil { | ||
return false, "", err | ||
} | ||
if filter { | ||
return filter, reason, nil | ||
} | ||
} | ||
case actuation.ActuationStrategyDelete: | ||
// For delete, check dependents (incoming) | ||
relationship := "dependent" | ||
for _, depID := range dnrf.TaskContext.Graph().EdgesTo(id) { | ||
filter, reason, err := dnrf.filterByRelationStatus(depID, relationship) | ||
if err != nil { | ||
return false, "", err | ||
} | ||
if filter { | ||
return filter, reason, nil | ||
} | ||
} | ||
default: | ||
panic(fmt.Sprintf("invalid filter strategy: %q", dnrf.Strategy)) | ||
} | ||
return false, "", nil | ||
} | ||
|
||
func (dnrf DependencyFilter) filterByRelationStatus(id object.ObjMetadata, relationship string) (bool, string, error) { | ||
// Skip invalid objects. | ||
// This shouldn't happen, because invalid objects are excluded by the solver. | ||
if dnrf.TaskContext.IsInvalidObject(id) { | ||
return true, fmt.Sprintf("%s invalid: %q", relationship, id), nil | ||
} | ||
|
||
status, found := dnrf.TaskContext.InventoryManager().ObjectStatus(id) | ||
if !found { | ||
// Status is registered during planning. | ||
// So if status is not found, the object is external (NYI) or invalid. | ||
return false, "", fmt.Errorf("unknown %s actuation strategy: %v", relationship, id) | ||
} | ||
|
||
// Dependencies must have the same actuation strategy. | ||
// If there is a mismatch, skip both. | ||
if status.Strategy != dnrf.Strategy { | ||
return true, fmt.Sprintf("%s skipped because %s is scheduled for %s: %q", dnrf.Strategy, relationship, status.Strategy, id), nil | ||
} | ||
|
||
switch status.Actuation { | ||
case actuation.ActuationPending: | ||
// If actuation is still pending, dependency sorting is probably broken. | ||
return false, "", fmt.Errorf("premature actuation: %s %s %s: %q", relationship, dnrf.Strategy, status.Actuation, id) | ||
case actuation.ActuationSkipped, actuation.ActuationFailed: | ||
// Skip! | ||
return true, fmt.Sprintf("%s %s %s: %q", relationship, dnrf.Strategy, status.Actuation, id), nil | ||
case actuation.ActuationSucceeded: | ||
// Don't skip! | ||
default: | ||
return false, "", fmt.Errorf("invalid %s apply status %q: %q", relationship, status.Actuation, id) | ||
} | ||
|
||
switch status.Reconcile { | ||
case actuation.ReconcilePending: | ||
// If reconcile is still pending, dependency sorting is probably broken. | ||
return false, "", fmt.Errorf("premature reconciliation: %s reconcile %s: %q", relationship, status.Reconcile, id) | ||
case actuation.ReconcileSkipped, actuation.ReconcileFailed, actuation.ReconcileTimeout: | ||
// Skip! | ||
return true, fmt.Sprintf("%s reconcile %s: %q", relationship, status.Reconcile, id), nil | ||
case actuation.ReconcileSucceeded: | ||
// Don't skip! | ||
default: | ||
return false, "", fmt.Errorf("invalid dependency reconcile status %q: %q", status.Reconcile, id) | ||
} | ||
|
||
// Don't skip! | ||
return false, "", nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.