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