func mergeComposeObject()

in pkg/loader/compose/v3.go [725:961]


func mergeComposeObject(oldCompose *types.Config, newCompose *types.Config) (*types.Config, error) {
	if oldCompose == nil || newCompose == nil {
		return nil, fmt.Errorf("merge multiple compose error, compose config is nil")
	}
	oldComposeServiceNameMap := make(map[string]int, len(oldCompose.Services))
	for index, service := range oldCompose.Services {
		oldComposeServiceNameMap[service.Name] = index
	}

	for _, service := range newCompose.Services {
		index := 0
		if tmpIndex, ok := oldComposeServiceNameMap[service.Name]; !ok {
			oldCompose.Services = append(oldCompose.Services, service)
			continue
		} else {
			index = tmpIndex
		}
		tmpOldService := oldCompose.Services[index]
		if service.Build.Dockerfile != "" {
			tmpOldService.Build = service.Build
		}
		if len(service.CapAdd) != 0 {
			tmpOldService.CapAdd = service.CapAdd
		}
		if len(service.CapDrop) != 0 {
			tmpOldService.CapDrop = service.CapDrop
		}
		if service.CgroupParent != "" {
			tmpOldService.CgroupParent = service.CgroupParent
		}
		if len(service.Command) != 0 {
			tmpOldService.Command = service.Command
		}
		if len(service.Configs) != 0 {
			tmpOldService.Configs = service.Configs
		}
		if service.ContainerName != "" {
			tmpOldService.ContainerName = service.ContainerName
		}
		if service.CredentialSpec.File != "" || service.CredentialSpec.Registry != "" {
			tmpOldService.CredentialSpec = service.CredentialSpec
		}
		if len(service.DependsOn) != 0 {
			tmpOldService.DependsOn = service.DependsOn
		}
		if service.Deploy.Mode != "" {
			tmpOldService.Deploy = service.Deploy
		}
		if service.Deploy.Resources.Limits != nil {
			tmpOldService.Deploy.Resources.Limits = service.Deploy.Resources.Limits
		}

		if service.Deploy.Resources.Reservations != nil {
			tmpOldService.Deploy.Resources.Reservations = service.Deploy.Resources.Reservations
		}
		if service.Deploy.Replicas != nil {
			tmpOldService.Deploy.Replicas = service.Deploy.Replicas
		}

		if len(service.Devices) != 0 {
			// merge the 2 sets of values
			// TODO: need to merge the sets based on target values
			// Not implemented yet as we don't convert devices to k8s anyway
			tmpOldService.Devices = service.Devices
		}

		if len(service.DNS) != 0 {
			// concat the 2 sets of values
			tmpOldService.DNS = append(tmpOldService.DNS, service.DNS...)
		}
		if len(service.DNSSearch) != 0 {
			// concat the 2 sets of values
			tmpOldService.DNSSearch = append(tmpOldService.DNSSearch, service.DNSSearch...)
		}
		if service.DomainName != "" {
			tmpOldService.DomainName = service.DomainName
		}
		if len(service.Entrypoint) != 0 {
			tmpOldService.Entrypoint = service.Entrypoint
		}
		if len(service.Environment) != 0 {
			// merge the 2 sets of values
			for k, v := range service.Environment {
				tmpOldService.Environment[k] = v
			}
		}
		if len(service.EnvFile) != 0 {
			tmpOldService.EnvFile = service.EnvFile
		}
		if len(service.Expose) != 0 {
			// concat the 2 sets of values
			tmpOldService.Expose = append(tmpOldService.Expose, service.Expose...)
		}
		if len(service.ExternalLinks) != 0 {
			// concat the 2 sets of values
			tmpOldService.ExternalLinks = append(tmpOldService.ExternalLinks, service.ExternalLinks...)
		}
		if len(service.ExtraHosts) != 0 {
			tmpOldService.ExtraHosts = service.ExtraHosts
		}
		if service.Hostname != "" {
			tmpOldService.Hostname = service.Hostname
		}
		if service.HealthCheck != nil {
			tmpOldService.HealthCheck = service.HealthCheck
		}
		if service.Image != "" {
			tmpOldService.Image = service.Image
		}

		if service.Ipc != "" {
			tmpOldService.Ipc = service.Ipc
		}
		if len(service.Labels) != 0 {
			// merge the 2 sets of values
			if tmpOldService.Labels == nil {
				tmpOldService.Labels = make(map[string]string)
			}
			for k, v := range service.Labels {
				tmpOldService.Labels[k] = v
			}
		}
		if len(service.Links) != 0 {
			tmpOldService.Links = service.Links
		}
		if service.Logging != nil {
			tmpOldService.Logging = service.Logging
		}
		if service.MacAddress != "" {
			tmpOldService.MacAddress = service.MacAddress
		}
		if service.NetworkMode != "" {
			tmpOldService.NetworkMode = service.NetworkMode
		}
		if len(service.Networks) != 0 {
			tmpOldService.Networks = service.Networks
		}
		if service.Pid != "" {
			tmpOldService.Pid = service.Pid
		}
		if len(service.Ports) != 0 {
			// concat the 2 sets of values
			tmpOldService.Ports = append(tmpOldService.Ports, service.Ports...)
		}
		if service.Privileged != tmpOldService.Privileged {
			tmpOldService.Privileged = service.Privileged
		}
		if service.ReadOnly != tmpOldService.ReadOnly {
			tmpOldService.ReadOnly = service.ReadOnly
		}
		if service.Restart != "" {
			tmpOldService.Restart = service.Restart
		}
		if len(service.Secrets) != 0 {
			tmpOldService.Secrets = service.Secrets
		}
		if len(service.SecurityOpt) != 0 {
			tmpOldService.SecurityOpt = service.SecurityOpt
		}
		if service.StdinOpen != tmpOldService.StdinOpen {
			tmpOldService.StdinOpen = service.StdinOpen
		}
		if service.StopSignal != "" {
			tmpOldService.StopSignal = service.StopSignal
		}
		if len(service.Tmpfs) != 0 {
			// concat the 2 sets of values
			tmpOldService.Tmpfs = append(tmpOldService.Tmpfs, service.Tmpfs...)
		}
		if service.Tty != tmpOldService.Tty {
			tmpOldService.Tty = service.Tty
		}
		if len(service.Ulimits) != 0 {
			tmpOldService.Ulimits = service.Ulimits
		}
		if service.User != "" {
			tmpOldService.User = service.User
		}
		if len(service.Volumes) != 0 {
			// merge the 2 sets of values

			// Store volumes by Target
			volumeConfigsMap := make(map[string]types.ServiceVolumeConfig)
			// map is not iterated in the same order.
			// but why only this code cause test error?
			var keys []string

			// populate the older values
			for _, volConfig := range tmpOldService.Volumes {
				volumeConfigsMap[volConfig.Target] = volConfig
				keys = append(keys, volConfig.Target)
			}
			// add the new values, overriding as needed
			for _, volConfig := range service.Volumes {
				if _, ok := volumeConfigsMap[volConfig.Target]; !ok {
					keys = append(keys, volConfig.Target)
				}
				volumeConfigsMap[volConfig.Target] = volConfig
			}

			// get the new list of volume configs
			var volumes []types.ServiceVolumeConfig

			for _, key := range keys {
				volumes = append(volumes, volumeConfigsMap[key])
			}

			tmpOldService.Volumes = volumes
		}
		if service.WorkingDir != "" {
			tmpOldService.WorkingDir = service.WorkingDir
		}
		oldCompose.Services[index] = tmpOldService
	}

	// Merge the networks information
	for idx, network := range newCompose.Networks {
		oldCompose.Networks[idx] = network
	}

	// Merge the volumes information
	for idx, volume := range newCompose.Volumes {
		oldCompose.Volumes[idx] = volume
	}

	// Merge the secrets information
	for idx, secret := range newCompose.Secrets {
		oldCompose.Secrets[idx] = secret
	}

	// Merge the configs information
	for idx, config := range newCompose.Configs {
		oldCompose.Configs[idx] = config
	}

	return oldCompose, nil
}