From 307b7c4e402c74b2ffafb4bea27ad3937f591d31 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Mon, 2 Jul 2018 15:39:00 -0700 Subject: [PATCH 01/16] Add timeout to sync and rollback commands --- cmd/argocd/commands/app.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index b1a3a643e3e63..e1b78ec928b78 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -757,6 +757,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co revision string prune bool dryRun bool + timeout uint ) var command = &cobra.Command{ Use: "sync APPNAME", @@ -789,6 +790,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co command.Flags().BoolVar(&dryRun, "dry-run", false, "Preview apply without affecting cluster") command.Flags().BoolVar(&prune, "prune", false, "Allow deleting unexpected resources") command.Flags().StringVar(&revision, "revision", "", "Sync to a specific revision. Preserves parameter overrides") + command.Flags().UintVar(&timeout, "timeout", defaultCheckTimeoutSeconds, "Time out after this many seconds") return command } @@ -892,7 +894,8 @@ func paramString(params []argoappv1.ComponentParameter) string { // NewApplicationRollbackCommand returns a new instance of an `argocd app rollback` command func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { var ( - prune bool + prune bool + timeout uint ) var command = &cobra.Command{ Use: "rollback APPNAME", @@ -938,6 +941,7 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr }, } command.Flags().BoolVar(&prune, "prune", false, "Allow deleting unexpected resources") + command.Flags().UintVar(&timeout, "timeout", defaultCheckTimeoutSeconds, "Time out after this many seconds") return command } From 0270fa5992b6dfb78b09baa2de093aa46e745f04 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Mon, 2 Jul 2018 15:45:45 -0700 Subject: [PATCH 02/16] Make defaultCheckTimeoutSeconds package-global --- cmd/argocd/commands/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index e1b78ec928b78..61dde3fa58f18 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -580,7 +580,6 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co healthOnly bool timeout uint ) - const defaultCheckTimeoutSeconds = 0 var command = &cobra.Command{ Use: "wait APPNAME", Short: "Wait for an application to reach a synced and healthy state", @@ -946,6 +945,7 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr } const printOpFmtStr = "%-20s%s\n" +const defaultCheckTimeoutSeconds = 0 func printOperationResult(appName string, opState *argoappv1.OperationState) error { fmt.Printf(printOpFmtStr, "Application:", appName) From c14760538ca6ec71b60bf159dd8b56c491332155 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Mon, 2 Jul 2018 15:52:10 -0700 Subject: [PATCH 03/16] Add cancel to context for rollback, sync --- cmd/argocd/commands/app.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 61dde3fa58f18..6abe670d571b6 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -768,6 +768,9 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co } conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() appName := args[0] syncReq := application.ApplicationSyncRequest{ Name: &appName, @@ -775,7 +778,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Revision: revision, Prune: prune, } - _, err := appIf.Sync(context.Background(), &syncReq) + _, err := appIf.Sync(ctx, &syncReq) errors.CheckError(err) status, err := waitUntilOperationCompleted(appIf, appName) errors.CheckError(err) @@ -910,6 +913,8 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) errors.CheckError(err) var depInfo *argoappv1.DeploymentInfo From 28f4fde98a93f6ed71f3c7bb6463a8fe8ee0ddfe Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Mon, 2 Jul 2018 16:04:12 -0700 Subject: [PATCH 04/16] Add cancel after timeout to rollback/sync --- cmd/argocd/commands/app.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 6abe670d571b6..ecfc1c03fe5a7 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -599,9 +599,7 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co defer cancel() if timeout != 0 { - time.AfterFunc(time.Duration(timeout)*time.Second, func() { - cancel() - }) + time.AfterFunc(time.Duration(timeout)*time.Second, cancel) } // print the initial components to format the tabwriter columns @@ -771,6 +769,11 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() + + if timeout != 0 { + time.AfterFunc(time.Duration(timeout)*time.Second, cancel) + } + appName := args[0] syncReq := application.ApplicationSyncRequest{ Name: &appName, @@ -915,6 +918,11 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() + + if timeout != 0 { + time.AfterFunc(time.Duration(timeout)*time.Second, cancel) + } + app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) errors.CheckError(err) var depInfo *argoappv1.DeploymentInfo From 238468cfca949a416bcf436481008e5ab8e4ea27 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Mon, 2 Jul 2018 16:06:16 -0700 Subject: [PATCH 05/16] Assign appName earlier in sync --- cmd/argocd/commands/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index ecfc1c03fe5a7..1670d7b488c2a 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -764,6 +764,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co c.HelpFunc()(c, args) os.Exit(1) } + appName := args[0] conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) ctx := context.Background() @@ -774,7 +775,6 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co time.AfterFunc(time.Duration(timeout)*time.Second, cancel) } - appName := args[0] syncReq := application.ApplicationSyncRequest{ Name: &appName, DryRun: dryRun, From 0622a11843caac5eccc09c28fc32a7c8b8a56667 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Mon, 2 Jul 2018 16:26:01 -0700 Subject: [PATCH 06/16] Don't unnecessarily reassign ctx --- cmd/argocd/commands/app.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 1670d7b488c2a..a19e53d33a7b4 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -594,8 +594,7 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co appName := args[0] conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - ctx := context.Background() - ctx, cancel := context.WithCancel(ctx) + ctx, cancel := context.WithCancel(context.Background()) defer cancel() if timeout != 0 { @@ -767,8 +766,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co appName := args[0] conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - ctx := context.Background() - ctx, cancel := context.WithCancel(ctx) + ctx, cancel := context.WithCancel(context.Background()) defer cancel() if timeout != 0 { @@ -915,8 +913,7 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr errors.CheckError(err) conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - ctx := context.Background() - ctx, cancel := context.WithCancel(ctx) + ctx, cancel := context.WithCancel(context.Background()) defer cancel() if timeout != 0 { From d11b8442cc5c41491488201cd3a7d4219e2ac972 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Mon, 2 Jul 2018 16:32:45 -0700 Subject: [PATCH 07/16] Use full func for timeout after all --- cmd/argocd/commands/app.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index a19e53d33a7b4..f1f513e27613a 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -598,7 +598,10 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co defer cancel() if timeout != 0 { - time.AfterFunc(time.Duration(timeout)*time.Second, cancel) + time.AfterFunc(time.Duration(timeout)*time.Second, func() { + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) + cancel() + }) } // print the initial components to format the tabwriter columns @@ -623,7 +626,6 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co return } } - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }, } command.Flags().BoolVar(&syncOnly, "sync-only", false, "Wait only for sync") @@ -770,7 +772,10 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co defer cancel() if timeout != 0 { - time.AfterFunc(time.Duration(timeout)*time.Second, cancel) + time.AfterFunc(time.Duration(timeout)*time.Second, func() { + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) + cancel() + }) } syncReq := application.ApplicationSyncRequest{ @@ -917,7 +922,10 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr defer cancel() if timeout != 0 { - time.AfterFunc(time.Duration(timeout)*time.Second, cancel) + time.AfterFunc(time.Duration(timeout)*time.Second, func() { + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) + cancel() + }) } app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) From 22fc3e98bc08df8e5d8976717aeb614c40381241 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Mon, 2 Jul 2018 16:34:36 -0700 Subject: [PATCH 08/16] Try applying wait logic --- cmd/argocd/commands/app.go | 56 +++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index f1f513e27613a..54037ae0da8b1 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -778,20 +778,35 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co }) } - syncReq := application.ApplicationSyncRequest{ + _, err := appIf.Sync(ctx, &application.ApplicationSyncRequest{ Name: &appName, DryRun: dryRun, Revision: revision, Prune: prune, - } - _, err := appIf.Sync(ctx, &syncReq) - errors.CheckError(err) - status, err := waitUntilOperationCompleted(appIf, appName) + }) errors.CheckError(err) - err = printOperationResult(appName, status) + + // print the initial components to format the tabwriter columns + app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) errors.CheckError(err) - if !status.Phase.Successful() && !dryRun { - os.Exit(1) + w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + printAppResources(w, app, nil) + _ = w.Flush() + prevCompRes := &app.Status.ComparisonResult + + appEventCh := watchApp(ctx, appIf, appName) + for appEvent := range appEventCh { + app := appEvent.Application + printAppStateChange(w, prevCompRes, &app) + _ = w.Flush() + prevCompRes = &app.Status.ComparisonResult + + synced := (app.Status.ComparisonResult.Status == argoappv1.ComparisonStatusSynced) + healthy := (app.Status.Health.Status == argoappv1.HealthStatusHealthy) + if (synced && healthy) || (synced && syncOnly) || (healthy && healthOnly) { + log.Printf("App %q matches desired state", appName) + return + } } }, } @@ -948,12 +963,27 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr }) errors.CheckError(err) - status, err := waitUntilOperationCompleted(appIf, appName) - errors.CheckError(err) - err = printOperationResult(appName, status) + // print the initial components to format the tabwriter columns + app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) errors.CheckError(err) - if !status.Phase.Successful() { - os.Exit(1) + w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) + printAppResources(w, app, nil) + _ = w.Flush() + prevCompRes := &app.Status.ComparisonResult + + appEventCh := watchApp(ctx, appIf, appName) + for appEvent := range appEventCh { + app := appEvent.Application + printAppStateChange(w, prevCompRes, &app) + _ = w.Flush() + prevCompRes = &app.Status.ComparisonResult + + synced := (app.Status.ComparisonResult.Status == argoappv1.ComparisonStatusSynced) + healthy := (app.Status.Health.Status == argoappv1.HealthStatusHealthy) + if (synced && healthy) || (synced && syncOnly) || (healthy && healthOnly) { + log.Printf("App %q matches desired state", appName) + return + } } }, } From d5436e5018650133818d6523f5e6c52506343c35 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Tue, 3 Jul 2018 10:11:24 -0700 Subject: [PATCH 09/16] Add sync/health flags to rollback/sync --- cmd/argocd/commands/app.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 54037ae0da8b1..399ab74909cc5 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -752,10 +752,12 @@ func printAppStateChange(w io.Writer, prevComp *argoappv1.ComparisonResult, app // NewApplicationSyncCommand returns a new instance of an `argocd app sync` command func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { var ( - revision string - prune bool - dryRun bool - timeout uint + revision string + prune bool + dryRun bool + syncOnly bool + healthOnly bool + timeout uint ) var command = &cobra.Command{ Use: "sync APPNAME", @@ -813,6 +815,8 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co command.Flags().BoolVar(&dryRun, "dry-run", false, "Preview apply without affecting cluster") command.Flags().BoolVar(&prune, "prune", false, "Allow deleting unexpected resources") command.Flags().StringVar(&revision, "revision", "", "Sync to a specific revision. Preserves parameter overrides") + command.Flags().BoolVar(&syncOnly, "sync-only", false, "Wait only for sync") + command.Flags().BoolVar(&healthOnly, "health-only", false, "Wait only for health") command.Flags().UintVar(&timeout, "timeout", defaultCheckTimeoutSeconds, "Time out after this many seconds") return command } @@ -917,8 +921,10 @@ func paramString(params []argoappv1.ComponentParameter) string { // NewApplicationRollbackCommand returns a new instance of an `argocd app rollback` command func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { var ( - prune bool - timeout uint + prune bool + syncOnly bool + healthOnly bool + timeout uint ) var command = &cobra.Command{ Use: "rollback APPNAME", @@ -964,7 +970,6 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr errors.CheckError(err) // print the initial components to format the tabwriter columns - app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) errors.CheckError(err) w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) printAppResources(w, app, nil) @@ -988,6 +993,8 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr }, } command.Flags().BoolVar(&prune, "prune", false, "Allow deleting unexpected resources") + command.Flags().BoolVar(&syncOnly, "sync-only", false, "Wait only for sync") + command.Flags().BoolVar(&healthOnly, "health-only", false, "Wait only for health") command.Flags().UintVar(&timeout, "timeout", defaultCheckTimeoutSeconds, "Time out after this many seconds") return command } From a8c20dadcb2cc8fd7b47d841e03e39abc308f850 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Tue, 3 Jul 2018 13:14:50 -0700 Subject: [PATCH 10/16] Slight cleanup to realign with spec --- cmd/argocd/commands/app.go | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 399ab74909cc5..775a2fc9f3a68 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -599,8 +599,8 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co if timeout != 0 { time.AfterFunc(time.Duration(timeout)*time.Second, func() { - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) cancel() + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }) } @@ -752,12 +752,10 @@ func printAppStateChange(w io.Writer, prevComp *argoappv1.ComparisonResult, app // NewApplicationSyncCommand returns a new instance of an `argocd app sync` command func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { var ( - revision string - prune bool - dryRun bool - syncOnly bool - healthOnly bool - timeout uint + revision string + prune bool + dryRun bool + timeout uint ) var command = &cobra.Command{ Use: "sync APPNAME", @@ -775,8 +773,8 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co if timeout != 0 { time.AfterFunc(time.Duration(timeout)*time.Second, func() { - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) cancel() + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }) } @@ -815,8 +813,6 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co command.Flags().BoolVar(&dryRun, "dry-run", false, "Preview apply without affecting cluster") command.Flags().BoolVar(&prune, "prune", false, "Allow deleting unexpected resources") command.Flags().StringVar(&revision, "revision", "", "Sync to a specific revision. Preserves parameter overrides") - command.Flags().BoolVar(&syncOnly, "sync-only", false, "Wait only for sync") - command.Flags().BoolVar(&healthOnly, "health-only", false, "Wait only for health") command.Flags().UintVar(&timeout, "timeout", defaultCheckTimeoutSeconds, "Time out after this many seconds") return command } @@ -921,10 +917,8 @@ func paramString(params []argoappv1.ComponentParameter) string { // NewApplicationRollbackCommand returns a new instance of an `argocd app rollback` command func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command { var ( - prune bool - syncOnly bool - healthOnly bool - timeout uint + prune bool + timeout uint ) var command = &cobra.Command{ Use: "rollback APPNAME", @@ -944,8 +938,8 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr if timeout != 0 { time.AfterFunc(time.Duration(timeout)*time.Second, func() { - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) cancel() + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }) } @@ -993,8 +987,6 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr }, } command.Flags().BoolVar(&prune, "prune", false, "Allow deleting unexpected resources") - command.Flags().BoolVar(&syncOnly, "sync-only", false, "Wait only for sync") - command.Flags().BoolVar(&healthOnly, "health-only", false, "Wait only for health") command.Flags().UintVar(&timeout, "timeout", defaultCheckTimeoutSeconds, "Time out after this many seconds") return command } From a9e26420f7a5a36be36c3a5cd6e55757d7e4b4ff Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Tue, 3 Jul 2018 14:12:13 -0700 Subject: [PATCH 11/16] Clean up, still broken --- cmd/argocd/commands/app.go | 97 +++++++++++++------------------------- 1 file changed, 33 insertions(+), 64 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 775a2fc9f3a68..da3399ffadb71 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -600,7 +600,6 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co if timeout != 0 { time.AfterFunc(time.Duration(timeout)*time.Second, func() { cancel() - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }) } @@ -626,6 +625,7 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co return } } + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }, } command.Flags().BoolVar(&syncOnly, "sync-only", false, "Wait only for sync") @@ -765,48 +765,24 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co c.HelpFunc()(c, args) os.Exit(1) } - appName := args[0] conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - if timeout != 0 { - time.AfterFunc(time.Duration(timeout)*time.Second, func() { - cancel() - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) - }) - } - - _, err := appIf.Sync(ctx, &application.ApplicationSyncRequest{ + appName := args[0] + syncReq := application.ApplicationSyncRequest{ Name: &appName, DryRun: dryRun, Revision: revision, Prune: prune, - }) + } + ctx := context.Background() + _, err := appIf.Sync(ctx, &syncReq) errors.CheckError(err) - - // print the initial components to format the tabwriter columns - app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) + status, err := waitUntilOperationCompleted(ctx, appIf, appName, timeout) errors.CheckError(err) - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) - printAppResources(w, app, nil) - _ = w.Flush() - prevCompRes := &app.Status.ComparisonResult - - appEventCh := watchApp(ctx, appIf, appName) - for appEvent := range appEventCh { - app := appEvent.Application - printAppStateChange(w, prevCompRes, &app) - _ = w.Flush() - prevCompRes = &app.Status.ComparisonResult - - synced := (app.Status.ComparisonResult.Status == argoappv1.ComparisonStatusSynced) - healthy := (app.Status.Health.Status == argoappv1.HealthStatusHealthy) - if (synced && healthy) || (synced && syncOnly) || (healthy && healthOnly) { - log.Printf("App %q matches desired state", appName) - return - } + err = printOperationResult(appName, status) + errors.CheckError(err) + if !status.Phase.Successful() && !dryRun { + os.Exit(1) } }, } @@ -817,7 +793,21 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co return command } -func waitUntilOperationCompleted(appClient application.ApplicationServiceClient, appName string) (*argoappv1.OperationState, error) { +func waitUntilOperationCompleted(ctx context.Context, appClient application.ApplicationServiceClient, appName string, timeout uint) (*argoappv1.OperationState, error) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + if timeout != 0 { + time.AfterFunc(time.Duration(timeout)*time.Second, func() { + cancel() + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) + }) + } + + appEventCh := watchApp(ctx, appClient, appName) + for appEvent := range appEventCh { + } + wc, err := appClient.Watch(context.Background(), &application.ApplicationQuery{ Name: &appName, }) @@ -933,15 +923,7 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr errors.CheckError(err) conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - if timeout != 0 { - time.AfterFunc(time.Duration(timeout)*time.Second, func() { - cancel() - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) - }) - } + ctx := context.Background() app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) errors.CheckError(err) @@ -963,26 +945,12 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr }) errors.CheckError(err) - // print the initial components to format the tabwriter columns + status, err := waitUntilOperationCompleted(ctx, appIf, appName, timeout) errors.CheckError(err) - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) - printAppResources(w, app, nil) - _ = w.Flush() - prevCompRes := &app.Status.ComparisonResult - - appEventCh := watchApp(ctx, appIf, appName) - for appEvent := range appEventCh { - app := appEvent.Application - printAppStateChange(w, prevCompRes, &app) - _ = w.Flush() - prevCompRes = &app.Status.ComparisonResult - - synced := (app.Status.ComparisonResult.Status == argoappv1.ComparisonStatusSynced) - healthy := (app.Status.Health.Status == argoappv1.HealthStatusHealthy) - if (synced && healthy) || (synced && syncOnly) || (healthy && healthOnly) { - log.Printf("App %q matches desired state", appName) - return - } + err = printOperationResult(appName, status) + errors.CheckError(err) + if !status.Phase.Successful() { + os.Exit(1) } }, } @@ -1045,6 +1013,7 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) ctx := context.Background() + app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) errors.CheckError(err) From e67299d42e5b7c5a71463d727e40126f3d7b163d Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Tue, 3 Jul 2018 14:22:09 -0700 Subject: [PATCH 12/16] Adapt waitUntilOPerationCompleted, thanks @jessesuen --- cmd/argocd/commands/app.go | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index da3399ffadb71..f26676bcf23a5 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -774,10 +774,9 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co Revision: revision, Prune: prune, } - ctx := context.Background() - _, err := appIf.Sync(ctx, &syncReq) + _, err := appIf.Sync(context.Background(), &syncReq) errors.CheckError(err) - status, err := waitUntilOperationCompleted(ctx, appIf, appName, timeout) + status, err := waitUntilOperationCompleted(appIf, appName, timeout) errors.CheckError(err) err = printOperationResult(appName, status) errors.CheckError(err) @@ -793,40 +792,24 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co return command } -func waitUntilOperationCompleted(ctx context.Context, appClient application.ApplicationServiceClient, appName string, timeout uint) (*argoappv1.OperationState, error) { - ctx, cancel := context.WithCancel(ctx) +func waitUntilOperationCompleted(appClient application.ApplicationServiceClient, appName string, timeout uint) (*argoappv1.OperationState, error) { + ctx, cancel := context.WithCancel(context.Background()) defer cancel() if timeout != 0 { time.AfterFunc(time.Duration(timeout)*time.Second, func() { cancel() - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }) } appEventCh := watchApp(ctx, appClient, appName) for appEvent := range appEventCh { - } - - wc, err := appClient.Watch(context.Background(), &application.ApplicationQuery{ - Name: &appName, - }) - if err != nil { - return nil, err - } - appEvent, err := wc.Recv() - if err != nil { - return nil, err - } - for { if appEvent.Application.Status.OperationState != nil && appEvent.Application.Status.OperationState.Phase.Completed() { return appEvent.Application.Status.OperationState, nil } - appEvent, err = wc.Recv() - if err != nil { - return nil, err - } } + return nil, fmt.Errorf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) + } // setParameterOverrides updates an existing or appends a new parameter override in the application @@ -945,7 +928,7 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr }) errors.CheckError(err) - status, err := waitUntilOperationCompleted(ctx, appIf, appName, timeout) + status, err := waitUntilOperationCompleted(appIf, appName, timeout) errors.CheckError(err) err = printOperationResult(appName, status) errors.CheckError(err) From e73867c8d5666c300b76cf8ef5841460707b1bdd Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Tue, 3 Jul 2018 14:34:51 -0700 Subject: [PATCH 13/16] Log fatal immediately after timeout --- cmd/argocd/commands/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index f26676bcf23a5..dd0c0ea9879f3 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -600,6 +600,7 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co if timeout != 0 { time.AfterFunc(time.Duration(timeout)*time.Second, func() { cancel() + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }) } @@ -625,7 +626,6 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co return } } - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }, } command.Flags().BoolVar(&syncOnly, "sync-only", false, "Wait only for sync") From c3853a733f605aba58af5c715dac68e790e4641c Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Tue, 3 Jul 2018 14:44:08 -0700 Subject: [PATCH 14/16] Move fatal log back --- cmd/argocd/commands/app.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index dd0c0ea9879f3..d4441ae52099e 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -600,7 +600,6 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co if timeout != 0 { time.AfterFunc(time.Duration(timeout)*time.Second, func() { cancel() - log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }) } @@ -626,6 +625,7 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co return } } + log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) }, } command.Flags().BoolVar(&syncOnly, "sync-only", false, "Wait only for sync") @@ -809,7 +809,6 @@ func waitUntilOperationCompleted(appClient application.ApplicationServiceClient, } } return nil, fmt.Errorf("Timed out (%ds) waiting for app %q match desired state", timeout, appName) - } // setParameterOverrides updates an existing or appends a new parameter override in the application From 18cf6cc18e721270165844b879b3a1d7ef180a9b Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Tue, 3 Jul 2018 14:45:05 -0700 Subject: [PATCH 15/16] Reduce diff further --- cmd/argocd/commands/app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index d4441ae52099e..03a56b7503000 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -594,7 +594,8 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co appName := args[0] conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) - ctx, cancel := context.WithCancel(context.Background()) + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) defer cancel() if timeout != 0 { From e2d85d5dceb7d36f65fb036784ec1b84d5d6cd35 Mon Sep 17 00:00:00 2001 From: Andrew Merenbach Date: Tue, 3 Jul 2018 14:46:02 -0700 Subject: [PATCH 16/16] Rm two blank lines --- cmd/argocd/commands/app.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go index 03a56b7503000..c49e40d721590 100644 --- a/cmd/argocd/commands/app.go +++ b/cmd/argocd/commands/app.go @@ -907,7 +907,6 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) ctx := context.Background() - app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) errors.CheckError(err) var depInfo *argoappv1.DeploymentInfo @@ -996,7 +995,6 @@ func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cob conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie() defer util.Close(conn) ctx := context.Background() - app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName}) errors.CheckError(err)