forked from toolshed/abra
		
	
		
			
				
	
	
		
			164 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package convert // https://github.com/docker/cli/blob/master/cli/compose/convert/volume.go
 | |
| 
 | |
| import (
 | |
| 	"coopcloud.tech/abra/pkg/i18n"
 | |
| 	composetypes "github.com/docker/cli/cli/compose/types"
 | |
| 	"github.com/docker/docker/api/types/mount"
 | |
| 	"github.com/pkg/errors"
 | |
| )
 | |
| 
 | |
| type volumes map[string]composetypes.VolumeConfig
 | |
| 
 | |
| // Volumes from compose-file types to engine api types
 | |
| func Volumes(serviceVolumes []composetypes.ServiceVolumeConfig, stackVolumes volumes, namespace Namespace) ([]mount.Mount, error) {
 | |
| 	var mounts []mount.Mount
 | |
| 
 | |
| 	for _, volumeConfig := range serviceVolumes {
 | |
| 		mount, err := convertVolumeToMount(volumeConfig, stackVolumes, namespace)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		mounts = append(mounts, mount)
 | |
| 	}
 | |
| 	return mounts, nil
 | |
| }
 | |
| 
 | |
| func createMountFromVolume(volume composetypes.ServiceVolumeConfig) mount.Mount {
 | |
| 	return mount.Mount{
 | |
| 		Type:        mount.Type(volume.Type),
 | |
| 		Target:      volume.Target,
 | |
| 		ReadOnly:    volume.ReadOnly,
 | |
| 		Source:      volume.Source,
 | |
| 		Consistency: mount.Consistency(volume.Consistency),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func handleVolumeToMount(
 | |
| 	volume composetypes.ServiceVolumeConfig,
 | |
| 	stackVolumes volumes,
 | |
| 	namespace Namespace,
 | |
| ) (mount.Mount, error) {
 | |
| 	result := createMountFromVolume(volume)
 | |
| 
 | |
| 	if volume.Tmpfs != nil {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("tmpfs options are incompatible with type volume"))
 | |
| 	}
 | |
| 	if volume.Bind != nil {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("bind options are incompatible with type volume"))
 | |
| 	}
 | |
| 	// Anonymous volumes
 | |
| 	if volume.Source == "" {
 | |
| 		return result, nil
 | |
| 	}
 | |
| 
 | |
| 	stackVolume, exists := stackVolumes[volume.Source]
 | |
| 	if !exists {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("undefined volume %q", volume.Source))
 | |
| 	}
 | |
| 
 | |
| 	result.Source = namespace.Scope(volume.Source)
 | |
| 	result.VolumeOptions = &mount.VolumeOptions{}
 | |
| 
 | |
| 	if volume.Volume != nil {
 | |
| 		result.VolumeOptions.NoCopy = volume.Volume.NoCopy
 | |
| 	}
 | |
| 
 | |
| 	if stackVolume.Name != "" {
 | |
| 		result.Source = stackVolume.Name
 | |
| 	}
 | |
| 
 | |
| 	// External named volumes
 | |
| 	if stackVolume.External.External {
 | |
| 		return result, nil
 | |
| 	}
 | |
| 
 | |
| 	result.VolumeOptions.Labels = AddStackLabel(namespace, stackVolume.Labels)
 | |
| 	if stackVolume.Driver != "" || stackVolume.DriverOpts != nil {
 | |
| 		result.VolumeOptions.DriverConfig = &mount.Driver{
 | |
| 			Name:    stackVolume.Driver,
 | |
| 			Options: stackVolume.DriverOpts,
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return result, nil
 | |
| }
 | |
| 
 | |
| func handleBindToMount(volume composetypes.ServiceVolumeConfig) (mount.Mount, error) {
 | |
| 	result := createMountFromVolume(volume)
 | |
| 
 | |
| 	if volume.Source == "" {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("invalid bind source, source cannot be empty"))
 | |
| 	}
 | |
| 	if volume.Volume != nil {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("volume options are incompatible with type bind"))
 | |
| 	}
 | |
| 	if volume.Tmpfs != nil {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("tmpfs options are incompatible with type bind"))
 | |
| 	}
 | |
| 	if volume.Bind != nil {
 | |
| 		result.BindOptions = &mount.BindOptions{
 | |
| 			Propagation: mount.Propagation(volume.Bind.Propagation),
 | |
| 		}
 | |
| 	}
 | |
| 	return result, nil
 | |
| }
 | |
| 
 | |
| func handleTmpfsToMount(volume composetypes.ServiceVolumeConfig) (mount.Mount, error) {
 | |
| 	result := createMountFromVolume(volume)
 | |
| 
 | |
| 	if volume.Source != "" {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("invalid tmpfs source, source must be empty"))
 | |
| 	}
 | |
| 	if volume.Bind != nil {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("bind options are incompatible with type tmpfs"))
 | |
| 	}
 | |
| 	if volume.Volume != nil {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("volume options are incompatible with type tmpfs"))
 | |
| 	}
 | |
| 	if volume.Tmpfs != nil {
 | |
| 		result.TmpfsOptions = &mount.TmpfsOptions{
 | |
| 			SizeBytes: volume.Tmpfs.Size,
 | |
| 		}
 | |
| 	}
 | |
| 	return result, nil
 | |
| }
 | |
| 
 | |
| func handleNpipeToMount(volume composetypes.ServiceVolumeConfig) (mount.Mount, error) {
 | |
| 	result := createMountFromVolume(volume)
 | |
| 
 | |
| 	if volume.Source == "" {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("invalid npipe source, source cannot be empty"))
 | |
| 	}
 | |
| 	if volume.Volume != nil {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("volume options are incompatible with type npipe"))
 | |
| 	}
 | |
| 	if volume.Tmpfs != nil {
 | |
| 		return mount.Mount{}, errors.New(i18n.G("tmpfs options are incompatible with type npipe"))
 | |
| 	}
 | |
| 	if volume.Bind != nil {
 | |
| 		result.BindOptions = &mount.BindOptions{
 | |
| 			Propagation: mount.Propagation(volume.Bind.Propagation),
 | |
| 		}
 | |
| 	}
 | |
| 	return result, nil
 | |
| }
 | |
| 
 | |
| func convertVolumeToMount(
 | |
| 	volume composetypes.ServiceVolumeConfig,
 | |
| 	stackVolumes volumes,
 | |
| 	namespace Namespace,
 | |
| ) (mount.Mount, error) {
 | |
| 
 | |
| 	switch volume.Type {
 | |
| 	case "volume", "":
 | |
| 		return handleVolumeToMount(volume, stackVolumes, namespace)
 | |
| 	case "bind":
 | |
| 		return handleBindToMount(volume)
 | |
| 	case "tmpfs":
 | |
| 		return handleTmpfsToMount(volume)
 | |
| 	case "npipe":
 | |
| 		return handleNpipeToMount(volume)
 | |
| 	}
 | |
| 	return mount.Mount{}, errors.New(i18n.G("volume type must be volume, bind, tmpfs or npipe"))
 | |
| }
 |