diff --git a/go.mod b/go.mod index 24d06871..29e6b909 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 github.com/aws/aws-sdk-go-v2/config v1.26.6 - github.com/compose-spec/compose-go/v2 v2.1.6 + github.com/compose-spec/compose-go/v2 v2.2.0 github.com/containerd/console v1.0.4 github.com/containerd/containerd v1.7.21 github.com/containerd/continuity v0.4.3 diff --git a/go.sum b/go.sum index ba0c1181..4b93e6b2 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,8 @@ github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/P github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= -github.com/compose-spec/compose-go/v2 v2.1.6 h1:d0Cs0DffmOwmSzs0YPHwKCskknGq2jfGg4uGowlEpps= -github.com/compose-spec/compose-go/v2 v2.1.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.2.0 h1:VsQosGhuO+H9wh5laiIiAe4TVd73kQ5NWwmNrdm0HRA= +github.com/compose-spec/compose-go/v2 v2.2.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= diff --git a/vendor/github.com/compose-spec/compose-go/v2/cli/options.go b/vendor/github.com/compose-spec/compose-go/v2/cli/options.go index 989f9088..c4b2f57a 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/cli/options.go +++ b/vendor/github.com/compose-spec/compose-go/v2/cli/options.go @@ -403,7 +403,7 @@ func (o *ProjectOptions) GetWorkingDir() (string, error) { return os.Getwd() } -func (o *ProjectOptions) GeConfigFiles() ([]types.ConfigFile, error) { +func (o *ProjectOptions) GetConfigFiles() ([]types.ConfigFile, error) { configPaths, err := o.getConfigPaths() if err != nil { return nil, err @@ -466,7 +466,7 @@ func (o *ProjectOptions) LoadModel(ctx context.Context) (map[string]any, error) // prepare converts ProjectOptions into loader's types.ConfigDetails and configures default load options func (o *ProjectOptions) prepare() (types.ConfigDetails, error) { - configs, err := o.GeConfigFiles() + configs, err := o.GetConfigFiles() if err != nil { return types.ConfigDetails{}, err } diff --git a/vendor/github.com/compose-spec/compose-go/v2/dotenv/parser.go b/vendor/github.com/compose-spec/compose-go/v2/dotenv/parser.go index 861cd953..d7b4a646 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/dotenv/parser.go +++ b/vendor/github.com/compose-spec/compose-go/v2/dotenv/parser.go @@ -119,7 +119,7 @@ loop: offset = i + 1 inherited = rune == '\n' break loop - case '_', '.', '-', '[', ']': + case '_', '.', '[', ']': default: // variable name should match [A-Za-z0-9_.-] if unicode.IsLetter(rune) || unicode.IsNumber(rune) { diff --git a/vendor/github.com/compose-spec/compose-go/v2/loader/environment.go b/vendor/github.com/compose-spec/compose-go/v2/loader/environment.go index 1906d2d9..3f7277b8 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/loader/environment.go +++ b/vendor/github.com/compose-spec/compose-go/v2/loader/environment.go @@ -79,7 +79,7 @@ func resolveSecretsEnvironment(dict map[string]any, environment types.Mapping) { continue } if found, ok := environment[env]; ok { - secret["content"] = found + secret[types.SecretConfigXValue] = found } secrets[name] = secret } diff --git a/vendor/github.com/compose-spec/compose-go/v2/loader/extends.go b/vendor/github.com/compose-spec/compose-go/v2/loader/extends.go index 150a4625..c48b1e4b 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/loader/extends.go +++ b/vendor/github.com/compose-spec/compose-go/v2/loader/extends.go @@ -163,8 +163,15 @@ func getExtendsBaseFromFile( if err != nil { return nil, nil, err } - services := source["services"].(map[string]any) - _, ok := services[ref] + m, ok := source["services"] + if !ok { + return nil, nil, fmt.Errorf("cannot extend service %q in %s: no services section", name, local) + } + services, ok := m.(map[string]any) + if !ok { + return nil, nil, fmt.Errorf("cannot extend service %q in %s: services must be a mapping", name, local) + } + _, ok = services[ref] if !ok { return nil, nil, fmt.Errorf( "cannot extend service %q in %s: service %q not found in %s", diff --git a/vendor/github.com/compose-spec/compose-go/v2/loader/full-example.yml b/vendor/github.com/compose-spec/compose-go/v2/loader/full-example.yml index 25dfbce6..2f7b8c43 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/loader/full-example.yml +++ b/vendor/github.com/compose-spec/compose-go/v2/loader/full-example.yml @@ -118,7 +118,9 @@ services: - "a 7:* rmw" devices: - - "/dev/ttyUSB0:/dev/ttyUSB0" + - source: /dev/ttyUSB0 + target: /dev/ttyUSB0 + permissions: rwm # String or list # dns: 8.8.8.8 diff --git a/vendor/github.com/compose-spec/compose-go/v2/loader/loader.go b/vendor/github.com/compose-spec/compose-go/v2/loader/loader.go index 8a0adbc3..25d2d0c6 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/loader/loader.go +++ b/vendor/github.com/compose-spec/compose-go/v2/loader/loader.go @@ -738,7 +738,9 @@ func Transform(source interface{}, target interface{}) error { DecodeHook: mapstructure.ComposeDecodeHookFunc( nameServices, decoderHook, - cast), + cast, + secretConfigDecoderHook, + ), Result: target, TagName: "yaml", Metadata: &data, @@ -764,6 +766,28 @@ func nameServices(from reflect.Value, to reflect.Value) (interface{}, error) { return from.Interface(), nil } +func secretConfigDecoderHook(from, to reflect.Type, data interface{}) (interface{}, error) { + // Check if the input is a map and we're decoding into a SecretConfig + if from.Kind() == reflect.Map && to == reflect.TypeOf(types.SecretConfig{}) { + if v, ok := data.(map[string]interface{}); ok { + if ext, ok := v["#extensions"].(map[string]interface{}); ok { + if val, ok := ext[types.SecretConfigXValue].(string); ok { + // Return a map with the Content field populated + v["Content"] = val + delete(ext, types.SecretConfigXValue) + + if len(ext) == 0 { + delete(v, "#extensions") + } + } + } + } + } + + // Return the original data so the rest is handled by default mapstructure logic + return data, nil +} + // keys need to be converted to strings for jsonschema func convertToStringKeysRecursive(value interface{}, keyPrefix string) (interface{}, error) { if mapping, ok := value.(map[string]interface{}); ok { diff --git a/vendor/github.com/compose-spec/compose-go/v2/override/uncity.go b/vendor/github.com/compose-spec/compose-go/v2/override/uncity.go index 620a70a2..3b0c63d3 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/override/uncity.go +++ b/vendor/github.com/compose-spec/compose-go/v2/override/uncity.go @@ -36,7 +36,6 @@ func init() { unique["services.*.annotations"] = keyValueIndexer unique["services.*.build.args"] = keyValueIndexer unique["services.*.build.additional_contexts"] = keyValueIndexer - unique["services.*.build.extra_hosts"] = keyValueIndexer unique["services.*.build.platform"] = keyValueIndexer unique["services.*.build.tags"] = keyValueIndexer unique["services.*.build.labels"] = keyValueIndexer @@ -51,7 +50,6 @@ func init() { unique["services.*.environment"] = keyValueIndexer unique["services.*.env_file"] = envFileIndexer unique["services.*.expose"] = exposeIndexer - unique["services.*.extra_hosts"] = keyValueIndexer unique["services.*.labels"] = keyValueIndexer unique["services.*.links"] = keyValueIndexer unique["services.*.networks.*.aliases"] = keyValueIndexer @@ -62,6 +60,7 @@ func init() { unique["services.*.sysctls"] = keyValueIndexer unique["services.*.tmpfs"] = keyValueIndexer unique["services.*.volumes"] = volumeIndexer + unique["services.*.devices"] = deviceMappingIndexer } // EnforceUnicity removes redefinition of elements declared in a sequence @@ -108,16 +107,16 @@ func enforceUnicity(value any, p tree.Path) (any, error) { return value, nil } -func keyValueIndexer(y any, p tree.Path) (string, error) { - switch value := y.(type) { +func keyValueIndexer(v any, p tree.Path) (string, error) { + switch value := v.(type) { case string: key, _, found := strings.Cut(value, "=") - if !found { - return value, nil + if found { + return key, nil } - return key, nil + return value, nil default: - return "", fmt.Errorf("%s: unexpected type %T", p, y) + return "", fmt.Errorf("%s: unexpected type %T", p, v) } } @@ -139,6 +138,24 @@ func volumeIndexer(y any, p tree.Path) (string, error) { return "", nil } +func deviceMappingIndexer(y any, p tree.Path) (string, error) { + switch value := y.(type) { + case map[string]any: + target, ok := value["target"].(string) + if !ok { + return "", fmt.Errorf("service device %s is missing a mount target", p) + } + return target, nil + case string: + arr := strings.Split(value, ":") + if len(arr) == 1 { + return arr[0], nil + } + return arr[1], nil + } + return "", nil +} + func exposeIndexer(a any, path tree.Path) (string, error) { switch v := a.(type) { case string: diff --git a/vendor/github.com/compose-spec/compose-go/v2/schema/compose-spec.json b/vendor/github.com/compose-spec/compose-go/v2/schema/compose-spec.json index 335cbe09..a2f5e244 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/schema/compose-spec.json +++ b/vendor/github.com/compose-spec/compose-go/v2/schema/compose-spec.json @@ -19,7 +19,6 @@ "include": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/include" }, "description": "compose sub-projects to be included." @@ -115,7 +114,7 @@ "pull": {"type": ["boolean", "string"]}, "target": {"type": "string"}, "shm_size": {"type": ["integer", "string"]}, - "extra_hosts": {"$ref": "#/definitions/list_or_dict"}, + "extra_hosts": {"$ref": "#/definitions/extra_hosts"}, "isolation": {"type": "string"}, "privileged": {"type": ["boolean", "string"]}, "secrets": {"$ref": "#/definitions/service_config_or_secret"}, @@ -216,7 +215,25 @@ ] }, "device_cgroup_rules": {"$ref": "#/definitions/list_of_strings"}, - "devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true}, + "devices": { + "type": "array", + "items": { + "oneOf": [ + {"type": "string"}, + { + "type": "object", + "required": ["source"], + "properties": { + "source": {"type": "string"}, + "target": {"type": "string"}, + "permissions": {"type": "string"} + }, + "additionalProperties": false, + "patternProperties": {"^x-": {}} + } + ] + } + }, "dns": {"$ref": "#/definitions/string_or_list"}, "dns_opt": {"type": "array","items": {"type": "string"}, "uniqueItems": true}, "dns_search": {"$ref": "#/definitions/string_or_list"}, @@ -249,7 +266,7 @@ ] }, "external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true}, - "extra_hosts": {"$ref": "#/definitions/list_or_dict"}, + "extra_hosts": {"$ref": "#/definitions/extra_hosts"}, "group_add": { "type": "array", "items": { @@ -854,6 +871,21 @@ ] }, + "extra_hosts": { + "oneOf": [ + { + "type": "object", + "patternProperties": { + ".+": { + "type": ["string", "array"] + } + }, + "additionalProperties": false + }, + {"type": "array", "items": {"type": "string"}, "uniqueItems": true} + ] + }, + "blkio_limit": { "type": "object", "properties": { diff --git a/vendor/github.com/compose-spec/compose-go/v2/transform/canonical.go b/vendor/github.com/compose-spec/compose-go/v2/transform/canonical.go index 1240c77c..a248b4be 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/transform/canonical.go +++ b/vendor/github.com/compose-spec/compose-go/v2/transform/canonical.go @@ -33,6 +33,7 @@ func init() { transformers["services.*.extends"] = transformExtends transformers["services.*.networks"] = transformServiceNetworks transformers["services.*.volumes.*"] = transformVolumeMount + transformers["services.*.devices.*"] = transformDeviceMapping transformers["services.*.secrets.*"] = transformFileMount transformers["services.*.configs.*"] = transformFileMount transformers["services.*.ports"] = transformPorts diff --git a/vendor/github.com/compose-spec/compose-go/v2/transform/device.go b/vendor/github.com/compose-spec/compose-go/v2/transform/device.go new file mode 100644 index 00000000..351d8151 --- /dev/null +++ b/vendor/github.com/compose-spec/compose-go/v2/transform/device.go @@ -0,0 +1,60 @@ +/* + 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 transform + +import ( + "fmt" + "strings" + + "github.com/compose-spec/compose-go/v2/tree" +) + +func transformDeviceMapping(data any, p tree.Path, ignoreParseError bool) (any, error) { + switch v := data.(type) { + case map[string]any: + return v, nil + case string: + src := "" + dst := "" + permissions := "rwm" + arr := strings.Split(v, ":") + switch len(arr) { + case 3: + permissions = arr[2] + fallthrough + case 2: + dst = arr[1] + fallthrough + case 1: + src = arr[0] + default: + if !ignoreParseError { + return nil, fmt.Errorf("confusing device mapping, please use long syntax: %s", v) + } + } + if dst == "" { + dst = src + } + return map[string]any{ + "source": src, + "target": dst, + "permissions": permissions, + }, nil + default: + return data, fmt.Errorf("%s: invalid type %T for service volume mount", p, v) + } +} diff --git a/vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go b/vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go index c78b17c8..d5d1d024 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go +++ b/vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go @@ -271,13 +271,13 @@ func deriveDeepCopyService(dst, src *ServiceConfig) { if cap(dst.Devices) >= len(src.Devices) { dst.Devices = (dst.Devices)[:len(src.Devices)] } else { - dst.Devices = make([]string, len(src.Devices)) + dst.Devices = make([]DeviceMapping, len(src.Devices)) } } else if len(src.Devices) < len(dst.Devices) { dst.Devices = (dst.Devices)[:len(src.Devices)] } } else { - dst.Devices = make([]string, len(src.Devices)) + dst.Devices = make([]DeviceMapping, len(src.Devices)) } copy(dst.Devices, src.Devices) } diff --git a/vendor/github.com/compose-spec/compose-go/v2/types/hostList.go b/vendor/github.com/compose-spec/compose-go/v2/types/hostList.go index e224b816..9bc0fbc5 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/types/hostList.go +++ b/vendor/github.com/compose-spec/compose-go/v2/types/hostList.go @@ -36,9 +36,9 @@ func NewHostsList(hosts []string) (HostsList, error) { if ok { // Mapping found with this separator, stop here. if ips, ok := list[host]; ok { - list[host] = append(ips, ip) + list[host] = append(ips, strings.Split(ip, ",")...) } else { - list[host] = []string{ip} + list[host] = strings.Split(ip, ",") } found = true break @@ -89,7 +89,18 @@ func (h *HostsList) DecodeMapstructure(value interface{}) error { if e == nil { e = "" } - list[i] = []string{fmt.Sprint(e)} + switch t := e.(type) { + case string: + list[i] = []string{t} + case []any: + hosts := make([]string, len(t)) + for j, h := range t { + hosts[j] = fmt.Sprint(h) + } + list[i] = hosts + default: + return fmt.Errorf("unexpected value type %T for extra_hosts entry", value) + } } err := list.cleanup() if err != nil { @@ -109,7 +120,7 @@ func (h *HostsList) DecodeMapstructure(value interface{}) error { *h = list return nil default: - return fmt.Errorf("unexpected value type %T for mapping", value) + return fmt.Errorf("unexpected value type %T for extra_hosts", value) } } diff --git a/vendor/github.com/compose-spec/compose-go/v2/types/types.go b/vendor/github.com/compose-spec/compose-go/v2/types/types.go index b0f97bf9..bee64467 100644 --- a/vendor/github.com/compose-spec/compose-go/v2/types/types.go +++ b/vendor/github.com/compose-spec/compose-go/v2/types/types.go @@ -62,7 +62,7 @@ type ServiceConfig struct { 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"` + Devices []DeviceMapping `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"` @@ -239,6 +239,10 @@ const ( NetworkModeContainerPrefix = ContainerPrefix ) +const ( + SecretConfigXValue = "x-#value" +) + // GetDependencies retrieves all services this service depends on func (s ServiceConfig) GetDependencies() []string { var dependencies []string @@ -301,6 +305,14 @@ type BlkioConfig struct { Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"` } +type DeviceMapping struct { + Source string `yaml:"source,omitempty" json:"source,omitempty"` + Target string `yaml:"target,omitempty" json:"target,omitempty"` + Permissions string `yaml:"permissions,omitempty" json:"permissions,omitempty"` + + Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"` +} + // WeightDevice is a structure that holds device:weight pair type WeightDevice struct { Path string diff --git a/vendor/modules.txt b/vendor/modules.txt index 5a650813..6c71a5cc 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -128,7 +128,7 @@ github.com/cenkalti/backoff/v4 # github.com/cespare/xxhash/v2 v2.2.0 ## explicit; go 1.11 github.com/cespare/xxhash/v2 -# github.com/compose-spec/compose-go/v2 v2.1.6 +# github.com/compose-spec/compose-go/v2 v2.2.0 ## explicit; go 1.21 github.com/compose-spec/compose-go/v2/cli github.com/compose-spec/compose-go/v2/consts