github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/cli/compose/types/types.go (about)

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