Skip to content

Commit 7921242

Browse files
anandfleoluz
andauthored
fix(server): Dry run always in client mode just for yaml manifest validation even with server side apply (#564)
* Revert "feat: retry with client side dry run if server one was failed (#548)" This reverts commit c0c2dd1. Signed-off-by: Anand Francis Joseph <[email protected]> * Revert "fix(server): use server side dry run in case if it is server side apply (#546)" This reverts commit 4a5648e. Signed-off-by: Anand Francis Joseph <[email protected]> * Fixed the logic to disable server side apply if it is a dry run Signed-off-by: Anand Francis Joseph <[email protected]> * Added more values in the log message for better debugging Signed-off-by: Anand Francis Joseph <[email protected]> * Fixed compilation error Signed-off-by: Anand Francis Joseph <[email protected]> * Written an inline fn to get string value of dry-run strategy Signed-off-by: Anand Francis Joseph <[email protected]> * Added comment as requested with reference to the issue number Signed-off-by: Anand Francis Joseph <[email protected]> --------- Signed-off-by: Anand Francis Joseph <[email protected]> Co-authored-by: Leonardo Luz Almeida <[email protected]>
1 parent c1e2359 commit 7921242

File tree

3 files changed

+40
-64
lines changed

3 files changed

+40
-64
lines changed

pkg/sync/sync_context.go

+34-43
Original file line numberDiff line numberDiff line change
@@ -903,57 +903,48 @@ func (sc *syncContext) ensureCRDReady(name string) error {
903903
})
904904
}
905905

906-
func getDryRunStrategy(serverSideApply, dryRun bool) cmdutil.DryRunStrategy {
907-
if !dryRun {
908-
return cmdutil.DryRunNone
909-
}
910-
if serverSideApply {
911-
return cmdutil.DryRunServer
912-
}
913-
return cmdutil.DryRunClient
914-
}
915-
916906
func (sc *syncContext) applyObject(t *syncTask, dryRun, force, validate bool) (common.ResultCode, string) {
917-
serverSideApply := sc.serverSideApply || resourceutil.HasAnnotationOption(t.targetObj, common.AnnotationSyncOptions, common.SyncOptionServerSideApply)
918-
919-
dryRunStrategy := getDryRunStrategy(serverSideApply, dryRun)
907+
dryRunStrategy := cmdutil.DryRunNone
908+
if dryRun {
909+
// irrespective of the dry run mode set in the sync context, always run
910+
// in client dry run mode as the goal is to validate only the
911+
// yaml correctness of the rendered manifests.
912+
// running dry-run in server mode breaks the auto create namespace feature
913+
// https://github.com/argoproj/argo-cd/issues/13874
914+
dryRunStrategy = cmdutil.DryRunClient
915+
}
920916

921917
var err error
922918
var message string
923919
shouldReplace := sc.replace || resourceutil.HasAnnotationOption(t.targetObj, common.AnnotationSyncOptions, common.SyncOptionReplace)
924-
applyFn := func(dryRunStrategy cmdutil.DryRunStrategy) (string, error) {
925-
if !shouldReplace {
926-
return sc.resourceOps.ApplyResource(context.TODO(), t.targetObj, dryRunStrategy, force, validate, serverSideApply, sc.serverSideApplyManager, false)
927-
}
928-
if t.liveObj == nil {
929-
return sc.resourceOps.CreateResource(context.TODO(), t.targetObj, dryRunStrategy, validate)
930-
}
931-
// Avoid using `kubectl replace` for CRDs since 'replace' might recreate resource and so delete all CRD instances.
932-
// The same thing applies for namespaces, which would delete the namespace as well as everything within it,
933-
// so we want to avoid using `kubectl replace` in that case as well.
934-
if kube.IsCRD(t.targetObj) || t.targetObj.GetKind() == kubeutil.NamespaceKind {
935-
update := t.targetObj.DeepCopy()
936-
update.SetResourceVersion(t.liveObj.GetResourceVersion())
937-
_, err = sc.resourceOps.UpdateResource(context.TODO(), update, dryRunStrategy)
938-
if err != nil {
939-
return fmt.Sprintf("error when updating: %v", err.Error()), err
920+
// if it is a dry run, disable server side apply, as the goal is to validate only the
921+
// yaml correctness of the rendered manifests.
922+
// running dry-run in server mode breaks the auto create namespace feature
923+
// https://github.com/argoproj/argo-cd/issues/13874
924+
serverSideApply := !dryRun && (sc.serverSideApply || resourceutil.HasAnnotationOption(t.targetObj, common.AnnotationSyncOptions, common.SyncOptionServerSideApply))
925+
if shouldReplace {
926+
if t.liveObj != nil {
927+
// Avoid using `kubectl replace` for CRDs since 'replace' might recreate resource and so delete all CRD instances.
928+
// The same thing applies for namespaces, which would delete the namespace as well as everything within it,
929+
// so we want to avoid using `kubectl replace` in that case as well.
930+
if kube.IsCRD(t.targetObj) || t.targetObj.GetKind() == kubeutil.NamespaceKind {
931+
update := t.targetObj.DeepCopy()
932+
update.SetResourceVersion(t.liveObj.GetResourceVersion())
933+
_, err = sc.resourceOps.UpdateResource(context.TODO(), update, dryRunStrategy)
934+
if err == nil {
935+
message = fmt.Sprintf("%s/%s updated", t.targetObj.GetKind(), t.targetObj.GetName())
936+
} else {
937+
message = fmt.Sprintf("error when updating: %v", err.Error())
938+
}
939+
} else {
940+
message, err = sc.resourceOps.ReplaceResource(context.TODO(), t.targetObj, dryRunStrategy, force)
940941
}
941-
return fmt.Sprintf("%s/%s updated", t.targetObj.GetKind(), t.targetObj.GetName()), nil
942-
942+
} else {
943+
message, err = sc.resourceOps.CreateResource(context.TODO(), t.targetObj, dryRunStrategy, validate)
943944
}
944-
return sc.resourceOps.ReplaceResource(context.TODO(), t.targetObj, dryRunStrategy, force)
945-
}
946-
947-
message, err = applyFn(dryRunStrategy)
948-
949-
// DryRunServer fails with "Kind does not support fieldValidation" error for kubernetes server < 1.25
950-
// it fails inside apply.go , o.DryRunVerifier.HasSupport(info.Mapping.GroupVersionKind) line
951-
// so we retry with DryRunClient that works for all cases, but cause issues with hooks
952-
// Details: https://github.com/argoproj/argo-cd/issues/16177
953-
if dryRunStrategy == cmdutil.DryRunServer && err != nil {
954-
message, err = applyFn(cmdutil.DryRunClient)
945+
} else {
946+
message, err = sc.resourceOps.ApplyResource(context.TODO(), t.targetObj, dryRunStrategy, force, validate, serverSideApply, sc.serverSideApplyManager, false)
955947
}
956-
957948
if err != nil {
958949
return common.ResultCodeSyncFailed, err.Error()
959950
}

pkg/sync/sync_context_test.go

-20
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8-
"k8s.io/kubectl/pkg/cmd/util"
98
"net/http"
109
"net/http/httptest"
1110
"reflect"
@@ -540,25 +539,6 @@ func (s *APIServerMock) newHttpServer(t *testing.T, apiFailuresCount int) *httpt
540539
return server
541540
}
542541

543-
func TestGetDryRunStrategy(t *testing.T) {
544-
t.Run("no dry run", func(t *testing.T) {
545-
strategy := getDryRunStrategy(false, false)
546-
assert.Equal(t, util.DryRunNone, strategy)
547-
})
548-
t.Run("no dry run with server side apply", func(t *testing.T) {
549-
strategy := getDryRunStrategy(true, false)
550-
assert.Equal(t, util.DryRunNone, strategy)
551-
})
552-
t.Run("dry run with server side apply", func(t *testing.T) {
553-
strategy := getDryRunStrategy(true, true)
554-
assert.Equal(t, util.DryRunServer, strategy)
555-
})
556-
t.Run("dry run with client side apply", func(t *testing.T) {
557-
strategy := getDryRunStrategy(false, true)
558-
assert.Equal(t, util.DryRunClient, strategy)
559-
})
560-
}
561-
562542
func TestServerResourcesRetry(t *testing.T) {
563543
type fixture struct {
564544
apiServerMock *APIServerMock

pkg/utils/kube/resource_ops.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,12 @@ func (k *kubectlResourceOperations) ApplyResource(ctx context.Context, obj *unst
244244
span.SetBaggageItem("kind", obj.GetKind())
245245
span.SetBaggageItem("name", obj.GetName())
246246
defer span.Finish()
247-
k.log.Info(fmt.Sprintf("Applying resource %s/%s in cluster: %s, namespace: %s", obj.GetKind(), obj.GetName(), k.config.Host, obj.GetNamespace()))
247+
k.log.WithValues(
248+
"dry-run", [...]string{"none", "client", "server"}[dryRunStrategy],
249+
"manager", manager,
250+
"serverSideApply", serverSideApply,
251+
"serverSideDiff", serverSideDiff).Info(fmt.Sprintf("Applying resource %s/%s in cluster: %s, namespace: %s", obj.GetKind(), obj.GetName(), k.config.Host, obj.GetNamespace()))
252+
248253
return k.runResourceCommand(ctx, obj, dryRunStrategy, serverSideDiff, func(f cmdutil.Factory, ioStreams genericclioptions.IOStreams, fileName string) error {
249254
cleanup, err := k.processKubectlRun("apply")
250255
if err != nil {

0 commit comments

Comments
 (0)