Implements projected volume driver

Proposal: kubernetes/kubernetes#35313
This commit is contained in:
Jeff Peeler
2016-11-10 17:33:06 -05:00
parent b385a94fed
commit 8fb1b71c66
20 changed files with 3269 additions and 29 deletions

View File

@@ -518,6 +518,14 @@ func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.E
numVolumes++
allErrs = append(allErrs, validateAzureDisk(source.AzureDisk, fldPath.Child("azureDisk"))...)
}
if source.Projected != nil {
if numVolumes > 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("projected"), "may not specify more than 1 volume type"))
} else {
numVolumes++
allErrs = append(allErrs, validateProjectedVolumeSource(source.Projected, fldPath.Child("projected"))...)
}
}
if numVolumes == 0 {
allErrs = append(allErrs, field.Required(fldPath, "must specify a volume type"))
@@ -723,6 +731,30 @@ var validDownwardAPIFieldPathExpressions = sets.NewString(
"metadata.labels",
"metadata.annotations")
func validateDownwardAPIVolumeFile(file *api.DownwardAPIVolumeFile, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(file.Path) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
}
allErrs = append(allErrs, validateLocalNonReservedPath(file.Path, fldPath.Child("path"))...)
if file.FieldRef != nil {
allErrs = append(allErrs, validateObjectFieldSelector(file.FieldRef, &validDownwardAPIFieldPathExpressions, fldPath.Child("fieldRef"))...)
if file.ResourceFieldRef != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "resource", "fieldRef and resourceFieldRef can not be specified simultaneously"))
}
} else if file.ResourceFieldRef != nil {
allErrs = append(allErrs, validateContainerResourceFieldSelector(file.ResourceFieldRef, &validContainerResourceFieldPathExpressions, fldPath.Child("resourceFieldRef"), true)...)
} else {
allErrs = append(allErrs, field.Required(fldPath, "one of fieldRef and resourceFieldRef is required"))
}
if file.Mode != nil && (*file.Mode > 0777 || *file.Mode < 0) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("mode"), *file.Mode, volumeModeErrorMsg))
}
return allErrs
}
func validateDownwardAPIVolumeSource(downwardAPIVolume *api.DownwardAPIVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
@@ -732,27 +764,99 @@ func validateDownwardAPIVolumeSource(downwardAPIVolume *api.DownwardAPIVolumeSou
}
for _, file := range downwardAPIVolume.Items {
if len(file.Path) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
}
allErrs = append(allErrs, validateLocalNonReservedPath(file.Path, fldPath.Child("path"))...)
if file.FieldRef != nil {
allErrs = append(allErrs, validateObjectFieldSelector(file.FieldRef, &validDownwardAPIFieldPathExpressions, fldPath.Child("fieldRef"))...)
if file.ResourceFieldRef != nil {
allErrs = append(allErrs, field.Invalid(fldPath, "resource", "fieldRef and resourceFieldRef can not be specified simultaneously"))
allErrs = append(allErrs, validateDownwardAPIVolumeFile(&file, fldPath)...)
}
return allErrs
}
func validateProjectionSources(projection *api.ProjectedVolumeSource, projectionMode *int32, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allPaths := sets.String{}
for _, source := range projection.Sources {
numSources := 0
if source.Secret != nil {
if numSources > 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("secret"), "may not specify more than 1 volume type"))
} else {
numSources++
if len(source.Secret.Name) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
}
itemsPath := fldPath.Child("items")
for i, kp := range source.Secret.Items {
itemPath := itemsPath.Index(i)
allErrs = append(allErrs, validateKeyToPath(&kp, itemPath)...)
if len(kp.Path) > 0 {
curPath := kp.Path
if !allPaths.Has(curPath) {
allPaths.Insert(curPath)
} else {
allErrs = append(allErrs, field.Invalid(fldPath, source.Secret.Name, "conflicting duplicate paths"))
}
}
}
}
} else if file.ResourceFieldRef != nil {
allErrs = append(allErrs, validateContainerResourceFieldSelector(file.ResourceFieldRef, &validContainerResourceFieldPathExpressions, fldPath.Child("resourceFieldRef"), true)...)
} else {
allErrs = append(allErrs, field.Required(fldPath, "one of fieldRef and resourceFieldRef is required"))
}
if file.Mode != nil && (*file.Mode > 0777 || *file.Mode < 0) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("mode"), *file.Mode, volumeModeErrorMsg))
if source.ConfigMap != nil {
if numSources > 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("configMap"), "may not specify more than 1 volume type"))
} else {
numSources++
if len(source.ConfigMap.Name) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
}
itemsPath := fldPath.Child("items")
for i, kp := range source.ConfigMap.Items {
itemPath := itemsPath.Index(i)
allErrs = append(allErrs, validateKeyToPath(&kp, itemPath)...)
if len(kp.Path) > 0 {
curPath := kp.Path
if !allPaths.Has(curPath) {
allPaths.Insert(curPath)
} else {
allErrs = append(allErrs, field.Invalid(fldPath, source.ConfigMap.Name, "conflicting duplicate paths"))
}
}
}
}
}
if source.DownwardAPI != nil {
if numSources > 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("downwardAPI"), "may not specify more than 1 volume type"))
} else {
numSources++
for _, file := range source.DownwardAPI.Items {
allErrs = append(allErrs, validateDownwardAPIVolumeFile(&file, fldPath.Child("downwardAPI"))...)
if len(file.Path) > 0 {
curPath := file.Path
if !allPaths.Has(curPath) {
allPaths.Insert(curPath)
} else {
allErrs = append(allErrs, field.Invalid(fldPath, curPath, "conflicting duplicate paths"))
}
}
}
}
}
}
return allErrs
}
func validateProjectedVolumeSource(projection *api.ProjectedVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
projectionMode := projection.DefaultMode
if projectionMode != nil && (*projectionMode > 0777 || *projectionMode < 0) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("defaultMode"), *projectionMode, volumeModeErrorMsg))
}
allErrs = append(allErrs, validateProjectionSources(projection, projectionMode, fldPath)...)
return allErrs
}
// This validate will make sure targetPath:
// 1. is not abs path
// 2. does not have any element which is ".."