| /* |
| Copyright 2015 The Kubernetes Authors. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| package flocker |
| |
| import ( |
| "fmt" |
| "os" |
| "testing" |
| |
| "k8s.io/api/core/v1" |
| "k8s.io/apimachinery/pkg/types" |
| utiltesting "k8s.io/client-go/util/testing" |
| "k8s.io/kubernetes/pkg/util/mount" |
| "k8s.io/kubernetes/pkg/volume" |
| volumetest "k8s.io/kubernetes/pkg/volume/testing" |
| |
| flockerapi "github.com/clusterhq/flocker-go" |
| "github.com/stretchr/testify/assert" |
| ) |
| |
| const pluginName = "kubernetes.io/flocker" |
| const datasetOneID = "11111111-1111-1111-1111-111111111100" |
| const nodeOneID = "11111111-1111-1111-1111-111111111111" |
| const nodeTwoID = "22222222-2222-2222-2222-222222222222" |
| |
| var _ flockerapi.Clientable = &fakeFlockerClient{} |
| |
| type fakeFlockerClient struct { |
| DatasetID string |
| Primary string |
| Deleted bool |
| Metadata map[string]string |
| Nodes []flockerapi.NodeState |
| Error error |
| } |
| |
| func newFakeFlockerClient() *fakeFlockerClient { |
| return &fakeFlockerClient{ |
| DatasetID: datasetOneID, |
| Primary: nodeOneID, |
| Deleted: false, |
| Metadata: map[string]string{"Name": "dataset-one"}, |
| Nodes: []flockerapi.NodeState{ |
| { |
| Host: "1.2.3.4", |
| UUID: nodeOneID, |
| }, |
| { |
| Host: "4.5.6.7", |
| UUID: nodeTwoID, |
| }, |
| }, |
| } |
| } |
| |
| func (c *fakeFlockerClient) CreateDataset(options *flockerapi.CreateDatasetOptions) (*flockerapi.DatasetState, error) { |
| |
| if c.Error != nil { |
| return nil, c.Error |
| } |
| |
| return &flockerapi.DatasetState{ |
| DatasetID: c.DatasetID, |
| }, nil |
| } |
| |
| func (c *fakeFlockerClient) DeleteDataset(datasetID string) error { |
| c.DatasetID = datasetID |
| c.Deleted = true |
| return nil |
| } |
| |
| func (c *fakeFlockerClient) GetDatasetState(datasetID string) (*flockerapi.DatasetState, error) { |
| return &flockerapi.DatasetState{}, nil |
| } |
| |
| func (c *fakeFlockerClient) GetDatasetID(metaName string) (datasetID string, err error) { |
| if val, ok := c.Metadata["Name"]; !ok { |
| return val, nil |
| } |
| return "", fmt.Errorf("No dataset with metadata X found") |
| } |
| |
| func (c *fakeFlockerClient) GetPrimaryUUID() (primaryUUID string, err error) { |
| return |
| } |
| |
| func (c *fakeFlockerClient) ListNodes() (nodes []flockerapi.NodeState, err error) { |
| return c.Nodes, nil |
| } |
| |
| func (c *fakeFlockerClient) UpdatePrimaryForDataset(primaryUUID, datasetID string) (*flockerapi.DatasetState, error) { |
| return &flockerapi.DatasetState{}, nil |
| } |
| |
| type fakeFlockerUtil struct { |
| } |
| |
| func (fake *fakeFlockerUtil) CreateVolume(c *flockerVolumeProvisioner) (datasetUUID string, volumeSizeGB int, labels map[string]string, err error) { |
| labels = make(map[string]string) |
| labels["fakeflockerutil"] = "yes" |
| return "test-flocker-volume-uuid", 3, labels, nil |
| } |
| |
| func (fake *fakeFlockerUtil) DeleteVolume(cd *flockerVolumeDeleter) error { |
| if cd.datasetUUID != "test-flocker-volume-uuid" { |
| return fmt.Errorf("Deleter got unexpected datasetUUID: %s", cd.datasetUUID) |
| } |
| return nil |
| } |
| |
| func newInitializedVolumePlugMgr(t *testing.T) (*volume.VolumePluginMgr, string) { |
| plugMgr := &volume.VolumePluginMgr{} |
| dir, err := utiltesting.MkTmpdir("flocker") |
| assert.NoError(t, err) |
| plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(dir, nil, nil)) |
| return plugMgr, dir |
| } |
| |
| func TestPlugin(t *testing.T) { |
| tmpDir, err := utiltesting.MkTmpdir("flockerTest") |
| if err != nil { |
| t.Fatalf("can't make a temp dir: %v", err) |
| } |
| defer os.RemoveAll(tmpDir) |
| plugMgr := volume.VolumePluginMgr{} |
| plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(tmpDir, nil, nil)) |
| |
| plug, err := plugMgr.FindPluginByName("kubernetes.io/flocker") |
| if err != nil { |
| t.Errorf("Can't find the plugin by name") |
| } |
| spec := &v1.Volume{ |
| Name: "vol1", |
| VolumeSource: v1.VolumeSource{ |
| Flocker: &v1.FlockerVolumeSource{ |
| DatasetUUID: "uuid1", |
| }, |
| }, |
| } |
| fakeManager := &fakeFlockerUtil{} |
| fakeMounter := &mount.FakeMounter{} |
| mounter, err := plug.(*flockerPlugin).newMounterInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), fakeManager, fakeMounter) |
| if err != nil { |
| t.Errorf("Failed to make a new Mounter: %v", err) |
| } |
| if mounter == nil { |
| t.Errorf("Got a nil Mounter") |
| } |
| } |
| |
| func TestGetByName(t *testing.T) { |
| assert := assert.New(t) |
| plugMgr, dir := newInitializedVolumePlugMgr(t) |
| defer os.RemoveAll(dir) |
| |
| plug, err := plugMgr.FindPluginByName(pluginName) |
| assert.NotNil(plug, "Can't find the plugin by name") |
| assert.NoError(err) |
| } |
| |
| func TestCanSupport(t *testing.T) { |
| assert := assert.New(t) |
| plugMgr, dir := newInitializedVolumePlugMgr(t) |
| defer os.RemoveAll(dir) |
| |
| plug, err := plugMgr.FindPluginByName(pluginName) |
| assert.NoError(err) |
| |
| specs := map[*volume.Spec]bool{ |
| { |
| Volume: &v1.Volume{ |
| VolumeSource: v1.VolumeSource{ |
| Flocker: &v1.FlockerVolumeSource{}, |
| }, |
| }, |
| }: true, |
| { |
| PersistentVolume: &v1.PersistentVolume{ |
| Spec: v1.PersistentVolumeSpec{ |
| PersistentVolumeSource: v1.PersistentVolumeSource{ |
| Flocker: &v1.FlockerVolumeSource{}, |
| }, |
| }, |
| }, |
| }: true, |
| { |
| Volume: &v1.Volume{ |
| VolumeSource: v1.VolumeSource{}, |
| }, |
| }: false, |
| } |
| |
| for spec, expected := range specs { |
| actual := plug.CanSupport(spec) |
| assert.Equal(expected, actual) |
| } |
| } |
| |
| func TestGetFlockerVolumeSource(t *testing.T) { |
| assert := assert.New(t) |
| |
| p := flockerPlugin{} |
| |
| spec := &volume.Spec{ |
| Volume: &v1.Volume{ |
| VolumeSource: v1.VolumeSource{ |
| Flocker: &v1.FlockerVolumeSource{}, |
| }, |
| }, |
| } |
| vs, ro := p.getFlockerVolumeSource(spec) |
| assert.False(ro) |
| assert.Equal(spec.Volume.Flocker, vs) |
| |
| spec = &volume.Spec{ |
| PersistentVolume: &v1.PersistentVolume{ |
| Spec: v1.PersistentVolumeSpec{ |
| PersistentVolumeSource: v1.PersistentVolumeSource{ |
| Flocker: &v1.FlockerVolumeSource{}, |
| }, |
| }, |
| }, |
| } |
| vs, ro = p.getFlockerVolumeSource(spec) |
| assert.False(ro) |
| assert.Equal(spec.PersistentVolume.Spec.Flocker, vs) |
| } |
| |
| func TestNewMounterDatasetName(t *testing.T) { |
| assert := assert.New(t) |
| |
| plugMgr, dir := newInitializedVolumePlugMgr(t) |
| defer os.RemoveAll(dir) |
| plug, err := plugMgr.FindPluginByName(pluginName) |
| assert.NoError(err) |
| |
| spec := &volume.Spec{ |
| Volume: &v1.Volume{ |
| VolumeSource: v1.VolumeSource{ |
| Flocker: &v1.FlockerVolumeSource{ |
| DatasetName: "something", |
| }, |
| }, |
| }, |
| } |
| |
| _, err = plug.NewMounter(spec, &v1.Pod{}, volume.VolumeOptions{}) |
| assert.NoError(err) |
| } |
| |
| func TestNewMounterDatasetUUID(t *testing.T) { |
| assert := assert.New(t) |
| |
| plugMgr, dir := newInitializedVolumePlugMgr(t) |
| defer os.RemoveAll(dir) |
| plug, err := plugMgr.FindPluginByName(pluginName) |
| assert.NoError(err) |
| |
| spec := &volume.Spec{ |
| Volume: &v1.Volume{ |
| VolumeSource: v1.VolumeSource{ |
| Flocker: &v1.FlockerVolumeSource{ |
| DatasetUUID: "uuid1", |
| }, |
| }, |
| }, |
| } |
| |
| mounter, err := plug.NewMounter(spec, &v1.Pod{}, volume.VolumeOptions{}) |
| assert.NoError(err) |
| assert.NotNil(mounter, "got a nil mounter") |
| |
| } |
| |
| func TestNewUnmounter(t *testing.T) { |
| t.Skip("broken") |
| assert := assert.New(t) |
| |
| p := flockerPlugin{} |
| |
| unmounter, err := p.NewUnmounter("", types.UID("")) |
| assert.Nil(unmounter) |
| assert.NoError(err) |
| } |
| |
| func TestIsReadOnly(t *testing.T) { |
| b := &flockerVolumeMounter{readOnly: true} |
| assert.True(t, b.GetAttributes().ReadOnly) |
| } |
| |
| type mockFlockerClient struct { |
| datasetID, primaryUUID, path string |
| datasetState *flockerapi.DatasetState |
| } |
| |
| func newMockFlockerClient(mockDatasetID, mockPrimaryUUID, mockPath string) *mockFlockerClient { |
| return &mockFlockerClient{ |
| datasetID: mockDatasetID, |
| primaryUUID: mockPrimaryUUID, |
| path: mockPath, |
| datasetState: &flockerapi.DatasetState{ |
| Path: mockPath, |
| DatasetID: mockDatasetID, |
| Primary: mockPrimaryUUID, |
| }, |
| } |
| } |
| |
| func (m mockFlockerClient) CreateDataset(metaName string) (*flockerapi.DatasetState, error) { |
| return m.datasetState, nil |
| } |
| func (m mockFlockerClient) GetDatasetState(datasetID string) (*flockerapi.DatasetState, error) { |
| return m.datasetState, nil |
| } |
| func (m mockFlockerClient) GetDatasetID(metaName string) (string, error) { |
| return m.datasetID, nil |
| } |
| func (m mockFlockerClient) GetPrimaryUUID() (string, error) { |
| return m.primaryUUID, nil |
| } |
| func (m mockFlockerClient) UpdatePrimaryForDataset(primaryUUID, datasetID string) (*flockerapi.DatasetState, error) { |
| return m.datasetState, nil |
| } |
| |
| /* |
| TODO: re-enable after refactor |
| func TestSetUpAtInternal(t *testing.T) { |
| const dir = "dir" |
| mockPath := "expected-to-be-set-properly" // package var |
| expectedPath := mockPath |
| |
| assert := assert.New(t) |
| |
| plugMgr, rootDir := newInitializedVolumePlugMgr(t) |
| if rootDir != "" { |
| defer os.RemoveAll(rootDir) |
| } |
| plug, err := plugMgr.FindPluginByName(flockerPluginName) |
| assert.NoError(err) |
| |
| pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}} |
| b := flockerVolumeMounter{flockerVolume: &flockerVolume{pod: pod, plugin: plug.(*flockerPlugin)}} |
| b.client = newMockFlockerClient("dataset-id", "primary-uid", mockPath) |
| |
| assert.NoError(b.SetUpAt(dir, nil)) |
| assert.Equal(expectedPath, b.flocker.path) |
| } |
| */ |