expand volume.Spec to include full Volume and PV

pull/6/head
markturansky 2015-08-12 15:11:03 -04:00
parent b6f2f396ba
commit 0e7f73ad67
32 changed files with 148 additions and 142 deletions

View File

@ -390,7 +390,7 @@ func (c *mockBinderClient) UpdatePersistentVolumeClaimStatus(claim *api.Persiste
func newMockRecycler(spec *volume.Spec, host volume.VolumeHost) (volume.Recycler, error) {
return &mockRecycler{
path: spec.PersistentVolumeSource.HostPath.Path,
path: spec.PersistentVolume.Spec.HostPath.Path,
}, nil
}

View File

@ -73,7 +73,7 @@ func (vh *volumeHost) NewWrapperCleaner(spec *volume.Spec, podUID types.UID, mou
// Not found but not an error
return nil, nil
}
c, err := plugin.NewCleaner(spec.Name, podUID, mounter)
c, err := plugin.NewCleaner(spec.Name(), podUID, mounter)
if err == nil && c == nil {
return nil, errUnsupportedVolumeType
}
@ -87,7 +87,7 @@ func (vh *volumeHost) GetCloudProvider() cloudprovider.Interface {
func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) {
plugin, err := kl.volumePluginMgr.FindPluginBySpec(spec)
if err != nil {
return nil, fmt.Errorf("can't use volume plugins for %s: %v", spec.Name, err)
return nil, fmt.Errorf("can't use volume plugins for %s: %v", spec.Name(), err)
}
if plugin == nil {
// Not found but not an error
@ -95,9 +95,9 @@ func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *volume.Spec, pod *api.Pod,
}
builder, err := plugin.NewBuilder(spec, pod, opts, mounter)
if err != nil {
return nil, fmt.Errorf("failed to instantiate volume plugin for %s: %v", spec.Name, err)
return nil, fmt.Errorf("failed to instantiate volume plugin for %s: %v", spec.Name(), err)
}
glog.V(3).Infof("Used volume plugin %q for %s", plugin.Name(), spec.Name)
glog.V(3).Infof("Used volume plugin %q for %s", plugin.Name(), spec.Name())
return builder, nil
}

View File

@ -60,7 +60,8 @@ func (plugin *awsElasticBlockStorePlugin) Name() string {
}
func (plugin *awsElasticBlockStorePlugin) CanSupport(spec *volume.Spec) bool {
return spec.PersistentVolumeSource.AWSElasticBlockStore != nil || spec.VolumeSource.AWSElasticBlockStore != nil
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.AWSElasticBlockStore != nil) ||
(spec.Volume != nil && spec.Volume.AWSElasticBlockStore != nil)
}
func (plugin *awsElasticBlockStorePlugin) GetAccessModes() []api.PersistentVolumeAccessMode {
@ -79,11 +80,11 @@ func (plugin *awsElasticBlockStorePlugin) newBuilderInternal(spec *volume.Spec,
// EBSs used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
var readOnly bool
var ebs *api.AWSElasticBlockStoreVolumeSource
if spec.VolumeSource.AWSElasticBlockStore != nil {
ebs = spec.VolumeSource.AWSElasticBlockStore
if spec.Volume != nil && spec.Volume.AWSElasticBlockStore != nil {
ebs = spec.Volume.AWSElasticBlockStore
readOnly = ebs.ReadOnly
} else {
ebs = spec.PersistentVolumeSource.AWSElasticBlockStore
ebs = spec.PersistentVolume.Spec.AWSElasticBlockStore
readOnly = spec.ReadOnly
}
@ -97,7 +98,7 @@ func (plugin *awsElasticBlockStorePlugin) newBuilderInternal(spec *volume.Spec,
return &awsElasticBlockStoreBuilder{
awsElasticBlockStore: &awsElasticBlockStore{
podUID: podUID,
volName: spec.Name,
volName: spec.Name(),
volumeID: volumeID,
manager: manager,
mounter: mounter,

View File

@ -39,10 +39,10 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/aws-ebs" {
t.Errorf("Wrong name: %s", plug.Name())
}
if !plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{}}}}) {
t.Errorf("Expected true")
}
if !plug.CanSupport(&volume.Spec{Name: "foo", PersistentVolumeSource: api.PersistentVolumeSource{AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{}}}}}) {
t.Errorf("Expected true")
}
}

View File

@ -52,7 +52,7 @@ func (plugin *cephfsPlugin) Name() string {
}
func (plugin *cephfsPlugin) CanSupport(spec *volume.Spec) bool {
return spec.VolumeSource.CephFS != nil || spec.PersistentVolumeSource.CephFS != nil
return (spec.Volume != nil && spec.Volume.CephFS != nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.CephFS != nil)
}
func (plugin *cephfsPlugin) GetAccessModes() []api.PersistentVolumeAccessMode {
@ -99,7 +99,7 @@ func (plugin *cephfsPlugin) newBuilderInternal(spec *volume.Spec, podUID types.U
return &cephfsBuilder{
cephfs: &cephfs{
podUID: podUID,
volName: spec.Name,
volName: spec.Name(),
mon: cephvs.Monitors,
secret: secret,
id: id,
@ -125,10 +125,10 @@ func (plugin *cephfsPlugin) newCleanerInternal(volName string, podUID types.UID,
}
func (plugin *cephfsPlugin) getVolumeSource(spec *volume.Spec) *api.CephFSVolumeSource {
if spec.VolumeSource.CephFS != nil {
return spec.VolumeSource.CephFS
if spec.Volume != nil && spec.Volume.CephFS != nil {
return spec.Volume.CephFS
} else {
return spec.PersistentVolumeSource.CephFS
return spec.PersistentVolume.Spec.CephFS
}
}

View File

@ -36,10 +36,10 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/cephfs" {
t.Errorf("Wrong name: %s", plug.Name())
}
if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{}}) {
if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) {
t.Errorf("Expected false")
}
if !plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{CephFS: &api.CephFSVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{CephFS: &api.CephFSVolumeSource{}}}}) {
t.Errorf("Expected true")
}
}

View File

@ -53,7 +53,7 @@ func (plugin *cinderPlugin) Name() string {
}
func (plugin *cinderPlugin) CanSupport(spec *volume.Spec) bool {
return spec.PersistentVolumeSource.Cinder != nil || spec.VolumeSource.Cinder != nil
return (spec.Volume != nil && spec.Volume.Cinder != nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Cinder != nil)
}
func (plugin *cinderPlugin) GetAccessModes() []api.PersistentVolumeAccessMode {
@ -68,10 +68,10 @@ func (plugin *cinderPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume
func (plugin *cinderPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID, manager cdManager, mounter mount.Interface) (volume.Builder, error) {
var cinder *api.CinderVolumeSource
if spec.VolumeSource.Cinder != nil {
cinder = spec.VolumeSource.Cinder
if spec.Volume != nil && spec.Volume.Cinder != nil {
cinder = spec.Volume.Cinder
} else {
cinder = spec.PersistentVolumeSource.Cinder
cinder = spec.PersistentVolume.Spec.Cinder
}
pdName := cinder.VolumeID
@ -81,7 +81,7 @@ func (plugin *cinderPlugin) newBuilderInternal(spec *volume.Spec, podUID types.U
return &cinderVolumeBuilder{
cinderVolume: &cinderVolume{
podUID: podUID,
volName: spec.Name,
volName: spec.Name(),
pdName: pdName,
mounter: mounter,
manager: manager,

View File

@ -37,13 +37,11 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/cinder" {
t.Errorf("Wrong name: %s", plug.Name())
}
if !plug.CanSupport(&volume.Spec{
Name: "foo",
VolumeSource: api.VolumeSource{Cinder: &api.CinderVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{Cinder: &api.CinderVolumeSource{}}}}) {
t.Errorf("Expected true")
}
if !plug.CanSupport(&volume.Spec{Name: "foo", PersistentVolumeSource: api.PersistentVolumeSource{Cinder: &api.CinderVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{Cinder: &api.CinderVolumeSource{}}}}}) {
t.Errorf("Expected true")
}
}

View File

@ -61,19 +61,19 @@ func (plugin *downwardAPIPlugin) Name() string {
}
func (plugin *downwardAPIPlugin) CanSupport(spec *volume.Spec) bool {
return spec.VolumeSource.DownwardAPI != nil
return spec.Volume != nil && spec.Volume.DownwardAPI != nil
}
func (plugin *downwardAPIPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) {
v := &downwardAPIVolume{
volName: spec.Name,
volName: spec.Name(),
pod: pod,
podUID: pod.UID,
plugin: plugin,
mounter: mounter,
}
v.fieldReferenceFileNames = make(map[string]string)
for _, fileInfo := range spec.VolumeSource.DownwardAPI.Items {
for _, fileInfo := range spec.Volume.DownwardAPI.Items {
v.fieldReferenceFileNames[fileInfo.FieldRef.FieldPath] = path.Clean(fileInfo.Path)
}
return &downwardAPIVolumeBuilder{
@ -97,8 +97,7 @@ type downwardAPIVolume struct {
// This is the spec for the volume that this plugin wraps.
var wrappedVolumeSpec = &volume.Spec{
Name: "not-used",
VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageMediumMemory}},
Volume: &api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageMediumMemory}}},
}
// downwardAPIVolumeBuilder fetches info from downward API from the pod

View File

@ -63,7 +63,7 @@ func (plugin *emptyDirPlugin) Name() string {
}
func (plugin *emptyDirPlugin) CanSupport(spec *volume.Spec) bool {
if spec.VolumeSource.EmptyDir != nil {
if spec.Volume != nil && spec.Volume.EmptyDir != nil {
return true
}
return false
@ -75,12 +75,12 @@ func (plugin *emptyDirPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts v
func (plugin *emptyDirPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod, mounter mount.Interface, mountDetector mountDetector, opts volume.VolumeOptions, chconRunner chconRunner) (volume.Builder, error) {
medium := api.StorageMediumDefault
if spec.VolumeSource.EmptyDir != nil { // Support a non-specified source as EmptyDir.
medium = spec.VolumeSource.EmptyDir.Medium
if spec.Volume.EmptyDir != nil { // Support a non-specified source as EmptyDir.
medium = spec.Volume.EmptyDir.Medium
}
return &emptyDir{
pod: pod,
volName: spec.Name,
volName: spec.Name(),
medium: medium,
mounter: mounter,
mountDetector: mountDetector,

View File

@ -47,10 +47,10 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/empty-dir" {
t.Errorf("Wrong name: %s", plug.Name())
}
if !plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}}) {
t.Errorf("Expected true")
}
if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{}}) {
if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) {
t.Errorf("Expected false")
}
}

View File

@ -55,7 +55,8 @@ func (plugin *gcePersistentDiskPlugin) Name() string {
}
func (plugin *gcePersistentDiskPlugin) CanSupport(spec *volume.Spec) bool {
return spec.VolumeSource.GCEPersistentDisk != nil || spec.PersistentVolumeSource.GCEPersistentDisk != nil
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.GCEPersistentDisk != nil) ||
(spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil)
}
func (plugin *gcePersistentDiskPlugin) GetAccessModes() []api.PersistentVolumeAccessMode {
@ -76,11 +77,11 @@ func (plugin *gcePersistentDiskPlugin) newBuilderInternal(spec *volume.Spec, pod
var readOnly bool
var gce *api.GCEPersistentDiskVolumeSource
if spec.VolumeSource.GCEPersistentDisk != nil {
gce = spec.VolumeSource.GCEPersistentDisk
if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
gce = spec.Volume.GCEPersistentDisk
readOnly = gce.ReadOnly
} else {
gce = spec.PersistentVolumeSource.GCEPersistentDisk
gce = spec.PersistentVolume.Spec.GCEPersistentDisk
readOnly = spec.ReadOnly
}
@ -94,7 +95,7 @@ func (plugin *gcePersistentDiskPlugin) newBuilderInternal(spec *volume.Spec, pod
return &gcePersistentDiskBuilder{
gcePersistentDisk: &gcePersistentDisk{
podUID: podUID,
volName: spec.Name,
volName: spec.Name(),
pdName: pdName,
partition: partition,
mounter: mounter,

View File

@ -39,10 +39,10 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/gce-pd" {
t.Errorf("Wrong name: %s", plug.Name())
}
if !plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}}) {
t.Errorf("Expected true")
}
if !plug.CanSupport(&volume.Spec{Name: "foo", PersistentVolumeSource: api.PersistentVolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}}}) {
t.Errorf("Expected true")
}
}

View File

@ -54,20 +54,20 @@ func (plugin *gitRepoPlugin) Name() string {
}
func (plugin *gitRepoPlugin) CanSupport(spec *volume.Spec) bool {
return spec.VolumeSource.GitRepo != nil
return spec.Volume != nil && spec.Volume.GitRepo != nil
}
func (plugin *gitRepoPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) {
return &gitRepoVolumeBuilder{
gitRepoVolume: &gitRepoVolume{
volName: spec.Name,
volName: spec.Name(),
podUID: pod.UID,
mounter: mounter,
plugin: plugin,
},
pod: *pod,
source: spec.VolumeSource.GitRepo.Repository,
revision: spec.VolumeSource.GitRepo.Revision,
source: spec.Volume.GitRepo.Repository,
revision: spec.Volume.GitRepo.Revision,
exec: exec.New(),
opts: opts,
}, nil
@ -124,8 +124,7 @@ func (b *gitRepoVolumeBuilder) IsReadOnly() bool {
// This is the spec for the volume that this plugin wraps.
var wrappedVolumeSpec = &volume.Spec{
Name: "not-used",
VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}},
Volume: &api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
}
// SetUpAt creates new directory and clones a git repo.

View File

@ -51,7 +51,7 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/git-repo" {
t.Errorf("Wrong name: %s", plug.Name())
}
if !plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}}) {
t.Errorf("Expected true")
}
}

View File

@ -54,7 +54,8 @@ func (plugin *glusterfsPlugin) Name() string {
}
func (plugin *glusterfsPlugin) CanSupport(spec *volume.Spec) bool {
return spec.VolumeSource.Glusterfs != nil || spec.PersistentVolumeSource.Glusterfs != nil
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Glusterfs != nil) ||
(spec.Volume != nil && spec.Volume.Glusterfs != nil)
}
func (plugin *glusterfsPlugin) GetAccessModes() []api.PersistentVolumeAccessMode {
@ -81,10 +82,10 @@ func (plugin *glusterfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ vol
func (plugin *glusterfsPlugin) getGlusterVolumeSource(spec *volume.Spec) (*api.GlusterfsVolumeSource, bool) {
// Glusterfs volumes used directly in a pod have a ReadOnly flag set by the pod author.
// Glusterfs volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
if spec.VolumeSource.Glusterfs != nil {
return spec.VolumeSource.Glusterfs, spec.VolumeSource.Glusterfs.ReadOnly
if spec.Volume != nil && spec.Volume.Glusterfs != nil {
return spec.Volume.Glusterfs, spec.Volume.Glusterfs.ReadOnly
} else {
return spec.PersistentVolumeSource.Glusterfs, spec.ReadOnly
return spec.PersistentVolume.Spec.Glusterfs, spec.ReadOnly
}
}
@ -92,7 +93,7 @@ func (plugin *glusterfsPlugin) newBuilderInternal(spec *volume.Spec, ep *api.End
source, readOnly := plugin.getGlusterVolumeSource(spec)
return &glusterfsBuilder{
glusterfs: &glusterfs{
volName: spec.Name,
volName: spec.Name(),
mounter: mounter,
pod: pod,
plugin: plugin,

View File

@ -39,13 +39,13 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/glusterfs" {
t.Errorf("Wrong name: %s", plug.Name())
}
if !plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{}}}}) {
t.Errorf("Expected true")
}
if !plug.CanSupport(&volume.Spec{Name: "foo", PersistentVolumeSource: api.PersistentVolumeSource{Glusterfs: &api.GlusterfsVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{Glusterfs: &api.GlusterfsVolumeSource{}}}}}) {
t.Errorf("Expected true")
}
if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{}}) {
if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) {
t.Errorf("Expected false")
}
}

View File

@ -60,7 +60,8 @@ func (plugin *hostPathPlugin) Name() string {
}
func (plugin *hostPathPlugin) CanSupport(spec *volume.Spec) bool {
return spec.VolumeSource.HostPath != nil || spec.PersistentVolumeSource.HostPath != nil
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.HostPath != nil) ||
(spec.Volume != nil && spec.Volume.HostPath != nil)
}
func (plugin *hostPathPlugin) GetAccessModes() []api.PersistentVolumeAccessMode {
@ -70,14 +71,14 @@ func (plugin *hostPathPlugin) GetAccessModes() []api.PersistentVolumeAccessMode
}
func (plugin *hostPathPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.VolumeOptions, _ mount.Interface) (volume.Builder, error) {
if spec.VolumeSource.HostPath != nil {
if spec.Volume != nil && spec.Volume.HostPath != nil {
return &hostPathBuilder{
hostPath: &hostPath{path: spec.VolumeSource.HostPath.Path},
hostPath: &hostPath{path: spec.Volume.HostPath.Path},
readOnly: false,
}, nil
} else {
return &hostPathBuilder{
hostPath: &hostPath{path: spec.PersistentVolumeSource.HostPath.Path},
hostPath: &hostPath{path: spec.PersistentVolume.Spec.HostPath.Path},
readOnly: spec.ReadOnly,
}, nil
}
@ -92,10 +93,10 @@ func (plugin *hostPathPlugin) NewRecycler(spec *volume.Spec) (volume.Recycler, e
}
func newRecycler(spec *volume.Spec, host volume.VolumeHost) (volume.Recycler, error) {
if spec.PersistentVolumeSource.HostPath == nil {
if spec.PersistentVolume == nil || spec.PersistentVolume.Spec.HostPath == nil {
return nil, fmt.Errorf("spec.PersistentVolumeSource.HostPath is nil")
}
return &hostPathRecycler{spec.Name, spec.PersistentVolumeSource.HostPath.Path, host}, nil
return &hostPathRecycler{spec.Name(), spec.PersistentVolume.Spec.HostPath.Path, host}, nil
}
// HostPath volumes represent a bare host file or directory mount.

View File

@ -37,13 +37,13 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/host-path" {
t.Errorf("Wrong name: %s", plug.Name())
}
if !plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{}}}}) {
t.Errorf("Expected true")
}
if !plug.CanSupport(&volume.Spec{Name: "foo", PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{}}}}}) {
t.Errorf("Expected true")
}
if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{}}) {
if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) {
t.Errorf("Expected false")
}
}
@ -65,7 +65,7 @@ func TestRecycler(t *testing.T) {
plugMgr := volume.VolumePluginMgr{}
plugMgr.InitPlugins([]volume.VolumePlugin{&hostPathPlugin{nil, newMockRecycler}}, volume.NewFakeVolumeHost("/tmp/fake", nil, nil))
spec := &volume.Spec{PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/foo"}}}
spec := &volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/foo"}}}}}
plug, err := plugMgr.FindRecyclablePluginBySpec(spec)
if err != nil {
t.Errorf("Can't find the plugin by name")
@ -74,8 +74,8 @@ func TestRecycler(t *testing.T) {
if err != nil {
t.Errorf("Failed to make a new Recyler: %v", err)
}
if recycler.GetPath() != spec.PersistentVolumeSource.HostPath.Path {
t.Errorf("Expected %s but got %s", spec.PersistentVolumeSource.HostPath.Path, recycler.GetPath())
if recycler.GetPath() != spec.PersistentVolume.Spec.HostPath.Path {
t.Errorf("Expected %s but got %s", spec.PersistentVolume.Spec.HostPath.Path, recycler.GetPath())
}
if err := recycler.Recycle(); err != nil {
t.Errorf("Mock Recycler expected to return nil but got %s", err)
@ -84,7 +84,7 @@ func TestRecycler(t *testing.T) {
func newMockRecycler(spec *volume.Spec, host volume.VolumeHost) (volume.Recycler, error) {
return &mockRecycler{
path: spec.PersistentVolumeSource.HostPath.Path,
path: spec.PersistentVolume.Spec.HostPath.Path,
}, nil
}

View File

@ -54,7 +54,7 @@ func (plugin *iscsiPlugin) Name() string {
}
func (plugin *iscsiPlugin) CanSupport(spec *volume.Spec) bool {
if spec.VolumeSource.ISCSI == nil && spec.PersistentVolumeSource.ISCSI == nil {
if (spec.Volume != nil && spec.Volume.ISCSI == nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.ISCSI == nil) {
return false
}
// TODO: turn this into a func so CanSupport can be unit tested without
@ -85,11 +85,11 @@ func (plugin *iscsiPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UI
// iscsi volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
var readOnly bool
var iscsi *api.ISCSIVolumeSource
if spec.VolumeSource.ISCSI != nil {
iscsi = spec.VolumeSource.ISCSI
if spec.Volume != nil && spec.Volume.ISCSI != nil {
iscsi = spec.Volume.ISCSI
readOnly = iscsi.ReadOnly
} else {
iscsi = spec.PersistentVolumeSource.ISCSI
iscsi = spec.PersistentVolume.Spec.ISCSI
readOnly = spec.ReadOnly
}
@ -98,7 +98,7 @@ func (plugin *iscsiPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UI
return &iscsiDiskBuilder{
iscsiDisk: &iscsiDisk{
podUID: podUID,
volName: spec.Name,
volName: spec.Name(),
portal: iscsi.TargetPortal,
iqn: iscsi.IQN,
lun: lun,

View File

@ -39,7 +39,7 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/iscsi" {
t.Errorf("Wrong name: %s", plug.Name())
}
if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{}}) {
if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) {
t.Errorf("Expected false")
}
}

View File

@ -59,7 +59,8 @@ func (plugin *nfsPlugin) Name() string {
}
func (plugin *nfsPlugin) CanSupport(spec *volume.Spec) bool {
return spec.VolumeSource.NFS != nil || spec.PersistentVolumeSource.NFS != nil
return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.NFS != nil) ||
(spec.Volume != nil && spec.Volume.NFS != nil)
}
func (plugin *nfsPlugin) GetAccessModes() []api.PersistentVolumeAccessMode {
@ -77,16 +78,16 @@ func (plugin *nfsPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.Vo
func (plugin *nfsPlugin) newBuilderInternal(spec *volume.Spec, pod *api.Pod, mounter mount.Interface) (volume.Builder, error) {
var source *api.NFSVolumeSource
var readOnly bool
if spec.VolumeSource.NFS != nil {
source = spec.VolumeSource.NFS
readOnly = spec.VolumeSource.NFS.ReadOnly
if spec.Volume != nil && spec.Volume.NFS != nil {
source = spec.Volume.NFS
readOnly = spec.Volume.NFS.ReadOnly
} else {
source = spec.PersistentVolumeSource.NFS
source = spec.PersistentVolume.Spec.NFS
readOnly = spec.ReadOnly
}
return &nfsBuilder{
nfs: &nfs{
volName: spec.Name,
volName: spec.Name(),
mounter: mounter,
pod: pod,
plugin: plugin,
@ -236,13 +237,13 @@ func (c *nfsCleaner) TearDownAt(dir string) error {
}
func newRecycler(spec *volume.Spec, host volume.VolumeHost) (volume.Recycler, error) {
if spec.PersistentVolumeSource.NFS == nil {
if spec.PersistentVolume == nil || spec.PersistentVolume.Spec.NFS == nil {
return nil, fmt.Errorf("spec.PersistentVolumeSource.NFS is nil")
}
return &nfsRecycler{
name: spec.Name,
server: spec.PersistentVolumeSource.NFS.Server,
path: spec.PersistentVolumeSource.NFS.Path,
name: spec.Name(),
server: spec.PersistentVolume.Spec.NFS.Server,
path: spec.PersistentVolume.Spec.NFS.Path,
host: host,
}, nil
}

View File

@ -38,13 +38,13 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/nfs" {
t.Errorf("Wrong name: %s", plug.Name())
}
if !plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{NFS: &api.NFSVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{NFS: &api.NFSVolumeSource{}}}}) {
t.Errorf("Expected true")
}
if !plug.CanSupport(&volume.Spec{Name: "foo", PersistentVolumeSource: api.PersistentVolumeSource{NFS: &api.NFSVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{NFS: &api.NFSVolumeSource{}}}}}) {
t.Errorf("Expected true")
}
if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{}}) {
if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) {
t.Errorf("Expected false")
}
}
@ -64,9 +64,9 @@ func TestGetAccessModes(t *testing.T) {
func TestRecycler(t *testing.T) {
plugMgr := volume.VolumePluginMgr{}
plugMgr.InitPlugins([]volume.VolumePlugin{&nfsPlugin{newRecyclerFunc: newMockRecycler}}, volume.NewFakeVolumeHost("/tmp/fake", nil, nil))
plugMgr.InitPlugins([]volume.VolumePlugin{&nfsPlugin{nil, newMockRecycler}}, volume.NewFakeVolumeHost("/tmp/fake", nil, nil))
spec := &volume.Spec{PersistentVolumeSource: api.PersistentVolumeSource{NFS: &api.NFSVolumeSource{Path: "/foo"}}}
spec := &volume.Spec{PersistentVolume: &api.PersistentVolume{Spec: api.PersistentVolumeSpec{PersistentVolumeSource: api.PersistentVolumeSource{NFS: &api.NFSVolumeSource{Path: "/foo"}}}}}
plug, err := plugMgr.FindRecyclablePluginBySpec(spec)
if err != nil {
t.Errorf("Can't find the plugin by name")
@ -75,8 +75,8 @@ func TestRecycler(t *testing.T) {
if err != nil {
t.Errorf("Failed to make a new Recyler: %v", err)
}
if recycler.GetPath() != spec.PersistentVolumeSource.NFS.Path {
t.Errorf("Expected %s but got %s", spec.PersistentVolumeSource.NFS.Path, recycler.GetPath())
if recycler.GetPath() != spec.PersistentVolume.Spec.NFS.Path {
t.Errorf("Expected %s but got %s", spec.PersistentVolume.Spec.NFS.Path, recycler.GetPath())
}
if err := recycler.Recycle(); err != nil {
t.Errorf("Mock Recycler expected to return nil but got %s", err)
@ -85,7 +85,7 @@ func TestRecycler(t *testing.T) {
func newMockRecycler(spec *volume.Spec, host volume.VolumeHost) (volume.Recycler, error) {
return &mockRecycler{
path: spec.PersistentVolumeSource.NFS.Path,
path: spec.PersistentVolume.Spec.NFS.Path,
}, nil
}

View File

@ -49,13 +49,13 @@ func (plugin *persistentClaimPlugin) Name() string {
}
func (plugin *persistentClaimPlugin) CanSupport(spec *volume.Spec) bool {
return spec.VolumeSource.PersistentVolumeClaim != nil
return spec.Volume != nil && spec.Volume.PersistentVolumeClaim != nil
}
func (plugin *persistentClaimPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) {
claim, err := plugin.host.GetKubeClient().PersistentVolumeClaims(pod.Namespace).Get(spec.VolumeSource.PersistentVolumeClaim.ClaimName)
claim, err := plugin.host.GetKubeClient().PersistentVolumeClaims(pod.Namespace).Get(spec.Volume.PersistentVolumeClaim.ClaimName)
if err != nil {
glog.Errorf("Error finding claim: %+v\n", spec.VolumeSource.PersistentVolumeClaim.ClaimName)
glog.Errorf("Error finding claim: %+v\n", spec.Volume.PersistentVolumeClaim.ClaimName)
return nil, err
}

View File

@ -51,13 +51,13 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/persistent-claim" {
t.Errorf("Wrong name: %s", plug.Name())
}
if !plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{}}}) {
if !plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{}}}}) {
t.Errorf("Expected true")
}
if plug.CanSupport(&volume.Spec{VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}) {
if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}}) {
t.Errorf("Expected false")
}
if plug.CanSupport(&volume.Spec{VolumeSource: api.VolumeSource{}}) {
if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) {
t.Errorf("Expected false")
}
}
@ -247,10 +247,7 @@ func TestNewBuilder(t *testing.T) {
if err != nil {
t.Errorf("Can't find the plugin by name")
}
spec := &volume.Spec{
Name: "vol1",
VolumeSource: item.podVolume,
}
spec := &volume.Spec{Volume: &api.Volume{VolumeSource: item.podVolume}}
pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
builder, err := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil)
@ -305,10 +302,7 @@ func TestNewBuilderClaimNotBound(t *testing.T) {
if err != nil {
t.Errorf("Can't find the plugin by name")
}
spec := &volume.Spec{
Name: "vol1",
VolumeSource: podVolume,
}
spec := &volume.Spec{Volume: &api.Volume{VolumeSource: podVolume}}
pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("poduid")}}
builder, err := plug.NewBuilder(spec, pod, volume.VolumeOptions{}, nil)
if builder != nil {

View File

@ -135,10 +135,21 @@ type VolumePluginMgr struct {
// Spec is an internal representation of a volume. All API volume types translate to Spec.
type Spec struct {
Name string
VolumeSource api.VolumeSource
PersistentVolumeSource api.PersistentVolumeSource
ReadOnly bool
Volume *api.Volume
PersistentVolume *api.PersistentVolume
ReadOnly bool
}
// Name returns the name of either Volume or PersistentVolume, one of which must not be nil.
func (spec *Spec) Name() string {
switch {
case spec.Volume != nil:
return spec.Volume.Name
case spec.PersistentVolume != nil:
return spec.PersistentVolume.Name
default:
return ""
}
}
// VolumeConfig is how volume plugins receive configuration. An instance specific to the plugin will be passed to
@ -166,17 +177,15 @@ type VolumeConfig struct {
// NewSpecFromVolume creates an Spec from an api.Volume
func NewSpecFromVolume(vs *api.Volume) *Spec {
return &Spec{
Name: vs.Name,
VolumeSource: vs.VolumeSource,
Volume: vs,
}
}
// NewSpecFromPersistentVolume creates an Spec from an api.PersistentVolume
func NewSpecFromPersistentVolume(pv *api.PersistentVolume, readOnly bool) *Spec {
return &Spec{
Name: pv.Name,
PersistentVolumeSource: pv.Spec.PersistentVolumeSource,
ReadOnly: readOnly,
PersistentVolume: pv,
ReadOnly: readOnly,
}
}

View File

@ -29,11 +29,11 @@ func TestSpecSourceConverters(t *testing.T) {
}
converted := NewSpecFromVolume(v)
if converted.VolumeSource.EmptyDir == nil {
if converted.Volume.EmptyDir == nil {
t.Errorf("Unexpected nil EmptyDir: %+v", converted)
}
if v.Name != converted.Name {
t.Errorf("Expected %v but got %v", v.Name, converted.Name)
if v.Name != converted.Name() {
t.Errorf("Expected %v but got %v", v.Name, converted.Name())
}
pv := &api.PersistentVolume{
@ -44,10 +44,10 @@ func TestSpecSourceConverters(t *testing.T) {
}
converted = NewSpecFromPersistentVolume(pv, false)
if converted.PersistentVolumeSource.AWSElasticBlockStore == nil {
if converted.PersistentVolume.Spec.AWSElasticBlockStore == nil {
t.Errorf("Unexpected nil AWSElasticBlockStore: %+v", converted)
}
if pv.Name != converted.Name {
t.Errorf("Expected %v but got %v", pv.Name, converted.Name)
if pv.Name != converted.Name() {
t.Errorf("Expected %v but got %v", pv.Name, converted.Name())
}
}

View File

@ -54,7 +54,7 @@ func (plugin *rbdPlugin) Name() string {
}
func (plugin *rbdPlugin) CanSupport(spec *volume.Spec) bool {
if spec.VolumeSource.RBD == nil && spec.PersistentVolumeSource.RBD == nil {
if (spec.Volume != nil && spec.Volume.RBD == nil) || (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.RBD == nil) {
return false
}
// see if rbd is there
@ -101,10 +101,10 @@ func (plugin *rbdPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, _ volume.Vo
func (plugin *rbdPlugin) getRBDVolumeSource(spec *volume.Spec) (*api.RBDVolumeSource, bool) {
// rbd volumes used directly in a pod have a ReadOnly flag set by the pod author.
// rbd volumes used as a PersistentVolume gets the ReadOnly flag indirectly through the persistent-claim volume used to mount the PV
if spec.VolumeSource.RBD != nil {
return spec.VolumeSource.RBD, spec.VolumeSource.RBD.ReadOnly
if spec.Volume != nil && spec.Volume.RBD != nil {
return spec.Volume.RBD, spec.Volume.RBD.ReadOnly
} else {
return spec.PersistentVolumeSource.RBD, spec.ReadOnly
return spec.PersistentVolume.Spec.RBD, spec.ReadOnly
}
}
@ -126,7 +126,7 @@ func (plugin *rbdPlugin) newBuilderInternal(spec *volume.Spec, podUID types.UID,
return &rbdBuilder{
rbd: &rbd{
podUID: podUID,
volName: spec.Name,
volName: spec.Name(),
Image: source.RBDImage,
Pool: pool,
ReadOnly: readOnly,

View File

@ -39,7 +39,7 @@ func TestCanSupport(t *testing.T) {
if plug.Name() != "kubernetes.io/rbd" {
t.Errorf("Wrong name: %s", plug.Name())
}
if plug.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{}}) {
if plug.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{}}}) {
t.Errorf("Expected false")
}
}

View File

@ -56,13 +56,13 @@ func (plugin *secretPlugin) Name() string {
}
func (plugin *secretPlugin) CanSupport(spec *volume.Spec) bool {
return spec.VolumeSource.Secret != nil
return spec.Volume != nil && spec.Volume.Secret != nil
}
func (plugin *secretPlugin) NewBuilder(spec *volume.Spec, pod *api.Pod, opts volume.VolumeOptions, mounter mount.Interface) (volume.Builder, error) {
return &secretVolumeBuilder{
secretVolume: &secretVolume{spec.Name, pod.UID, plugin, mounter},
secretName: spec.VolumeSource.Secret.SecretName,
secretVolume: &secretVolume{spec.Name(), pod.UID, plugin, mounter},
secretName: spec.Volume.Secret.SecretName,
pod: *pod,
opts: &opts}, nil
}
@ -102,8 +102,7 @@ func (b *secretVolumeBuilder) SetUp() error {
// This is the spec for the volume that this plugin wraps.
var wrappedVolumeSpec = &volume.Spec{
Name: "not-used",
VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageMediumMemory}},
Volume: &api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageMediumMemory}}},
}
func (b *secretVolumeBuilder) getMetaDir() string {

View File

@ -55,9 +55,12 @@ func TestCanSupport(t *testing.T) {
if plugin.Name() != secretPluginName {
t.Errorf("Wrong name: %s", plugin.Name())
}
if !plugin.CanSupport(&volume.Spec{Name: "foo", VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: ""}}}) {
if !plugin.CanSupport(&volume.Spec{Volume: &api.Volume{VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: ""}}}}) {
t.Errorf("Expected true")
}
if plugin.CanSupport(&volume.Spec{}) {
t.Errorf("Expected false")
}
}
func TestPlugin(t *testing.T) {

View File

@ -75,7 +75,7 @@ func (f *fakeVolumeHost) NewWrapperCleaner(spec *Spec, podUID types.UID, mounter
if err != nil {
return nil, err
}
return plug.NewCleaner(spec.Name, podUID, mounter)
return plug.NewCleaner(spec.Name(), podUID, mounter)
}
func ProbeVolumePlugins(config VolumeConfig) []VolumePlugin {
@ -112,12 +112,12 @@ func (plugin *FakeVolumePlugin) Name() string {
}
func (plugin *FakeVolumePlugin) CanSupport(spec *Spec) bool {
// TODO: maybe pattern-match on spec.Name to decide?
// TODO: maybe pattern-match on spec.Name() to decide?
return true
}
func (plugin *FakeVolumePlugin) NewBuilder(spec *Spec, pod *api.Pod, opts VolumeOptions, mounter mount.Interface) (Builder, error) {
return &FakeVolume{pod.UID, spec.Name, plugin}, nil
return &FakeVolume{pod.UID, spec.Name(), plugin}, nil
}
func (plugin *FakeVolumePlugin) NewCleaner(volName string, podUID types.UID, mounter mount.Interface) (Cleaner, error) {