moby/daemon/cluster/convert/volume_test.go
Drew Erny 240a9fcb83
Add Swarm cluster volume supports
Adds code to support Cluster Volumes in Swarm using CSI drivers.

Signed-off-by: Drew Erny <derny@mirantis.com>
2022-05-13 00:55:44 +02:00

210 lines
5.6 KiB
Go

package convert
import (
"testing"
volumetypes "github.com/docker/docker/api/types/volume"
swarmapi "github.com/moby/swarmkit/v2/api"
"gotest.tools/v3/assert"
)
func TestTopologyFromGRPC(t *testing.T) {
nilTopology := topologyFromGRPC(nil)
assert.DeepEqual(t, nilTopology, volumetypes.Topology{})
swarmTop := &swarmapi.Topology{
Segments: map[string]string{"foo": "bar"},
}
top := topologyFromGRPC(swarmTop)
assert.DeepEqual(t, top.Segments, swarmTop.Segments)
}
func TestCapacityRangeFromGRPC(t *testing.T) {
nilCapacity := capacityRangeFromGRPC(nil)
assert.Assert(t, nilCapacity == nil)
swarmZeroCapacity := &swarmapi.CapacityRange{}
zeroCapacity := capacityRangeFromGRPC(swarmZeroCapacity)
assert.Assert(t, zeroCapacity != nil)
assert.Equal(t, zeroCapacity.RequiredBytes, int64(0))
assert.Equal(t, zeroCapacity.LimitBytes, int64(0))
swarmNonZeroCapacity := &swarmapi.CapacityRange{
RequiredBytes: 1024,
LimitBytes: 2048,
}
nonZeroCapacity := capacityRangeFromGRPC(swarmNonZeroCapacity)
assert.Assert(t, nonZeroCapacity != nil)
assert.Equal(t, nonZeroCapacity.RequiredBytes, int64(1024))
assert.Equal(t, nonZeroCapacity.LimitBytes, int64(2048))
}
func TestVolumeAvailabilityFromGRPC(t *testing.T) {
for _, tc := range []struct {
name string
in swarmapi.VolumeSpec_VolumeAvailability
expected volumetypes.Availability
}{
{
name: "Active",
in: swarmapi.VolumeAvailabilityActive,
expected: volumetypes.AvailabilityActive,
}, {
name: "Pause",
in: swarmapi.VolumeAvailabilityPause,
expected: volumetypes.AvailabilityPause,
}, {
name: "Drain",
in: swarmapi.VolumeAvailabilityDrain,
expected: volumetypes.AvailabilityDrain,
},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {
actual := volumeAvailabilityFromGRPC(tc.in)
assert.Equal(t, actual, tc.expected)
})
}
}
// TestAccessModeFromGRPC tests that the AccessMode type is correctly converted
func TestAccessModeFromGRPC(t *testing.T) {
for _, tc := range []struct {
name string
in *swarmapi.VolumeAccessMode
expected *volumetypes.AccessMode
}{
{
name: "MountVolume",
in: &swarmapi.VolumeAccessMode{
Scope: swarmapi.VolumeScopeSingleNode,
Sharing: swarmapi.VolumeSharingNone,
AccessType: &swarmapi.VolumeAccessMode_Mount{
Mount: &swarmapi.VolumeAccessMode_MountVolume{
FsType: "foo",
// TODO(dperny): maybe don't convert this?
MountFlags: []string{"one", "two"},
},
},
},
expected: &volumetypes.AccessMode{
Scope: volumetypes.ScopeSingleNode,
Sharing: volumetypes.SharingNone,
MountVolume: &volumetypes.TypeMount{
FsType: "foo",
MountFlags: []string{"one", "two"},
},
},
}, {
name: "BlockVolume",
in: &swarmapi.VolumeAccessMode{
Scope: swarmapi.VolumeScopeSingleNode,
Sharing: swarmapi.VolumeSharingNone,
AccessType: &swarmapi.VolumeAccessMode_Block{
Block: &swarmapi.VolumeAccessMode_BlockVolume{},
},
},
expected: &volumetypes.AccessMode{
Scope: volumetypes.ScopeSingleNode,
Sharing: volumetypes.SharingNone,
BlockVolume: &volumetypes.TypeBlock{},
},
},
} {
tc := tc
t.Run(tc.name, func(t *testing.T) {
out := accessModeFromGRPC(tc.in)
assert.DeepEqual(t, tc.expected, out)
})
}
}
// TestVolumeCreateToGRPC tests that a docker-typed VolumeCreateBody is
// correctly converted to a swarm-typed VolumeSpec.
func TestVolumeCreateToGRPC(t *testing.T) {
volume := &volumetypes.CreateOptions{
Driver: "plug1",
DriverOpts: map[string]string{"options": "yeah"},
Labels: map[string]string{"labeled": "yeah"},
Name: "volume1",
}
spec := &volumetypes.ClusterVolumeSpec{
Group: "gronp",
AccessMode: &volumetypes.AccessMode{
Scope: volumetypes.ScopeMultiNode,
Sharing: volumetypes.SharingAll,
MountVolume: &volumetypes.TypeMount{
FsType: "foo",
MountFlags: []string{"one", "two"},
},
},
Secrets: []volumetypes.Secret{
{Key: "key1", Secret: "secret1"},
{Key: "key2", Secret: "secret2"},
},
AccessibilityRequirements: &volumetypes.TopologyRequirement{
Requisite: []volumetypes.Topology{
{Segments: map[string]string{"top1": "yup"}},
{Segments: map[string]string{"top2": "def"}},
{Segments: map[string]string{"top3": "nah"}},
},
Preferred: []volumetypes.Topology{},
},
CapacityRange: &volumetypes.CapacityRange{
RequiredBytes: 1,
LimitBytes: 0,
},
}
volume.ClusterVolumeSpec = spec
swarmSpec := VolumeCreateToGRPC(volume)
assert.Assert(t, swarmSpec != nil)
expectedSwarmSpec := &swarmapi.VolumeSpec{
Annotations: swarmapi.Annotations{
Name: "volume1",
Labels: map[string]string{
"labeled": "yeah",
},
},
Group: "gronp",
Driver: &swarmapi.Driver{
Name: "plug1",
Options: map[string]string{
"options": "yeah",
},
},
AccessMode: &swarmapi.VolumeAccessMode{
Scope: swarmapi.VolumeScopeMultiNode,
Sharing: swarmapi.VolumeSharingAll,
AccessType: &swarmapi.VolumeAccessMode_Mount{
Mount: &swarmapi.VolumeAccessMode_MountVolume{
FsType: "foo",
MountFlags: []string{"one", "two"},
},
},
},
Secrets: []*swarmapi.VolumeSecret{
{Key: "key1", Secret: "secret1"},
{Key: "key2", Secret: "secret2"},
},
AccessibilityRequirements: &swarmapi.TopologyRequirement{
Requisite: []*swarmapi.Topology{
{Segments: map[string]string{"top1": "yup"}},
{Segments: map[string]string{"top2": "def"}},
{Segments: map[string]string{"top3": "nah"}},
},
Preferred: nil,
},
CapacityRange: &swarmapi.CapacityRange{
RequiredBytes: 1,
LimitBytes: 0,
},
}
assert.DeepEqual(t, swarmSpec, expectedSwarmSpec)
}