github.com/docker/libcompose@v0.4.1-0.20210616120443-2a046c0bdbf2/yaml/volume.go (about) 1 package yaml 2 3 import ( 4 "errors" 5 "fmt" 6 "sort" 7 "strings" 8 ) 9 10 // Volumes represents a list of service volumes in compose file. 11 // It has several representation, hence this specific struct. 12 type Volumes struct { 13 Volumes []*Volume 14 } 15 16 // Volume represent a service volume 17 type Volume struct { 18 Source string `yaml:"-"` 19 Destination string `yaml:"-"` 20 AccessMode string `yaml:"-"` 21 } 22 23 // Generate a hash string to detect service volume config changes 24 func (v *Volumes) HashString() string { 25 if v == nil { 26 return "" 27 } 28 result := []string{} 29 for _, vol := range v.Volumes { 30 result = append(result, vol.String()) 31 } 32 sort.Strings(result) 33 return strings.Join(result, ",") 34 } 35 36 // String implements the Stringer interface. 37 func (v *Volume) String() string { 38 var paths []string 39 if v.Source != "" { 40 paths = []string{v.Source, v.Destination} 41 } else { 42 paths = []string{v.Destination} 43 } 44 if v.AccessMode != "" { 45 paths = append(paths, v.AccessMode) 46 } 47 return strings.Join(paths, ":") 48 } 49 50 // MarshalYAML implements the Marshaller interface. 51 func (v Volumes) MarshalYAML() (interface{}, error) { 52 vs := []string{} 53 for _, volume := range v.Volumes { 54 vs = append(vs, volume.String()) 55 } 56 return vs, nil 57 } 58 59 // UnmarshalYAML implements the Unmarshaller interface. 60 func (v *Volumes) UnmarshalYAML(unmarshal func(interface{}) error) error { 61 var sliceType []interface{} 62 if err := unmarshal(&sliceType); err == nil { 63 v.Volumes = []*Volume{} 64 for _, volume := range sliceType { 65 name, ok := volume.(string) 66 if !ok { 67 return fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", name, name) 68 } 69 elts := strings.SplitN(name, ":", 3) 70 var vol *Volume 71 switch { 72 case len(elts) == 1: 73 vol = &Volume{ 74 Destination: elts[0], 75 } 76 case len(elts) == 2: 77 vol = &Volume{ 78 Source: elts[0], 79 Destination: elts[1], 80 } 81 case len(elts) == 3: 82 vol = &Volume{ 83 Source: elts[0], 84 Destination: elts[1], 85 AccessMode: elts[2], 86 } 87 default: 88 // FIXME 89 return fmt.Errorf("") 90 } 91 v.Volumes = append(v.Volumes, vol) 92 } 93 return nil 94 } 95 96 return errors.New("Failed to unmarshal Volumes") 97 }