11package convert
22
33import (
4+ "strings"
5+
46 composetypes "github.com/docker/cli/cli/compose/types"
57 "github.com/docker/docker/api/types/mount"
68 "github.com/pkg/errors"
@@ -45,6 +47,9 @@ func handleVolumeToMount(
4547 if volume .Bind != nil {
4648 return mount.Mount {}, errors .New ("bind options are incompatible with type volume" )
4749 }
50+ if volume .Cluster != nil {
51+ return mount.Mount {}, errors .New ("cluster options are incompatible with type volume" )
52+ }
4853 // Anonymous volumes
4954 if volume .Source == "" {
5055 return result , nil
@@ -94,6 +99,9 @@ func handleBindToMount(volume composetypes.ServiceVolumeConfig) (mount.Mount, er
9499 if volume .Tmpfs != nil {
95100 return mount.Mount {}, errors .New ("tmpfs options are incompatible with type bind" )
96101 }
102+ if volume .Cluster != nil {
103+ return mount.Mount {}, errors .New ("cluster options are incompatible with type bind" )
104+ }
97105 if volume .Bind != nil {
98106 result .BindOptions = & mount.BindOptions {
99107 Propagation : mount .Propagation (volume .Bind .Propagation ),
@@ -114,6 +122,9 @@ func handleTmpfsToMount(volume composetypes.ServiceVolumeConfig) (mount.Mount, e
114122 if volume .Volume != nil {
115123 return mount.Mount {}, errors .New ("volume options are incompatible with type tmpfs" )
116124 }
125+ if volume .Cluster != nil {
126+ return mount.Mount {}, errors .New ("cluster options are incompatible with type tmpfs" )
127+ }
117128 if volume .Tmpfs != nil {
118129 result .TmpfsOptions = & mount.TmpfsOptions {
119130 SizeBytes : volume .Tmpfs .Size ,
@@ -142,6 +153,49 @@ func handleNpipeToMount(volume composetypes.ServiceVolumeConfig) (mount.Mount, e
142153 return result , nil
143154}
144155
156+ func handleClusterToMount (
157+ volume composetypes.ServiceVolumeConfig ,
158+ stackVolumes volumes ,
159+ namespace Namespace ,
160+ ) (mount.Mount , error ) {
161+ if volume .Source == "" {
162+ return mount.Mount {}, errors .New ("invalid cluster source, source cannot be empty" )
163+ }
164+ if volume .Tmpfs != nil {
165+ return mount.Mount {}, errors .New ("tmpfs options are incompatible with type cluster" )
166+ }
167+ if volume .Bind != nil {
168+ return mount.Mount {}, errors .New ("bind options are incompatible with type cluster" )
169+ }
170+ if volume .Volume != nil {
171+ return mount.Mount {}, errors .New ("volume options are incompatible with type cluster" )
172+ }
173+
174+ result := createMountFromVolume (volume )
175+ result .ClusterOptions = & mount.ClusterOptions {}
176+
177+ if ! strings .HasPrefix (volume .Source , "group:" ) {
178+ // if the volume is a cluster volume and the source is a volumegroup, we
179+ // will ignore checking to see if such a volume is defined. the volume
180+ // group isn't namespaced, and there's no simple way to indicate that
181+ // external volumes with a given group exist.
182+ stackVolume , exists := stackVolumes [volume .Source ]
183+ if ! exists {
184+ return mount.Mount {}, errors .Errorf ("undefined volume %q" , volume .Source )
185+ }
186+
187+ // if the volume is not specified with a group source, we may namespace
188+ // the name, if one is not otherwise specified.
189+ if stackVolume .Name != "" {
190+ result .Source = stackVolume .Name
191+ } else {
192+ result .Source = namespace .Scope (volume .Source )
193+ }
194+ }
195+
196+ return result , nil
197+ }
198+
145199func convertVolumeToMount (
146200 volume composetypes.ServiceVolumeConfig ,
147201 stackVolumes volumes ,
@@ -156,6 +210,8 @@ func convertVolumeToMount(
156210 return handleTmpfsToMount (volume )
157211 case "npipe" :
158212 return handleNpipeToMount (volume )
213+ case "cluster" :
214+ return handleClusterToMount (volume , stackVolumes , namespace )
159215 }
160- return mount.Mount {}, errors .New ("volume type must be volume, bind, tmpfs or npipe " )
216+ return mount.Mount {}, errors .New ("volume type must be volume, bind, tmpfs, npipe, or cluster " )
161217}
0 commit comments