Merge pull request #5122 from markturansky/volume_interface_improvements

Change volume.NewBuilder podUID argument to ObjectRef
pull/6/head
Daniel Smith 2015-03-10 13:37:49 -07:00
commit a89c1959d4
16 changed files with 53 additions and 34 deletions

View File

@ -780,7 +780,7 @@ func main() {
// 1 pod infra container + 2 pods from the URL + // 1 pod infra container + 2 pods from the URL +
// 1 pod infra container + 1 pod from the service test. // 1 pod infra container + 1 pod from the service test.
if len(createdPods) != 9 { if len(createdPods) != 9 {
glog.Fatalf("Unexpected list of created pods:\n\n%#v\n\n%#v\n\n%#v\n\n", createdPods.List(), fakeDocker1.Created, fakeDocker2.Created) glog.Fatalf("Expected 9 pods; got %v\n\nlist of created pods:\n\n%#v\n\nDocker 1 Created:\n\n%#v\n\nDocker 2 Created:\n\n%#v\n\n", len(createdPods), createdPods.List(), fakeDocker1.Created, fakeDocker2.Created)
} }
glog.Infof("OK - found created pods: %#v", createdPods.List()) glog.Infof("OK - found created pods: %#v", createdPods.List())
} }

View File

@ -40,6 +40,10 @@ func init() {
return nil return nil
}, },
// Convert ContainerManifest to BoundPod // Convert ContainerManifest to BoundPod
//
// This function generates a dummy selfLink using the same method as the
// boundPod registry, in order for the Kubelet to work with well-formed
// boundPods during the integration test.
func(in *ContainerManifest, out *BoundPod, s conversion.Scope) error { func(in *ContainerManifest, out *BoundPod, s conversion.Scope) error {
out.Spec.Containers = in.Containers out.Spec.Containers = in.Containers
out.Spec.Volumes = in.Volumes out.Spec.Volumes = in.Volumes
@ -47,6 +51,11 @@ func init() {
out.Spec.DNSPolicy = in.DNSPolicy out.Spec.DNSPolicy = in.DNSPolicy
out.Name = in.ID out.Name = in.ID
out.UID = in.UUID out.UID = in.UUID
if in.ID != "" {
out.SelfLink = "/api/v1beta1/boundPods/" + in.ID
}
return nil return nil
}, },
func(in *BoundPod, out *ContainerManifest, s conversion.Scope) error { func(in *BoundPod, out *ContainerManifest, s conversion.Scope) error {

View File

@ -137,6 +137,7 @@ func TestExtractFromHTTP(t *testing.T) {
UID: "111", UID: "111",
Name: "foo" + "-" + hostname, Name: "foo" + "-" + hostname,
Namespace: "foobar", Namespace: "foobar",
SelfLink: "/api/v1beta1/boundPods/foo",
}, },
Spec: api.PodSpec{ Spec: api.PodSpec{
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
@ -177,6 +178,7 @@ func TestExtractFromHTTP(t *testing.T) {
UID: "111", UID: "111",
Name: "foo" + "-" + hostname, Name: "foo" + "-" + hostname,
Namespace: "foobar", Namespace: "foobar",
SelfLink: "/api/v1beta1/boundPods/foo",
}, },
Spec: api.PodSpec{ Spec: api.PodSpec{
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
@ -204,6 +206,7 @@ func TestExtractFromHTTP(t *testing.T) {
UID: "111", UID: "111",
Name: "foo" + "-" + hostname, Name: "foo" + "-" + hostname,
Namespace: "foobar", Namespace: "foobar",
SelfLink: "/api/v1beta1/boundPods/foo",
}, },
Spec: api.PodSpec{ Spec: api.PodSpec{
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},
@ -220,6 +223,7 @@ func TestExtractFromHTTP(t *testing.T) {
UID: "222", UID: "222",
Name: "bar" + "-" + hostname, Name: "bar" + "-" + hostname,
Namespace: "foobar", Namespace: "foobar",
SelfLink: "/api/v1beta1/boundPods/bar",
}, },
Spec: api.PodSpec{ Spec: api.PodSpec{
RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}}, RestartPolicy: api.RestartPolicy{Always: &api.RestartPolicyAlways{}},

View File

@ -69,12 +69,12 @@ func (plugin *emptyDirPlugin) CanSupport(spec *api.Volume) bool {
return false return false
} }
func (plugin *emptyDirPlugin) NewBuilder(spec *api.Volume, podUID types.UID) (volume.Builder, error) { func (plugin *emptyDirPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
if plugin.legacyMode { if plugin.legacyMode {
// Legacy mode instances can be cleaned up but not created anew. // Legacy mode instances can be cleaned up but not created anew.
return nil, fmt.Errorf("legacy mode: can not create new instances") return nil, fmt.Errorf("legacy mode: can not create new instances")
} }
return &emptyDir{podUID, spec.Name, plugin, false}, nil return &emptyDir{podRef.UID, spec.Name, plugin, false}, nil
} }
func (plugin *emptyDirPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { func (plugin *emptyDirPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) {

View File

@ -56,7 +56,7 @@ func TestPlugin(t *testing.T) {
Name: "vol1", Name: "vol1",
VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}, VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}},
} }
builder, err := plug.NewBuilder(spec, types.UID("poduid")) builder, err := plug.NewBuilder(spec, &api.ObjectReference{UID: types.UID("poduid")})
if err != nil { if err != nil {
t.Errorf("Failed to make a new Builder: %v", err) t.Errorf("Failed to make a new Builder: %v", err)
} }
@ -109,7 +109,7 @@ func TestPluginBackCompat(t *testing.T) {
spec := &api.Volume{ spec := &api.Volume{
Name: "vol1", Name: "vol1",
} }
builder, err := plug.NewBuilder(spec, types.UID("poduid")) builder, err := plug.NewBuilder(spec, &api.ObjectReference{UID: types.UID("poduid")})
if err != nil { if err != nil {
t.Errorf("Failed to make a new Builder: %v", err) t.Errorf("Failed to make a new Builder: %v", err)
} }
@ -138,7 +138,7 @@ func TestPluginLegacy(t *testing.T) {
t.Errorf("Expected false") t.Errorf("Expected false")
} }
if _, err := plug.NewBuilder(&api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}, types.UID("poduid")); err == nil { if _, err := plug.NewBuilder(&api.Volume{VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}, &api.ObjectReference{UID: types.UID("poduid")}); err == nil {
t.Errorf("Expected failiure") t.Errorf("Expected failiure")
} }

View File

@ -70,9 +70,9 @@ func (plugin *gcePersistentDiskPlugin) CanSupport(spec *api.Volume) bool {
return false return false
} }
func (plugin *gcePersistentDiskPlugin) NewBuilder(spec *api.Volume, podUID types.UID) (volume.Builder, error) { func (plugin *gcePersistentDiskPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
// Inject real implementations here, test through the internal function. // Inject real implementations here, test through the internal function.
return plugin.newBuilderInternal(spec, podUID, &GCEDiskUtil{}, mount.New()) return plugin.newBuilderInternal(spec, podRef.UID, &GCEDiskUtil{}, mount.New())
} }
func (plugin *gcePersistentDiskPlugin) newBuilderInternal(spec *api.Volume, podUID types.UID, manager pdManager, mounter mount.Interface) (volume.Builder, error) { func (plugin *gcePersistentDiskPlugin) newBuilderInternal(spec *api.Volume, podUID types.UID, manager pdManager, mounter mount.Interface) (volume.Builder, error) {

View File

@ -145,7 +145,7 @@ func TestPluginLegacy(t *testing.T) {
t.Errorf("Expected false") t.Errorf("Expected false")
} }
if _, err := plug.NewBuilder(&api.Volume{VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}, types.UID("poduid")); err == nil { if _, err := plug.NewBuilder(&api.Volume{VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}}, &api.ObjectReference{UID: types.UID("poduid")}); err == nil {
t.Errorf("Expected failiure") t.Errorf("Expected failiure")
} }

View File

@ -69,13 +69,13 @@ func (plugin *gitRepoPlugin) CanSupport(spec *api.Volume) bool {
return false return false
} }
func (plugin *gitRepoPlugin) NewBuilder(spec *api.Volume, podUID types.UID) (volume.Builder, error) { func (plugin *gitRepoPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
if plugin.legacyMode { if plugin.legacyMode {
// Legacy mode instances can be cleaned up but not created anew. // Legacy mode instances can be cleaned up but not created anew.
return nil, fmt.Errorf("legacy mode: can not create new instances") return nil, fmt.Errorf("legacy mode: can not create new instances")
} }
return &gitRepo{ return &gitRepo{
podUID: podUID, podUID: podRef.UID,
volName: spec.Name, volName: spec.Name,
source: spec.GitRepo.Repository, source: spec.GitRepo.Repository,
revision: spec.GitRepo.Revision, revision: spec.GitRepo.Revision,

View File

@ -117,7 +117,7 @@ func TestPlugin(t *testing.T) {
}, },
}, },
} }
builder, err := plug.NewBuilder(spec, types.UID("poduid")) builder, err := plug.NewBuilder(spec, &api.ObjectReference{UID: types.UID("poduid")})
if err != nil { if err != nil {
t.Errorf("Failed to make a new Builder: %v", err) t.Errorf("Failed to make a new Builder: %v", err)
} }
@ -172,7 +172,7 @@ func TestPluginLegacy(t *testing.T) {
t.Errorf("Expected false") t.Errorf("Expected false")
} }
if _, err := plug.NewBuilder(&api.Volume{VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}, types.UID("poduid")); err == nil { if _, err := plug.NewBuilder(&api.Volume{VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{}}}, &api.ObjectReference{UID: types.UID("poduid")}); err == nil {
t.Errorf("Expected failiure") t.Errorf("Expected failiure")
} }

View File

@ -52,7 +52,7 @@ func (plugin *hostPathPlugin) CanSupport(spec *api.Volume) bool {
return false return false
} }
func (plugin *hostPathPlugin) NewBuilder(spec *api.Volume, podUID types.UID) (volume.Builder, error) { func (plugin *hostPathPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
return &hostPath{spec.HostPath.Path}, nil return &hostPath{spec.HostPath.Path}, nil
} }

View File

@ -55,7 +55,7 @@ func TestPlugin(t *testing.T) {
Name: "vol1", Name: "vol1",
VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/vol1"}}, VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{"/vol1"}},
} }
builder, err := plug.NewBuilder(spec, types.UID("poduid")) builder, err := plug.NewBuilder(spec, &api.ObjectReference{UID: types.UID("poduid")})
if err != nil { if err != nil {
t.Errorf("Failed to make a new Builder: %v", err) t.Errorf("Failed to make a new Builder: %v", err)
} }

View File

@ -49,8 +49,8 @@ type Plugin interface {
// NewBuilder creates a new volume.Builder from an API specification. // NewBuilder creates a new volume.Builder from an API specification.
// Ownership of the spec pointer in *not* transferred. // Ownership of the spec pointer in *not* transferred.
// - spec: The api.Volume spec // - spec: The api.Volume spec
// - podUID: The UID of the enclosing pod // - podRef: a reference to the enclosing pod
NewBuilder(spec *api.Volume, podUID types.UID) (Builder, error) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (Builder, error)
// NewCleaner creates a new volume.Cleaner from recoverable state. // NewCleaner creates a new volume.Cleaner from recoverable state.
// - name: The volume name, as per the api.Volume spec. // - name: The volume name, as per the api.Volume spec.

View File

@ -58,12 +58,12 @@ func (plugin *secretPlugin) CanSupport(spec *api.Volume) bool {
return false return false
} }
func (plugin *secretPlugin) NewBuilder(spec *api.Volume, podUID types.UID) (volume.Builder, error) { func (plugin *secretPlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
return plugin.newBuilderInternal(spec, podUID) return plugin.newBuilderInternal(spec, podRef)
} }
func (plugin *secretPlugin) newBuilderInternal(spec *api.Volume, podUID types.UID) (volume.Builder, error) { func (plugin *secretPlugin) newBuilderInternal(spec *api.Volume, podRef *api.ObjectReference) (volume.Builder, error) {
return &secretVolume{spec.Name, podUID, plugin, &spec.Secret.Target}, nil return &secretVolume{spec.Name, podRef, plugin, &spec.Secret.Target}, nil
} }
func (plugin *secretPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) { func (plugin *secretPlugin) NewCleaner(volName string, podUID types.UID) (volume.Cleaner, error) {
@ -71,14 +71,14 @@ func (plugin *secretPlugin) NewCleaner(volName string, podUID types.UID) (volume
} }
func (plugin *secretPlugin) newCleanerInternal(volName string, podUID types.UID) (volume.Cleaner, error) { func (plugin *secretPlugin) newCleanerInternal(volName string, podUID types.UID) (volume.Cleaner, error) {
return &secretVolume{volName, podUID, plugin, nil}, nil return &secretVolume{volName, &api.ObjectReference{UID: podUID}, plugin, nil}, nil
} }
// secretVolume handles retrieving secrets from the API server // secretVolume handles retrieving secrets from the API server
// and placing them into the volume on the host. // and placing them into the volume on the host.
type secretVolume struct { type secretVolume struct {
volName string volName string
podUID types.UID podRef *api.ObjectReference
plugin *secretPlugin plugin *secretPlugin
secretRef *api.ObjectReference secretRef *api.ObjectReference
} }
@ -86,7 +86,7 @@ type secretVolume struct {
func (sv *secretVolume) SetUp() error { func (sv *secretVolume) SetUp() error {
// TODO: explore tmpfs for secret volumes // TODO: explore tmpfs for secret volumes
hostPath := sv.GetPath() hostPath := sv.GetPath()
glog.V(3).Infof("Setting up volume %v for pod %v at %v", sv.volName, sv.podUID, hostPath) glog.V(3).Infof("Setting up volume %v for pod %v at %v", sv.volName, sv.podRef.UID, hostPath)
err := os.MkdirAll(hostPath, 0777) err := os.MkdirAll(hostPath, 0777)
if err != nil { if err != nil {
return err return err
@ -97,7 +97,7 @@ func (sv *secretVolume) SetUp() error {
return fmt.Errorf("Cannot setup secret volume %v because kube client is not configured", sv) return fmt.Errorf("Cannot setup secret volume %v because kube client is not configured", sv)
} }
secret, err := kubeClient.Secrets(sv.secretRef.Namespace).Get(sv.secretRef.Name) secret, err := kubeClient.Secrets(sv.podRef.Namespace).Get(sv.secretRef.Name)
if err != nil { if err != nil {
glog.Errorf("Couldn't get secret %v/%v", sv.secretRef.Namespace, sv.secretRef.Name) glog.Errorf("Couldn't get secret %v/%v", sv.secretRef.Namespace, sv.secretRef.Name)
return err return err
@ -116,11 +116,11 @@ func (sv *secretVolume) SetUp() error {
} }
func (sv *secretVolume) GetPath() string { func (sv *secretVolume) GetPath() string {
return sv.plugin.host.GetPodVolumeDir(sv.podUID, volume.EscapePluginName(secretPluginName), sv.volName) return sv.plugin.host.GetPodVolumeDir(sv.podRef.UID, volume.EscapePluginName(secretPluginName), sv.volName)
} }
func (sv *secretVolume) TearDown() error { func (sv *secretVolume) TearDown() error {
glog.V(3).Infof("Tearing down volume %v for pod %v at %v", sv.volName, sv.podUID, sv.GetPath()) glog.V(3).Infof("Tearing down volume %v for pod %v at %v", sv.volName, sv.podRef.UID, sv.GetPath())
tmpDir, err := volume.RenameDirectory(sv.GetPath(), sv.volName+".deleting~") tmpDir, err := volume.RenameDirectory(sv.GetPath(), sv.volName+".deleting~")
if err != nil { if err != nil {
return err return err

View File

@ -99,7 +99,7 @@ func TestPlugin(t *testing.T) {
t.Errorf("Can't find the plugin by name") t.Errorf("Can't find the plugin by name")
} }
builder, err := plugin.NewBuilder(volumeSpec, types.UID(testPodUID)) builder, err := plugin.NewBuilder(volumeSpec, &api.ObjectReference{UID: types.UID(testPodUID)})
if err != nil { if err != nil {
t.Errorf("Failed to make a new Builder: %v", err) t.Errorf("Failed to make a new Builder: %v", err)
} }

View File

@ -71,8 +71,8 @@ func (plugin *FakePlugin) CanSupport(spec *api.Volume) bool {
return true return true
} }
func (plugin *FakePlugin) NewBuilder(spec *api.Volume, podUID types.UID) (Builder, error) { func (plugin *FakePlugin) NewBuilder(spec *api.Volume, podRef *api.ObjectReference) (Builder, error) {
return &FakeVolume{podUID, spec.Name, plugin}, nil return &FakeVolume{podRef.UID, spec.Name, plugin}, nil
} }
func (plugin *FakePlugin) NewCleaner(volName string, podUID types.UID) (Cleaner, error) { func (plugin *FakePlugin) NewCleaner(volName string, podUID types.UID) (Cleaner, error) {

View File

@ -53,7 +53,7 @@ func (vh *volumeHost) GetKubeClient() client.Interface {
return vh.kubelet.kubeClient return vh.kubelet.kubeClient
} }
func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *api.Volume, podUID types.UID) volume.Builder { func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *api.Volume, podRef *api.ObjectReference) volume.Builder {
plugin, err := kl.volumePluginMgr.FindPluginBySpec(spec) plugin, err := kl.volumePluginMgr.FindPluginBySpec(spec)
if err != nil { if err != nil {
glog.Warningf("Can't use volume plugins for %s: %v", spew.Sprintf("%#v", *spec), err) glog.Warningf("Can't use volume plugins for %s: %v", spew.Sprintf("%#v", *spec), err)
@ -63,7 +63,7 @@ func (kl *Kubelet) newVolumeBuilderFromPlugins(spec *api.Volume, podUID types.UI
glog.Errorf("No error, but nil volume plugin for %s", spew.Sprintf("%#v", *spec)) glog.Errorf("No error, but nil volume plugin for %s", spew.Sprintf("%#v", *spec))
return nil return nil
} }
builder, err := plugin.NewBuilder(spec, podUID) builder, err := plugin.NewBuilder(spec, podRef)
if err != nil { if err != nil {
glog.Warningf("Error instantiating volume plugin for %s: %v", spew.Sprintf("%#v", *spec), err) glog.Warningf("Error instantiating volume plugin for %s: %v", spew.Sprintf("%#v", *spec), err)
return nil return nil
@ -77,12 +77,18 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.BoundPod) (volumeMap, error) {
for i := range pod.Spec.Volumes { for i := range pod.Spec.Volumes {
volSpec := &pod.Spec.Volumes[i] volSpec := &pod.Spec.Volumes[i]
podRef, err := api.GetReference(pod)
if err != nil {
glog.Errorf("Error getting object reference for pod: %v", pod, err)
return nil, err
}
// Try to use a plugin for this volume. // Try to use a plugin for this volume.
builder := kl.newVolumeBuilderFromPlugins(volSpec, pod.UID) builder := kl.newVolumeBuilderFromPlugins(volSpec, podRef)
if builder == nil { if builder == nil {
return nil, errUnsupportedVolumeType return nil, errUnsupportedVolumeType
} }
err := builder.SetUp() err = builder.SetUp()
if err != nil { if err != nil {
return nil, err return nil, err
} }