Merge pull request #14328 from agonzalezro/flocker
Add flocker volume plugin
This commit is contained in:
@@ -571,6 +571,11 @@ func deepCopy_api_FCVolumeSource(in FCVolumeSource, out *FCVolumeSource, c *conv
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_api_FlockerVolumeSource(in FlockerVolumeSource, out *FlockerVolumeSource, c *conversion.Cloner) error {
|
||||
out.DatasetName = in.DatasetName
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_api_GCEPersistentDiskVolumeSource(in GCEPersistentDiskVolumeSource, out *GCEPersistentDiskVolumeSource, c *conversion.Cloner) error {
|
||||
out.PDName = in.PDName
|
||||
out.FSType = in.FSType
|
||||
@@ -1295,6 +1300,14 @@ func deepCopy_api_PersistentVolumeSource(in PersistentVolumeSource, out *Persist
|
||||
} else {
|
||||
out.FC = nil
|
||||
}
|
||||
if in.Flocker != nil {
|
||||
out.Flocker = new(FlockerVolumeSource)
|
||||
if err := deepCopy_api_FlockerVolumeSource(*in.Flocker, out.Flocker, c); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Flocker = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2211,6 +2224,14 @@ func deepCopy_api_VolumeSource(in VolumeSource, out *VolumeSource, c *conversion
|
||||
} else {
|
||||
out.CephFS = nil
|
||||
}
|
||||
if in.Flocker != nil {
|
||||
out.Flocker = new(FlockerVolumeSource)
|
||||
if err := deepCopy_api_FlockerVolumeSource(*in.Flocker, out.Flocker, c); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Flocker = nil
|
||||
}
|
||||
if in.DownwardAPI != nil {
|
||||
out.DownwardAPI = new(DownwardAPIVolumeSource)
|
||||
if err := deepCopy_api_DownwardAPIVolumeSource(*in.DownwardAPI, out.DownwardAPI, c); err != nil {
|
||||
@@ -2308,6 +2329,7 @@ func init() {
|
||||
deepCopy_api_EventSource,
|
||||
deepCopy_api_ExecAction,
|
||||
deepCopy_api_FCVolumeSource,
|
||||
deepCopy_api_FlockerVolumeSource,
|
||||
deepCopy_api_GCEPersistentDiskVolumeSource,
|
||||
deepCopy_api_GitRepoVolumeSource,
|
||||
deepCopy_api_GlusterfsVolumeSource,
|
||||
|
@@ -204,6 +204,9 @@ type VolumeSource struct {
|
||||
// CephFS represents a Cephfs mount on the host that shares a pod's lifetime
|
||||
CephFS *CephFSVolumeSource `json:"cephfs,omitempty"`
|
||||
|
||||
// Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running
|
||||
Flocker *FlockerVolumeSource `json:"flocker,omitempty"`
|
||||
|
||||
// DownwardAPI represents metadata about the pod that should populate this volume
|
||||
DownwardAPI *DownwardAPIVolumeSource `json:"downwardAPI,omitempty"`
|
||||
// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.
|
||||
@@ -239,6 +242,8 @@ type PersistentVolumeSource struct {
|
||||
CephFS *CephFSVolumeSource `json:"cephfs,omitempty"`
|
||||
// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.
|
||||
FC *FCVolumeSource `json:"fc,omitempty"`
|
||||
// Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running
|
||||
Flocker *FlockerVolumeSource `json:"flocker,omitempty"`
|
||||
}
|
||||
|
||||
type PersistentVolumeClaimVolumeSource struct {
|
||||
@@ -592,6 +597,12 @@ type CephFSVolumeSource struct {
|
||||
ReadOnly bool `json:"readOnly,omitempty"`
|
||||
}
|
||||
|
||||
// FlockerVolumeSource represents a Flocker volume mounted by the Flocker agent.
|
||||
type FlockerVolumeSource struct {
|
||||
// Required: the volume name. This is going to be store on metadata -> name on the payload for Flocker
|
||||
DatasetName string `json:"datasetName"`
|
||||
}
|
||||
|
||||
// DownwardAPIVolumeSource represents a volume containing downward API info
|
||||
type DownwardAPIVolumeSource struct {
|
||||
// Items is a list of DownwardAPIVolume file
|
||||
|
@@ -790,6 +790,18 @@ func convert_api_FCVolumeSource_To_v1_FCVolumeSource(in *api.FCVolumeSource, out
|
||||
return autoconvert_api_FCVolumeSource_To_v1_FCVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoconvert_api_FlockerVolumeSource_To_v1_FlockerVolumeSource(in *api.FlockerVolumeSource, out *FlockerVolumeSource, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*api.FlockerVolumeSource))(in)
|
||||
}
|
||||
out.DatasetName = in.DatasetName
|
||||
return nil
|
||||
}
|
||||
|
||||
func convert_api_FlockerVolumeSource_To_v1_FlockerVolumeSource(in *api.FlockerVolumeSource, out *FlockerVolumeSource, s conversion.Scope) error {
|
||||
return autoconvert_api_FlockerVolumeSource_To_v1_FlockerVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoconvert_api_GCEPersistentDiskVolumeSource_To_v1_GCEPersistentDiskVolumeSource(in *api.GCEPersistentDiskVolumeSource, out *GCEPersistentDiskVolumeSource, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*api.GCEPersistentDiskVolumeSource))(in)
|
||||
@@ -1777,6 +1789,14 @@ func autoconvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api
|
||||
} else {
|
||||
out.FC = nil
|
||||
}
|
||||
if in.Flocker != nil {
|
||||
out.Flocker = new(FlockerVolumeSource)
|
||||
if err := convert_api_FlockerVolumeSource_To_v1_FlockerVolumeSource(in.Flocker, out.Flocker, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Flocker = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2984,6 +3004,14 @@ func autoconvert_api_VolumeSource_To_v1_VolumeSource(in *api.VolumeSource, out *
|
||||
} else {
|
||||
out.CephFS = nil
|
||||
}
|
||||
if in.Flocker != nil {
|
||||
out.Flocker = new(FlockerVolumeSource)
|
||||
if err := convert_api_FlockerVolumeSource_To_v1_FlockerVolumeSource(in.Flocker, out.Flocker, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Flocker = nil
|
||||
}
|
||||
if in.DownwardAPI != nil {
|
||||
out.DownwardAPI = new(DownwardAPIVolumeSource)
|
||||
if err := convert_api_DownwardAPIVolumeSource_To_v1_DownwardAPIVolumeSource(in.DownwardAPI, out.DownwardAPI, s); err != nil {
|
||||
@@ -3771,6 +3799,18 @@ func convert_v1_FCVolumeSource_To_api_FCVolumeSource(in *FCVolumeSource, out *ap
|
||||
return autoconvert_v1_FCVolumeSource_To_api_FCVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoconvert_v1_FlockerVolumeSource_To_api_FlockerVolumeSource(in *FlockerVolumeSource, out *api.FlockerVolumeSource, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*FlockerVolumeSource))(in)
|
||||
}
|
||||
out.DatasetName = in.DatasetName
|
||||
return nil
|
||||
}
|
||||
|
||||
func convert_v1_FlockerVolumeSource_To_api_FlockerVolumeSource(in *FlockerVolumeSource, out *api.FlockerVolumeSource, s conversion.Scope) error {
|
||||
return autoconvert_v1_FlockerVolumeSource_To_api_FlockerVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoconvert_v1_GCEPersistentDiskVolumeSource_To_api_GCEPersistentDiskVolumeSource(in *GCEPersistentDiskVolumeSource, out *api.GCEPersistentDiskVolumeSource, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*GCEPersistentDiskVolumeSource))(in)
|
||||
@@ -4758,6 +4798,14 @@ func autoconvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *Per
|
||||
} else {
|
||||
out.FC = nil
|
||||
}
|
||||
if in.Flocker != nil {
|
||||
out.Flocker = new(api.FlockerVolumeSource)
|
||||
if err := convert_v1_FlockerVolumeSource_To_api_FlockerVolumeSource(in.Flocker, out.Flocker, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Flocker = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5965,6 +6013,14 @@ func autoconvert_v1_VolumeSource_To_api_VolumeSource(in *VolumeSource, out *api.
|
||||
} else {
|
||||
out.CephFS = nil
|
||||
}
|
||||
if in.Flocker != nil {
|
||||
out.Flocker = new(api.FlockerVolumeSource)
|
||||
if err := convert_v1_FlockerVolumeSource_To_api_FlockerVolumeSource(in.Flocker, out.Flocker, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Flocker = nil
|
||||
}
|
||||
if in.DownwardAPI != nil {
|
||||
out.DownwardAPI = new(api.DownwardAPIVolumeSource)
|
||||
if err := convert_v1_DownwardAPIVolumeSource_To_api_DownwardAPIVolumeSource(in.DownwardAPI, out.DownwardAPI, s); err != nil {
|
||||
@@ -6022,6 +6078,7 @@ func init() {
|
||||
autoconvert_api_Event_To_v1_Event,
|
||||
autoconvert_api_ExecAction_To_v1_ExecAction,
|
||||
autoconvert_api_FCVolumeSource_To_v1_FCVolumeSource,
|
||||
autoconvert_api_FlockerVolumeSource_To_v1_FlockerVolumeSource,
|
||||
autoconvert_api_GCEPersistentDiskVolumeSource_To_v1_GCEPersistentDiskVolumeSource,
|
||||
autoconvert_api_GitRepoVolumeSource_To_v1_GitRepoVolumeSource,
|
||||
autoconvert_api_GlusterfsVolumeSource_To_v1_GlusterfsVolumeSource,
|
||||
@@ -6139,6 +6196,7 @@ func init() {
|
||||
autoconvert_v1_Event_To_api_Event,
|
||||
autoconvert_v1_ExecAction_To_api_ExecAction,
|
||||
autoconvert_v1_FCVolumeSource_To_api_FCVolumeSource,
|
||||
autoconvert_v1_FlockerVolumeSource_To_api_FlockerVolumeSource,
|
||||
autoconvert_v1_GCEPersistentDiskVolumeSource_To_api_GCEPersistentDiskVolumeSource,
|
||||
autoconvert_v1_GitRepoVolumeSource_To_api_GitRepoVolumeSource,
|
||||
autoconvert_v1_GlusterfsVolumeSource_To_api_GlusterfsVolumeSource,
|
||||
|
@@ -607,6 +607,11 @@ func deepCopy_v1_FCVolumeSource(in FCVolumeSource, out *FCVolumeSource, c *conve
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_v1_FlockerVolumeSource(in FlockerVolumeSource, out *FlockerVolumeSource, c *conversion.Cloner) error {
|
||||
out.DatasetName = in.DatasetName
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_v1_GCEPersistentDiskVolumeSource(in GCEPersistentDiskVolumeSource, out *GCEPersistentDiskVolumeSource, c *conversion.Cloner) error {
|
||||
out.PDName = in.PDName
|
||||
out.FSType = in.FSType
|
||||
@@ -1315,6 +1320,14 @@ func deepCopy_v1_PersistentVolumeSource(in PersistentVolumeSource, out *Persiste
|
||||
} else {
|
||||
out.FC = nil
|
||||
}
|
||||
if in.Flocker != nil {
|
||||
out.Flocker = new(FlockerVolumeSource)
|
||||
if err := deepCopy_v1_FlockerVolumeSource(*in.Flocker, out.Flocker, c); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Flocker = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2245,6 +2258,14 @@ func deepCopy_v1_VolumeSource(in VolumeSource, out *VolumeSource, c *conversion.
|
||||
} else {
|
||||
out.CephFS = nil
|
||||
}
|
||||
if in.Flocker != nil {
|
||||
out.Flocker = new(FlockerVolumeSource)
|
||||
if err := deepCopy_v1_FlockerVolumeSource(*in.Flocker, out.Flocker, c); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Flocker = nil
|
||||
}
|
||||
if in.DownwardAPI != nil {
|
||||
out.DownwardAPI = new(DownwardAPIVolumeSource)
|
||||
if err := deepCopy_v1_DownwardAPIVolumeSource(*in.DownwardAPI, out.DownwardAPI, c); err != nil {
|
||||
@@ -2321,6 +2342,7 @@ func init() {
|
||||
deepCopy_v1_EventSource,
|
||||
deepCopy_v1_ExecAction,
|
||||
deepCopy_v1_FCVolumeSource,
|
||||
deepCopy_v1_FlockerVolumeSource,
|
||||
deepCopy_v1_GCEPersistentDiskVolumeSource,
|
||||
deepCopy_v1_GitRepoVolumeSource,
|
||||
deepCopy_v1_GlusterfsVolumeSource,
|
||||
|
@@ -250,6 +250,9 @@ type VolumeSource struct {
|
||||
// CephFS represents a Ceph FS mount on the host that shares a pod's lifetime
|
||||
CephFS *CephFSVolumeSource `json:"cephfs,omitempty"`
|
||||
|
||||
// Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running
|
||||
Flocker *FlockerVolumeSource `json:"flocker,omitempty"`
|
||||
|
||||
// DownwardAPI represents downward API about the pod that should populate this volume
|
||||
DownwardAPI *DownwardAPIVolumeSource `json:"downwardAPI,omitempty"`
|
||||
// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.
|
||||
@@ -306,6 +309,8 @@ type PersistentVolumeSource struct {
|
||||
CephFS *CephFSVolumeSource `json:"cephfs,omitempty"`
|
||||
// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.
|
||||
FC *FCVolumeSource `json:"fc,omitempty"`
|
||||
// Flocker represents a Flocker volume attached to a kubelet's host machine and exposed to the pod for its usage. This depends on the Flocker control service being running
|
||||
Flocker *FlockerVolumeSource `json:"flocker,omitempty"`
|
||||
}
|
||||
|
||||
// PersistentVolume (PV) is a storage resource provisioned by an administrator.
|
||||
@@ -589,6 +594,12 @@ type CephFSVolumeSource struct {
|
||||
ReadOnly bool `json:"readOnly,omitempty"`
|
||||
}
|
||||
|
||||
// FlockerVolumeSource represents a Flocker volume mounted by the Flocker agent.
|
||||
type FlockerVolumeSource struct {
|
||||
// Required: the volume name. This is going to be store on metadata -> name on the payload for Flocker
|
||||
DatasetName string `json:"datasetName"`
|
||||
}
|
||||
|
||||
const (
|
||||
StorageMediumDefault StorageMedium = "" // use whatever the default is for the node
|
||||
StorageMediumMemory StorageMedium = "Memory" // use memory (tmpfs)
|
||||
|
@@ -389,6 +389,15 @@ func (FCVolumeSource) SwaggerDoc() map[string]string {
|
||||
return map_FCVolumeSource
|
||||
}
|
||||
|
||||
var map_FlockerVolumeSource = map[string]string{
|
||||
"": "FlockerVolumeSource represents a Flocker volume mounted by the Flocker agent.",
|
||||
"datasetName": "Required: the volume name. This is going to be store on metadata -> name on the payload for Flocker",
|
||||
}
|
||||
|
||||
func (FlockerVolumeSource) SwaggerDoc() map[string]string {
|
||||
return map_FlockerVolumeSource
|
||||
}
|
||||
|
||||
var map_GCEPersistentDiskVolumeSource = map[string]string{
|
||||
"": "GCEPersistentDiskVolumeSource represents a Persistent Disk resource in Google Compute Engine.\n\nA GCE PD must exist and be formatted before mounting to a container. The disk must also be in the same GCE project and zone as the kubelet. A GCE PD can only be mounted as read/write once.",
|
||||
"pdName": "Unique name of the PD resource in GCE. Used to identify the disk in GCE. More info: http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#gcepersistentdisk",
|
||||
@@ -847,6 +856,7 @@ var map_PersistentVolumeSource = map[string]string{
|
||||
"cinder": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: http://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md",
|
||||
"cephfs": "CephFS represents a Ceph FS mount on the host that shares a pod's lifetime",
|
||||
"fc": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.",
|
||||
"flocker": "Flocker represents a Flocker volume attached to a kubelet's host machine and exposed to the pod for its usage. This depends on the Flocker control service being running",
|
||||
}
|
||||
|
||||
func (PersistentVolumeSource) SwaggerDoc() map[string]string {
|
||||
@@ -1358,6 +1368,7 @@ var map_VolumeSource = map[string]string{
|
||||
"rbd": "RBD represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: http://releases.k8s.io/HEAD/examples/rbd/README.md",
|
||||
"cinder": "Cinder represents a cinder volume attached and mounted on kubelets host machine More info: http://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md",
|
||||
"cephfs": "CephFS represents a Ceph FS mount on the host that shares a pod's lifetime",
|
||||
"flocker": "Flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running",
|
||||
"downwardAPI": "DownwardAPI represents downward API about the pod that should populate this volume",
|
||||
"fc": "FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.",
|
||||
}
|
||||
|
@@ -379,6 +379,10 @@ func validateSource(source *api.VolumeSource) errs.ValidationErrorList {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateGlusterfs(source.Glusterfs).Prefix("glusterfs")...)
|
||||
}
|
||||
if source.Flocker != nil {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateFlocker(source.Flocker).Prefix("flocker")...)
|
||||
}
|
||||
if source.PersistentVolumeClaim != nil {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validatePersistentClaimVolumeSource(source.PersistentVolumeClaim).Prefix("persistentVolumeClaim")...)
|
||||
@@ -531,6 +535,17 @@ func validateGlusterfs(glusterfs *api.GlusterfsVolumeSource) errs.ValidationErro
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateFlocker(flocker *api.FlockerVolumeSource) errs.ValidationErrorList {
|
||||
allErrs := errs.ValidationErrorList{}
|
||||
if flocker.DatasetName == "" {
|
||||
allErrs = append(allErrs, errs.NewFieldRequired("datasetName"))
|
||||
}
|
||||
if strings.Contains(flocker.DatasetName, "/") {
|
||||
allErrs = append(allErrs, errs.NewFieldInvalid("datasetName", flocker.DatasetName, "must not contain '/'"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
var validDownwardAPIFieldPathExpressions = sets.NewString("metadata.name", "metadata.namespace", "metadata.labels", "metadata.annotations")
|
||||
|
||||
func validateDownwardAPIVolumeSource(downwardAPIVolume *api.DownwardAPIVolumeSource) errs.ValidationErrorList {
|
||||
@@ -636,6 +651,10 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) errs.ValidationErrorList
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateGlusterfs(pv.Spec.Glusterfs).Prefix("glusterfs")...)
|
||||
}
|
||||
if pv.Spec.Flocker != nil {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateFlocker(pv.Spec.Flocker).Prefix("flocker")...)
|
||||
}
|
||||
if pv.Spec.NFS != nil {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateNFS(pv.Spec.NFS).Prefix("nfs")...)
|
||||
|
@@ -458,6 +458,7 @@ func TestValidateVolumes(t *testing.T) {
|
||||
{Name: "iscsidisk", VolumeSource: api.VolumeSource{ISCSI: &api.ISCSIVolumeSource{TargetPortal: "127.0.0.1", IQN: "iqn.2015-02.example.com:test", Lun: 1, FSType: "ext4", ReadOnly: false}}},
|
||||
{Name: "secret", VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "my-secret"}}},
|
||||
{Name: "glusterfs", VolumeSource: api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{EndpointsName: "host1", Path: "path", ReadOnly: false}}},
|
||||
{Name: "flocker", VolumeSource: api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: "datasetName"}}},
|
||||
{Name: "rbd", VolumeSource: api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{"foo"}, RBDImage: "bar", FSType: "ext4"}}},
|
||||
{Name: "cinder", VolumeSource: api.VolumeSource{Cinder: &api.CinderVolumeSource{"29ea5088-4f60-4757-962e-dba678767887", "ext4", false}}},
|
||||
{Name: "cephfs", VolumeSource: api.VolumeSource{CephFS: &api.CephFSVolumeSource{Monitors: []string{"foo"}}}},
|
||||
@@ -501,6 +502,7 @@ func TestValidateVolumes(t *testing.T) {
|
||||
emptyIQN := api.VolumeSource{ISCSI: &api.ISCSIVolumeSource{TargetPortal: "127.0.0.1", IQN: "", Lun: 1, FSType: "ext4", ReadOnly: false}}
|
||||
emptyHosts := api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{EndpointsName: "", Path: "path", ReadOnly: false}}
|
||||
emptyPath := api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{EndpointsName: "host", Path: "", ReadOnly: false}}
|
||||
emptyName := api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: ""}}
|
||||
emptyMon := api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{}, RBDImage: "bar", FSType: "ext4"}}
|
||||
emptyImage := api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{"foo"}, RBDImage: "", FSType: "ext4"}}
|
||||
emptyCephFSMon := api.VolumeSource{CephFS: &api.CephFSVolumeSource{Monitors: []string{}}}
|
||||
@@ -531,30 +533,33 @@ func TestValidateVolumes(t *testing.T) {
|
||||
}}
|
||||
zeroWWN := api.VolumeSource{FC: &api.FCVolumeSource{[]string{}, &lun, "ext4", false}}
|
||||
emptyLun := api.VolumeSource{FC: &api.FCVolumeSource{[]string{"wwn"}, nil, "ext4", false}}
|
||||
slashInName := api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: "foo/bar"}}
|
||||
errorCases := map[string]struct {
|
||||
V []api.Volume
|
||||
T errors.ValidationErrorType
|
||||
F string
|
||||
D string
|
||||
}{
|
||||
"zero-length name": {[]api.Volume{{Name: "", VolumeSource: emptyVS}}, errors.ValidationErrorTypeRequired, "[0].name", ""},
|
||||
"name > 63 characters": {[]api.Volume{{Name: strings.Repeat("a", 64), VolumeSource: emptyVS}}, errors.ValidationErrorTypeInvalid, "[0].name", "must be a DNS label (at most 63 characters, matching regex [a-z0-9]([-a-z0-9]*[a-z0-9])?): e.g. \"my-name\""},
|
||||
"name not a DNS label": {[]api.Volume{{Name: "a.b.c", VolumeSource: emptyVS}}, errors.ValidationErrorTypeInvalid, "[0].name", "must be a DNS label (at most 63 characters, matching regex [a-z0-9]([-a-z0-9]*[a-z0-9])?): e.g. \"my-name\""},
|
||||
"name not unique": {[]api.Volume{{Name: "abc", VolumeSource: emptyVS}, {Name: "abc", VolumeSource: emptyVS}}, errors.ValidationErrorTypeDuplicate, "[1].name", ""},
|
||||
"empty portal": {[]api.Volume{{Name: "badportal", VolumeSource: emptyPortal}}, errors.ValidationErrorTypeRequired, "[0].source.iscsi.targetPortal", ""},
|
||||
"empty iqn": {[]api.Volume{{Name: "badiqn", VolumeSource: emptyIQN}}, errors.ValidationErrorTypeRequired, "[0].source.iscsi.iqn", ""},
|
||||
"empty hosts": {[]api.Volume{{Name: "badhost", VolumeSource: emptyHosts}}, errors.ValidationErrorTypeRequired, "[0].source.glusterfs.endpoints", ""},
|
||||
"empty path": {[]api.Volume{{Name: "badpath", VolumeSource: emptyPath}}, errors.ValidationErrorTypeRequired, "[0].source.glusterfs.path", ""},
|
||||
"empty mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyMon}}, errors.ValidationErrorTypeRequired, "[0].source.rbd.monitors", ""},
|
||||
"empty image": {[]api.Volume{{Name: "badimage", VolumeSource: emptyImage}}, errors.ValidationErrorTypeRequired, "[0].source.rbd.image", ""},
|
||||
"empty cephfs mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyCephFSMon}}, errors.ValidationErrorTypeRequired, "[0].source.cephfs.monitors", ""},
|
||||
"empty metatada path": {[]api.Volume{{Name: "emptyname", VolumeSource: emptyPathName}}, errors.ValidationErrorTypeRequired, "[0].source.downwardApi.path", ""},
|
||||
"absolute path": {[]api.Volume{{Name: "absolutepath", VolumeSource: absolutePathName}}, errors.ValidationErrorTypeForbidden, "[0].source.downwardApi.path", ""},
|
||||
"dot dot path": {[]api.Volume{{Name: "dotdotpath", VolumeSource: dotDotInPath}}, errors.ValidationErrorTypeInvalid, "[0].source.downwardApi.path", "must not contain \"..\"."},
|
||||
"dot dot file name": {[]api.Volume{{Name: "dotdotfilename", VolumeSource: dotDotPathName}}, errors.ValidationErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."},
|
||||
"dot dot first level dirent ": {[]api.Volume{{Name: "dotdotdirfilename", VolumeSource: dotDotFirstLevelDirent}}, errors.ValidationErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."},
|
||||
"empty wwn": {[]api.Volume{{Name: "badimage", VolumeSource: zeroWWN}}, errors.ValidationErrorTypeRequired, "[0].source.fc.targetWWNs", ""},
|
||||
"empty lun": {[]api.Volume{{Name: "badimage", VolumeSource: emptyLun}}, errors.ValidationErrorTypeRequired, "[0].source.fc.lun", ""},
|
||||
"zero-length name": {[]api.Volume{{Name: "", VolumeSource: emptyVS}}, errors.ValidationErrorTypeRequired, "[0].name", ""},
|
||||
"name > 63 characters": {[]api.Volume{{Name: strings.Repeat("a", 64), VolumeSource: emptyVS}}, errors.ValidationErrorTypeInvalid, "[0].name", "must be a DNS label (at most 63 characters, matching regex [a-z0-9]([-a-z0-9]*[a-z0-9])?): e.g. \"my-name\""},
|
||||
"name not a DNS label": {[]api.Volume{{Name: "a.b.c", VolumeSource: emptyVS}}, errors.ValidationErrorTypeInvalid, "[0].name", "must be a DNS label (at most 63 characters, matching regex [a-z0-9]([-a-z0-9]*[a-z0-9])?): e.g. \"my-name\""},
|
||||
"name not unique": {[]api.Volume{{Name: "abc", VolumeSource: emptyVS}, {Name: "abc", VolumeSource: emptyVS}}, errors.ValidationErrorTypeDuplicate, "[1].name", ""},
|
||||
"empty portal": {[]api.Volume{{Name: "badportal", VolumeSource: emptyPortal}}, errors.ValidationErrorTypeRequired, "[0].source.iscsi.targetPortal", ""},
|
||||
"empty iqn": {[]api.Volume{{Name: "badiqn", VolumeSource: emptyIQN}}, errors.ValidationErrorTypeRequired, "[0].source.iscsi.iqn", ""},
|
||||
"empty hosts": {[]api.Volume{{Name: "badhost", VolumeSource: emptyHosts}}, errors.ValidationErrorTypeRequired, "[0].source.glusterfs.endpoints", ""},
|
||||
"empty path": {[]api.Volume{{Name: "badpath", VolumeSource: emptyPath}}, errors.ValidationErrorTypeRequired, "[0].source.glusterfs.path", ""},
|
||||
"empty datasetName": {[]api.Volume{{Name: "badname", VolumeSource: emptyName}}, errors.ValidationErrorTypeRequired, "[0].source.flocker.datasetName", ""},
|
||||
"empty mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyMon}}, errors.ValidationErrorTypeRequired, "[0].source.rbd.monitors", ""},
|
||||
"empty image": {[]api.Volume{{Name: "badimage", VolumeSource: emptyImage}}, errors.ValidationErrorTypeRequired, "[0].source.rbd.image", ""},
|
||||
"empty cephfs mon": {[]api.Volume{{Name: "badmon", VolumeSource: emptyCephFSMon}}, errors.ValidationErrorTypeRequired, "[0].source.cephfs.monitors", ""},
|
||||
"empty metatada path": {[]api.Volume{{Name: "emptyname", VolumeSource: emptyPathName}}, errors.ValidationErrorTypeRequired, "[0].source.downwardApi.path", ""},
|
||||
"absolute path": {[]api.Volume{{Name: "absolutepath", VolumeSource: absolutePathName}}, errors.ValidationErrorTypeForbidden, "[0].source.downwardApi.path", ""},
|
||||
"dot dot path": {[]api.Volume{{Name: "dotdotpath", VolumeSource: dotDotInPath}}, errors.ValidationErrorTypeInvalid, "[0].source.downwardApi.path", "must not contain \"..\"."},
|
||||
"dot dot file name": {[]api.Volume{{Name: "dotdotfilename", VolumeSource: dotDotPathName}}, errors.ValidationErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."},
|
||||
"dot dot first level dirent": {[]api.Volume{{Name: "dotdotdirfilename", VolumeSource: dotDotFirstLevelDirent}}, errors.ValidationErrorTypeInvalid, "[0].source.downwardApi.path", "must not start with \"..\"."},
|
||||
"empty wwn": {[]api.Volume{{Name: "badimage", VolumeSource: zeroWWN}}, errors.ValidationErrorTypeRequired, "[0].source.fc.targetWWNs", ""},
|
||||
"empty lun": {[]api.Volume{{Name: "badimage", VolumeSource: emptyLun}}, errors.ValidationErrorTypeRequired, "[0].source.fc.lun", ""},
|
||||
"slash in datasetName": {[]api.Volume{{Name: "slashinname", VolumeSource: slashInName}}, errors.ValidationErrorTypeInvalid, "[0].source.flocker.datasetName", "must not contain '/'"},
|
||||
}
|
||||
for k, v := range errorCases {
|
||||
_, errs := validateVolumes(v.V)
|
||||
|
Reference in New Issue
Block a user