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