fix(edge-stack): add completed status EE-6210 (#11632)
parent
7479302043
commit
a9ead542b3
|
@ -627,6 +627,7 @@ func getEdgeStackStatusParam(r *http.Request) (*portainer.EdgeStackStatusType, e
|
||||||
portainer.EdgeStackStatusRunning,
|
portainer.EdgeStackStatusRunning,
|
||||||
portainer.EdgeStackStatusDeploying,
|
portainer.EdgeStackStatusDeploying,
|
||||||
portainer.EdgeStackStatusRemoving,
|
portainer.EdgeStackStatusRemoving,
|
||||||
|
portainer.EdgeStackStatusCompleted,
|
||||||
}, edgeStackStatus) {
|
}, edgeStackStatus) {
|
||||||
return nil, errors.New("invalid edgeStackStatus parameter")
|
return nil, errors.New("invalid edgeStackStatus parameter")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1728,6 +1728,8 @@ const (
|
||||||
EdgeStackStatusRollingBack
|
EdgeStackStatusRollingBack
|
||||||
// EdgeStackStatusRolledBack represents an Edge stack which has rolled back
|
// EdgeStackStatusRolledBack represents an Edge stack which has rolled back
|
||||||
EdgeStackStatusRolledBack
|
EdgeStackStatusRolledBack
|
||||||
|
// EdgeStackStatusCompleted represents a completed Edge stack
|
||||||
|
EdgeStackStatusCompleted
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -68,6 +68,8 @@ function getLabel(type: StatusType): ReactNode {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case StatusType.Running:
|
case StatusType.Running:
|
||||||
return 'deployments running';
|
return 'deployments running';
|
||||||
|
case StatusType.Completed:
|
||||||
|
return 'deployments completed';
|
||||||
case StatusType.DeploymentReceived:
|
case StatusType.DeploymentReceived:
|
||||||
return 'deployments received';
|
return 'deployments received';
|
||||||
case StatusType.Error:
|
case StatusType.Error:
|
||||||
|
|
|
@ -84,6 +84,16 @@ function getStatus(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const allCompleted = envStatus.every((s) => s.Type === StatusType.Completed);
|
||||||
|
|
||||||
|
if (allCompleted) {
|
||||||
|
return {
|
||||||
|
label: 'Completed',
|
||||||
|
icon: CheckCircle,
|
||||||
|
mode: 'success',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const allRunning = envStatus.every(
|
const allRunning = envStatus.every(
|
||||||
(s) =>
|
(s) =>
|
||||||
s.Type === StatusType.Running ||
|
s.Type === StatusType.Running ||
|
||||||
|
|
|
@ -44,6 +44,8 @@ export enum StatusType {
|
||||||
RollingBack,
|
RollingBack,
|
||||||
/** PausedRemoving represents an Edge stack which has been rolled back */
|
/** PausedRemoving represents an Edge stack which has been rolled back */
|
||||||
RolledBack,
|
RolledBack,
|
||||||
|
/** Completed represents a completed Edge stack */
|
||||||
|
Completed,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeploymentStatus {
|
export interface DeploymentStatus {
|
||||||
|
|
|
@ -51,7 +51,12 @@ func getServiceStatus(service service) (libstack.Status, string) {
|
||||||
return libstack.StatusRunning, ""
|
return libstack.StatusRunning, ""
|
||||||
case "removing":
|
case "removing":
|
||||||
return libstack.StatusRemoving, ""
|
return libstack.StatusRemoving, ""
|
||||||
case "exited", "dead":
|
case "exited":
|
||||||
|
if service.ExitCode != 0 {
|
||||||
|
return libstack.StatusError, fmt.Sprintf("service %s exited with code %d", service.Name, service.ExitCode)
|
||||||
|
}
|
||||||
|
return libstack.StatusCompleted, ""
|
||||||
|
case "dead":
|
||||||
if service.ExitCode != 0 {
|
if service.ExitCode != 0 {
|
||||||
return libstack.StatusError, fmt.Sprintf("service %s exited with code %d", service.Name, service.ExitCode)
|
return libstack.StatusError, fmt.Sprintf("service %s exited with code %d", service.Name, service.ExitCode)
|
||||||
}
|
}
|
||||||
|
@ -94,7 +99,9 @@ func aggregateStatuses(services []service) (libstack.Status, string) {
|
||||||
return libstack.StatusStarting, ""
|
return libstack.StatusStarting, ""
|
||||||
case statusCounts[libstack.StatusRemoving] > 0:
|
case statusCounts[libstack.StatusRemoving] > 0:
|
||||||
return libstack.StatusRemoving, ""
|
return libstack.StatusRemoving, ""
|
||||||
case statusCounts[libstack.StatusRunning] == servicesCount:
|
case statusCounts[libstack.StatusCompleted] == servicesCount:
|
||||||
|
return libstack.StatusCompleted, ""
|
||||||
|
case statusCounts[libstack.StatusRunning]+statusCounts[libstack.StatusCompleted] == servicesCount:
|
||||||
return libstack.StatusRunning, ""
|
return libstack.StatusRunning, ""
|
||||||
case statusCounts[libstack.StatusStopped] == servicesCount:
|
case statusCounts[libstack.StatusStopped] == servicesCount:
|
||||||
return libstack.StatusStopped, ""
|
return libstack.StatusStopped, ""
|
||||||
|
@ -106,15 +113,19 @@ func aggregateStatuses(services []service) (libstack.Status, string) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wrapper *PluginWrapper) WaitForStatus(ctx context.Context, name string, status libstack.Status) <-chan string {
|
func (wrapper *PluginWrapper) WaitForStatus(ctx context.Context, name string, status libstack.Status) <-chan libstack.WaitResult {
|
||||||
errorMessageCh := make(chan string)
|
waitResultCh := make(chan libstack.WaitResult)
|
||||||
|
waitResult := libstack.WaitResult{
|
||||||
|
Status: status,
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
OUTER:
|
OUTER:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
errorMessageCh <- fmt.Sprintf("failed to wait for status: %s", ctx.Err().Error())
|
waitResult.ErrorMsg = fmt.Sprintf("failed to wait for status: %s", ctx.Err().Error())
|
||||||
|
waitResultCh <- waitResult
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +140,7 @@ func (wrapper *PluginWrapper) WaitForStatus(ctx context.Context, name string, st
|
||||||
Msg("no output from docker compose ps")
|
Msg("no output from docker compose ps")
|
||||||
|
|
||||||
if status == libstack.StatusRemoved {
|
if status == libstack.StatusRemoved {
|
||||||
errorMessageCh <- ""
|
waitResultCh <- waitResult
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,18 +176,25 @@ func (wrapper *PluginWrapper) WaitForStatus(ctx context.Context, name string, st
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(services) == 0 && status == libstack.StatusRemoved {
|
if len(services) == 0 && status == libstack.StatusRemoved {
|
||||||
errorMessageCh <- ""
|
waitResultCh <- waitResult
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
aggregateStatus, errorMessage := aggregateStatuses(services)
|
aggregateStatus, errorMessage := aggregateStatuses(services)
|
||||||
if aggregateStatus == status {
|
if aggregateStatus == status {
|
||||||
errorMessageCh <- ""
|
waitResultCh <- waitResult
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == libstack.StatusRunning && aggregateStatus == libstack.StatusCompleted {
|
||||||
|
waitResult.Status = libstack.StatusCompleted
|
||||||
|
waitResultCh <- waitResult
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if errorMessage != "" {
|
if errorMessage != "" {
|
||||||
errorMessageCh <- errorMessage
|
waitResult.ErrorMsg = errorMessage
|
||||||
|
waitResultCh <- waitResult
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,5 +206,5 @@ func (wrapper *PluginWrapper) WaitForStatus(ctx context.Context, name string, st
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return errorMessageCh
|
return waitResultCh
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,9 +108,9 @@ func waitForStatus(deployer libstack.Deployer, ctx context.Context, stackName st
|
||||||
|
|
||||||
statusCh := deployer.WaitForStatus(ctx, stackName, requiredStatus)
|
statusCh := deployer.WaitForStatus(ctx, stackName, requiredStatus)
|
||||||
result := <-statusCh
|
result := <-statusCh
|
||||||
if result == "" {
|
if result.ErrorMsg == "" {
|
||||||
return requiredStatus, "", nil
|
return result.Status, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return libstack.StatusError, result, nil
|
return libstack.StatusError, result.ErrorMsg, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,21 +13,27 @@ type Deployer interface {
|
||||||
Remove(ctx context.Context, projectName string, filePaths []string, options Options) error
|
Remove(ctx context.Context, projectName string, filePaths []string, options Options) error
|
||||||
Pull(ctx context.Context, filePaths []string, options Options) error
|
Pull(ctx context.Context, filePaths []string, options Options) error
|
||||||
Validate(ctx context.Context, filePaths []string, options Options) error
|
Validate(ctx context.Context, filePaths []string, options Options) error
|
||||||
WaitForStatus(ctx context.Context, name string, status Status) <-chan string
|
WaitForStatus(ctx context.Context, name string, status Status) <-chan WaitResult
|
||||||
}
|
}
|
||||||
|
|
||||||
type Status string
|
type Status string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
StatusUnknown Status = "unknown"
|
StatusUnknown Status = "unknown"
|
||||||
StatusStarting Status = "starting"
|
StatusStarting Status = "starting"
|
||||||
StatusRunning Status = "running"
|
StatusRunning Status = "running"
|
||||||
StatusStopped Status = "stopped"
|
StatusStopped Status = "stopped"
|
||||||
StatusError Status = "error"
|
StatusError Status = "error"
|
||||||
StatusRemoving Status = "removing"
|
StatusRemoving Status = "removing"
|
||||||
StatusRemoved Status = "removed"
|
StatusRemoved Status = "removed"
|
||||||
|
StatusCompleted Status = "completed"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type WaitResult struct {
|
||||||
|
Status Status
|
||||||
|
ErrorMsg string
|
||||||
|
}
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
WorkingDir string
|
WorkingDir string
|
||||||
Host string
|
Host string
|
||||||
|
|
Loading…
Reference in New Issue