Refactor flex pv to allow secret namespace

This commit is contained in:
Jordan Liggitt 2017-11-27 23:19:38 -05:00
parent bba84d785e
commit d073c10dbc
No known key found for this signature in database
GPG Key ID: 39928704103C7229
14 changed files with 231 additions and 34 deletions

View File

@ -62,9 +62,17 @@ func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool {
} }
} }
case source.FlexVolume != nil: case source.FlexVolume != nil:
if source.FlexVolume.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.FlexVolume.SecretRef.Name) { if source.FlexVolume.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.FlexVolume.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.FlexVolume.SecretRef.Namespace
}
if !visitor(ns, source.FlexVolume.SecretRef.Name) {
return false return false
} }
}
case source.RBD != nil: case source.RBD != nil:
if source.RBD.SecretRef != nil { if source.RBD.SecretRef != nil {
// previously persisted PV objects use claimRef namespace // previously persisted PV objects use claimRef namespace

View File

@ -61,8 +61,15 @@ func TestPVSecrets(t *testing.T) {
{Spec: api.PersistentVolumeSpec{ {Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"}, ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{ PersistentVolumeSource: api.PersistentVolumeSource{
FlexVolume: &api.FlexVolumeSource{ FlexVolume: &api.FlexPersistentVolumeSource{
SecretRef: &api.LocalObjectReference{ SecretRef: &api.SecretReference{
Name: "Spec.PersistentVolumeSource.FlexVolume.SecretRef",
Namespace: "flexns"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
FlexVolume: &api.FlexPersistentVolumeSource{
SecretRef: &api.SecretReference{
Name: "Spec.PersistentVolumeSource.FlexVolume.SecretRef"}}}}}, Name: "Spec.PersistentVolumeSource.FlexVolume.SecretRef"}}}}},
{Spec: api.PersistentVolumeSpec{ {Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"}, ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
@ -160,15 +167,22 @@ func TestPVSecrets(t *testing.T) {
expectedNamespacedNames := sets.NewString( expectedNamespacedNames := sets.NewString(
"claimrefns/Spec.PersistentVolumeSource.AzureFile.SecretName", "claimrefns/Spec.PersistentVolumeSource.AzureFile.SecretName",
"Spec.PersistentVolumeSource.AzureFile.SecretNamespace/Spec.PersistentVolumeSource.AzureFile.SecretName", "Spec.PersistentVolumeSource.AzureFile.SecretNamespace/Spec.PersistentVolumeSource.AzureFile.SecretName",
"claimrefns/Spec.PersistentVolumeSource.CephFS.SecretRef", "claimrefns/Spec.PersistentVolumeSource.CephFS.SecretRef",
"cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef", "cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef",
"claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef", "claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef",
"flexns/Spec.PersistentVolumeSource.FlexVolume.SecretRef",
"claimrefns/Spec.PersistentVolumeSource.RBD.SecretRef", "claimrefns/Spec.PersistentVolumeSource.RBD.SecretRef",
"rbdns/Spec.PersistentVolumeSource.RBD.SecretRef", "rbdns/Spec.PersistentVolumeSource.RBD.SecretRef",
"claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef", "claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef",
"scaleions/Spec.PersistentVolumeSource.ScaleIO.SecretRef", "scaleions/Spec.PersistentVolumeSource.ScaleIO.SecretRef",
"claimrefns/Spec.PersistentVolumeSource.ISCSI.SecretRef", "claimrefns/Spec.PersistentVolumeSource.ISCSI.SecretRef",
"iscsi/Spec.PersistentVolumeSource.ISCSI.SecretRef", "iscsi/Spec.PersistentVolumeSource.ISCSI.SecretRef",
"storageosns/Spec.PersistentVolumeSource.StorageOS.SecretRef", "storageosns/Spec.PersistentVolumeSource.StorageOS.SecretRef",
) )
if missingNames := expectedNamespacedNames.Difference(extractedNamesWithNamespace); len(missingNames) > 0 { if missingNames := expectedNamespacedNames.Difference(extractedNamesWithNamespace); len(missingNames) > 0 {

View File

@ -354,7 +354,7 @@ type PersistentVolumeSource struct {
// FlexVolume represents a generic volume resource that is // FlexVolume represents a generic volume resource that is
// provisioned/attached using an exec based plugin. // provisioned/attached using an exec based plugin.
// +optional // +optional
FlexVolume *FlexVolumeSource FlexVolume *FlexPersistentVolumeSource
// Cinder represents a cinder volume attached and mounted on kubelets host machine // Cinder represents a cinder volume attached and mounted on kubelets host machine
// +optional // +optional
Cinder *CinderVolumeSource Cinder *CinderVolumeSource
@ -867,6 +867,32 @@ type FCVolumeSource struct {
WWIDs []string WWIDs []string
} }
// FlexPersistentVolumeSource represents a generic persistent volume resource that is
// provisioned/attached using an exec based plugin.
type FlexPersistentVolumeSource struct {
// Driver is the name of the driver to use for this volume.
Driver string
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script.
// +optional
FSType string
// Optional: SecretRef is reference to the secret object containing
// sensitive information to pass to the plugin scripts. This may be
// empty if no secret object is specified. If the secret object
// contains more than one secret, all secrets are passed to the plugin
// scripts.
// +optional
SecretRef *SecretReference
// Optional: Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool
// Optional: Extra driver options if any.
// +optional
Options map[string]string
}
// FlexVolume represents a generic volume resource that is // FlexVolume represents a generic volume resource that is
// provisioned/attached using an exec based plugin. // provisioned/attached using an exec based plugin.
type FlexVolumeSource struct { type FlexVolumeSource struct {

View File

@ -1257,6 +1257,27 @@ func validateFlexVolumeSource(fv *core.FlexVolumeSource, fldPath *field.Path) fi
return allErrs return allErrs
} }
func validateFlexPersistentVolumeSource(fv *core.FlexPersistentVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(fv.Driver) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("driver"), ""))
}
// Make sure user-specified options don't use kubernetes namespaces
for k := range fv.Options {
namespace := k
if parts := strings.SplitN(k, "/", 2); len(parts) == 2 {
namespace = parts[0]
}
normalized := "." + strings.ToLower(namespace)
if strings.HasSuffix(normalized, ".kubernetes.io") || strings.HasSuffix(normalized, ".k8s.io") {
allErrs = append(allErrs, field.Invalid(fldPath.Child("options").Key(k), k, "kubernetes.io and k8s.io namespaces are reserved"))
}
}
return allErrs
}
func validateAzureFile(azure *core.AzureFileVolumeSource, fldPath *field.Path) field.ErrorList { func validateAzureFile(azure *core.AzureFileVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
if azure.SecretName == "" { if azure.SecretName == "" {
@ -1588,7 +1609,7 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList {
} }
if pv.Spec.FlexVolume != nil { if pv.Spec.FlexVolume != nil {
numVolumes++ numVolumes++
allErrs = append(allErrs, validateFlexVolumeSource(pv.Spec.FlexVolume, specPath.Child("flexVolume"))...) allErrs = append(allErrs, validateFlexPersistentVolumeSource(pv.Spec.FlexVolume, specPath.Child("flexVolume"))...)
} }
if pv.Spec.AzureFile != nil { if pv.Spec.AzureFile != nil {
if numVolumes > 0 { if numVolumes > 0 {

View File

@ -469,7 +469,7 @@ func TestValidatePersistentVolumeSourceUpdate(t *testing.T) {
validPvSourceNoUpdate := validVolume.DeepCopy() validPvSourceNoUpdate := validVolume.DeepCopy()
invalidPvSourceUpdateType := validVolume.DeepCopy() invalidPvSourceUpdateType := validVolume.DeepCopy()
invalidPvSourceUpdateType.Spec.PersistentVolumeSource = core.PersistentVolumeSource{ invalidPvSourceUpdateType.Spec.PersistentVolumeSource = core.PersistentVolumeSource{
FlexVolume: &core.FlexVolumeSource{ FlexVolume: &core.FlexPersistentVolumeSource{
Driver: "kubernetes.io/blue", Driver: "kubernetes.io/blue",
FSType: "ext4", FSType: "ext4",
}, },

View File

@ -1076,6 +1076,16 @@ func printAzureFilePersistentVolumeSource(azureFile *api.AzureFilePersistentVolu
azureFile.SecretName, ns, azureFile.ShareName, azureFile.ReadOnly) azureFile.SecretName, ns, azureFile.ShareName, azureFile.ReadOnly)
} }
func printFlexPersistentVolumeSource(flex *api.FlexPersistentVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tFlexVolume (a generic volume resource that is provisioned/attached using an exec based plugin)\n"+
" Driver:\t%v\n"+
" FSType:\t%v\n"+
" SecretRef:\t%v\n"+
" ReadOnly:\t%v\n",
" Options:\t%v\n",
flex.Driver, flex.FSType, flex.SecretRef, flex.ReadOnly, flex.Options)
}
func printFlexVolumeSource(flex *api.FlexVolumeSource, w PrefixWriter) { func printFlexVolumeSource(flex *api.FlexVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tFlexVolume (a generic volume resource that is provisioned/attached using an exec based plugin)\n"+ w.Write(LEVEL_2, "Type:\tFlexVolume (a generic volume resource that is provisioned/attached using an exec based plugin)\n"+
" Driver:\t%v\n"+ " Driver:\t%v\n"+
@ -1184,7 +1194,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
case pv.Spec.AzureFile != nil: case pv.Spec.AzureFile != nil:
printAzureFilePersistentVolumeSource(pv.Spec.AzureFile, w) printAzureFilePersistentVolumeSource(pv.Spec.AzureFile, w)
case pv.Spec.FlexVolume != nil: case pv.Spec.FlexVolume != nil:
printFlexVolumeSource(pv.Spec.FlexVolume, w) printFlexPersistentVolumeSource(pv.Spec.FlexVolume, w)
case pv.Spec.Flocker != nil: case pv.Spec.Flocker != nil:
printFlockerVolumeSource(pv.Spec.Flocker, w) printFlockerVolumeSource(pv.Spec.Flocker, w)
case pv.Spec.CSI != nil: case pv.Spec.CSI != nil:

View File

@ -48,7 +48,16 @@ func (a *attacherDefaults) GetDeviceMountPath(spec *volume.Spec, mountsDir strin
// MountDevice is part of the volume.Attacher interface // MountDevice is part of the volume.Attacher interface
func (a *attacherDefaults) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string, mounter mount.Interface) error { func (a *attacherDefaults) MountDevice(spec *volume.Spec, devicePath string, deviceMountPath string, mounter mount.Interface) error {
glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default MountDevice for volume ", spec.Name, ", device ", devicePath, ", deviceMountPath ", deviceMountPath) glog.Warning(logPrefix(a.plugin.flexVolumePlugin), "using default MountDevice for volume ", spec.Name, ", device ", devicePath, ", deviceMountPath ", deviceMountPath)
volSource, readOnly := getVolumeSource(spec)
volSourceFSType, err := getFSType(spec)
if err != nil {
return err
}
readOnly, err := getReadOnly(spec)
if err != nil {
return err
}
options := make([]string, 0) options := make([]string, 0)
@ -60,5 +69,5 @@ func (a *attacherDefaults) MountDevice(spec *volume.Spec, devicePath string, dev
diskMounter := &mount.SafeFormatAndMount{Interface: mounter, Exec: a.plugin.host.GetExec(a.plugin.GetPluginName())} diskMounter := &mount.SafeFormatAndMount{Interface: mounter, Exec: a.plugin.host.GetExec(a.plugin.GetPluginName())}
return diskMounter.FormatAndMount(devicePath, deviceMountPath, volSource.FSType, options) return diskMounter.FormatAndMount(devicePath, deviceMountPath, volSourceFSType, options)
} }

View File

@ -119,7 +119,7 @@ func fakePersistentVolumeSpec() *volume.Spec {
}, },
Spec: v1.PersistentVolumeSpec{ Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{ PersistentVolumeSource: v1.PersistentVolumeSource{
FlexVolume: &v1.FlexVolumeSource{ FlexVolume: &v1.FlexPersistentVolumeSource{
Driver: "kubernetes.io/fakeAttacher", Driver: "kubernetes.io/fakeAttacher",
ReadOnly: false, ReadOnly: false,
}, },

View File

@ -162,10 +162,25 @@ func (dc *DriverCall) Run() (*DriverStatus, error) {
type OptionsForDriver map[string]string type OptionsForDriver map[string]string
func NewOptionsForDriver(spec *volume.Spec, host volume.VolumeHost, extraOptions map[string]string) (OptionsForDriver, error) { func NewOptionsForDriver(spec *volume.Spec, host volume.VolumeHost, extraOptions map[string]string) (OptionsForDriver, error) {
volSource, readOnly := getVolumeSource(spec)
volSourceFSType, err := getFSType(spec)
if err != nil {
return nil, err
}
readOnly, err := getReadOnly(spec)
if err != nil {
return nil, err
}
volSourceOptions, err := getOptions(spec)
if err != nil {
return nil, err
}
options := map[string]string{} options := map[string]string{}
options[optionFSType] = volSource.FSType options[optionFSType] = volSourceFSType
if readOnly { if readOnly {
options[optionReadWrite] = "ro" options[optionReadWrite] = "ro"
@ -179,7 +194,7 @@ func NewOptionsForDriver(spec *volume.Spec, host volume.VolumeHost, extraOptions
options[key] = value options[key] = value
} }
for key, value := range volSource.Options { for key, value := range volSourceOptions {
options[key] = value options[key] = value
} }

View File

@ -185,7 +185,7 @@ func TestCanSupport(t *testing.T) {
if !plugin.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{FlexVolume: &v1.FlexVolumeSource{Driver: "kubernetes.io/fakeAttacher"}}}}) { if !plugin.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{FlexVolume: &v1.FlexVolumeSource{Driver: "kubernetes.io/fakeAttacher"}}}}) {
t.Errorf("Expected true") t.Errorf("Expected true")
} }
if !plugin.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{FlexVolume: &v1.FlexVolumeSource{Driver: "kubernetes.io/fakeAttacher"}}}}}) { if !plugin.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{FlexVolume: &v1.FlexPersistentVolumeSource{Driver: "kubernetes.io/fakeAttacher"}}}}}) {
t.Errorf("Expected true") t.Errorf("Expected true")
} }
if plugin.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) { if plugin.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) {

View File

@ -132,8 +132,11 @@ func (plugin *flexVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error)
// CanSupport is part of the volume.VolumePlugin interface. // CanSupport is part of the volume.VolumePlugin interface.
func (plugin *flexVolumePlugin) CanSupport(spec *volume.Spec) bool { func (plugin *flexVolumePlugin) CanSupport(spec *volume.Spec) bool {
source, _ := getVolumeSource(spec) sourceDriver, err := getDriver(spec)
return (source != nil) && (source.Driver == plugin.driverName) if err != nil {
return false
}
return sourceDriver == plugin.driverName
} }
// RequiresRemount is part of the volume.VolumePlugin interface. // RequiresRemount is part of the volume.VolumePlugin interface.
@ -156,10 +159,19 @@ func (plugin *flexVolumePlugin) NewMounter(spec *volume.Spec, pod *api.Pod, _ vo
// newMounterInternal is the internal mounter routine to build the volume. // newMounterInternal is the internal mounter routine to build the volume.
func (plugin *flexVolumePlugin) newMounterInternal(spec *volume.Spec, pod *api.Pod, mounter mount.Interface, runner exec.Interface) (volume.Mounter, error) { func (plugin *flexVolumePlugin) newMounterInternal(spec *volume.Spec, pod *api.Pod, mounter mount.Interface, runner exec.Interface) (volume.Mounter, error) {
source, readOnly := getVolumeSource(spec) sourceDriver, err := getDriver(spec)
if err != nil {
return nil, err
}
readOnly, err := getReadOnly(spec)
if err != nil {
return nil, err
}
return &flexVolumeMounter{ return &flexVolumeMounter{
flexVolume: &flexVolume{ flexVolume: &flexVolume{
driverName: source.Driver, driverName: sourceDriver,
execPath: plugin.getExecutable(), execPath: plugin.getExecutable(),
mounter: mounter, mounter: mounter,
plugin: plugin, plugin: plugin,

View File

@ -22,15 +22,18 @@ import (
"os" "os"
"github.com/golang/glog" "github.com/golang/glog"
api "k8s.io/api/core/v1"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
) )
func addSecretsToOptions(options map[string]string, spec *volume.Spec, namespace string, driverName string, host volume.VolumeHost) error { func addSecretsToOptions(options map[string]string, spec *volume.Spec, namespace string, driverName string, host volume.VolumeHost) error {
fv, _ := getVolumeSource(spec) secretName, secretNamespace, err := getSecretNameAndNamespace(spec, namespace)
if fv.SecretRef == nil { if err != nil {
return err
}
if len(secretName) == 0 || len(secretNamespace) == 0 {
return nil return nil
} }
@ -39,9 +42,9 @@ func addSecretsToOptions(options map[string]string, spec *volume.Spec, namespace
return fmt.Errorf("Cannot get kube client") return fmt.Errorf("Cannot get kube client")
} }
secrets, err := util.GetSecretForPV(namespace, fv.SecretRef.Name, driverName, host.GetKubeClient()) secrets, err := util.GetSecretForPV(secretNamespace, secretName, driverName, host.GetKubeClient())
if err != nil { if err != nil {
err = fmt.Errorf("Couldn't get secret %v/%v err: %v", namespace, fv.SecretRef.Name, err) err = fmt.Errorf("Couldn't get secret %v/%v err: %v", secretNamespace, secretName, err)
return err return err
} }
for name, data := range secrets { for name, data := range secrets {
@ -52,15 +55,68 @@ func addSecretsToOptions(options map[string]string, spec *volume.Spec, namespace
return nil return nil
} }
func getVolumeSource(spec *volume.Spec) (volumeSource *api.FlexVolumeSource, readOnly bool) { var notFlexVolume = fmt.Errorf("not a flex volume")
func getDriver(spec *volume.Spec) (string, error) {
if spec.Volume != nil && spec.Volume.FlexVolume != nil { if spec.Volume != nil && spec.Volume.FlexVolume != nil {
volumeSource = spec.Volume.FlexVolume return spec.Volume.FlexVolume.Driver, nil
readOnly = volumeSource.ReadOnly
} else if spec.PersistentVolume != nil {
volumeSource = spec.PersistentVolume.Spec.FlexVolume
readOnly = spec.ReadOnly
} }
return if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.FlexVolume != nil {
return spec.PersistentVolume.Spec.FlexVolume.Driver, nil
}
return "", notFlexVolume
}
func getFSType(spec *volume.Spec) (string, error) {
if spec.Volume != nil && spec.Volume.FlexVolume != nil {
return spec.Volume.FlexVolume.FSType, nil
}
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.FlexVolume != nil {
return spec.PersistentVolume.Spec.FlexVolume.FSType, nil
}
return "", notFlexVolume
}
func getSecretNameAndNamespace(spec *volume.Spec, podNamespace string) (string, string, error) {
if spec.Volume != nil && spec.Volume.FlexVolume != nil {
if spec.Volume.FlexVolume.SecretRef == nil {
return "", "", nil
}
return spec.Volume.FlexVolume.SecretRef.Name, podNamespace, nil
}
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.FlexVolume != nil {
if spec.PersistentVolume.Spec.FlexVolume.SecretRef == nil {
return "", "", nil
}
secretName := spec.PersistentVolume.Spec.FlexVolume.SecretRef.Name
secretNamespace := spec.PersistentVolume.Spec.FlexVolume.SecretRef.Namespace
if len(secretNamespace) == 0 {
secretNamespace = podNamespace
}
return secretName, secretNamespace, nil
}
return "", "", notFlexVolume
}
func getReadOnly(spec *volume.Spec) (bool, error) {
if spec.Volume != nil && spec.Volume.FlexVolume != nil {
return spec.Volume.FlexVolume.ReadOnly, nil
}
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.FlexVolume != nil {
// ReadOnly is specified at the PV level
return spec.ReadOnly, nil
}
return false, notFlexVolume
}
func getOptions(spec *volume.Spec) (map[string]string, error) {
if spec.Volume != nil && spec.Volume.FlexVolume != nil {
return spec.Volume.FlexVolume.Options, nil
}
if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.FlexVolume != nil {
return spec.PersistentVolume.Spec.FlexVolume.Options, nil
}
return nil, notFlexVolume
} }
func prepareForMount(mounter mount.Interface, deviceMountPath string) (bool, error) { func prepareForMount(mounter mount.Interface, deviceMountPath string) (bool, error) {

View File

@ -410,7 +410,7 @@ func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume) {
for i := 0; i < opts.uniquePVCsPerPod; i++ { for i := 0; i < opts.uniquePVCsPerPod; i++ {
pv := &api.PersistentVolume{} pv := &api.PersistentVolume{}
pv.Name = fmt.Sprintf("pv%d-%s-%s", i, pod.Name, pod.Namespace) pv.Name = fmt.Sprintf("pv%d-%s-%s", i, pod.Name, pod.Namespace)
pv.Spec.FlexVolume = &api.FlexVolumeSource{SecretRef: &api.LocalObjectReference{Name: fmt.Sprintf("secret-%s", pv.Name)}} pv.Spec.FlexVolume = &api.FlexPersistentVolumeSource{SecretRef: &api.SecretReference{Name: fmt.Sprintf("secret-%s", pv.Name)}}
pv.Spec.ClaimRef = &api.ObjectReference{Name: fmt.Sprintf("pvc%d-%s", i, pod.Name), Namespace: pod.Namespace} pv.Spec.ClaimRef = &api.ObjectReference{Name: fmt.Sprintf("pvc%d-%s", i, pod.Name), Namespace: pod.Namespace}
pvs = append(pvs, pv) pvs = append(pvs, pv)
@ -421,7 +421,7 @@ func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume) {
for i := 0; i < opts.sharedPVCsPerPod; i++ { for i := 0; i < opts.sharedPVCsPerPod; i++ {
pv := &api.PersistentVolume{} pv := &api.PersistentVolume{}
pv.Name = fmt.Sprintf("pv%d-shared-%s", i, pod.Namespace) pv.Name = fmt.Sprintf("pv%d-shared-%s", i, pod.Namespace)
pv.Spec.FlexVolume = &api.FlexVolumeSource{SecretRef: &api.LocalObjectReference{Name: fmt.Sprintf("secret-%s", pv.Name)}} pv.Spec.FlexVolume = &api.FlexPersistentVolumeSource{SecretRef: &api.SecretReference{Name: fmt.Sprintf("secret-%s", pv.Name)}}
pv.Spec.ClaimRef = &api.ObjectReference{Name: fmt.Sprintf("pvc%d-shared", i), Namespace: pod.Namespace} pv.Spec.ClaimRef = &api.ObjectReference{Name: fmt.Sprintf("pvc%d-shared", i), Namespace: pod.Namespace}
pvs = append(pvs, pv) pvs = append(pvs, pv)

View File

@ -418,7 +418,7 @@ type PersistentVolumeSource struct {
// FlexVolume represents a generic volume resource that is // FlexVolume represents a generic volume resource that is
// provisioned/attached using an exec based plugin. // provisioned/attached using an exec based plugin.
// +optional // +optional
FlexVolume *FlexVolumeSource `json:"flexVolume,omitempty" protobuf:"bytes,12,opt,name=flexVolume"` FlexVolume *FlexPersistentVolumeSource `json:"flexVolume,omitempty" protobuf:"bytes,12,opt,name=flexVolume"`
// AzureFile represents an Azure File Service mount on the host and bind mount to the pod. // AzureFile represents an Azure File Service mount on the host and bind mount to the pod.
// +optional // +optional
AzureFile *AzureFilePersistentVolumeSource `json:"azureFile,omitempty" protobuf:"bytes,13,opt,name=azureFile"` AzureFile *AzureFilePersistentVolumeSource `json:"azureFile,omitempty" protobuf:"bytes,13,opt,name=azureFile"`
@ -1081,6 +1081,32 @@ type QuobyteVolumeSource struct {
Group string `json:"group,omitempty" protobuf:"bytes,5,opt,name=group"` Group string `json:"group,omitempty" protobuf:"bytes,5,opt,name=group"`
} }
// FlexPersistentVolumeSource represents a generic persistent volume resource that is
// provisioned/attached using an exec based plugin.
type FlexPersistentVolumeSource struct {
// Driver is the name of the driver to use for this volume.
Driver string `json:"driver" protobuf:"bytes,1,opt,name=driver"`
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script.
// +optional
FSType string `json:"fsType,omitempty" protobuf:"bytes,2,opt,name=fsType"`
// Optional: SecretRef is reference to the secret object containing
// sensitive information to pass to the plugin scripts. This may be
// empty if no secret object is specified. If the secret object
// contains more than one secret, all secrets are passed to the plugin
// scripts.
// +optional
SecretRef *SecretReference `json:"secretRef,omitempty" protobuf:"bytes,3,opt,name=secretRef"`
// Optional: Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool `json:"readOnly,omitempty" protobuf:"varint,4,opt,name=readOnly"`
// Optional: Extra command options if any.
// +optional
Options map[string]string `json:"options,omitempty" protobuf:"bytes,5,rep,name=options"`
}
// FlexVolume represents a generic volume resource that is // FlexVolume represents a generic volume resource that is
// provisioned/attached using an exec based plugin. // provisioned/attached using an exec based plugin.
type FlexVolumeSource struct { type FlexVolumeSource struct {