package dockerCompose type Config struct { Networks map[string]*Network `json:"networks,omitempty" yaml:"networks,omitempty"` Secrets map[string]*Secret `json:"secrets,omitempty" yaml:"secrets,omitempty"` Services map[string]*Service `json:"services,omitempty" yaml:"services,omitempty"` Version string `json:"version,omitempty" yaml:"version,omitempty"` Volumes map[string]*Volume `json:"volumes,omitempty" yaml:"volumes,omitempty"` } // ExistsNetwork returns true if a network with the passed named exists. func (c *Config) ExistsNetwork(name string) bool { return existsKeyInMap(c.Networks, name) } // ExistsSecret returns true if a secret with the passed named exists. func (c *Config) ExistsSecret(name string) bool { return existsKeyInMap(c.Secrets, name) } // ExistsService returns true if a service with the passed named exists. func (c *Config) ExistsService(name string) bool { return existsKeyInMap(c.Services, name) } // ExistsVolumes returns true if a volume with the passed named exists. func (c *Config) ExistsVolume(name string) bool { return existsKeyInMap(c.Volumes, name) } // MergeLastWin merges a config and overwrite already existing properties func (c *Config) MergeLastWin(config *Config) { if c.Version != config.Version { c.Version = config.Version } for networkName, network := range c.Networks { if network == nil { continue } if c.ExistsNetwork(networkName) { c.Networks[networkName].MergeLastWin(network) } else { c.Networks[networkName] = network } } // for secretName, secret := range c.Secrets { // if secret == nil { // continue // } // if c.ExistsSecret(secretName) { // c.Secrets[secretName].MergeLastWin(secret) // } else { // c.Secrets[secretName] = secret // } // } // for serviceName, service := range c.Services { // if service == nil { // continue // } // if c.ExistsService(serviceName) { // c.Services[serviceName].MergeLastWin(service) // } else { // c.Services[serviceName] = service // } // } // for volumeName, volume := range c.Volumes { // if volume == nil { // continue // } // if c.ExistsVolume(volumeName) { // c.Volumes[volumeName].MergeLastWin(volume) // } else { // c.Volumes[volumeName] = volume // } // } } func NewConfig() *Config { return &Config{ Services: make(map[string]*Service), Networks: make(map[string]*Network), Secrets: make(map[string]*Secret), Volumes: make(map[string]*Volume), } } type Network struct { External bool `json:"external,omitempty" yaml:"external,omitempty"` Driver string `json:"driver,omitempty" yaml:"driver,omitempty"` IPAM *NetworkIPAM `json:"ipam,omitempty" yaml:"ipam,omitempty"` } // MergeLastWin merges a network and overwrite already existing properties func (n *Network) MergeLastWin(network *Network) { if n.External != network.External { n.External = network.External } if n.Driver != network.Driver { n.Driver = network.Driver } // n.IPAM.MergeLastWin(network.IPAM.Config) } type NetworkIPAM struct { Config []*NetworkIPAMConfig `json:"config,omitempty" yaml:"config,omitempty"` } func (nipam *NetworkIPAM) Merge(networkIPAM *NetworkIPAM) { if networkIPAM == nil { return } } type NetworkIPAMConfig struct { Subnet string `json:"subnet,omitempty" yaml:"subnet,omitempty"` } type Secret struct { File string `json:"file,omitempty" yaml:"file,omitempty"` } type Service struct { CapabilitiesAdd []string `json:"cap_add,omitempty" yaml:"cap_add,omitempty"` CapabilitiesDrop []string `json:"cap_drop,omitempty" yaml:"cap_drop,omitempty"` Deploy *ServiceDeploy `json:"deploy,omitempty" yaml:"deploy,omitempty"` Environments []string `json:"environment,omitempty" yaml:"environment,omitempty"` ExtraHosts []string `json:"extra_hosts,omitempty" yaml:"extra_hosts,omitempty"` Image string `json:"image,omitempty" yaml:"image,omitempty"` Labels []string `json:"labels,omitempty" yaml:"labels,omitempty"` Networks map[string]*ServiceNetwork `json:"networks,omitempty" yaml:"networks,omitempty"` Ports []string `json:"ports,omitempty" yaml:"ports,omitempty"` Secrets []string `json:"secrets,omitempty" yaml:"secrets,omitempty"` ULimits *ServiceULimits `json:"ulimits,omitempty" yaml:"ulimits,omitempty"` Volumes []string `json:"volumes,omitempty" yaml:"volumes,omitempty"` } type ServiceDeploy struct { Resources *ServiceDeployResources `json:"resources" yaml:"resources"` } type ServiceDeployResources struct { Limits *ServiceDeployResourcesLimits `json:"limits,omitempty" yaml:"limits,omitempty"` Reservations *ServiceDeployResourcesLimits `json:"reservations,omitempty" yaml:"reservations,omitempty"` } type ServiceDeployResourcesLimits struct { CPUs string `json:"cpus,omitempty" yaml:"cpus,omitempty"` Memory string `json:"memory,omitempty" yaml:"memory,omitempty"` } type ServiceNetwork struct { Aliases []string `json:"aliases,omitempty" yaml:"aliases,omitempty"` } // Equal returns true if the passed equalable is equal func (sn *ServiceNetwork) Equal(equalable Equalable) bool { serviceNetwork, ok := equalable.(*ServiceNetwork) if !ok { return false } switch { case sn == nil && serviceNetwork == nil: return true case sn != nil && serviceNetwork == nil: fallthrough case sn == nil && serviceNetwork != nil: return false default: //TODO: return false } } type ServiceULimits struct { NProc uint `json:"nproc,omitempty" yaml:"nproc,omitempty"` NoFile *ServiceULimitsNoFile `json:"nofile,omitempty" yaml:"nofile,omitempty"` } // Equal returns true if the passed equalable is equal func (l *ServiceULimits) Equal(equalable Equalable) bool { serviceULimits, ok := equalable.(*ServiceULimits) if !ok { return false } switch { case l == nil && serviceULimits == nil: return true case l != nil && serviceULimits == nil: fallthrough case l == nil && serviceULimits != nil: return false default: return l.NProc == serviceULimits.NProc && l.NoFile.Equal(serviceULimits.NoFile) } } type ServiceULimitsNoFile struct { Hard uint `json:"hard" yaml:"hard"` Soft uint `json:"soft" yaml:"soft"` } // Equal returns true if the passed equalable is equal func (nf *ServiceULimitsNoFile) Equal(equalable Equalable) bool { serviceULimitsNoFile, ok := equalable.(*ServiceULimitsNoFile) if !ok { return false } switch { case nf == nil && serviceULimitsNoFile == nil: return true case nf != nil && serviceULimitsNoFile == nil: fallthrough case nf == nil && serviceULimitsNoFile != nil: return false default: return nf.Hard == serviceULimitsNoFile.Hard && nf.Soft == serviceULimitsNoFile.Soft } } type Volume struct { External bool `json:"external,omitempty" yaml:"external,omitempty"` } // Equal returns true if the passed equalable is equal func (v *Volume) Equal(equalable Equalable) bool { volume, ok := equalable.(*Volume) if !ok { return false } switch { case v == nil && volume == nil: return true case v != nil && volume == nil: fallthrough case v == nil && volume != nil: return false default: return v.External == volume.External } }