Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object-level prune propagation policy, propagation policy for kubectl replace #561

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
5 changes: 4 additions & 1 deletion pkg/sync/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ const (
// Sync option that disables resource deletion
SyncOptionDisableDeletion = "Delete=false"
// Sync option that sync only out of sync resources
SyncOptionApplyOutOfSyncOnly = "ApplyOutOfSyncOnly=true"
SyncOptionApplyOutOfSyncOnly = "ApplyOutOfSyncOnly=true"
SyncOptionPrunePropagationPolicyForeground = "PrunePropagationPolicy=foreground"
SyncOptionPrunePropagationPolicyBackground = "PrunePropagationPolicy=background"
SyncOptionPrunePropagationPolicyOrphan = "PrunePropagationPolicy=orphan"
)

type PermissionValidator func(un *unstructured.Unstructured, res *metav1.APIResource) error
Expand Down
33 changes: 30 additions & 3 deletions pkg/sync/sync_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,19 @@ func (sc *syncContext) applyObject(t *syncTask, dryRun, validate bool) (common.R
var message string
shouldReplace := sc.replace || resourceutil.HasAnnotationOption(t.targetObj, common.AnnotationSyncOptions, common.SyncOptionReplace)
force := sc.force || resourceutil.HasAnnotationOption(t.targetObj, common.AnnotationSyncOptions, common.SyncOptionForce)
// Default to foreground deletion, use sync context policy, then use object-level config
prunePropagationPolicy := metav1.DeletePropagationForeground
if sc.prunePropagationPolicy != nil {
prunePropagationPolicy = *sc.prunePropagationPolicy
}
switch {
case resourceutil.HasAnnotationOption(t.targetObj, common.AnnotationSyncOptions, common.SyncOptionPrunePropagationPolicyBackground):
prunePropagationPolicy = metav1.DeletePropagationBackground
case resourceutil.HasAnnotationOption(t.targetObj, common.AnnotationSyncOptions, common.SyncOptionPrunePropagationPolicyForeground):
prunePropagationPolicy = metav1.DeletePropagationForeground
case resourceutil.HasAnnotationOption(t.targetObj, common.AnnotationSyncOptions, common.SyncOptionPrunePropagationPolicyOrphan):
prunePropagationPolicy = metav1.DeletePropagationOrphan
}
// if it is a dry run, disable server side apply, as the goal is to validate only the
// yaml correctness of the rendered manifests.
// running dry-run in server mode breaks the auto create namespace feature
Expand All @@ -975,13 +988,13 @@ func (sc *syncContext) applyObject(t *syncTask, dryRun, validate bool) (common.R
message = fmt.Sprintf("error when updating: %v", err.Error())
}
} else {
message, err = sc.resourceOps.ReplaceResource(context.TODO(), t.targetObj, dryRunStrategy, force)
message, err = sc.resourceOps.ReplaceResource(context.TODO(), t.targetObj, dryRunStrategy, force, prunePropagationPolicy)
}
} else {
message, err = sc.resourceOps.CreateResource(context.TODO(), t.targetObj, dryRunStrategy, validate)
}
} else {
message, err = sc.resourceOps.ApplyResource(context.TODO(), t.targetObj, dryRunStrategy, force, validate, serverSideApply, sc.serverSideApplyManager, false)
message, err = sc.resourceOps.ApplyResource(context.TODO(), t.targetObj, dryRunStrategy, force, validate, serverSideApply, sc.serverSideApplyManager, false, prunePropagationPolicy)
}
if err != nil {
return common.ResultCodeSyncFailed, err.Error()
Expand All @@ -1008,7 +1021,21 @@ func (sc *syncContext) pruneObject(liveObj *unstructured.Unstructured, prune, dr
// Skip deletion if object is already marked for deletion, so we don't cause a resource update hotloop
deletionTimestamp := liveObj.GetDeletionTimestamp()
if deletionTimestamp == nil || deletionTimestamp.IsZero() {
err := sc.kubectl.DeleteResource(context.TODO(), sc.config, liveObj.GroupVersionKind(), liveObj.GetName(), liveObj.GetNamespace(), sc.getDeleteOptions())
propagationPolicy := metav1.DeletePropagationForeground
deleteOptions := sc.getDeleteOptions()
if deleteOptions.PropagationPolicy != nil {
propagationPolicy = *deleteOptions.PropagationPolicy
}
switch {
case resourceutil.HasAnnotationOption(liveObj, common.AnnotationSyncOptions, common.SyncOptionPrunePropagationPolicyBackground):
propagationPolicy = metav1.DeletePropagationBackground
case resourceutil.HasAnnotationOption(liveObj, common.AnnotationSyncOptions, common.SyncOptionPrunePropagationPolicyForeground):
propagationPolicy = metav1.DeletePropagationForeground
case resourceutil.HasAnnotationOption(liveObj, common.AnnotationSyncOptions, common.SyncOptionPrunePropagationPolicyOrphan):
propagationPolicy = metav1.DeletePropagationOrphan
}
deleteOptions.PropagationPolicy = &propagationPolicy
err := sc.kubectl.DeleteResource(context.TODO(), sc.config, liveObj.GroupVersionKind(), liveObj.GetName(), liveObj.GetNamespace(), deleteOptions)
if err != nil {
return common.ResultCodeSyncFailed, err.Error()
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/utils/kube/kubetest/mock_resource_operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"sync"

"github.com/argoproj/gitops-engine/pkg/utils/kube"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
Expand Down Expand Up @@ -105,7 +106,7 @@ func (r *MockResourceOps) GetLastResourceCommand(key kube.ResourceKey) string {
return r.lastCommandPerResource[key]
}

func (r *MockResourceOps) ApplyResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force, validate, serverSideApply bool, manager string, serverSideDiff bool) (string, error) {
func (r *MockResourceOps) ApplyResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force, validate, serverSideApply bool, manager string, serverSideDiff bool, cascadingStrategy metav1.DeletionPropagation) (string, error) {
r.SetLastValidate(validate)
r.SetLastServerSideApply(serverSideApply)
r.SetLastServerSideApplyManager(manager)
Expand All @@ -119,7 +120,7 @@ func (r *MockResourceOps) ApplyResource(ctx context.Context, obj *unstructured.U
return command.Output, command.Err
}

func (r *MockResourceOps) ReplaceResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force bool) (string, error) {
func (r *MockResourceOps) ReplaceResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force bool, cascadingStrategy metav1.DeletionPropagation) (string, error) {
r.SetLastForce(force)
command, ok := r.Commands[obj.GetName()]
r.SetLastResourceCommand(kube.GetResourceKey(obj), "replace")
Expand Down
18 changes: 10 additions & 8 deletions pkg/utils/kube/resource_ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ import (

// ResourceOperations provides methods to manage k8s resources
type ResourceOperations interface {
ApplyResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force, validate, serverSideApply bool, manager string, serverSideDiff bool) (string, error)
ReplaceResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force bool) (string, error)
ApplyResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force, validate, serverSideApply bool, manager string, serverSideDiff bool, cascadingStrategy metav1.DeletionPropagation) (string, error)
ReplaceResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force bool, cascadingStrategy metav1.DeletionPropagation) (string, error)
CreateResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, validate bool) (string, error)
UpdateResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy) (*unstructured.Unstructured, error)
}
Expand Down Expand Up @@ -159,7 +159,7 @@ func kubeCmdFactory(kubeconfig, ns string, config *rest.Config) cmdutil.Factory
return cmdutil.NewFactory(matchVersionKubeConfigFlags)
}

func (k *kubectlResourceOperations) ReplaceResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force bool) (string, error) {
func (k *kubectlResourceOperations) ReplaceResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force bool, cascadingStrategy metav1.DeletionPropagation) (string, error) {
span := k.tracer.StartSpan("ReplaceResource")
span.SetBaggageItem("kind", obj.GetKind())
span.SetBaggageItem("name", obj.GetName())
Expand All @@ -172,7 +172,7 @@ func (k *kubectlResourceOperations) ReplaceResource(ctx context.Context, obj *un
}
defer cleanup()

replaceOptions, err := k.newReplaceOptions(k.config, f, ioStreams, fileName, obj.GetNamespace(), force, dryRunStrategy)
replaceOptions, err := k.newReplaceOptions(k.config, f, ioStreams, fileName, obj.GetNamespace(), force, dryRunStrategy, cascadingStrategy)
if err != nil {
return err
}
Expand Down Expand Up @@ -240,7 +240,7 @@ func (k *kubectlResourceOperations) UpdateResource(ctx context.Context, obj *uns
}

// ApplyResource performs an apply of a unstructured resource
func (k *kubectlResourceOperations) ApplyResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force, validate, serverSideApply bool, manager string, serverSideDiff bool) (string, error) {
func (k *kubectlResourceOperations) ApplyResource(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, force, validate, serverSideApply bool, manager string, serverSideDiff bool, cascadingStrategy metav1.DeletionPropagation) (string, error) {
span := k.tracer.StartSpan("ApplyResource")
span.SetBaggageItem("kind", obj.GetKind())
span.SetBaggageItem("name", obj.GetName())
Expand All @@ -258,15 +258,15 @@ func (k *kubectlResourceOperations) ApplyResource(ctx context.Context, obj *unst
}
defer cleanup()

applyOpts, err := k.newApplyOptions(ioStreams, obj, fileName, validate, force, serverSideApply, dryRunStrategy, manager, serverSideDiff)
applyOpts, err := k.newApplyOptions(ioStreams, obj, fileName, validate, force, serverSideApply, dryRunStrategy, manager, serverSideDiff, cascadingStrategy)
if err != nil {
return err
}
return applyOpts.Run()
})
}

func (k *kubectlResourceOperations) newApplyOptions(ioStreams genericclioptions.IOStreams, obj *unstructured.Unstructured, fileName string, validate bool, force, serverSideApply bool, dryRunStrategy cmdutil.DryRunStrategy, manager string, serverSideDiff bool) (*apply.ApplyOptions, error) {
func (k *kubectlResourceOperations) newApplyOptions(ioStreams genericclioptions.IOStreams, obj *unstructured.Unstructured, fileName string, validate bool, force, serverSideApply bool, dryRunStrategy cmdutil.DryRunStrategy, manager string, serverSideDiff bool, cascadingStrategy metav1.DeletionPropagation) (*apply.ApplyOptions, error) {
flags := apply.NewApplyFlags(ioStreams)
o := &apply.ApplyOptions{
IOStreams: ioStreams,
Expand Down Expand Up @@ -334,6 +334,7 @@ func (k *kubectlResourceOperations) newApplyOptions(ioStreams genericclioptions.
o.DeleteOptions.FilenameOptions.Filenames = []string{fileName}
o.Namespace = obj.GetNamespace()
o.DeleteOptions.ForceDeletion = force
o.DeleteOptions.CascadingStrategy = cascadingStrategy
o.DryRunStrategy = dryRunStrategy
if manager != "" {
o.FieldManager = manager
Expand Down Expand Up @@ -378,7 +379,7 @@ func (k *kubectlResourceOperations) newCreateOptions(ioStreams genericclioptions
return o, nil
}

func (k *kubectlResourceOperations) newReplaceOptions(config *rest.Config, f cmdutil.Factory, ioStreams genericclioptions.IOStreams, fileName string, namespace string, force bool, dryRunStrategy cmdutil.DryRunStrategy) (*replace.ReplaceOptions, error) {
func (k *kubectlResourceOperations) newReplaceOptions(config *rest.Config, f cmdutil.Factory, ioStreams genericclioptions.IOStreams, fileName string, namespace string, force bool, dryRunStrategy cmdutil.DryRunStrategy, cascadingStrategy metav1.DeletionPropagation) (*replace.ReplaceOptions, error) {
o := replace.NewReplaceOptions(ioStreams)

recorder, err := o.RecordFlags.ToRecorder()
Expand Down Expand Up @@ -426,6 +427,7 @@ func (k *kubectlResourceOperations) newReplaceOptions(config *rest.Config, f cmd
o.DeleteOptions.FilenameOptions.Filenames = []string{fileName}
o.Namespace = namespace
o.DeleteOptions.ForceDeletion = force
o.DeleteOptions.CascadingStrategy = cascadingStrategy
return o, nil
}

Expand Down
Loading