diff --git a/go.mod b/go.mod index 906630f2..e36289cf 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/bugsnag/panicwrap v1.2.0 // indirect github.com/cenkalti/backoff v2.1.1+incompatible // indirect github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e // indirect - github.com/compose-spec/compose-go v1.0.8 + github.com/compose-spec/compose-go v1.2.1 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.6.1 github.com/docker/cli v20.10.12+incompatible diff --git a/go.sum b/go.sum index 2752e0d0..795a8fc6 100644 --- a/go.sum +++ b/go.sum @@ -280,10 +280,8 @@ github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/compose-spec/compose-go v1.0.8 h1:fgT7mYYu5Sp37i2lUIAAvwJpkAHk6dP5ITHy/LlutUk= -github.com/compose-spec/compose-go v1.0.8/go.mod h1:REnCbBugoIdHB7S1sfkN/aJ7AJpNApGNjNiVjA9L8x4= -github.com/compose-spec/godotenv v1.1.1 h1:lp+WpAInnw06YN9sV/XLUOV/9z4C+6wjJdWlrdVac7o= -github.com/compose-spec/godotenv v1.1.1/go.mod h1:zF/3BOa18Z24tts5qnO/E9YURQanJTBUf7nlcCTNsyc= +github.com/compose-spec/compose-go v1.2.1 h1:8+DAP7Mt/Ohl5y6YbZdilLMvIhMxvuSZcNZyywjQmJE= +github.com/compose-spec/compose-go v1.2.1/go.mod h1:pAy7Mikpeft4pxkFU565/DRHEbDfR84G6AQuiL+Hdg8= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= @@ -966,8 +964,8 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ= github.com/moby/buildkit v0.10.0-rc2.0.20220308185020-fdecd0ae108b h1:plbnJxjht8Z6D3c/ga79D1+VaA/IUfNVp08J3lcDgI8= @@ -2042,8 +2040,9 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk= +gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vendor/github.com/compose-spec/compose-go/consts/consts.go b/vendor/github.com/compose-spec/compose-go/consts/consts.go new file mode 100644 index 00000000..bf5cc9f1 --- /dev/null +++ b/vendor/github.com/compose-spec/compose-go/consts/consts.go @@ -0,0 +1,23 @@ +/* + 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 consts + +const ( + ComposeProjectName = "COMPOSE_PROJECT_NAME" + ComposePathSeparator = "COMPOSE_PATH_SEPARATOR" + ComposeFilePath = "COMPOSE_FILE" +) diff --git a/vendor/github.com/compose-spec/godotenv/LICENCE b/vendor/github.com/compose-spec/compose-go/dotenv/LICENSE similarity index 99% rename from vendor/github.com/compose-spec/godotenv/LICENCE rename to vendor/github.com/compose-spec/compose-go/dotenv/LICENSE index e7ddd51b..9390caf6 100644 --- a/vendor/github.com/compose-spec/godotenv/LICENCE +++ b/vendor/github.com/compose-spec/compose-go/dotenv/LICENSE @@ -20,4 +20,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/vendor/github.com/compose-spec/godotenv/godotenv.go b/vendor/github.com/compose-spec/compose-go/dotenv/godotenv.go similarity index 98% rename from vendor/github.com/compose-spec/godotenv/godotenv.go rename to vendor/github.com/compose-spec/compose-go/dotenv/godotenv.go index 4045e345..479831aa 100644 --- a/vendor/github.com/compose-spec/godotenv/godotenv.go +++ b/vendor/github.com/compose-spec/compose-go/dotenv/godotenv.go @@ -1,4 +1,4 @@ -// Package godotenv is a go port of the ruby dotenv library (https://github.com/bkeepers/dotenv) +// Package dotenv is a go port of the ruby dotenv library (https://github.com/bkeepers/dotenv) // // Examples/readme can be found on the github page at https://github.com/joho/godotenv // @@ -11,7 +11,7 @@ // godotenv.Load() // // and all the env vars declared in .env will be available through os.Getenv("SOME_ENV_VAR") -package godotenv +package dotenv import ( "errors" diff --git a/vendor/github.com/compose-spec/godotenv/parser.go b/vendor/github.com/compose-spec/compose-go/dotenv/parser.go similarity index 93% rename from vendor/github.com/compose-spec/godotenv/parser.go rename to vendor/github.com/compose-spec/compose-go/dotenv/parser.go index 1d144de0..85ed2c00 100644 --- a/vendor/github.com/compose-spec/godotenv/parser.go +++ b/vendor/github.com/compose-spec/compose-go/dotenv/parser.go @@ -1,4 +1,4 @@ -package godotenv +package dotenv import ( "bytes" @@ -41,9 +41,9 @@ func parseBytes(src []byte, out map[string]string, lookupFn LookupFn) error { value, ok := lookupFn(key) if ok { out[key] = value - cutset = left - continue } + cutset = left + continue } value, left, err := extractVarValue(left, out, lookupFn) @@ -132,14 +132,14 @@ func extractVarValue(src []byte, envMap map[string]string, lookupFn LookupFn) (v // unquoted value - read until new line end := bytes.IndexFunc(src, isNewLine) var rest []byte - var value string if end < 0 { - value := strings.TrimRightFunc(string(src), unicode.IsSpace) - rest = nil - return expandVariables(value, envMap, lookupFn), rest, nil + value := strings.Split(string(src), "#")[0] // Remove inline comments on unquoted lines + value = strings.TrimRightFunc(value, unicode.IsSpace) + return expandVariables(value, envMap, lookupFn), nil, nil } - value = strings.TrimRightFunc(string(src[0:end]), unicode.IsSpace) + value := strings.Split(string(src[0:end]), "#")[0] + value = strings.TrimRightFunc(value, unicode.IsSpace) rest = src[end:] return expandVariables(value, envMap, lookupFn), rest, nil } @@ -228,7 +228,6 @@ func isSpace(r rune) bool { return false } - // isNewLine reports whether the rune is a new line character func isNewLine(r rune) bool { return r == '\n' 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 2619016a..9c36e6d8 100644 --- a/vendor/github.com/compose-spec/compose-go/interpolation/interpolation.go +++ b/vendor/github.com/compose-spec/compose-go/interpolation/interpolation.go @@ -115,7 +115,7 @@ func newPathError(path Path, err error) error { return nil case *template.InvalidTemplateError: return errors.Errorf( - "invalid interpolation format for %s: %#v. You may need to escape any $ with another $.", + "invalid interpolation format for %s: %#v. You may need to escape any $ with another $", path, err.Template) default: return errors.Wrapf(err, "error while interpolating %s", path) 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 529d28b6..4f17450e 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 @@ -1,3 +1,4 @@ +name: Full_Example_project_name services: foo: @@ -6,6 +7,8 @@ services: dockerfile: Dockerfile args: foo: bar + ssh: + - default target: foo network: foo cache_from: @@ -85,6 +88,10 @@ services: - spread: node.labels.az endpoint_mode: dnsrr + device_cgroup_rules: + - "c 1:3 mr" + - "a 7:* rmw" + devices: - "/dev/ttyUSB0:/dev/ttyUSB0" 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 76839a6d..97a19f5d 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/interpolate.go +++ b/vendor/github.com/compose-spec/compose-go/loader/interpolate.go @@ -21,7 +21,6 @@ import ( "strings" interp "github.com/compose-spec/compose-go/interpolation" - "github.com/compose-spec/compose-go/types" "github.com/pkg/errors" ) @@ -53,7 +52,6 @@ var interpolateTypeCastMapping = map[interp.Path]interp.Cast{ servicePath("oom_score_adj"): toInt64, servicePath("pids_limit"): toInt64, servicePath("ports", interp.PathMatchList, "target"): toInt, - servicePath("ports", interp.PathMatchList, "published"): toInt, servicePath("privileged"): toBoolean, servicePath("read_only"): toBoolean, servicePath("scale"): toInt, @@ -94,19 +92,11 @@ func toInt64(value string) (interface{}, error) { } func toUnitBytes(value string) (interface{}, error) { - i, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return nil, err - } - return types.UnitBytes(i), nil + return transformSize(value) } func toDuration(value string) (interface{}, error) { - i, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return nil, err - } - return types.Duration(i), nil + return transformStringToDuration(value) } func toFloat(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 b55b0056..5aeeb214 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/loader.go +++ b/vendor/github.com/compose-spec/compose-go/loader/loader.go @@ -23,15 +23,18 @@ import ( "path" "path/filepath" "reflect" + "regexp" "sort" + "strconv" "strings" "time" + "github.com/compose-spec/compose-go/consts" + "github.com/compose-spec/compose-go/dotenv" interp "github.com/compose-spec/compose-go/interpolation" "github.com/compose-spec/compose-go/schema" "github.com/compose-spec/compose-go/template" "github.com/compose-spec/compose-go/types" - "github.com/compose-spec/godotenv" "github.com/docker/go-units" "github.com/mattn/go-shellwords" "github.com/mitchellh/mapstructure" @@ -58,8 +61,19 @@ type Options struct { Interpolate *interp.Options // Discard 'env_file' entries after resolving to 'environment' section discardEnvFiles bool - // Set project name - Name string + // Set project projectName + projectName string + // Indicates when the projectName was imperatively set or guessed from path + projectNameImperativelySet bool +} + +func (o *Options) SetProjectName(name string, imperativelySet bool) { + o.projectName = normalizeProjectName(name) + o.projectNameImperativelySet = imperativelySet +} + +func (o Options) GetProjectName() (string, bool) { + return o.projectName, o.projectNameImperativelySet } // serviceRef identifies a reference to a service. It's used to detect cyclic @@ -192,8 +206,17 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types. s.EnvFile = newEnvFiles } + projectName, projectNameImperativelySet := opts.GetProjectName() + model.Name = normalizeProjectName(model.Name) + if !projectNameImperativelySet && model.Name != "" { + projectName = model.Name + } + + if projectName != "" { + configDetails.Environment[consts.ComposeProjectName] = projectName + } project := &types.Project{ - Name: opts.Name, + Name: projectName, WorkingDir: configDetails.WorkingDir, Services: model.Services, Networks: model.Networks, @@ -221,6 +244,13 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types. return project, nil } +func normalizeProjectName(s string) string { + r := regexp.MustCompile("[a-z0-9_-]") + s = strings.ToLower(s) + s = strings.Join(r.FindAllString(s, -1), "") + return strings.TrimLeft(s, "_-") +} + func parseConfig(b []byte, opts *Options) (map[string]interface{}, error) { yml, err := ParseYAML(b) if err != nil { @@ -254,7 +284,14 @@ func loadSections(filename string, config map[string]interface{}, configDetails cfg := types.Config{ Filename: filename, } - + name := "" + if n, ok := config["name"]; ok { + name, ok = n.(string) + if !ok { + return nil, errors.New("project name must be a string") + } + } + cfg.Name = name cfg.Services, err = LoadServices(filename, getSection(config, "services"), configDetails.WorkingDir, configDetails.LookupEnv, opts) if err != nil { return nil, err @@ -280,10 +317,6 @@ func loadSections(filename string, config map[string]interface{}, configDetails if len(extensions) > 0 { cfg.Extensions = extensions } - if err != nil { - return nil, err - } - return &cfg, nil } @@ -357,6 +390,7 @@ func createTransformHook(additionalTransformers ...Transformer) mapstructure.Dec reflect.TypeOf(types.DependsOnConfig{}): transformDependsOnConfig, reflect.TypeOf(types.ExtendsConfig{}): transformExtendsConfig, reflect.TypeOf(types.DeviceRequest{}): transformServiceDeviceRequest, + reflect.TypeOf(types.SSHConfig{}): transformSSHConfig, } for _, transformer := range additionalTransformers { @@ -559,7 +593,7 @@ func resolveEnvironment(serviceConfig *types.ServiceConfig, workingDir string, l return err } defer file.Close() - fileVars, err := godotenv.ParseWithLookup(file, godotenv.LookupFn(lookupEnv)) + fileVars, err := dotenv.ParseWithLookup(file, dotenv.LookupFn(lookupEnv)) if err != nil { return err } @@ -817,6 +851,10 @@ var transformServicePort TransformerFunc = func(data interface{}) (interface{}, ports = append(ports, v) } case map[string]interface{}: + published := value["published"] + if v, ok := published.(int); ok { + value["published"] = strconv.Itoa(v) + } ports = append(ports, groupXFieldsIntoExtensions(value)) default: return data, errors.Errorf("invalid type %T for port", value) @@ -891,7 +929,7 @@ var transformDependsOnConfig TransformerFunc = func(data interface{}) (interface for _, serviceIntf := range value { service, ok := serviceIntf.(string) if !ok { - return data, errors.Errorf("invalid type %T for service depends_on element. Expected string.", value) + return data, errors.Errorf("invalid type %T for service depends_on elementn, expected string", value) } transformed[service] = map[string]interface{}{"condition": types.ServiceConditionStarted} } @@ -941,6 +979,35 @@ var transformServiceNetworkMap TransformerFunc = func(value interface{}) (interf return value, nil } +var transformSSHConfig TransformerFunc = func(data interface{}) (interface{}, error) { + switch value := data.(type) { + case map[string]interface{}: + var result []types.SSHKey + for key, val := range value { + if val == nil { + val = "" + } + result = append(result, types.SSHKey{ID: key, Path: val.(string)}) + } + return result, nil + case []interface{}: + var result []types.SSHKey + for _, v := range value { + key, val := transformValueToMapEntry(v.(string), "=", false) + result = append(result, types.SSHKey{ID: key, Path: val.(string)}) + } + return result, nil + case string: + if value == "" { + value = "default" + } + key, val := transformValueToMapEntry(value, "=", false) + result := []types.SSHKey{{ID: key, Path: val.(string)}} + return result, nil + } + return nil, errors.Errorf("expected a sting, map or a list, got %T: %#v", data, data) +} + var transformStringOrNumberList TransformerFunc = func(value interface{}) (interface{}, error) { list := value.([]interface{}) result := make([]string, len(list)) @@ -963,47 +1030,52 @@ var transformStringList TransformerFunc = func(data interface{}) (interface{}, e func transformMappingOrListFunc(sep string, allowNil bool) TransformerFunc { return func(data interface{}) (interface{}, error) { - return transformMappingOrList(data, sep, allowNil), nil + return transformMappingOrList(data, sep, allowNil) } } func transformListOrMappingFunc(sep string, allowNil bool) TransformerFunc { return func(data interface{}) (interface{}, error) { - return transformListOrMapping(data, sep, allowNil), nil + return transformListOrMapping(data, sep, allowNil) } } -func transformListOrMapping(listOrMapping interface{}, sep string, allowNil bool) interface{} { +func transformListOrMapping(listOrMapping interface{}, sep string, allowNil bool) (interface{}, error) { switch value := listOrMapping.(type) { case map[string]interface{}: - return toStringList(value, sep, allowNil) + return toStringList(value, sep, allowNil), nil case []interface{}: - return listOrMapping + return listOrMapping, nil } - panic(errors.Errorf("expected a map or a list, got %T: %#v", listOrMapping, listOrMapping)) + return nil, errors.Errorf("expected a map or a list, got %T: %#v", listOrMapping, listOrMapping) } -func transformMappingOrList(mappingOrList interface{}, sep string, allowNil bool) interface{} { +func transformMappingOrList(mappingOrList interface{}, sep string, allowNil bool) (interface{}, error) { switch value := mappingOrList.(type) { case map[string]interface{}: - return toMapStringString(value, allowNil) + return toMapStringString(value, allowNil), nil case []interface{}: result := make(map[string]interface{}) for _, value := range value { - parts := strings.SplitN(value.(string), sep, 2) - key := parts[0] - switch { - case len(parts) == 1 && allowNil: - result[key] = nil - case len(parts) == 1 && !allowNil: - result[key] = "" - default: - result[key] = parts[1] - } + key, val := transformValueToMapEntry(value.(string), sep, allowNil) + result[key] = val } - return result + return result, nil + } + return nil, errors.Errorf("expected a map or a list, got %T: %#v", mappingOrList, mappingOrList) +} + +func transformValueToMapEntry(value string, separator string, allowNil bool) (string, interface{}) { + parts := strings.SplitN(value, separator, 2) + key := parts[0] + switch { + case len(parts) == 1 && allowNil: + return key, nil + case len(parts) == 1 && !allowNil: + return key, "" + default: + return key, parts[1] } - panic(errors.Errorf("expected a map or a list, got %T: %#v", mappingOrList, mappingOrList)) } var transformShellCommand TransformerFunc = func(value interface{}) (interface{}, error) { @@ -1045,6 +1117,8 @@ var transformStringToDuration TransformerFunc = func(value interface{}) (interfa return value, err } return types.Duration(d), nil + case types.Duration: + return value, nil default: return value, errors.Errorf("invalid type %T for duration", value) } diff --git a/vendor/github.com/compose-spec/compose-go/loader/merge.go b/vendor/github.com/compose-spec/compose-go/loader/merge.go index b01c868c..f6138ca2 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/merge.go +++ b/vendor/github.com/compose-spec/compose-go/loader/merge.go @@ -53,6 +53,7 @@ func merge(configs []*types.Config) (*types.Config, error) { base := configs[0] for _, override := range configs[1:] { var err error + base.Name = mergeNames(base.Name, override.Name) base.Services, err = mergeServices(base.Services, override.Services) if err != nil { return base, errors.Wrapf(err, "cannot merge services from %s", override.Filename) @@ -81,6 +82,13 @@ func merge(configs []*types.Config) (*types.Config, error) { return base, nil } +func mergeNames(base, override string) string { + if override != "" { + return override + } + return base +} + func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig, error) { baseServices := mapByName(base) overrideServices := mapByName(override) @@ -154,7 +162,7 @@ func toServicePortConfigsMap(s interface{}) (map[interface{}]interface{}, error) m := map[interface{}]interface{}{} type port struct { target uint32 - published uint32 + published string ip string protocol string } @@ -291,7 +299,7 @@ func mergeLoggingConfig(dst, src reflect.Value) error { return nil } -//nolint: unparam +// nolint: unparam func mergeUlimitsConfig(dst, src reflect.Value) error { if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() { dst.Elem().Set(src.Elem()) @@ -299,7 +307,7 @@ func mergeUlimitsConfig(dst, src reflect.Value) error { return nil } -//nolint: unparam +// nolint: unparam func mergeServiceNetworkConfig(dst, src reflect.Value) error { if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() { dst.Elem().FieldByName("Aliases").Set(src.Elem().FieldByName("Aliases")) 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 23851ae3..4b98d624 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/normalize.go +++ b/vendor/github.com/compose-spec/compose-go/loader/normalize.go @@ -79,7 +79,7 @@ func normalize(project *types.Project, resolvePaths bool) error { if resolvePaths { s.Build.Context = localContext } - } else { + // } else { // might be a remote http/git context. Unfortunately supported "remote" syntax is highly ambiguous // in moby/moby and not defined by compose-spec, so let's assume runtime will check } 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 dd0f612e..f1e66cde 100644 --- a/vendor/github.com/compose-spec/compose-go/loader/volume.go +++ b/vendor/github.com/compose-spec/compose-go/loader/volume.go @@ -92,7 +92,7 @@ func populateFieldFromBuffer(char rune, buffer []rune, volume *types.ServiceVolu volume.Volume = &types.ServiceVolumeVolume{NoCopy: true} default: if isBindOption(option) { - volume.Bind = &types.ServiceVolumeBind{Propagation: option} + setBindOption(volume, option) } // ignore unknown options } @@ -109,13 +109,39 @@ var Propagations = []string{ types.PropagationSlave, } +type setBindOptionFunc func(bind *types.ServiceVolumeBind, option string) + +var bindOptions = map[string]setBindOptionFunc{ + types.PropagationRPrivate: setBindPropagation, + types.PropagationPrivate: setBindPropagation, + types.PropagationRShared: setBindPropagation, + types.PropagationShared: setBindPropagation, + types.PropagationRSlave: setBindPropagation, + types.PropagationSlave: setBindPropagation, + types.SELinuxShared: setBindSELinux, + types.SELinuxPrivate: setBindSELinux, +} + +func setBindPropagation(bind *types.ServiceVolumeBind, option string) { + bind.Propagation = option +} + +func setBindSELinux(bind *types.ServiceVolumeBind, option string) { + bind.SELinux = option +} + func isBindOption(option string) bool { - for _, propagation := range Propagations { - if option == propagation { - return true - } + _, ok := bindOptions[option] + + return ok +} + +func setBindOption(volume *types.ServiceVolumeConfig, option string) { + if volume.Bind == nil { + volume.Bind = &types.ServiceVolumeBind{} } - return false + + bindOptions[option](volume.Bind, option) } func populateType(volume *types.ServiceVolumeConfig) { 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 91bdb342..b2088998 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 @@ -8,7 +8,12 @@ "properties": { "version": { "type": "string", - "description": "Version of the Compose specification used. Tools not implementing required version MUST reject the configuration file." + "description": "declared for backward compatibility, ignored." + }, + + "name": { + "type": "string", + "description": "define the Compose project name, until user defines one explicitly." }, "services": { @@ -86,9 +91,13 @@ "context": {"type": "string"}, "dockerfile": {"type": "string"}, "args": {"$ref": "#/definitions/list_or_dict"}, + "ssh": {"$ref": "#/definitions/list_or_dict"}, "labels": {"$ref": "#/definitions/list_or_dict"}, "cache_from": {"type": "array", "items": {"type": "string"}}, + "cache_to": {"type": "array", "items": {"type": "string"}}, + "no_cache": {"type": "boolean"}, "network": {"type": "string"}, + "pull": {"type": "boolean"}, "target": {"type": "string"}, "shm_size": {"type": ["integer", "string"]}, "extra_hosts": {"$ref": "#/definitions/list_or_dict"}, @@ -318,7 +327,7 @@ "mode": {"type": "string"}, "host_ip": {"type": "string"}, "target": {"type": "integer"}, - "published": {"type": "integer"}, + "published": {"type": ["string", "integer"]}, "protocol": {"type": "string"} }, "additionalProperties": false, @@ -410,7 +419,8 @@ "type": "object", "properties": { "propagation": {"type": "string"}, - "create_host_path": {"type": "boolean"} + "create_host_path": {"type": "boolean"}, + "selinux": {"type": "string", "enum": ["z", "Z"]} }, "additionalProperties": false, "patternProperties": {"^x-": {}} @@ -519,7 +529,8 @@ "type": "object", "properties": { "cpus": {"type": ["number", "string"]}, - "memory": {"type": "string"} + "memory": {"type": "string"}, + "pids": {"type": "integer"} }, "additionalProperties": false, "patternProperties": {"^x-": {}} diff --git a/vendor/github.com/compose-spec/compose-go/schema/schema.go b/vendor/github.com/compose-spec/compose-go/schema/schema.go index cf14b399..af3cb0a3 100644 --- a/vendor/github.com/compose-spec/compose-go/schema/schema.go +++ b/vendor/github.com/compose-spec/compose-go/schema/schema.go @@ -27,11 +27,6 @@ import ( _ "embed" ) -const ( - defaultVersion = "1.0" - versionField = "version" -) - type portsFormatChecker struct{} func (checker portsFormatChecker) IsFormat(input interface{}) bool { 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 ecb7358b..22e4e95a 100644 --- a/vendor/github.com/compose-spec/compose-go/template/template.go +++ b/vendor/github.com/compose-spec/compose-go/template/template.go @@ -26,6 +26,7 @@ import ( var delimiter = "\\$" var substitutionNamed = "[_a-z][_a-z0-9]*" + var substitutionBraced = "[_a-z][_a-z0-9]*(?::?[-?](.*}|[^}]*))?" var patternString = fmt.Sprintf( @@ -60,15 +61,17 @@ type SubstituteFunc func(string, Mapping) (string, bool, error) // It accepts additional substitute function. func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, subsFuncs ...SubstituteFunc) (string, error) { if len(subsFuncs) == 0 { - subsFuncs = []SubstituteFunc{ - softDefault, - hardDefault, - requiredNonEmpty, - required, - } + subsFuncs = getDefaultSortedSubstitutionFunctions(template) } var err error result := pattern.ReplaceAllStringFunc(template, func(substring string) string { + closingBraceIndex := getFirstBraceClosingIndex(substring) + rest := "" + if closingBraceIndex > -1 { + rest = substring[closingBraceIndex+1:] + substring = substring[0 : closingBraceIndex+1] + } + matches := pattern.FindStringSubmatch(substring) groups := matchGroups(matches, pattern) if escaped := groups["escaped"]; escaped != "" { @@ -100,7 +103,11 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su if !applied { continue } - return value + interpolatedNested, err := SubstituteWith(rest, mapping, pattern, subsFuncs...) + if err != nil { + return "" + } + return value + interpolatedNested } } @@ -114,6 +121,42 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su return result, err } +func getDefaultSortedSubstitutionFunctions(template string, fns ...SubstituteFunc) []SubstituteFunc { + hyphenIndex := strings.IndexByte(template, '-') + questionIndex := strings.IndexByte(template, '?') + if hyphenIndex < 0 || hyphenIndex > questionIndex { + return []SubstituteFunc{ + requiredNonEmpty, + required, + softDefault, + hardDefault, + } + } + return []SubstituteFunc{ + softDefault, + hardDefault, + requiredNonEmpty, + required, + } +} + +func getFirstBraceClosingIndex(s string) int { + openVariableBraces := 0 + for i := 0; i < len(s); i++ { + if s[i] == '}' { + openVariableBraces-- + if openVariableBraces == 0 { + return i + } + } + if strings.HasPrefix(s[i:], "${") { + openVariableBraces++ + i++ + } + } + return -1 +} + // Substitute variables in the string with their values func Substitute(template string, mapping Mapping) (string, error) { return SubstituteWith(template, mapping, defaultPattern) 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 21127f49..b395363b 100644 --- a/vendor/github.com/compose-spec/compose-go/types/config.go +++ b/vendor/github.com/compose-spec/compose-go/types/config.go @@ -49,6 +49,7 @@ type ConfigFile struct { // Config is a full compose file configuration and model type Config struct { Filename string `yaml:"-" json:"-"` + Name string `yaml:",omitempty" json:"name,omitempty"` Services Services `json:"services"` Networks Networks `yaml:",omitempty" json:"networks,omitempty"` Volumes Volumes `yaml:",omitempty" json:"volumes,omitempty"` 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 6de8e61e..dc208ed5 100644 --- a/vendor/github.com/compose-spec/compose-go/types/project.go +++ b/vendor/github.com/compose-spec/compose-go/types/project.go @@ -29,7 +29,7 @@ import ( // Project is the result of loading a set of compose files type Project struct { - Name string `yaml:"-" json:"-"` + Name string `yaml:"name,omitempty" json:"name,omitempty"` WorkingDir string `yaml:"-" json:"-"` Services Services `json:"services"` Networks Networks `yaml:",omitempty" json:"networks,omitempty"` 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 c19d0ebf..ec4b0bc7 100644 --- a/vendor/github.com/compose-spec/compose-go/types/types.go +++ b/vendor/github.com/compose-spec/compose-go/types/types.go @@ -88,88 +88,90 @@ 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"` - 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"` - Command ShellCommand `yaml:",omitempty" json:"command,omitempty"` - 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"` - 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"` - Dockerfile string `yaml:"dockerfile,omitempty" json:"dockerfile,omitempty"` - DomainName string `mapstructure:"domainname" yaml:"domainname,omitempty" json:"domainname,omitempty"` - Entrypoint ShellCommand `yaml:",omitempty" json:"entrypoint,omitempty"` - 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"` - 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"` - 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"` - 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"` - 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"` + 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"` + 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"` + Command ShellCommand `yaml:",omitempty" json:"command,omitempty"` + 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"` + Dockerfile string `yaml:"dockerfile,omitempty" json:"dockerfile,omitempty"` + DomainName string `mapstructure:"domainname" yaml:"domainname,omitempty" json:"domainname,omitempty"` + Entrypoint ShellCommand `yaml:",omitempty" json:"entrypoint,omitempty"` + 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"` + 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"` + 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"` + 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"` + 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"` Extensions map[string]interface{} `yaml:",inline" json:"-"` } @@ -292,8 +294,12 @@ type BuildConfig struct { Context string `yaml:",omitempty" json:"context,omitempty"` Dockerfile string `yaml:",omitempty" json:"dockerfile,omitempty"` Args MappingWithEquals `yaml:",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"` + 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"` @@ -305,11 +311,11 @@ type BuildConfig struct { // BlkioConfig define blkio config type BlkioConfig struct { Weight uint16 `yaml:",omitempty" json:"weight,omitempty"` - WeightDevice []WeightDevice `yaml:",omitempty" json:"weight_device,omitempty"` - DeviceReadBps []ThrottleDevice `yaml:",omitempty" json:"device_read_bps,omitempty"` - DeviceReadIOps []ThrottleDevice `yaml:",omitempty" json:"device_read_iops,omitempty"` - DeviceWriteBps []ThrottleDevice `yaml:",omitempty" json:"device_write_bps,omitempty"` - DeviceWriteIOps []ThrottleDevice `yaml:",omitempty" json:"device_write_iops,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"` Extensions map[string]interface{} `yaml:",inline" json:"-"` } @@ -423,6 +429,39 @@ func (l Labels) Add(key, value string) Labels { return l } +type SSHKey struct { + ID string + Path string +} + +// SSHConfig is a mapping type for SSH build config +type SSHConfig []SSHKey + +func (s SSHConfig) Get(id string) (string, error) { + for _, sshKey := range s { + if sshKey.ID == id { + return sshKey.Path, nil + } + } + return "", fmt.Errorf("ID %s not found in SSH keys", id) +} + +// MarshalYAML makes SSHKey implement yaml.Marshaller +func (s SSHKey) MarshalYAML() (interface{}, error) { + if s.Path == "" { + return s.ID, nil + } + return fmt.Sprintf("%s: %s", s.ID, s.Path), nil +} + +// MarshalJSON makes SSHKey implement json.Marshaller +func (s SSHKey) MarshalJSON() ([]byte, error) { + if s.Path == "" { + return []byte(fmt.Sprintf(`"%s"`, s.ID)), nil + } + return []byte(fmt.Sprintf(`"%s": %s`, s.ID, s.Path)), nil +} + // MappingWithColon is a mapping type that can be converted from a list of // 'key: value' strings type MappingWithColon map[string]string @@ -493,6 +532,7 @@ 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"` @@ -579,7 +619,7 @@ 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 uint32 `yaml:",omitempty" json:"published,omitempty"` + Published string `yaml:",omitempty" json:"published,omitempty"` Protocol string `yaml:",omitempty" json:"protocol,omitempty"` Extensions map[string]interface{} `yaml:",inline" json:"-"` @@ -613,21 +653,13 @@ func ParsePortConfig(value string) ([]ServicePortConfig, error) { func convertPortToPortConfig(port nat.Port, portBindings map[nat.Port][]nat.PortBinding) ([]ServicePortConfig, error) { var portConfigs []ServicePortConfig for _, binding := range portBindings[port] { - startHostPort, endHostPort, err := nat.ParsePortRange(binding.HostPort) - - if err != nil && binding.HostPort != "" { - return nil, fmt.Errorf("invalid hostport binding (%s) for port (%s)", binding.HostPort, port.Port()) - } - - for i := startHostPort; i <= endHostPort; i++ { - portConfigs = append(portConfigs, ServicePortConfig{ - HostIP: binding.HostIP, - Protocol: strings.ToLower(port.Proto()), - Target: uint32(port.Int()), - Published: uint32(i), - Mode: "ingress", - }) - } + portConfigs = append(portConfigs, ServicePortConfig{ + HostIP: binding.HostIP, + Protocol: strings.ToLower(port.Proto()), + Target: uint32(port.Int()), + Published: binding.HostPort, + Mode: "ingress", + }) } return portConfigs, nil } @@ -655,16 +687,30 @@ const ( VolumeTypeTmpfs = "tmpfs" // VolumeTypeNamedPipe is the type for mounting Windows named pipes VolumeTypeNamedPipe = "npipe" + + // SElinuxShared share the volume content + SElinuxShared = "z" + // SElinuxUnshared label content as private unshared + SElinuxUnshared = "Z" ) // 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"` Extensions map[string]interface{} `yaml:",inline" json:"-"` } +// SELinux represents the SELinux re-labeling options. +const ( + // SELinuxShared option indicates that the bind mount content is shared among multiple containers + SELinuxShared string = "z" + // SELinuxPrivate option indicates that the bind mount content is private and unshared + SELinuxPrivate string = "Z" +) + // Propagation represents the propagation of a mount. const ( // PropagationRPrivate RPRIVATE diff --git a/vendor/github.com/compose-spec/godotenv/.gitignore b/vendor/github.com/compose-spec/godotenv/.gitignore deleted file mode 100644 index e43b0f98..00000000 --- a/vendor/github.com/compose-spec/godotenv/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store diff --git a/vendor/github.com/compose-spec/godotenv/Earthfile b/vendor/github.com/compose-spec/godotenv/Earthfile deleted file mode 100644 index 8bdfcea0..00000000 --- a/vendor/github.com/compose-spec/godotenv/Earthfile +++ /dev/null @@ -1,27 +0,0 @@ -ARG GOLANG_VERSION=1.17.1 -ARG ALPINE_VERSION=3.14 - -FROM golang:${GOLANG_VERSION}-alpine${ALPINE_VERSION} -WORKDIR /code - -code: - FROM +base - COPY . . - -golangci: - ARG GOLANGCI_VERSION=v1.40.1 - FROM golangci/golangci-lint:${GOLANGCI_VERSION}-alpine - SAVE ARTIFACT /usr/bin/golangci-lint - -lint: - FROM +code - COPY +golangci/golangci-lint /usr/bin/golangci-lint - RUN golangci-lint run --timeout 5m ./... - -test: - FROM +code - RUN go test ./... - -all: - BUILD +lint - BUILD +test diff --git a/vendor/github.com/compose-spec/godotenv/README.md b/vendor/github.com/compose-spec/godotenv/README.md deleted file mode 100644 index 3420cd9c..00000000 --- a/vendor/github.com/compose-spec/godotenv/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# GoDotEnv - -A Go (golang) port of the Ruby dotenv project (which loads env vars from a .env file) - -From the original Library: - -> Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environments–such as resource handles for databases or credentials for external services–should be extracted from the code into environment variables. -> -> But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped. - -This is a fork of [joho/godotenv](https://github.com/joho/godotenv) focussing on `.env` file support by the compose specification - - - -To run linter and tests, please install [Earthly](https://earthly.dev/get-earthly) and run: -```sh -earthly +all -``` diff --git a/vendor/github.com/compose-spec/godotenv/go.mod b/vendor/github.com/compose-spec/godotenv/go.mod deleted file mode 100644 index 72e37f6e..00000000 --- a/vendor/github.com/compose-spec/godotenv/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/compose-spec/godotenv - -go 1.16 diff --git a/vendor/github.com/compose-spec/godotenv/go.sum b/vendor/github.com/compose-spec/godotenv/go.sum deleted file mode 100644 index e69de29b..00000000 diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md index 9fe803a5..38a09916 100644 --- a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md +++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.3 + +* Fix cases where `json.Number` didn't decode properly [GH-261] + ## 1.4.2 * Custom name matchers to support any sort of casing, formatting, etc. for diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go index dcee0f2d..6b81b006 100644 --- a/vendor/github.com/mitchellh/mapstructure/mapstructure.go +++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go @@ -684,16 +684,12 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": jn := data.(json.Number) - i, err := jn.Int64() + i, err := strconv.ParseUint(string(jn), 0, 64) if err != nil { return fmt.Errorf( "error decoding json.Number into %s: %s", name, err) } - if i < 0 && !d.config.WeaklyTypedInput { - return fmt.Errorf("cannot parse '%s', %d overflows uint", - name, i) - } - val.SetUint(uint64(i)) + val.SetUint(i) default: return fmt.Errorf( "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", diff --git a/vendor/modules.txt b/vendor/modules.txt index 0d704693..8bcf83d7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -32,16 +32,16 @@ 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.0.8 +# github.com/compose-spec/compose-go v1.2.1 ## explicit +github.com/compose-spec/compose-go/consts +github.com/compose-spec/compose-go/dotenv github.com/compose-spec/compose-go/errdefs 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/types -# github.com/compose-spec/godotenv v1.1.1 -github.com/compose-spec/godotenv # github.com/containerd/console v1.0.3 ## explicit github.com/containerd/console @@ -292,7 +292,7 @@ github.com/matttproud/golang_protobuf_extensions/pbutil github.com/miekg/pkcs11 # github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 github.com/mitchellh/go-wordwrap -# github.com/mitchellh/mapstructure v1.4.2 +# github.com/mitchellh/mapstructure v1.4.3 github.com/mitchellh/mapstructure # github.com/moby/buildkit v0.10.0-rc2.0.20220308185020-fdecd0ae108b ## explicit