Merge pull request #1866 from crazy-max/bump-compose

vendor: github.com/compose-spec/compose-go v1.14.0
This commit is contained in:
CrazyMax 2023-06-07 14:55:55 +02:00 committed by GitHub
commit 5d94b0fcc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 701 additions and 405 deletions

4
go.mod
View File

@ -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
View File

@ -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=

View File

@ -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"])
}
}
}

View File

@ -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

View File

@ -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
}
}

View File

@ -8,6 +8,8 @@ services:
RUN echo "hello" > /world.txt
foo:
annotations:
- com.example.foo=bar
build:
context: ./dir
dockerfile: Dockerfile

View File

@ -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) {

View File

@ -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
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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]))
}

View File

@ -83,6 +83,7 @@
"properties": {
"deploy": {"$ref": "#/definitions/deployment"},
"annotations": {"$ref": "#/definitions/list_or_dict"},
"build": {
"oneOf": [
{"type": "string"},

View File

@ -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>)))",

67
vendor/github.com/compose-spec/compose-go/tree/path.go generated vendored Normal file
View File

@ -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
}

View File

@ -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)

View File

@ -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

5
vendor/modules.txt vendored
View File

@ -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