Add GIDs specified in a PV's annotations to pod's supplemental groups

This commit is contained in:
Sami Wagiaalla 2016-02-05 17:05:02 -05:00
parent ad86986c87
commit e1e7da2712
2 changed files with 71 additions and 6 deletions

View File

@ -18,6 +18,7 @@ package persistent_claim
import (
"fmt"
"strconv"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
@ -38,6 +39,7 @@ var _ volume.VolumePlugin = &persistentClaimPlugin{}
const (
persistentClaimPluginName = "kubernetes.io/persistent-claim"
volumeGidAnnotationKey = "pv.beta.kubernetes.io/gid"
)
func (plugin *persistentClaimPlugin) Init(host volume.VolumeHost) error {
@ -80,6 +82,19 @@ func (plugin *persistentClaimPlugin) NewMounter(spec *volume.Spec, pod *api.Pod,
return nil, err
}
// If a GID annotation is provided set the GID attribute.
if volumeGid, ok := pv.Annotations[volumeGidAnnotationKey]; ok {
gid, err := strconv.ParseInt(volumeGid, 10, 64)
if err != nil {
return nil, fmt.Errorf("Invalid value for %s %v", volumeGidAnnotationKey, err)
}
if pod.Spec.SecurityContext == nil {
pod.Spec.SecurityContext = &api.PodSecurityContext{}
}
pod.Spec.SecurityContext.SupplementalGroups = append(pod.Spec.SecurityContext.SupplementalGroups, gid)
}
mounter, err := plugin.host.NewWrapperMounter(claim.Spec.VolumeName, *volume.NewSpecFromPersistentVolume(pv, spec.ReadOnly), pod, opts)
if err != nil {
glog.Errorf("Error creating mounter for claim: %+v\n", claim.Name)

View File

@ -72,7 +72,7 @@ func TestNewMounter(t *testing.T) {
claim *api.PersistentVolumeClaim
plugin volume.VolumePlugin
podVolume api.VolumeSource
testFunc func(mounter volume.Mounter, plugin volume.VolumePlugin) error
testFunc func(mounter volume.Mounter, plugin volume.VolumePlugin, pod *api.Pod) error
expectedFailure bool
}{
{
@ -108,7 +108,7 @@ func TestNewMounter(t *testing.T) {
},
},
plugin: gce_pd.ProbeVolumePlugins()[0],
testFunc: func(mounter volume.Mounter, plugin volume.VolumePlugin) error {
testFunc: func(mounter volume.Mounter, plugin volume.VolumePlugin, pod *api.Pod) error {
if !strings.Contains(mounter.GetPath(), utilstrings.EscapeQualifiedNameForDisk(plugin.Name())) {
return fmt.Errorf("mounter path expected to contain plugin name. Got: %s", mounter.GetPath())
}
@ -146,7 +146,7 @@ func TestNewMounter(t *testing.T) {
},
},
plugin: host_path.ProbeVolumePlugins(volume.VolumeConfig{})[0],
testFunc: func(mounter volume.Mounter, plugin volume.VolumePlugin) error {
testFunc: func(mounter volume.Mounter, plugin volume.VolumePlugin, pod *api.Pod) error {
if mounter.GetPath() != "/somepath" {
return fmt.Errorf("Expected HostPath.Path /somepath, got: %s", mounter.GetPath())
}
@ -184,7 +184,7 @@ func TestNewMounter(t *testing.T) {
},
},
plugin: gce_pd.ProbeVolumePlugins()[0],
testFunc: func(mounter volume.Mounter, plugin volume.VolumePlugin) error {
testFunc: func(mounter volume.Mounter, plugin volume.VolumePlugin, pod *api.Pod) error {
if mounter != nil {
return fmt.Errorf("Unexpected non-nil mounter: %+v", mounter)
}
@ -227,7 +227,7 @@ func TestNewMounter(t *testing.T) {
},
},
plugin: gce_pd.ProbeVolumePlugins()[0],
testFunc: func(mounter volume.Mounter, plugin volume.VolumePlugin) error {
testFunc: func(mounter volume.Mounter, plugin volume.VolumePlugin, pod *api.Pod) error {
if mounter != nil {
return fmt.Errorf("Unexpected non-nil mounter: %+v", mounter)
}
@ -235,6 +235,56 @@ func TestNewMounter(t *testing.T) {
},
expectedFailure: true, // mismatched pv.Spec.ClaimRef and pvc
},
{ // Test GID annotation
pv: &api.PersistentVolume{
ObjectMeta: api.ObjectMeta{
Name: "pv",
Annotations: map[string]string{
volumeGidAnnotationKey: "12345",
},
},
Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{},
},
ClaimRef: &api.ObjectReference{
Name: "claim",
UID: types.UID("abc123"),
},
},
},
claim: &api.PersistentVolumeClaim{
ObjectMeta: api.ObjectMeta{
Name: "claim",
UID: types.UID("abc123"),
},
Spec: api.PersistentVolumeClaimSpec{
VolumeName: "pv",
},
Status: api.PersistentVolumeClaimStatus{
Phase: api.ClaimBound,
},
},
podVolume: api.VolumeSource{
PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{
ReadOnly: false,
ClaimName: "claim",
},
},
plugin: gce_pd.ProbeVolumePlugins()[0],
testFunc: func(mounter volume.Mounter, plugin volume.VolumePlugin, pod *api.Pod) error {
if pod.Spec.SecurityContext == nil {
return fmt.Errorf("Pod SecurityContext was not set")
}
if pod.Spec.SecurityContext.SupplementalGroups[0] != 12345 {
return fmt.Errorf("Pod's SupplementalGroups list does not contain expect group")
}
return nil
},
expectedFailure: false,
},
}
for _, item := range tests {
@ -262,7 +312,7 @@ func TestNewMounter(t *testing.T) {
}
}
if err := item.testFunc(mounter, item.plugin); err != nil {
if err := item.testFunc(mounter, item.plugin, pod); err != nil {
t.Errorf("Unexpected error %+v", err)
}
}