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

feat: add enable field for automatedSync #21999

Merged
merged 13 commits into from
Mar 21, 2025
2 changes: 1 addition & 1 deletion applicationset/controllers/applicationset_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1398,7 +1398,7 @@ func (r *ApplicationSetReconciler) syncValidApplications(logCtx *log.Entry, appl
pruneEnabled := false

// ensure that Applications generated with RollingSync do not have an automated sync policy, since the AppSet controller will handle triggering the sync operation instead
if validApps[i].Spec.SyncPolicy != nil && validApps[i].Spec.SyncPolicy.Automated != nil {
if validApps[i].Spec.SyncPolicy != nil && validApps[i].Spec.SyncPolicy.IsAutomatedSyncEnabled() {
pruneEnabled = validApps[i].Spec.SyncPolicy.Automated.Prune
validApps[i].Spec.SyncPolicy.Automated = nil
}
Expand Down
4 changes: 4 additions & 0 deletions assets/swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions cmd/argocd/commands/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ func printAppSummaryTable(app *argoappv1.Application, appURL string, windows *ar
}

var syncPolicy string
if app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.Automated != nil {
if app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.IsAutomatedSyncEnabled() {
syncPolicy = "Automated"
if app.Spec.SyncPolicy.Automated.Prune {
syncPolicy += " (Prune)"
Expand Down Expand Up @@ -1726,7 +1726,7 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
}

func formatSyncPolicy(app argoappv1.Application) string {
if app.Spec.SyncPolicy == nil || app.Spec.SyncPolicy.Automated == nil {
if app.Spec.SyncPolicy == nil || !app.Spec.SyncPolicy.IsAutomatedSyncEnabled() {
return "Manual"
}
policy := "Auto"
Expand Down Expand Up @@ -2158,7 +2158,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
}

if local != "" {
if app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.Automated != nil && !dryRun {
if app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.IsAutomatedSyncEnabled() && !dryRun {
log.Fatal("Cannot use local sync when Automatic Sync Policy is enabled except with --dry-run")
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/argocd/commands/applicationset.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ func printAppSetSummaryTable(appSet *arogappsetv1.ApplicationSet) {
syncPolicyStr string
syncPolicy = appSet.Spec.Template.Spec.SyncPolicy
)
if syncPolicy != nil && syncPolicy.Automated != nil {
if syncPolicy != nil && syncPolicy.IsAutomatedSyncEnabled() {
syncPolicyStr = "Automated"
if syncPolicy.Automated.Prune {
syncPolicyStr += " (Prune)"
Expand Down
6 changes: 3 additions & 3 deletions cmd/util/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,19 +289,19 @@ func SetAppSpecOptions(flags *pflag.FlagSet, spec *argoappv1.ApplicationSpec, ap
}
})
if flags.Changed("auto-prune") {
if spec.SyncPolicy == nil || spec.SyncPolicy.Automated == nil {
if spec.SyncPolicy == nil || !spec.SyncPolicy.IsAutomatedSyncEnabled() {
log.Fatal("Cannot set --auto-prune: application not configured with automatic sync")
}
spec.SyncPolicy.Automated.Prune = appOpts.autoPrune
}
if flags.Changed("self-heal") {
if spec.SyncPolicy == nil || spec.SyncPolicy.Automated == nil {
if spec.SyncPolicy == nil || !spec.SyncPolicy.IsAutomatedSyncEnabled() {
log.Fatal("Cannot set --self-heal: application not configured with automatic sync")
}
spec.SyncPolicy.Automated.SelfHeal = appOpts.selfHeal
}
if flags.Changed("allow-empty") {
if spec.SyncPolicy == nil || spec.SyncPolicy.Automated == nil {
if spec.SyncPolicy == nil || !spec.SyncPolicy.IsAutomatedSyncEnabled() {
log.Fatal("Cannot set --allow-empty: application not configured with automatic sync")
}
spec.SyncPolicy.Automated.AllowEmpty = appOpts.allowEmpty
Expand Down
6 changes: 3 additions & 3 deletions controller/appcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2060,7 +2060,7 @@ func (ctrl *ApplicationController) autoSync(app *appv1.Application, syncStatus *
logCtx = logCtx.WithField("time_ms", time.Since(ts.StartTime).Milliseconds())
logCtx.Debug("Finished auto sync")
}()
if app.Spec.SyncPolicy == nil || app.Spec.SyncPolicy.Automated == nil {
if app.Spec.SyncPolicy == nil || !app.Spec.SyncPolicy.IsAutomatedSyncEnabled() {
return nil, 0
}

Expand Down Expand Up @@ -2486,14 +2486,14 @@ func isOperationInProgress(app *appv1.Application) bool {
func automatedSyncEnabled(oldApp *appv1.Application, newApp *appv1.Application) bool {
oldEnabled := false
oldSelfHealEnabled := false
if oldApp.Spec.SyncPolicy != nil && oldApp.Spec.SyncPolicy.Automated != nil {
if oldApp.Spec.SyncPolicy != nil && oldApp.Spec.SyncPolicy.IsAutomatedSyncEnabled() {
oldEnabled = true
oldSelfHealEnabled = oldApp.Spec.SyncPolicy.Automated.SelfHeal
}

newEnabled := false
newSelfHealEnabled := false
if newApp.Spec.SyncPolicy != nil && newApp.Spec.SyncPolicy.Automated != nil {
if newApp.Spec.SyncPolicy != nil && newApp.Spec.SyncPolicy.IsAutomatedSyncEnabled() {
newEnabled = true
newSelfHealEnabled = newApp.Spec.SyncPolicy.Automated.SelfHeal
}
Expand Down
35 changes: 35 additions & 0 deletions controller/appcontroller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,24 @@ func TestAutoSync(t *testing.T) {
assert.False(t, app.Operation.Sync.Prune)
}

func TestAutoSyncEnabledSetToTrue(t *testing.T) {
app := newFakeApp()
enable := true
app.Spec.SyncPolicy.Automated = &v1alpha1.SyncPolicyAutomated{Enable: &enable}
ctrl := newFakeController(&fakeData{apps: []runtime.Object{app}}, nil)
syncStatus := v1alpha1.SyncStatus{
Status: v1alpha1.SyncStatusCodeOutOfSync,
Revision: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
}
cond, _ := ctrl.autoSync(app, &syncStatus, []v1alpha1.ResourceStatus{{Name: "guestbook", Kind: kube.DeploymentKind, Status: v1alpha1.SyncStatusCodeOutOfSync}}, true)
assert.Nil(t, cond)
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get(t.Context(), "my-app", metav1.GetOptions{})
require.NoError(t, err)
assert.NotNil(t, app.Operation)
assert.NotNil(t, app.Operation.Sync)
assert.False(t, app.Operation.Sync.Prune)
}

func TestMultiSourceSelfHeal(t *testing.T) {
// Simulate OutOfSync caused by object change in cluster
// So our Sync Revisions and SyncStatus Revisions should deep equal
Expand Down Expand Up @@ -711,6 +729,23 @@ func TestSkipAutoSync(t *testing.T) {
assert.Nil(t, app.Operation)
})

// Verify we skip when auto-sync is disabled
t.Run("AutoSyncEnableFieldIsSetFalse", func(t *testing.T) {
app := newFakeApp()
enable := true
app.Spec.SyncPolicy.Automated = &v1alpha1.SyncPolicyAutomated{Enable: &enable}
ctrl := newFakeController(&fakeData{apps: []runtime.Object{app}}, nil)
syncStatus := v1alpha1.SyncStatus{
Status: v1alpha1.SyncStatusCodeOutOfSync,
Revision: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
}
cond, _ := ctrl.autoSync(app, &syncStatus, []v1alpha1.ResourceStatus{}, true)
assert.Nil(t, cond)
app, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(test.FakeArgoCDNamespace).Get(t.Context(), "my-app", metav1.GetOptions{})
require.NoError(t, err)
assert.Nil(t, app.Operation)
})

// Verify we skip when application is marked for deletion
t.Run("ApplicationIsMarkedForDeletion", func(t *testing.T) {
app := newFakeApp()
Expand Down
2 changes: 1 addition & 1 deletion controller/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ func (c *appCollector) collectApps(ch chan<- prometheus.Metric, app *argoappv1.A
healthStatus = health.HealthStatusUnknown
}

autoSyncEnabled := app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.Automated != nil
autoSyncEnabled := app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.IsAutomatedSyncEnabled()

addGauge(descAppInfo, 1, strconv.FormatBool(autoSyncEnabled), git.NormalizeGitURL(app.Spec.GetSource().RepoURL), app.Spec.Destination.Server, app.Spec.Destination.Namespace, string(syncStatus), string(healthStatus), operation)

Expand Down
10 changes: 10 additions & 0 deletions docs/user-guide/auto_sync.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ spec:
syncPolicy:
automated: {}
```
Application CRD now also support explicitly setting automated sync to be turn on or off by using `spec.syncPolicy.automated.enable` flag to true or false
```yaml
spec:
syncPolicy:
automated:
enable: true
```

!!!note
**Note:** Setting `spec.syncPolicy.automated.enable` flag to null will be treated as automated sync as enabled.

## Temporarily toggling auto-sync for applications managed by ApplicationSets

Expand Down
Loading
Loading