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