2014-07-16 19:30:51 +00:00
|
|
|
/*
|
|
|
|
Copyright 2014 Google Inc. All rights reserved.
|
2014-07-15 01:39:30 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2014-07-16 19:30:51 +00:00
|
|
|
package volume
|
2014-07-15 01:39:30 +00:00
|
|
|
|
|
|
|
import (
|
2014-07-27 18:38:35 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
2014-08-05 17:58:43 +00:00
|
|
|
"reflect"
|
2014-07-15 01:39:30 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
|
|
|
)
|
|
|
|
|
2014-08-05 17:58:43 +00:00
|
|
|
type MockDiskUtil struct{}
|
|
|
|
|
|
|
|
// TODO(jonesdl) To fully test this, we could create a loopback device
|
|
|
|
// and mount that instead.
|
|
|
|
func (util *MockDiskUtil) AttachDisk(PD *GCEPersistentDisk) error {
|
|
|
|
err := os.MkdirAll(path.Join(PD.RootDir, "global", "pd", PD.PDName), 0750)
|
2014-07-27 18:38:35 +00:00
|
|
|
if err != nil {
|
2014-08-05 17:58:43 +00:00
|
|
|
return err
|
2014-07-27 18:38:35 +00:00
|
|
|
}
|
2014-08-05 17:58:43 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (util *MockDiskUtil) DetachDisk(PD *GCEPersistentDisk, devicePath string) error {
|
|
|
|
err := os.RemoveAll(path.Join(PD.RootDir, "global", "pd", PD.PDName))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type MockMounter struct{}
|
|
|
|
|
|
|
|
func (mounter *MockMounter) Mount(source string, target string, fstype string, flags uintptr, data string) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mounter *MockMounter) Unmount(target string, flags int) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mounter *MockMounter) RefCount(vol Interface) (string, int, error) {
|
|
|
|
return "", 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCreateVolumeBuilders(t *testing.T) {
|
|
|
|
tempDir := "CreateVolumes"
|
2014-07-27 18:38:35 +00:00
|
|
|
createVolumesTests := []struct {
|
|
|
|
volume api.Volume
|
|
|
|
path string
|
|
|
|
podID string
|
|
|
|
}{
|
2014-07-15 01:39:30 +00:00
|
|
|
{
|
2014-07-27 18:38:35 +00:00
|
|
|
api.Volume{
|
|
|
|
Name: "host-dir",
|
|
|
|
Source: &api.VolumeSource{
|
2014-10-01 20:35:21 +00:00
|
|
|
HostDir: &api.HostDir{"/dir/path"},
|
2014-07-27 18:38:35 +00:00
|
|
|
},
|
2014-07-16 19:32:59 +00:00
|
|
|
},
|
2014-07-27 18:38:35 +00:00
|
|
|
"/dir/path",
|
2014-07-29 17:51:59 +00:00
|
|
|
"",
|
2014-07-16 19:32:59 +00:00
|
|
|
},
|
|
|
|
{
|
2014-07-27 18:38:35 +00:00
|
|
|
api.Volume{
|
|
|
|
Name: "empty-dir",
|
|
|
|
Source: &api.VolumeSource{
|
2014-10-01 20:35:21 +00:00
|
|
|
EmptyDir: &api.EmptyDir{},
|
2014-07-27 18:38:35 +00:00
|
|
|
},
|
2014-07-16 19:32:59 +00:00
|
|
|
},
|
2014-07-27 18:38:35 +00:00
|
|
|
path.Join(tempDir, "/my-id/volumes/empty/empty-dir"),
|
|
|
|
"my-id",
|
|
|
|
},
|
2014-08-05 17:58:43 +00:00
|
|
|
{
|
|
|
|
api.Volume{
|
|
|
|
Name: "gce-pd",
|
|
|
|
Source: &api.VolumeSource{
|
|
|
|
GCEPersistentDisk: &api.GCEPersistentDisk{"my-disk", "ext4", 0, false},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
path.Join(tempDir, "/my-id/volumes/gce-pd/gce-pd"),
|
|
|
|
"my-id",
|
|
|
|
},
|
|
|
|
{api.Volume{}, "", ""},
|
2014-07-27 18:38:35 +00:00
|
|
|
{
|
|
|
|
api.Volume{
|
|
|
|
Name: "empty-dir",
|
|
|
|
Source: &api.VolumeSource{},
|
|
|
|
},
|
|
|
|
"",
|
|
|
|
"",
|
2014-07-15 01:39:30 +00:00
|
|
|
},
|
|
|
|
}
|
2014-07-27 18:38:35 +00:00
|
|
|
for _, createVolumesTest := range createVolumesTests {
|
|
|
|
tt := createVolumesTest
|
2014-07-29 17:51:59 +00:00
|
|
|
vb, err := CreateVolumeBuilder(&tt.volume, tt.podID, tempDir)
|
2014-07-27 18:38:35 +00:00
|
|
|
if tt.volume.Source == nil {
|
2014-07-29 17:51:59 +00:00
|
|
|
if vb != nil {
|
2014-07-27 18:38:35 +00:00
|
|
|
t.Errorf("Expected volume to be nil")
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
2014-08-05 17:58:43 +00:00
|
|
|
if tt.volume.Source.HostDir == nil && tt.volume.Source.EmptyDir == nil && tt.volume.Source.GCEPersistentDisk == nil {
|
2014-07-27 18:38:35 +00:00
|
|
|
if err != ErrUnsupportedVolumeType {
|
|
|
|
t.Errorf("Unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Unexpected error: %v", err)
|
|
|
|
}
|
2014-07-29 17:51:59 +00:00
|
|
|
path := vb.GetPath()
|
2014-07-27 18:38:35 +00:00
|
|
|
if path != tt.path {
|
|
|
|
t.Errorf("Unexpected bind path. Expected %v, got %v", tt.path, path)
|
|
|
|
}
|
2014-08-05 17:58:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCreateVolumeCleaners(t *testing.T) {
|
|
|
|
tempDir := "CreateVolumeCleaners"
|
|
|
|
createVolumeCleanerTests := []struct {
|
|
|
|
kind string
|
|
|
|
name string
|
|
|
|
podID string
|
|
|
|
}{
|
|
|
|
{"empty", "empty-vol", "my-id"},
|
|
|
|
{"", "", ""},
|
|
|
|
{"gce-pd", "gce-pd-vol", "my-id"},
|
|
|
|
}
|
|
|
|
for _, tt := range createVolumeCleanerTests {
|
|
|
|
vol, err := CreateVolumeCleaner(tt.kind, tt.name, tt.podID, tempDir)
|
|
|
|
if tt.kind == "" && err != nil && vol == nil {
|
2014-07-29 17:51:59 +00:00
|
|
|
continue
|
2014-07-25 21:17:02 +00:00
|
|
|
}
|
2014-08-05 17:58:43 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Unexpected error occured: %s", err)
|
|
|
|
}
|
|
|
|
actualKind := reflect.TypeOf(vol).Elem().Name()
|
|
|
|
if tt.kind == "empty" && actualKind != "EmptyDir" {
|
|
|
|
t.Errorf("CreateVolumeCleaner returned invalid type. Expected EmptyDirectory, got %v, %v", tt.kind, actualKind)
|
|
|
|
}
|
|
|
|
if tt.kind == "gce-pd" && actualKind != "GCEPersistentDisk" {
|
|
|
|
t.Errorf("CreateVolumeCleaner returned invalid type. Expected PersistentDisk, got %v, %v", tt.kind, actualKind)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetUpAndTearDown(t *testing.T) {
|
|
|
|
tempDir, err := ioutil.TempDir("", "CreateVolumes")
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
fakeID := "my-id"
|
|
|
|
type VolumeTester interface {
|
|
|
|
Builder
|
|
|
|
Cleaner
|
|
|
|
}
|
|
|
|
volumes := []VolumeTester{
|
|
|
|
&EmptyDir{"empty", fakeID, tempDir},
|
|
|
|
&GCEPersistentDisk{"pd", fakeID, tempDir, "pd-disk", "ext4", "", false, &MockDiskUtil{}, &MockMounter{}},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, vol := range volumes {
|
|
|
|
err = vol.SetUp()
|
|
|
|
path := vol.GetPath()
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
|
|
t.Errorf("SetUp() failed, volume path not created: %v", path)
|
|
|
|
}
|
|
|
|
err = vol.TearDown()
|
2014-07-27 18:38:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Unexpected error: %v", err)
|
2014-07-15 01:39:30 +00:00
|
|
|
}
|
2014-07-30 21:04:19 +00:00
|
|
|
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
|
|
|
t.Errorf("TearDown() failed, original volume path not properly removed: %v", path)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetActiveVolumes(t *testing.T) {
|
|
|
|
tempDir, err := ioutil.TempDir("", "CreateVolumes")
|
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
getActiveVolumesTests := []struct {
|
|
|
|
name string
|
|
|
|
podID string
|
|
|
|
kind string
|
|
|
|
identifier string
|
|
|
|
}{
|
|
|
|
{"fakeName", "fakeID", "empty", "fakeID/fakeName"},
|
|
|
|
{"fakeName2", "fakeID2", "empty", "fakeID2/fakeName2"},
|
|
|
|
}
|
|
|
|
expectedIdentifiers := []string{}
|
|
|
|
for _, test := range getActiveVolumesTests {
|
|
|
|
volumeDir := path.Join(tempDir, test.podID, "volumes", test.kind, test.name)
|
|
|
|
os.MkdirAll(volumeDir, 0750)
|
|
|
|
expectedIdentifiers = append(expectedIdentifiers, test.identifier)
|
|
|
|
}
|
|
|
|
volumeMap := GetCurrentVolumes(tempDir)
|
|
|
|
for _, name := range expectedIdentifiers {
|
|
|
|
if _, ok := volumeMap[name]; !ok {
|
|
|
|
t.Errorf("Expected volume map entry not found: %v", name)
|
|
|
|
}
|
2014-07-15 01:39:30 +00:00
|
|
|
}
|
|
|
|
}
|