github.com/artisanhe/tools@v1.0.1-0.20210607022958-19a8fef2eb04/docker/volume.go (about)

     1  package docker
     2  
     3  import (
     4  	"fmt"
     5  	"path"
     6  	"strings"
     7  )
     8  
     9  type VolumeAccessMode string
    10  
    11  const (
    12  	VolumeAccessModeReadWrite = "rw"
    13  	VolumeAccessModeReadOnly  = "ro"
    14  )
    15  
    16  type Volume struct {
    17  	Name       string
    18  	LocalPath  string
    19  	MountPath  string
    20  	AccessMode VolumeAccessMode
    21  }
    22  
    23  func (v Volume) ReadOnly() bool {
    24  	return v.AccessMode == VolumeAccessModeReadOnly
    25  }
    26  
    27  func (v Volume) IsMountFromStorage() bool {
    28  	return v.Name != ""
    29  }
    30  
    31  func (v Volume) IsMountFromLocal() bool {
    32  	return v.LocalPath != ""
    33  }
    34  
    35  func (v Volume) IsProvider() bool {
    36  	return v.LocalPath == "" && v.Name == ""
    37  }
    38  
    39  func isRel(p string) bool {
    40  	return len(p) > 0 && p[0] == '.'
    41  }
    42  
    43  func ParseVolumeString(s string) (*Volume, error) {
    44  	v := Volume{}
    45  	values := strings.Split(s, ":")
    46  
    47  	if values[0] == "container" {
    48  		values = values[1:]
    49  	}
    50  
    51  	accessMode := strings.ToLower(values[len(values)-1])
    52  	if accessMode == VolumeAccessModeReadOnly || accessMode == VolumeAccessModeReadWrite {
    53  		v.AccessMode = VolumeAccessMode(accessMode)
    54  		values = values[0 : len(values)-1]
    55  	}
    56  
    57  	mouthPath := values[len(values)-1]
    58  
    59  	if path.IsAbs(mouthPath) {
    60  		v.MountPath = mouthPath
    61  		if len(values) == 2 {
    62  			if path.IsAbs(values[0]) || isRel(values[0]) {
    63  				v.LocalPath = values[0]
    64  			} else {
    65  				v.Name = values[0]
    66  			}
    67  		}
    68  	} else {
    69  		v.Name = values[0]
    70  	}
    71  
    72  	if v.AccessMode == "" {
    73  		if !v.IsProvider() {
    74  			v.AccessMode = VolumeAccessModeReadWrite
    75  		}
    76  	}
    77  
    78  	return &v, nil
    79  }
    80  
    81  func (v Volume) String() string {
    82  	if v.AccessMode == "" {
    83  		v.AccessMode = VolumeAccessModeReadWrite
    84  	}
    85  
    86  	if v.IsMountFromLocal() {
    87  		return fmt.Sprintf("%s:%s:%s", v.LocalPath, v.MountPath, v.AccessMode)
    88  	}
    89  	if v.IsMountFromStorage() {
    90  		if v.MountPath != "" {
    91  			return fmt.Sprintf("%s:%s:%s", v.Name, v.MountPath, v.AccessMode)
    92  		}
    93  		return fmt.Sprintf("%s:%s", v.Name, v.AccessMode)
    94  	}
    95  	return v.MountPath
    96  }
    97  
    98  func (v Volume) MarshalYAML() (interface{}, error) {
    99  	return v.String(), nil
   100  }
   101  
   102  func (v *Volume) UnmarshalYAML(unmarshal func(interface{}) error) error {
   103  	var s string
   104  	err := unmarshal(&s)
   105  	if err == nil {
   106  		volume, err := ParseVolumeString(s)
   107  		if err != nil {
   108  			return err
   109  		}
   110  		*v = *volume
   111  	}
   112  	return nil
   113  }