diff --git a/pkg/app/piped/controller/controller.go b/pkg/app/piped/controller/controller.go index fafa88c40b..61de4a8f2e 100644 --- a/pkg/app/piped/controller/controller.go +++ b/pkg/app/piped/controller/controller.go @@ -302,6 +302,17 @@ func (c *controller) syncPlanners(ctx context.Context) error { ) c.donePlanners[p.ID()] = p.DoneTimestamp() delete(c.planners, id) + + // Application will be marked as NOT deploying when planner's deployment was completed. + if model.IsCompletedDeployment(p.DoneDeploymentStatus()) { + if err := reportApplicationDeployingStatus(ctx, c.apiClient, id, false); err != nil { + c.logger.Error("failed to mark application as NOT deploying", + zap.String("deployment-id", p.ID()), + zap.String("app-id", id), + zap.Error(err), + ) + } + } } // Add missing planners. @@ -347,6 +358,15 @@ func (c *controller) syncPlanners(ctx context.Context) error { continue } c.planners[appID] = planner + + // Application will be marked as DEPLOYING after its planner was successfully created. + if err := reportApplicationDeployingStatus(ctx, c.apiClient, d.ApplicationId, true); err != nil { + c.logger.Error("failed to mark application as deploying", + zap.String("deployment-id", d.Id), + zap.String("app-id", d.ApplicationId), + zap.Error(err), + ) + } } return nil @@ -456,6 +476,17 @@ func (c *controller) syncSchedulers(ctx context.Context) error { ) c.doneSchedulers[s.ID()] = s.DoneTimestamp() delete(c.schedulers, id) + + // Application will be marked as NOT deploying when scheduler's deployment was completed. + if model.IsCompletedDeployment(s.DoneDeploymentStatus()) { + if err := reportApplicationDeployingStatus(ctx, c.apiClient, id, false); err != nil { + c.logger.Error("failed to mark application as NOT deploying", + zap.String("deployment-id", s.ID()), + zap.String("app-id", id), + zap.Error(err), + ) + } + } } // Add missing schedulers. @@ -590,7 +621,17 @@ func (c *controller) getMostRecentlySuccessfulDeployment(ctx context.Context, ap return nil, err } -func (c *controller) reportApplicationDeployingStatus(ctx context.Context, appID string, deploying bool) error { +type appLiveResourceLister struct { + lister liveResourceLister + cloudProvider string + appID string +} + +func (l appLiveResourceLister) ListKubernetesResources() ([]provider.Manifest, bool) { + return l.lister.ListKubernetesAppLiveResources(l.cloudProvider, l.appID) +} + +func reportApplicationDeployingStatus(ctx context.Context, c apiClient, appID string, deploying bool) error { var ( err error retry = pipedservice.NewRetry(10) @@ -601,20 +642,10 @@ func (c *controller) reportApplicationDeployingStatus(ctx context.Context, appID ) for retry.WaitNext(ctx) { - if _, err = c.apiClient.ReportApplicationDeployingStatus(ctx, req); err == nil { + if _, err = c.ReportApplicationDeployingStatus(ctx, req); err == nil { return nil } err = fmt.Errorf("failed to report application deploying status to control-plane: %w", err) } return err } - -type appLiveResourceLister struct { - lister liveResourceLister - cloudProvider string - appID string -} - -func (l appLiveResourceLister) ListKubernetesResources() ([]provider.Manifest, bool) { - return l.lister.ListKubernetesAppLiveResources(l.cloudProvider, l.appID) -} diff --git a/pkg/app/piped/controller/planner.go b/pkg/app/piped/controller/planner.go index 7bb982b81e..904d410f26 100644 --- a/pkg/app/piped/controller/planner.go +++ b/pkg/app/piped/controller/planner.go @@ -54,10 +54,11 @@ type planner struct { appManifestsCache cache.Cache logger *zap.Logger - done atomic.Bool - doneTimestamp time.Time - cancelled bool - cancelledCh chan *model.ReportableCommand + done atomic.Bool + doneTimestamp time.Time + doneDeploymentStatus model.DeploymentStatus + cancelled bool + cancelledCh chan *model.ReportableCommand nowFunc func() time.Time } @@ -97,6 +98,7 @@ func newPlanner( pipedConfig: pipedConfig, plannerRegistry: registry.DefaultRegistry(), appManifestsCache: appManifestsCache, + doneDeploymentStatus: d.Status, cancelledCh: make(chan *model.ReportableCommand, 1), nowFunc: time.Now, logger: logger, @@ -121,6 +123,12 @@ func (p *planner) DoneTimestamp() time.Time { return p.doneTimestamp } +// DoneDeploymentStatus returns the deployment status when planner has done. +// This can be used only after IsDone() returns true. +func (p *planner) DoneDeploymentStatus() model.DeploymentStatus { + return p.doneDeploymentStatus +} + func (p *planner) Cancel(cmd model.ReportableCommand) { if p.cancelled { return @@ -140,6 +148,7 @@ func (p *planner) Run(ctx context.Context) error { planner, ok := p.plannerRegistry.Planner(p.deployment.Kind) if !ok { + p.doneDeploymentStatus = model.DeploymentStatus_DEPLOYMENT_FAILURE p.reportDeploymentFailed(ctx, "Unable to find the planner for this application kind") return fmt.Errorf("unable to find the planner for application %v", p.deployment.Kind) } @@ -147,6 +156,7 @@ func (p *planner) Run(ctx context.Context) error { repoID := p.deployment.GitPath.Repo.Id repoCfg, ok := p.pipedConfig.GetRepository(repoID) if !ok { + p.doneDeploymentStatus = model.DeploymentStatus_DEPLOYMENT_FAILURE p.reportDeploymentFailed(ctx, fmt.Sprintf("Unable to find %q from the repository list in piped config", repoID)) return fmt.Errorf("unable to find %q from the repository list in piped config", repoID) } @@ -187,6 +197,7 @@ func (p *planner) Run(ctx context.Context) error { select { case cmd := <-p.cancelledCh: if cmd != nil { + p.doneDeploymentStatus = model.DeploymentStatus_DEPLOYMENT_CANCELLED desc := fmt.Sprintf("Deployment was cancelled by %s while planning", cmd.Commander) p.reportDeploymentCancelled(ctx, cmd.Commander, desc) return cmd.Report(ctx, model.CommandStatus_COMMAND_SUCCEEDED, nil) @@ -195,9 +206,11 @@ func (p *planner) Run(ctx context.Context) error { } if err != nil { + p.doneDeploymentStatus = model.DeploymentStatus_DEPLOYMENT_FAILURE return p.reportDeploymentFailed(ctx, fmt.Sprintf("Unable to plan the deployment (%v)", err)) } + p.doneDeploymentStatus = model.DeploymentStatus_DEPLOYMENT_PLANNED return p.reportDeploymentPlanned(ctx, p.lastSuccessfulCommitHash, out) }