volume.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. package convert // import "github.com/docker/docker/daemon/cluster/convert"
  2. import (
  3. volumetypes "github.com/docker/docker/api/types/volume"
  4. gogotypes "github.com/gogo/protobuf/types"
  5. swarmapi "github.com/moby/swarmkit/v2/api"
  6. )
  7. // VolumeFromGRPC converts a swarmkit api Volume object to a docker api Volume
  8. // object
  9. func VolumeFromGRPC(v *swarmapi.Volume) volumetypes.Volume {
  10. clusterVolumeSpec := volumetypes.ClusterVolumeSpec{
  11. Group: v.Spec.Group,
  12. AccessMode: accessModeFromGRPC(v.Spec.AccessMode),
  13. AccessibilityRequirements: topologyRequirementFromGRPC(v.Spec.AccessibilityRequirements),
  14. CapacityRange: capacityRangeFromGRPC(v.Spec.CapacityRange),
  15. Secrets: volumeSecretsFromGRPC(v.Spec.Secrets),
  16. Availability: volumeAvailabilityFromGRPC(v.Spec.Availability),
  17. }
  18. clusterVolume := &volumetypes.ClusterVolume{
  19. ID: v.ID,
  20. Spec: clusterVolumeSpec,
  21. PublishStatus: volumePublishStatusFromGRPC(v.PublishStatus),
  22. Info: volumeInfoFromGRPC(v.VolumeInfo),
  23. }
  24. clusterVolume.Version.Index = v.Meta.Version.Index
  25. clusterVolume.CreatedAt, _ = gogotypes.TimestampFromProto(v.Meta.CreatedAt)
  26. clusterVolume.UpdatedAt, _ = gogotypes.TimestampFromProto(v.Meta.UpdatedAt)
  27. return volumetypes.Volume{
  28. ClusterVolume: clusterVolume,
  29. CreatedAt: clusterVolume.CreatedAt.String(),
  30. Driver: v.Spec.Driver.Name,
  31. Labels: v.Spec.Annotations.Labels,
  32. Name: v.Spec.Annotations.Name,
  33. Options: v.Spec.Driver.Options,
  34. Scope: "global",
  35. }
  36. }
  37. func volumeSpecToGRPC(spec volumetypes.ClusterVolumeSpec) *swarmapi.VolumeSpec {
  38. swarmSpec := &swarmapi.VolumeSpec{
  39. Group: spec.Group,
  40. }
  41. if spec.AccessMode != nil {
  42. swarmSpec.AccessMode = &swarmapi.VolumeAccessMode{}
  43. switch spec.AccessMode.Scope {
  44. case volumetypes.ScopeSingleNode:
  45. swarmSpec.AccessMode.Scope = swarmapi.VolumeScopeSingleNode
  46. case volumetypes.ScopeMultiNode:
  47. swarmSpec.AccessMode.Scope = swarmapi.VolumeScopeMultiNode
  48. }
  49. switch spec.AccessMode.Sharing {
  50. case volumetypes.SharingNone:
  51. swarmSpec.AccessMode.Sharing = swarmapi.VolumeSharingNone
  52. case volumetypes.SharingReadOnly:
  53. swarmSpec.AccessMode.Sharing = swarmapi.VolumeSharingReadOnly
  54. case volumetypes.SharingOneWriter:
  55. swarmSpec.AccessMode.Sharing = swarmapi.VolumeSharingOneWriter
  56. case volumetypes.SharingAll:
  57. swarmSpec.AccessMode.Sharing = swarmapi.VolumeSharingAll
  58. }
  59. if spec.AccessMode.BlockVolume != nil {
  60. swarmSpec.AccessMode.AccessType = &swarmapi.VolumeAccessMode_Block{
  61. Block: &swarmapi.VolumeAccessMode_BlockVolume{},
  62. }
  63. }
  64. if spec.AccessMode.MountVolume != nil {
  65. swarmSpec.AccessMode.AccessType = &swarmapi.VolumeAccessMode_Mount{
  66. Mount: &swarmapi.VolumeAccessMode_MountVolume{
  67. FsType: spec.AccessMode.MountVolume.FsType,
  68. MountFlags: spec.AccessMode.MountVolume.MountFlags,
  69. },
  70. }
  71. }
  72. }
  73. for _, secret := range spec.Secrets {
  74. swarmSpec.Secrets = append(swarmSpec.Secrets, &swarmapi.VolumeSecret{
  75. Key: secret.Key,
  76. Secret: secret.Secret,
  77. })
  78. }
  79. if spec.AccessibilityRequirements != nil {
  80. swarmSpec.AccessibilityRequirements = &swarmapi.TopologyRequirement{}
  81. for _, top := range spec.AccessibilityRequirements.Requisite {
  82. swarmSpec.AccessibilityRequirements.Requisite = append(
  83. swarmSpec.AccessibilityRequirements.Requisite,
  84. &swarmapi.Topology{
  85. Segments: top.Segments,
  86. },
  87. )
  88. }
  89. for _, top := range spec.AccessibilityRequirements.Preferred {
  90. swarmSpec.AccessibilityRequirements.Preferred = append(
  91. swarmSpec.AccessibilityRequirements.Preferred,
  92. &swarmapi.Topology{
  93. Segments: top.Segments,
  94. },
  95. )
  96. }
  97. }
  98. if spec.CapacityRange != nil {
  99. swarmSpec.CapacityRange = &swarmapi.CapacityRange{
  100. RequiredBytes: spec.CapacityRange.RequiredBytes,
  101. LimitBytes: spec.CapacityRange.LimitBytes,
  102. }
  103. }
  104. // availability is not a pointer, it is a value. if the user does not
  105. // specify an availability, it will be inferred as the 0-value, which is
  106. // "active".
  107. switch spec.Availability {
  108. case volumetypes.AvailabilityActive:
  109. swarmSpec.Availability = swarmapi.VolumeAvailabilityActive
  110. case volumetypes.AvailabilityPause:
  111. swarmSpec.Availability = swarmapi.VolumeAvailabilityPause
  112. case volumetypes.AvailabilityDrain:
  113. swarmSpec.Availability = swarmapi.VolumeAvailabilityDrain
  114. }
  115. return swarmSpec
  116. }
  117. // VolumeCreateToGRPC takes a VolumeCreateBody and outputs the matching
  118. // swarmapi VolumeSpec.
  119. func VolumeCreateToGRPC(volume *volumetypes.CreateOptions) *swarmapi.VolumeSpec {
  120. var swarmSpec *swarmapi.VolumeSpec
  121. if volume != nil && volume.ClusterVolumeSpec != nil {
  122. swarmSpec = volumeSpecToGRPC(*volume.ClusterVolumeSpec)
  123. } else {
  124. swarmSpec = &swarmapi.VolumeSpec{}
  125. }
  126. swarmSpec.Annotations = swarmapi.Annotations{
  127. Name: volume.Name,
  128. Labels: volume.Labels,
  129. }
  130. swarmSpec.Driver = &swarmapi.Driver{
  131. Name: volume.Driver,
  132. Options: volume.DriverOpts,
  133. }
  134. return swarmSpec
  135. }
  136. func volumeInfoFromGRPC(info *swarmapi.VolumeInfo) *volumetypes.Info {
  137. if info == nil {
  138. return nil
  139. }
  140. var accessibleTopology []volumetypes.Topology
  141. if info.AccessibleTopology != nil {
  142. accessibleTopology = make([]volumetypes.Topology, len(info.AccessibleTopology))
  143. for i, top := range info.AccessibleTopology {
  144. accessibleTopology[i] = topologyFromGRPC(top)
  145. }
  146. }
  147. return &volumetypes.Info{
  148. CapacityBytes: info.CapacityBytes,
  149. VolumeContext: info.VolumeContext,
  150. VolumeID: info.VolumeID,
  151. AccessibleTopology: accessibleTopology,
  152. }
  153. }
  154. func volumePublishStatusFromGRPC(publishStatus []*swarmapi.VolumePublishStatus) []*volumetypes.PublishStatus {
  155. if publishStatus == nil {
  156. return nil
  157. }
  158. vps := make([]*volumetypes.PublishStatus, len(publishStatus))
  159. for i, status := range publishStatus {
  160. var state volumetypes.PublishState
  161. switch status.State {
  162. case swarmapi.VolumePublishStatus_PENDING_PUBLISH:
  163. state = volumetypes.StatePending
  164. case swarmapi.VolumePublishStatus_PUBLISHED:
  165. state = volumetypes.StatePublished
  166. case swarmapi.VolumePublishStatus_PENDING_NODE_UNPUBLISH:
  167. state = volumetypes.StatePendingNodeUnpublish
  168. case swarmapi.VolumePublishStatus_PENDING_UNPUBLISH:
  169. state = volumetypes.StatePendingUnpublish
  170. }
  171. vps[i] = &volumetypes.PublishStatus{
  172. NodeID: status.NodeID,
  173. State: state,
  174. PublishContext: status.PublishContext,
  175. }
  176. }
  177. return vps
  178. }
  179. func accessModeFromGRPC(accessMode *swarmapi.VolumeAccessMode) *volumetypes.AccessMode {
  180. if accessMode == nil {
  181. return nil
  182. }
  183. convertedAccessMode := &volumetypes.AccessMode{}
  184. switch accessMode.Scope {
  185. case swarmapi.VolumeScopeSingleNode:
  186. convertedAccessMode.Scope = volumetypes.ScopeSingleNode
  187. case swarmapi.VolumeScopeMultiNode:
  188. convertedAccessMode.Scope = volumetypes.ScopeMultiNode
  189. }
  190. switch accessMode.Sharing {
  191. case swarmapi.VolumeSharingNone:
  192. convertedAccessMode.Sharing = volumetypes.SharingNone
  193. case swarmapi.VolumeSharingReadOnly:
  194. convertedAccessMode.Sharing = volumetypes.SharingReadOnly
  195. case swarmapi.VolumeSharingOneWriter:
  196. convertedAccessMode.Sharing = volumetypes.SharingOneWriter
  197. case swarmapi.VolumeSharingAll:
  198. convertedAccessMode.Sharing = volumetypes.SharingAll
  199. }
  200. if block := accessMode.GetBlock(); block != nil {
  201. convertedAccessMode.BlockVolume = &volumetypes.TypeBlock{}
  202. }
  203. if mount := accessMode.GetMount(); mount != nil {
  204. convertedAccessMode.MountVolume = &volumetypes.TypeMount{
  205. FsType: mount.FsType,
  206. MountFlags: mount.MountFlags,
  207. }
  208. }
  209. return convertedAccessMode
  210. }
  211. func volumeSecretsFromGRPC(secrets []*swarmapi.VolumeSecret) []volumetypes.Secret {
  212. if secrets == nil {
  213. return nil
  214. }
  215. convertedSecrets := make([]volumetypes.Secret, len(secrets))
  216. for i, secret := range secrets {
  217. convertedSecrets[i] = volumetypes.Secret{
  218. Key: secret.Key,
  219. Secret: secret.Secret,
  220. }
  221. }
  222. return convertedSecrets
  223. }
  224. func topologyRequirementFromGRPC(top *swarmapi.TopologyRequirement) *volumetypes.TopologyRequirement {
  225. if top == nil {
  226. return nil
  227. }
  228. convertedTop := &volumetypes.TopologyRequirement{}
  229. if top.Requisite != nil {
  230. convertedTop.Requisite = make([]volumetypes.Topology, len(top.Requisite))
  231. for i, req := range top.Requisite {
  232. convertedTop.Requisite[i] = topologyFromGRPC(req)
  233. }
  234. }
  235. if top.Preferred != nil {
  236. convertedTop.Preferred = make([]volumetypes.Topology, len(top.Preferred))
  237. for i, pref := range top.Preferred {
  238. convertedTop.Preferred[i] = topologyFromGRPC(pref)
  239. }
  240. }
  241. return convertedTop
  242. }
  243. func topologyFromGRPC(top *swarmapi.Topology) volumetypes.Topology {
  244. if top == nil {
  245. return volumetypes.Topology{}
  246. }
  247. return volumetypes.Topology{
  248. Segments: top.Segments,
  249. }
  250. }
  251. func capacityRangeFromGRPC(capacity *swarmapi.CapacityRange) *volumetypes.CapacityRange {
  252. if capacity == nil {
  253. return nil
  254. }
  255. return &volumetypes.CapacityRange{
  256. RequiredBytes: capacity.RequiredBytes,
  257. LimitBytes: capacity.LimitBytes,
  258. }
  259. }
  260. func volumeAvailabilityFromGRPC(availability swarmapi.VolumeSpec_VolumeAvailability) volumetypes.Availability {
  261. switch availability {
  262. case swarmapi.VolumeAvailabilityActive:
  263. return volumetypes.AvailabilityActive
  264. case swarmapi.VolumeAvailabilityPause:
  265. return volumetypes.AvailabilityPause
  266. }
  267. return volumetypes.AvailabilityDrain
  268. }