mirror of https://github.com/docker/compose.git
Merge pull request #10622 from ndeloof/logs_follow
fix `compose -p x logs -f` detect new services started after command
This commit is contained in:
commit
7c3fe359b7
|
@ -25,7 +25,6 @@ import (
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
|
||||||
"github.com/docker/compose/v2/pkg/api"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
|
|
||||||
"github.com/docker/compose/v2/pkg/utils"
|
"github.com/docker/compose/v2/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -67,8 +66,8 @@ func (s *composeService) Events(ctx context.Context, projectName string, options
|
||||||
err := options.Consumer(api.Event{
|
err := options.Consumer(api.Event{
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
Service: service,
|
Service: service,
|
||||||
Container: event.ID,
|
Container: event.Actor.ID,
|
||||||
Status: event.Status,
|
Status: event.Action,
|
||||||
Attributes: attributes,
|
Attributes: attributes,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -45,19 +45,12 @@ func (s *composeService) Logs(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
project := options.Project
|
if options.Project != nil && len(options.Services) == 0 {
|
||||||
if project == nil {
|
// we run with an explicit compose.yaml, so only consider services defined in this file
|
||||||
project, err = s.getProjectWithResources(ctx, containers, projectName)
|
options.Services = options.Project.ServiceNames()
|
||||||
if err != nil {
|
containers = containers.filter(isService(options.Services...))
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(options.Services) == 0 {
|
|
||||||
options.Services = project.ServiceNames()
|
|
||||||
}
|
|
||||||
|
|
||||||
containers = containers.filter(isService(options.Services...))
|
|
||||||
eg, ctx := errgroup.WithContext(ctx)
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
for _, c := range containers {
|
for _, c := range containers {
|
||||||
c := c
|
c := c
|
||||||
|
|
|
@ -155,13 +155,31 @@ func (s *composeService) watchContainers(ctx context.Context, //nolint:gocyclo
|
||||||
required = services
|
required = services
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// predicate to tell if a container we receive event for should be considered or ignored
|
||||||
|
ofInterest := func(c moby.Container) bool {
|
||||||
|
if len(services) > 0 {
|
||||||
|
// we only watch some services
|
||||||
|
return utils.Contains(services, c.Labels[api.ServiceLabel])
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// predicate to tell if a container we receive event for should be watched until termination
|
||||||
|
isRequired := func(c moby.Container) bool {
|
||||||
|
if len(services) > 0 && len(required) > 0 {
|
||||||
|
// we only watch some services
|
||||||
|
return utils.Contains(required, c.Labels[api.ServiceLabel])
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
expected []string
|
expected []string
|
||||||
watched = map[string]int{}
|
watched = map[string]int{}
|
||||||
replaced []string
|
replaced []string
|
||||||
)
|
)
|
||||||
for _, c := range containers {
|
for _, c := range containers {
|
||||||
if utils.Contains(required, c.Labels[api.ServiceLabel]) {
|
if isRequired(c) {
|
||||||
expected = append(expected, c.ID)
|
expected = append(expected, c.ID)
|
||||||
}
|
}
|
||||||
watched[c.ID] = 0
|
watched[c.ID] = 0
|
||||||
|
@ -265,6 +283,11 @@ func (s *composeService) watchContainers(ctx context.Context, //nolint:gocyclo
|
||||||
if utils.Contains(expected, id) {
|
if utils.Contains(expected, id) {
|
||||||
expected = append(expected, container.ID)
|
expected = append(expected, container.ID)
|
||||||
}
|
}
|
||||||
|
} else if ofInterest(container) {
|
||||||
|
watched[container.ID] = 1
|
||||||
|
if isRequired(container) {
|
||||||
|
expected = append(expected, container.ID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(expected) == 0 {
|
if len(expected) == 0 {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
services:
|
services:
|
||||||
ping:
|
ping:
|
||||||
image: alpine
|
image: alpine
|
||||||
command: ping localhost -c 1
|
command: ping localhost -c ${REPEAT:-1}
|
||||||
hello:
|
hello:
|
||||||
image: alpine
|
image: alpine
|
||||||
command: echo hello
|
command: echo hello
|
||||||
|
|
|
@ -17,10 +17,13 @@
|
||||||
package e2e
|
package e2e
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
|
"gotest.tools/v3/poll"
|
||||||
|
|
||||||
"gotest.tools/v3/icmd"
|
"gotest.tools/v3/icmd"
|
||||||
)
|
)
|
||||||
|
@ -56,3 +59,42 @@ func TestLocalComposeLogs(t *testing.T) {
|
||||||
_ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
|
_ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLocalComposeLogsFollow(t *testing.T) {
|
||||||
|
c := NewCLI(t, WithEnv("REPEAT=20"))
|
||||||
|
const projectName = "compose-e2e-logs"
|
||||||
|
t.Cleanup(func() {
|
||||||
|
c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
|
||||||
|
})
|
||||||
|
|
||||||
|
c.RunDockerComposeCmd(t, "-f", "./fixtures/logs-test/compose.yaml", "--project-name", projectName, "up", "-d", "ping")
|
||||||
|
|
||||||
|
cmd := c.NewDockerComposeCmd(t, "--project-name", projectName, "logs", "-f")
|
||||||
|
res := icmd.StartCmd(cmd)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = res.Cmd.Process.Kill()
|
||||||
|
})
|
||||||
|
|
||||||
|
expected := fmt.Sprintf("%s-ping-1 ", projectName)
|
||||||
|
poll.WaitOn(t, expectOutput(res, expected), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(1*time.Second))
|
||||||
|
|
||||||
|
c.RunDockerComposeCmd(t, "-f", "./fixtures/logs-test/compose.yaml", "--project-name", projectName, "up", "-d")
|
||||||
|
|
||||||
|
expected = fmt.Sprintf("%s-hello-1 ", projectName)
|
||||||
|
poll.WaitOn(t, expectOutput(res, expected), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(1*time.Second))
|
||||||
|
|
||||||
|
c.RunDockerComposeCmd(t, "-f", "./fixtures/logs-test/compose.yaml", "--project-name", projectName, "up", "-d", "--scale", "ping=2", "ping")
|
||||||
|
|
||||||
|
expected = fmt.Sprintf("%s-ping-2 ", projectName)
|
||||||
|
poll.WaitOn(t, expectOutput(res, expected), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(20*time.Second))
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectOutput(res *icmd.Result, expected string) func(t poll.LogT) poll.Result {
|
||||||
|
return func(t poll.LogT) poll.Result {
|
||||||
|
if strings.Contains(res.Stdout(), expected) {
|
||||||
|
return poll.Success()
|
||||||
|
}
|
||||||
|
return poll.Continue("condition not met")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue