Skip to content

Commit

Permalink
feat: Implement Server-Side Diff (argoproj#13663)
Browse files Browse the repository at this point in the history
* feat: Implement Server-Side Diff

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* propagate the refreshtype to the diff config

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* Create the serverSideDiff config

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* chore: add featureflag utility package

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* remove featureflag package

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* add param

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* make ssd configurable with app annotation

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* add server-side-diff flags

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* apply the same logic regardless of the refresh type

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* fix gitops-engine reference

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* address review comments

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* Address review comments

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* docs: add docs related to server-side-diff

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* docs: update doc

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* Add config to include mutation webhooks

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* Address review comments

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* go mod update

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* Add sdd cache test case

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* fix ssd cache unit test

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* Update clidocs

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* update manifests

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* Fix procfile

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* additional doc changes

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

* update gitops-engine version

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>

---------

Signed-off-by: Leonardo Luz Almeida <leonardo_almeida@intuit.com>
Signed-off-by: Kevin Lyda <kevin@lyda.ie>
  • Loading branch information
leoluz authored and lyda committed Mar 28, 2024
1 parent b235f19 commit 56dd770
Show file tree
Hide file tree
Showing 26 changed files with 475 additions and 170 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ start-local: mod-vendor-local dep-ui-local cli-local
ARGOCD_ZJWT_FEATURE_FLAG=always \
ARGOCD_IN_CI=false \
ARGOCD_GPG_ENABLED=$(ARGOCD_GPG_ENABLED) \
BIN_MODE=$(ARGOCD_BIN_MODE) \
ARGOCD_E2E_TEST=false \
ARGOCD_APPLICATION_NAMESPACES=$(ARGOCD_APPLICATION_NAMESPACES) \
goreman -f $(ARGOCD_PROCFILE) start ${ARGOCD_START}
Expand Down
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
controller: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-application-controller $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --otlp-address=${ARGOCD_OTLP_ADDRESS} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''}"
controller: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-application-controller $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --otlp-address=${ARGOCD_OTLP_ADDRESS} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''} --server-side-diff-enabled=${ARGOCD_APPLICATION_CONTROLLER_SERVER_SIDE_DIFF:-'false'}"
api-server: [ "$BIN_MODE" = 'true' ] && COMMAND=./dist/argocd || COMMAND='go run ./cmd/main.go' && sh -c "FORCE_LOG_COLORS=1 ARGOCD_FAKE_IN_CLUSTER=true ARGOCD_TLS_DATA_PATH=${ARGOCD_TLS_DATA_PATH:-/tmp/argocd-local/tls} ARGOCD_SSH_DATA_PATH=${ARGOCD_SSH_DATA_PATH:-/tmp/argocd-local/ssh} ARGOCD_BINARY_NAME=argocd-server $COMMAND --loglevel debug --redis localhost:${ARGOCD_E2E_REDIS_PORT:-6379} --disable-auth=${ARGOCD_E2E_DISABLE_AUTH:-'true'} --insecure --dex-server http://localhost:${ARGOCD_E2E_DEX_PORT:-5556} --repo-server localhost:${ARGOCD_E2E_REPOSERVER_PORT:-8081} --port ${ARGOCD_E2E_APISERVER_PORT:-8080} --otlp-address=${ARGOCD_OTLP_ADDRESS} --application-namespaces=${ARGOCD_APPLICATION_NAMESPACES:-''}"
dex: sh -c "ARGOCD_BINARY_NAME=argocd-dex go run github.com/argoproj/argo-cd/v2/cmd gendexcfg -o `pwd`/dist/dex.yaml && (test -f dist/dex.yaml || { echo 'Failed to generate dex configuration'; exit 1; }) && docker run --rm -p ${ARGOCD_E2E_DEX_PORT:-5556}:${ARGOCD_E2E_DEX_PORT:-5556} -v `pwd`/dist/dex.yaml:/dex.yaml ghcr.io/dexidp/dex:$(grep "image: ghcr.io/dexidp/dex" manifests/base/dex/argocd-dex-server-deployment.yaml | cut -d':' -f3) dex serve /dex.yaml"
redis: bash -c "if [ \"$ARGOCD_REDIS_LOCAL\" = 'true' ]; then redis-server --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; else docker run --rm --name argocd-redis -i -p ${ARGOCD_E2E_REDIS_PORT:-6379}:${ARGOCD_E2E_REDIS_PORT:-6379} docker.io/library/redis:$(grep "image: redis" manifests/base/redis/argocd-redis-deployment.yaml | cut -d':' -f3) --save '' --appendonly no --port ${ARGOCD_E2E_REDIS_PORT:-6379}; fi"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func NewCommand() *cobra.Command {
persistResourceHealth bool
shardingAlgorithm string
enableDynamicClusterDistribution bool
serverSideDiff bool
)
var command = cobra.Command{
Use: cliName,
Expand Down Expand Up @@ -166,6 +167,7 @@ func NewCommand() *cobra.Command {
clusterFilter,
applicationNamespaces,
&workqueueRateLimit,
serverSideDiff,
)
errors.CheckError(err)
cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer())
Expand Down Expand Up @@ -224,6 +226,7 @@ func NewCommand() *cobra.Command {
command.Flags().DurationVar(&workqueueRateLimit.MaxDelay, "wq-maxdelay-ns", time.Duration(env.ParseInt64FromEnv("WORKQUEUE_MAX_DELAY_NS", time.Second.Nanoseconds(), 1*time.Millisecond.Nanoseconds(), (24*time.Hour).Nanoseconds())), "Set Workqueue Per Item Rate Limiter Max Delay duration in nanoseconds, default 1000000000 (1s)")
command.Flags().Float64Var(&workqueueRateLimit.BackoffFactor, "wq-backoff-factor", env.ParseFloat64FromEnv("WORKQUEUE_BACKOFF_FACTOR", 1.5, 0, math.MaxFloat64), "Set Workqueue Per Item Rate Limiter Backoff Factor, default is 1.5")
command.Flags().BoolVar(&enableDynamicClusterDistribution, "dynamic-cluster-distribution-enabled", env.ParseBoolFromEnv(common.EnvEnableDynamicClusterDistribution, false), "Enables dynamic cluster distribution.")
command.Flags().BoolVar(&serverSideDiff, "server-side-diff-enabled", env.ParseBoolFromEnv(common.EnvServerSideDiff, false), "Feature flag to enable ServerSide diff. Default (\"false\")")
cacheSource = appstatecache.AddCacheFlagsToCmd(&command, func(client *redis.Client) {
redisClient = client
})
Expand Down
7 changes: 5 additions & 2 deletions cmd/argocd/commands/admin/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ func NewReconcileCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
repoServerAddress string
outputFormat string
refresh bool
serverSideDiff bool
)

var command = &cobra.Command{
Expand Down Expand Up @@ -280,7 +281,7 @@ func NewReconcileCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command

appClientset := appclientset.NewForConfigOrDie(cfg)
kubeClientset := kubernetes.NewForConfigOrDie(cfg)
result, err = reconcileApplications(ctx, kubeClientset, appClientset, namespace, repoServerClient, selector, newLiveStateCache)
result, err = reconcileApplications(ctx, kubeClientset, appClientset, namespace, repoServerClient, selector, newLiveStateCache, serverSideDiff)
errors.CheckError(err)
} else {
appClientset := appclientset.NewForConfigOrDie(cfg)
Expand All @@ -295,6 +296,7 @@ func NewReconcileCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
command.Flags().StringVar(&selector, "l", "", "Label selector")
command.Flags().StringVar(&outputFormat, "o", "yaml", "Output format (yaml|json)")
command.Flags().BoolVar(&refresh, "refresh", false, "If set to true then recalculates apps reconciliation")
command.Flags().BoolVar(&serverSideDiff, "server-side-diff", false, "If set to \"true\" will use server-side diff while comparing resources. Default (\"false\")")

return command
}
Expand Down Expand Up @@ -344,6 +346,7 @@ func reconcileApplications(
repoServerClient reposerverclient.Clientset,
selector string,
createLiveStateCache func(argoDB db.ArgoDB, appInformer kubecache.SharedIndexInformer, settingsMgr *settings.SettingsManager, server *metrics.MetricsServer) cache.LiveStateCache,
serverSideDiff bool,
) ([]appReconcileResult, error) {
settingsMgr := settings.NewSettingsManager(ctx, kubeClientset, namespace)
argoDB := db.NewDB(namespace, settingsMgr, kubeClientset)
Expand Down Expand Up @@ -384,7 +387,7 @@ func reconcileApplications(
)

appStateManager := controller.NewAppStateManager(
argoDB, appClientset, repoServerClient, namespace, kubeutil.NewKubectl(), settingsMgr, stateCache, projInformer, server, cache, time.Second, argo.NewResourceTracking(), false, 0)
argoDB, appClientset, repoServerClient, namespace, kubeutil.NewKubectl(), settingsMgr, stateCache, projInformer, server, cache, time.Second, argo.NewResourceTracking(), false, 0, serverSideDiff)

appsList, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(ctx, v1.ListOptions{LabelSelector: selector})
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions cmd/argocd/commands/admin/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func TestGetReconcileResults_Refresh(t *testing.T) {
func(argoDB db.ArgoDB, appInformer cache.SharedIndexInformer, settingsMgr *settings.SettingsManager, server *metrics.MetricsServer) statecache.LiveStateCache {
return &liveStateCache
},
false,
)

if !assert.NoError(t, err) {
Expand Down
3 changes: 3 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ const (
EnvRedisHaProxyName = "ARGOCD_REDIS_HAPROXY_NAME"
// EnvGRPCKeepAliveMin defines the GRPCKeepAliveEnforcementMinimum, used in the grpc.KeepaliveEnforcementPolicy. Expects a "Duration" format (e.g. 10s).
EnvGRPCKeepAliveMin = "ARGOCD_GRPC_KEEP_ALIVE_MIN"
// EnvServerSideDiff defines the env var used to enable ServerSide Diff feature.
// If defined, value must be "true" or "false".
EnvServerSideDiff = "ARGOCD_APPLICATION_CONTROLLER_SERVER_SIDE_DIFF"
)

// Config Management Plugin related constants
Expand Down
3 changes: 2 additions & 1 deletion controller/appcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ func NewApplicationController(
clusterFilter func(cluster *appv1.Cluster) bool,
applicationNamespaces []string,
rateLimiterConfig *ratelimiter.AppControllerRateLimiterConfig,
serverSideDiff bool,
) (*ApplicationController, error) {
log.Infof("appResyncPeriod=%v, appHardResyncPeriod=%v", appResyncPeriod, appHardResyncPeriod)
db := db.NewDB(namespace, settingsMgr, kubeClientset)
Expand Down Expand Up @@ -260,7 +261,7 @@ func NewApplicationController(
}
}
stateCache := statecache.NewLiveStateCache(db, appInformer, ctrl.settingsMgr, kubectl, ctrl.metricsServer, ctrl.handleObjectUpdated, clusterFilter, argo.NewResourceTracking())
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectl, ctrl.settingsMgr, stateCache, projInformer, ctrl.metricsServer, argoCache, ctrl.statusRefreshTimeout, argo.NewResourceTracking(), persistResourceHealth, repoErrorGracePeriod)
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectl, ctrl.settingsMgr, stateCache, projInformer, ctrl.metricsServer, argoCache, ctrl.statusRefreshTimeout, argo.NewResourceTracking(), persistResourceHealth, repoErrorGracePeriod, serverSideDiff)
ctrl.appInformer = appInformer
ctrl.appLister = appLister
ctrl.projInformer = projInformer
Expand Down
1 change: 1 addition & 0 deletions controller/appcontroller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ func newFakeController(data *fakeData, repoErr error) *ApplicationController {
nil,
data.applicationNamespaces,
nil,
false,
)
if err != nil {
panic(err)
Expand Down
43 changes: 38 additions & 5 deletions controller/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ type appStateManager struct {
persistResourceHealth bool
repoErrorCache goSync.Map
repoErrorGracePeriod time.Duration
serverSideDiff bool
}

// GetRepoObjs will generate the manifests for the given application delegating the
Expand Down Expand Up @@ -592,7 +593,16 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
manifestRevisions = append(manifestRevisions, manifestInfo.Revision)
}

useDiffCache := useDiffCache(noCache, manifestInfos, sources, app, manifestRevisions, m.statusRefreshTimeout, logCtx)
serverSideDiff := m.serverSideDiff ||
resourceutil.HasAnnotationOption(app, common.AnnotationCompareOptions, "ServerSideDiff=true")

// This allows turning SSD off for a given app if it is enabled at the
// controller level
if resourceutil.HasAnnotationOption(app, common.AnnotationCompareOptions, "ServerSideDiff=false") {
serverSideDiff = false
}

useDiffCache := useDiffCache(noCache, manifestInfos, sources, app, manifestRevisions, m.statusRefreshTimeout, serverSideDiff, logCtx)

diffConfigBuilder := argodiff.NewDiffConfigBuilder().
WithDiffSettings(app.Spec.IgnoreDifferences, resourceOverrides, compareOptions.IgnoreAggregatedRoles).
Expand All @@ -604,13 +614,29 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
diffConfigBuilder.WithNoCache()
}

if resourceutil.HasAnnotationOption(app, common.AnnotationCompareOptions, "IncludeMutationWebhook=true") {
diffConfigBuilder.WithIgnoreMutationWebhook(false)
}

gvkParser, err := m.getGVKParser(app.Spec.Destination.Server)
if err != nil {
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionUnknownError, Message: err.Error(), LastTransitionTime: &now})
}
diffConfigBuilder.WithGVKParser(gvkParser)
diffConfigBuilder.WithManager(common.ArgoCDSSAManager)

diffConfigBuilder.WithServerSideDiff(serverSideDiff)

if serverSideDiff {
resourceOps, cleanup, err := m.getResourceOperations(app.Spec.Destination.Server)
if err != nil {
log.Errorf("CompareAppState error getting resource operations: %s", err)
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionUnknownError, Message: err.Error(), LastTransitionTime: &now})
}
defer cleanup()
diffConfigBuilder.WithServerSideDryRunner(diff.NewK8sServerSideDryRunner(resourceOps))
}

// enable structured merge diff if application syncs with server-side apply
if app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.SyncOptions.HasOption("ServerSideApply=true") {
diffConfigBuilder.WithStructuredMergeDiff(true)
Expand Down Expand Up @@ -811,18 +837,23 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1

// useDiffCache will determine if the diff should be calculated based
// on the existing live state cache or not.
func useDiffCache(noCache bool, manifestInfos []*apiclient.ManifestResponse, sources []v1alpha1.ApplicationSource, app *v1alpha1.Application, manifestRevisions []string, statusRefreshTimeout time.Duration, log *log.Entry) bool {
func useDiffCache(noCache bool, manifestInfos []*apiclient.ManifestResponse, sources []v1alpha1.ApplicationSource, app *v1alpha1.Application, manifestRevisions []string, statusRefreshTimeout time.Duration, serverSideDiff bool, log *log.Entry) bool {

if noCache {
log.WithField("useDiffCache", "false").Debug("noCache is true")
return false
}
_, refreshRequested := app.IsRefreshRequested()
refreshType, refreshRequested := app.IsRefreshRequested()
if refreshRequested {
log.WithField("useDiffCache", "false").Debug("refreshRequested")
log.WithField("useDiffCache", "false").Debugf("refresh type %s requested", string(refreshType))
return false
}
if app.Status.Expired(statusRefreshTimeout) {
// serverSideDiff should still use cache even if status is expired.
// This is an attempt to avoid hitting k8s API server too frequently during
// app refresh with serverSideDiff is enabled. If there are negative side
// effects identified with this approach, the serverSideDiff should be removed
// from this condition.
if app.Status.Expired(statusRefreshTimeout) && !serverSideDiff {
log.WithField("useDiffCache", "false").Debug("app.status.expired")
return false
}
Expand Down Expand Up @@ -903,6 +934,7 @@ func NewAppStateManager(
resourceTracking argo.ResourceTracking,
persistResourceHealth bool,
repoErrorGracePeriod time.Duration,
serverSideDiff bool,
) AppStateManager {
return &appStateManager{
liveStateCache: liveStateCache,
Expand All @@ -919,6 +951,7 @@ func NewAppStateManager(
resourceTracking: resourceTracking,
persistResourceHealth: persistResourceHealth,
repoErrorGracePeriod: repoErrorGracePeriod,
serverSideDiff: serverSideDiff,
}
}

Expand Down
22 changes: 21 additions & 1 deletion controller/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,7 @@ func TestUseDiffCache(t *testing.T) {
manifestRevisions []string
statusRefreshTimeout time.Duration
expectedUseCache bool
serverSideDiff bool
}

manifestInfos := func(revision string) []*apiclient.ManifestResponse {
Expand Down Expand Up @@ -1505,6 +1506,7 @@ func TestUseDiffCache(t *testing.T) {
manifestRevisions: []string{"rev1"},
statusRefreshTimeout: time.Hour * 24,
expectedUseCache: true,
serverSideDiff: false,
},
{
testName: "will use diff cache for multisource",
Expand Down Expand Up @@ -1548,6 +1550,7 @@ func TestUseDiffCache(t *testing.T) {
manifestRevisions: []string{"rev1", "rev2"},
statusRefreshTimeout: time.Hour * 24,
expectedUseCache: true,
serverSideDiff: false,
},
{
testName: "will return false if nocache is true",
Expand All @@ -1558,6 +1561,7 @@ func TestUseDiffCache(t *testing.T) {
manifestRevisions: []string{"rev1"},
statusRefreshTimeout: time.Hour * 24,
expectedUseCache: false,
serverSideDiff: false,
},
{
testName: "will return false if requested refresh",
Expand All @@ -1568,6 +1572,7 @@ func TestUseDiffCache(t *testing.T) {
manifestRevisions: []string{"rev1"},
statusRefreshTimeout: time.Hour * 24,
expectedUseCache: false,
serverSideDiff: false,
},
{
testName: "will return false if status expired",
Expand All @@ -1578,6 +1583,18 @@ func TestUseDiffCache(t *testing.T) {
manifestRevisions: []string{"rev1"},
statusRefreshTimeout: time.Minute,
expectedUseCache: false,
serverSideDiff: false,
},
{
testName: "will return true if status expired and server-side diff",
noCache: false,
manifestInfos: manifestInfos("rev1"),
sources: sources(),
app: app("httpbin", "rev1", false, nil),
manifestRevisions: []string{"rev1"},
statusRefreshTimeout: time.Minute,
expectedUseCache: true,
serverSideDiff: true,
},
{
testName: "will return false if there is a new revision",
Expand All @@ -1588,6 +1605,7 @@ func TestUseDiffCache(t *testing.T) {
manifestRevisions: []string{"rev2"},
statusRefreshTimeout: time.Hour * 24,
expectedUseCache: false,
serverSideDiff: false,
},
{
testName: "will return false if app spec repo changed",
Expand All @@ -1604,6 +1622,7 @@ func TestUseDiffCache(t *testing.T) {
manifestRevisions: []string{"rev1"},
statusRefreshTimeout: time.Hour * 24,
expectedUseCache: false,
serverSideDiff: false,
},
{
testName: "will return false if app spec IgnoreDifferences changed",
Expand All @@ -1626,6 +1645,7 @@ func TestUseDiffCache(t *testing.T) {
manifestRevisions: []string{"rev1"},
statusRefreshTimeout: time.Hour * 24,
expectedUseCache: false,
serverSideDiff: false,
},
}

Expand All @@ -1638,7 +1658,7 @@ func TestUseDiffCache(t *testing.T) {
log := logrus.NewEntry(logger)

// When
useDiffCache := useDiffCache(tc.noCache, tc.manifestInfos, tc.sources, tc.app, tc.manifestRevisions, tc.statusRefreshTimeout, log)
useDiffCache := useDiffCache(tc.noCache, tc.manifestInfos, tc.sources, tc.app, tc.manifestRevisions, tc.statusRefreshTimeout, tc.serverSideDiff, log)

// Then
assert.Equal(t, useDiffCache, tc.expectedUseCache)
Expand Down
21 changes: 21 additions & 0 deletions controller/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,27 @@ func (m *appStateManager) getGVKParser(server string) (*managedfields.GvkParser,
return cluster.GetGVKParser(), nil
}

// getResourceOperations will return the kubectl implementation of the ResourceOperations
// interface that provides functionality to manage kubernetes resources. Returns a
// cleanup function that must be called to remove the generated kube config for this
// server.
func (m *appStateManager) getResourceOperations(server string) (kube.ResourceOperations, func(), error) {
clusterCache, err := m.liveStateCache.GetClusterCache(server)
if err != nil {
return nil, nil, fmt.Errorf("error getting cluster cache: %w", err)
}

cluster, err := m.db.GetCluster(context.Background(), server)
if err != nil {
return nil, nil, fmt.Errorf("error getting cluster: %w", err)
}
ops, cleanup, err := m.kubectl.ManageResources(cluster.RawRestConfig(), clusterCache.GetOpenAPISchema())
if err != nil {
return nil, nil, fmt.Errorf("error creating kubectl ResourceOperations: %w", err)
}
return ops, cleanup, nil
}

func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha1.OperationState) {
// Sync requests might be requested with ambiguous revisions (e.g. master, HEAD, v1.2.3).
// This can change meaning when resuming operations (e.g a hook sync). After calculating a
Expand Down
4 changes: 4 additions & 0 deletions docs/operator-manual/argocd-cmd-params-cm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ data:
controller.k8sclient.retry.base.backoff: "100"
# Grace period in seconds for ignoring consecutive errors while communicating with repo server.
controller.repo.error.grace.period.seconds: "180"
# Enables the server side diff feature at the application controller level.
# Diff calculation will be done by running a server side apply dryrun (when
# diff cache is unavailable).
controller.diff.server.side: "false"

## Server properties
# Listen on given address for incoming connections (default "0.0.0.0")
Expand Down
Loading

0 comments on commit 56dd770

Please sign in to comment.