From 9a125afba0e3985707718d72ac371fe4939817c5 Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Tue, 6 Jun 2023 17:34:34 +0200 Subject: [PATCH] vendor: github.com/compose-spec/compose-go v1.14.0 https: //github.com/compose-spec/compose-go/compare/v1.13.4...v1.14.0 Signed-off-by: CrazyMax --- go.mod | 4 +- go.sum | 8 +- .../compose-spec/compose-go/cli/options.go | 19 +- .../compose-go/dotenv/godotenv.go | 7 +- .../compose-go/interpolation/interpolation.go | 63 +-- .../compose-go/loader/full-example.yml | 2 + .../compose-go/loader/interpolate.go | 107 ++-- .../compose-spec/compose-go/loader/loader.go | 74 ++- .../compose-go/loader/normalize.go | 57 ++ .../compose-spec/compose-go/loader/null.go | 159 ++++++ .../compose-spec/compose-go/loader/volume.go | 3 + .../compose-go/schema/compose-spec.json | 1 + .../compose-go/template/template.go | 2 +- .../compose-spec/compose-go/tree/path.go | 67 +++ .../compose-spec/compose-go/types/project.go | 17 +- .../compose-spec/compose-go/types/types.go | 517 +++++++++--------- vendor/modules.txt | 5 +- 17 files changed, 704 insertions(+), 408 deletions(-) create mode 100644 vendor/github.com/compose-spec/compose-go/loader/null.go create mode 100644 vendor/github.com/compose-spec/compose-go/tree/path.go diff --git a/go.mod b/go.mod index 9b1e5355..31067630 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/Masterminds/semver/v3 v3.2.0 github.com/aws/aws-sdk-go-v2/config v1.18.16 - github.com/compose-spec/compose-go v1.13.4 + github.com/compose-spec/compose-go v1.14.0 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.7.1 github.com/containerd/continuity v0.4.1 @@ -38,7 +38,7 @@ require ( github.com/zclconf/go-cty v1.10.0 go.opentelemetry.io/otel v1.14.0 go.opentelemetry.io/otel/trace v1.14.0 - golang.org/x/sync v0.1.0 + golang.org/x/sync v0.2.0 golang.org/x/term v0.6.0 google.golang.org/grpc v1.53.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 29b7daf0..79d22fdf 100644 --- a/go.sum +++ b/go.sum @@ -122,8 +122,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.13.4 h1:O6xAsPqaY1s9KXteiO7wRCDTJLahv1XP/z/eUO9EfbI= -github.com/compose-spec/compose-go v1.13.4/go.mod h1:rsiZ8uaOHJYJemDBzTe9UBpaq5ZFVEOO4TxM2G3SJxk= +github.com/compose-spec/compose-go v1.14.0 h1:/+tQxBEPIrfsi87Qh7/VjMzcJN3BRNER/RO71ku+u6E= +github.com/compose-spec/compose-go v1.14.0/go.mod h1:m0o4G6MQDHjjz9rY7No9FpnNi+9sKic262rzrwuCqic= 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= @@ -641,8 +641,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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 c1d54ee6..0815dcc0 100644 --- a/vendor/github.com/compose-spec/compose-go/cli/options.go +++ b/vendor/github.com/compose-spec/compose-go/cli/options.go @@ -255,9 +255,8 @@ func WithDotEnv(o *ProjectOptions) error { return err } for k, v := range envMap { - o.Environment[k] = v - if osVal, ok := os.LookupEnv(k); ok { - o.Environment[k] = osVal + if _, set := o.Environment[k]; !set { + o.Environment[k] = v } } return nil @@ -304,15 +303,12 @@ func GetEnvFromFile(currentEnv map[string]string, workingDir string, filenames [ } env, err := dotenv.ParseWithLookup(bytes.NewReader(b), func(k string) (string, bool) { - v, ok := envMap[k] + v, ok := currentEnv[k] if ok { return v, true } - v, ok = currentEnv[k] - if !ok { - return "", false - } - return v, true + v, ok = envMap[k] + return v, ok }) if err != nil { return envMap, errors.Wrapf(err, "failed to read %s", dotEnvFile) @@ -461,8 +457,9 @@ func withNamePrecedenceLoad(absWorkingDir string, options *ProjectOptions) func( func withConvertWindowsPaths(options *ProjectOptions) func(*loader.Options) { return func(o *loader.Options) { - o.ConvertWindowsPaths = utils.StringToBool(options.Environment["COMPOSE_CONVERT_WINDOWS_PATHS"]) - o.ResolvePaths = true + if o.ResolvePaths { + o.ConvertWindowsPaths = utils.StringToBool(options.Environment["COMPOSE_CONVERT_WINDOWS_PATHS"]) + } } } diff --git a/vendor/github.com/compose-spec/compose-go/dotenv/godotenv.go b/vendor/github.com/compose-spec/compose-go/dotenv/godotenv.go index cd19cb40..9b95c990 100644 --- a/vendor/github.com/compose-spec/compose-go/dotenv/godotenv.go +++ b/vendor/github.com/compose-spec/compose-go/dotenv/godotenv.go @@ -162,10 +162,11 @@ func readFile(filename string, lookupFn LookupFn) (map[string]string, error) { func expandVariables(value string, envMap map[string]string, lookupFn LookupFn) (string, error) { retVal, err := template.Substitute(value, func(k string) (string, bool) { - if v, ok := envMap[k]; ok { - return v, ok + if v, ok := lookupFn(k); ok { + return v, true } - return lookupFn(k) + v, ok := envMap[k] + return v, ok }) if err != nil { return value, err diff --git a/vendor/github.com/compose-spec/compose-go/interpolation/interpolation.go b/vendor/github.com/compose-spec/compose-go/interpolation/interpolation.go index f77c19c2..30573083 100644 --- a/vendor/github.com/compose-spec/compose-go/interpolation/interpolation.go +++ b/vendor/github.com/compose-spec/compose-go/interpolation/interpolation.go @@ -18,9 +18,9 @@ package interpolation import ( "os" - "strings" "github.com/compose-spec/compose-go/template" + "github.com/compose-spec/compose-go/tree" "github.com/pkg/errors" ) @@ -29,7 +29,7 @@ type Options struct { // LookupValue from a key LookupValue LookupValue // TypeCastMapping maps key paths to functions to cast to a type - TypeCastMapping map[Path]Cast + TypeCastMapping map[tree.Path]Cast // Substitution function to use Substitute func(string, template.Mapping) (string, error) } @@ -49,7 +49,7 @@ func Interpolate(config map[string]interface{}, opts Options) (map[string]interf opts.LookupValue = os.LookupEnv } if opts.TypeCastMapping == nil { - opts.TypeCastMapping = make(map[Path]Cast) + opts.TypeCastMapping = make(map[tree.Path]Cast) } if opts.Substitute == nil { opts.Substitute = template.Substitute @@ -58,7 +58,7 @@ func Interpolate(config map[string]interface{}, opts Options) (map[string]interf out := map[string]interface{}{} for key, value := range config { - interpolatedValue, err := recursiveInterpolate(value, NewPath(key), opts) + interpolatedValue, err := recursiveInterpolate(value, tree.NewPath(key), opts) if err != nil { return out, err } @@ -68,7 +68,7 @@ func Interpolate(config map[string]interface{}, opts Options) (map[string]interf return out, nil } -func recursiveInterpolate(value interface{}, path Path, opts Options) (interface{}, error) { +func recursiveInterpolate(value interface{}, path tree.Path, opts Options) (interface{}, error) { switch value := value.(type) { case string: newValue, err := opts.Substitute(value, template.Mapping(opts.LookupValue)) @@ -96,7 +96,7 @@ func recursiveInterpolate(value interface{}, path Path, opts Options) (interface case []interface{}: out := make([]interface{}, len(value)) for i, elem := range value { - interpolatedElem, err := recursiveInterpolate(elem, path.Next(PathMatchList), opts) + interpolatedElem, err := recursiveInterpolate(elem, path.Next(tree.PathMatchList), opts) if err != nil { return nil, err } @@ -109,7 +109,7 @@ func recursiveInterpolate(value interface{}, path Path, opts Options) (interface } } -func newPathError(path Path, err error) error { +func newPathError(path tree.Path, err error) error { switch err := err.(type) { case nil: return nil @@ -122,54 +122,9 @@ func newPathError(path Path, err error) error { } } -const pathSeparator = "." - -// PathMatchAll is a token used as part of a Path to match any key at that level -// in the nested structure -const PathMatchAll = "*" - -// PathMatchList is a token used as part of a Path to match items in a list -const PathMatchList = "[]" - -// Path is a dotted path of keys to a value in a nested mapping structure. A * -// section in a path will match any key in the mapping structure. -type Path string - -// NewPath returns a new Path -func NewPath(items ...string) Path { - return Path(strings.Join(items, pathSeparator)) -} - -// Next returns a new path by append part to the current path -func (p Path) Next(part string) Path { - return Path(string(p) + pathSeparator + part) -} - -func (p Path) parts() []string { - return strings.Split(string(p), pathSeparator) -} - -func (p Path) matches(pattern Path) bool { - patternParts := pattern.parts() - parts := p.parts() - - if len(patternParts) != len(parts) { - return false - } - for index, part := range parts { - switch patternParts[index] { - case PathMatchAll, part: - continue - default: - return false - } - } - return true -} - -func (o Options) getCasterForPath(path Path) (Cast, bool) { +func (o Options) getCasterForPath(path tree.Path) (Cast, bool) { for pattern, caster := range o.TypeCastMapping { - if path.matches(pattern) { + if path.Matches(pattern) { return caster, true } } diff --git a/vendor/github.com/compose-spec/compose-go/loader/full-example.yml b/vendor/github.com/compose-spec/compose-go/loader/full-example.yml index b3b07f80..9f818f8c 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/full-example.yml +++ b/vendor/github.com/compose-spec/compose-go/loader/full-example.yml @@ -8,6 +8,8 @@ services: RUN echo "hello" > /world.txt foo: + annotations: + - com.example.foo=bar build: context: ./dir dockerfile: Dockerfile diff --git a/vendor/github.com/compose-spec/compose-go/loader/interpolate.go b/vendor/github.com/compose-spec/compose-go/loader/interpolate.go index 42ffe641..aae6dc3a 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/interpolate.go +++ b/vendor/github.com/compose-spec/compose-go/loader/interpolate.go @@ -21,67 +21,68 @@ import ( "strings" interp "github.com/compose-spec/compose-go/interpolation" + "github.com/compose-spec/compose-go/tree" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) -var interpolateTypeCastMapping = map[interp.Path]interp.Cast{ - servicePath("configs", interp.PathMatchList, "mode"): toInt, - servicePath("cpu_count"): toInt64, - servicePath("cpu_percent"): toFloat, - servicePath("cpu_period"): toInt64, - servicePath("cpu_quota"): toInt64, - servicePath("cpu_rt_period"): toInt64, - servicePath("cpu_rt_runtime"): toInt64, - servicePath("cpus"): toFloat32, - servicePath("cpu_shares"): toInt64, - servicePath("init"): toBoolean, - servicePath("deploy", "replicas"): toInt, - servicePath("deploy", "update_config", "parallelism"): toInt, - servicePath("deploy", "update_config", "max_failure_ratio"): toFloat, - servicePath("deploy", "rollback_config", "parallelism"): toInt, - servicePath("deploy", "rollback_config", "max_failure_ratio"): toFloat, - servicePath("deploy", "restart_policy", "max_attempts"): toInt, - servicePath("deploy", "placement", "max_replicas_per_node"): toInt, - servicePath("healthcheck", "retries"): toInt, - servicePath("healthcheck", "disable"): toBoolean, - servicePath("mem_limit"): toUnitBytes, - servicePath("mem_reservation"): toUnitBytes, - servicePath("memswap_limit"): toUnitBytes, - servicePath("mem_swappiness"): toUnitBytes, - servicePath("oom_kill_disable"): toBoolean, - servicePath("oom_score_adj"): toInt64, - servicePath("pids_limit"): toInt64, - servicePath("ports", interp.PathMatchList, "target"): toInt, - servicePath("privileged"): toBoolean, - servicePath("read_only"): toBoolean, - servicePath("scale"): toInt, - servicePath("secrets", interp.PathMatchList, "mode"): toInt, - servicePath("shm_size"): toUnitBytes, - servicePath("stdin_open"): toBoolean, - servicePath("stop_grace_period"): toDuration, - servicePath("tty"): toBoolean, - servicePath("ulimits", interp.PathMatchAll): toInt, - servicePath("ulimits", interp.PathMatchAll, "hard"): toInt, - servicePath("ulimits", interp.PathMatchAll, "soft"): toInt, - servicePath("volumes", interp.PathMatchList, "read_only"): toBoolean, - servicePath("volumes", interp.PathMatchList, "volume", "nocopy"): toBoolean, - servicePath("volumes", interp.PathMatchList, "tmpfs", "size"): toUnitBytes, - iPath("networks", interp.PathMatchAll, "external"): toBoolean, - iPath("networks", interp.PathMatchAll, "internal"): toBoolean, - iPath("networks", interp.PathMatchAll, "attachable"): toBoolean, - iPath("networks", interp.PathMatchAll, "enable_ipv6"): toBoolean, - iPath("volumes", interp.PathMatchAll, "external"): toBoolean, - iPath("secrets", interp.PathMatchAll, "external"): toBoolean, - iPath("configs", interp.PathMatchAll, "external"): toBoolean, +var interpolateTypeCastMapping = map[tree.Path]interp.Cast{ + servicePath("configs", tree.PathMatchList, "mode"): toInt, + servicePath("cpu_count"): toInt64, + servicePath("cpu_percent"): toFloat, + servicePath("cpu_period"): toInt64, + servicePath("cpu_quota"): toInt64, + servicePath("cpu_rt_period"): toInt64, + servicePath("cpu_rt_runtime"): toInt64, + servicePath("cpus"): toFloat32, + servicePath("cpu_shares"): toInt64, + servicePath("init"): toBoolean, + servicePath("deploy", "replicas"): toInt, + servicePath("deploy", "update_config", "parallelism"): toInt, + servicePath("deploy", "update_config", "max_failure_ratio"): toFloat, + servicePath("deploy", "rollback_config", "parallelism"): toInt, + servicePath("deploy", "rollback_config", "max_failure_ratio"): toFloat, + servicePath("deploy", "restart_policy", "max_attempts"): toInt, + servicePath("deploy", "placement", "max_replicas_per_node"): toInt, + servicePath("healthcheck", "retries"): toInt, + servicePath("healthcheck", "disable"): toBoolean, + servicePath("mem_limit"): toUnitBytes, + servicePath("mem_reservation"): toUnitBytes, + servicePath("memswap_limit"): toUnitBytes, + servicePath("mem_swappiness"): toUnitBytes, + servicePath("oom_kill_disable"): toBoolean, + servicePath("oom_score_adj"): toInt64, + servicePath("pids_limit"): toInt64, + servicePath("ports", tree.PathMatchList, "target"): toInt, + servicePath("privileged"): toBoolean, + servicePath("read_only"): toBoolean, + servicePath("scale"): toInt, + servicePath("secrets", tree.PathMatchList, "mode"): toInt, + servicePath("shm_size"): toUnitBytes, + servicePath("stdin_open"): toBoolean, + servicePath("stop_grace_period"): toDuration, + servicePath("tty"): toBoolean, + servicePath("ulimits", tree.PathMatchAll): toInt, + servicePath("ulimits", tree.PathMatchAll, "hard"): toInt, + servicePath("ulimits", tree.PathMatchAll, "soft"): toInt, + servicePath("volumes", tree.PathMatchList, "read_only"): toBoolean, + servicePath("volumes", tree.PathMatchList, "volume", "nocopy"): toBoolean, + servicePath("volumes", tree.PathMatchList, "tmpfs", "size"): toUnitBytes, + iPath("networks", tree.PathMatchAll, "external"): toBoolean, + iPath("networks", tree.PathMatchAll, "internal"): toBoolean, + iPath("networks", tree.PathMatchAll, "attachable"): toBoolean, + iPath("networks", tree.PathMatchAll, "enable_ipv6"): toBoolean, + iPath("volumes", tree.PathMatchAll, "external"): toBoolean, + iPath("secrets", tree.PathMatchAll, "external"): toBoolean, + iPath("configs", tree.PathMatchAll, "external"): toBoolean, } -func iPath(parts ...string) interp.Path { - return interp.NewPath(parts...) +func iPath(parts ...string) tree.Path { + return tree.NewPath(parts...) } -func servicePath(parts ...string) interp.Path { - return iPath(append([]string{"services", interp.PathMatchAll}, parts...)...) +func servicePath(parts ...string) tree.Path { + return iPath(append([]string{"services", tree.PathMatchAll}, parts...)...) } func toInt(value string) (interface{}, error) { 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 85cf593c..8873b29b 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/loader.go +++ b/vendor/github.com/compose-spec/compose-go/loader/loader.go @@ -134,27 +134,43 @@ 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) + return m, err +} + +// 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 { + yaml.Unmarshaler + + // Apply changes to compose model based on recorder metadata + Apply(config *types.Config) error +} + +func parseYAML(source []byte) (map[string]interface{}, PostProcessor, error) { var cfg interface{} - if err := yaml.Unmarshal(source, &cfg); err != nil { - return nil, err + processor := ResetProcessor{target: &cfg} + + if err := yaml.Unmarshal(source, &processor); err != nil { + return nil, nil, err } stringMap, ok := cfg.(map[string]interface{}) if ok { converted, err := convertToStringKeysRecursive(stringMap, "") if err != nil { - return nil, err + return nil, nil, err } - return converted.(map[string]interface{}), nil + return converted.(map[string]interface{}), &processor, nil } cfgMap, ok := cfg.(map[interface{}]interface{}) if !ok { - return nil, errors.Errorf("Top-level object must be a mapping") + return nil, nil, errors.Errorf("Top-level object must be a mapping") } converted, err := convertToStringKeysRecursive(cfgMap, "") if err != nil { - return nil, err + return nil, nil, err } - return converted.(map[string]interface{}), nil + return converted.(map[string]interface{}), &processor, nil } // Load reads a ConfigDetails and returns a fully loaded configuration @@ -180,8 +196,9 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types. return nil, err } - var configs []*types.Config + var model *types.Config for i, file := range configDetails.ConfigFiles { + var postProcessor PostProcessor configDict := file.Config if configDict == nil { if len(file.Content) == 0 { @@ -191,13 +208,14 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types. } file.Content = content } - dict, err := parseConfig(file.Content, opts) + dict, p, err := parseConfig(file.Content, opts) if err != nil { return nil, fmt.Errorf("parsing %s: %w", file.Filename, err) } configDict = dict file.Config = dict configDetails.ConfigFiles[i] = file + postProcessor = p } if !opts.SkipValidation { @@ -212,12 +230,22 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types. if err != nil { return nil, err } - configs = append(configs, cfg) - } - model, err := merge(configs) - if err != nil { - return nil, err + if i == 0 { + model = cfg + continue + } + merged, err := merge([]*types.Config{model, cfg}) + if err != nil { + return nil, err + } + if postProcessor != nil { + err = postProcessor.Apply(merged) + if err != nil { + return nil, err + } + } + model = merged } for _, s := range model.Services { @@ -266,8 +294,8 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types. func InvalidProjectNameErr(v string) error { return fmt.Errorf( - "%q is not a valid project name: it must contain only "+ - "characters from [a-z0-9_-] and start with [a-z0-9]", v, + "invalid project name %q: must consist only of lowercase alphanumeric characters, hyphens, and underscores as well as start with a letter or number", + v, ) } @@ -343,15 +371,16 @@ func NormalizeProjectName(s string) string { return strings.TrimLeft(s, "_-") } -func parseConfig(b []byte, opts *Options) (map[string]interface{}, error) { - yml, err := ParseYAML(b) +func parseConfig(b []byte, opts *Options) (map[string]interface{}, PostProcessor, error) { + yml, postProcessor, err := parseYAML(b) if err != nil { - return nil, err + return nil, nil, err } if !opts.SkipInterpolation { - return interp.Interpolate(yml, *opts.Interpolate) + interpolated, err := interp.Interpolate(yml, *opts.Interpolate) + return interpolated, postProcessor, err } - return yml, err + return yml, postProcessor, err } const extensions = "#extensions" // Using # prefix, we prevent risk to conflict with an actual yaml key @@ -441,6 +470,7 @@ func Transform(source interface{}, target interface{}, additionalTransformers .. createTransformHook(additionalTransformers...), mapstructure.StringToTimeDurationHookFunc()), Result: target, + TagName: "yaml", Metadata: &data, } decoder, err := mapstructure.NewDecoder(config) @@ -626,7 +656,7 @@ func loadServiceWithExtends(filename, name string, servicesDict map[string]inter return nil, err } - baseFile, err := parseConfig(b, opts) + baseFile, _, err := parseConfig(b, opts) if err != nil { return nil, err } diff --git a/vendor/github.com/compose-spec/compose-go/loader/normalize.go b/vendor/github.com/compose-spec/compose-go/loader/normalize.go index a50634b3..f6610b14 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/normalize.go +++ b/vendor/github.com/compose-spec/compose-go/loader/normalize.go @@ -155,6 +155,8 @@ func Normalize(project *types.Project, resolvePaths bool) error { return err } + inferImplicitDependencies(&s) + project.Services[i] = s } @@ -171,6 +173,61 @@ func Normalize(project *types.Project, resolvePaths bool) error { return nil } +// IsServiceDependency check the relation set by ref refers to a service +func IsServiceDependency(ref string) (string, bool) { + if strings.HasPrefix( + ref, + types.ServicePrefix, + ) { + return ref[len(types.ServicePrefix):], true + } + return "", false +} + +func inferImplicitDependencies(service *types.ServiceConfig) { + var dependencies []string + + maybeReferences := []string{ + service.NetworkMode, + service.Ipc, + service.Pid, + service.Uts, + service.Cgroup, + } + for _, ref := range maybeReferences { + if dep, ok := IsServiceDependency(ref); ok { + dependencies = append(dependencies, dep) + } + } + + for _, vol := range service.VolumesFrom { + spec := strings.Split(vol, ":") + if len(spec) == 0 { + continue + } + if spec[0] == "container" { + continue + } + dependencies = append(dependencies, spec[0]) + } + + for _, link := range service.Links { + dependencies = append(dependencies, strings.Split(link, ":")[0]) + } + + if len(dependencies) > 0 && service.DependsOn == nil { + service.DependsOn = make(types.DependsOnConfig) + } + + for _, d := range dependencies { + if _, ok := service.DependsOn[d]; !ok { + service.DependsOn[d] = types.ServiceDependency{ + Condition: types.ServiceConditionStarted, + } + } + } +} + // setIfMissing adds a ServiceDependency for service if not already defined func setIfMissing(d types.DependsOnConfig, service string, dep types.ServiceDependency) types.DependsOnConfig { if d == nil { diff --git a/vendor/github.com/compose-spec/compose-go/loader/null.go b/vendor/github.com/compose-spec/compose-go/loader/null.go new file mode 100644 index 00000000..648aacde --- /dev/null +++ b/vendor/github.com/compose-spec/compose-go/loader/null.go @@ -0,0 +1,159 @@ +/* + Copyright 2020 The Compose Specification Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package loader + +import ( + "fmt" + "reflect" + "strconv" + "strings" + + "github.com/compose-spec/compose-go/tree" + "github.com/compose-spec/compose-go/types" + "gopkg.in/yaml.v3" +) + +type ResetProcessor struct { + target interface{} + paths []tree.Path +} + +// UnmarshalYAML implement yaml.Unmarshaler +func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error { + resolved, err := p.resolveReset(value, tree.NewPath()) + if err != nil { + return err + } + return resolved.Decode(p.target) +} + +// resolveReset detects `!reset` tag being set on yaml nodes and record position in the yaml tree +func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.Node, error) { + if node.Tag == "!reset" { + p.paths = append(p.paths, path) + } + switch node.Kind { + case yaml.SequenceNode: + var err error + for idx, v := range node.Content { + next := path.Next(strconv.Itoa(idx)) + node.Content[idx], err = p.resolveReset(v, next) + if err != nil { + return nil, err + } + } + case yaml.MappingNode: + var err error + var key string + for idx, v := range node.Content { + if idx%2 == 0 { + key = v.Value + } else { + node.Content[idx], err = p.resolveReset(v, path.Next(key)) + if err != nil { + return nil, err + } + } + } + } + return node, nil +} + +// Apply finds the go attributes matching recorded paths and reset them to zero value +func (p *ResetProcessor) Apply(target *types.Config) error { + return p.applyNullOverrides(reflect.ValueOf(target), tree.NewPath()) +} + +// applyNullOverrides set val to Zero if it matches any of the recorded paths +func (p *ResetProcessor) applyNullOverrides(val reflect.Value, path tree.Path) error { + val = reflect.Indirect(val) + if !val.IsValid() { + return nil + } + typ := val.Type() + switch { + case path == "services": + // Project.Services is a slice in compose-go, but a mapping in yaml + for i := 0; i < val.Len(); i++ { + service := val.Index(i) + name := service.FieldByName("Name") + next := path.Next(name.String()) + err := p.applyNullOverrides(service, next) + if err != nil { + return err + } + } + case typ.Kind() == reflect.Map: + iter := val.MapRange() + KEYS: + for iter.Next() { + k := iter.Key() + next := path.Next(k.String()) + for _, pattern := range p.paths { + if next.Matches(pattern) { + val.SetMapIndex(k, reflect.Value{}) + continue KEYS + } + } + return p.applyNullOverrides(iter.Value(), next) + } + case typ.Kind() == reflect.Slice: + ITER: + for i := 0; i < val.Len(); i++ { + next := path.Next(fmt.Sprintf("[%d]", i)) + for _, pattern := range p.paths { + if next.Matches(pattern) { + + continue ITER + } + } + // TODO(ndeloof) support removal from sequence + return p.applyNullOverrides(val.Index(i), next) + } + + case typ.Kind() == reflect.Struct: + FIELDS: + for i := 0; i < typ.NumField(); i++ { + field := typ.Field(i) + name := field.Name + attr := strings.ToLower(name) + tag := field.Tag.Get("yaml") + tag = strings.Split(tag, ",")[0] + if tag != "" && tag != "-" { + attr = tag + } + next := path.Next(attr) + f := val.Field(i) + for _, pattern := range p.paths { + if next.Matches(pattern) { + f := f + if !f.CanSet() { + return fmt.Errorf("can't override attribute %s", name) + } + // f.SetZero() requires go 1.20 + f.Set(reflect.Zero(f.Type())) + continue FIELDS + } + } + err := p.applyNullOverrides(f, next) + if err != nil { + return err + } + } + } + return nil +} diff --git a/vendor/github.com/compose-spec/compose-go/loader/volume.go b/vendor/github.com/compose-spec/compose-go/loader/volume.go index f1e66cde..dd83414a 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/volume.go +++ b/vendor/github.com/compose-spec/compose-go/loader/volume.go @@ -176,5 +176,8 @@ func isFilePath(source string) bool { } first, nextIndex := utf8.DecodeRuneInString(source) + if len(source) <= nextIndex { + return false + } return isWindowsDrive([]rune{first}, rune(source[nextIndex])) } diff --git a/vendor/github.com/compose-spec/compose-go/schema/compose-spec.json b/vendor/github.com/compose-spec/compose-go/schema/compose-spec.json index c5871256..53f3c1db 100644 --- a/vendor/github.com/compose-spec/compose-go/schema/compose-spec.json +++ b/vendor/github.com/compose-spec/compose-go/schema/compose-spec.json @@ -83,6 +83,7 @@ "properties": { "deploy": {"$ref": "#/definitions/deployment"}, + "annotations": {"$ref": "#/definitions/list_or_dict"}, "build": { "oneOf": [ {"type": "string"}, diff --git a/vendor/github.com/compose-spec/compose-go/template/template.go b/vendor/github.com/compose-spec/compose-go/template/template.go index f9b52f6e..3d548e09 100644 --- a/vendor/github.com/compose-spec/compose-go/template/template.go +++ b/vendor/github.com/compose-spec/compose-go/template/template.go @@ -28,7 +28,7 @@ import ( var delimiter = "\\$" var substitutionNamed = "[_a-z][_a-z0-9]*" -var substitutionBraced = "[_a-z][_a-z0-9]*(?::?[-+?](.*}|[^}]*))?" +var substitutionBraced = "[_a-z][_a-z0-9]*(?::?[-+?](.*))?" var patternString = fmt.Sprintf( "%s(?i:(?P%s)|(?P%s)|{(?:(?P%s)}|(?P)))", diff --git a/vendor/github.com/compose-spec/compose-go/tree/path.go b/vendor/github.com/compose-spec/compose-go/tree/path.go new file mode 100644 index 00000000..59c25030 --- /dev/null +++ b/vendor/github.com/compose-spec/compose-go/tree/path.go @@ -0,0 +1,67 @@ +/* + Copyright 2020 The Compose Specification Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package tree + +import "strings" + +const pathSeparator = "." + +// PathMatchAll is a token used as part of a Path to match any key at that level +// in the nested structure +const PathMatchAll = "*" + +// PathMatchList is a token used as part of a Path to match items in a list +const PathMatchList = "[]" + +// Path is a dotted path of keys to a value in a nested mapping structure. A * +// section in a path will match any key in the mapping structure. +type Path string + +// NewPath returns a new Path +func NewPath(items ...string) Path { + return Path(strings.Join(items, pathSeparator)) +} + +// Next returns a new path by append part to the current path +func (p Path) Next(part string) Path { + if p == "" { + return Path(part) + } + return Path(string(p) + pathSeparator + part) +} + +func (p Path) Parts() []string { + return strings.Split(string(p), pathSeparator) +} + +func (p Path) Matches(pattern Path) bool { + patternParts := pattern.Parts() + parts := p.Parts() + + if len(patternParts) != len(parts) { + return false + } + for index, part := range parts { + switch patternParts[index] { + case PathMatchAll, part: + continue + default: + return false + } + } + return true +} 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 bb8a3abe..896bcd69 100644 --- a/vendor/github.com/compose-spec/compose-go/types/project.go +++ b/vendor/github.com/compose-spec/compose-go/types/project.go @@ -36,12 +36,12 @@ import ( type Project struct { Name string `yaml:"name,omitempty" json:"name,omitempty"` WorkingDir string `yaml:"-" json:"-"` - Services Services `json:"services"` - Networks Networks `yaml:",omitempty" json:"networks,omitempty"` - Volumes Volumes `yaml:",omitempty" json:"volumes,omitempty"` - Secrets Secrets `yaml:",omitempty" json:"secrets,omitempty"` - Configs Configs `yaml:",omitempty" json:"configs,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` // https://github.com/golang/go/issues/6213 + 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:"-"` @@ -396,6 +396,11 @@ func (p *Project) ForServices(names []string, options ...DependencyOption) error var enabled Services for _, s := range p.Services { if _, ok := set[s.Name]; ok { + for _, option := range options { + if option == IgnoreDependencies { + s.DependsOn = nil + } + } enabled = append(enabled, s) } else { p.DisabledServices = append(p.DisabledServices, s) 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 9d8fa586..4c67bc66 100644 --- a/vendor/github.com/compose-spec/compose-go/types/types.go +++ b/vendor/github.com/compose-spec/compose-go/types/types.go @@ -86,42 +86,43 @@ func (s Services) MarshalJSON() ([]byte, error) { // ServiceConfig is the configuration of one service type ServiceConfig struct { Name string `yaml:"-" json:"-"` - Profiles []string `mapstructure:"profiles" yaml:"profiles,omitempty" json:"profiles,omitempty"` - - Build *BuildConfig `yaml:",omitempty" json:"build,omitempty"` - BlkioConfig *BlkioConfig `mapstructure:"blkio_config" yaml:",omitempty" json:"blkio_config,omitempty"` - CapAdd []string `mapstructure:"cap_add" yaml:"cap_add,omitempty" json:"cap_add,omitempty"` - CapDrop []string `mapstructure:"cap_drop" yaml:"cap_drop,omitempty" json:"cap_drop,omitempty"` - CgroupParent string `mapstructure:"cgroup_parent" yaml:"cgroup_parent,omitempty" json:"cgroup_parent,omitempty"` - Cgroup string `mapstructure:"cgroup" yaml:"cgroup,omitempty" json:"cgroup,omitempty"` - CPUCount int64 `mapstructure:"cpu_count" yaml:"cpu_count,omitempty" json:"cpu_count,omitempty"` - CPUPercent float32 `mapstructure:"cpu_percent" yaml:"cpu_percent,omitempty" json:"cpu_percent,omitempty"` - CPUPeriod int64 `mapstructure:"cpu_period" yaml:"cpu_period,omitempty" json:"cpu_period,omitempty"` - CPUQuota int64 `mapstructure:"cpu_quota" yaml:"cpu_quota,omitempty" json:"cpu_quota,omitempty"` - CPURTPeriod int64 `mapstructure:"cpu_rt_period" yaml:"cpu_rt_period,omitempty" json:"cpu_rt_period,omitempty"` - CPURTRuntime int64 `mapstructure:"cpu_rt_runtime" yaml:"cpu_rt_runtime,omitempty" json:"cpu_rt_runtime,omitempty"` - CPUS float32 `mapstructure:"cpus" yaml:"cpus,omitempty" json:"cpus,omitempty"` - CPUSet string `mapstructure:"cpuset" yaml:"cpuset,omitempty" json:"cpuset,omitempty"` - CPUShares int64 `mapstructure:"cpu_shares" yaml:"cpu_shares,omitempty" json:"cpu_shares,omitempty"` + Profiles []string `yaml:"profiles,omitempty" json:"profiles,omitempty"` + + Annotations Mapping `yaml:"annotations,omitempty" json:"annotations,omitempty"` + Build *BuildConfig `yaml:"build,omitempty" json:"build,omitempty"` + BlkioConfig *BlkioConfig `yaml:"blkio_config,omitempty" json:"blkio_config,omitempty"` + CapAdd []string `yaml:"cap_add,omitempty" json:"cap_add,omitempty"` + CapDrop []string `yaml:"cap_drop,omitempty" json:"cap_drop,omitempty"` + CgroupParent string `yaml:"cgroup_parent,omitempty" json:"cgroup_parent,omitempty"` + Cgroup string `yaml:"cgroup,omitempty" json:"cgroup,omitempty"` + CPUCount int64 `yaml:"cpu_count,omitempty" json:"cpu_count,omitempty"` + CPUPercent float32 `yaml:"cpu_percent,omitempty" json:"cpu_percent,omitempty"` + CPUPeriod int64 `yaml:"cpu_period,omitempty" json:"cpu_period,omitempty"` + CPUQuota int64 `yaml:"cpu_quota,omitempty" json:"cpu_quota,omitempty"` + CPURTPeriod int64 `yaml:"cpu_rt_period,omitempty" json:"cpu_rt_period,omitempty"` + CPURTRuntime int64 `yaml:"cpu_rt_runtime,omitempty" json:"cpu_rt_runtime,omitempty"` + CPUS float32 `yaml:"cpus,omitempty" json:"cpus,omitempty"` + CPUSet string `yaml:"cpuset,omitempty" json:"cpuset,omitempty"` + CPUShares int64 `yaml:"cpu_shares,omitempty" json:"cpu_shares,omitempty"` // Command for the service containers. // If set, overrides COMMAND from the image. // // Set to `[]` or an empty string to clear the command from the image. - Command ShellCommand `yaml:",omitempty" json:"command"` // NOTE: we can NOT omitempty for JSON! see ShellCommand type for details. - - Configs []ServiceConfigObjConfig `yaml:",omitempty" json:"configs,omitempty"` - ContainerName string `mapstructure:"container_name" yaml:"container_name,omitempty" json:"container_name,omitempty"` - CredentialSpec *CredentialSpecConfig `mapstructure:"credential_spec" yaml:"credential_spec,omitempty" json:"credential_spec,omitempty"` - DependsOn DependsOnConfig `mapstructure:"depends_on" yaml:"depends_on,omitempty" json:"depends_on,omitempty"` - Deploy *DeployConfig `yaml:",omitempty" json:"deploy,omitempty"` - DeviceCgroupRules []string `mapstructure:"device_cgroup_rules" yaml:"device_cgroup_rules,omitempty" json:"device_cgroup_rules,omitempty"` - Devices []string `yaml:",omitempty" json:"devices,omitempty"` - DNS StringList `yaml:",omitempty" json:"dns,omitempty"` - DNSOpts []string `mapstructure:"dns_opt" yaml:"dns_opt,omitempty" json:"dns_opt,omitempty"` - DNSSearch StringList `mapstructure:"dns_search" yaml:"dns_search,omitempty" json:"dns_search,omitempty"` + Command ShellCommand `yaml:"command,omitempty" json:"command"` // NOTE: we can NOT omitempty for JSON! see ShellCommand type for details. + + Configs []ServiceConfigObjConfig `yaml:"configs,omitempty" json:"configs,omitempty"` + ContainerName string `yaml:"container_name,omitempty" json:"container_name,omitempty"` + CredentialSpec *CredentialSpecConfig `yaml:"credential_spec,omitempty" json:"credential_spec,omitempty"` + DependsOn DependsOnConfig `yaml:"depends_on,omitempty" json:"depends_on,omitempty"` + Deploy *DeployConfig `yaml:"deploy,omitempty" json:"deploy,omitempty"` + DeviceCgroupRules []string `yaml:"device_cgroup_rules,omitempty" json:"device_cgroup_rules,omitempty"` + Devices []string `yaml:"devices,omitempty" json:"devices,omitempty"` + DNS StringList `yaml:"dns,omitempty" json:"dns,omitempty"` + DNSOpts []string `yaml:"dns_opt,omitempty" json:"dns_opt,omitempty"` + DNSSearch StringList `yaml:"dns_search,omitempty" json:"dns_search,omitempty"` Dockerfile string `yaml:"dockerfile,omitempty" json:"dockerfile,omitempty"` - DomainName string `mapstructure:"domainname" yaml:"domainname,omitempty" json:"domainname,omitempty"` + DomainName string `yaml:"domainname,omitempty" json:"domainname,omitempty"` // Entrypoint for the service containers. // If set, overrides ENTRYPOINT from the image. @@ -129,64 +130,80 @@ type ServiceConfig struct { // Set to `[]` or an empty string to clear the entrypoint from the image. Entrypoint ShellCommand `yaml:"entrypoint,omitempty" json:"entrypoint"` // NOTE: we can NOT omitempty for JSON! see ShellCommand type for details. - Environment MappingWithEquals `yaml:",omitempty" json:"environment,omitempty"` - EnvFile StringList `mapstructure:"env_file" yaml:"env_file,omitempty" json:"env_file,omitempty"` - Expose StringOrNumberList `yaml:",omitempty" json:"expose,omitempty"` + Environment MappingWithEquals `yaml:"environment,omitempty" json:"environment,omitempty"` + EnvFile StringList `yaml:"env_file,omitempty" json:"env_file,omitempty"` + Expose StringOrNumberList `yaml:"expose,omitempty" json:"expose,omitempty"` Extends *ExtendsConfig `yaml:"extends,omitempty" json:"extends,omitempty"` - ExternalLinks []string `mapstructure:"external_links" yaml:"external_links,omitempty" json:"external_links,omitempty"` - ExtraHosts HostsList `mapstructure:"extra_hosts" yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"` - GroupAdd []string `mapstructure:"group_add" yaml:"group_add,omitempty" json:"group_add,omitempty"` - Hostname string `yaml:",omitempty" json:"hostname,omitempty"` - HealthCheck *HealthCheckConfig `yaml:",omitempty" json:"healthcheck,omitempty"` - Image string `yaml:",omitempty" json:"image,omitempty"` - Init *bool `yaml:",omitempty" json:"init,omitempty"` - Ipc string `yaml:",omitempty" json:"ipc,omitempty"` - Isolation string `mapstructure:"isolation" yaml:"isolation,omitempty" json:"isolation,omitempty"` - Labels Labels `yaml:",omitempty" json:"labels,omitempty"` + ExternalLinks []string `yaml:"external_links,omitempty" json:"external_links,omitempty"` + ExtraHosts HostsList `yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"` + GroupAdd []string `yaml:"group_add,omitempty" json:"group_add,omitempty"` + Hostname string `yaml:"hostname,omitempty" json:"hostname,omitempty"` + HealthCheck *HealthCheckConfig `yaml:"healthcheck,omitempty" json:"healthcheck,omitempty"` + Image string `yaml:"image,omitempty" json:"image,omitempty"` + Init *bool `yaml:"init,omitempty" json:"init,omitempty"` + Ipc string `yaml:"ipc,omitempty" json:"ipc,omitempty"` + Isolation string `yaml:"isolation,omitempty" json:"isolation,omitempty"` + Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"` CustomLabels Labels `yaml:"-" json:"-"` - Links []string `yaml:",omitempty" json:"links,omitempty"` - Logging *LoggingConfig `yaml:",omitempty" json:"logging,omitempty"` - LogDriver string `mapstructure:"log_driver" yaml:"log_driver,omitempty" json:"log_driver,omitempty"` - LogOpt map[string]string `mapstructure:"log_opt" yaml:"log_opt,omitempty" json:"log_opt,omitempty"` - MemLimit UnitBytes `mapstructure:"mem_limit" yaml:"mem_limit,omitempty" json:"mem_limit,omitempty"` - MemReservation UnitBytes `mapstructure:"mem_reservation" yaml:"mem_reservation,omitempty" json:"mem_reservation,omitempty"` - MemSwapLimit UnitBytes `mapstructure:"memswap_limit" yaml:"memswap_limit,omitempty" json:"memswap_limit,omitempty"` - MemSwappiness UnitBytes `mapstructure:"mem_swappiness" yaml:"mem_swappiness,omitempty" json:"mem_swappiness,omitempty"` - MacAddress string `mapstructure:"mac_address" yaml:"mac_address,omitempty" json:"mac_address,omitempty"` + Links []string `yaml:"links,omitempty" json:"links,omitempty"` + Logging *LoggingConfig `yaml:"logging,omitempty" json:"logging,omitempty"` + LogDriver string `yaml:"log_driver,omitempty" json:"log_driver,omitempty"` + LogOpt map[string]string `yaml:"log_opt,omitempty" json:"log_opt,omitempty"` + MemLimit UnitBytes `yaml:"mem_limit,omitempty" json:"mem_limit,omitempty"` + MemReservation UnitBytes `yaml:"mem_reservation,omitempty" json:"mem_reservation,omitempty"` + MemSwapLimit UnitBytes `yaml:"memswap_limit,omitempty" json:"memswap_limit,omitempty"` + MemSwappiness UnitBytes `yaml:"mem_swappiness,omitempty" json:"mem_swappiness,omitempty"` + MacAddress string `yaml:"mac_address,omitempty" json:"mac_address,omitempty"` Net string `yaml:"net,omitempty" json:"net,omitempty"` - NetworkMode string `mapstructure:"network_mode" yaml:"network_mode,omitempty" json:"network_mode,omitempty"` - Networks map[string]*ServiceNetworkConfig `yaml:",omitempty" json:"networks,omitempty"` - OomKillDisable bool `mapstructure:"oom_kill_disable" yaml:"oom_kill_disable,omitempty" json:"oom_kill_disable,omitempty"` - OomScoreAdj int64 `mapstructure:"oom_score_adj" yaml:"oom_score_adj,omitempty" json:"oom_score_adj,omitempty"` - Pid string `yaml:",omitempty" json:"pid,omitempty"` - PidsLimit int64 `mapstructure:"pids_limit" yaml:"pids_limit,omitempty" json:"pids_limit,omitempty"` - Platform string `yaml:",omitempty" json:"platform,omitempty"` - Ports []ServicePortConfig `yaml:",omitempty" json:"ports,omitempty"` - Privileged bool `yaml:",omitempty" json:"privileged,omitempty"` - PullPolicy string `mapstructure:"pull_policy" yaml:"pull_policy,omitempty" json:"pull_policy,omitempty"` - ReadOnly bool `mapstructure:"read_only" yaml:"read_only,omitempty" json:"read_only,omitempty"` - Restart string `yaml:",omitempty" json:"restart,omitempty"` - Runtime string `yaml:",omitempty" json:"runtime,omitempty"` - Scale int `yaml:"-" json:"-"` - Secrets []ServiceSecretConfig `yaml:",omitempty" json:"secrets,omitempty"` - SecurityOpt []string `mapstructure:"security_opt" yaml:"security_opt,omitempty" json:"security_opt,omitempty"` - ShmSize UnitBytes `mapstructure:"shm_size" yaml:"shm_size,omitempty" json:"shm_size,omitempty"` - StdinOpen bool `mapstructure:"stdin_open" yaml:"stdin_open,omitempty" json:"stdin_open,omitempty"` - StopGracePeriod *Duration `mapstructure:"stop_grace_period" yaml:"stop_grace_period,omitempty" json:"stop_grace_period,omitempty"` - StopSignal string `mapstructure:"stop_signal" yaml:"stop_signal,omitempty" json:"stop_signal,omitempty"` - Sysctls Mapping `yaml:",omitempty" json:"sysctls,omitempty"` - Tmpfs StringList `yaml:",omitempty" json:"tmpfs,omitempty"` - Tty bool `mapstructure:"tty" yaml:"tty,omitempty" json:"tty,omitempty"` - Ulimits map[string]*UlimitsConfig `yaml:",omitempty" json:"ulimits,omitempty"` - User string `yaml:",omitempty" json:"user,omitempty"` - UserNSMode string `mapstructure:"userns_mode" yaml:"userns_mode,omitempty" json:"userns_mode,omitempty"` + NetworkMode string `yaml:"network_mode,omitempty" json:"network_mode,omitempty"` + Networks map[string]*ServiceNetworkConfig `yaml:"networks,omitempty" json:"networks,omitempty"` + OomKillDisable bool `yaml:"oom_kill_disable,omitempty" json:"oom_kill_disable,omitempty"` + OomScoreAdj int64 `yaml:"oom_score_adj,omitempty" json:"oom_score_adj,omitempty"` + Pid string `yaml:"pid,omitempty" json:"pid,omitempty"` + PidsLimit int64 `yaml:"pids_limit,omitempty" json:"pids_limit,omitempty"` + Platform string `yaml:"platform,omitempty" json:"platform,omitempty"` + Ports []ServicePortConfig `yaml:"ports,omitempty" json:"ports,omitempty"` + Privileged bool `yaml:"privileged,omitempty" json:"privileged,omitempty"` + PullPolicy string `yaml:"pull_policy,omitempty" json:"pull_policy,omitempty"` + ReadOnly bool `yaml:"read_only,omitempty" json:"read_only,omitempty"` + Restart string `yaml:"restart,omitempty" json:"restart,omitempty"` + Runtime string `yaml:"runtime,omitempty" json:"runtime,omitempty"` + Scale int `yaml:"scale,omitempty" json:"scale,omitempty"` + Secrets []ServiceSecretConfig `yaml:"secrets,omitempty" json:"secrets,omitempty"` + SecurityOpt []string `yaml:"security_opt,omitempty" json:"security_opt,omitempty"` + ShmSize UnitBytes `yaml:"shm_size,omitempty" json:"shm_size,omitempty"` + StdinOpen bool `yaml:"stdin_open,omitempty" json:"stdin_open,omitempty"` + StopGracePeriod *Duration `yaml:"stop_grace_period,omitempty" json:"stop_grace_period,omitempty"` + StopSignal string `yaml:"stop_signal,omitempty" json:"stop_signal,omitempty"` + Sysctls Mapping `yaml:"sysctls,omitempty" json:"sysctls,omitempty"` + Tmpfs StringList `yaml:"tmpfs,omitempty" json:"tmpfs,omitempty"` + Tty bool `yaml:"tty,omitempty" json:"tty,omitempty"` + Ulimits map[string]*UlimitsConfig `yaml:"ulimits,omitempty" json:"ulimits,omitempty"` + User string `yaml:"user,omitempty" json:"user,omitempty"` + UserNSMode string `yaml:"userns_mode,omitempty" json:"userns_mode,omitempty"` Uts string `yaml:"uts,omitempty" json:"uts,omitempty"` - VolumeDriver string `mapstructure:"volume_driver" yaml:"volume_driver,omitempty" json:"volume_driver,omitempty"` - Volumes []ServiceVolumeConfig `yaml:",omitempty" json:"volumes,omitempty"` - VolumesFrom []string `mapstructure:"volumes_from" yaml:"volumes_from,omitempty" json:"volumes_from,omitempty"` - WorkingDir string `mapstructure:"working_dir" yaml:"working_dir,omitempty" json:"working_dir,omitempty"` + VolumeDriver string `yaml:"volume_driver,omitempty" json:"volume_driver,omitempty"` + Volumes []ServiceVolumeConfig `yaml:"volumes,omitempty" json:"volumes,omitempty"` + VolumesFrom []string `yaml:"volumes_from,omitempty" json:"volumes_from,omitempty"` + WorkingDir string `yaml:"working_dir,omitempty" json:"working_dir,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` +} + +// MarshalYAML makes ServiceConfig implement yaml.Marshaller +func (s ServiceConfig) MarshalYAML() (interface{}, error) { + type t ServiceConfig + value := t(s) + value.Scale = 0 // deprecated, but default value "1" doesn't match omitempty + return value, nil +} + +// MarshalJSON makes SSHKey implement json.Marshaller +func (s ServiceConfig) MarshalJSON() ([]byte, error) { + type t ServiceConfig + value := t(s) + value.Scale = 0 // deprecated, but default value "1" doesn't match omitempty + return json.Marshal(value) } // NetworksByPriority return the service networks IDs sorted according to Priority @@ -294,39 +311,39 @@ func (s set) toSlice() []string { // BuildConfig is a type for build type BuildConfig struct { - Context string `yaml:",omitempty" json:"context,omitempty"` - Dockerfile string `yaml:",omitempty" json:"dockerfile,omitempty"` - DockerfileInline string `mapstructure:"dockerfile_inline,omitempty" yaml:"dockerfile_inline,omitempty" json:"dockerfile_inline,omitempty"` - Args MappingWithEquals `yaml:",omitempty" json:"args,omitempty"` + Context string `yaml:"context,omitempty" json:"context,omitempty"` + Dockerfile string `yaml:"dockerfile,omitempty" json:"dockerfile,omitempty"` + DockerfileInline string `yaml:"dockerfile_inline,omitempty" json:"dockerfile_inline,omitempty"` + Args MappingWithEquals `yaml:"args,omitempty" json:"args,omitempty"` SSH SSHConfig `yaml:"ssh,omitempty" json:"ssh,omitempty"` - Labels Labels `yaml:",omitempty" json:"labels,omitempty"` - CacheFrom StringList `mapstructure:"cache_from" yaml:"cache_from,omitempty" json:"cache_from,omitempty"` - CacheTo StringList `mapstructure:"cache_to" yaml:"cache_to,omitempty" json:"cache_to,omitempty"` - NoCache bool `mapstructure:"no_cache" yaml:"no_cache,omitempty" json:"no_cache,omitempty"` - AdditionalContexts Mapping `mapstructure:"additional_contexts" yaml:"additional_contexts,omitempty" json:"additional_contexts,omitempty"` - Pull bool `mapstructure:"pull" yaml:"pull,omitempty" json:"pull,omitempty"` - ExtraHosts HostsList `mapstructure:"extra_hosts" yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"` - Isolation string `yaml:",omitempty" json:"isolation,omitempty"` - Network string `yaml:",omitempty" json:"network,omitempty"` - Target string `yaml:",omitempty" json:"target,omitempty"` - Secrets []ServiceSecretConfig `yaml:",omitempty" json:"secrets,omitempty"` - Tags StringList `mapstructure:"tags" yaml:"tags,omitempty" json:"tags,omitempty"` - Platforms StringList `mapstructure:"platforms" yaml:"platforms,omitempty" json:"platforms,omitempty"` - Privileged bool `yaml:",omitempty" json:"privileged,omitempty"` - - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"` + CacheFrom StringList `yaml:"cache_from,omitempty" json:"cache_from,omitempty"` + CacheTo StringList `yaml:"cache_to,omitempty" json:"cache_to,omitempty"` + NoCache bool `yaml:"no_cache,omitempty" json:"no_cache,omitempty"` + AdditionalContexts Mapping `yaml:"additional_contexts,omitempty" json:"additional_contexts,omitempty"` + Pull bool `yaml:"pull,omitempty" json:"pull,omitempty"` + ExtraHosts HostsList `yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"` + Isolation string `yaml:"isolation,omitempty" json:"isolation,omitempty"` + Network string `yaml:"network,omitempty" json:"network,omitempty"` + Target string `yaml:"target,omitempty" json:"target,omitempty"` + Secrets []ServiceSecretConfig `yaml:"secrets,omitempty" json:"secrets,omitempty"` + Tags StringList `yaml:"tags,omitempty" json:"tags,omitempty"` + Platforms StringList `yaml:"platforms,omitempty" json:"platforms,omitempty"` + Privileged bool `yaml:"privileged,omitempty" json:"privileged,omitempty"` + + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // BlkioConfig define blkio config type BlkioConfig struct { - Weight uint16 `yaml:",omitempty" json:"weight,omitempty"` - WeightDevice []WeightDevice `mapstructure:"weight_device" yaml:",omitempty" json:"weight_device,omitempty"` - DeviceReadBps []ThrottleDevice `mapstructure:"device_read_bps" yaml:",omitempty" json:"device_read_bps,omitempty"` - DeviceReadIOps []ThrottleDevice `mapstructure:"device_read_iops" yaml:",omitempty" json:"device_read_iops,omitempty"` - DeviceWriteBps []ThrottleDevice `mapstructure:"device_write_bps" yaml:",omitempty" json:"device_write_bps,omitempty"` - DeviceWriteIOps []ThrottleDevice `mapstructure:"device_write_iops" yaml:",omitempty" json:"device_write_iops,omitempty"` + Weight uint16 `yaml:"weight,omitempty" json:"weight,omitempty"` + WeightDevice []WeightDevice `yaml:"weight_device,omitempty" json:"weight_device,omitempty"` + DeviceReadBps []ThrottleDevice `yaml:"device_read_bps,omitempty" json:"device_read_bps,omitempty"` + DeviceReadIOps []ThrottleDevice `yaml:"device_read_iops,omitempty" json:"device_read_iops,omitempty"` + DeviceWriteBps []ThrottleDevice `yaml:"device_write_bps,omitempty" json:"device_write_bps,omitempty"` + DeviceWriteIOps []ThrottleDevice `yaml:"device_write_iops,omitempty" json:"device_write_iops,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // WeightDevice is a structure that holds device:weight pair @@ -334,7 +351,7 @@ type WeightDevice struct { Path string Weight uint16 - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // ThrottleDevice is a structure that holds device:rate_per_second pair @@ -342,7 +359,7 @@ type ThrottleDevice struct { Path string Rate UnitBytes - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // ShellCommand is a string or list of string args. @@ -562,37 +579,37 @@ func (h HostsList) MarshalJSON() ([]byte, error) { // LoggingConfig the logging configuration for a service type LoggingConfig struct { - Driver string `yaml:",omitempty" json:"driver,omitempty"` - Options map[string]string `yaml:",omitempty" json:"options,omitempty"` + Driver string `yaml:"driver,omitempty" json:"driver,omitempty"` + Options map[string]string `yaml:"options,omitempty" json:"options,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // DeployConfig the deployment configuration for a service type DeployConfig struct { - Mode string `yaml:",omitempty" json:"mode,omitempty"` - Replicas *uint64 `yaml:",omitempty" json:"replicas,omitempty"` - Labels Labels `yaml:",omitempty" json:"labels,omitempty"` - UpdateConfig *UpdateConfig `mapstructure:"update_config" yaml:"update_config,omitempty" json:"update_config,omitempty"` - RollbackConfig *UpdateConfig `mapstructure:"rollback_config" yaml:"rollback_config,omitempty" json:"rollback_config,omitempty"` - Resources Resources `yaml:",omitempty" json:"resources,omitempty"` - RestartPolicy *RestartPolicy `mapstructure:"restart_policy" yaml:"restart_policy,omitempty" json:"restart_policy,omitempty"` - Placement Placement `yaml:",omitempty" json:"placement,omitempty"` - EndpointMode string `mapstructure:"endpoint_mode" yaml:"endpoint_mode,omitempty" json:"endpoint_mode,omitempty"` + Mode string `yaml:"mode,omitempty" json:"mode,omitempty"` + Replicas *uint64 `yaml:"replicas,omitempty" json:"replicas,omitempty"` + Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"` + UpdateConfig *UpdateConfig `yaml:"update_config,omitempty" json:"update_config,omitempty"` + RollbackConfig *UpdateConfig `yaml:"rollback_config,omitempty" json:"rollback_config,omitempty"` + Resources Resources `yaml:"resources,omitempty" json:"resources,omitempty"` + RestartPolicy *RestartPolicy `yaml:"restart_policy,omitempty" json:"restart_policy,omitempty"` + Placement Placement `yaml:"placement,omitempty" json:"placement,omitempty"` + EndpointMode string `yaml:"endpoint_mode,omitempty" json:"endpoint_mode,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // HealthCheckConfig the healthcheck configuration for a service type HealthCheckConfig struct { - Test HealthCheckTest `yaml:",omitempty" json:"test,omitempty"` - Timeout *Duration `yaml:",omitempty" json:"timeout,omitempty"` - Interval *Duration `yaml:",omitempty" json:"interval,omitempty"` - Retries *uint64 `yaml:",omitempty" json:"retries,omitempty"` - StartPeriod *Duration `mapstructure:"start_period" yaml:"start_period,omitempty" json:"start_period,omitempty"` - Disable bool `yaml:",omitempty" json:"disable,omitempty"` + Test HealthCheckTest `yaml:"test,omitempty" json:"test,omitempty"` + Timeout *Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"` + Interval *Duration `yaml:"interval,omitempty" json:"interval,omitempty"` + Retries *uint64 `yaml:"retries,omitempty" json:"retries,omitempty"` + StartPeriod *Duration `yaml:"start_period,omitempty" json:"start_period,omitempty"` + Disable bool `yaml:"disable,omitempty" json:"disable,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // HealthCheckTest is the command run to test the health of a service @@ -600,49 +617,49 @@ type HealthCheckTest []string // UpdateConfig the service update configuration type UpdateConfig struct { - Parallelism *uint64 `yaml:",omitempty" json:"parallelism,omitempty"` - Delay Duration `yaml:",omitempty" json:"delay,omitempty"` - FailureAction string `mapstructure:"failure_action" yaml:"failure_action,omitempty" json:"failure_action,omitempty"` - Monitor Duration `yaml:",omitempty" json:"monitor,omitempty"` - MaxFailureRatio float32 `mapstructure:"max_failure_ratio" yaml:"max_failure_ratio,omitempty" json:"max_failure_ratio,omitempty"` - Order string `yaml:",omitempty" json:"order,omitempty"` + Parallelism *uint64 `yaml:"parallelism,omitempty" json:"parallelism,omitempty"` + Delay Duration `yaml:"delay,omitempty" json:"delay,omitempty"` + FailureAction string `yaml:"failure_action,omitempty" json:"failure_action,omitempty"` + Monitor Duration `yaml:"monitor,omitempty" json:"monitor,omitempty"` + MaxFailureRatio float32 `yaml:"max_failure_ratio,omitempty" json:"max_failure_ratio,omitempty"` + Order string `yaml:"order,omitempty" json:"order,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // Resources the resource limits and reservations type Resources struct { - Limits *Resource `yaml:",omitempty" json:"limits,omitempty"` - Reservations *Resource `yaml:",omitempty" json:"reservations,omitempty"` + Limits *Resource `yaml:"limits,omitempty" json:"limits,omitempty"` + Reservations *Resource `yaml:"reservations,omitempty" json:"reservations,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // Resource is a resource to be limited or reserved type Resource struct { // TODO: types to convert from units and ratios - NanoCPUs string `mapstructure:"cpus" yaml:"cpus,omitempty" json:"cpus,omitempty"` - MemoryBytes UnitBytes `mapstructure:"memory" yaml:"memory,omitempty" json:"memory,omitempty"` - PIds int64 `mapstructure:"pids" yaml:"pids,omitempty" json:"pids,omitempty"` - Devices []DeviceRequest `mapstructure:"devices" yaml:"devices,omitempty" json:"devices,omitempty"` - GenericResources []GenericResource `mapstructure:"generic_resources" yaml:"generic_resources,omitempty" json:"generic_resources,omitempty"` + NanoCPUs string `yaml:"cpus,omitempty" json:"cpus,omitempty"` + MemoryBytes UnitBytes `yaml:"memory,omitempty" json:"memory,omitempty"` + Pids int64 `yaml:"pids,omitempty" json:"pids,omitempty"` + Devices []DeviceRequest `yaml:"devices,omitempty" json:"devices,omitempty"` + GenericResources []GenericResource `yaml:"generic_resources,omitempty" json:"generic_resources,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } type DeviceRequest struct { - Capabilities []string `mapstructure:"capabilities" yaml:"capabilities,omitempty" json:"capabilities,omitempty"` - Driver string `mapstructure:"driver" yaml:"driver,omitempty" json:"driver,omitempty"` - Count int64 `mapstructure:"count" yaml:"count,omitempty" json:"count,omitempty"` - IDs []string `mapstructure:"device_ids" yaml:"device_ids,omitempty" json:"device_ids,omitempty"` + Capabilities []string `yaml:"capabilities,omitempty" json:"capabilities,omitempty"` + Driver string `yaml:"driver,omitempty" json:"driver,omitempty"` + Count int64 `yaml:"count,omitempty" json:"count,omitempty"` + IDs []string `yaml:"device_ids,omitempty" json:"device_ids,omitempty"` } // GenericResource represents a "user defined" resource which can // only be an integer (e.g: SSD=3) for a service type GenericResource struct { - DiscreteResourceSpec *DiscreteGenericResource `mapstructure:"discrete_resource_spec" yaml:"discrete_resource_spec,omitempty" json:"discrete_resource_spec,omitempty"` + DiscreteResourceSpec *DiscreteGenericResource `yaml:"discrete_resource_spec,omitempty" json:"discrete_resource_spec,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // DiscreteGenericResource represents a "user defined" resource which is defined @@ -653,7 +670,7 @@ type DiscreteGenericResource struct { Kind string `json:"kind"` Value int64 `json:"value"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // UnitBytes is the bytes type @@ -671,50 +688,50 @@ func (u UnitBytes) MarshalJSON() ([]byte, error) { // RestartPolicy the service restart policy type RestartPolicy struct { - Condition string `yaml:",omitempty" json:"condition,omitempty"` - Delay *Duration `yaml:",omitempty" json:"delay,omitempty"` - MaxAttempts *uint64 `mapstructure:"max_attempts" yaml:"max_attempts,omitempty" json:"max_attempts,omitempty"` - Window *Duration `yaml:",omitempty" json:"window,omitempty"` + Condition string `yaml:"condition,omitempty" json:"condition,omitempty"` + Delay *Duration `yaml:"delay,omitempty" json:"delay,omitempty"` + MaxAttempts *uint64 `yaml:"max_attempts,omitempty" json:"max_attempts,omitempty"` + Window *Duration `yaml:"window,omitempty" json:"window,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // Placement constraints for the service type Placement struct { - Constraints []string `yaml:",omitempty" json:"constraints,omitempty"` - Preferences []PlacementPreferences `yaml:",omitempty" json:"preferences,omitempty"` - MaxReplicas uint64 `mapstructure:"max_replicas_per_node" yaml:"max_replicas_per_node,omitempty" json:"max_replicas_per_node,omitempty"` + Constraints []string `yaml:"constraints,omitempty" json:"constraints,omitempty"` + Preferences []PlacementPreferences `yaml:"preferences,omitempty" json:"preferences,omitempty"` + MaxReplicas uint64 `yaml:"max_replicas_per_node,omitempty" json:"max_replicas_per_node,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // PlacementPreferences is the preferences for a service placement type PlacementPreferences struct { - Spread string `yaml:",omitempty" json:"spread,omitempty"` + Spread string `yaml:"spread,omitempty" json:"spread,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // ServiceNetworkConfig is the network configuration for a service type ServiceNetworkConfig struct { - Priority int `yaml:",omitempty" json:"priority,omitempty"` - Aliases []string `yaml:",omitempty" json:"aliases,omitempty"` - Ipv4Address string `mapstructure:"ipv4_address" yaml:"ipv4_address,omitempty" json:"ipv4_address,omitempty"` - Ipv6Address string `mapstructure:"ipv6_address" yaml:"ipv6_address,omitempty" json:"ipv6_address,omitempty"` - LinkLocalIPs []string `mapstructure:"link_local_ips" yaml:"link_local_ips,omitempty" json:"link_local_ips,omitempty"` + Priority int `yaml:"priority,omitempty" json:"priority,omitempty"` + Aliases []string `yaml:"aliases,omitempty" json:"aliases,omitempty"` + Ipv4Address string `yaml:"ipv4_address,omitempty" json:"ipv4_address,omitempty"` + Ipv6Address string `yaml:"ipv6_address,omitempty" json:"ipv6_address,omitempty"` + LinkLocalIPs []string `yaml:"link_local_ips,omitempty" json:"link_local_ips,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // ServicePortConfig is the port configuration for a service type ServicePortConfig struct { - Mode string `yaml:",omitempty" json:"mode,omitempty"` - HostIP string `mapstructure:"host_ip" yaml:"host_ip,omitempty" json:"host_ip,omitempty"` - Target uint32 `yaml:",omitempty" json:"target,omitempty"` - Published string `yaml:",omitempty" json:"published,omitempty"` - Protocol string `yaml:",omitempty" json:"protocol,omitempty"` + Mode string `yaml:"mode,omitempty" json:"mode,omitempty"` + HostIP string `yaml:"host_ip,omitempty" json:"host_ip,omitempty"` + Target uint32 `yaml:"target,omitempty" json:"target,omitempty"` + Published string `yaml:"published,omitempty" json:"published,omitempty"` + Protocol string `yaml:"protocol,omitempty" json:"protocol,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // ParsePortConfig parse short syntax for service port configuration @@ -758,16 +775,16 @@ func convertPortToPortConfig(port nat.Port, portBindings map[nat.Port][]nat.Port // ServiceVolumeConfig are references to a volume used by a service type ServiceVolumeConfig struct { - Type string `yaml:",omitempty" json:"type,omitempty"` - Source string `yaml:",omitempty" json:"source,omitempty"` - Target string `yaml:",omitempty" json:"target,omitempty"` - ReadOnly bool `mapstructure:"read_only" yaml:"read_only,omitempty" json:"read_only,omitempty"` - Consistency string `yaml:",omitempty" json:"consistency,omitempty"` - Bind *ServiceVolumeBind `yaml:",omitempty" json:"bind,omitempty"` - Volume *ServiceVolumeVolume `yaml:",omitempty" json:"volume,omitempty"` - Tmpfs *ServiceVolumeTmpfs `yaml:",omitempty" json:"tmpfs,omitempty"` + Type string `yaml:"type,omitempty" json:"type,omitempty"` + Source string `yaml:"source,omitempty" json:"source,omitempty"` + Target string `yaml:"target,omitempty" json:"target,omitempty"` + ReadOnly bool `yaml:"read_only,omitempty" json:"read_only,omitempty"` + Consistency string `yaml:"consistency,omitempty" json:"consistency,omitempty"` + Bind *ServiceVolumeBind `yaml:"bind,omitempty" json:"bind,omitempty"` + Volume *ServiceVolumeVolume `yaml:"volume,omitempty" json:"volume,omitempty"` + Tmpfs *ServiceVolumeTmpfs `yaml:"tmpfs,omitempty" json:"tmpfs,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // String render ServiceVolumeConfig as a volume string, one can parse back using loader.ParseVolume @@ -807,11 +824,11 @@ const ( // ServiceVolumeBind are options for a service volume of type bind type ServiceVolumeBind struct { - SELinux string `mapstructure:"selinux" yaml:",omitempty" json:"selinux,omitempty"` - Propagation string `yaml:",omitempty" json:"propagation,omitempty"` - CreateHostPath bool `mapstructure:"create_host_path" yaml:"create_host_path,omitempty" json:"create_host_path,omitempty"` + SELinux string `yaml:"selinux,omitempty" json:"selinux,omitempty"` + Propagation string `yaml:"propagation,omitempty" json:"propagation,omitempty"` + CreateHostPath bool `yaml:"create_host_path,omitempty" json:"create_host_path,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // SELinux represents the SELinux re-labeling options. @@ -840,29 +857,29 @@ const ( // ServiceVolumeVolume are options for a service volume of type volume type ServiceVolumeVolume struct { - NoCopy bool `mapstructure:"nocopy" yaml:"nocopy,omitempty" json:"nocopy,omitempty"` + NoCopy bool `yaml:"nocopy,omitempty" json:"nocopy,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // ServiceVolumeTmpfs are options for a service volume of type tmpfs type ServiceVolumeTmpfs struct { - Size UnitBytes `yaml:",omitempty" json:"size,omitempty"` + Size UnitBytes `yaml:"size,omitempty" json:"size,omitempty"` - Mode uint32 `yaml:",omitempty" json:"mode,omitempty"` + Mode uint32 `yaml:"mode,omitempty" json:"mode,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // FileReferenceConfig for a reference to a swarm file object type FileReferenceConfig struct { - Source string `yaml:",omitempty" json:"source,omitempty"` - Target string `yaml:",omitempty" json:"target,omitempty"` - UID string `yaml:",omitempty" json:"uid,omitempty"` - GID string `yaml:",omitempty" json:"gid,omitempty"` - Mode *uint32 `yaml:",omitempty" json:"mode,omitempty"` + Source string `yaml:"source,omitempty" json:"source,omitempty"` + Target string `yaml:"target,omitempty" json:"target,omitempty"` + UID string `yaml:"uid,omitempty" json:"uid,omitempty"` + GID string `yaml:"gid,omitempty" json:"gid,omitempty"` + Mode *uint32 `yaml:"mode,omitempty" json:"mode,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // ServiceConfigObjConfig is the config obj configuration for a service @@ -873,11 +890,11 @@ type ServiceSecretConfig FileReferenceConfig // UlimitsConfig the ulimit configuration type UlimitsConfig struct { - Single int `yaml:",omitempty" json:"single,omitempty"` - Soft int `yaml:",omitempty" json:"soft,omitempty"` - Hard int `yaml:",omitempty" json:"hard,omitempty"` + Single int `yaml:"single,omitempty" json:"single,omitempty"` + Soft int `yaml:"soft,omitempty" json:"soft,omitempty"` + Hard int `yaml:"hard,omitempty" json:"hard,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // MarshalYAML makes UlimitsConfig implement yaml.Marshaller @@ -905,51 +922,51 @@ func (u *UlimitsConfig) MarshalJSON() ([]byte, error) { // NetworkConfig for a network type NetworkConfig struct { - Name string `yaml:",omitempty" json:"name,omitempty"` - Driver string `yaml:",omitempty" json:"driver,omitempty"` - DriverOpts map[string]string `mapstructure:"driver_opts" yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"` - Ipam IPAMConfig `yaml:",omitempty" json:"ipam,omitempty"` - External External `yaml:",omitempty" json:"external,omitempty"` - Internal bool `yaml:",omitempty" json:"internal,omitempty"` - Attachable bool `yaml:",omitempty" json:"attachable,omitempty"` - Labels Labels `yaml:",omitempty" json:"labels,omitempty"` - EnableIPv6 bool `mapstructure:"enable_ipv6" yaml:"enable_ipv6,omitempty" json:"enable_ipv6,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Name string `yaml:"name,omitempty" json:"name,omitempty"` + Driver string `yaml:"driver,omitempty" json:"driver,omitempty"` + DriverOpts map[string]string `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"` + Ipam IPAMConfig `yaml:"ipam,omitempty" json:"ipam,omitempty"` + External External `yaml:"external,omitempty" json:"external,omitempty"` + Internal bool `yaml:"internal,omitempty" json:"internal,omitempty"` + Attachable bool `yaml:"attachable,omitempty" json:"attachable,omitempty"` + Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"` + EnableIPv6 bool `yaml:"enable_ipv6,omitempty" json:"enable_ipv6,omitempty"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // IPAMConfig for a network type IPAMConfig struct { - Driver string `yaml:",omitempty" json:"driver,omitempty"` - Config []*IPAMPool `yaml:",omitempty" json:"config,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Driver string `yaml:"driver,omitempty" json:"driver,omitempty"` + Config []*IPAMPool `yaml:"config,omitempty" json:"config,omitempty"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // IPAMPool for a network type IPAMPool struct { - Subnet string `yaml:",omitempty" json:"subnet,omitempty"` - Gateway string `yaml:",omitempty" json:"gateway,omitempty"` - IPRange string `mapstructure:"ip_range" yaml:"ip_range,omitempty" json:"ip_range,omitempty"` - AuxiliaryAddresses map[string]string `mapstructure:"aux_addresses" yaml:"aux_addresses,omitempty" json:"aux_addresses,omitempty"` + Subnet string `yaml:"subnet,omitempty" json:"subnet,omitempty"` + Gateway string `yaml:"gateway,omitempty" json:"gateway,omitempty"` + IPRange string `yaml:"ip_range,omitempty" json:"ip_range,omitempty"` + AuxiliaryAddresses map[string]string `yaml:"aux_addresses,omitempty" json:"aux_addresses,omitempty"` Extensions map[string]interface{} `yaml:",inline" json:"-"` } // VolumeConfig for a volume type VolumeConfig struct { - Name string `yaml:",omitempty" json:"name,omitempty"` - Driver string `yaml:",omitempty" json:"driver,omitempty"` - DriverOpts map[string]string `mapstructure:"driver_opts" yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"` - External External `yaml:",omitempty" json:"external,omitempty"` - Labels Labels `yaml:",omitempty" json:"labels,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Name string `yaml:"name,omitempty" json:"name,omitempty"` + Driver string `yaml:"driver,omitempty" json:"driver,omitempty"` + DriverOpts map[string]string `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"` + External External `yaml:"external,omitempty" json:"external,omitempty"` + Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // External identifies a Volume or Network as a reference to a resource that is // not managed, and should already exist. // External.name is deprecated and replaced by Volume.name type External struct { - Name string `yaml:",omitempty" json:"name,omitempty"` - External bool `yaml:",omitempty" json:"external,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Name string `yaml:"name,omitempty" json:"name,omitempty"` + External bool `yaml:"external,omitempty" json:"external,omitempty"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // MarshalYAML makes External implement yaml.Marshaller @@ -970,23 +987,23 @@ func (e External) MarshalJSON() ([]byte, error) { // CredentialSpecConfig for credential spec on Windows type CredentialSpecConfig struct { - Config string `yaml:",omitempty" json:"config,omitempty"` // Config was added in API v1.40 - File string `yaml:",omitempty" json:"file,omitempty"` - Registry string `yaml:",omitempty" json:"registry,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Config string `yaml:"config,omitempty" json:"config,omitempty"` // Config was added in API v1.40 + File string `yaml:"file,omitempty" json:"file,omitempty"` + Registry string `yaml:"registry,omitempty" json:"registry,omitempty"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } // FileObjectConfig is a config type for a file used by a service type FileObjectConfig struct { - Name string `yaml:",omitempty" json:"name,omitempty"` - File string `yaml:",omitempty" json:"file,omitempty"` - Environment string `yaml:",omitempty" json:"environment,omitempty"` - External External `yaml:",omitempty" json:"external,omitempty"` - Labels Labels `yaml:",omitempty" json:"labels,omitempty"` - Driver string `yaml:",omitempty" json:"driver,omitempty"` - DriverOpts map[string]string `mapstructure:"driver_opts" yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"` - TemplateDriver string `mapstructure:"template_driver" yaml:"template_driver,omitempty" json:"template_driver,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Name string `yaml:"name,omitempty" json:"name,omitempty"` + File string `yaml:"file,omitempty" json:"file,omitempty"` + Environment string `yaml:"environment,omitempty" json:"environment,omitempty"` + External External `yaml:"external,omitempty" json:"external,omitempty"` + Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"` + Driver string `yaml:"driver,omitempty" json:"driver,omitempty"` + DriverOpts map[string]string `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"` + TemplateDriver string `yaml:"template_driver,omitempty" json:"template_driver,omitempty"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } const ( @@ -1003,14 +1020,14 @@ const ( type DependsOnConfig map[string]ServiceDependency type ServiceDependency struct { - Condition string `yaml:",omitempty" json:"condition,omitempty"` - Restart bool `yaml:",omitempty" json:"restart,omitempty"` - Extensions Extensions `mapstructure:"#extensions" yaml:",inline" json:"-"` + Condition string `yaml:"condition,omitempty" json:"condition,omitempty"` + Restart bool `yaml:"restart,omitempty" json:"restart,omitempty"` + Extensions Extensions `yaml:"#extensions,inline" json:"-"` } type ExtendsConfig struct { - File string `yaml:",omitempty" json:"file,omitempty"` - Service string `yaml:",omitempty" json:"service,omitempty"` + File string `yaml:"file,omitempty" json:"file,omitempty"` + Service string `yaml:"service,omitempty" json:"service,omitempty"` } // SecretConfig for a secret diff --git a/vendor/modules.txt b/vendor/modules.txt index ca7f112f..68b985cf 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -131,7 +131,7 @@ github.com/cenkalti/backoff/v4 github.com/cespare/xxhash/v2 # github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e ## explicit -# github.com/compose-spec/compose-go v1.13.4 +# github.com/compose-spec/compose-go v1.14.0 ## explicit; go 1.19 github.com/compose-spec/compose-go/cli github.com/compose-spec/compose-go/consts @@ -141,6 +141,7 @@ github.com/compose-spec/compose-go/interpolation github.com/compose-spec/compose-go/loader github.com/compose-spec/compose-go/schema github.com/compose-spec/compose-go/template +github.com/compose-spec/compose-go/tree github.com/compose-spec/compose-go/types github.com/compose-spec/compose-go/utils # github.com/containerd/console v1.0.3 @@ -809,7 +810,7 @@ golang.org/x/net/trace ## explicit; go 1.17 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sync v0.1.0 +# golang.org/x/sync v0.2.0 ## explicit golang.org/x/sync/errgroup golang.org/x/sync/semaphore