mirror of
https://github.com/docker/compose.git
synced 2026-02-09 01:59:22 +08:00
distinguish event (short) status text and details
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
committed by
Guillaume Lours
parent
bff3d35305
commit
d70bb8cf5e
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ bin/
|
||||
coverage.out
|
||||
covdatafiles/
|
||||
.DS_Store
|
||||
pkg/e2e/*.tar
|
||||
|
||||
1
go.mod
1
go.mod
@@ -63,6 +63,7 @@ require (
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect
|
||||
|
||||
3
go.sum
3
go.sum
@@ -4,8 +4,9 @@ github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkk
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e h1:rd4bOvKmDIx0WeTv9Qz+hghsgyjikFiPrseXHlKepO0=
|
||||
github.com/DefangLabs/secret-detector v0.0.0-20250403165618-22662109213e/go.mod h1:blbwPQh4DTlCZEfk1BLU4oMIhLda2U+A840Uag9DsZw=
|
||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||
|
||||
@@ -41,21 +41,18 @@ func (s *composeService) commit(ctx context.Context, projectName string, options
|
||||
}
|
||||
|
||||
name := getCanonicalContainerName(ctr)
|
||||
msg := fmt.Sprintf("Commit %s", name)
|
||||
|
||||
s.events.On(progress.Event{
|
||||
ID: name,
|
||||
Text: msg,
|
||||
Status: progress.Working,
|
||||
StatusText: "Committing",
|
||||
ID: name,
|
||||
Status: progress.Working,
|
||||
Text: progress.StatusCommitting,
|
||||
})
|
||||
|
||||
if s.dryRun {
|
||||
s.events.On(progress.Event{
|
||||
ID: name,
|
||||
Text: msg,
|
||||
Status: progress.Done,
|
||||
StatusText: "Committed",
|
||||
ID: name,
|
||||
Status: progress.Done,
|
||||
Text: progress.StatusCommitted,
|
||||
})
|
||||
|
||||
return nil
|
||||
@@ -73,10 +70,9 @@ func (s *composeService) commit(ctx context.Context, projectName string, options
|
||||
}
|
||||
|
||||
s.events.On(progress.Event{
|
||||
ID: name,
|
||||
Text: msg,
|
||||
Status: progress.Done,
|
||||
StatusText: fmt.Sprintf("Committed as %s", response.ID),
|
||||
ID: name,
|
||||
Text: fmt.Sprintf("Committed as %s", response.ID),
|
||||
Status: progress.Done,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
||||
@@ -504,7 +504,9 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
|
||||
logrus.Warnf("optional dependency %q failed to start: %s", dep, err.Error())
|
||||
return nil
|
||||
}
|
||||
s.events.On(containerEvents(waitingFor, progress.ErrorEvent)...)
|
||||
s.events.On(containerEvents(waitingFor, func(s string) progress.Event {
|
||||
return progress.ErrorEventf(s, "dependency %s failed to start", dep)
|
||||
})...)
|
||||
return fmt.Errorf("dependency failed to start: %w", err)
|
||||
}
|
||||
if healthy {
|
||||
@@ -532,7 +534,9 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("service %s", messageSuffix)
|
||||
s.events.On(containerReasonEvents(waitingFor, progress.ErrorMessageEvent, msg)...)
|
||||
s.events.On(containerEvents(waitingFor, func(s string) progress.Event {
|
||||
return progress.ErrorEventf(s, "service %s", messageSuffix)
|
||||
})...)
|
||||
return errors.New(msg)
|
||||
}
|
||||
default:
|
||||
@@ -600,9 +604,9 @@ func (s *composeService) createContainer(ctx context.Context, project *types.Pro
|
||||
if err != nil {
|
||||
if ctx.Err() == nil {
|
||||
s.events.On(progress.Event{
|
||||
ID: eventName,
|
||||
Status: progress.Error,
|
||||
StatusText: err.Error(),
|
||||
ID: eventName,
|
||||
Status: progress.Error,
|
||||
Text: err.Error(),
|
||||
})
|
||||
}
|
||||
return ctr, err
|
||||
@@ -619,9 +623,9 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P
|
||||
defer func() {
|
||||
if err != nil && ctx.Err() == nil {
|
||||
s.events.On(progress.Event{
|
||||
ID: eventName,
|
||||
Status: progress.Error,
|
||||
StatusText: err.Error(),
|
||||
ID: eventName,
|
||||
Status: progress.Error,
|
||||
Text: err.Error(),
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -86,24 +86,24 @@ func (s *composeService) copy(ctx context.Context, projectName string, options a
|
||||
name := getCanonicalContainerName(ctr)
|
||||
var msg string
|
||||
if direction == fromService {
|
||||
msg = fmt.Sprintf("copy %s:%s to %s", name, srcPath, dstPath)
|
||||
msg = fmt.Sprintf("%s:%s to %s", name, srcPath, dstPath)
|
||||
} else {
|
||||
msg = fmt.Sprintf("copy %s to %s:%s", srcPath, name, dstPath)
|
||||
msg = fmt.Sprintf("%s to %s:%s", srcPath, name, dstPath)
|
||||
}
|
||||
s.events.On(progress.Event{
|
||||
ID: name,
|
||||
Text: msg,
|
||||
Status: progress.Working,
|
||||
StatusText: "Copying",
|
||||
ID: name,
|
||||
Text: progress.StatusCopying,
|
||||
Details: msg,
|
||||
Status: progress.Working,
|
||||
})
|
||||
if err := copyFunc(ctx, ctr.ID, srcPath, dstPath, options); err != nil {
|
||||
return err
|
||||
}
|
||||
s.events.On(progress.Event{
|
||||
ID: name,
|
||||
Text: msg,
|
||||
Status: progress.Done,
|
||||
StatusText: "Copied",
|
||||
ID: name,
|
||||
Text: progress.StatusCopied,
|
||||
Details: msg,
|
||||
Status: progress.Done,
|
||||
})
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -1398,7 +1398,7 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *ty
|
||||
|
||||
resp, err := s.apiClient().NetworkCreate(ctx, n.Name, createOpts)
|
||||
if err != nil {
|
||||
s.events.On(progress.ErrorEvent(networkEventName))
|
||||
s.events.On(progress.ErrorEvent(networkEventName, err.Error()))
|
||||
return "", fmt.Errorf("failed to create network %s: %w", n.Name, err)
|
||||
}
|
||||
s.events.On(progress.CreatedEvent(networkEventName))
|
||||
@@ -1632,7 +1632,7 @@ func (s *composeService) createVolume(ctx context.Context, volume types.VolumeCo
|
||||
DriverOpts: volume.DriverOpts,
|
||||
})
|
||||
if err != nil {
|
||||
s.events.On(progress.ErrorEvent(eventName))
|
||||
s.events.On(progress.ErrorEvent(eventName, err.Error()))
|
||||
return err
|
||||
}
|
||||
s.events.On(progress.CreatedEvent(eventName))
|
||||
|
||||
@@ -235,7 +235,7 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s
|
||||
if errdefs.IsNotFound(err) {
|
||||
continue
|
||||
}
|
||||
s.events.On(progress.ErrorEvent(eventName))
|
||||
s.events.On(progress.ErrorEvent(eventName, err.Error()))
|
||||
return fmt.Errorf("failed to remove network %s: %w", name, err)
|
||||
}
|
||||
s.events.On(progress.RemovedEvent(eventName))
|
||||
@@ -317,7 +317,7 @@ func (s *composeService) stopContainer(ctx context.Context, service *types.Servi
|
||||
timeoutInSecond := utils.DurationSecondToInt(timeout)
|
||||
err := s.apiClient().ContainerStop(ctx, ctr.ID, containerType.StopOptions{Timeout: timeoutInSecond})
|
||||
if err != nil {
|
||||
s.events.On(progress.ErrorMessageEvent(eventName, "Error while Stopping"))
|
||||
s.events.On(progress.ErrorEvent(eventName, "Error while Stopping"))
|
||||
return err
|
||||
}
|
||||
s.events.On(progress.StoppedEvent(eventName))
|
||||
@@ -360,7 +360,7 @@ func (s *composeService) stopAndRemoveContainer(ctx context.Context, ctr contain
|
||||
RemoveVolumes: volumes,
|
||||
})
|
||||
if err != nil && !errdefs.IsNotFound(err) && !errdefs.IsConflict(err) {
|
||||
s.events.On(progress.ErrorMessageEvent(eventName, "Error while Removing"))
|
||||
s.events.On(progress.ErrorEvent(eventName, "Error while Removing"))
|
||||
return err
|
||||
}
|
||||
s.events.On(progress.RemovedEvent(eventName))
|
||||
|
||||
@@ -51,13 +51,10 @@ func (s *composeService) export(ctx context.Context, projectName string, options
|
||||
}
|
||||
|
||||
name := getCanonicalContainerName(container)
|
||||
msg := fmt.Sprintf("export %s to %s", name, options.Output)
|
||||
|
||||
s.events.On(progress.Event{
|
||||
ID: name,
|
||||
Text: msg,
|
||||
Status: progress.Working,
|
||||
StatusText: "Exporting",
|
||||
ID: name,
|
||||
Text: progress.StatusExporting,
|
||||
Status: progress.Working,
|
||||
})
|
||||
|
||||
responseBody, err := s.apiClient().ContainerExport(ctx, container.ID)
|
||||
@@ -67,12 +64,7 @@ func (s *composeService) export(ctx context.Context, projectName string, options
|
||||
|
||||
defer func() {
|
||||
if err := responseBody.Close(); err != nil {
|
||||
s.events.On(progress.Event{
|
||||
ID: name,
|
||||
Text: msg,
|
||||
Status: progress.Error,
|
||||
StatusText: fmt.Sprintf("Failed to close response body: %v", err),
|
||||
})
|
||||
s.events.On(progress.ErrorEventf(name, "Failed to close response body: %s", err.Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -93,10 +85,9 @@ func (s *composeService) export(ctx context.Context, projectName string, options
|
||||
}
|
||||
|
||||
s.events.On(progress.Event{
|
||||
ID: name,
|
||||
Text: msg,
|
||||
Status: progress.Done,
|
||||
StatusText: "Exported",
|
||||
ID: name,
|
||||
Text: progress.StatusExported,
|
||||
Status: progress.Done,
|
||||
})
|
||||
|
||||
return nil
|
||||
|
||||
@@ -66,7 +66,7 @@ func (s *composeService) kill(ctx context.Context, projectName string, options a
|
||||
s.events.On(progress.KillingEvent(eventName))
|
||||
err := s.apiClient().ContainerKill(ctx, ctr.ID, options.Signal)
|
||||
if err != nil {
|
||||
s.events.On(progress.ErrorMessageEvent(eventName, "Error while Killing"))
|
||||
s.events.On(progress.ErrorEvent(eventName, "Error while Killing"))
|
||||
return err
|
||||
}
|
||||
s.events.On(progress.KilledEvent(eventName))
|
||||
|
||||
@@ -132,31 +132,30 @@ func (m *modelAPI) PullModel(ctx context.Context, model types.ModelConfig, quiet
|
||||
|
||||
if !quietPull {
|
||||
events.On(progress.Event{
|
||||
ID: model.Name,
|
||||
Status: progress.Working,
|
||||
Text: "Pulling",
|
||||
StatusText: msg,
|
||||
ID: model.Name,
|
||||
Status: progress.Working,
|
||||
Text: progress.StatusPulling,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
events.On(progress.ErrorMessageEvent(model.Name, err.Error()))
|
||||
events.On(progress.ErrorEvent(model.Name, err.Error()))
|
||||
}
|
||||
events.On(progress.Event{
|
||||
ID: model.Name,
|
||||
Status: progress.Working,
|
||||
StatusText: "Pulled",
|
||||
ID: model.Name,
|
||||
Status: progress.Working,
|
||||
Text: progress.StatusPulled,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *modelAPI) ConfigureModel(ctx context.Context, config types.ModelConfig, events progress.EventProcessor) error {
|
||||
events.On(progress.Event{
|
||||
ID: config.Name,
|
||||
Status: progress.Working,
|
||||
StatusText: "Configuring",
|
||||
ID: config.Name,
|
||||
Status: progress.Working,
|
||||
Text: "Configuring",
|
||||
})
|
||||
// configure [--context-size=<n>] MODEL [-- <runtime-flags...>]
|
||||
args := []string{"configure"}
|
||||
|
||||
@@ -143,7 +143,7 @@ func (s *composeService) executePlugin(cmd *exec.Cmd, command string, service ty
|
||||
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
s.events.On(progress.ErrorMessageEvent(service.Name, err.Error()))
|
||||
s.events.On(progress.ErrorEvent(service.Name, err.Error()))
|
||||
return nil, fmt.Errorf("failed to %s service provider: %s", action, err.Error())
|
||||
}
|
||||
switch command {
|
||||
|
||||
@@ -68,9 +68,10 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
||||
for name, service := range project.Services {
|
||||
if service.Image == "" {
|
||||
s.events.On(progress.Event{
|
||||
ID: name,
|
||||
Status: progress.Done,
|
||||
Text: "Skipped - No image to be pulled",
|
||||
ID: name,
|
||||
Status: progress.Done,
|
||||
Text: "Skipped",
|
||||
Details: "No image to be pulled",
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -86,9 +87,10 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
||||
case types.PullPolicyMissing, types.PullPolicyIfNotPresent:
|
||||
if imageAlreadyPresent(service.Image, images) {
|
||||
s.events.On(progress.Event{
|
||||
ID: "Image " + service.Image,
|
||||
Status: progress.Done,
|
||||
Text: "Skipped - Image is already present locally",
|
||||
ID: "Image " + service.Image,
|
||||
Status: progress.Done,
|
||||
Text: "Skipped",
|
||||
Details: "Image is already present locally",
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -96,9 +98,10 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
||||
|
||||
if service.Build != nil && opts.IgnoreBuildable {
|
||||
s.events.On(progress.Event{
|
||||
ID: "Image " + service.Image,
|
||||
Status: progress.Done,
|
||||
Text: "Skipped - Image can be built",
|
||||
ID: "Image " + service.Image,
|
||||
Status: progress.Done,
|
||||
Text: "Skipped",
|
||||
Details: "Image can be built",
|
||||
})
|
||||
continue
|
||||
}
|
||||
@@ -119,11 +122,8 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
||||
}
|
||||
if !opts.IgnoreFailures && service.Build == nil {
|
||||
if s.dryRun {
|
||||
s.events.On(progress.Event{
|
||||
ID: "Image " + service.Image,
|
||||
Status: progress.Error,
|
||||
Text: fmt.Sprintf(" - Pull error for image: %s", service.Image),
|
||||
})
|
||||
s.events.On(progress.ErrorEventf("Image "+service.Image,
|
||||
"error pulling image: %s", service.Image))
|
||||
}
|
||||
// fail fast if image can't be pulled nor built
|
||||
return err
|
||||
@@ -197,9 +197,9 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser
|
||||
|
||||
if ctx.Err() != nil {
|
||||
s.events.On(progress.Event{
|
||||
ID: resource,
|
||||
Status: progress.Warning,
|
||||
StatusText: "Interrupted",
|
||||
ID: resource,
|
||||
Status: progress.Warning,
|
||||
Text: "Interrupted",
|
||||
})
|
||||
return "", nil
|
||||
}
|
||||
@@ -208,21 +208,15 @@ func (s *composeService) pullServiceImage(ctx context.Context, service types.Ser
|
||||
// then the status should be warning instead of error
|
||||
if err != nil && service.Build != nil {
|
||||
s.events.On(progress.Event{
|
||||
ID: resource,
|
||||
Status: progress.Warning,
|
||||
Text: "Warning",
|
||||
StatusText: getUnwrappedErrorMessage(err),
|
||||
ID: resource,
|
||||
Status: progress.Warning,
|
||||
Text: getUnwrappedErrorMessage(err),
|
||||
})
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s.events.On(progress.Event{
|
||||
ID: resource,
|
||||
Status: progress.Error,
|
||||
Text: "Error",
|
||||
StatusText: getUnwrappedErrorMessage(err),
|
||||
})
|
||||
s.events.On(progress.ErrorEvent(resource, getUnwrappedErrorMessage(err)))
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -442,13 +436,12 @@ func toPullProgressEvent(parent string, jm jsonmessage.JSONMessage, events progr
|
||||
}
|
||||
|
||||
events.On(progress.Event{
|
||||
ID: jm.ID,
|
||||
ParentID: parent,
|
||||
Current: current,
|
||||
Total: total,
|
||||
Percent: percent,
|
||||
Text: jm.Status,
|
||||
Status: status,
|
||||
StatusText: text,
|
||||
ID: jm.ID,
|
||||
ParentID: parent,
|
||||
Current: current,
|
||||
Total: total,
|
||||
Percent: percent,
|
||||
Status: status,
|
||||
Text: text,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -161,14 +161,13 @@ func toPushProgressEvent(prefix string, jm jsonmessage.JSONMessage, events progr
|
||||
}
|
||||
|
||||
events.On(progress.Event{
|
||||
ParentID: prefix,
|
||||
ID: jm.ID,
|
||||
Text: jm.Status,
|
||||
Status: status,
|
||||
Current: current,
|
||||
Total: total,
|
||||
Percent: percent,
|
||||
StatusText: text,
|
||||
ParentID: prefix,
|
||||
ID: jm.ID,
|
||||
Text: text,
|
||||
Status: status,
|
||||
Current: current,
|
||||
Total: total,
|
||||
Percent: percent,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -536,7 +536,7 @@ func TestBuildDependsOn(t *testing.T) {
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "fixtures/build-dependencies/compose-depends_on.yaml", "--progress=plain", "up", "test2")
|
||||
out := res.Combined()
|
||||
assert.Check(t, strings.Contains(out, "test1 Built"))
|
||||
assert.Check(t, strings.Contains(out, "test1 Built"))
|
||||
}
|
||||
|
||||
func TestBuildSubset(t *testing.T) {
|
||||
@@ -548,7 +548,7 @@ func TestBuildSubset(t *testing.T) {
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "fixtures/build-test/subset/compose.yaml", "build", "main")
|
||||
out := res.Combined()
|
||||
assert.Check(t, strings.Contains(out, "main Built"))
|
||||
assert.Check(t, strings.Contains(out, "main Built"))
|
||||
}
|
||||
|
||||
func TestBuildDependentImage(t *testing.T) {
|
||||
@@ -560,11 +560,11 @@ func TestBuildDependentImage(t *testing.T) {
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "fixtures/build-test/dependencies/compose.yaml", "build", "firstbuild")
|
||||
out := res.Combined()
|
||||
assert.Check(t, strings.Contains(out, "firstbuild Built"))
|
||||
assert.Check(t, strings.Contains(out, "firstbuild Built"))
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "-f", "fixtures/build-test/dependencies/compose.yaml", "build", "secondbuild")
|
||||
out = res.Combined()
|
||||
assert.Check(t, strings.Contains(out, "secondbuild Built"))
|
||||
assert.Check(t, strings.Contains(out, "secondbuild Built"))
|
||||
}
|
||||
|
||||
func TestBuildSubDependencies(t *testing.T) {
|
||||
@@ -576,11 +576,11 @@ func TestBuildSubDependencies(t *testing.T) {
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "fixtures/build-test/sub-dependencies/compose.yaml", "build", "main")
|
||||
out := res.Combined()
|
||||
assert.Check(t, strings.Contains(out, "main Built"))
|
||||
assert.Check(t, strings.Contains(out, "main Built"))
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "-f", "fixtures/build-test/sub-dependencies/compose.yaml", "up", "--build", "main")
|
||||
out = res.Combined()
|
||||
assert.Check(t, strings.Contains(out, "main Built"))
|
||||
assert.Check(t, strings.Contains(out, "main Built"))
|
||||
}
|
||||
|
||||
func TestBuildLongOutputLine(t *testing.T) {
|
||||
@@ -592,11 +592,11 @@ func TestBuildLongOutputLine(t *testing.T) {
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "fixtures/build-test/long-output-line/compose.yaml", "build", "long-line")
|
||||
out := res.Combined()
|
||||
assert.Check(t, strings.Contains(out, "long-line Built"))
|
||||
assert.Check(t, strings.Contains(out, "long-line Built"))
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "-f", "fixtures/build-test/long-output-line/compose.yaml", "up", "--build", "long-line")
|
||||
out = res.Combined()
|
||||
assert.Check(t, strings.Contains(out, "long-line Built"))
|
||||
assert.Check(t, strings.Contains(out, "long-line Built"))
|
||||
}
|
||||
|
||||
func TestBuildDependentImageWithProfile(t *testing.T) {
|
||||
@@ -608,7 +608,7 @@ func TestBuildDependentImageWithProfile(t *testing.T) {
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "fixtures/build-test/profiles/compose.yaml", "build", "secret-build-test")
|
||||
out := res.Combined()
|
||||
assert.Check(t, strings.Contains(out, "secret-build-test Built"))
|
||||
assert.Check(t, strings.Contains(out, "secret-build-test Built"))
|
||||
}
|
||||
|
||||
func TestBuildTLS(t *testing.T) {
|
||||
|
||||
@@ -187,8 +187,8 @@ func TestLocalComposeRun(t *testing.T) {
|
||||
res.Assert(t, icmd.Success)
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/pull.yaml", "run", "--pull", "always", "backend")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Image nginx Pulling"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Image nginx Pulled"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Image nginx Pulling"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Image nginx Pulled"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("compose run --env-from-file", func(t *testing.T) {
|
||||
|
||||
@@ -213,10 +213,10 @@ func TestNetworkRecreate(t *testing.T) {
|
||||
err := res.Stderr()
|
||||
fmt.Println(err)
|
||||
res.Assert(t, icmd.Expected{Err: `
|
||||
Container network_recreate-web-1 Stopped
|
||||
Network network_recreate_test Removed
|
||||
Network network_recreate_test Creating
|
||||
Network network_recreate_test Created
|
||||
Container network_recreate-web-1 Starting
|
||||
Container network_recreate-web-1 Started`})
|
||||
Container network_recreate-web-1 Stopped
|
||||
Network network_recreate_test Removed
|
||||
Network network_recreate_test Creating
|
||||
Network network_recreate_test Created
|
||||
Container network_recreate-web-1 Starting
|
||||
Container network_recreate-web-1 Started`})
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestPs(t *testing.T) {
|
||||
_ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
|
||||
})
|
||||
|
||||
assert.Contains(t, res.Combined(), "Container e2e-ps-busybox-1 Started", res.Combined())
|
||||
assert.Contains(t, res.Combined(), "Container e2e-ps-busybox-1 Started", res.Combined())
|
||||
|
||||
t.Run("table", func(t *testing.T) {
|
||||
res = c.RunDockerComposeCmd(t, "-f", "./fixtures/ps-test/compose.yaml", "--project-name", projectName, "ps")
|
||||
|
||||
@@ -34,15 +34,15 @@ func TestComposePull(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/simple", "pull")
|
||||
output := res.Combined()
|
||||
|
||||
assert.Assert(t, strings.Contains(output, "Image alpine:3.14 Pulled"))
|
||||
assert.Assert(t, strings.Contains(output, "Image alpine:3.15 Pulled"))
|
||||
assert.Assert(t, strings.Contains(output, "Image alpine:3.14 Pulled"))
|
||||
assert.Assert(t, strings.Contains(output, "Image alpine:3.15 Pulled"))
|
||||
|
||||
// verify default policy is 'always' for pull command
|
||||
res = c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/simple", "pull")
|
||||
output = res.Combined()
|
||||
|
||||
assert.Assert(t, strings.Contains(output, "Image alpine:3.14 Pulled"))
|
||||
assert.Assert(t, strings.Contains(output, "Image alpine:3.15 Pulled"))
|
||||
assert.Assert(t, strings.Contains(output, "Image alpine:3.14 Pulled"))
|
||||
assert.Assert(t, strings.Contains(output, "Image alpine:3.15 Pulled"))
|
||||
})
|
||||
|
||||
t.Run("Verify skipped pull if image is already present locally", func(t *testing.T) {
|
||||
@@ -52,16 +52,16 @@ func TestComposePull(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/image-present-locally", "pull")
|
||||
output := res.Combined()
|
||||
|
||||
assert.Assert(t, strings.Contains(output, "alpine:3.13.12 Skipped - Image is already present locally"))
|
||||
assert.Assert(t, strings.Contains(output, "alpine:3.13.12 Skipped Image is already present locally"))
|
||||
// image with :latest tag gets pulled regardless if pull_policy: missing or if_not_present
|
||||
assert.Assert(t, strings.Contains(output, "alpine:latest Pulled"))
|
||||
assert.Assert(t, strings.Contains(output, "alpine:latest Pulled"))
|
||||
})
|
||||
|
||||
t.Run("Verify skipped no image to be pulled", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/compose-pull/no-image-name-given", "pull")
|
||||
output := res.Combined()
|
||||
|
||||
assert.Assert(t, strings.Contains(output, "Skipped - No image to be pulled"))
|
||||
assert.Assert(t, strings.Contains(output, "Skipped No image to be pulled"))
|
||||
})
|
||||
|
||||
t.Run("Verify pull failure", func(t *testing.T) {
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestRestart(t *testing.T) {
|
||||
c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/restart-test/compose.yaml", "--project-name", projectName, "up", "-d")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-restart-restart-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-restart-restart-1 Started"), res.Combined())
|
||||
|
||||
c.WaitForCmdResult(t, c.NewDockerComposeCmd(t, "--project-name", projectName, "ps", "-a", "--format",
|
||||
"json"),
|
||||
@@ -80,9 +80,9 @@ func TestRestartWithDependencies(t *testing.T) {
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "restart", baseService)
|
||||
out := res.Combined()
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Restarting", baseService)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Healthy", baseService)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Started", depWithRestart)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Restarting", baseService)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Healthy", baseService)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Started", depWithRestart)), out)
|
||||
assert.Assert(t, !strings.Contains(out, depNoRestart), out)
|
||||
|
||||
c = NewParallelCLI(t, WithEnv(
|
||||
@@ -91,11 +91,11 @@ func TestRestartWithDependencies(t *testing.T) {
|
||||
))
|
||||
res = c.RunDockerComposeCmd(t, "-f", "./fixtures/restart-test/compose-depends-on.yaml", "up", "-d")
|
||||
out = res.Combined()
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Stopped", depWithRestart)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Recreated", baseService)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Healthy", baseService)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Started", depWithRestart)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Running", depNoRestart)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Stopped", depWithRestart)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Recreated", baseService)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Healthy", baseService)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Started", depWithRestart)), out)
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Running", depNoRestart)), out)
|
||||
}
|
||||
|
||||
func TestRestartWithProfiles(t *testing.T) {
|
||||
@@ -111,5 +111,5 @@ func TestRestartWithProfiles(t *testing.T) {
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "restart", "test")
|
||||
fmt.Println(res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-restart-profiles-test-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-restart-profiles-test-1 Started"), res.Combined())
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestStartStop(t *testing.T) {
|
||||
t.Run("Up a project", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/compose.yaml", "--project-name", projectName, "up",
|
||||
"-d")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-no-dependencies-simple-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-no-dependencies-simple-1 Started"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "ls", "--all")
|
||||
testify.Regexp(t, getProjectRegx("running"), res.Stdout())
|
||||
@@ -87,14 +87,14 @@ func TestStartStopWithDependencies(t *testing.T) {
|
||||
t.Run("Up", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dependencies/compose.yaml", "--project-name", projectName,
|
||||
"up", "-d")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Started"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("stop foo", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "--project-name", projectName, "stop", "foo")
|
||||
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Stopped"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Stopped"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "ps", "--status", "running")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "e2e-start-stop-with-dependencies-bar-1"), res.Combined())
|
||||
@@ -103,12 +103,12 @@ func TestStartStopWithDependencies(t *testing.T) {
|
||||
|
||||
t.Run("start foo", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "--project-name", projectName, "stop")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Stopped"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Stopped"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "start", "foo")
|
||||
out := res.Combined()
|
||||
assert.Assert(t, strings.Contains(out, "Container e2e-start-stop-with-dependencies-bar-1 Started"), out)
|
||||
assert.Assert(t, strings.Contains(out, "Container e2e-start-stop-with-dependencies-foo-1 Started"), out)
|
||||
assert.Assert(t, strings.Contains(out, "Container e2e-start-stop-with-dependencies-bar-1 Started"), out)
|
||||
assert.Assert(t, strings.Contains(out, "Container e2e-start-stop-with-dependencies-foo-1 Started"), out)
|
||||
|
||||
res = c.RunDockerComposeCmd(t, "--project-name", projectName, "ps", "--status", "running")
|
||||
out = res.Combined()
|
||||
@@ -120,8 +120,8 @@ func TestStartStopWithDependencies(t *testing.T) {
|
||||
_ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/links/compose.yaml", "--project-name", projectName, "up",
|
||||
"--no-deps", "-d", "foo")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "Container e2e-start-stop-with-dependencies-bar-1 Started"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("down", func(t *testing.T) {
|
||||
@@ -136,8 +136,8 @@ func TestStartStopWithOneOffs(t *testing.T) {
|
||||
t.Run("Up", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dependencies/compose.yaml", "--project-name", projectName,
|
||||
"up", "-d")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-oneoffs-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-oneoffs-bar-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-oneoffs-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-with-oneoffs-bar-1 Started"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("run one-off", func(t *testing.T) {
|
||||
@@ -213,7 +213,7 @@ func TestStopAlreadyStopped(t *testing.T) {
|
||||
// container is already stopped
|
||||
res.Assert(t, icmd.Expected{
|
||||
ExitCode: 0,
|
||||
Err: "Container e2e-start-stop-svc-already-stopped-simple-1 Stopped",
|
||||
Err: "Container e2e-start-stop-svc-already-stopped-simple-1 Stopped",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -230,14 +230,14 @@ func TestStartStopMultipleServices(t *testing.T) {
|
||||
res := cli.RunDockerComposeCmd(t, "stop", "simple", "another")
|
||||
services := []string{"simple", "another"}
|
||||
for _, svc := range services {
|
||||
stopMsg := fmt.Sprintf("Container e2e-start-stop-svc-multiple-%s-1 Stopped", svc)
|
||||
stopMsg := fmt.Sprintf("Container e2e-start-stop-svc-multiple-%s-1 Stopped", svc)
|
||||
assert.Assert(t, strings.Contains(res.Stderr(), stopMsg),
|
||||
fmt.Sprintf("Missing stop message for %s\n%s", svc, res.Combined()))
|
||||
}
|
||||
|
||||
res = cli.RunDockerComposeCmd(t, "start", "simple", "another")
|
||||
for _, svc := range services {
|
||||
startMsg := fmt.Sprintf("Container e2e-start-stop-svc-multiple-%s-1 Started", svc)
|
||||
startMsg := fmt.Sprintf("Container e2e-start-stop-svc-multiple-%s-1 Started", svc)
|
||||
assert.Assert(t, strings.Contains(res.Stderr(), startMsg),
|
||||
fmt.Sprintf("Missing start message for %s\n%s", svc, res.Combined()))
|
||||
}
|
||||
@@ -256,7 +256,7 @@ func TestStartSingleServiceAndDependency(t *testing.T) {
|
||||
res := cli.RunDockerComposeCmd(t, "start", "desired")
|
||||
desiredServices := []string{"desired", "dep_1", "dep_2"}
|
||||
for _, s := range desiredServices {
|
||||
startMsg := fmt.Sprintf("Container e2e-start-single-deps-%s-1 Started", s)
|
||||
startMsg := fmt.Sprintf("Container e2e-start-single-deps-%s-1 Started", s)
|
||||
assert.Assert(t, strings.Contains(res.Combined(), startMsg),
|
||||
fmt.Sprintf("Missing start message for service: %s\n%s", s, res.Combined()))
|
||||
}
|
||||
@@ -277,8 +277,8 @@ func TestStartStopMultipleFiles(t *testing.T) {
|
||||
cli.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/other.yaml", "up", "-d")
|
||||
|
||||
res := cli.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/compose.yaml", "stop")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-simple-1 Stopped"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-another-1 Stopped"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-a-different-one-1 Stopped"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-and-another-one-1 Stopped"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-simple-1 Stopped"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-another-1 Stopped"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-a-different-one-1 Stopped"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-and-another-one-1 Stopped"), res.Combined())
|
||||
}
|
||||
|
||||
@@ -175,8 +175,8 @@ func TestUpWithAllResources(t *testing.T) {
|
||||
})
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/resources/compose.yaml", "--all-resources", "--project-name", projectName, "up")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), fmt.Sprintf(`Volume %s_my_vol Created`, projectName)), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), fmt.Sprintf(`Network %s_my_net Created`, projectName)), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), fmt.Sprintf(`Volume %s_my_vol Created`, projectName)), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), fmt.Sprintf(`Network %s_my_net Created`, projectName)), res.Combined())
|
||||
}
|
||||
|
||||
func TestUpProfile(t *testing.T) {
|
||||
@@ -187,9 +187,9 @@ func TestUpProfile(t *testing.T) {
|
||||
})
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/profiles/docker-compose.yaml", "--project-name", projectName, "up", "foo")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), `Container db_c Created`), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), `Container foo_c Created`), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), `Container bar_c Created`), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), `Container db_c Created`), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), `Container foo_c Created`), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), `Container bar_c Created`), res.Combined())
|
||||
}
|
||||
|
||||
func TestUpImageID(t *testing.T) {
|
||||
@@ -218,7 +218,7 @@ func TestUpStopWithLogsMixed(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/stop/compose.yaml", "--project-name", projectName, "up", "--abort-on-container-exit")
|
||||
// assert we still get service2 logs after service 1 Stopped event
|
||||
res.Assert(t, icmd.Expected{
|
||||
Err: "Container compose-e2e-stop-logs-service1-1 Stopped",
|
||||
Err: "Container compose-e2e-stop-logs-service1-1 Stopped",
|
||||
})
|
||||
// assert we get stop hook logs
|
||||
res.Assert(t, icmd.Expected{Out: "service2-1 -> | stop hook running...\nservice2-1 | 64 bytes"})
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
package progress
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// EventStatus indicates the status of an action
|
||||
type EventStatus int
|
||||
@@ -54,28 +57,52 @@ const (
|
||||
StatusBuilt = "Built"
|
||||
StatusPulling = "Pulling"
|
||||
StatusPulled = "Pulled"
|
||||
StatusCommitting = "Committing"
|
||||
StatusCommitted = "Committed"
|
||||
StatusCopying = "Copying"
|
||||
StatusCopied = "Copied"
|
||||
StatusExporting = "Exporting"
|
||||
StatusExported = "Exported"
|
||||
)
|
||||
|
||||
// Event represents a progress event.
|
||||
type Event struct {
|
||||
ID string
|
||||
ParentID string
|
||||
Text string
|
||||
Status EventStatus
|
||||
StatusText string
|
||||
Current int64
|
||||
Percent int
|
||||
Total int64
|
||||
ID string
|
||||
ParentID string
|
||||
Text string
|
||||
Details string
|
||||
Status EventStatus
|
||||
Current int64
|
||||
Percent int
|
||||
Total int64
|
||||
}
|
||||
|
||||
// ErrorMessageEvent creates a new Error Event with message
|
||||
func ErrorMessageEvent(id string, msg string) Event {
|
||||
return NewEvent(id, Error, msg)
|
||||
func (e *Event) StatusText() string {
|
||||
switch e.Status {
|
||||
case Working:
|
||||
return "Working"
|
||||
case Warning:
|
||||
return "Warning"
|
||||
case Done:
|
||||
return "Done"
|
||||
default:
|
||||
return "Error"
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorEvent creates a new Error Event
|
||||
func ErrorEvent(id string) Event {
|
||||
return NewEvent(id, Error, StatusError)
|
||||
// ErrorEvent creates a new Error Event with message
|
||||
func ErrorEvent(id string, msg string) Event {
|
||||
return Event{
|
||||
ID: id,
|
||||
Status: Error,
|
||||
Text: StatusError,
|
||||
Details: msg,
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorEventf creates a new Error Event with format message
|
||||
func ErrorEventf(id string, msg string, args ...any) Event {
|
||||
return ErrorEvent(id, fmt.Sprintf(msg, args...))
|
||||
}
|
||||
|
||||
// CreatingEvent creates a new Create in progress Event
|
||||
@@ -181,18 +208,18 @@ func PulledEvent(id string) Event {
|
||||
// SkippedEvent creates a new Skipped Event
|
||||
func SkippedEvent(id string, reason string) Event {
|
||||
return Event{
|
||||
ID: id,
|
||||
Status: Warning,
|
||||
StatusText: "Skipped: " + reason,
|
||||
ID: id,
|
||||
Status: Warning,
|
||||
Text: "Skipped: " + reason,
|
||||
}
|
||||
}
|
||||
|
||||
// NewEvent new event
|
||||
func NewEvent(id string, status EventStatus, statusText string) Event {
|
||||
func NewEvent(id string, status EventStatus, text string) Event {
|
||||
return Event{
|
||||
ID: id,
|
||||
Status: status,
|
||||
StatusText: statusText,
|
||||
ID: id,
|
||||
Status: status,
|
||||
Text: text,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,9 @@ type jsonMessage struct {
|
||||
Tail bool `json:"tail,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
ParentID string `json:"parent_id,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Details string `json:"details,omitempty"`
|
||||
Current int64 `json:"current,omitempty"`
|
||||
Total int64 `json:"total,omitempty"`
|
||||
Percent int `json:"percent,omitempty"`
|
||||
@@ -54,8 +55,9 @@ func (p *jsonWriter) Event(e Event) {
|
||||
DryRun: p.dryRun,
|
||||
Tail: false,
|
||||
ID: e.ID,
|
||||
Status: e.StatusText(),
|
||||
Text: e.Text,
|
||||
Status: e.StatusText,
|
||||
Details: e.Details,
|
||||
ParentID: e.ParentID,
|
||||
Current: e.Current,
|
||||
Total: e.Total,
|
||||
|
||||
@@ -32,13 +32,13 @@ func TestJsonWriter_Event(t *testing.T) {
|
||||
}
|
||||
|
||||
event := Event{
|
||||
ID: "service1",
|
||||
ParentID: "project",
|
||||
Text: "Creating",
|
||||
StatusText: "Working",
|
||||
Current: 50,
|
||||
Total: 100,
|
||||
Percent: 50,
|
||||
ID: "service1",
|
||||
ParentID: "project",
|
||||
Status: Working,
|
||||
Text: StatusCreating,
|
||||
Current: 50,
|
||||
Total: 100,
|
||||
Percent: 50,
|
||||
}
|
||||
w.Event(event)
|
||||
|
||||
@@ -50,8 +50,8 @@ func TestJsonWriter_Event(t *testing.T) {
|
||||
DryRun: true,
|
||||
ID: event.ID,
|
||||
ParentID: event.ParentID,
|
||||
Text: event.Text,
|
||||
Status: event.StatusText,
|
||||
Text: StatusCreating,
|
||||
Status: "Working",
|
||||
Current: event.Current,
|
||||
Total: event.Total,
|
||||
Percent: event.Percent,
|
||||
|
||||
@@ -43,7 +43,7 @@ func (p *plainWriter) Event(e Event) {
|
||||
if p.dryRun {
|
||||
prefix = api.DRYRUN_PREFIX
|
||||
}
|
||||
_, _ = fmt.Fprintln(p.out, prefix, e.ID, e.Text, e.StatusText)
|
||||
_, _ = fmt.Fprintln(p.out, prefix, e.ID, e.Text, e.Details)
|
||||
}
|
||||
|
||||
func (p *plainWriter) On(events ...Event) {
|
||||
|
||||
@@ -58,17 +58,17 @@ type ttyWriter struct {
|
||||
}
|
||||
|
||||
type task struct {
|
||||
ID string
|
||||
parentID string
|
||||
startTime time.Time
|
||||
endTime time.Time
|
||||
text string
|
||||
status EventStatus
|
||||
statusText string
|
||||
current int64
|
||||
percent int
|
||||
total int64
|
||||
spinner *Spinner
|
||||
ID string
|
||||
parentID string
|
||||
startTime time.Time
|
||||
endTime time.Time
|
||||
text string
|
||||
details string
|
||||
status EventStatus
|
||||
current int64
|
||||
percent int
|
||||
total int64
|
||||
spinner *Spinner
|
||||
}
|
||||
|
||||
func (t *task) stop() {
|
||||
@@ -112,7 +112,7 @@ func (w *ttyWriter) On(events ...Event) {
|
||||
w.mtx.Lock()
|
||||
defer w.mtx.Unlock()
|
||||
for _, e := range events {
|
||||
if w.operation != "start" && (e.StatusText == "Started" || e.StatusText == "Starting") {
|
||||
if w.operation != "start" && (e.Text == StatusStarted || e.Text == StatusStarting) {
|
||||
// skip those events to avoid mix with container logs
|
||||
continue
|
||||
}
|
||||
@@ -122,8 +122,7 @@ func (w *ttyWriter) On(events ...Event) {
|
||||
|
||||
func (w *ttyWriter) event(e Event) {
|
||||
// Suspend print while a build is in progress, to avoid collision with buildkit Display
|
||||
if e.StatusText == StatusBuilding {
|
||||
fmt.Println("suspend during build")
|
||||
if e.Text == StatusBuilding {
|
||||
w.ticker.Stop()
|
||||
w.suspended = true
|
||||
} else if w.suspended {
|
||||
@@ -142,7 +141,7 @@ func (w *ttyWriter) event(e Event) {
|
||||
}
|
||||
last.status = e.Status
|
||||
last.text = e.Text
|
||||
last.statusText = e.StatusText
|
||||
last.details = e.Details
|
||||
// progress can only go up
|
||||
if e.Total > last.total {
|
||||
last.total = e.Total
|
||||
@@ -160,16 +159,16 @@ func (w *ttyWriter) event(e Event) {
|
||||
w.tasks[e.ID] = last
|
||||
} else {
|
||||
t := task{
|
||||
ID: e.ID,
|
||||
parentID: e.ParentID,
|
||||
startTime: time.Now(),
|
||||
text: e.Text,
|
||||
status: e.Status,
|
||||
statusText: e.StatusText,
|
||||
current: e.Current,
|
||||
percent: e.Percent,
|
||||
total: e.Total,
|
||||
spinner: NewSpinner(),
|
||||
ID: e.ID,
|
||||
parentID: e.ParentID,
|
||||
startTime: time.Now(),
|
||||
text: e.Text,
|
||||
details: e.Details,
|
||||
status: e.Status,
|
||||
current: e.Current,
|
||||
percent: e.Percent,
|
||||
total: e.Total,
|
||||
spinner: NewSpinner(),
|
||||
}
|
||||
if e.Status == Done || e.Status == Error {
|
||||
t.stop()
|
||||
@@ -197,7 +196,7 @@ func (w *ttyWriter) printEvent(e Event) {
|
||||
case Error:
|
||||
color = ErrorColor
|
||||
}
|
||||
_, _ = fmt.Fprintf(w.out, "%s %s %s\n", e.ID, e.Text, color(e.StatusText))
|
||||
_, _ = fmt.Fprintf(w.out, "%s %s %s\n", e.ID, color(e.Text), e.Details)
|
||||
}
|
||||
|
||||
func (w *ttyWriter) print() {
|
||||
@@ -228,7 +227,7 @@ func (w *ttyWriter) print() {
|
||||
|
||||
var statusPadding int
|
||||
for _, t := range w.tasks {
|
||||
l := len(fmt.Sprintf("%s %s", t.ID, t.text))
|
||||
l := len(t.ID)
|
||||
if statusPadding < l {
|
||||
statusPadding = l
|
||||
}
|
||||
@@ -314,20 +313,17 @@ func (w *ttyWriter) lineText(t task, pad string, terminalWidth, statusPadding in
|
||||
hideDetails = true
|
||||
}
|
||||
|
||||
var txt string
|
||||
txt := t.ID
|
||||
if len(completion) > 0 {
|
||||
var details string
|
||||
var progress string
|
||||
if !hideDetails {
|
||||
details = fmt.Sprintf(" %7s / %-7s", units.HumanSize(float64(current)), units.HumanSize(float64(total)))
|
||||
progress = fmt.Sprintf(" %7s / %-7s", units.HumanSize(float64(current)), units.HumanSize(float64(total)))
|
||||
}
|
||||
txt = fmt.Sprintf("%s [%s]%s %s",
|
||||
txt = fmt.Sprintf("%s [%s]%s",
|
||||
t.ID,
|
||||
SuccessColor(strings.Join(completion, "")),
|
||||
details,
|
||||
t.text,
|
||||
progress,
|
||||
)
|
||||
} else {
|
||||
txt = fmt.Sprintf("%s %s", t.ID, t.text)
|
||||
}
|
||||
textLen := len(txt)
|
||||
padding := statusPadding - textLen
|
||||
@@ -336,19 +332,20 @@ func (w *ttyWriter) lineText(t task, pad string, terminalWidth, statusPadding in
|
||||
}
|
||||
// calculate the max length for the status text, on errors it
|
||||
// is 2-3 lines long and breaks the line formatting
|
||||
maxStatusLen := terminalWidth - textLen - statusPadding - 15
|
||||
status := t.statusText
|
||||
maxDetailsLen := terminalWidth - textLen - statusPadding - 15
|
||||
details := t.details
|
||||
// in some cases (debugging under VS Code), terminalWidth is set to zero by goterm.Width() ; ensuring we don't tweak strings with negative char index
|
||||
if maxStatusLen > 0 && len(status) > maxStatusLen {
|
||||
status = status[:maxStatusLen] + "..."
|
||||
if maxDetailsLen > 0 && len(details) > maxDetailsLen {
|
||||
details = details[:maxDetailsLen] + "..."
|
||||
}
|
||||
text := fmt.Sprintf("%s %s%s %s%s %s",
|
||||
text := fmt.Sprintf("%s %s%s %s %s%s %s",
|
||||
pad,
|
||||
spinner(t),
|
||||
prefix,
|
||||
txt,
|
||||
strings.Repeat(" ", padding),
|
||||
colorFn(t.status)(status),
|
||||
colorFn(t.status)(t.text),
|
||||
details,
|
||||
)
|
||||
timer := fmt.Sprintf("%.1fs ", elapsed)
|
||||
o := align(text, TimerColor(timer), terminalWidth)
|
||||
|
||||
Reference in New Issue
Block a user