Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically Add Supplemental Groups from Volumes to Pods #20490

Merged
merged 1 commit into from May 8, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions pkg/volume/persistent_claim/persistent_claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package persistent_claim

import (
"fmt"
"strconv"

"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down
62 changes: 56 additions & 6 deletions pkg/volume/persistent_claim/persistent_claim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}{
{
Expand Down Expand Up @@ -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())
}
Expand Down Expand Up @@ -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())
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -227,14 +227,64 @@ 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)
}
return nil
},
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 {
Expand Down Expand Up @@ -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)
}
}
Expand Down