mirror of https://github.com/docker/buildx.git
bump compose-go to v2.2.0
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
This commit is contained in:
parent
3f81293fd4
commit
4da753da79
2
go.mod
2
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
|
||||
|
|
4
go.sum
4
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=
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue