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