mirror of https://github.com/portainer/portainer
feat(stacks): simplify WaitForStatus() BE-11505 (#241)
parent
35dcb5ca46
commit
13317ec43c
|
@ -59,7 +59,7 @@ services:
|
||||||
|
|
||||||
require.True(t, containerExists(composeContainerName))
|
require.True(t, containerExists(composeContainerName))
|
||||||
|
|
||||||
waitResult := <-w.WaitForStatus(ctx, projectName, libstack.StatusCompleted)
|
waitResult := w.WaitForStatus(ctx, projectName, libstack.StatusCompleted)
|
||||||
|
|
||||||
require.Empty(t, waitResult.ErrorMsg)
|
require.Empty(t, waitResult.ErrorMsg)
|
||||||
require.Equal(t, libstack.StatusCompleted, waitResult.Status)
|
require.Equal(t, libstack.StatusCompleted, waitResult.Status)
|
||||||
|
|
|
@ -111,74 +111,66 @@ func aggregateStatuses(services []service) (libstack.Status, string) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ComposeDeployer) WaitForStatus(ctx context.Context, name string, status libstack.Status) <-chan libstack.WaitResult {
|
func (c *ComposeDeployer) WaitForStatus(ctx context.Context, name string, status libstack.Status) libstack.WaitResult {
|
||||||
waitResultCh := make(chan libstack.WaitResult)
|
|
||||||
waitResult := libstack.WaitResult{Status: status}
|
waitResult := libstack.WaitResult{Status: status}
|
||||||
|
|
||||||
go func() {
|
for {
|
||||||
for {
|
if ctx.Err() != nil {
|
||||||
select {
|
waitResult.ErrorMsg = "failed to wait for status: " + ctx.Err().Error()
|
||||||
case <-ctx.Done():
|
|
||||||
waitResult.ErrorMsg = "failed to wait for status: " + ctx.Err().Error()
|
|
||||||
waitResultCh <- waitResult
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
return waitResult
|
||||||
|
}
|
||||||
|
|
||||||
var containerSummaries []api.ContainerSummary
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
if err := withComposeService(ctx, nil, libstack.Options{ProjectName: name}, func(composeService api.Service, project *types.Project) error {
|
var containerSummaries []api.ContainerSummary
|
||||||
var err error
|
|
||||||
|
|
||||||
psCtx, cancelFunc := context.WithTimeout(context.Background(), time.Minute)
|
if err := withComposeService(ctx, nil, libstack.Options{ProjectName: name}, func(composeService api.Service, project *types.Project) error {
|
||||||
defer cancelFunc()
|
var err error
|
||||||
containerSummaries, err = composeService.Ps(psCtx, name, api.PsOptions{All: true})
|
|
||||||
|
|
||||||
return err
|
psCtx, cancelFunc := context.WithTimeout(context.Background(), time.Minute)
|
||||||
}); err != nil {
|
defer cancelFunc()
|
||||||
log.Debug().
|
containerSummaries, err = composeService.Ps(psCtx, name, api.PsOptions{All: true})
|
||||||
Str("project_name", name).
|
|
||||||
Err(err).
|
|
||||||
Msg("error from docker compose ps")
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
services := serviceListFromContainerSummary(containerSummaries)
|
|
||||||
|
|
||||||
if len(services) == 0 && status == libstack.StatusRemoved {
|
|
||||||
waitResultCh <- waitResult
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
aggregateStatus, errorMessage := aggregateStatuses(services)
|
|
||||||
if aggregateStatus == status {
|
|
||||||
waitResultCh <- waitResult
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if status == libstack.StatusRunning && aggregateStatus == libstack.StatusCompleted {
|
|
||||||
waitResult.Status = libstack.StatusCompleted
|
|
||||||
waitResultCh <- waitResult
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if errorMessage != "" {
|
|
||||||
waitResult.ErrorMsg = errorMessage
|
|
||||||
waitResultCh <- waitResult
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return err
|
||||||
|
}); err != nil {
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("project_name", name).
|
Str("project_name", name).
|
||||||
Str("required_status", string(status)).
|
Err(err).
|
||||||
Str("status", string(aggregateStatus)).
|
Msg("error from docker compose ps")
|
||||||
Msg("waiting for status")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return waitResultCh
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
services := serviceListFromContainerSummary(containerSummaries)
|
||||||
|
|
||||||
|
if len(services) == 0 && status == libstack.StatusRemoved {
|
||||||
|
return waitResult
|
||||||
|
}
|
||||||
|
|
||||||
|
aggregateStatus, errorMessage := aggregateStatuses(services)
|
||||||
|
if aggregateStatus == status {
|
||||||
|
return waitResult
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == libstack.StatusRunning && aggregateStatus == libstack.StatusCompleted {
|
||||||
|
waitResult.Status = libstack.StatusCompleted
|
||||||
|
|
||||||
|
return waitResult
|
||||||
|
}
|
||||||
|
|
||||||
|
if errorMessage != "" {
|
||||||
|
waitResult.ErrorMsg = errorMessage
|
||||||
|
|
||||||
|
return waitResult
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug().
|
||||||
|
Str("project_name", name).
|
||||||
|
Str("required_status", string(status)).
|
||||||
|
Str("status", string(aggregateStatus)).
|
||||||
|
Msg("waiting for status")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func serviceListFromContainerSummary(containerSummaries []api.ContainerSummary) []service {
|
func serviceListFromContainerSummary(containerSummaries []api.ContainerSummary) []service {
|
||||||
|
|
|
@ -106,8 +106,7 @@ func waitForStatus(deployer libstack.Deployer, ctx context.Context, stackName st
|
||||||
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
|
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
statusCh := deployer.WaitForStatus(ctx, stackName, requiredStatus)
|
result := deployer.WaitForStatus(ctx, stackName, requiredStatus)
|
||||||
result := <-statusCh
|
|
||||||
if result.ErrorMsg == "" {
|
if result.ErrorMsg == "" {
|
||||||
return result.Status, "", nil
|
return result.Status, "", nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ type Deployer interface {
|
||||||
Pull(ctx context.Context, filePaths []string, options Options) error
|
Pull(ctx context.Context, filePaths []string, options Options) error
|
||||||
Run(ctx context.Context, filePaths []string, serviceName string, options RunOptions) error
|
Run(ctx context.Context, filePaths []string, serviceName string, options RunOptions) 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 WaitResult
|
WaitForStatus(ctx context.Context, name string, status Status) WaitResult
|
||||||
Config(ctx context.Context, filePaths []string, options Options) ([]byte, error)
|
Config(ctx context.Context, filePaths []string, options Options) ([]byte, error)
|
||||||
GetExistingEdgeStacks(ctx context.Context) ([]EdgeStack, error)
|
GetExistingEdgeStacks(ctx context.Context) ([]EdgeStack, error)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue