diff --git a/go.mod b/go.mod index a2fb8d3..9999a51 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.26.0 require ( github.com/codeclysm/extract/v4 v4.0.0 - github.com/compose-spec/compose-go/v2 v2.11.0 + github.com/compose-spec/compose-go/v2 v2.12.1 github.com/distribution/reference v0.6.0 github.com/docker/docker v28.5.2+incompatible github.com/docker/go-connections v0.7.0 diff --git a/go.sum b/go.sum index a9acc8c..bd7366f 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1 github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo= github.com/codeclysm/extract/v4 v4.0.0 h1:H87LFsUNaJTu2e/8p/oiuiUsOK/TaPQ5wxsjPnwPEIY= github.com/codeclysm/extract/v4 v4.0.0/go.mod h1:SFju1lj6as7FvUgalpSct7torJE0zttbJUWtryPRG6s= -github.com/compose-spec/compose-go/v2 v2.11.0 h1:xoq/ootgIL6TsHmbJHrkuh7+bzjhPV3NHftHRPPyVXM= -github.com/compose-spec/compose-go/v2 v2.11.0/go.mod h1:ZU6zlcweCZKyiB7BVfCizQT9XmkEIMFE+PRZydVcsZg= +github.com/compose-spec/compose-go/v2 v2.12.1 h1:+xBZNxcgSus4atQJwXPEdhHRgCEyZmj/BuqN5m33Ou0= +github.com/compose-spec/compose-go/v2 v2.12.1/go.mod h1:ZU6zlcweCZKyiB7BVfCizQT9XmkEIMFE+PRZydVcsZg= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= diff --git a/vendor/github.com/compose-spec/compose-go/v2/cli/options.go b/vendor/github.com/compose-spec/compose-go/v2/cli/options.go index 69ea565..884ecfc 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/cli/options.go +++ b/vendor/github.com/compose-spec/compose-go/v2/cli/options.go @@ -383,6 +383,24 @@ func WithoutEnvironmentResolution(o *ProjectOptions) error { return nil } +// WithSelectedServices restricts the loaded project to the given services and their +// dependencies. An empty list means "all services". When set, services not in the +// list are dropped from the project before environment resolution, so their +// `env_file` / `label_file` entries are not loaded from disk. +func WithSelectedServices(services ...string) ProjectOptionsFn { + return func(o *ProjectOptions) error { + o.loadOptions = append(o.loadOptions, loader.WithSelectedServices(services)) + return nil + } +} + +// WithoutUnnecessaryResources drops networks/volumes/secrets/configs/models that +// are not referenced by services remaining after selection. +func WithoutUnnecessaryResources(o *ProjectOptions) error { + o.loadOptions = append(o.loadOptions, loader.WithoutUnnecessaryResources) + return nil +} + // DefaultFileNames defines the Compose file names for auto-discovery (in order of preference) var DefaultFileNames = []string{"compose.yaml", "compose.yml", "docker-compose.yml", "docker-compose.yaml"} diff --git a/vendor/github.com/compose-spec/compose-go/v2/loader/loader.go b/vendor/github.com/compose-spec/compose-go/v2/loader/loader.go index 4f3d59d..24911eb 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/loader/loader.go +++ b/vendor/github.com/compose-spec/compose-go/v2/loader/loader.go @@ -78,6 +78,14 @@ type Options struct { projectNameImperativelySet bool // Profiles set profiles to enable Profiles []string + // SelectedServices restricts the project model to these services (and their dependencies) + // after parsing. An empty slice means "all services". When set, services not in the list + // are dropped from the project before environment resolution, so their env_file / label_file + // entries are not loaded. + SelectedServices []string + // PruneUnnecessaryResources drops networks/volumes/secrets/configs/models that are not + // referenced by active services after service selection. + PruneUnnecessaryResources bool // ResourceLoaders manages support for remote resources ResourceLoaders []ResourceLoader // KnownExtensions manages x-* attribute we know and the corresponding go structs @@ -187,6 +195,8 @@ func (o *Options) clone() *Options { projectName: o.projectName, projectNameImperativelySet: o.projectNameImperativelySet, Profiles: o.Profiles, + SelectedServices: o.SelectedServices, + PruneUnnecessaryResources: o.PruneUnnecessaryResources, ResourceLoaders: o.ResourceLoaders, KnownExtensions: o.KnownExtensions, Listeners: o.Listeners, @@ -260,6 +270,22 @@ func WithProfiles(profiles []string) func(*Options) { } } +// WithSelectedServices restricts the loaded project to the given services and their +// dependencies. An empty slice means "all services". When set, services not in the +// list are dropped from the project before environment resolution: their `env_file` +// and `label_file` entries will not be loaded from disk. +func WithSelectedServices(services []string) func(*Options) { + return func(opts *Options) { + opts.SelectedServices = services + } +} + +// WithoutUnnecessaryResources drops networks/volumes/secrets/configs/models that +// are not referenced by services remaining after selection. +func WithoutUnnecessaryResources(opts *Options) { + opts.PruneUnnecessaryResources = true +} + // PostProcessor is used to tweak compose model based on metadata extracted during yaml Unmarshal phase // that hardly can be implemented using go-yaml and mapstructure type PostProcessor interface { @@ -603,6 +629,24 @@ func ModelToProject(dict map[string]interface{}, opts *Options, configDetails ty } } + if len(opts.SelectedServices) > 0 { + // WithServicesEnabled must precede WithSelectedServices: the latter walks + // only active services, so any selected service currently sitting in + // DisabledServices (e.g. gated by a profile) would otherwise be invisible. + project, err = project.WithServicesEnabled(opts.SelectedServices...) + if err != nil { + return nil, err + } + project, err = project.WithSelectedServices(opts.SelectedServices) + if err != nil { + return nil, err + } + } + + if opts.PruneUnnecessaryResources { + project = project.WithoutUnnecessaryResources() + } + if !opts.SkipResolveEnvironment { project, err = project.WithServicesEnvironmentResolved(opts.discardEnvFiles) if err != nil { diff --git a/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go b/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go index 7a07dfe..cdea920 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go +++ b/vendor/github.com/compose-spec/compose-go/v2/loader/reset.go @@ -190,7 +190,12 @@ func (p *ResetProcessor) resolveContainer(node *yaml.Node, path tree.Path) (*yam if resolved == nil { continue } - if v.Kind == yaml.AliasNode { + // Under the merge key `<<`, the YAML library only accepts an + // AliasNode value when its target is a MappingNode. An alias to a + // SequenceNode (the spec-allowed "sequence of mappings" form via an + // anchor) is rejected. Substitute the resolved target so the YAML + // library sees the underlying node directly for merge keys. + if v.Kind == yaml.AliasNode && key != "<<" { nodes = append(nodes, node.Content[idx-1], v) } else { nodes = append(nodes, node.Content[idx-1], resolved) diff --git a/vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go b/vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go index e284fa9..56b252d 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go +++ b/vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go @@ -2139,6 +2139,12 @@ func deriveDeepCopy_50(dst, src *IPAMConfig) { } deriveDeepCopy_60(dst.Config, src.Config) } + if src.Options != nil { + dst.Options = make(map[string]string, len(src.Options)) + deriveDeepCopy_5(dst.Options, src.Options) + } else { + dst.Options = nil + } if src.Extensions != nil { dst.Extensions = make(map[string]any, len(src.Extensions)) src.Extensions.DeepCopy(dst.Extensions) diff --git a/vendor/github.com/compose-spec/compose-go/v2/types/types.go b/vendor/github.com/compose-spec/compose-go/v2/types/types.go index fd4f351..eeb6ba1 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/types/types.go +++ b/vendor/github.com/compose-spec/compose-go/v2/types/types.go @@ -753,6 +753,7 @@ type NetworkConfig struct { type IPAMConfig struct { Driver string `yaml:"driver,omitempty" json:"driver,omitempty"` Config []*IPAMPool `yaml:"config,omitempty" json:"config,omitempty"` + Options Options `yaml:"options,omitempty" json:"options,omitempty"` Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"` } diff --git a/vendor/modules.txt b/vendor/modules.txt index 52e9566..5f1d26f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -15,7 +15,7 @@ github.com/cihub/seelog/archive/zip # github.com/codeclysm/extract/v4 v4.0.0 ## explicit; go 1.22 github.com/codeclysm/extract/v4 -# github.com/compose-spec/compose-go/v2 v2.11.0 +# github.com/compose-spec/compose-go/v2 v2.12.1 ## explicit; go 1.24 github.com/compose-spec/compose-go/v2/cli github.com/compose-spec/compose-go/v2/consts