mirror of https://github.com/docker/compose.git
project.Services is a map
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
cda04f288e
commit
138facea62
|
@ -23,7 +23,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/v2/cli"
|
||||
"github.com/compose-spec/compose-go/v2/loader"
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
"github.com/docker/cli/cli/command"
|
||||
cliopts "github.com/docker/cli/opts"
|
||||
|
|
|
@ -26,20 +26,20 @@ import (
|
|||
func TestFilterServices(t *testing.T) {
|
||||
p := &types.Project{
|
||||
Services: types.Services{
|
||||
{
|
||||
"foo": {
|
||||
Name: "foo",
|
||||
Links: []string{"bar"},
|
||||
},
|
||||
{
|
||||
"bar": {
|
||||
Name: "bar",
|
||||
DependsOn: map[string]types.ServiceDependency{
|
||||
"zot": {},
|
||||
},
|
||||
},
|
||||
{
|
||||
"zot": {
|
||||
Name: "zot",
|
||||
},
|
||||
{
|
||||
"qix": {
|
||||
Name: "qix",
|
||||
},
|
||||
},
|
||||
|
|
|
@ -86,7 +86,7 @@ func sampleProject() *types.Project {
|
|||
return &types.Project{
|
||||
Name: "test",
|
||||
Services: types.Services{
|
||||
{
|
||||
"svc": {
|
||||
Name: "svc",
|
||||
Build: &types.BuildConfig{
|
||||
Context: ".",
|
||||
|
|
|
@ -25,10 +25,7 @@ import (
|
|||
|
||||
func applyPlatforms(project *types.Project, buildForSinglePlatform bool) error {
|
||||
defaultPlatform := project.Environment["DOCKER_DEFAULT_PLATFORM"]
|
||||
for i := range project.Services {
|
||||
// mutable reference so platform fields can be updated
|
||||
service := &project.Services[i]
|
||||
|
||||
for _, service := range project.Services {
|
||||
if service.Build == nil {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ func TestApplyPlatforms_InferFromRuntime(t *testing.T) {
|
|||
makeProject := func() *types.Project {
|
||||
return &types.Project{
|
||||
Services: types.Services{
|
||||
{
|
||||
"test": {
|
||||
Name: "test",
|
||||
Image: "foo",
|
||||
Build: &types.BuildConfig{
|
||||
|
@ -47,14 +47,14 @@ func TestApplyPlatforms_InferFromRuntime(t *testing.T) {
|
|||
t.Run("SinglePlatform", func(t *testing.T) {
|
||||
project := makeProject()
|
||||
require.NoError(t, applyPlatforms(project, true))
|
||||
require.EqualValues(t, []string{"alice/32"}, project.Services[0].Build.Platforms)
|
||||
require.EqualValues(t, []string{"alice/32"}, project.Services["test"].Build.Platforms)
|
||||
})
|
||||
|
||||
t.Run("MultiPlatform", func(t *testing.T) {
|
||||
project := makeProject()
|
||||
require.NoError(t, applyPlatforms(project, false))
|
||||
require.EqualValues(t, []string{"linux/amd64", "linux/arm64", "alice/32"},
|
||||
project.Services[0].Build.Platforms)
|
||||
project.Services["test"].Build.Platforms)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ func TestApplyPlatforms_DockerDefaultPlatform(t *testing.T) {
|
|||
"DOCKER_DEFAULT_PLATFORM": "linux/amd64",
|
||||
},
|
||||
Services: types.Services{
|
||||
{
|
||||
"test": {
|
||||
Name: "test",
|
||||
Image: "foo",
|
||||
Build: &types.BuildConfig{
|
||||
|
@ -83,14 +83,14 @@ func TestApplyPlatforms_DockerDefaultPlatform(t *testing.T) {
|
|||
t.Run("SinglePlatform", func(t *testing.T) {
|
||||
project := makeProject()
|
||||
require.NoError(t, applyPlatforms(project, true))
|
||||
require.EqualValues(t, []string{"linux/amd64"}, project.Services[0].Build.Platforms)
|
||||
require.EqualValues(t, []string{"linux/amd64"}, project.Services["test"].Build.Platforms)
|
||||
})
|
||||
|
||||
t.Run("MultiPlatform", func(t *testing.T) {
|
||||
project := makeProject()
|
||||
require.NoError(t, applyPlatforms(project, false))
|
||||
require.EqualValues(t, []string{"linux/amd64", "linux/arm64"},
|
||||
project.Services[0].Build.Platforms)
|
||||
project.Services["test"].Build.Platforms)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ func TestApplyPlatforms_UnsupportedPlatform(t *testing.T) {
|
|||
"DOCKER_DEFAULT_PLATFORM": "commodore/64",
|
||||
},
|
||||
Services: types.Services{
|
||||
{
|
||||
"foo": {
|
||||
Name: "test",
|
||||
Image: "foo",
|
||||
Build: &types.BuildConfig{
|
||||
|
|
|
@ -26,21 +26,21 @@ import (
|
|||
func TestApplyPullOptions(t *testing.T) {
|
||||
project := &types.Project{
|
||||
Services: types.Services{
|
||||
{
|
||||
"must-build": {
|
||||
Name: "must-build",
|
||||
// No image, local build only
|
||||
Build: &types.BuildConfig{
|
||||
Context: ".",
|
||||
},
|
||||
},
|
||||
{
|
||||
"has-build": {
|
||||
Name: "has-build",
|
||||
Image: "registry.example.com/myservice",
|
||||
Build: &types.BuildConfig{
|
||||
Context: ".",
|
||||
},
|
||||
},
|
||||
{
|
||||
"must-pull": {
|
||||
Name: "must-pull",
|
||||
Image: "registry.example.com/another-service",
|
||||
},
|
||||
|
@ -51,7 +51,7 @@ func TestApplyPullOptions(t *testing.T) {
|
|||
}.apply(project, nil)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Equal(t, project.Services[0].PullPolicy, "") // still default
|
||||
assert.Equal(t, project.Services[1].PullPolicy, types.PullPolicyMissing)
|
||||
assert.Equal(t, project.Services[2].PullPolicy, types.PullPolicyMissing)
|
||||
assert.Equal(t, project.Services["must-build"].PullPolicy, "") // still default
|
||||
assert.Equal(t, project.Services["has-build"].PullPolicy, types.PullPolicyMissing)
|
||||
assert.Equal(t, project.Services["must-pull"].PullPolicy, types.PullPolicyMissing)
|
||||
}
|
||||
|
|
|
@ -300,16 +300,16 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
|
|||
func startDependencies(ctx context.Context, backend api.Service, project types.Project, buildOpts *api.BuildOptions, requestedServiceName string, ignoreOrphans bool) error {
|
||||
dependencies := types.Services{}
|
||||
var requestedService types.ServiceConfig
|
||||
for _, service := range project.Services {
|
||||
for name, service := range project.Services {
|
||||
if service.Name != requestedServiceName {
|
||||
dependencies = append(dependencies, service)
|
||||
dependencies[name] = service
|
||||
} else {
|
||||
requestedService = service
|
||||
}
|
||||
}
|
||||
|
||||
project.Services = dependencies
|
||||
project.DisabledServices = append(project.DisabledServices, requestedService)
|
||||
project.DisabledServices[requestedServiceName] = requestedService
|
||||
err := backend.Create(ctx, &project, api.CreateOptions{
|
||||
Build: buildOpts,
|
||||
IgnoreOrphans: ignoreOrphans,
|
||||
|
|
|
@ -26,10 +26,10 @@ import (
|
|||
func TestApplyScaleOpt(t *testing.T) {
|
||||
p := types.Project{
|
||||
Services: types.Services{
|
||||
{
|
||||
"foo": {
|
||||
Name: "foo",
|
||||
},
|
||||
{
|
||||
"bar": {
|
||||
Name: "bar",
|
||||
Deploy: &types.DeployConfig{
|
||||
Mode: "test",
|
||||
|
|
2
go.mod
2
go.mod
|
@ -6,7 +6,7 @@ require (
|
|||
github.com/AlecAivazis/survey/v2 v2.3.7
|
||||
github.com/Microsoft/go-winio v0.6.1
|
||||
github.com/buger/goterm v1.0.4
|
||||
github.com/compose-spec/compose-go/v2 v2.0.0-20231121074112-593b77722992
|
||||
github.com/compose-spec/compose-go/v2 v2.0.0-20231123162526-11ef9572f1a4
|
||||
github.com/containerd/console v1.0.3
|
||||
github.com/containerd/containerd v1.7.7
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
|
|
4
go.sum
4
go.sum
|
@ -132,8 +132,8 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g
|
|||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
|
||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
|
||||
github.com/compose-spec/compose-go/v2 v2.0.0-20231121074112-593b77722992 h1:0BM7GPtSRK7djjvG3h67aJYH8eRikBgxkrEG7wNtgaU=
|
||||
github.com/compose-spec/compose-go/v2 v2.0.0-20231121074112-593b77722992/go.mod h1:uAthZuC/GWStR8mxGMRaQyaOeSqA4V+MZIiAIfuBoIU=
|
||||
github.com/compose-spec/compose-go/v2 v2.0.0-20231123162526-11ef9572f1a4 h1:Lr78By808iuG+2gTyxIDslRpKQCk/lcRqElKsrhzp+U=
|
||||
github.com/compose-spec/compose-go/v2 v2.0.0-20231123162526-11ef9572f1a4/go.mod h1:PWCgeD8cxiI/DmdpBM407CuLDrZ2W4xuS6/Z9jAi0YQ=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
|
|
|
@ -58,17 +58,12 @@ func ProjectOptions(proj *types.Project) SpanOptions {
|
|||
return nil
|
||||
}
|
||||
|
||||
disabledServiceNames := make([]string, len(proj.DisabledServices))
|
||||
for i := range proj.DisabledServices {
|
||||
disabledServiceNames[i] = proj.DisabledServices[i].Name
|
||||
}
|
||||
|
||||
attrs := []attribute.KeyValue{
|
||||
attribute.String("project.name", proj.Name),
|
||||
attribute.String("project.dir", proj.WorkingDir),
|
||||
attribute.StringSlice("project.compose_files", proj.ComposeFiles),
|
||||
attribute.StringSlice("project.services.active", proj.ServiceNames()),
|
||||
attribute.StringSlice("project.services.disabled", disabledServiceNames),
|
||||
attribute.StringSlice("project.services.disabled", proj.DisabledServiceNames()),
|
||||
attribute.StringSlice("project.profiles", proj.Profiles),
|
||||
attribute.StringSlice("project.volumes", proj.VolumeNames()),
|
||||
attribute.StringSlice("project.networks", proj.NetworkNames()),
|
||||
|
|
|
@ -67,7 +67,7 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti
|
|||
}
|
||||
|
||||
type serviceToBuild struct {
|
||||
idx int
|
||||
name string
|
||||
service types.ServiceConfig
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|||
if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
|
||||
return nil
|
||||
}
|
||||
service, idx := getServiceIndex(project, name)
|
||||
service := project.Services[name]
|
||||
|
||||
if service.Build == nil {
|
||||
return nil
|
||||
|
@ -97,7 +97,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|||
return nil
|
||||
}
|
||||
mapServiceMutx.Lock()
|
||||
serviceToBeBuild[name] = serviceToBuild{idx: idx, service: service}
|
||||
serviceToBeBuild[name] = serviceToBuild{name: name, service: service}
|
||||
mapServiceMutx.Unlock()
|
||||
return nil
|
||||
}, func(traversal *graphTraversal) {
|
||||
|
@ -146,7 +146,17 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|||
}
|
||||
}
|
||||
|
||||
// we use a pre-allocated []string to collect build digest by service index while running concurrent goroutines
|
||||
builtDigests := make([]string, len(project.Services))
|
||||
names := project.ServiceNames()
|
||||
getServiceIndex := func(name string) int {
|
||||
for idx, n := range names {
|
||||
if n == name {
|
||||
return idx
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
err = InDependencyOrder(ctx, project, func(ctx context.Context, name string) error {
|
||||
if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
|
||||
return nil
|
||||
|
@ -156,14 +166,13 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|||
return nil
|
||||
}
|
||||
service := serviceToBuild.service
|
||||
idx := serviceToBuild.idx
|
||||
|
||||
if !buildkitEnabled {
|
||||
id, err := s.doBuildClassic(ctx, project, service, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
builtDigests[idx] = id
|
||||
builtDigests[getServiceIndex(name)] = id
|
||||
|
||||
if options.Push {
|
||||
return s.push(ctx, project, api.PushOptions{})
|
||||
|
@ -184,7 +193,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
builtDigests[idx] = digest
|
||||
builtDigests[getServiceIndex(name)] = digest
|
||||
|
||||
return nil
|
||||
}, func(traversal *graphTraversal) {
|
||||
|
@ -204,25 +213,13 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|||
|
||||
for i, imageDigest := range builtDigests {
|
||||
if imageDigest != "" {
|
||||
imageRef := api.GetImageNameOrDefault(project.Services[i], project.Name)
|
||||
imageRef := api.GetImageNameOrDefault(project.Services[names[i]], project.Name)
|
||||
imageIDs[imageRef] = imageDigest
|
||||
}
|
||||
}
|
||||
return imageIDs, err
|
||||
}
|
||||
|
||||
func getServiceIndex(project *types.Project, name string) (types.ServiceConfig, int) {
|
||||
var service types.ServiceConfig
|
||||
var idx int
|
||||
for i, s := range project.Services {
|
||||
if s.Name == name {
|
||||
idx, service = i, s
|
||||
break
|
||||
}
|
||||
}
|
||||
return service, idx
|
||||
}
|
||||
|
||||
func (s *composeService) ensureImagesExists(ctx context.Context, project *types.Project, buildOpts *api.BuildOptions, quietPull bool) error {
|
||||
for _, service := range project.Services {
|
||||
if service.Image == "" && service.Build == nil {
|
||||
|
@ -264,14 +261,14 @@ func (s *composeService) ensureImagesExists(ctx context.Context, project *types.
|
|||
}
|
||||
|
||||
// set digest as com.docker.compose.image label so we can detect outdated containers
|
||||
for i, service := range project.Services {
|
||||
for _, service := range project.Services {
|
||||
image := api.GetImageNameOrDefault(service, project.Name)
|
||||
digest, ok := images[image]
|
||||
if ok {
|
||||
if project.Services[i].Labels == nil {
|
||||
project.Services[i].Labels = types.Labels{}
|
||||
if service.Labels == nil {
|
||||
service.Labels = types.Labels{}
|
||||
}
|
||||
project.Services[i].CustomLabels.Add(api.ImageDigestLabel, digest)
|
||||
service.CustomLabels.Add(api.ImageDigestLabel, digest)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -440,7 +437,7 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
|
|||
Platforms: plats,
|
||||
Labels: imageLabels,
|
||||
NetworkMode: service.Build.Network,
|
||||
ExtraHosts: service.Build.ExtraHosts.AsList(),
|
||||
ExtraHosts: service.Build.ExtraHosts.AsList(":"),
|
||||
Ulimits: toUlimitOpt(service.Build.Ulimits),
|
||||
Session: sessionConfig,
|
||||
Allow: allow,
|
||||
|
|
|
@ -229,7 +229,7 @@ func imageBuildOptions(dockerCli command.Cli, project *types.Project, service ty
|
|||
BuildArgs: resolveAndMergeBuildArgs(dockerCli, project, service, options),
|
||||
Labels: config.Labels,
|
||||
NetworkMode: config.Network,
|
||||
ExtraHosts: config.ExtraHosts.AsList(),
|
||||
ExtraHosts: config.ExtraHosts.AsList(":"),
|
||||
Target: config.Target,
|
||||
Isolation: container.Isolation(config.Isolation),
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
|
|||
if len(containers) == 0 {
|
||||
return project, fmt.Errorf("no container found for project %q: %w", projectName, api.ErrNotFound)
|
||||
}
|
||||
set := map[string]types.ServiceConfig{}
|
||||
set := types.Services{}
|
||||
for _, c := range containers {
|
||||
serviceLabel := c.Labels[api.ServiceLabel]
|
||||
service, ok := set[serviceLabel]
|
||||
|
@ -197,7 +197,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
|
|||
}
|
||||
service.Scale = increment(service.Scale)
|
||||
}
|
||||
for _, service := range set {
|
||||
for name, service := range set {
|
||||
dependencies := service.Labels[api.DependenciesLabel]
|
||||
if len(dependencies) > 0 {
|
||||
service.DependsOn = types.DependsOnConfig{}
|
||||
|
@ -218,9 +218,11 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
|
|||
}
|
||||
service.DependsOn[dependency] = types.ServiceDependency{Condition: condition, Restart: restart, Required: required}
|
||||
}
|
||||
set[name] = service
|
||||
}
|
||||
project.Services = append(project.Services, service)
|
||||
}
|
||||
project.Services = set
|
||||
|
||||
SERVICES:
|
||||
for _, qs := range services {
|
||||
for _, es := range project.Services {
|
||||
|
|
|
@ -227,7 +227,10 @@ func TestWaitDependencies(t *testing.T) {
|
|||
t.Run("should skip dependencies with scale 0", func(t *testing.T) {
|
||||
dbService := types.ServiceConfig{Name: "db", Scale: intPtr(0)}
|
||||
redisService := types.ServiceConfig{Name: "redis", Scale: intPtr(0)}
|
||||
project := types.Project{Name: strings.ToLower(testProject), Services: types.Services{dbService, redisService}}
|
||||
project := types.Project{Name: strings.ToLower(testProject), Services: types.Services{
|
||||
"db": dbService,
|
||||
"redis": redisService,
|
||||
}}
|
||||
dependencies := types.DependsOnConfig{
|
||||
"db": {Condition: ServiceConditionRunningOrHealthy},
|
||||
"redis": {Condition: ServiceConditionRunningOrHealthy},
|
||||
|
@ -237,7 +240,10 @@ func TestWaitDependencies(t *testing.T) {
|
|||
t.Run("should skip dependencies with condition service_started", func(t *testing.T) {
|
||||
dbService := types.ServiceConfig{Name: "db", Scale: intPtr(1)}
|
||||
redisService := types.ServiceConfig{Name: "redis", Scale: intPtr(1)}
|
||||
project := types.Project{Name: strings.ToLower(testProject), Services: types.Services{dbService, redisService}}
|
||||
project := types.Project{Name: strings.ToLower(testProject), Services: types.Services{
|
||||
"db": dbService,
|
||||
"redis": redisService,
|
||||
}}
|
||||
dependencies := types.DependsOnConfig{
|
||||
"db": {Condition: types.ServiceConditionStarted, Required: true},
|
||||
"redis": {Condition: types.ServiceConditionStarted, Required: true},
|
||||
|
|
|
@ -94,11 +94,7 @@ func (s *composeService) create(ctx context.Context, project *types.Project, opt
|
|||
return err
|
||||
}
|
||||
|
||||
allServices := project.AllServices()
|
||||
allServiceNames := []string{}
|
||||
for _, service := range allServices {
|
||||
allServiceNames = append(allServiceNames, service.Name)
|
||||
}
|
||||
allServiceNames := append(project.ServiceNames(), project.DisabledServiceNames()...)
|
||||
orphans := observedState.filter(isNotService(allServiceNames...))
|
||||
if len(orphans) > 0 && !options.IgnoreOrphans {
|
||||
if options.RemoveOrphans {
|
||||
|
@ -263,7 +259,7 @@ func (s *composeService) getCreateConfigs(ctx context.Context,
|
|||
DNS: service.DNS,
|
||||
DNSSearch: service.DNSSearch,
|
||||
DNSOptions: service.DNSOpts,
|
||||
ExtraHosts: service.ExtraHosts.AsList(),
|
||||
ExtraHosts: service.ExtraHosts.AsList(":"),
|
||||
SecurityOpt: securityOpts,
|
||||
UsernsMode: container.UsernsMode(service.UserNSMode),
|
||||
UTSMode: container.UTSMode(service.Uts),
|
||||
|
|
|
@ -101,8 +101,8 @@ func TestPrepareNetworkLabels(t *testing.T) {
|
|||
func TestBuildContainerMountOptions(t *testing.T) {
|
||||
project := composetypes.Project{
|
||||
Name: "myProject",
|
||||
Services: []composetypes.ServiceConfig{
|
||||
{
|
||||
Services: composetypes.Services{
|
||||
"myService": {
|
||||
Name: "myService",
|
||||
Volumes: []composetypes.ServiceVolumeConfig{
|
||||
{
|
||||
|
@ -144,7 +144,7 @@ func TestBuildContainerMountOptions(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
mounts, err := buildContainerMountOptions(project, project.Services[0], moby.ImageInspect{}, inherit)
|
||||
mounts, err := buildContainerMountOptions(project, project.Services["myService"], moby.ImageInspect{}, inherit)
|
||||
sort.Slice(mounts, func(i, j int) bool {
|
||||
return mounts[i].Target < mounts[j].Target
|
||||
})
|
||||
|
@ -154,7 +154,7 @@ func TestBuildContainerMountOptions(t *testing.T) {
|
|||
assert.Equal(t, mounts[1].Target, "/var/myvolume2")
|
||||
assert.Equal(t, mounts[2].Target, "\\\\.\\pipe\\docker_engine")
|
||||
|
||||
mounts, err = buildContainerMountOptions(project, project.Services[0], moby.ImageInspect{}, inherit)
|
||||
mounts, err = buildContainerMountOptions(project, project.Services["myService"], moby.ImageInspect{}, inherit)
|
||||
sort.Slice(mounts, func(i, j int) bool {
|
||||
return mounts[i].Target < mounts[j].Target
|
||||
})
|
||||
|
@ -180,8 +180,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
|
|||
}
|
||||
project := composetypes.Project{
|
||||
Name: "myProject",
|
||||
Services: []composetypes.ServiceConfig{
|
||||
service,
|
||||
Services: composetypes.Services{
|
||||
"myService": service,
|
||||
},
|
||||
Networks: composetypes.Networks(map[string]composetypes.NetworkConfig{
|
||||
"myNetwork1": {
|
||||
|
@ -205,8 +205,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
|
|||
}
|
||||
project := composetypes.Project{
|
||||
Name: "myProject",
|
||||
Services: []composetypes.ServiceConfig{
|
||||
service,
|
||||
Services: composetypes.Services{
|
||||
"myService": service,
|
||||
},
|
||||
Networks: composetypes.Networks(map[string]composetypes.NetworkConfig{
|
||||
"myNetwork1": {
|
||||
|
@ -233,8 +233,8 @@ func TestDefaultNetworkSettings(t *testing.T) {
|
|||
}
|
||||
project := composetypes.Project{
|
||||
Name: "myProject",
|
||||
Services: []composetypes.ServiceConfig{
|
||||
service,
|
||||
Services: composetypes.Services{
|
||||
"myService": service,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -250,7 +250,7 @@ func TestDefaultNetworkSettings(t *testing.T) {
|
|||
}
|
||||
project := composetypes.Project{
|
||||
Name: "myProject",
|
||||
Services: []composetypes.ServiceConfig{service},
|
||||
Services: composetypes.Services{"myService": service},
|
||||
Networks: composetypes.Networks(map[string]composetypes.NetworkConfig{
|
||||
"default": {
|
||||
Name: "myProject_default",
|
||||
|
|
|
@ -33,19 +33,19 @@ import (
|
|||
func createTestProject() *types.Project {
|
||||
return &types.Project{
|
||||
Services: types.Services{
|
||||
{
|
||||
"test1": {
|
||||
Name: "test1",
|
||||
DependsOn: map[string]types.ServiceDependency{
|
||||
"test2": {},
|
||||
},
|
||||
},
|
||||
{
|
||||
"test2": {
|
||||
Name: "test2",
|
||||
DependsOn: map[string]types.ServiceDependency{
|
||||
"test3": {},
|
||||
},
|
||||
},
|
||||
{
|
||||
"test3": {
|
||||
Name: "test3",
|
||||
},
|
||||
},
|
||||
|
@ -59,7 +59,7 @@ func TestTraversalWithMultipleParents(t *testing.T) {
|
|||
}
|
||||
|
||||
project := types.Project{
|
||||
Services: types.Services{dependent},
|
||||
Services: types.Services{"dependent": dependent},
|
||||
}
|
||||
|
||||
for i := 1; i <= 100; i++ {
|
||||
|
@ -67,7 +67,7 @@ func TestTraversalWithMultipleParents(t *testing.T) {
|
|||
dependent.DependsOn[name] = types.ServiceDependency{}
|
||||
|
||||
svc := types.ServiceConfig{Name: name}
|
||||
project.Services = append(project.Services, svc)
|
||||
project.Services[name] = svc
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
@ -132,7 +132,7 @@ func TestBuildGraph(t *testing.T) {
|
|||
{
|
||||
desc: "builds graph with single service",
|
||||
services: types.Services{
|
||||
{
|
||||
"test": {
|
||||
Name: "test",
|
||||
DependsOn: types.DependsOnConfig{},
|
||||
},
|
||||
|
@ -150,11 +150,11 @@ func TestBuildGraph(t *testing.T) {
|
|||
{
|
||||
desc: "builds graph with two separate services",
|
||||
services: types.Services{
|
||||
{
|
||||
"test": {
|
||||
Name: "test",
|
||||
DependsOn: types.DependsOnConfig{},
|
||||
},
|
||||
{
|
||||
"another": {
|
||||
Name: "another",
|
||||
DependsOn: types.DependsOnConfig{},
|
||||
},
|
||||
|
@ -179,13 +179,13 @@ func TestBuildGraph(t *testing.T) {
|
|||
{
|
||||
desc: "builds graph with a service and a dependency",
|
||||
services: types.Services{
|
||||
{
|
||||
"test": {
|
||||
Name: "test",
|
||||
DependsOn: types.DependsOnConfig{
|
||||
"another": types.ServiceDependency{},
|
||||
},
|
||||
},
|
||||
{
|
||||
"another": {
|
||||
Name: "another",
|
||||
DependsOn: types.DependsOnConfig{},
|
||||
},
|
||||
|
@ -214,19 +214,19 @@ func TestBuildGraph(t *testing.T) {
|
|||
{
|
||||
desc: "builds graph with multiple dependency levels",
|
||||
services: types.Services{
|
||||
{
|
||||
"test": {
|
||||
Name: "test",
|
||||
DependsOn: types.DependsOnConfig{
|
||||
"another": types.ServiceDependency{},
|
||||
},
|
||||
},
|
||||
{
|
||||
"another": {
|
||||
Name: "another",
|
||||
DependsOn: types.DependsOnConfig{
|
||||
"another_dep": types.ServiceDependency{},
|
||||
},
|
||||
},
|
||||
{
|
||||
"another_dep": {
|
||||
Name: "another_dep",
|
||||
DependsOn: types.DependsOnConfig{},
|
||||
},
|
||||
|
|
|
@ -184,12 +184,12 @@ func TestDownRemoveImages(t *testing.T) {
|
|||
Project: &types.Project{
|
||||
Name: strings.ToLower(testProject),
|
||||
Services: types.Services{
|
||||
{Name: "local-anonymous"},
|
||||
{Name: "local-named", Image: "local-named-image"},
|
||||
{Name: "remote", Image: "remote-image"},
|
||||
{Name: "remote-tagged", Image: "registry.example.com/remote-image-tagged:v1.0"},
|
||||
{Name: "no-images-anonymous"},
|
||||
{Name: "no-images-named", Image: "missing-named-image"},
|
||||
"local-anonymous": {Name: "local-anonymous"},
|
||||
"local-named": {Name: "local-named", Image: "local-named-image"},
|
||||
"remote": {Name: "remote", Image: "remote-image"},
|
||||
"remote-tagged": {Name: "remote-tagged", Image: "registry.example.com/remote-image-tagged:v1.0"},
|
||||
"no-images-anonymous": {Name: "no-images-anonymous"},
|
||||
"no-images-named": {Name: "no-images-named", Image: "missing-named-image"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ func TestComposeService_Logs_Demux(t *testing.T) {
|
|||
opts := compose.LogOptions{
|
||||
Project: &types.Project{
|
||||
Services: types.Services{
|
||||
{Name: "service"},
|
||||
"service": {Name: "service"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -153,8 +153,8 @@ func TestComposeService_Logs_ServiceFiltering(t *testing.T) {
|
|||
// reference `serviceB` even though it has running services for this proj
|
||||
proj := &types.Project{
|
||||
Services: types.Services{
|
||||
{Name: "serviceA"},
|
||||
{Name: "serviceC"},
|
||||
"serviceA": {Name: "serviceA"},
|
||||
"serviceC": {Name: "serviceC"},
|
||||
},
|
||||
}
|
||||
consumer := &testLogConsumer{}
|
||||
|
|
|
@ -63,8 +63,8 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
|||
imagesBeingPulled = map[string]string{}
|
||||
)
|
||||
|
||||
for i, service := range project.Services {
|
||||
i, service := i, service
|
||||
i := 0
|
||||
for _, service := range project.Services {
|
||||
if service.Image == "" {
|
||||
w.Event(progress.Event{
|
||||
ID: service.Name,
|
||||
|
@ -113,10 +113,11 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
|||
|
||||
imagesBeingPulled[service.Image] = service.Name
|
||||
|
||||
idx, service := i, service
|
||||
eg.Go(func() error {
|
||||
_, err := s.pullServiceImage(ctx, service, s.configFile(), w, false, project.Environment["DOCKER_DEFAULT_PLATFORM"])
|
||||
if err != nil {
|
||||
pullErrors[i] = err
|
||||
pullErrors[idx] = err
|
||||
if service.Build != nil {
|
||||
mustBuild = append(mustBuild, service.Name)
|
||||
}
|
||||
|
@ -134,6 +135,7 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
|
|||
}
|
||||
return nil
|
||||
})
|
||||
i++
|
||||
}
|
||||
|
||||
err = eg.Wait()
|
||||
|
@ -260,7 +262,7 @@ func encodedAuth(ref reference.Named, configFile driver.Auth) (string, error) {
|
|||
}
|
||||
|
||||
func (s *composeService) pullRequiredImages(ctx context.Context, project *types.Project, images map[string]string, quietPull bool) error {
|
||||
var needPull types.Services
|
||||
var needPull []types.ServiceConfig
|
||||
for _, service := range project.Services {
|
||||
if service.Image == "" {
|
||||
continue
|
||||
|
|
|
@ -34,7 +34,7 @@ func TestViz(t *testing.T) {
|
|||
Name: "viz-test",
|
||||
WorkingDir: "/home",
|
||||
Services: types.Services{
|
||||
{
|
||||
"service1": {
|
||||
Name: "service1",
|
||||
Image: "image-for-service1",
|
||||
Ports: []types.ServicePortConfig{
|
||||
|
@ -53,12 +53,12 @@ func TestViz(t *testing.T) {
|
|||
"internal": nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
"service2": {
|
||||
Name: "service2",
|
||||
Image: "image-for-service2",
|
||||
Ports: []types.ServicePortConfig{},
|
||||
},
|
||||
{
|
||||
"service3": {
|
||||
Name: "service3",
|
||||
Image: "some-image",
|
||||
DependsOn: map[string]types.ServiceDependency{
|
||||
|
@ -66,7 +66,7 @@ func TestViz(t *testing.T) {
|
|||
"service1": {},
|
||||
},
|
||||
},
|
||||
{
|
||||
"service4": {
|
||||
Name: "service4",
|
||||
Image: "another-image",
|
||||
DependsOn: map[string]types.ServiceDependency{
|
||||
|
@ -82,7 +82,7 @@ func TestViz(t *testing.T) {
|
|||
"external": nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
"With host IP": {
|
||||
Name: "With host IP",
|
||||
Image: "user/image-name",
|
||||
DependsOn: map[string]types.ServiceDependency{
|
||||
|
|
|
@ -106,7 +106,7 @@ func TestWatch_Sync(t *testing.T) {
|
|||
|
||||
proj := types.Project{
|
||||
Services: types.Services{
|
||||
{
|
||||
"test": {
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
|
|
|
@ -79,10 +79,10 @@ func TestRestartWithDependencies(t *testing.T) {
|
|||
c.RunDockerComposeCmd(t, "-f", "./fixtures/restart-test/compose-depends-on.yaml", "up", "-d")
|
||||
|
||||
res := c.RunDockerComposeCmd(t, "restart", baseService)
|
||||
fmt.Println(res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), fmt.Sprintf("Container e2e-restart-deps-%s-1 Started", baseService)), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), fmt.Sprintf("Container e2e-restart-deps-%s-1 Started", depWithRestart)), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), depNoRestart), res.Combined())
|
||||
out := res.Combined()
|
||||
assert.Assert(t, strings.Contains(out, fmt.Sprintf("Container e2e-restart-deps-%s-1 Started", 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)
|
||||
}
|
||||
|
||||
func TestRestartWithProfiles(t *testing.T) {
|
||||
|
|
|
@ -106,12 +106,14 @@ func TestStartStopWithDependencies(t *testing.T) {
|
|||
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")
|
||||
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())
|
||||
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)
|
||||
|
||||
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())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "e2e-start-stop-with-dependencies-foo-1"), res.Combined())
|
||||
out = res.Combined()
|
||||
assert.Assert(t, strings.Contains(out, "e2e-start-stop-with-dependencies-bar-1"), out)
|
||||
assert.Assert(t, strings.Contains(out, "e2e-start-stop-with-dependencies-foo-1"), out)
|
||||
})
|
||||
|
||||
t.Run("Up no-deps links", func(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue