Skip to content

Commit 33951a4

Browse files
committed
project.Services is a map
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent d04699b commit 33951a4

25 files changed

+120
-124
lines changed

cmd/compose/build.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"strings"
2424

2525
"github.com/compose-spec/compose-go/v2/cli"
26-
"github.com/compose-spec/compose-go/v2/loader"
2726
"github.com/compose-spec/compose-go/v2/types"
2827
"github.com/docker/cli/cli/command"
2928
cliopts "github.com/docker/cli/opts"

cmd/compose/compose_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,20 @@ import (
2626
func TestFilterServices(t *testing.T) {
2727
p := &types.Project{
2828
Services: types.Services{
29-
{
29+
"foo": {
3030
Name: "foo",
3131
Links: []string{"bar"},
3232
},
33-
{
33+
"bar": {
3434
Name: "bar",
3535
DependsOn: map[string]types.ServiceDependency{
3636
"zot": {},
3737
},
3838
},
39-
{
39+
"zot": {
4040
Name: "zot",
4141
},
42-
{
42+
"qix": {
4343
Name: "qix",
4444
},
4545
},

cmd/compose/create_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func sampleProject() *types.Project {
8686
return &types.Project{
8787
Name: "test",
8888
Services: types.Services{
89-
{
89+
"svc": {
9090
Name: "svc",
9191
Build: &types.BuildConfig{
9292
Context: ".",

cmd/compose/options.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ import (
2525

2626
func applyPlatforms(project *types.Project, buildForSinglePlatform bool) error {
2727
defaultPlatform := project.Environment["DOCKER_DEFAULT_PLATFORM"]
28-
for i := range project.Services {
29-
// mutable reference so platform fields can be updated
30-
service := &project.Services[i]
31-
28+
for _, service := range project.Services {
3229
if service.Build == nil {
3330
continue
3431
}

cmd/compose/options_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func TestApplyPlatforms_InferFromRuntime(t *testing.T) {
2727
makeProject := func() *types.Project {
2828
return &types.Project{
2929
Services: types.Services{
30-
{
30+
"test": {
3131
Name: "test",
3232
Image: "foo",
3333
Build: &types.BuildConfig{
@@ -47,14 +47,14 @@ func TestApplyPlatforms_InferFromRuntime(t *testing.T) {
4747
t.Run("SinglePlatform", func(t *testing.T) {
4848
project := makeProject()
4949
require.NoError(t, applyPlatforms(project, true))
50-
require.EqualValues(t, []string{"alice/32"}, project.Services[0].Build.Platforms)
50+
require.EqualValues(t, []string{"alice/32"}, project.Services["test"].Build.Platforms)
5151
})
5252

5353
t.Run("MultiPlatform", func(t *testing.T) {
5454
project := makeProject()
5555
require.NoError(t, applyPlatforms(project, false))
5656
require.EqualValues(t, []string{"linux/amd64", "linux/arm64", "alice/32"},
57-
project.Services[0].Build.Platforms)
57+
project.Services["test"].Build.Platforms)
5858
})
5959
}
6060

@@ -65,7 +65,7 @@ func TestApplyPlatforms_DockerDefaultPlatform(t *testing.T) {
6565
"DOCKER_DEFAULT_PLATFORM": "linux/amd64",
6666
},
6767
Services: types.Services{
68-
{
68+
"test": {
6969
Name: "test",
7070
Image: "foo",
7171
Build: &types.BuildConfig{
@@ -83,14 +83,14 @@ func TestApplyPlatforms_DockerDefaultPlatform(t *testing.T) {
8383
t.Run("SinglePlatform", func(t *testing.T) {
8484
project := makeProject()
8585
require.NoError(t, applyPlatforms(project, true))
86-
require.EqualValues(t, []string{"linux/amd64"}, project.Services[0].Build.Platforms)
86+
require.EqualValues(t, []string{"linux/amd64"}, project.Services["test"].Build.Platforms)
8787
})
8888

8989
t.Run("MultiPlatform", func(t *testing.T) {
9090
project := makeProject()
9191
require.NoError(t, applyPlatforms(project, false))
9292
require.EqualValues(t, []string{"linux/amd64", "linux/arm64"},
93-
project.Services[0].Build.Platforms)
93+
project.Services["test"].Build.Platforms)
9494
})
9595
}
9696

@@ -101,7 +101,7 @@ func TestApplyPlatforms_UnsupportedPlatform(t *testing.T) {
101101
"DOCKER_DEFAULT_PLATFORM": "commodore/64",
102102
},
103103
Services: types.Services{
104-
{
104+
"foo": {
105105
Name: "test",
106106
Image: "foo",
107107
Build: &types.BuildConfig{

cmd/compose/pullOptions_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,21 @@ import (
2626
func TestApplyPullOptions(t *testing.T) {
2727
project := &types.Project{
2828
Services: types.Services{
29-
{
29+
"must-build": {
3030
Name: "must-build",
3131
// No image, local build only
3232
Build: &types.BuildConfig{
3333
Context: ".",
3434
},
3535
},
36-
{
36+
"has-build": {
3737
Name: "has-build",
3838
Image: "registry.example.com/myservice",
3939
Build: &types.BuildConfig{
4040
Context: ".",
4141
},
4242
},
43-
{
43+
"must-pull": {
4444
Name: "must-pull",
4545
Image: "registry.example.com/another-service",
4646
},
@@ -51,7 +51,7 @@ func TestApplyPullOptions(t *testing.T) {
5151
}.apply(project, nil)
5252
assert.NilError(t, err)
5353

54-
assert.Equal(t, project.Services[0].PullPolicy, "") // still default
55-
assert.Equal(t, project.Services[1].PullPolicy, types.PullPolicyMissing)
56-
assert.Equal(t, project.Services[2].PullPolicy, types.PullPolicyMissing)
54+
assert.Equal(t, project.Services["must-build"].PullPolicy, "") // still default
55+
assert.Equal(t, project.Services["has-build"].PullPolicy, types.PullPolicyMissing)
56+
assert.Equal(t, project.Services["must-pull"].PullPolicy, types.PullPolicyMissing)
5757
}

cmd/compose/run.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,16 +300,16 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
300300
func startDependencies(ctx context.Context, backend api.Service, project types.Project, buildOpts *api.BuildOptions, requestedServiceName string, ignoreOrphans bool) error {
301301
dependencies := types.Services{}
302302
var requestedService types.ServiceConfig
303-
for _, service := range project.Services {
303+
for name, service := range project.Services {
304304
if service.Name != requestedServiceName {
305-
dependencies = append(dependencies, service)
305+
dependencies[name] = service
306306
} else {
307307
requestedService = service
308308
}
309309
}
310310

311311
project.Services = dependencies
312-
project.DisabledServices = append(project.DisabledServices, requestedService)
312+
project.DisabledServices[requestedServiceName] = requestedService
313313
err := backend.Create(ctx, &project, api.CreateOptions{
314314
Build: buildOpts,
315315
IgnoreOrphans: ignoreOrphans,

cmd/compose/up_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ import (
2626
func TestApplyScaleOpt(t *testing.T) {
2727
p := types.Project{
2828
Services: types.Services{
29-
{
29+
"foo": {
3030
Name: "foo",
3131
},
32-
{
32+
"bar": {
3333
Name: "bar",
3434
Deploy: &types.DeployConfig{
3535
Mode: "test",

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/AlecAivazis/survey/v2 v2.3.7
77
github.com/Microsoft/go-winio v0.6.1
88
github.com/buger/goterm v1.0.4
9-
github.com/compose-spec/compose-go/v2 v2.0.0-20231121074112-593b77722992
9+
github.com/compose-spec/compose-go/v2 v2.0.0-20231123162526-11ef9572f1a4
1010
github.com/containerd/console v1.0.3
1111
github.com/containerd/containerd v1.7.7
1212
github.com/davecgh/go-spew v1.1.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g
130130
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
131131
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
132132
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
133-
github.com/compose-spec/compose-go/v2 v2.0.0-20231121074112-593b77722992 h1:0BM7GPtSRK7djjvG3h67aJYH8eRikBgxkrEG7wNtgaU=
134-
github.com/compose-spec/compose-go/v2 v2.0.0-20231121074112-593b77722992/go.mod h1:uAthZuC/GWStR8mxGMRaQyaOeSqA4V+MZIiAIfuBoIU=
133+
github.com/compose-spec/compose-go/v2 v2.0.0-20231123162526-11ef9572f1a4 h1:Lr78By808iuG+2gTyxIDslRpKQCk/lcRqElKsrhzp+U=
134+
github.com/compose-spec/compose-go/v2 v2.0.0-20231123162526-11ef9572f1a4/go.mod h1:PWCgeD8cxiI/DmdpBM407CuLDrZ2W4xuS6/Z9jAi0YQ=
135135
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
136136
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
137137
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=

internal/tracing/attributes.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,12 @@ func ProjectOptions(proj *types.Project) SpanOptions {
5858
return nil
5959
}
6060

61-
disabledServiceNames := make([]string, len(proj.DisabledServices))
62-
for i := range proj.DisabledServices {
63-
disabledServiceNames[i] = proj.DisabledServices[i].Name
64-
}
65-
6661
attrs := []attribute.KeyValue{
6762
attribute.String("project.name", proj.Name),
6863
attribute.String("project.dir", proj.WorkingDir),
6964
attribute.StringSlice("project.compose_files", proj.ComposeFiles),
7065
attribute.StringSlice("project.services.active", proj.ServiceNames()),
71-
attribute.StringSlice("project.services.disabled", disabledServiceNames),
66+
attribute.StringSlice("project.services.disabled", proj.DisabledServiceNames()),
7267
attribute.StringSlice("project.profiles", proj.Profiles),
7368
attribute.StringSlice("project.volumes", proj.VolumeNames()),
7469
attribute.StringSlice("project.networks", proj.NetworkNames()),

pkg/compose/build.go

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti
6767
}
6868

6969
type serviceToBuild struct {
70-
idx int
70+
name string
7171
service types.ServiceConfig
7272
}
7373

@@ -85,7 +85,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
8585
if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
8686
return nil
8787
}
88-
service, idx := getServiceIndex(project, name)
88+
service := project.Services[name]
8989

9090
if service.Build == nil {
9191
return nil
@@ -97,7 +97,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
9797
return nil
9898
}
9999
mapServiceMutx.Lock()
100-
serviceToBeBuild[name] = serviceToBuild{idx: idx, service: service}
100+
serviceToBeBuild[name] = serviceToBuild{name: name, service: service}
101101
mapServiceMutx.Unlock()
102102
return nil
103103
}, func(traversal *graphTraversal) {
@@ -146,7 +146,17 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
146146
}
147147
}
148148

149+
// we use a pre-allocated []string to collect build digest by service index while running concurrent goroutines
149150
builtDigests := make([]string, len(project.Services))
151+
names := project.ServiceNames()
152+
getServiceIndex := func(name string) int {
153+
for idx, n := range names {
154+
if n == name {
155+
return idx
156+
}
157+
}
158+
return -1
159+
}
150160
err = InDependencyOrder(ctx, project, func(ctx context.Context, name string) error {
151161
if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
152162
return nil
@@ -156,14 +166,13 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
156166
return nil
157167
}
158168
service := serviceToBuild.service
159-
idx := serviceToBuild.idx
160169

161170
if !buildkitEnabled {
162171
id, err := s.doBuildClassic(ctx, project, service, options)
163172
if err != nil {
164173
return err
165174
}
166-
builtDigests[idx] = id
175+
builtDigests[getServiceIndex(name)] = id
167176

168177
if options.Push {
169178
return s.push(ctx, project, api.PushOptions{})
@@ -184,7 +193,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
184193
if err != nil {
185194
return err
186195
}
187-
builtDigests[idx] = digest
196+
builtDigests[getServiceIndex(name)] = digest
188197

189198
return nil
190199
}, func(traversal *graphTraversal) {
@@ -204,25 +213,13 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
204213

205214
for i, imageDigest := range builtDigests {
206215
if imageDigest != "" {
207-
imageRef := api.GetImageNameOrDefault(project.Services[i], project.Name)
216+
imageRef := api.GetImageNameOrDefault(project.Services[names[i]], project.Name)
208217
imageIDs[imageRef] = imageDigest
209218
}
210219
}
211220
return imageIDs, err
212221
}
213222

214-
func getServiceIndex(project *types.Project, name string) (types.ServiceConfig, int) {
215-
var service types.ServiceConfig
216-
var idx int
217-
for i, s := range project.Services {
218-
if s.Name == name {
219-
idx, service = i, s
220-
break
221-
}
222-
}
223-
return service, idx
224-
}
225-
226223
func (s *composeService) ensureImagesExists(ctx context.Context, project *types.Project, buildOpts *api.BuildOptions, quietPull bool) error {
227224
for _, service := range project.Services {
228225
if service.Image == "" && service.Build == nil {
@@ -264,14 +261,14 @@ func (s *composeService) ensureImagesExists(ctx context.Context, project *types.
264261
}
265262

266263
// set digest as com.docker.compose.image label so we can detect outdated containers
267-
for i, service := range project.Services {
264+
for _, service := range project.Services {
268265
image := api.GetImageNameOrDefault(service, project.Name)
269266
digest, ok := images[image]
270267
if ok {
271-
if project.Services[i].Labels == nil {
272-
project.Services[i].Labels = types.Labels{}
268+
if service.Labels == nil {
269+
service.Labels = types.Labels{}
273270
}
274-
project.Services[i].CustomLabels.Add(api.ImageDigestLabel, digest)
271+
service.CustomLabels.Add(api.ImageDigestLabel, digest)
275272
}
276273
}
277274
return nil
@@ -440,7 +437,7 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
440437
Platforms: plats,
441438
Labels: imageLabels,
442439
NetworkMode: service.Build.Network,
443-
ExtraHosts: service.Build.ExtraHosts.AsList(),
440+
ExtraHosts: service.Build.ExtraHosts.AsList(":"),
444441
Ulimits: toUlimitOpt(service.Build.Ulimits),
445442
Session: sessionConfig,
446443
Allow: allow,

pkg/compose/build_classic.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ func imageBuildOptions(dockerCli command.Cli, project *types.Project, service ty
229229
BuildArgs: resolveAndMergeBuildArgs(dockerCli, project, service, options),
230230
Labels: config.Labels,
231231
NetworkMode: config.Network,
232-
ExtraHosts: config.ExtraHosts.AsList(),
232+
ExtraHosts: config.ExtraHosts.AsList(":"),
233233
Target: config.Target,
234234
Isolation: container.Isolation(config.Isolation),
235235
}

pkg/compose/compose.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
183183
if len(containers) == 0 {
184184
return project, fmt.Errorf("no container found for project %q: %w", projectName, api.ErrNotFound)
185185
}
186-
set := map[string]types.ServiceConfig{}
186+
set := types.Services{}
187187
for _, c := range containers {
188188
serviceLabel := c.Labels[api.ServiceLabel]
189189
service, ok := set[serviceLabel]
@@ -197,7 +197,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
197197
}
198198
service.Scale = increment(service.Scale)
199199
}
200-
for _, service := range set {
200+
for name, service := range set {
201201
dependencies := service.Labels[api.DependenciesLabel]
202202
if len(dependencies) > 0 {
203203
service.DependsOn = types.DependsOnConfig{}
@@ -218,9 +218,11 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
218218
}
219219
service.DependsOn[dependency] = types.ServiceDependency{Condition: condition, Restart: restart, Required: required}
220220
}
221+
set[name] = service
221222
}
222-
project.Services = append(project.Services, service)
223223
}
224+
project.Services = set
225+
224226
SERVICES:
225227
for _, qs := range services {
226228
for _, es := range project.Services {

0 commit comments

Comments
 (0)