github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/daemon/cluster/convert/volume.go (about)

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