github.com/ali-iotechsys/cli@v20.10.0+incompatible/cli/compose/types/types.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"time"
     7  )
     8  
     9  // UnsupportedProperties not yet supported by this implementation of the compose file
    10  var UnsupportedProperties = []string{
    11  	"build",
    12  	"cgroupns_mode",
    13  	"cgroup_parent",
    14  	"devices",
    15  	"domainname",
    16  	"external_links",
    17  	"ipc",
    18  	"links",
    19  	"mac_address",
    20  	"network_mode",
    21  	"pid",
    22  	"privileged",
    23  	"restart",
    24  	"security_opt",
    25  	"shm_size",
    26  	"userns_mode",
    27  }
    28  
    29  // DeprecatedProperties that were removed from the v3 format, but their
    30  // use should not impact the behaviour of the application.
    31  var DeprecatedProperties = map[string]string{
    32  	"container_name": "Setting the container name is not supported.",
    33  	"expose":         "Exposing ports is unnecessary - services on the same network can access each other's containers on any port.",
    34  }
    35  
    36  // ForbiddenProperties that are not supported in this implementation of the
    37  // compose file.
    38  var ForbiddenProperties = map[string]string{
    39  	"extends":       "Support for `extends` is not implemented yet.",
    40  	"volume_driver": "Instead of setting the volume driver on the service, define a volume using the top-level `volumes` option and specify the driver there.",
    41  	"volumes_from":  "To share a volume between services, define it using the top-level `volumes` option and reference it from each service that shares it using the service-level `volumes` option.",
    42  	"cpu_quota":     "Set resource limits using deploy.resources",
    43  	"cpu_shares":    "Set resource limits using deploy.resources",
    44  	"cpuset":        "Set resource limits using deploy.resources",
    45  	"mem_limit":     "Set resource limits using deploy.resources",
    46  	"memswap_limit": "Set resource limits using deploy.resources",
    47  }
    48  
    49  // ConfigFile is a filename and the contents of the file as a Dict
    50  type ConfigFile struct {
    51  	Filename string
    52  	Config   map[string]interface{}
    53  }
    54  
    55  // ConfigDetails are the details about a group of ConfigFiles
    56  type ConfigDetails struct {
    57  	Version     string
    58  	WorkingDir  string
    59  	ConfigFiles []ConfigFile
    60  	Environment map[string]string
    61  }
    62  
    63  // Duration is a thin wrapper around time.Duration with improved JSON marshalling
    64  type Duration time.Duration
    65  
    66  func (d Duration) String() string {
    67  	return time.Duration(d).String()
    68  }
    69  
    70  // ConvertDurationPtr converts a typedefined Duration pointer to a time.Duration pointer with the same value.
    71  func ConvertDurationPtr(d *Duration) *time.Duration {
    72  	if d == nil {
    73  		return nil
    74  	}
    75  	res := time.Duration(*d)
    76  	return &res
    77  }
    78  
    79  // MarshalJSON makes Duration implement json.Marshaler
    80  func (d Duration) MarshalJSON() ([]byte, error) {
    81  	return json.Marshal(d.String())
    82  }
    83  
    84  // MarshalYAML makes Duration implement yaml.Marshaler
    85  func (d Duration) MarshalYAML() (interface{}, error) {
    86  	return d.String(), nil
    87  }
    88  
    89  // LookupEnv provides a lookup function for environment variables
    90  func (cd ConfigDetails) LookupEnv(key string) (string, bool) {
    91  	v, ok := cd.Environment[key]
    92  	return v, ok
    93  }
    94  
    95  // Config is a full compose file configuration
    96  type Config struct {
    97  	Filename string                     `yaml:"-" json:"-"`
    98  	Version  string                     `json:"version"`
    99  	Services Services                   `json:"services"`
   100  	Networks map[string]NetworkConfig   `yaml:",omitempty" json:"networks,omitempty"`
   101  	Volumes  map[string]VolumeConfig    `yaml:",omitempty" json:"volumes,omitempty"`
   102  	Secrets  map[string]SecretConfig    `yaml:",omitempty" json:"secrets,omitempty"`
   103  	Configs  map[string]ConfigObjConfig `yaml:",omitempty" json:"configs,omitempty"`
   104  	Extras   map[string]interface{}     `yaml:",inline" json:"-"`
   105  }
   106  
   107  // MarshalJSON makes Config implement json.Marshaler
   108  func (c Config) MarshalJSON() ([]byte, error) {
   109  	m := map[string]interface{}{
   110  		"version":  c.Version,
   111  		"services": c.Services,
   112  	}
   113  
   114  	if len(c.Networks) > 0 {
   115  		m["networks"] = c.Networks
   116  	}
   117  	if len(c.Volumes) > 0 {
   118  		m["volumes"] = c.Volumes
   119  	}
   120  	if len(c.Secrets) > 0 {
   121  		m["secrets"] = c.Secrets
   122  	}
   123  	if len(c.Configs) > 0 {
   124  		m["configs"] = c.Configs
   125  	}
   126  	for k, v := range c.Extras {
   127  		m[k] = v
   128  	}
   129  	return json.Marshal(m)
   130  }
   131  
   132  // Services is a list of ServiceConfig
   133  type Services []ServiceConfig
   134  
   135  // MarshalYAML makes Services implement yaml.Marshaller
   136  func (s Services) MarshalYAML() (interface{}, error) {
   137  	services := map[string]ServiceConfig{}
   138  	for _, service := range s {
   139  		services[service.Name] = service
   140  	}
   141  	return services, nil
   142  }
   143  
   144  // MarshalJSON makes Services implement json.Marshaler
   145  func (s Services) MarshalJSON() ([]byte, error) {
   146  	data, err := s.MarshalYAML()
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	return json.MarshalIndent(data, "", "  ")
   151  }
   152  
   153  // ServiceConfig is the configuration of one service
   154  type ServiceConfig struct {
   155  	Name string `yaml:"-" json:"-"`
   156  
   157  	Build           BuildConfig                      `yaml:",omitempty" json:"build,omitempty"`
   158  	CapAdd          []string                         `mapstructure:"cap_add" yaml:"cap_add,omitempty" json:"cap_add,omitempty"`
   159  	CapDrop         []string                         `mapstructure:"cap_drop" yaml:"cap_drop,omitempty" json:"cap_drop,omitempty"`
   160  	CgroupNSMode    string                           `mapstructure:"cgroupns_mode" yaml:"cgroupns_mode,omitempty" json:"cgroupns_mode,omitempty"`
   161  	CgroupParent    string                           `mapstructure:"cgroup_parent" yaml:"cgroup_parent,omitempty" json:"cgroup_parent,omitempty"`
   162  	Command         ShellCommand                     `yaml:",omitempty" json:"command,omitempty"`
   163  	Configs         []ServiceConfigObjConfig         `yaml:",omitempty" json:"configs,omitempty"`
   164  	ContainerName   string                           `mapstructure:"container_name" yaml:"container_name,omitempty" json:"container_name,omitempty"`
   165  	CredentialSpec  CredentialSpecConfig             `mapstructure:"credential_spec" yaml:"credential_spec,omitempty" json:"credential_spec,omitempty"`
   166  	DependsOn       []string                         `mapstructure:"depends_on" yaml:"depends_on,omitempty" json:"depends_on,omitempty"`
   167  	Deploy          DeployConfig                     `yaml:",omitempty" json:"deploy,omitempty"`
   168  	Devices         []string                         `yaml:",omitempty" json:"devices,omitempty"`
   169  	DNS             StringList                       `yaml:",omitempty" json:"dns,omitempty"`
   170  	DNSSearch       StringList                       `mapstructure:"dns_search" yaml:"dns_search,omitempty" json:"dns_search,omitempty"`
   171  	DomainName      string                           `mapstructure:"domainname" yaml:"domainname,omitempty" json:"domainname,omitempty"`
   172  	Entrypoint      ShellCommand                     `yaml:",omitempty" json:"entrypoint,omitempty"`
   173  	Environment     MappingWithEquals                `yaml:",omitempty" json:"environment,omitempty"`
   174  	EnvFile         StringList                       `mapstructure:"env_file" yaml:"env_file,omitempty" json:"env_file,omitempty"`
   175  	Expose          StringOrNumberList               `yaml:",omitempty" json:"expose,omitempty"`
   176  	ExternalLinks   []string                         `mapstructure:"external_links" yaml:"external_links,omitempty" json:"external_links,omitempty"`
   177  	ExtraHosts      HostsList                        `mapstructure:"extra_hosts" yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"`
   178  	Hostname        string                           `yaml:",omitempty" json:"hostname,omitempty"`
   179  	HealthCheck     *HealthCheckConfig               `yaml:",omitempty" json:"healthcheck,omitempty"`
   180  	Image           string                           `yaml:",omitempty" json:"image,omitempty"`
   181  	Init            *bool                            `yaml:",omitempty" json:"init,omitempty"`
   182  	Ipc             string                           `yaml:",omitempty" json:"ipc,omitempty"`
   183  	Isolation       string                           `mapstructure:"isolation" yaml:"isolation,omitempty" json:"isolation,omitempty"`
   184  	Labels          Labels                           `yaml:",omitempty" json:"labels,omitempty"`
   185  	Links           []string                         `yaml:",omitempty" json:"links,omitempty"`
   186  	Logging         *LoggingConfig                   `yaml:",omitempty" json:"logging,omitempty"`
   187  	MacAddress      string                           `mapstructure:"mac_address" yaml:"mac_address,omitempty" json:"mac_address,omitempty"`
   188  	NetworkMode     string                           `mapstructure:"network_mode" yaml:"network_mode,omitempty" json:"network_mode,omitempty"`
   189  	Networks        map[string]*ServiceNetworkConfig `yaml:",omitempty" json:"networks,omitempty"`
   190  	Pid             string                           `yaml:",omitempty" json:"pid,omitempty"`
   191  	Ports           []ServicePortConfig              `yaml:",omitempty" json:"ports,omitempty"`
   192  	Privileged      bool                             `yaml:",omitempty" json:"privileged,omitempty"`
   193  	ReadOnly        bool                             `mapstructure:"read_only" yaml:"read_only,omitempty" json:"read_only,omitempty"`
   194  	Restart         string                           `yaml:",omitempty" json:"restart,omitempty"`
   195  	Secrets         []ServiceSecretConfig            `yaml:",omitempty" json:"secrets,omitempty"`
   196  	SecurityOpt     []string                         `mapstructure:"security_opt" yaml:"security_opt,omitempty" json:"security_opt,omitempty"`
   197  	ShmSize         string                           `mapstructure:"shm_size" yaml:"shm_size,omitempty" json:"shm_size,omitempty"`
   198  	StdinOpen       bool                             `mapstructure:"stdin_open" yaml:"stdin_open,omitempty" json:"stdin_open,omitempty"`
   199  	StopGracePeriod *Duration                        `mapstructure:"stop_grace_period" yaml:"stop_grace_period,omitempty" json:"stop_grace_period,omitempty"`
   200  	StopSignal      string                           `mapstructure:"stop_signal" yaml:"stop_signal,omitempty" json:"stop_signal,omitempty"`
   201  	Sysctls         Mapping                          `yaml:",omitempty" json:"sysctls,omitempty"`
   202  	Tmpfs           StringList                       `yaml:",omitempty" json:"tmpfs,omitempty"`
   203  	Tty             bool                             `mapstructure:"tty" yaml:"tty,omitempty" json:"tty,omitempty"`
   204  	Ulimits         map[string]*UlimitsConfig        `yaml:",omitempty" json:"ulimits,omitempty"`
   205  	User            string                           `yaml:",omitempty" json:"user,omitempty"`
   206  	UserNSMode      string                           `mapstructure:"userns_mode" yaml:"userns_mode,omitempty" json:"userns_mode,omitempty"`
   207  	Volumes         []ServiceVolumeConfig            `yaml:",omitempty" json:"volumes,omitempty"`
   208  	WorkingDir      string                           `mapstructure:"working_dir" yaml:"working_dir,omitempty" json:"working_dir,omitempty"`
   209  
   210  	Extras map[string]interface{} `yaml:",inline" json:"-"`
   211  }
   212  
   213  // BuildConfig is a type for build
   214  // using the same format at libcompose: https://github.com/docker/libcompose/blob/master/yaml/build.go#L12
   215  type BuildConfig struct {
   216  	Context    string            `yaml:",omitempty" json:"context,omitempty"`
   217  	Dockerfile string            `yaml:",omitempty" json:"dockerfile,omitempty"`
   218  	Args       MappingWithEquals `yaml:",omitempty" json:"args,omitempty"`
   219  	Labels     Labels            `yaml:",omitempty" json:"labels,omitempty"`
   220  	CacheFrom  StringList        `mapstructure:"cache_from" yaml:"cache_from,omitempty" json:"cache_from,omitempty"`
   221  	ExtraHosts HostsList         `mapstructure:"extra_hosts" yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"`
   222  	Network    string            `yaml:",omitempty" json:"network,omitempty"`
   223  	Target     string            `yaml:",omitempty" json:"target,omitempty"`
   224  }
   225  
   226  // ShellCommand is a string or list of string args
   227  type ShellCommand []string
   228  
   229  // StringList is a type for fields that can be a string or list of strings
   230  type StringList []string
   231  
   232  // StringOrNumberList is a type for fields that can be a list of strings or
   233  // numbers
   234  type StringOrNumberList []string
   235  
   236  // MappingWithEquals is a mapping type that can be converted from a list of
   237  // key[=value] strings.
   238  // For the key with an empty value (`key=`), the mapped value is set to a pointer to `""`.
   239  // For the key without value (`key`), the mapped value is set to nil.
   240  type MappingWithEquals map[string]*string
   241  
   242  // Mapping is a mapping type that can be converted from a list of
   243  // key[=value] strings.
   244  // For the key with an empty value (`key=`), or key without value (`key`), the
   245  // mapped value is set to an empty string `""`.
   246  type Mapping map[string]string
   247  
   248  // Labels is a mapping type for labels
   249  type Labels map[string]string
   250  
   251  // MappingWithColon is a mapping type that can be converted from a list of
   252  // 'key: value' strings
   253  type MappingWithColon map[string]string
   254  
   255  // HostsList is a list of colon-separated host-ip mappings
   256  type HostsList []string
   257  
   258  // LoggingConfig the logging configuration for a service
   259  type LoggingConfig struct {
   260  	Driver  string            `yaml:",omitempty" json:"driver,omitempty"`
   261  	Options map[string]string `yaml:",omitempty" json:"options,omitempty"`
   262  }
   263  
   264  // DeployConfig the deployment configuration for a service
   265  type DeployConfig struct {
   266  	Mode           string         `yaml:",omitempty" json:"mode,omitempty"`
   267  	Replicas       *uint64        `yaml:",omitempty" json:"replicas,omitempty"`
   268  	Labels         Labels         `yaml:",omitempty" json:"labels,omitempty"`
   269  	UpdateConfig   *UpdateConfig  `mapstructure:"update_config" yaml:"update_config,omitempty" json:"update_config,omitempty"`
   270  	RollbackConfig *UpdateConfig  `mapstructure:"rollback_config" yaml:"rollback_config,omitempty" json:"rollback_config,omitempty"`
   271  	Resources      Resources      `yaml:",omitempty" json:"resources,omitempty"`
   272  	RestartPolicy  *RestartPolicy `mapstructure:"restart_policy" yaml:"restart_policy,omitempty" json:"restart_policy,omitempty"`
   273  	Placement      Placement      `yaml:",omitempty" json:"placement,omitempty"`
   274  	EndpointMode   string         `mapstructure:"endpoint_mode" yaml:"endpoint_mode,omitempty" json:"endpoint_mode,omitempty"`
   275  }
   276  
   277  // HealthCheckConfig the healthcheck configuration for a service
   278  type HealthCheckConfig struct {
   279  	Test        HealthCheckTest `yaml:",omitempty" json:"test,omitempty"`
   280  	Timeout     *Duration       `yaml:",omitempty" json:"timeout,omitempty"`
   281  	Interval    *Duration       `yaml:",omitempty" json:"interval,omitempty"`
   282  	Retries     *uint64         `yaml:",omitempty" json:"retries,omitempty"`
   283  	StartPeriod *Duration       `mapstructure:"start_period" yaml:"start_period,omitempty" json:"start_period,omitempty"`
   284  	Disable     bool            `yaml:",omitempty" json:"disable,omitempty"`
   285  }
   286  
   287  // HealthCheckTest is the command run to test the health of a service
   288  type HealthCheckTest []string
   289  
   290  // UpdateConfig the service update configuration
   291  type UpdateConfig struct {
   292  	Parallelism     *uint64  `yaml:",omitempty" json:"parallelism,omitempty"`
   293  	Delay           Duration `yaml:",omitempty" json:"delay,omitempty"`
   294  	FailureAction   string   `mapstructure:"failure_action" yaml:"failure_action,omitempty" json:"failure_action,omitempty"`
   295  	Monitor         Duration `yaml:",omitempty" json:"monitor,omitempty"`
   296  	MaxFailureRatio float32  `mapstructure:"max_failure_ratio" yaml:"max_failure_ratio,omitempty" json:"max_failure_ratio,omitempty"`
   297  	Order           string   `yaml:",omitempty" json:"order,omitempty"`
   298  }
   299  
   300  // Resources the resource limits and reservations
   301  type Resources struct {
   302  	Limits       *ResourceLimit `yaml:",omitempty" json:"limits,omitempty"`
   303  	Reservations *Resource      `yaml:",omitempty" json:"reservations,omitempty"`
   304  }
   305  
   306  // ResourceLimit is a resource to be limited
   307  type ResourceLimit struct {
   308  	// TODO: types to convert from units and ratios
   309  	NanoCPUs    string    `mapstructure:"cpus" yaml:"cpus,omitempty" json:"cpus,omitempty"`
   310  	MemoryBytes UnitBytes `mapstructure:"memory" yaml:"memory,omitempty" json:"memory,omitempty"`
   311  	Pids        int64     `mapstructure:"pids" yaml:"pids,omitempty" json:"pids,omitempty"`
   312  }
   313  
   314  // Resource is a resource to be reserved
   315  type Resource struct {
   316  	// TODO: types to convert from units and ratios
   317  	NanoCPUs         string            `mapstructure:"cpus" yaml:"cpus,omitempty" json:"cpus,omitempty"`
   318  	MemoryBytes      UnitBytes         `mapstructure:"memory" yaml:"memory,omitempty" json:"memory,omitempty"`
   319  	GenericResources []GenericResource `mapstructure:"generic_resources" yaml:"generic_resources,omitempty" json:"generic_resources,omitempty"`
   320  }
   321  
   322  // GenericResource represents a "user defined" resource which can
   323  // only be an integer (e.g: SSD=3) for a service
   324  type GenericResource struct {
   325  	DiscreteResourceSpec *DiscreteGenericResource `mapstructure:"discrete_resource_spec" yaml:"discrete_resource_spec,omitempty" json:"discrete_resource_spec,omitempty"`
   326  }
   327  
   328  // DiscreteGenericResource represents a "user defined" resource which is defined
   329  // as an integer
   330  // "Kind" is used to describe the Kind of a resource (e.g: "GPU", "FPGA", "SSD", ...)
   331  // Value is used to count the resource (SSD=5, HDD=3, ...)
   332  type DiscreteGenericResource struct {
   333  	Kind  string `json:"kind"`
   334  	Value int64  `json:"value"`
   335  }
   336  
   337  // UnitBytes is the bytes type
   338  type UnitBytes int64
   339  
   340  // MarshalYAML makes UnitBytes implement yaml.Marshaller
   341  func (u UnitBytes) MarshalYAML() (interface{}, error) {
   342  	return fmt.Sprintf("%d", u), nil
   343  }
   344  
   345  // MarshalJSON makes UnitBytes implement json.Marshaler
   346  func (u UnitBytes) MarshalJSON() ([]byte, error) {
   347  	return []byte(fmt.Sprintf(`"%d"`, u)), nil
   348  }
   349  
   350  // RestartPolicy the service restart policy
   351  type RestartPolicy struct {
   352  	Condition   string    `yaml:",omitempty" json:"condition,omitempty"`
   353  	Delay       *Duration `yaml:",omitempty" json:"delay,omitempty"`
   354  	MaxAttempts *uint64   `mapstructure:"max_attempts" yaml:"max_attempts,omitempty" json:"max_attempts,omitempty"`
   355  	Window      *Duration `yaml:",omitempty" json:"window,omitempty"`
   356  }
   357  
   358  // Placement constraints for the service
   359  type Placement struct {
   360  	Constraints []string               `yaml:",omitempty" json:"constraints,omitempty"`
   361  	Preferences []PlacementPreferences `yaml:",omitempty" json:"preferences,omitempty"`
   362  	MaxReplicas uint64                 `mapstructure:"max_replicas_per_node" yaml:"max_replicas_per_node,omitempty" json:"max_replicas_per_node,omitempty"`
   363  }
   364  
   365  // PlacementPreferences is the preferences for a service placement
   366  type PlacementPreferences struct {
   367  	Spread string `yaml:",omitempty" json:"spread,omitempty"`
   368  }
   369  
   370  // ServiceNetworkConfig is the network configuration for a service
   371  type ServiceNetworkConfig struct {
   372  	Aliases     []string `yaml:",omitempty" json:"aliases,omitempty"`
   373  	Ipv4Address string   `mapstructure:"ipv4_address" yaml:"ipv4_address,omitempty" json:"ipv4_address,omitempty"`
   374  	Ipv6Address string   `mapstructure:"ipv6_address" yaml:"ipv6_address,omitempty" json:"ipv6_address,omitempty"`
   375  }
   376  
   377  // ServicePortConfig is the port configuration for a service
   378  type ServicePortConfig struct {
   379  	Mode      string `yaml:",omitempty" json:"mode,omitempty"`
   380  	Target    uint32 `yaml:",omitempty" json:"target,omitempty"`
   381  	Published uint32 `yaml:",omitempty" json:"published,omitempty"`
   382  	Protocol  string `yaml:",omitempty" json:"protocol,omitempty"`
   383  }
   384  
   385  // ServiceVolumeConfig are references to a volume used by a service
   386  type ServiceVolumeConfig struct {
   387  	Type        string               `yaml:",omitempty" json:"type,omitempty"`
   388  	Source      string               `yaml:",omitempty" json:"source,omitempty"`
   389  	Target      string               `yaml:",omitempty" json:"target,omitempty"`
   390  	ReadOnly    bool                 `mapstructure:"read_only" yaml:"read_only,omitempty" json:"read_only,omitempty"`
   391  	Consistency string               `yaml:",omitempty" json:"consistency,omitempty"`
   392  	Bind        *ServiceVolumeBind   `yaml:",omitempty" json:"bind,omitempty"`
   393  	Volume      *ServiceVolumeVolume `yaml:",omitempty" json:"volume,omitempty"`
   394  	Tmpfs       *ServiceVolumeTmpfs  `yaml:",omitempty" json:"tmpfs,omitempty"`
   395  }
   396  
   397  // ServiceVolumeBind are options for a service volume of type bind
   398  type ServiceVolumeBind struct {
   399  	Propagation string `yaml:",omitempty" json:"propagation,omitempty"`
   400  }
   401  
   402  // ServiceVolumeVolume are options for a service volume of type volume
   403  type ServiceVolumeVolume struct {
   404  	NoCopy bool `mapstructure:"nocopy" yaml:"nocopy,omitempty" json:"nocopy,omitempty"`
   405  }
   406  
   407  // ServiceVolumeTmpfs are options for a service volume of type tmpfs
   408  type ServiceVolumeTmpfs struct {
   409  	Size int64 `yaml:",omitempty" json:"size,omitempty"`
   410  }
   411  
   412  // FileReferenceConfig for a reference to a swarm file object
   413  type FileReferenceConfig struct {
   414  	Source string  `yaml:",omitempty" json:"source,omitempty"`
   415  	Target string  `yaml:",omitempty" json:"target,omitempty"`
   416  	UID    string  `yaml:",omitempty" json:"uid,omitempty"`
   417  	GID    string  `yaml:",omitempty" json:"gid,omitempty"`
   418  	Mode   *uint32 `yaml:",omitempty" json:"mode,omitempty"`
   419  }
   420  
   421  // ServiceConfigObjConfig is the config obj configuration for a service
   422  type ServiceConfigObjConfig FileReferenceConfig
   423  
   424  // ServiceSecretConfig is the secret configuration for a service
   425  type ServiceSecretConfig FileReferenceConfig
   426  
   427  // UlimitsConfig the ulimit configuration
   428  type UlimitsConfig struct {
   429  	Single int `yaml:",omitempty" json:"single,omitempty"`
   430  	Soft   int `yaml:",omitempty" json:"soft,omitempty"`
   431  	Hard   int `yaml:",omitempty" json:"hard,omitempty"`
   432  }
   433  
   434  // MarshalYAML makes UlimitsConfig implement yaml.Marshaller
   435  func (u *UlimitsConfig) MarshalYAML() (interface{}, error) {
   436  	if u.Single != 0 {
   437  		return u.Single, nil
   438  	}
   439  	return u, nil
   440  }
   441  
   442  // MarshalJSON makes UlimitsConfig implement json.Marshaller
   443  func (u *UlimitsConfig) MarshalJSON() ([]byte, error) {
   444  	if u.Single != 0 {
   445  		return json.Marshal(u.Single)
   446  	}
   447  	// Pass as a value to avoid re-entering this method and use the default implementation
   448  	return json.Marshal(*u)
   449  }
   450  
   451  // NetworkConfig for a network
   452  type NetworkConfig struct {
   453  	Name       string                 `yaml:",omitempty" json:"name,omitempty"`
   454  	Driver     string                 `yaml:",omitempty" json:"driver,omitempty"`
   455  	DriverOpts map[string]string      `mapstructure:"driver_opts" yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
   456  	Ipam       IPAMConfig             `yaml:",omitempty" json:"ipam,omitempty"`
   457  	External   External               `yaml:",omitempty" json:"external,omitempty"`
   458  	Internal   bool                   `yaml:",omitempty" json:"internal,omitempty"`
   459  	Attachable bool                   `yaml:",omitempty" json:"attachable,omitempty"`
   460  	Labels     Labels                 `yaml:",omitempty" json:"labels,omitempty"`
   461  	Extras     map[string]interface{} `yaml:",inline" json:"-"`
   462  }
   463  
   464  // IPAMConfig for a network
   465  type IPAMConfig struct {
   466  	Driver string      `yaml:",omitempty" json:"driver,omitempty"`
   467  	Config []*IPAMPool `yaml:",omitempty" json:"config,omitempty"`
   468  }
   469  
   470  // IPAMPool for a network
   471  type IPAMPool struct {
   472  	Subnet string `yaml:",omitempty" json:"subnet,omitempty"`
   473  }
   474  
   475  // VolumeConfig for a volume
   476  type VolumeConfig struct {
   477  	Name       string                 `yaml:",omitempty" json:"name,omitempty"`
   478  	Driver     string                 `yaml:",omitempty" json:"driver,omitempty"`
   479  	DriverOpts map[string]string      `mapstructure:"driver_opts" yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
   480  	External   External               `yaml:",omitempty" json:"external,omitempty"`
   481  	Labels     Labels                 `yaml:",omitempty" json:"labels,omitempty"`
   482  	Extras     map[string]interface{} `yaml:",inline" json:"-"`
   483  }
   484  
   485  // External identifies a Volume or Network as a reference to a resource that is
   486  // not managed, and should already exist.
   487  // External.name is deprecated and replaced by Volume.name
   488  type External struct {
   489  	Name     string `yaml:",omitempty" json:"name,omitempty"`
   490  	External bool   `yaml:",omitempty" json:"external,omitempty"`
   491  }
   492  
   493  // MarshalYAML makes External implement yaml.Marshaller
   494  func (e External) MarshalYAML() (interface{}, error) {
   495  	if e.Name == "" {
   496  		return e.External, nil
   497  	}
   498  	return External{Name: e.Name}, nil
   499  }
   500  
   501  // MarshalJSON makes External implement json.Marshaller
   502  func (e External) MarshalJSON() ([]byte, error) {
   503  	if e.Name == "" {
   504  		return []byte(fmt.Sprintf("%v", e.External)), nil
   505  	}
   506  	return []byte(fmt.Sprintf(`{"name": %q}`, e.Name)), nil
   507  }
   508  
   509  // CredentialSpecConfig for credential spec on Windows
   510  type CredentialSpecConfig struct {
   511  	Config   string `yaml:",omitempty" json:"config,omitempty"` // Config was added in API v1.40
   512  	File     string `yaml:",omitempty" json:"file,omitempty"`
   513  	Registry string `yaml:",omitempty" json:"registry,omitempty"`
   514  }
   515  
   516  // FileObjectConfig is a config type for a file used by a service
   517  type FileObjectConfig struct {
   518  	Name           string                 `yaml:",omitempty" json:"name,omitempty"`
   519  	File           string                 `yaml:",omitempty" json:"file,omitempty"`
   520  	External       External               `yaml:",omitempty" json:"external,omitempty"`
   521  	Labels         Labels                 `yaml:",omitempty" json:"labels,omitempty"`
   522  	Extras         map[string]interface{} `yaml:",inline" json:"-"`
   523  	Driver         string                 `yaml:",omitempty" json:"driver,omitempty"`
   524  	DriverOpts     map[string]string      `mapstructure:"driver_opts" yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
   525  	TemplateDriver string                 `mapstructure:"template_driver" yaml:"template_driver,omitempty" json:"template_driver,omitempty"`
   526  }
   527  
   528  // SecretConfig for a secret
   529  type SecretConfig FileObjectConfig
   530  
   531  // ConfigObjConfig is the config for the swarm "Config" object
   532  type ConfigObjConfig FileObjectConfig