From 978f0fa5c7a5acf8f9bfcedbf716198e9c4211fc Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 4 Sep 2023 14:43:58 +0200 Subject: [PATCH] vendor: github.com/compose-spec/compose-go v1.18.3 - Parse service device count to int if possible - introduce ResourceResolver to accept remote resources - use include.env_file to resolve variables in included compose.yaml file - remove potential dependencies to disabled services in ForServices - ability to convert a mapping (back) to KEY=VALUE strings - load: include details about included files on Project - include disabled services - local environment to override included .env - load: move env var profile detection to option - add support for multi-document yaml full diff: https://github.com/compose-spec/compose-go/compare/v1.17.0...v1.18.3 Signed-off-by: Sebastiaan van Stijn --- go.mod | 2 +- go.sum | 4 +- .../compose-spec/compose-go/cli/options.go | 52 ++++- .../compose-spec/compose-go/loader/include.go | 50 +++-- .../compose-spec/compose-go/loader/loader.go | 185 ++++++++++++------ .../compose-spec/compose-go/loader/paths.go | 30 +++ .../compose-spec/compose-go/types/config.go | 2 +- .../compose-spec/compose-go/types/project.go | 39 ++-- .../compose-spec/compose-go/types/types.go | 28 +++ vendor/modules.txt | 2 +- 10 files changed, 297 insertions(+), 97 deletions(-) diff --git a/go.mod b/go.mod index 967aa16f..320ad44b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/aws/aws-sdk-go-v2/config v1.18.16 - github.com/compose-spec/compose-go v1.17.0 + github.com/compose-spec/compose-go v1.18.3 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.7.2 github.com/containerd/continuity v0.4.1 diff --git a/go.sum b/go.sum index 731ddc76..d5af5e5c 100644 --- a/go.sum +++ b/go.sum @@ -126,8 +126,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= -github.com/compose-spec/compose-go v1.17.0 h1:cvje90CU94dQyTnJoHJYjx9yE4Iggse1XmGcO3Qi5ts= -github.com/compose-spec/compose-go v1.17.0/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= +github.com/compose-spec/compose-go v1.18.3 h1:hiwTZ8ED1l+CB2G2G4LFv/bIaoUfG2ZBalz4S7MOy5w= +github.com/compose-spec/compose-go v1.18.3/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= diff --git a/vendor/github.com/compose-spec/compose-go/cli/options.go b/vendor/github.com/compose-spec/compose-go/cli/options.go index e6d49cdf..332ea3b5 100644 --- a/vendor/github.com/compose-spec/compose-go/cli/options.go +++ b/vendor/github.com/compose-spec/compose-go/cli/options.go @@ -17,6 +17,7 @@ package cli import ( + "context" "io" "os" "path/filepath" @@ -35,6 +36,8 @@ import ( // ProjectOptions provides common configuration for loading a project. type ProjectOptions struct { + ctx context.Context + // Name is a valid Compose project name to be used or empty. // // If empty, the project loader will automatically infer a reasonable @@ -63,7 +66,7 @@ type ProjectOptions struct { // NOTE: For security, the loader does not automatically expose any // process environment variables. For convenience, WithOsEnv can be // used if appropriate. - Environment map[string]string + Environment types.Mapping // EnvFiles are file paths to ".env" files with additional environment // variable data. @@ -191,7 +194,7 @@ func WithEnv(env []string) ProjectOptionsFn { } } -// WithDiscardEnvFiles sets discards the `env_file` section after resolving to +// WithDiscardEnvFile sets discards the `env_file` section after resolving to // the `environment` section func WithDiscardEnvFile(o *ProjectOptions) error { o.loadOptions = append(o.loadOptions, loader.WithDiscardEnvFiles) @@ -206,6 +209,15 @@ func WithLoadOptions(loadOptions ...func(*loader.Options)) ProjectOptionsFn { } } +// WithDefaultProfiles uses the provided profiles (if any), and falls back to +// profiles specified via the COMPOSE_PROFILES environment variable otherwise. +func WithDefaultProfiles(profile ...string) ProjectOptionsFn { + if len(profile) == 0 { + profile = strings.Split(os.Getenv(consts.ComposeProfiles), ",") + } + return WithProfiles(profile) +} + // WithProfiles sets profiles to be activated func WithProfiles(profiles []string) ProjectOptionsFn { return func(o *ProjectOptions) error { @@ -225,8 +237,9 @@ func WithOsEnv(o *ProjectOptions) error { return nil } -// WithEnvFile set an alternate env file -// deprecated - use WithEnvFiles +// WithEnvFile sets an alternate env file. +// +// Deprecated: use WithEnvFiles instead. func WithEnvFile(file string) ProjectOptionsFn { var files []string if file != "" { @@ -253,11 +266,7 @@ func WithDotEnv(o *ProjectOptions) error { if err != nil { return err } - for k, v := range envMap { - if _, set := o.Environment[k]; !set { - o.Environment[k] = v - } - } + o.Environment.Merge(envMap) return nil } @@ -301,6 +310,24 @@ func WithResolvedPaths(resolve bool) ProjectOptionsFn { } } +// WithContext sets the context used to load model and resources +func WithContext(ctx context.Context) ProjectOptionsFn { + return func(o *ProjectOptions) error { + o.ctx = ctx + return nil + } +} + +// WithResourceLoader register support for ResourceLoader to manage remote resources +func WithResourceLoader(r loader.ResourceLoader) ProjectOptionsFn { + return func(o *ProjectOptions) error { + o.loadOptions = append(o.loadOptions, func(options *loader.Options) { + options.ResourceLoaders = append(options.ResourceLoaders, r) + }) + 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"} @@ -367,7 +394,12 @@ func ProjectFromOptions(options *ProjectOptions) (*types.Project, error) { withNamePrecedenceLoad(absWorkingDir, options), withConvertWindowsPaths(options)) - project, err := loader.Load(types.ConfigDetails{ + ctx := options.ctx + if ctx == nil { + ctx = context.Background() + } + + project, err := loader.LoadWithContext(ctx, types.ConfigDetails{ ConfigFiles: configs, WorkingDir: workingDir, Environment: options.Environment, diff --git a/vendor/github.com/compose-spec/compose-go/loader/include.go b/vendor/github.com/compose-spec/compose-go/loader/include.go index eeddf8b1..ea784144 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/include.go +++ b/vendor/github.com/compose-spec/compose-go/loader/include.go @@ -17,10 +17,12 @@ package loader import ( + "context" "fmt" "path/filepath" "github.com/compose-spec/compose-go/dotenv" + interp "github.com/compose-spec/compose-go/interpolation" "github.com/compose-spec/compose-go/types" "github.com/pkg/errors" ) @@ -43,12 +45,23 @@ var transformIncludeConfig TransformerFunc = func(data interface{}) (interface{} } } -func loadInclude(configDetails types.ConfigDetails, model *types.Config, options *Options, loaded []string) (*types.Config, error) { +func loadInclude(ctx context.Context, filename string, configDetails types.ConfigDetails, model *types.Config, options *Options, loaded []string) (*types.Config, map[string][]types.IncludeConfig, error) { + included := make(map[string][]types.IncludeConfig) for _, r := range model.Include { + included[filename] = append(included[filename], r) + for i, p := range r.Path { - if !filepath.IsAbs(p) { - r.Path[i] = filepath.Join(configDetails.WorkingDir, p) + for _, loader := range options.ResourceLoaders { + if loader.Accept(p) { + path, err := loader.Load(ctx, p) + if err != nil { + return nil, nil, err + } + p = path + break + } } + r.Path[i] = absPath(configDetails.WorkingDir, p) } if r.ProjectDirectory == "" { r.ProjectDirectory = filepath.Dir(r.Path[0]) @@ -60,27 +73,36 @@ func loadInclude(configDetails types.ConfigDetails, model *types.Config, options loadOptions.SkipNormalization = true loadOptions.SkipConsistencyCheck = true - env, err := dotenv.GetEnvFromFile(configDetails.Environment, r.ProjectDirectory, r.EnvFile) + envFromFile, err := dotenv.GetEnvFromFile(configDetails.Environment, r.ProjectDirectory, r.EnvFile) if err != nil { - return nil, err + return nil, nil, err } - imported, err := load(types.ConfigDetails{ + config := types.ConfigDetails{ WorkingDir: r.ProjectDirectory, ConfigFiles: types.ToConfigFiles(r.Path), - Environment: env, - }, loadOptions, loaded) + Environment: configDetails.Environment.Clone().Merge(envFromFile), + } + loadOptions.Interpolate = &interp.Options{ + Substitute: options.Interpolate.Substitute, + LookupValue: config.LookupEnv, + TypeCastMapping: options.Interpolate.TypeCastMapping, + } + imported, err := load(ctx, config, loadOptions, loaded) if err != nil { - return nil, err + return nil, nil, err + } + for k, v := range imported.IncludeReferences { + included[k] = append(included[k], v...) } err = importResources(model, imported, r.Path) if err != nil { - return nil, err + return nil, nil, err } } model.Include = nil - return model, nil + return model, included, nil } // importResources import into model all resources defined by imported, and report error on conflict @@ -92,6 +114,12 @@ func importResources(model *types.Config, imported *types.Project, path []string } model.Services = append(model.Services, service) } + for _, service := range imported.DisabledServices { + if _, ok := services[service.Name]; ok { + return fmt.Errorf("imported compose file %s defines conflicting service %s", path, service.Name) + } + model.Services = append(model.Services, service) + } for n, network := range imported.Networks { if _, ok := model.Networks[n]; ok { return fmt.Errorf("imported compose file %s defines conflicting network %s", path, n) diff --git a/vendor/github.com/compose-spec/compose-go/loader/loader.go b/vendor/github.com/compose-spec/compose-go/loader/loader.go index 76dbe2ff..205dcd67 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/loader.go +++ b/vendor/github.com/compose-spec/compose-go/loader/loader.go @@ -17,7 +17,10 @@ package loader import ( + "bytes" + "context" "fmt" + "io" "os" paths "path" "path/filepath" @@ -68,6 +71,16 @@ type Options struct { projectNameImperativelySet bool // Profiles set profiles to enable Profiles []string + // ResourceLoaders manages support for remote resources + ResourceLoaders []ResourceLoader +} + +// ResourceLoader is a plugable remote resource resolver +type ResourceLoader interface { + // Accept returns `true` is the resource reference matches ResourceLoader supported protocol(s) + Accept(path string) bool + // Load returns the path to a local copy of remote resource identified by `path`. + Load(ctx context.Context, path string) (string, error) } func (o *Options) clone() *Options { @@ -85,6 +98,7 @@ func (o *Options) clone() *Options { projectName: o.projectName, projectNameImperativelySet: o.projectNameImperativelySet, Profiles: o.Profiles, + ResourceLoaders: o.ResourceLoaders, } } @@ -154,7 +168,9 @@ func WithProfiles(profiles []string) func(*Options) { // ParseYAML reads the bytes from a file, parses the bytes into a mapping // structure, and returns it. func ParseYAML(source []byte) (map[string]interface{}, error) { - m, _, err := parseYAML(source) + r := bytes.NewReader(source) + decoder := yaml.NewDecoder(r) + m, _, err := parseYAML(decoder) return m, err } @@ -167,11 +183,11 @@ type PostProcessor interface { Apply(config *types.Config) error } -func parseYAML(source []byte) (map[string]interface{}, PostProcessor, error) { +func parseYAML(decoder *yaml.Decoder) (map[string]interface{}, PostProcessor, error) { var cfg interface{} processor := ResetProcessor{target: &cfg} - if err := yaml.Unmarshal(source, &processor); err != nil { + if err := decoder.Decode(&processor); err != nil { return nil, nil, err } stringMap, ok := cfg.(map[string]interface{}) @@ -193,8 +209,14 @@ func parseYAML(source []byte) (map[string]interface{}, PostProcessor, error) { return converted.(map[string]interface{}), &processor, nil } -// Load reads a ConfigDetails and returns a fully loaded configuration +// Load reads a ConfigDetails and returns a fully loaded configuration. +// Deprecated: use LoadWithContext. func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.Project, error) { + return LoadWithContext(context.Background(), configDetails, options...) +} + +// LoadWithContext reads a ConfigDetails and returns a fully loaded configuration +func LoadWithContext(ctx context.Context, configDetails types.ConfigDetails, options ...func(*Options)) (*types.Project, error) { if len(configDetails.ConfigFiles) < 1 { return nil, errors.Errorf("No files specified") } @@ -217,10 +239,10 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types. return nil, err } opts.projectName = projectName - return load(configDetails, opts, nil) + return load(ctx, configDetails, opts, nil) } -func load(configDetails types.ConfigDetails, opts *Options, loaded []string) (*types.Project, error) { +func load(ctx context.Context, configDetails types.ConfigDetails, opts *Options, loaded []string) (*types.Project, error) { var model *types.Config mainFile := configDetails.ConfigFiles[0].Filename @@ -232,63 +254,87 @@ func load(configDetails types.ConfigDetails, opts *Options, loaded []string) (*t } loaded = append(loaded, mainFile) - for i, file := range configDetails.ConfigFiles { + includeRefs := make(map[string][]types.IncludeConfig) + first := true + for _, file := range configDetails.ConfigFiles { var postProcessor PostProcessor configDict := file.Config - if configDict == nil { - if len(file.Content) == 0 { - content, err := os.ReadFile(file.Filename) - if err != nil { - return nil, err + + processYaml := func() error { + if !opts.SkipValidation { + if err := schema.Validate(configDict); err != nil { + return fmt.Errorf("validating %s: %w", file.Filename, err) } - file.Content = content } - dict, p, err := parseConfig(file.Content, opts) + + configDict = groupXFieldsIntoExtensions(configDict) + + cfg, err := loadSections(ctx, file.Filename, configDict, configDetails, opts) if err != nil { - return nil, fmt.Errorf("parsing %s: %w", file.Filename, err) + return err } - configDict = dict - file.Config = dict - configDetails.ConfigFiles[i] = file - postProcessor = p - } - if !opts.SkipValidation { - if err := schema.Validate(configDict); err != nil { - return nil, fmt.Errorf("validating %s: %w", file.Filename, err) + if !opts.SkipInclude { + var included map[string][]types.IncludeConfig + cfg, included, err = loadInclude(ctx, file.Filename, configDetails, cfg, opts, loaded) + if err != nil { + return err + } + for k, v := range included { + includeRefs[k] = append(includeRefs[k], v...) + } } - } - - configDict = groupXFieldsIntoExtensions(configDict) - - cfg, err := loadSections(file.Filename, configDict, configDetails, opts) - if err != nil { - return nil, err - } - if !opts.SkipInclude { - cfg, err = loadInclude(configDetails, cfg, opts, loaded) + if first { + first = false + model = cfg + return nil + } + merged, err := merge([]*types.Config{model, cfg}) if err != nil { - return nil, err + return err } + if postProcessor != nil { + err = postProcessor.Apply(merged) + if err != nil { + return err + } + } + model = merged + return nil } - if i == 0 { - model = cfg - continue - } + if configDict == nil { + if len(file.Content) == 0 { + content, err := os.ReadFile(file.Filename) + if err != nil { + return nil, err + } + file.Content = content + } - merged, err := merge([]*types.Config{model, cfg}) - if err != nil { - return nil, err - } - if postProcessor != nil { - err = postProcessor.Apply(merged) - if err != nil { + r := bytes.NewReader(file.Content) + decoder := yaml.NewDecoder(r) + for { + dict, p, err := parseConfig(decoder, opts) + if err != nil { + if err != io.EOF { + return nil, fmt.Errorf("parsing %s: %w", file.Filename, err) + } + break + } + configDict = dict + postProcessor = p + + if err := processYaml(); err != nil { + return nil, err + } + } + } else { + if err := processYaml(); err != nil { return nil, err } } - model = merged } project := &types.Project{ @@ -303,6 +349,10 @@ func load(configDetails types.ConfigDetails, opts *Options, loaded []string) (*t Extensions: model.Extensions, } + if len(includeRefs) != 0 { + project.IncludeReferences = includeRefs + } + if !opts.SkipNormalization { err := Normalize(project) if err != nil { @@ -333,9 +383,6 @@ func load(configDetails types.ConfigDetails, opts *Options, loaded []string) (*t } } - if profiles, ok := project.Environment[consts.ComposeProfiles]; ok && len(opts.Profiles) == 0 { - opts.Profiles = strings.Split(profiles, ",") - } project.ApplyProfiles(opts.Profiles) err := project.ResolveServicesEnvironment(opts.discardEnvFiles) @@ -422,8 +469,8 @@ func NormalizeProjectName(s string) string { return strings.TrimLeft(s, "_-") } -func parseConfig(b []byte, opts *Options) (map[string]interface{}, PostProcessor, error) { - yml, postProcessor, err := parseYAML(b) +func parseConfig(decoder *yaml.Decoder, opts *Options) (map[string]interface{}, PostProcessor, error) { + yml, postProcessor, err := parseYAML(decoder) if err != nil { return nil, nil, err } @@ -453,7 +500,7 @@ func groupXFieldsIntoExtensions(dict map[string]interface{}) map[string]interfac return dict } -func loadSections(filename string, config map[string]interface{}, configDetails types.ConfigDetails, opts *Options) (*types.Config, error) { +func loadSections(ctx context.Context, filename string, config map[string]interface{}, configDetails types.ConfigDetails, opts *Options) (*types.Config, error) { var err error cfg := types.Config{ Filename: filename, @@ -466,7 +513,7 @@ func loadSections(filename string, config map[string]interface{}, configDetails } } cfg.Name = name - cfg.Services, err = LoadServices(filename, getSection(config, "services"), configDetails.WorkingDir, configDetails.LookupEnv, opts) + cfg.Services, err = LoadServices(ctx, filename, getSection(config, "services"), configDetails.WorkingDir, configDetails.LookupEnv, opts) if err != nil { return nil, err } @@ -659,7 +706,7 @@ func formatInvalidKeyError(keyPrefix string, key interface{}) error { // LoadServices produces a ServiceConfig map from a compose file Dict // the servicesDict is not validated if directly used. Use Load() to enable validation -func LoadServices(filename string, servicesDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, opts *Options) ([]types.ServiceConfig, error) { +func LoadServices(ctx context.Context, filename string, servicesDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, opts *Options) ([]types.ServiceConfig, error) { var services []types.ServiceConfig x, ok := servicesDict[extensions] @@ -672,7 +719,7 @@ func LoadServices(filename string, servicesDict map[string]interface{}, workingD } for name := range servicesDict { - serviceConfig, err := loadServiceWithExtends(filename, name, servicesDict, workingDir, lookupEnv, opts, &cycleTracker{}) + serviceConfig, err := loadServiceWithExtends(ctx, filename, name, servicesDict, workingDir, lookupEnv, opts, &cycleTracker{}) if err != nil { return nil, err } @@ -683,7 +730,7 @@ func LoadServices(filename string, servicesDict map[string]interface{}, workingD return services, nil } -func loadServiceWithExtends(filename, name string, servicesDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, opts *Options, ct *cycleTracker) (*types.ServiceConfig, error) { +func loadServiceWithExtends(ctx context.Context, filename, name string, servicesDict map[string]interface{}, workingDir string, lookupEnv template.Mapping, opts *Options, ct *cycleTracker) (*types.ServiceConfig, error) { if err := ct.Add(filename, name); err != nil { return nil, err } @@ -707,11 +754,21 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter var baseService *types.ServiceConfig file := serviceConfig.Extends.File if file == "" { - baseService, err = loadServiceWithExtends(filename, baseServiceName, servicesDict, workingDir, lookupEnv, opts, ct) + baseService, err = loadServiceWithExtends(ctx, filename, baseServiceName, servicesDict, workingDir, lookupEnv, opts, ct) if err != nil { return nil, err } } else { + for _, loader := range opts.ResourceLoaders { + if loader.Accept(file) { + path, err := loader.Load(ctx, file) + if err != nil { + return nil, err + } + file = path + break + } + } // Resolve the path to the imported file, and load it. baseFilePath := absPath(workingDir, file) @@ -720,13 +777,16 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter return nil, err } - baseFile, _, err := parseConfig(b, opts) + r := bytes.NewReader(b) + decoder := yaml.NewDecoder(r) + + baseFile, _, err := parseConfig(decoder, opts) if err != nil { return nil, err } baseFileServices := getSection(baseFile, "services") - baseService, err = loadServiceWithExtends(baseFilePath, baseServiceName, baseFileServices, filepath.Dir(baseFilePath), lookupEnv, opts, ct) + baseService, err = loadServiceWithExtends(ctx, baseFilePath, baseServiceName, baseFileServices, filepath.Dir(baseFilePath), lookupEnv, opts, ct) if err != nil { return nil, err } @@ -1038,7 +1098,12 @@ var transformServiceDeviceRequest TransformerFunc = func(data interface{}) (inte value["count"] = -1 return value, nil } - return data, errors.Errorf("invalid string value for 'count' (the only value allowed is 'all')") + i, err := strconv.ParseInt(val, 10, 64) + if err == nil { + value["count"] = i + return value, nil + } + return data, errors.Errorf("invalid string value for 'count' (the only value allowed is 'all' or a number)") default: return data, errors.Errorf("invalid type %T for device count", val) } diff --git a/vendor/github.com/compose-spec/compose-go/loader/paths.go b/vendor/github.com/compose-spec/compose-go/loader/paths.go index 45bbc545..61e79f01 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/paths.go +++ b/vendor/github.com/compose-spec/compose-go/loader/paths.go @@ -64,6 +64,25 @@ func ResolveRelativePaths(project *types.Project) error { project.Volumes[name] = config } } + + // don't coerce a nil map to an empty map + if project.IncludeReferences != nil { + absIncludes := make(map[string][]types.IncludeConfig, len(project.IncludeReferences)) + for filename, config := range project.IncludeReferences { + filename = absPath(project.WorkingDir, filename) + absConfigs := make([]types.IncludeConfig, len(config)) + for i, c := range config { + absConfigs[i] = types.IncludeConfig{ + Path: resolvePaths(project.WorkingDir, c.Path), + ProjectDirectory: absPath(project.WorkingDir, c.ProjectDirectory), + EnvFile: resolvePaths(project.WorkingDir, c.EnvFile), + } + } + absIncludes[filename] = absConfigs + } + project.IncludeReferences = absIncludes + } + return nil } @@ -133,3 +152,14 @@ func isRemoteContext(maybeURL string) bool { } return false } + +func resolvePaths(basePath string, in types.StringList) types.StringList { + if in == nil { + return nil + } + ret := make(types.StringList, len(in)) + for i := range in { + ret[i] = absPath(basePath, in[i]) + } + return ret +} diff --git a/vendor/github.com/compose-spec/compose-go/types/config.go b/vendor/github.com/compose-spec/compose-go/types/config.go index 517e6122..25e6f82e 100644 --- a/vendor/github.com/compose-spec/compose-go/types/config.go +++ b/vendor/github.com/compose-spec/compose-go/types/config.go @@ -34,7 +34,7 @@ type ConfigDetails struct { Version string WorkingDir string ConfigFiles []ConfigFile - Environment map[string]string + Environment Mapping } // LookupEnv provides a lookup function for environment variables diff --git a/vendor/github.com/compose-spec/compose-go/types/project.go b/vendor/github.com/compose-spec/compose-go/types/project.go index 42c24714..2a82ccfb 100644 --- a/vendor/github.com/compose-spec/compose-go/types/project.go +++ b/vendor/github.com/compose-spec/compose-go/types/project.go @@ -36,16 +36,22 @@ import ( // Project is the result of loading a set of compose files type Project struct { - Name string `yaml:"name,omitempty" json:"name,omitempty"` - WorkingDir string `yaml:"-" json:"-"` - Services Services `yaml:"services" json:"services"` - Networks Networks `yaml:"networks,omitempty" json:"networks,omitempty"` - Volumes Volumes `yaml:"volumes,omitempty" json:"volumes,omitempty"` - Secrets Secrets `yaml:"secrets,omitempty" json:"secrets,omitempty"` - Configs Configs `yaml:"configs,omitempty" json:"configs,omitempty"` - Extensions Extensions `yaml:"#extensions,inline" json:"-"` // https://github.com/golang/go/issues/6213 - ComposeFiles []string `yaml:"-" json:"-"` - Environment Mapping `yaml:"-" json:"-"` + Name string `yaml:"name,omitempty" json:"name,omitempty"` + WorkingDir string `yaml:"-" json:"-"` + Services Services `yaml:"services" json:"services"` + Networks Networks `yaml:"networks,omitempty" json:"networks,omitempty"` + Volumes Volumes `yaml:"volumes,omitempty" json:"volumes,omitempty"` + Secrets Secrets `yaml:"secrets,omitempty" json:"secrets,omitempty"` + Configs Configs `yaml:"configs,omitempty" json:"configs,omitempty"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` // https://github.com/golang/go/issues/6213 + + // IncludeReferences is keyed by Compose YAML filename and contains config for + // other Compose YAML files it directly triggered a load of via `include`. + // + // Note: this is + IncludeReferences map[string][]IncludeConfig `yaml:"-" json:"-"` + ComposeFiles []string `yaml:"-" json:"-"` + Environment Mapping `yaml:"-" json:"-"` // DisabledServices track services which have been disable as profile is not active DisabledServices Services `yaml:"-" json:"-"` @@ -423,13 +429,24 @@ func (p *Project) ForServices(names []string, options ...DependencyOption) error } enabled = append(enabled, s) } else { - p.DisabledServices = append(p.DisabledServices, s) + p.DisableService(s) } } p.Services = enabled return nil } +func (p *Project) DisableService(service ServiceConfig) { + // We should remove all dependencies which reference the disabled service + for i, s := range p.Services { + if _, ok := s.DependsOn[service.Name]; ok { + delete(s.DependsOn, service.Name) + p.Services[i] = s + } + } + p.DisabledServices = append(p.DisabledServices, service) +} + // ResolveImages updates services images to include digest computed by a resolver function func (p *Project) ResolveImages(resolver func(named reference.Named) (godigest.Digest, error)) error { eg := errgroup.Group{} diff --git a/vendor/github.com/compose-spec/compose-go/types/types.go b/vendor/github.com/compose-spec/compose-go/types/types.go index a9a515f0..5864dc00 100644 --- a/vendor/github.com/compose-spec/compose-go/types/types.go +++ b/vendor/github.com/compose-spec/compose-go/types/types.go @@ -491,6 +491,16 @@ func NewMapping(values []string) Mapping { return mapping } +// convert values into a set of KEY=VALUE strings +func (m Mapping) Values() []string { + values := make([]string, 0, len(m)) + for k, v := range m { + values = append(values, fmt.Sprintf("%s=%s", k, v)) + } + sort.Strings(values) + return values +} + // ToMappingWithEquals converts Mapping into a MappingWithEquals with pointer references func (m Mapping) ToMappingWithEquals() MappingWithEquals { mapping := MappingWithEquals{} @@ -506,6 +516,24 @@ func (m Mapping) Resolve(s string) (string, bool) { return v, ok } +func (m Mapping) Clone() Mapping { + clone := Mapping{} + for k, v := range m { + clone[k] = v + } + return clone +} + +// Merge adds all values from second mapping which are not already defined +func (m Mapping) Merge(o Mapping) Mapping { + for k, v := range o { + if _, set := m[k]; !set { + m[k] = v + } + } + return m +} + // Labels is a mapping type for labels type Labels map[string]string diff --git a/vendor/modules.txt b/vendor/modules.txt index 56941420..43a8b8be 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -119,7 +119,7 @@ github.com/cenkalti/backoff/v4 # github.com/cespare/xxhash/v2 v2.2.0 ## explicit; go 1.11 github.com/cespare/xxhash/v2 -# github.com/compose-spec/compose-go v1.17.0 +# github.com/compose-spec/compose-go v1.18.3 ## explicit; go 1.19 github.com/compose-spec/compose-go/cli github.com/compose-spec/compose-go/consts