Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion pkg/compose/convergence.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project,
case ContainerCreated:
case ContainerRestarting:
case ContainerExited:
w.Event(progress.CreatedEvent(name))
default:
container := container
eg.Go(tracing.EventWrapFuncForErrGroup(ctx, "service/start", tracing.ContainerOptions(container), func(ctx context.Context) error {
Expand Down
65 changes: 58 additions & 7 deletions pkg/compose/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ import (
"github.com/compose-spec/compose-go/v2/paths"
"github.com/compose-spec/compose-go/v2/types"
cerrdefs "github.com/containerd/errdefs"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/prompt"
"github.com/docker/docker/api/types/blkiodev"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
Expand All @@ -45,6 +42,10 @@ import (
"github.com/docker/go-connections/nat"
"github.com/sirupsen/logrus"
cdi "tags.cncf.io/container-device-interface/pkg/parser"

"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/prompt"
)

type createOptions struct {
Expand Down Expand Up @@ -1262,6 +1263,9 @@ func (s *composeService) ensureNetwork(ctx context.Context, project *types.Proje
}

func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *types.Project, name string, n *types.NetworkConfig) (string, error) { //nolint:gocyclo
// This is containers that could be left after a diverged network was removed
var dangledContainers Containers

// First, try to find a unique network matching by name or ID
inspect, err := s.apiClient().NetworkInspect(ctx, n.Name, network.InspectOptions{})
if err == nil {
Expand Down Expand Up @@ -1295,7 +1299,7 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *ty
return inspect.ID, nil
}

err = s.removeDivergedNetwork(ctx, project, name, n)
dangledContainers, err = s.removeDivergedNetwork(ctx, project, name, n)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -1392,10 +1396,16 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *ty
return "", fmt.Errorf("failed to create network %s: %w", n.Name, err)
}
w.Event(progress.CreatedEvent(networkEventName))

err = s.connectNetwork(ctx, n.Name, dangledContainers, nil)
if err != nil {
return "", err
}

return resp.ID, nil
}

func (s *composeService) removeDivergedNetwork(ctx context.Context, project *types.Project, name string, n *types.NetworkConfig) error {
func (s *composeService) removeDivergedNetwork(ctx context.Context, project *types.Project, name string, n *types.NetworkConfig) (Containers, error) {
// Remove services attached to this network to force recreation
var services []string
for _, service := range project.Services.Filter(func(config types.ServiceConfig) bool {
Expand All @@ -1412,13 +1422,54 @@ func (s *composeService) removeDivergedNetwork(ctx context.Context, project *typ
Project: project,
})
if err != nil {
return err
return nil, err
}

containers, err := s.getContainers(ctx, project.Name, oneOffExclude, true, services...)
if err != nil {
return nil, err
}

err = s.disconnectNetwork(ctx, n.Name, containers)
if err != nil {
return nil, err
}

err = s.apiClient().NetworkRemove(ctx, n.Name)
eventName := fmt.Sprintf("Network %s", n.Name)
progress.ContextWriter(ctx).Event(progress.RemovedEvent(eventName))
return err
return containers, err
}

func (s *composeService) disconnectNetwork(
ctx context.Context,
network string,
containers Containers,
) error {
for _, c := range containers {
err := s.apiClient().NetworkDisconnect(ctx, network, c.ID, true)
if err != nil {
return err
}
}

return nil
}

func (s *composeService) connectNetwork(
ctx context.Context,
network string,
containers Containers,
config *network.EndpointSettings,
) error {
for _, c := range containers {
err := s.apiClient().NetworkConnect(ctx, network, c.ID, config)
if err != nil {
return err
}
}

return nil
}

func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.NetworkConfig) (string, error) {
Expand Down
10 changes: 10 additions & 0 deletions pkg/e2e/fixtures/network-recreate/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
services:
web:
image: nginx
networks:
- test

networks:
test:
labels:
- foo=${FOO:-foo}
21 changes: 21 additions & 0 deletions pkg/e2e/networks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,24 @@ func TestInterfaceName(t *testing.T) {
})
res.Assert(t, icmd.Expected{Out: "foobar@"})
}

func TestNetworkRecreate(t *testing.T) {
c := NewCLI(t)
const projectName = "network_recreate"
t.Cleanup(func() {
c.cleanupWithDown(t, projectName)
})
c.RunDockerComposeCmd(t, "-f", "./fixtures/network-recreate/compose.yaml", "--project-name", projectName, "up", "-d")

c = NewCLI(t, WithEnv("FOO=bar"))
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/network-recreate/compose.yaml", "--project-name", projectName, "--progress=plain", "up", "-d")
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`})
}