mirror of https://github.com/docker/buildx.git
vendor: update compose-go to v1.20.0
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
parent
be4fd7110d
commit
05a0fdf744
2
go.mod
2
go.mod
|
@ -5,7 +5,7 @@ go 1.20
|
|||
require (
|
||||
github.com/Masterminds/semver/v3 v3.2.1
|
||||
github.com/aws/aws-sdk-go-v2/config v1.18.16
|
||||
github.com/compose-spec/compose-go v1.19.0
|
||||
github.com/compose-spec/compose-go v1.20.0
|
||||
github.com/containerd/console v1.0.3
|
||||
github.com/containerd/containerd v1.7.2
|
||||
github.com/containerd/continuity v0.4.1
|
||||
|
|
4
go.sum
4
go.sum
|
@ -123,8 +123,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
|
|||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
|
||||
github.com/compose-spec/compose-go v1.19.0 h1:t68gAcwStDg0hy2kFvqHJIksf6xkqRnlSKfL45/ETqo=
|
||||
github.com/compose-spec/compose-go v1.19.0/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
|
||||
github.com/compose-spec/compose-go v1.20.0 h1:h4ZKOst1EF/DwZp7dWkb+wbTVE4nEyT9Lc89to84Ol4=
|
||||
github.com/compose-spec/compose-go v1.20.0/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
|
|
|
@ -98,7 +98,11 @@ func (p *parser) locateKeyName(src string) (string, string, bool, error) {
|
|||
var key string
|
||||
var inherited bool
|
||||
// trim "export" and space at beginning
|
||||
src = strings.TrimLeftFunc(exportRegex.ReplaceAllString(src, ""), isSpace)
|
||||
if exportRegex.MatchString(src) {
|
||||
// we use a `strings.trim` to preserve the pointer to the same underlying memory.
|
||||
// a regexp replace would copy the string.
|
||||
src = strings.TrimLeftFunc(strings.TrimPrefix(src, "export"), isSpace)
|
||||
}
|
||||
|
||||
// locate key name end and validate it in single loop
|
||||
offset := 0
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
||||
"github.com/compose-spec/compose-go/dotenv"
|
||||
interp "github.com/compose-spec/compose-go/interpolation"
|
||||
|
@ -109,37 +110,55 @@ func loadInclude(ctx context.Context, filename string, configDetails types.Confi
|
|||
func importResources(model *types.Config, imported *types.Project, path []string) error {
|
||||
services := mapByName(model.Services)
|
||||
for _, service := range imported.Services {
|
||||
if _, ok := services[service.Name]; ok {
|
||||
if present, ok := services[service.Name]; ok {
|
||||
if reflect.DeepEqual(present, service) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("imported compose file %s defines conflicting service %s", path, service.Name)
|
||||
}
|
||||
model.Services = append(model.Services, service)
|
||||
}
|
||||
for _, service := range imported.DisabledServices {
|
||||
if _, ok := services[service.Name]; ok {
|
||||
if disabled, ok := services[service.Name]; ok {
|
||||
if reflect.DeepEqual(disabled, service) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("imported compose file %s defines conflicting service %s", path, service.Name)
|
||||
}
|
||||
model.Services = append(model.Services, service)
|
||||
}
|
||||
for n, network := range imported.Networks {
|
||||
if _, ok := model.Networks[n]; ok {
|
||||
if present, ok := model.Networks[n]; ok {
|
||||
if reflect.DeepEqual(present, network) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("imported compose file %s defines conflicting network %s", path, n)
|
||||
}
|
||||
model.Networks[n] = network
|
||||
}
|
||||
for n, volume := range imported.Volumes {
|
||||
if _, ok := model.Volumes[n]; ok {
|
||||
if present, ok := model.Volumes[n]; ok {
|
||||
if reflect.DeepEqual(present, volume) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("imported compose file %s defines conflicting volume %s", path, n)
|
||||
}
|
||||
model.Volumes[n] = volume
|
||||
}
|
||||
for n, secret := range imported.Secrets {
|
||||
if _, ok := model.Secrets[n]; ok {
|
||||
if present, ok := model.Secrets[n]; ok {
|
||||
if reflect.DeepEqual(present, secret) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("imported compose file %s defines conflicting secret %s", path, n)
|
||||
}
|
||||
model.Secrets[n] = secret
|
||||
}
|
||||
for n, config := range imported.Configs {
|
||||
if _, ok := model.Configs[n]; ok {
|
||||
if present, ok := model.Configs[n]; ok {
|
||||
if reflect.DeepEqual(present, config) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("imported compose file %s defines conflicting config %s", path, n)
|
||||
}
|
||||
model.Configs[n] = config
|
||||
|
|
|
@ -46,10 +46,6 @@ var interpolateTypeCastMapping = map[tree.Path]interp.Cast{
|
|||
servicePath("deploy", "placement", "max_replicas_per_node"): toInt,
|
||||
servicePath("healthcheck", "retries"): toInt,
|
||||
servicePath("healthcheck", "disable"): toBoolean,
|
||||
servicePath("mem_limit"): toUnitBytes,
|
||||
servicePath("mem_reservation"): toUnitBytes,
|
||||
servicePath("memswap_limit"): toUnitBytes,
|
||||
servicePath("mem_swappiness"): toUnitBytes,
|
||||
servicePath("oom_kill_disable"): toBoolean,
|
||||
servicePath("oom_score_adj"): toInt64,
|
||||
servicePath("pids_limit"): toInt64,
|
||||
|
@ -58,16 +54,13 @@ var interpolateTypeCastMapping = map[tree.Path]interp.Cast{
|
|||
servicePath("read_only"): toBoolean,
|
||||
servicePath("scale"): toInt,
|
||||
servicePath("secrets", tree.PathMatchList, "mode"): toInt,
|
||||
servicePath("shm_size"): toUnitBytes,
|
||||
servicePath("stdin_open"): toBoolean,
|
||||
servicePath("stop_grace_period"): toDuration,
|
||||
servicePath("tty"): toBoolean,
|
||||
servicePath("ulimits", tree.PathMatchAll): toInt,
|
||||
servicePath("ulimits", tree.PathMatchAll, "hard"): toInt,
|
||||
servicePath("ulimits", tree.PathMatchAll, "soft"): toInt,
|
||||
servicePath("volumes", tree.PathMatchList, "read_only"): toBoolean,
|
||||
servicePath("volumes", tree.PathMatchList, "volume", "nocopy"): toBoolean,
|
||||
servicePath("volumes", tree.PathMatchList, "tmpfs", "size"): toUnitBytes,
|
||||
iPath("networks", tree.PathMatchAll, "external"): toBoolean,
|
||||
iPath("networks", tree.PathMatchAll, "internal"): toBoolean,
|
||||
iPath("networks", tree.PathMatchAll, "attachable"): toBoolean,
|
||||
|
@ -93,14 +86,6 @@ func toInt64(value string) (interface{}, error) {
|
|||
return strconv.ParseInt(value, 10, 64)
|
||||
}
|
||||
|
||||
func toUnitBytes(value string) (interface{}, error) {
|
||||
return transformSize(value)
|
||||
}
|
||||
|
||||
func toDuration(value string) (interface{}, error) {
|
||||
return transformStringToDuration(value)
|
||||
}
|
||||
|
||||
func toFloat(value string) (interface{}, error) {
|
||||
return strconv.ParseFloat(value, 64)
|
||||
}
|
||||
|
|
|
@ -28,15 +28,12 @@ import (
|
|||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/compose-spec/compose-go/consts"
|
||||
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/docker/go-units"
|
||||
"github.com/mattn/go-shellwords"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -241,6 +238,15 @@ func LoadWithContext(ctx context.Context, configDetails types.ConfigDetails, opt
|
|||
return nil, err
|
||||
}
|
||||
opts.projectName = projectName
|
||||
|
||||
// TODO(milas): this should probably ALWAYS set (overriding any existing)
|
||||
if _, ok := configDetails.Environment[consts.ComposeProjectName]; !ok && projectName != "" {
|
||||
if configDetails.Environment == nil {
|
||||
configDetails.Environment = map[string]string{}
|
||||
}
|
||||
configDetails.Environment[consts.ComposeProjectName] = projectName
|
||||
}
|
||||
|
||||
return load(ctx, configDetails, opts, nil)
|
||||
}
|
||||
|
||||
|
@ -464,10 +470,6 @@ func projectName(details types.ConfigDetails, opts *Options) (string, error) {
|
|||
return "", InvalidProjectNameErr(projectName)
|
||||
}
|
||||
|
||||
// TODO(milas): this should probably ALWAYS set (overriding any existing)
|
||||
if _, ok := details.Environment[consts.ComposeProjectName]; !ok && projectName != "" {
|
||||
details.Environment[consts.ComposeProjectName] = projectName
|
||||
}
|
||||
return projectName, nil
|
||||
}
|
||||
|
||||
|
@ -586,7 +588,7 @@ func Transform(source interface{}, target interface{}, additionalTransformers ..
|
|||
config := &mapstructure.DecoderConfig{
|
||||
DecodeHook: mapstructure.ComposeDecodeHookFunc(
|
||||
createTransformHook(additionalTransformers...),
|
||||
mapstructure.StringToTimeDurationHookFunc()),
|
||||
decoderHook),
|
||||
Result: target,
|
||||
TagName: "yaml",
|
||||
Metadata: &data,
|
||||
|
@ -610,28 +612,20 @@ type Transformer struct {
|
|||
func createTransformHook(additionalTransformers ...Transformer) mapstructure.DecodeHookFuncType {
|
||||
transforms := map[reflect.Type]func(interface{}) (interface{}, error){
|
||||
reflect.TypeOf(types.External{}): transformExternal,
|
||||
reflect.TypeOf(types.HealthCheckTest{}): transformHealthCheckTest,
|
||||
reflect.TypeOf(types.ShellCommand{}): transformShellCommand,
|
||||
reflect.TypeOf(types.StringList{}): transformStringList,
|
||||
reflect.TypeOf(map[string]string{}): transformMapStringString,
|
||||
reflect.TypeOf(types.Options{}): transformOptions,
|
||||
reflect.TypeOf(types.UlimitsConfig{}): transformUlimits,
|
||||
reflect.TypeOf(types.UnitBytes(0)): transformSize,
|
||||
reflect.TypeOf([]types.ServicePortConfig{}): transformServicePort,
|
||||
reflect.TypeOf(types.ServiceSecretConfig{}): transformFileReferenceConfig,
|
||||
reflect.TypeOf(types.ServiceConfigObjConfig{}): transformFileReferenceConfig,
|
||||
reflect.TypeOf(types.StringOrNumberList{}): transformStringOrNumberList,
|
||||
reflect.TypeOf(map[string]*types.ServiceNetworkConfig{}): transformServiceNetworkMap,
|
||||
reflect.TypeOf(types.Mapping{}): transformMappingOrListFunc("=", false),
|
||||
reflect.TypeOf(types.MappingWithEquals{}): transformMappingOrListFunc("=", true),
|
||||
reflect.TypeOf(types.Labels{}): transformMappingOrListFunc("=", false),
|
||||
reflect.TypeOf(types.MappingWithColon{}): transformMappingOrListFunc(":", false),
|
||||
reflect.TypeOf(types.HostsList{}): transformMappingOrListFunc(":", false),
|
||||
reflect.TypeOf(types.ServiceVolumeConfig{}): transformServiceVolumeConfig,
|
||||
reflect.TypeOf(types.BuildConfig{}): transformBuildConfig,
|
||||
reflect.TypeOf(types.Duration(0)): transformStringToDuration,
|
||||
reflect.TypeOf(types.DependsOnConfig{}): transformDependsOnConfig,
|
||||
reflect.TypeOf(types.ExtendsConfig{}): transformExtendsConfig,
|
||||
reflect.TypeOf(types.DeviceRequest{}): transformServiceDeviceRequest,
|
||||
reflect.TypeOf(types.SSHConfig{}): transformSSHConfig,
|
||||
reflect.TypeOf(types.IncludeConfig{}): transformIncludeConfig,
|
||||
}
|
||||
|
@ -1031,7 +1025,7 @@ func loadFileObjectConfig(name string, objType string, obj types.FileObjectConfi
|
|||
return obj, nil
|
||||
}
|
||||
|
||||
var transformMapStringString TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
var transformOptions TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
switch value := data.(type) {
|
||||
case map[string]interface{}:
|
||||
return toMapStringString(value, false), nil
|
||||
|
@ -1094,35 +1088,6 @@ var transformServicePort TransformerFunc = func(data interface{}) (interface{},
|
|||
}
|
||||
}
|
||||
|
||||
var transformServiceDeviceRequest TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
switch value := data.(type) {
|
||||
case map[string]interface{}:
|
||||
count, ok := value["count"]
|
||||
if ok {
|
||||
switch val := count.(type) {
|
||||
case int:
|
||||
return value, nil
|
||||
case string:
|
||||
if strings.ToLower(val) == "all" {
|
||||
value["count"] = -1
|
||||
return value, nil
|
||||
}
|
||||
i, err := strconv.ParseInt(val, 10, 64)
|
||||
if err == nil {
|
||||
value["count"] = i
|
||||
return value, nil
|
||||
}
|
||||
return data, errors.Errorf("invalid string value for 'count' (the only value allowed is 'all' or a number)")
|
||||
default:
|
||||
return data, errors.Errorf("invalid type %T for device count", val)
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
default:
|
||||
return data, errors.Errorf("invalid type %T for resource reservation", value)
|
||||
}
|
||||
}
|
||||
|
||||
var transformFileReferenceConfig TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
switch value := data.(type) {
|
||||
case string:
|
||||
|
@ -1258,26 +1223,6 @@ func ParseShortSSHSyntax(value string) ([]types.SSHKey, error) {
|
|||
return result, nil
|
||||
}
|
||||
|
||||
var transformStringOrNumberList TransformerFunc = func(value interface{}) (interface{}, error) {
|
||||
list := value.([]interface{})
|
||||
result := make([]string, len(list))
|
||||
for i, item := range list {
|
||||
result[i] = fmt.Sprint(item)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var transformStringList TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
switch value := data.(type) {
|
||||
case string:
|
||||
return []string{value}, nil
|
||||
case []interface{}:
|
||||
return value, nil
|
||||
default:
|
||||
return data, errors.Errorf("invalid type %T for string list", value)
|
||||
}
|
||||
}
|
||||
|
||||
func transformMappingOrListFunc(sep string, allowNil bool) TransformerFunc {
|
||||
return func(data interface{}) (interface{}, error) {
|
||||
return transformMappingOrList(data, sep, allowNil)
|
||||
|
@ -1312,52 +1257,6 @@ func transformValueToMapEntry(value string, separator string, allowNil bool) (st
|
|||
}
|
||||
}
|
||||
|
||||
var transformShellCommand TransformerFunc = func(value interface{}) (interface{}, error) {
|
||||
if str, ok := value.(string); ok {
|
||||
return shellwords.Parse(str)
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
var transformHealthCheckTest TransformerFunc = func(data interface{}) (interface{}, error) {
|
||||
switch value := data.(type) {
|
||||
case string:
|
||||
return append([]string{"CMD-SHELL"}, value), nil
|
||||
case []interface{}:
|
||||
return value, nil
|
||||
default:
|
||||
return value, errors.Errorf("invalid type %T for healthcheck.test", value)
|
||||
}
|
||||
}
|
||||
|
||||
var transformSize TransformerFunc = func(value interface{}) (interface{}, error) {
|
||||
switch value := value.(type) {
|
||||
case int:
|
||||
return int64(value), nil
|
||||
case int64, types.UnitBytes:
|
||||
return value, nil
|
||||
case string:
|
||||
return units.RAMInBytes(value)
|
||||
default:
|
||||
return value, errors.Errorf("invalid type for size %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
var transformStringToDuration TransformerFunc = func(value interface{}) (interface{}, error) {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
d, err := time.ParseDuration(value)
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
func toMapStringString(value map[string]interface{}, allowNil bool) map[string]interface{} {
|
||||
output := make(map[string]interface{})
|
||||
for key, value := range value {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright 2020 The Compose Specification Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package loader
|
||||
|
||||
import "reflect"
|
||||
|
||||
// comparable to yaml.Unmarshaler, decoder allow a type to define it's own custom logic to convert value
|
||||
// see https://github.com/mitchellh/mapstructure/pull/294
|
||||
type decoder interface {
|
||||
DecodeMapstructure(interface{}) error
|
||||
}
|
||||
|
||||
// see https://github.com/mitchellh/mapstructure/issues/115#issuecomment-735287466
|
||||
// adapted to support types derived from built-in types, as DecodeMapstructure would not be able to mutate internal
|
||||
// value, so need to invoke DecodeMapstructure defined by pointer to type
|
||||
func decoderHook(from reflect.Value, to reflect.Value) (interface{}, error) {
|
||||
// If the destination implements the decoder interface
|
||||
u, ok := to.Interface().(decoder)
|
||||
if !ok {
|
||||
// for non-struct types we need to invoke func (*type) DecodeMapstructure()
|
||||
if to.CanAddr() {
|
||||
pto := to.Addr()
|
||||
u, ok = pto.Interface().(decoder)
|
||||
}
|
||||
if !ok {
|
||||
return from.Interface(), nil
|
||||
}
|
||||
}
|
||||
// If it is nil and a pointer, create and assign the target value first
|
||||
if to.Type().Kind() == reflect.Ptr && to.IsNil() {
|
||||
to.Set(reflect.New(to.Type().Elem()))
|
||||
u = to.Interface().(decoder)
|
||||
}
|
||||
// Call the custom DecodeMapstructure method
|
||||
if err := u.DecodeMapstructure(from.Interface()); err != nil {
|
||||
return to.Interface(), err
|
||||
}
|
||||
return to.Interface(), nil
|
||||
}
|
|
@ -320,8 +320,8 @@ func mergeLoggingConfig(dst, src reflect.Value) error {
|
|||
if getLoggingDriver(dst.Elem()) == "" {
|
||||
dst.Elem().FieldByName("Driver").SetString(getLoggingDriver(src.Elem()))
|
||||
}
|
||||
dstOptions := dst.Elem().FieldByName("Options").Interface().(map[string]string)
|
||||
srcOptions := src.Elem().FieldByName("Options").Interface().(map[string]string)
|
||||
dstOptions := dst.Elem().FieldByName("Options").Interface().(types.Options)
|
||||
srcOptions := src.Elem().FieldByName("Options").Interface().(types.Options)
|
||||
return mergo.Merge(&dstOptions, srcOptions, mergo.WithOverride)
|
||||
}
|
||||
// Different driver, override with src
|
||||
|
|
|
@ -475,7 +475,7 @@
|
|||
"properties": {
|
||||
"ignore": {"type": "array", "items": {"type": "string"}},
|
||||
"path": {"type": "string"},
|
||||
"action": {"type": "string", "enum": ["rebuild", "sync"]},
|
||||
"action": {"type": "string", "enum": ["rebuild", "sync", "sync+restart"]},
|
||||
"target": {"type": "string"}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
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 types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
)
|
||||
|
||||
// UnitBytes is the bytes type
|
||||
type UnitBytes int64
|
||||
|
||||
// MarshalYAML makes UnitBytes implement yaml.Marshaller
|
||||
func (u UnitBytes) MarshalYAML() (interface{}, error) {
|
||||
return fmt.Sprintf("%d", u), nil
|
||||
}
|
||||
|
||||
// MarshalJSON makes UnitBytes implement json.Marshaler
|
||||
func (u UnitBytes) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf(`"%d"`, u)), nil
|
||||
}
|
||||
|
||||
func (u *UnitBytes) DecodeMapstructure(value interface{}) error {
|
||||
v, err := units.RAMInBytes(fmt.Sprint(value))
|
||||
*u = UnitBytes(v)
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
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 types
|
||||
|
||||
import "github.com/mattn/go-shellwords"
|
||||
|
||||
// ShellCommand is a string or list of string args.
|
||||
//
|
||||
// When marshaled to YAML, nil command fields will be omitted if `omitempty`
|
||||
// is specified as a struct tag. Explicitly empty commands (i.e. `[]` or
|
||||
// empty string will serialize to an empty array (`[]`).
|
||||
//
|
||||
// When marshaled to JSON, the `omitempty` struct must NOT be specified.
|
||||
// If the command field is nil, it will be serialized as `null`.
|
||||
// Explicitly empty commands (i.e. `[]` or empty string) will serialize to
|
||||
// an empty array (`[]`).
|
||||
//
|
||||
// The distinction between nil and explicitly empty is important to distinguish
|
||||
// between an unset value and a provided, but empty, value, which should be
|
||||
// preserved so that it can override any base value (e.g. container entrypoint).
|
||||
//
|
||||
// The different semantics between YAML and JSON are due to limitations with
|
||||
// JSON marshaling + `omitempty` in the Go stdlib, while gopkg.in/yaml.v3 gives
|
||||
// us more flexibility via the yaml.IsZeroer interface.
|
||||
//
|
||||
// In the future, it might make sense to make fields of this type be
|
||||
// `*ShellCommand` to avoid this situation, but that would constitute a
|
||||
// breaking change.
|
||||
type ShellCommand []string
|
||||
|
||||
// IsZero returns true if the slice is nil.
|
||||
//
|
||||
// Empty (but non-nil) slices are NOT considered zero values.
|
||||
func (s ShellCommand) IsZero() bool {
|
||||
// we do NOT want len(s) == 0, ONLY explicitly nil
|
||||
return s == nil
|
||||
}
|
||||
|
||||
// MarshalYAML returns nil (which will be serialized as `null`) for nil slices
|
||||
// and delegates to the standard marshaller behavior otherwise.
|
||||
//
|
||||
// NOTE: Typically the nil case here is not hit because IsZero has already
|
||||
// short-circuited marshalling, but this ensures that the type serializes
|
||||
// accurately if the `omitempty` struct tag is omitted/forgotten.
|
||||
//
|
||||
// A similar MarshalJSON() implementation is not needed because the Go stdlib
|
||||
// already serializes nil slices to `null`, whereas gopkg.in/yaml.v3 by default
|
||||
// serializes nil slices to `[]`.
|
||||
func (s ShellCommand) MarshalYAML() (interface{}, error) {
|
||||
if s == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return []string(s), nil
|
||||
}
|
||||
|
||||
func (s *ShellCommand) DecodeMapstructure(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
cmd, err := shellwords.Parse(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s = cmd
|
||||
case []interface{}:
|
||||
cmd := make([]string, len(v))
|
||||
for i, s := range v {
|
||||
cmd[i] = s.(string)
|
||||
}
|
||||
*s = cmd
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -23,8 +23,9 @@ type DevelopConfig struct {
|
|||
type WatchAction string
|
||||
|
||||
const (
|
||||
WatchActionSync WatchAction = "sync"
|
||||
WatchActionRebuild WatchAction = "rebuild"
|
||||
WatchActionSync WatchAction = "sync"
|
||||
WatchActionRebuild WatchAction = "rebuild"
|
||||
WatchActionSyncRestart WatchAction = "sync+restart"
|
||||
)
|
||||
|
||||
type Trigger struct {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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 types
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DeviceRequest struct {
|
||||
Capabilities []string `yaml:"capabilities,omitempty" json:"capabilities,omitempty"`
|
||||
Driver string `yaml:"driver,omitempty" json:"driver,omitempty"`
|
||||
Count DeviceCount `yaml:"count,omitempty" json:"count,omitempty"`
|
||||
IDs []string `yaml:"device_ids,omitempty" json:"device_ids,omitempty"`
|
||||
}
|
||||
|
||||
type DeviceCount int64
|
||||
|
||||
func (c *DeviceCount) DecodeMapstructure(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case int:
|
||||
*c = DeviceCount(v)
|
||||
case string:
|
||||
if strings.ToLower(v) == "all" {
|
||||
*c = -1
|
||||
return nil
|
||||
}
|
||||
i, err := strconv.ParseInt(v, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Errorf("invalid value %q, the only value allowed is 'all' or a number", v)
|
||||
}
|
||||
*c = DeviceCount(i)
|
||||
default:
|
||||
return errors.Errorf("invalid type %T for device count", v)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -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 types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Duration is a thin wrapper around time.Duration with improved JSON marshalling
|
||||
type Duration time.Duration
|
||||
|
||||
func (d Duration) String() string {
|
||||
return time.Duration(d).String()
|
||||
}
|
||||
|
||||
func (d *Duration) DecodeMapstructure(value interface{}) error {
|
||||
v, err := time.ParseDuration(fmt.Sprint(value))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*d = Duration(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON makes Duration implement json.Marshaler
|
||||
func (d Duration) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(d.String())
|
||||
}
|
||||
|
||||
// MarshalYAML makes Duration implement yaml.Marshaler
|
||||
func (d Duration) MarshalYAML() (interface{}, error) {
|
||||
return d.String(), nil
|
||||
}
|
||||
|
||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||
s := strings.Trim(string(b), "\"")
|
||||
timeDuration, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*d = Duration(timeDuration)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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 types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// HealthCheckConfig the healthcheck configuration for a service
|
||||
type HealthCheckConfig struct {
|
||||
Test HealthCheckTest `yaml:"test,omitempty" json:"test,omitempty"`
|
||||
Timeout *Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"`
|
||||
Interval *Duration `yaml:"interval,omitempty" json:"interval,omitempty"`
|
||||
Retries *uint64 `yaml:"retries,omitempty" json:"retries,omitempty"`
|
||||
StartPeriod *Duration `yaml:"start_period,omitempty" json:"start_period,omitempty"`
|
||||
StartInterval *Duration `yaml:"start_interval,omitempty" json:"start_interval,omitempty"`
|
||||
Disable bool `yaml:"disable,omitempty" json:"disable,omitempty"`
|
||||
|
||||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
}
|
||||
|
||||
// HealthCheckTest is the command run to test the health of a service
|
||||
type HealthCheckTest []string
|
||||
|
||||
func (l *HealthCheckTest) DecodeMapstructure(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
*l = []string{"CMD-SHELL", v}
|
||||
case []interface{}:
|
||||
seq := make([]string, len(v))
|
||||
for i, e := range v {
|
||||
seq[i] = e.(string)
|
||||
}
|
||||
*l = seq
|
||||
default:
|
||||
return fmt.Errorf("unexpected value type %T for healthcheck.test", value)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
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 types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Labels is a mapping type for labels
|
||||
type Labels map[string]string
|
||||
|
||||
func (l Labels) Add(key, value string) Labels {
|
||||
if l == nil {
|
||||
l = Labels{}
|
||||
}
|
||||
l[key] = value
|
||||
return l
|
||||
}
|
||||
|
||||
func (l Labels) AsList() []string {
|
||||
s := make([]string, len(l))
|
||||
i := 0
|
||||
for k, v := range l {
|
||||
s[i] = fmt.Sprintf("%s=%s", k, v)
|
||||
i++
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// label value can be a string | number | boolean | null (empty)
|
||||
func labelValue(e interface{}) string {
|
||||
if e == nil {
|
||||
return ""
|
||||
}
|
||||
switch v := e.(type) {
|
||||
case string:
|
||||
return v
|
||||
default:
|
||||
return fmt.Sprint(v)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Labels) DecodeMapstructure(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case map[string]interface{}:
|
||||
labels := make(map[string]string, len(v))
|
||||
for k, e := range v {
|
||||
labels[k] = labelValue(e)
|
||||
}
|
||||
*l = labels
|
||||
case []interface{}:
|
||||
labels := make(map[string]string, len(v))
|
||||
for _, s := range v {
|
||||
k, e, ok := strings.Cut(fmt.Sprint(s), "=")
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid label %q", v)
|
||||
}
|
||||
labels[k] = labelValue(e)
|
||||
}
|
||||
*l = labels
|
||||
default:
|
||||
return fmt.Errorf("unexpected value type %T for labels", value)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
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 types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Options is a mapping type for options we pass as-is to container runtime
|
||||
type Options map[string]string
|
||||
|
||||
func (d *Options) DecodeMapstructure(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case map[string]interface{}:
|
||||
m := make(map[string]string)
|
||||
for key, e := range v {
|
||||
if e == nil {
|
||||
m[key] = ""
|
||||
} else {
|
||||
m[key] = fmt.Sprint(e)
|
||||
}
|
||||
}
|
||||
*d = m
|
||||
case map[string]string:
|
||||
*d = v
|
||||
default:
|
||||
return errors.Errorf("invalid type %T for options", value)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
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 types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// StringList is a type for fields that can be a string or list of strings
|
||||
type StringList []string
|
||||
|
||||
func (l *StringList) DecodeMapstructure(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
*l = []string{v}
|
||||
case []interface{}:
|
||||
list := make([]string, len(v))
|
||||
for i, e := range v {
|
||||
list[i] = e.(string)
|
||||
}
|
||||
*l = list
|
||||
default:
|
||||
return errors.Errorf("invalid type %T for string list", value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StringOrNumberList is a type for fields that can be a list of strings or numbers
|
||||
type StringOrNumberList []string
|
||||
|
||||
func (l *StringOrNumberList) DecodeMapstructure(value interface{}) error {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
*l = []string{v}
|
||||
case []interface{}:
|
||||
list := make([]string, len(v))
|
||||
for i, e := range v {
|
||||
list[i] = fmt.Sprint(e)
|
||||
}
|
||||
*l = list
|
||||
default:
|
||||
return errors.Errorf("invalid type %T for string list", value)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -21,47 +21,10 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
// Duration is a thin wrapper around time.Duration with improved JSON marshalling
|
||||
type Duration time.Duration
|
||||
|
||||
func (d Duration) String() string {
|
||||
return time.Duration(d).String()
|
||||
}
|
||||
|
||||
// ConvertDurationPtr converts a type defined Duration pointer to a time.Duration pointer with the same value.
|
||||
func ConvertDurationPtr(d *Duration) *time.Duration {
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
res := time.Duration(*d)
|
||||
return &res
|
||||
}
|
||||
|
||||
// MarshalJSON makes Duration implement json.Marshaler
|
||||
func (d Duration) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(d.String())
|
||||
}
|
||||
|
||||
// MarshalYAML makes Duration implement yaml.Marshaler
|
||||
func (d Duration) MarshalYAML() (interface{}, error) {
|
||||
return d.String(), nil
|
||||
}
|
||||
|
||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||
s := strings.Trim(string(b), "\"")
|
||||
timeDuration, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*d = Duration(timeDuration)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Services is a list of ServiceConfig
|
||||
type Services []ServiceConfig
|
||||
|
||||
|
@ -364,62 +327,6 @@ type ThrottleDevice struct {
|
|||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
}
|
||||
|
||||
// ShellCommand is a string or list of string args.
|
||||
//
|
||||
// When marshaled to YAML, nil command fields will be omitted if `omitempty`
|
||||
// is specified as a struct tag. Explicitly empty commands (i.e. `[]` or
|
||||
// empty string will serialize to an empty array (`[]`).
|
||||
//
|
||||
// When marshaled to JSON, the `omitempty` struct must NOT be specified.
|
||||
// If the command field is nil, it will be serialized as `null`.
|
||||
// Explicitly empty commands (i.e. `[]` or empty string) will serialize to
|
||||
// an empty array (`[]`).
|
||||
//
|
||||
// The distinction between nil and explicitly empty is important to distinguish
|
||||
// between an unset value and a provided, but empty, value, which should be
|
||||
// preserved so that it can override any base value (e.g. container entrypoint).
|
||||
//
|
||||
// The different semantics between YAML and JSON are due to limitations with
|
||||
// JSON marshaling + `omitempty` in the Go stdlib, while gopkg.in/yaml.v3 gives
|
||||
// us more flexibility via the yaml.IsZeroer interface.
|
||||
//
|
||||
// In the future, it might make sense to make fields of this type be
|
||||
// `*ShellCommand` to avoid this situation, but that would constitute a
|
||||
// breaking change.
|
||||
type ShellCommand []string
|
||||
|
||||
// IsZero returns true if the slice is nil.
|
||||
//
|
||||
// Empty (but non-nil) slices are NOT considered zero values.
|
||||
func (s ShellCommand) IsZero() bool {
|
||||
// we do NOT want len(s) == 0, ONLY explicitly nil
|
||||
return s == nil
|
||||
}
|
||||
|
||||
// MarshalYAML returns nil (which will be serialized as `null`) for nil slices
|
||||
// and delegates to the standard marshaller behavior otherwise.
|
||||
//
|
||||
// NOTE: Typically the nil case here is not hit because IsZero has already
|
||||
// short-circuited marshalling, but this ensures that the type serializes
|
||||
// accurately if the `omitempty` struct tag is omitted/forgotten.
|
||||
//
|
||||
// A similar MarshalJSON() implementation is not needed because the Go stdlib
|
||||
// already serializes nil slices to `null`, whereas gopkg.in/yaml.v3 by default
|
||||
// serializes nil slices to `[]`.
|
||||
func (s ShellCommand) MarshalYAML() (interface{}, error) {
|
||||
if s == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return []string(s), nil
|
||||
}
|
||||
|
||||
// StringList is a type for fields that can be a string or list of strings
|
||||
type StringList []string
|
||||
|
||||
// StringOrNumberList is a type for fields that can be a list of strings or
|
||||
// numbers
|
||||
type StringOrNumberList []string
|
||||
|
||||
// MappingWithEquals is a mapping type that can be converted from a list of
|
||||
// key[=value] strings.
|
||||
// For the key with an empty value (`key=`), the mapped value is set to a pointer to `""`.
|
||||
|
@ -535,17 +442,6 @@ func (m Mapping) Merge(o Mapping) Mapping {
|
|||
return m
|
||||
}
|
||||
|
||||
// Labels is a mapping type for labels
|
||||
type Labels map[string]string
|
||||
|
||||
func (l Labels) Add(key, value string) Labels {
|
||||
if l == nil {
|
||||
l = Labels{}
|
||||
}
|
||||
l[key] = value
|
||||
return l
|
||||
}
|
||||
|
||||
type SSHKey struct {
|
||||
ID string
|
||||
Path string
|
||||
|
@ -609,8 +505,8 @@ func (h HostsList) MarshalJSON() ([]byte, error) {
|
|||
|
||||
// LoggingConfig the logging configuration for a service
|
||||
type LoggingConfig struct {
|
||||
Driver string `yaml:"driver,omitempty" json:"driver,omitempty"`
|
||||
Options map[string]string `yaml:"options,omitempty" json:"options,omitempty"`
|
||||
Driver string `yaml:"driver,omitempty" json:"driver,omitempty"`
|
||||
Options Options `yaml:"options,omitempty" json:"options,omitempty"`
|
||||
|
||||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
}
|
||||
|
@ -630,22 +526,6 @@ type DeployConfig struct {
|
|||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
}
|
||||
|
||||
// HealthCheckConfig the healthcheck configuration for a service
|
||||
type HealthCheckConfig struct {
|
||||
Test HealthCheckTest `yaml:"test,omitempty" json:"test,omitempty"`
|
||||
Timeout *Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"`
|
||||
Interval *Duration `yaml:"interval,omitempty" json:"interval,omitempty"`
|
||||
Retries *uint64 `yaml:"retries,omitempty" json:"retries,omitempty"`
|
||||
StartPeriod *Duration `yaml:"start_period,omitempty" json:"start_period,omitempty"`
|
||||
StartInterval *Duration `yaml:"start_interval,omitempty" json:"start_interval,omitempty"`
|
||||
Disable bool `yaml:"disable,omitempty" json:"disable,omitempty"`
|
||||
|
||||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
}
|
||||
|
||||
// HealthCheckTest is the command run to test the health of a service
|
||||
type HealthCheckTest []string
|
||||
|
||||
// UpdateConfig the service update configuration
|
||||
type UpdateConfig struct {
|
||||
Parallelism *uint64 `yaml:"parallelism,omitempty" json:"parallelism,omitempty"`
|
||||
|
@ -678,13 +558,6 @@ type Resource struct {
|
|||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
}
|
||||
|
||||
type DeviceRequest struct {
|
||||
Capabilities []string `yaml:"capabilities,omitempty" json:"capabilities,omitempty"`
|
||||
Driver string `yaml:"driver,omitempty" json:"driver,omitempty"`
|
||||
Count int64 `yaml:"count,omitempty" json:"count,omitempty"`
|
||||
IDs []string `yaml:"device_ids,omitempty" json:"device_ids,omitempty"`
|
||||
}
|
||||
|
||||
// GenericResource represents a "user defined" resource which can
|
||||
// only be an integer (e.g: SSD=3) for a service
|
||||
type GenericResource struct {
|
||||
|
@ -704,19 +577,6 @@ type DiscreteGenericResource struct {
|
|||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
}
|
||||
|
||||
// UnitBytes is the bytes type
|
||||
type UnitBytes int64
|
||||
|
||||
// MarshalYAML makes UnitBytes implement yaml.Marshaller
|
||||
func (u UnitBytes) MarshalYAML() (interface{}, error) {
|
||||
return fmt.Sprintf("%d", u), nil
|
||||
}
|
||||
|
||||
// MarshalJSON makes UnitBytes implement json.Marshaler
|
||||
func (u UnitBytes) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf(`"%d"`, u)), nil
|
||||
}
|
||||
|
||||
// RestartPolicy the service restart policy
|
||||
type RestartPolicy struct {
|
||||
Condition string `yaml:"condition,omitempty" json:"condition,omitempty"`
|
||||
|
@ -955,16 +815,16 @@ func (u *UlimitsConfig) MarshalJSON() ([]byte, error) {
|
|||
|
||||
// NetworkConfig for a network
|
||||
type NetworkConfig struct {
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Driver string `yaml:"driver,omitempty" json:"driver,omitempty"`
|
||||
DriverOpts map[string]string `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
|
||||
Ipam IPAMConfig `yaml:"ipam,omitempty" json:"ipam,omitempty"`
|
||||
External External `yaml:"external,omitempty" json:"external,omitempty"`
|
||||
Internal bool `yaml:"internal,omitempty" json:"internal,omitempty"`
|
||||
Attachable bool `yaml:"attachable,omitempty" json:"attachable,omitempty"`
|
||||
Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"`
|
||||
EnableIPv6 bool `yaml:"enable_ipv6,omitempty" json:"enable_ipv6,omitempty"`
|
||||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Driver string `yaml:"driver,omitempty" json:"driver,omitempty"`
|
||||
DriverOpts Options `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
|
||||
Ipam IPAMConfig `yaml:"ipam,omitempty" json:"ipam,omitempty"`
|
||||
External External `yaml:"external,omitempty" json:"external,omitempty"`
|
||||
Internal bool `yaml:"internal,omitempty" json:"internal,omitempty"`
|
||||
Attachable bool `yaml:"attachable,omitempty" json:"attachable,omitempty"`
|
||||
Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"`
|
||||
EnableIPv6 bool `yaml:"enable_ipv6,omitempty" json:"enable_ipv6,omitempty"`
|
||||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
}
|
||||
|
||||
// IPAMConfig for a network
|
||||
|
@ -979,18 +839,18 @@ type IPAMPool struct {
|
|||
Subnet string `yaml:"subnet,omitempty" json:"subnet,omitempty"`
|
||||
Gateway string `yaml:"gateway,omitempty" json:"gateway,omitempty"`
|
||||
IPRange string `yaml:"ip_range,omitempty" json:"ip_range,omitempty"`
|
||||
AuxiliaryAddresses map[string]string `yaml:"aux_addresses,omitempty" json:"aux_addresses,omitempty"`
|
||||
AuxiliaryAddresses Mapping `yaml:"aux_addresses,omitempty" json:"aux_addresses,omitempty"`
|
||||
Extensions map[string]interface{} `yaml:",inline" json:"-"`
|
||||
}
|
||||
|
||||
// VolumeConfig for a volume
|
||||
type VolumeConfig struct {
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Driver string `yaml:"driver,omitempty" json:"driver,omitempty"`
|
||||
DriverOpts map[string]string `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
|
||||
External External `yaml:"external,omitempty" json:"external,omitempty"`
|
||||
Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"`
|
||||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
Name string `yaml:"name,omitempty" json:"name,omitempty"`
|
||||
Driver string `yaml:"driver,omitempty" json:"driver,omitempty"`
|
||||
DriverOpts Options `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
|
||||
External External `yaml:"external,omitempty" json:"external,omitempty"`
|
||||
Labels Labels `yaml:"labels,omitempty" json:"labels,omitempty"`
|
||||
Extensions Extensions `yaml:"#extensions,inline" json:"-"`
|
||||
}
|
||||
|
||||
// External identifies a Volume or Network as a reference to a resource that is
|
||||
|
|
|
@ -118,7 +118,7 @@ github.com/cenkalti/backoff/v4
|
|||
# github.com/cespare/xxhash/v2 v2.2.0
|
||||
## explicit; go 1.11
|
||||
github.com/cespare/xxhash/v2
|
||||
# github.com/compose-spec/compose-go v1.19.0
|
||||
# github.com/compose-spec/compose-go v1.20.0
|
||||
## explicit; go 1.19
|
||||
github.com/compose-spec/compose-go/cli
|
||||
github.com/compose-spec/compose-go/consts
|
||||
|
|
Loading…
Reference in New Issue