Update dependencies to K8s 1.8

This commit is contained in:
Nick Sardo 2017-09-29 10:12:14 -07:00
parent ba6c89672d
commit 6a59f4c9a2
1114 changed files with 160955 additions and 262845 deletions

View file

@ -1,12 +1,4 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
@ -23,11 +15,12 @@ go_library(
"types.go",
"zz_generated.deepcopy.go",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
@ -44,7 +37,6 @@ go_test(
name = "go_default_test",
srcs = ["taint_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
)
go_test(
@ -59,20 +51,17 @@ go_test(
"serialization_test.go",
"unstructured_test.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
":go_default_library",
"//pkg/api/testapi:go_default_library",
"//pkg/api/testing:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/apis/batch/v2alpha1:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/golang/protobuf/proto:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/ugorji/go/codec:go_default_library",
"//vendor/k8s.io/api/batch/v2alpha1:go_default_library",
"//vendor/github.com/json-iterator/go:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
@ -106,11 +95,10 @@ filegroup(
srcs = [
":package-srcs",
"//pkg/api/endpoints:all-srcs",
"//pkg/api/errors:all-srcs",
"//pkg/api/events:all-srcs",
"//pkg/api/fuzzer:all-srcs",
"//pkg/api/helper:all-srcs",
"//pkg/api/install:all-srcs",
"//pkg/api/meta:all-srcs",
"//pkg/api/persistentvolume:all-srcs",
"//pkg/api/pod:all-srcs",
"//pkg/api/ref:all-srcs",
@ -124,4 +112,5 @@ filegroup(
"//pkg/api/validation:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View file

@ -3,6 +3,8 @@ approvers:
- lavalamp
- smarterclayton
- thockin
- liggitt
# - bgrant0607 # manual escalations only
reviewers:
- thockin
- lavalamp

View file

@ -47,6 +47,8 @@ const (
// CreatedByAnnotation represents the key used to store the spec(json)
// used to create the resource.
// This field is deprecated in favor of ControllerRef (see #44407).
// TODO(#50720): Remove this field in v1.9.
CreatedByAnnotation = "kubernetes.io/created-by"
// PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized)
@ -89,20 +91,4 @@ const (
//
// Not all cloud providers support this annotation, though AWS & GCE do.
AnnotationLoadBalancerSourceRangesKey = "service.beta.kubernetes.io/load-balancer-source-ranges"
// AnnotationValueExternalTrafficLocal Value of annotation to specify local endpoints behavior.
AnnotationValueExternalTrafficLocal = "OnlyLocal"
// AnnotationValueExternalTrafficGlobal Value of annotation to specify global (legacy) behavior.
AnnotationValueExternalTrafficGlobal = "Global"
// TODO: The beta annotations have been deprecated, remove them when we release k8s 1.8.
// BetaAnnotationHealthCheckNodePort Annotation specifying the healthcheck nodePort for the service.
// If not specified, annotation is created by the service api backend with the allocated nodePort.
// Will use user-specified nodePort value if specified by the client.
BetaAnnotationHealthCheckNodePort = "service.beta.kubernetes.io/healthcheck-nodeport"
// BetaAnnotationExternalTraffic An annotation that denotes if this Service desires to route
// external traffic to local endpoints only. This preserves Source IP and avoids a second hop.
BetaAnnotationExternalTraffic = "service.beta.kubernetes.io/external-traffic"
)

View file

@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
@ -12,7 +10,6 @@ go_test(
name = "go_default_test",
srcs = ["helpers_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
@ -23,7 +20,6 @@ go_test(
go_library(
name = "go_default_library",
srcs = ["helpers.go"],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",

View file

@ -31,6 +31,30 @@ import (
"k8s.io/kubernetes/pkg/api"
)
// IsHugePageResourceName returns true if the resource name has the huge page
// resource prefix.
func IsHugePageResourceName(name api.ResourceName) bool {
return strings.HasPrefix(string(name), api.ResourceHugePagesPrefix)
}
// HugePageResourceName returns a ResourceName with the canonical hugepage
// prefix prepended for the specified page size. The page size is converted
// to its canonical representation.
func HugePageResourceName(pageSize resource.Quantity) api.ResourceName {
return api.ResourceName(fmt.Sprintf("%s%s", api.ResourceHugePagesPrefix, pageSize.String()))
}
// HugePageSizeFromResourceName returns the page size for the specified huge page
// resource name. If the specified input is not a valid huge page resource name
// an error is returned.
func HugePageSizeFromResourceName(name api.ResourceName) (resource.Quantity, error) {
if !IsHugePageResourceName(name) {
return resource.Quantity{}, fmt.Errorf("resource name: %s is not valid hugepage name", name)
}
pageSize := strings.TrimPrefix(string(name), api.ResourceHugePagesPrefix)
return resource.ParseQuantity(pageSize)
}
// NonConvertibleFields iterates over the provided map and filters out all but
// any keys with the "non-convertible.kubernetes.io" prefix.
func NonConvertibleFields(annotations map[string]string) map[string]string {
@ -53,6 +77,9 @@ var Semantic = conversion.EqualitiesOrDie(
// Uninitialized quantities are equivalent to 0 quantities.
return a.Cmp(b) == 0
},
func(a, b metav1.MicroTime) bool {
return a.UTC() == b.UTC()
},
func(a, b metav1.Time) bool {
return a.UTC() == b.UTC()
},
@ -104,12 +131,28 @@ func IsResourceQuotaScopeValidForResource(scope api.ResourceQuotaScope, resource
var standardContainerResources = sets.NewString(
string(api.ResourceCPU),
string(api.ResourceMemory),
string(api.ResourceEphemeralStorage),
)
// IsStandardContainerResourceName returns true if the container can make a resource request
// for the specified resource
func IsStandardContainerResourceName(str string) bool {
return standardContainerResources.Has(str)
return standardContainerResources.Has(str) || IsHugePageResourceName(api.ResourceName(str))
}
// IsExtendedResourceName returns true if the resource name is not in the
// default namespace, or it has the opaque integer resource prefix.
func IsExtendedResourceName(name api.ResourceName) bool {
// TODO: Remove OIR part following deprecation.
return !IsDefaultNamespaceResource(name) || IsOpaqueIntResourceName(name)
}
// IsDefaultNamespaceResource returns true if the resource name is in the
// *kubernetes.io/ namespace. Partially-qualified (unprefixed) names are
// implicitly in the kubernetes.io/ namespace.
func IsDefaultNamespaceResource(name api.ResourceName) bool {
return !strings.Contains(string(name), "/") ||
strings.Contains(string(name), api.ResourceDefaultNamespacePrefix)
}
// IsOpaqueIntResourceName returns true if the resource name has the opaque
@ -128,6 +171,16 @@ func OpaqueIntResourceName(name string) api.ResourceName {
return api.ResourceName(fmt.Sprintf("%s%s", api.ResourceOpaqueIntPrefix, name))
}
var overcommitBlacklist = sets.NewString(string(api.ResourceNvidiaGPU))
// IsOvercommitAllowed returns true if the resource is in the default
// namespace and not blacklisted.
func IsOvercommitAllowed(name api.ResourceName) bool {
return IsDefaultNamespaceResource(name) &&
!IsHugePageResourceName(name) &&
!overcommitBlacklist.Has(string(name))
}
var standardLimitRangeTypes = sets.NewString(
string(api.LimitTypePod),
string(api.LimitTypeContainer),
@ -142,11 +195,14 @@ func IsStandardLimitRangeType(str string) bool {
var standardQuotaResources = sets.NewString(
string(api.ResourceCPU),
string(api.ResourceMemory),
string(api.ResourceEphemeralStorage),
string(api.ResourceRequestsCPU),
string(api.ResourceRequestsMemory),
string(api.ResourceRequestsStorage),
string(api.ResourceRequestsEphemeralStorage),
string(api.ResourceLimitsCPU),
string(api.ResourceLimitsMemory),
string(api.ResourceLimitsEphemeralStorage),
string(api.ResourcePods),
string(api.ResourceQuotas),
string(api.ResourceServices),
@ -167,10 +223,13 @@ func IsStandardQuotaResourceName(str string) bool {
var standardResources = sets.NewString(
string(api.ResourceCPU),
string(api.ResourceMemory),
string(api.ResourceEphemeralStorage),
string(api.ResourceRequestsCPU),
string(api.ResourceRequestsMemory),
string(api.ResourceRequestsEphemeralStorage),
string(api.ResourceLimitsCPU),
string(api.ResourceLimitsMemory),
string(api.ResourceLimitsEphemeralStorage),
string(api.ResourcePods),
string(api.ResourceQuotas),
string(api.ResourceServices),
@ -180,11 +239,13 @@ var standardResources = sets.NewString(
string(api.ResourcePersistentVolumeClaims),
string(api.ResourceStorage),
string(api.ResourceRequestsStorage),
string(api.ResourceServicesNodePorts),
string(api.ResourceServicesLoadBalancers),
)
// IsStandardResourceName returns true if the resource is known to the system
func IsStandardResourceName(str string) bool {
return standardResources.Has(str)
return standardResources.Has(str) || IsHugePageResourceName(api.ResourceName(str))
}
var integerResources = sets.NewString(
@ -201,7 +262,7 @@ var integerResources = sets.NewString(
// IsIntegerResourceName returns true if the resource is measured in integer values
func IsIntegerResourceName(str string) bool {
return integerResources.Has(str) || IsOpaqueIntResourceName(api.ResourceName(str))
return integerResources.Has(str) || IsExtendedResourceName(api.ResourceName(str))
}
// this function aims to check if the service's ClusterIP is set or not

View file

@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
@ -11,7 +9,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["install.go"],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library",
@ -26,7 +23,6 @@ go_test(
name = "go_default_test",
srcs = ["install_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",

View file

@ -37,7 +37,6 @@ func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *r
&announced.GroupMetaFactoryArgs{
GroupName: api.GroupName,
VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version},
ImportPrefix: "k8s.io/api/core",
AddInternalObjectsToScheme: api.AddToScheme,
RootScopedKinds: sets.NewString(
"Node",

View file

@ -85,6 +85,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ServiceProxyOptions{},
&NodeList{},
&Node{},
&NodeConfigSource{},
&NodeProxyOptions{},
&Endpoints{},
&EndpointsList{},

View file

@ -54,8 +54,8 @@ func (self *ResourceList) NvidiaGPU() *resource.Quantity {
return &resource.Quantity{}
}
func (self *ResourceList) StorageOverlay() *resource.Quantity {
if val, ok := (*self)[ResourceStorageOverlay]; ok {
func (self *ResourceList) StorageEphemeral() *resource.Quantity {
if val, ok := (*self)[ResourceEphemeralStorage]; ok {
return &val
}
return &resource.Quantity{}

View file

@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
@ -11,11 +9,9 @@ load(
go_library(
name = "go_default_library",
srcs = ["util.go"],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/util/net/sets:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
],
)
@ -23,12 +19,9 @@ go_test(
name = "go_default_test",
srcs = ["util_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/util/net/sets:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
],
)

View file

@ -18,13 +18,10 @@ package service
import (
"fmt"
"strconv"
"strings"
"k8s.io/kubernetes/pkg/api"
netsets "k8s.io/kubernetes/pkg/util/net/sets"
"github.com/golang/glog"
)
const (
@ -77,72 +74,13 @@ func RequestsOnlyLocalTraffic(service *api.Service) bool {
return false
}
// First check the beta annotation and then the first class field. This is so that
// existing Services continue to work till the user decides to transition to the
// first class field.
if l, ok := service.Annotations[api.BetaAnnotationExternalTraffic]; ok {
switch l {
case api.AnnotationValueExternalTrafficLocal:
return true
case api.AnnotationValueExternalTrafficGlobal:
return false
default:
glog.Errorf("Invalid value for annotation %v: %v", api.BetaAnnotationExternalTraffic, l)
return false
}
}
return service.Spec.ExternalTrafficPolicy == api.ServiceExternalTrafficPolicyTypeLocal
}
// NeedsHealthCheck Check if service needs health check.
// NeedsHealthCheck checks if service needs health check.
func NeedsHealthCheck(service *api.Service) bool {
if service.Spec.Type != api.ServiceTypeLoadBalancer {
return false
}
return RequestsOnlyLocalTraffic(service)
}
// GetServiceHealthCheckNodePort Return health check node port for service, if one exists
func GetServiceHealthCheckNodePort(service *api.Service) int32 {
// First check the beta annotation and then the first class field. This is so that
// existing Services continue to work till the user decides to transition to the
// first class field.
if l, ok := service.Annotations[api.BetaAnnotationHealthCheckNodePort]; ok {
p, err := strconv.Atoi(l)
if err != nil {
glog.Errorf("Failed to parse annotation %v: %v", api.BetaAnnotationHealthCheckNodePort, err)
return 0
}
return int32(p)
}
return service.Spec.HealthCheckNodePort
}
// ClearExternalTrafficPolicy resets the ExternalTrafficPolicy field.
func ClearExternalTrafficPolicy(service *api.Service) {
// First check the beta annotation and then the first class field. This is so that
// existing Services continue to work till the user decides to transition to the
// first class field.
if _, ok := service.Annotations[api.BetaAnnotationExternalTraffic]; ok {
delete(service.Annotations, api.BetaAnnotationExternalTraffic)
return
}
service.Spec.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyType("")
}
// SetServiceHealthCheckNodePort sets the given health check node port on service.
// It does not check whether this service needs healthCheckNodePort.
func SetServiceHealthCheckNodePort(service *api.Service, hcNodePort int32) {
// First check the beta annotation and then the first class field. This is so that
// existing Services continue to work till the user decides to transition to the
// first class field.
if _, ok := service.Annotations[api.BetaAnnotationExternalTraffic]; ok {
if hcNodePort == 0 {
delete(service.Annotations, api.BetaAnnotationHealthCheckNodePort)
} else {
service.Annotations[api.BetaAnnotationHealthCheckNodePort] = fmt.Sprintf("%d", hcNodePort)
}
return
}
service.Spec.HealthCheckNodePort = hcNodePort
}

View file

@ -18,10 +18,10 @@ package api
import (
"k8s.io/apimachinery/pkg/api/resource"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
)
@ -360,7 +360,7 @@ type PersistentVolumeSource struct {
Cinder *CinderVolumeSource
// CephFS represents a Ceph FS mount on the host that shares a pod's lifetime
// +optional
CephFS *CephFSVolumeSource
CephFS *CephFSPersistentVolumeSource
// FC represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.
// +optional
FC *FCVolumeSource
@ -369,7 +369,7 @@ type PersistentVolumeSource struct {
Flocker *FlockerVolumeSource
// AzureFile represents an Azure File Service mount on the host and bind mount to the pod.
// +optional
AzureFile *AzureFileVolumeSource
AzureFile *AzureFilePersistentVolumeSource
// VsphereVolume represents a vSphere volume attached and mounted on kubelets host machine
// +optional
VsphereVolume *VsphereVirtualDiskVolumeSource
@ -455,6 +455,10 @@ type PersistentVolumeSpec struct {
// means that this volume does not belong to any StorageClass.
// +optional
StorageClassName string
// A list of mount options, e.g. ["ro", "soft"]. Not validated - mount will
// simply fail if one is invalid.
// +optional
MountOptions []string
}
// PersistentVolumeReclaimPolicy describes a policy for end-of-life maintenance of persistent volumes
@ -543,6 +547,27 @@ type PersistentVolumeClaimSpec struct {
StorageClassName *string
}
type PersistentVolumeClaimConditionType string
// These are valid conditions of Pvc
const (
// An user trigger resize of pvc has been started
PersistentVolumeClaimResizing PersistentVolumeClaimConditionType = "Resizing"
)
type PersistentVolumeClaimCondition struct {
Type PersistentVolumeClaimConditionType
Status ConditionStatus
// +optional
LastProbeTime metav1.Time
// +optional
LastTransitionTime metav1.Time
// +optional
Reason string
// +optional
Message string
}
type PersistentVolumeClaimStatus struct {
// Phase represents the current phase of PersistentVolumeClaim
// +optional
@ -553,6 +578,8 @@ type PersistentVolumeClaimStatus struct {
// Represents the actual resources of the underlying volume
// +optional
Capacity ResourceList
// +optional
Conditions []PersistentVolumeClaimCondition
}
type PersistentVolumeAccessMode string
@ -597,10 +624,36 @@ const (
ClaimLost PersistentVolumeClaimPhase = "Lost"
)
type HostPathType string
const (
// For backwards compatible, leave it empty if unset
HostPathUnset HostPathType = ""
// If nothing exists at the given path, an empty directory will be created there
// as needed with file mode 0755, having the same group and ownership with Kubelet.
HostPathDirectoryOrCreate HostPathType = "DirectoryOrCreate"
// A directory must exist at the given path
HostPathDirectory HostPathType = "Directory"
// If nothing exists at the given path, an empty file will be created there
// as needed with file mode 0644, having the same group and ownership with Kubelet.
HostPathFileOrCreate HostPathType = "FileOrCreate"
// A file must exist at the given path
HostPathFile HostPathType = "File"
// A UNIX socket must exist at the given path
HostPathSocket HostPathType = "Socket"
// A character device must exist at the given path
HostPathCharDev HostPathType = "CharDevice"
// A block device must exist at the given path
HostPathBlockDev HostPathType = "BlockDevice"
)
// Represents a host path mapped into a pod.
// Host path volumes do not support ownership management or SELinux relabeling.
type HostPathVolumeSource struct {
// If the path is a symlink, it will follow the link to the real path.
Path string
// Defaults to ""
Type *HostPathType
}
// Represents an empty directory for a pod.
@ -621,15 +674,16 @@ type EmptyDirVolumeSource struct {
// The default is nil which means that the limit is undefined.
// More info: http://kubernetes.io/docs/user-guide/volumes#emptydir
// +optional
SizeLimit resource.Quantity
SizeLimit *resource.Quantity
}
// StorageMedium defines ways that storage can be allocated to a volume.
type StorageMedium string
const (
StorageMediumDefault StorageMedium = "" // use whatever the default is for the node
StorageMediumMemory StorageMedium = "Memory" // use memory (tmpfs)
StorageMediumDefault StorageMedium = "" // use whatever the default is for the node
StorageMediumMemory StorageMedium = "Memory" // use memory (tmpfs)
StorageMediumHugePages StorageMedium = "HugePages" // use hugepages
)
// Protocol defines network protocols supported for things like container ports.
@ -709,15 +763,22 @@ type ISCSIVolumeSource struct {
// The secret is used if either DiscoveryCHAPAuth or SessionCHAPAuth is true
// +optional
SecretRef *LocalObjectReference
// Optional: Custom initiator name per volume.
// If initiatorName is specified with iscsiInterface simultaneously, new iSCSI interface
// <target portal>:<volume name> will be created for the connection.
// +optional
InitiatorName *string
}
// Represents a Fibre Channel volume.
// Fibre Channel volumes can only be mounted as read/write once.
// Fibre Channel volumes support ownership management and SELinux relabeling.
type FCVolumeSource struct {
// Required: FC target worldwide names (WWNs)
// Optional: FC target worldwide names (WWNs)
// +optional
TargetWWNs []string
// Required: FC target lun number
// Optional: FC target lun number
// +optional
Lun *int32
// Filesystem type to mount.
// Must be a filesystem type supported by the host operating system.
@ -729,6 +790,10 @@ type FCVolumeSource struct {
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool
// Optional: FC volume World Wide Identifiers (WWIDs)
// Either WWIDs or TargetWWNs and Lun must be set, but not both simultaneously.
// +optional
WWIDs []string
}
// FlexVolume represents a generic volume resource that is
@ -982,6 +1047,40 @@ type CephFSVolumeSource struct {
ReadOnly bool
}
// SecretReference represents a Secret Reference. It has enough information to retrieve secret
// in any namespace
type SecretReference struct {
// Name is unique within a namespace to reference a secret resource.
// +optional
Name string
// Namespace defines the space within which the secret name must be unique.
// +optional
Namespace string
}
// Represents a Ceph Filesystem mount that lasts the lifetime of a pod
// Cephfs volumes do not support ownership management or SELinux relabeling.
type CephFSPersistentVolumeSource struct {
// Required: Monitors is a collection of Ceph monitors
Monitors []string
// Optional: Used as the mounted root, rather than the full Ceph tree, default is /
// +optional
Path string
// Optional: User is the rados user name, default is admin
// +optional
User string
// Optional: SecretFile is the path to key ring for User, default is /etc/ceph/user.secret
// +optional
SecretFile string
// Optional: SecretRef is reference to the authentication secret for User, default is empty.
// +optional
SecretRef *SecretReference
// Optional: Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool
}
// Represents a Flocker volume mounted by the Flocker agent.
// One and only one of datasetName and datasetUUID should be set.
// Flocker volumes do not support ownership management or SELinux relabeling.
@ -1050,6 +1149,22 @@ type AzureFileVolumeSource struct {
ReadOnly bool
}
// AzureFile represents an Azure File Service mount on the host and bind mount to the pod.
type AzureFilePersistentVolumeSource struct {
// the name of secret that contains Azure Storage Account Name and Key
SecretName string
// Share Name
ShareName string
// Defaults to false (read/write). ReadOnly here will force
// the ReadOnly setting in VolumeMounts.
// +optional
ReadOnly bool
// the namespace of the secret that contains Azure Storage Account Name and Key
// default is the same as the Pod
// +optional
SecretNamespace *string
}
// Represents a vSphere volume resource.
type VsphereVirtualDiskVolumeSource struct {
// Path that identifies vSphere volume vmdk
@ -1354,8 +1469,34 @@ type VolumeMount struct {
// Defaults to "" (volume's root).
// +optional
SubPath string
// mountPropagation determines how mounts are propagated from the host
// to container and the other way around.
// When not set, MountPropagationHostToContainer is used.
// This field is alpha in 1.8 and can be reworked or removed in a future
// release.
// +optional
MountPropagation *MountPropagationMode
}
// MountPropagationMode describes mount propagation.
type MountPropagationMode string
const (
// MountPropagationHostToContainer means that the volume in a container will
// receive new mounts from the host or other containers, but filesystems
// mounted inside the container won't be propagated to the host or other
// containers.
// Note that this mode is recursively applied to all mounts in the volume
// ("rslave" in Linux terminology).
MountPropagationHostToContainer MountPropagationMode = "HostToContainer"
// MountPropagationBidirectional means that the volume in a container will
// receive new mounts from the host or other containers, and its own mounts
// will be propagated from the container to the host or other containers.
// Note that this mode is recursively applied to all mounts in the volume
// ("rshared" in Linux terminology).
MountPropagationBidirectional MountPropagationMode = "Bidirectional"
)
// EnvVar represents an environment variable present in a Container.
type EnvVar struct {
// Required: This must be a C_IDENTIFIER.
@ -1383,7 +1524,7 @@ type EnvVarSource struct {
// +optional
FieldRef *ObjectFieldSelector
// Selects a resource of the container: only resources limits and requests
// (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.
// (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
// +optional
ResourceFieldRef *ResourceFieldSelector
// Selects a key of a ConfigMap.
@ -1440,7 +1581,7 @@ type SecretKeySelector struct {
// EnvFromSource represents the source of a set of ConfigMaps
type EnvFromSource struct {
// An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.
// An optional identifier to prepend to each key in the ConfigMap.
// +optional
Prefix string
// The ConfigMap to select from.
@ -1944,6 +2085,7 @@ type PodAffinity struct {
// podAffinityTerm are intersected, i.e. all terms must be satisfied.
// +optional
// RequiredDuringSchedulingRequiredDuringExecution []PodAffinityTerm
// If the affinity requirements specified by this field are not met at
// scheduling time, the pod will not be scheduled onto the node.
// If the affinity requirements specified by this field cease to be met
@ -1978,6 +2120,7 @@ type PodAntiAffinity struct {
// podAffinityTerm are intersected, i.e. all terms must be satisfied.
// +optional
// RequiredDuringSchedulingRequiredDuringExecution []PodAffinityTerm
// If the anti-affinity requirements specified by this field are not met at
// scheduling time, the pod will not be scheduled onto the node.
// If the anti-affinity requirements specified by this field cease to be met
@ -2026,9 +2169,7 @@ type PodAffinityTerm struct {
// the labelSelector in the specified namespaces, where co-located is defined as running on a node
// whose value of the label with key topologyKey matches that of any node on which any of the
// selected pods is running.
// For PreferredDuringScheduling pod anti-affinity, empty topologyKey is interpreted as "all topologies"
// ("all topologies" here means all the topologyKeys indicated by scheduler command-line argument --failure-domains);
// for affinity and for RequiredDuringScheduling pod anti-affinity, empty topologyKey is not allowed.
// Empty topologyKey is not allowed.
// +optional
TopologyKey string
}
@ -2073,8 +2214,8 @@ type PreferredSchedulingTerm struct {
Preference NodeSelectorTerm
}
// The node this Taint is attached to has the effect "effect" on
// any pod that that does not tolerate the Taint.
// The node this Taint is attached to has the "effect" on
// any pod that does not tolerate the Taint.
type Taint struct {
// Required. The taint key to be applied to a node.
Key string
@ -2108,6 +2249,7 @@ const (
// Kubelet without going through the scheduler to start.
// Enforced by Kubelet and the scheduler.
// TaintEffectNoScheduleNoAdmit TaintEffect = "NoScheduleNoAdmit"
// Evict any already-running pods that do not tolerate the taint.
// Currently enforced by NodeController.
TaintEffectNoExecute TaintEffect = "NoExecute"
@ -2516,6 +2658,8 @@ type ReplicationControllerCondition struct {
}
// +genclient
// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/kubernetes/pkg/apis/extensions.Scale
// +genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/kubernetes/pkg/apis/extensions.Scale,result=k8s.io/kubernetes/pkg/apis/extensions.Scale
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ReplicationController represents the configuration of a replication controller.
@ -2573,6 +2717,31 @@ const (
ServiceAffinityNone ServiceAffinity = "None"
)
const (
// DefaultClientIPServiceAffinitySeconds is the default timeout seconds
// of Client IP based session affinity - 3 hours.
DefaultClientIPServiceAffinitySeconds int32 = 10800
// MaxClientIPServiceAffinitySeconds is the max timeout seconds
// of Client IP based session affinity - 1 day.
MaxClientIPServiceAffinitySeconds int32 = 86400
)
// SessionAffinityConfig represents the configurations of session affinity.
type SessionAffinityConfig struct {
// clientIP contains the configurations of Client IP based session affinity.
// +optional
ClientIP *ClientIPConfig
}
// ClientIPConfig represents the configurations of Client IP based session affinity.
type ClientIPConfig struct {
// timeoutSeconds specifies the seconds of ClientIP type session sticky time.
// The value must be >0 && <=86400(for 1 day) if ServiceAffinity == "ClientIP".
// Default value is 10800(for 3 hours).
// +optional
TimeoutSeconds *int32
}
// Service Type string describes ingress methods for a service
type ServiceType string
@ -2700,6 +2869,10 @@ type ServiceSpec struct {
// +optional
SessionAffinity ServiceAffinity
// sessionAffinityConfig contains the configurations of session affinity.
// +optional
SessionAffinityConfig *SessionAffinityConfig
// Optional: If specified and supported by the platform, this will restrict traffic through the cloud-provider
// load-balancer will be restricted to the specified client IPs. This field will be ignored if the
// cloud-provider does not support the feature."
@ -2722,6 +2895,18 @@ type ServiceSpec struct {
// and ExternalTrafficPolicy is set to Local.
// +optional
HealthCheckNodePort int32
// publishNotReadyAddresses, when set to true, indicates that DNS implementations
// must publish the notReadyAddresses of subsets for the Endpoints associated with
// the Service. The default value is false.
// The primary use case for setting this field is to use a StatefulSet's Headless Service
// to propagate SRV records for its Pods without respect to their readiness for purpose
// of peer discovery.
// This field will replace the service.alpha.kubernetes.io/tolerate-unready-endpoints
// when that annotation is deprecated and all clients have been converted to use this
// field.
// +optional
PublishNotReadyAddresses bool
}
type ServicePort struct {
@ -2913,6 +3098,19 @@ type NodeSpec struct {
// If specified, the node's taints.
// +optional
Taints []Taint
// If specified, the source to get node configuration from
// The DynamicKubeletConfig feature gate must be enabled for the Kubelet to use this field
// +optional
ConfigSource *NodeConfigSource
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// NodeConfigSource specifies a source of node configuration. Exactly one subfield must be non-nil.
type NodeConfigSource struct {
metav1.TypeMeta
ConfigMapRef *ObjectReference
}
// DaemonEndpoint contains information about a single Daemon endpoint.
@ -3078,6 +3276,8 @@ const (
NodeDiskPressure NodeConditionType = "DiskPressure"
// NodeNetworkUnavailable means that network for the node is not correctly configured.
NodeNetworkUnavailable NodeConditionType = "NetworkUnavailable"
// NodeConfigOK indicates whether the kubelet is correctly configured
NodeConfigOK NodeConditionType = "ConfigOK"
)
type NodeCondition struct {
@ -3131,20 +3331,20 @@ const (
ResourceMemory ResourceName = "memory"
// Volume size, in bytes (e,g. 5Gi = 5GiB = 5 * 1024 * 1024 * 1024)
ResourceStorage ResourceName = "storage"
// Local Storage for overlay filesystem, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
// The resource name for ResourceStorageOverlay is alpha and it can change across releases.
ResourceStorageOverlay ResourceName = "storage.kubernetes.io/overlay"
// Local Storage for scratch space, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
// The resource name for ResourceStorageScratch is alpha and it can change across releases.
ResourceStorageScratch ResourceName = "storage.kubernetes.io/scratch"
// Local ephemeral storage, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
// The resource name for ResourceEphemeralStorage is alpha and it can change across releases.
ResourceEphemeralStorage ResourceName = "ephemeral-storage"
// NVIDIA GPU, in devices. Alpha, might change: although fractional and allowing values >1, only one whole device per node is assigned.
ResourceNvidiaGPU ResourceName = "alpha.kubernetes.io/nvidia-gpu"
// Number of Pods that may be running on this Node: see ResourcePods
)
const (
// Namespace prefix for opaque counted resources (alpha).
ResourceOpaqueIntPrefix = "pod.alpha.kubernetes.io/opaque-int-resource-"
// Default namespace prefix.
ResourceDefaultNamespacePrefix = "kubernetes.io/"
// Name prefix for huge page resources (alpha).
ResourceHugePagesPrefix = "hugepages-"
)
// ResourceList is a set of (resource name, quantity) pairs.
@ -3593,13 +3793,7 @@ type EventList struct {
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// List holds a list of objects, which may not be known by the server.
type List struct {
metav1.TypeMeta
// +optional
metav1.ListMeta
Items []runtime.Object
}
type List metainternalversion.List
// A type of object that is limited
type LimitType string
@ -3693,10 +3887,14 @@ const (
ResourceRequestsMemory ResourceName = "requests.memory"
// Storage request, in bytes
ResourceRequestsStorage ResourceName = "requests.storage"
// Local ephemeral storage request, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
ResourceRequestsEphemeralStorage ResourceName = "requests.ephemeral-storage"
// CPU limit, in cores. (500m = .5 cores)
ResourceLimitsCPU ResourceName = "limits.cpu"
// Memory limit, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
ResourceLimitsMemory ResourceName = "limits.memory"
// Local ephemeral storage limit, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
ResourceLimitsEphemeralStorage ResourceName = "limits.ephemeral-storage"
)
// A ResourceQuotaScope defines a filter that must match each object tracked by a quota
@ -4030,6 +4228,11 @@ type SecurityContext struct {
// files to, ensuring the persistent data can only be written to mounts.
// +optional
ReadOnlyRootFilesystem *bool
// AllowPrivilegeEscalation controls whether a process can gain more
// privileges than its parent process. This bool directly controls if
// the no_new_privs flag will be set on the container process.
// +optional
AllowPrivilegeEscalation *bool
}
// SELinuxOptions are the labels to be applied to the container.

View file

@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
@ -11,14 +9,12 @@ load(
go_library(
name = "go_default_library",
srcs = ["group_version.go"],
tags = ["automanaged"],
)
go_test(
name = "go_default_test",
srcs = ["group_version_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
)
filegroup(

View file

@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
@ -19,13 +17,13 @@ go_library(
"zz_generated.conversion.go",
"zz_generated.defaults.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/util/parsers:go_default_library",
"//pkg/util/pointer:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
@ -44,12 +42,11 @@ go_test(
"conversion_test.go",
"defaults_test.go",
],
tags = ["automanaged"],
deps = [
":go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/install:go_default_library",
"//pkg/api/testing/compat:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/api/validation:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",

View file

@ -17,7 +17,6 @@ limitations under the License.
package v1
import (
"encoding/json"
"fmt"
"reflect"
@ -154,32 +153,6 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
return err
}
// Add field label conversions for kinds having selectable nothing but v1.ObjectMeta fields.
for _, k := range []string{
"Endpoints",
"ResourceQuota",
"PersistentVolumeClaim",
"Service",
"ServiceAccount",
"ConfigMap",
} {
kind := k // don't close over range variables
err = scheme.AddFieldLabelConversionFunc("v1", kind,
func(label, value string) (string, string, error) {
switch label {
case "metadata.namespace",
"metadata.name":
return label, value, nil
default:
return "", "", fmt.Errorf("field label %q not supported for %q", label, kind)
}
},
)
if err != nil {
return err
}
}
// Add field conversion funcs.
err = scheme.AddFieldLabelConversionFunc("v1", "Pod",
func(label, value string) (string, string, error) {
@ -192,6 +165,7 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
"spec.nodeName",
"spec.restartPolicy",
"spec.serviceAccountName",
"spec.schedulerName",
"status.phase",
"status.hostIP",
"status.podIP":
@ -236,19 +210,6 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
if err != nil {
return err
}
err = scheme.AddFieldLabelConversionFunc("v1", "PersistentVolume",
func(label, value string) (string, string, error) {
switch label {
case "metadata.name":
return label, value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
},
)
if err != nil {
return err
}
if err := AddFieldLabelConversionsForEvent(scheme); err != nil {
return err
}
@ -368,146 +329,19 @@ func Convert_v1_ReplicationControllerSpec_To_api_ReplicationControllerSpec(in *v
return nil
}
func Convert_api_PodStatusResult_To_v1_PodStatusResult(in *api.PodStatusResult, out *v1.PodStatusResult, s conversion.Scope) error {
if err := autoConvert_api_PodStatusResult_To_v1_PodStatusResult(in, out, s); err != nil {
return err
}
if old := out.Annotations; old != nil {
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
}
if len(out.Status.InitContainerStatuses) > 0 {
if out.Annotations == nil {
out.Annotations = make(map[string]string)
}
value, err := json.Marshal(out.Status.InitContainerStatuses)
if err != nil {
return err
}
out.Annotations[v1.PodInitContainerStatusesAnnotationKey] = string(value)
out.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey] = string(value)
} else {
delete(out.Annotations, v1.PodInitContainerStatusesAnnotationKey)
delete(out.Annotations, v1.PodInitContainerStatusesBetaAnnotationKey)
}
return nil
}
func Convert_v1_PodStatusResult_To_api_PodStatusResult(in *v1.PodStatusResult, out *api.PodStatusResult, s conversion.Scope) error {
// TODO: sometime after we move init container to stable, remove these conversions
// If there is a beta annotation, copy to alpha key.
// See commit log for PR #31026 for why we do this.
if valueBeta, okBeta := in.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey]; okBeta {
in.Annotations[v1.PodInitContainerStatusesAnnotationKey] = valueBeta
}
// Move the annotation to the internal repr. field
if value, ok := in.Annotations[v1.PodInitContainerStatusesAnnotationKey]; ok {
var values []v1.ContainerStatus
if err := json.Unmarshal([]byte(value), &values); err != nil {
return err
}
// Conversion from external to internal version exists more to
// satisfy the needs of the decoder than it does to be a general
// purpose tool. And Decode always creates an intermediate object
// to decode to. Thus the caller of UnsafeConvertToVersion is
// taking responsibility to ensure mutation of in is not exposed
// back to the caller.
in.Status.InitContainerStatuses = values
}
if err := autoConvert_v1_PodStatusResult_To_api_PodStatusResult(in, out, s); err != nil {
return err
}
if len(out.Annotations) > 0 {
old := out.Annotations
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
delete(out.Annotations, v1.PodInitContainerStatusesAnnotationKey)
delete(out.Annotations, v1.PodInitContainerStatusesBetaAnnotationKey)
}
return nil
}
func Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(in *api.PodTemplateSpec, out *v1.PodTemplateSpec, s conversion.Scope) error {
if err := autoConvert_api_PodTemplateSpec_To_v1_PodTemplateSpec(in, out, s); err != nil {
return err
}
// TODO: sometime after we move init container to stable, remove these conversions.
if old := out.Annotations; old != nil {
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
}
if len(out.Spec.InitContainers) > 0 {
if out.Annotations == nil {
out.Annotations = make(map[string]string)
}
value, err := json.Marshal(out.Spec.InitContainers)
if err != nil {
return err
}
out.Annotations[v1.PodInitContainersAnnotationKey] = string(value)
out.Annotations[v1.PodInitContainersBetaAnnotationKey] = string(value)
} else {
delete(out.Annotations, v1.PodInitContainersAnnotationKey)
delete(out.Annotations, v1.PodInitContainersBetaAnnotationKey)
}
return nil
}
func Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(in *v1.PodTemplateSpec, out *api.PodTemplateSpec, s conversion.Scope) error {
// TODO: sometime after we move init container to stable, remove these conversions
// If there is a beta annotation, copy to alpha key.
// See commit log for PR #31026 for why we do this.
if valueBeta, okBeta := in.Annotations[v1.PodInitContainersBetaAnnotationKey]; okBeta {
in.Annotations[v1.PodInitContainersAnnotationKey] = valueBeta
}
// Move the annotation to the internal repr. field
if value, ok := in.Annotations[v1.PodInitContainersAnnotationKey]; ok {
var values []v1.Container
if err := json.Unmarshal([]byte(value), &values); err != nil {
return err
}
// Conversion from external to internal version exists more to
// satisfy the needs of the decoder than it does to be a general
// purpose tool. And Decode always creates an intermediate object
// to decode to. Thus the caller of UnsafeConvertToVersion is
// taking responsibility to ensure mutation of in is not exposed
// back to the caller.
in.Spec.InitContainers = values
// Call defaulters explicitly until annotations are removed
tmpPodTemp := &v1.PodTemplate{
Template: v1.PodTemplateSpec{
Spec: v1.PodSpec{
HostNetwork: in.Spec.HostNetwork,
InitContainers: values,
},
},
}
SetObjectDefaults_PodTemplate(tmpPodTemp)
in.Spec.InitContainers = tmpPodTemp.Template.Spec.InitContainers
}
if err := autoConvert_v1_PodTemplateSpec_To_api_PodTemplateSpec(in, out, s); err != nil {
return err
}
if len(out.Annotations) > 0 {
old := out.Annotations
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
delete(out.Annotations, v1.PodInitContainersAnnotationKey)
delete(out.Annotations, v1.PodInitContainersBetaAnnotationKey)
}
return nil
}
@ -560,101 +394,20 @@ func Convert_api_Pod_To_v1_Pod(in *api.Pod, out *v1.Pod, s conversion.Scope) err
return err
}
// TODO: sometime after we move init container to stable, remove these conversions
if len(out.Spec.InitContainers) > 0 || len(out.Status.InitContainerStatuses) > 0 {
old := out.Annotations
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
delete(out.Annotations, v1.PodInitContainersAnnotationKey)
delete(out.Annotations, v1.PodInitContainersBetaAnnotationKey)
delete(out.Annotations, v1.PodInitContainerStatusesAnnotationKey)
delete(out.Annotations, v1.PodInitContainerStatusesBetaAnnotationKey)
}
if len(out.Spec.InitContainers) > 0 {
value, err := json.Marshal(out.Spec.InitContainers)
if err != nil {
return err
}
out.Annotations[v1.PodInitContainersAnnotationKey] = string(value)
out.Annotations[v1.PodInitContainersBetaAnnotationKey] = string(value)
}
if len(out.Status.InitContainerStatuses) > 0 {
value, err := json.Marshal(out.Status.InitContainerStatuses)
if err != nil {
return err
}
out.Annotations[v1.PodInitContainerStatusesAnnotationKey] = string(value)
out.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey] = string(value)
}
return nil
}
func Convert_v1_Pod_To_api_Pod(in *v1.Pod, out *api.Pod, s conversion.Scope) error {
// If there is a beta annotation, copy to alpha key.
// See commit log for PR #31026 for why we do this.
if valueBeta, okBeta := in.Annotations[v1.PodInitContainersBetaAnnotationKey]; okBeta {
in.Annotations[v1.PodInitContainersAnnotationKey] = valueBeta
}
// TODO: sometime after we move init container to stable, remove these conversions
// Move the annotation to the internal repr. field
if value, ok := in.Annotations[v1.PodInitContainersAnnotationKey]; ok {
var values []v1.Container
if err := json.Unmarshal([]byte(value), &values); err != nil {
return err
}
// Conversion from external to internal version exists more to
// satisfy the needs of the decoder than it does to be a general
// purpose tool. And Decode always creates an intermediate object
// to decode to. Thus the caller of UnsafeConvertToVersion is
// taking responsibility to ensure mutation of in is not exposed
// back to the caller.
in.Spec.InitContainers = values
// Call defaulters explicitly until annotations are removed
tmpPod := &v1.Pod{
Spec: v1.PodSpec{
HostNetwork: in.Spec.HostNetwork,
InitContainers: values,
},
}
SetObjectDefaults_Pod(tmpPod)
in.Spec.InitContainers = tmpPod.Spec.InitContainers
}
// If there is a beta annotation, copy to alpha key.
// See commit log for PR #31026 for why we do this.
if valueBeta, okBeta := in.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey]; okBeta {
in.Annotations[v1.PodInitContainerStatusesAnnotationKey] = valueBeta
}
if value, ok := in.Annotations[v1.PodInitContainerStatusesAnnotationKey]; ok {
var values []v1.ContainerStatus
if err := json.Unmarshal([]byte(value), &values); err != nil {
return err
}
// Conversion from external to internal version exists more to
// satisfy the needs of the decoder than it does to be a general
// purpose tool. And Decode always creates an intermediate object
// to decode to. Thus the caller of UnsafeConvertToVersion is
// taking responsibility to ensure mutation of in is not exposed
// back to the caller.
in.Status.InitContainerStatuses = values
}
if err := autoConvert_v1_Pod_To_api_Pod(in, out, s); err != nil {
return err
}
// drop init container annotations so they don't take effect on legacy kubelets.
// remove this once the oldest supported kubelet no longer honors the annotations over the field.
if len(out.Annotations) > 0 {
old := out.Annotations
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
delete(out.Annotations, v1.PodInitContainersAnnotationKey)
delete(out.Annotations, v1.PodInitContainersBetaAnnotationKey)
delete(out.Annotations, v1.PodInitContainerStatusesAnnotationKey)
delete(out.Annotations, v1.PodInitContainerStatusesBetaAnnotationKey)
delete(out.Annotations, "pod.beta.kubernetes.io/init-containers")
delete(out.Annotations, "pod.alpha.kubernetes.io/init-containers")
delete(out.Annotations, "pod.beta.kubernetes.io/init-container-statuses")
delete(out.Annotations, "pod.alpha.kubernetes.io/init-container-statuses")
}
return nil
}
@ -675,6 +428,30 @@ func Convert_v1_Secret_To_api_Secret(in *v1.Secret, out *api.Secret, s conversio
return nil
}
func Convert_api_SecurityContext_To_v1_SecurityContext(in *api.SecurityContext, out *v1.SecurityContext, s conversion.Scope) error {
if in.Capabilities != nil {
out.Capabilities = new(v1.Capabilities)
if err := Convert_api_Capabilities_To_v1_Capabilities(in.Capabilities, out.Capabilities, s); err != nil {
return err
}
} else {
out.Capabilities = nil
}
out.Privileged = in.Privileged
if in.SELinuxOptions != nil {
out.SELinuxOptions = new(v1.SELinuxOptions)
if err := Convert_api_SELinuxOptions_To_v1_SELinuxOptions(in.SELinuxOptions, out.SELinuxOptions, s); err != nil {
return err
}
} else {
out.SELinuxOptions = nil
}
out.RunAsUser = in.RunAsUser
out.RunAsNonRoot = in.RunAsNonRoot
out.ReadOnlyRootFilesystem = in.ReadOnlyRootFilesystem
out.AllowPrivilegeEscalation = in.AllowPrivilegeEscalation
return nil
}
func Convert_api_PodSecurityContext_To_v1_PodSecurityContext(in *api.PodSecurityContext, out *v1.PodSecurityContext, s conversion.Scope) error {
out.SupplementalGroups = in.SupplementalGroups

View file

@ -101,6 +101,19 @@ func SetDefaults_Service(obj *v1.Service) {
if obj.Spec.SessionAffinity == "" {
obj.Spec.SessionAffinity = v1.ServiceAffinityNone
}
if obj.Spec.SessionAffinity == v1.ServiceAffinityNone {
obj.Spec.SessionAffinityConfig = nil
}
if obj.Spec.SessionAffinity == v1.ServiceAffinityClientIP {
if obj.Spec.SessionAffinityConfig == nil || obj.Spec.SessionAffinityConfig.ClientIP == nil || obj.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds == nil {
timeoutSeconds := v1.DefaultClientIPServiceAffinitySeconds
obj.Spec.SessionAffinityConfig = &v1.SessionAffinityConfig{
ClientIP: &v1.ClientIPConfig{
TimeoutSeconds: &timeoutSeconds,
},
}
}
}
if obj.Spec.Type == "" {
obj.Spec.Type = v1.ServiceTypeClusterIP
}
@ -115,10 +128,7 @@ func SetDefaults_Service(obj *v1.Service) {
}
// Defaults ExternalTrafficPolicy field for NodePort / LoadBalancer service
// to Global for consistency.
if _, ok := obj.Annotations[v1.BetaAnnotationExternalTraffic]; ok {
// Don't default this field if beta annotation exists.
return
} else if (obj.Spec.Type == v1.ServiceTypeNodePort ||
if (obj.Spec.Type == v1.ServiceTypeNodePort ||
obj.Spec.Type == v1.ServiceTypeLoadBalancer) &&
obj.Spec.ExternalTrafficPolicy == "" {
obj.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster
@ -372,3 +382,10 @@ func SetDefaults_ScaleIOVolumeSource(obj *v1.ScaleIOVolumeSource) {
obj.FSType = "xfs"
}
}
func SetDefaults_HostPathVolumeSource(obj *v1.HostPathVolumeSource) {
typeVol := v1.HostPathUnset
if obj.Type == nil {
obj.Type = &typeVol
}
}

View file

@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
@ -12,7 +10,6 @@ go_test(
name = "go_default_test",
srcs = ["helpers_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
@ -24,12 +21,13 @@ go_test(
go_library(
name = "go_default_library",
srcs = ["helpers.go"],
tags = ["automanaged"],
deps = [
"//pkg/api/helper:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/selection:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)

View file

@ -22,11 +22,53 @@ import (
"strings"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/pkg/api/helper"
)
// IsExtendedResourceName returns true if the resource name is not in the
// default namespace, or it has the opaque integer resource prefix.
func IsExtendedResourceName(name v1.ResourceName) bool {
// TODO: Remove OIR part following deprecation.
return !IsDefaultNamespaceResource(name) || IsOpaqueIntResourceName(name)
}
// IsDefaultNamespaceResource returns true if the resource name is in the
// *kubernetes.io/ namespace. Partially-qualified (unprefixed) names are
// implicitly in the kubernetes.io/ namespace.
func IsDefaultNamespaceResource(name v1.ResourceName) bool {
return !strings.Contains(string(name), "/") ||
strings.Contains(string(name), v1.ResourceDefaultNamespacePrefix)
}
// IsHugePageResourceName returns true if the resource name has the huge page
// resource prefix.
func IsHugePageResourceName(name v1.ResourceName) bool {
return strings.HasPrefix(string(name), v1.ResourceHugePagesPrefix)
}
// HugePageResourceName returns a ResourceName with the canonical hugepage
// prefix prepended for the specified page size. The page size is converted
// to its canonical representation.
func HugePageResourceName(pageSize resource.Quantity) v1.ResourceName {
return v1.ResourceName(fmt.Sprintf("%s%s", v1.ResourceHugePagesPrefix, pageSize.String()))
}
// HugePageSizeFromResourceName returns the page size for the specified huge page
// resource name. If the specified input is not a valid huge page resource name
// an error is returned.
func HugePageSizeFromResourceName(name v1.ResourceName) (resource.Quantity, error) {
if !IsHugePageResourceName(name) {
return resource.Quantity{}, fmt.Errorf("resource name: %s is not valid hugepage name", name)
}
pageSize := strings.TrimPrefix(string(name), v1.ResourceHugePagesPrefix)
return resource.ParseQuantity(pageSize)
}
// IsOpaqueIntResourceName returns true if the resource name has the opaque
// integer resource prefix.
func IsOpaqueIntResourceName(name v1.ResourceName) bool {
@ -43,6 +85,15 @@ func OpaqueIntResourceName(name string) v1.ResourceName {
return v1.ResourceName(fmt.Sprintf("%s%s", v1.ResourceOpaqueIntPrefix, name))
}
var overcommitBlacklist = sets.NewString(string(v1.ResourceNvidiaGPU))
// IsOvercommitAllowed returns true if the resource is in the default
// namespace and not blacklisted.
func IsOvercommitAllowed(name v1.ResourceName) bool {
return IsDefaultNamespaceResource(name) &&
!overcommitBlacklist.Has(string(name))
}
// this function aims to check if the service's ClusterIP is set or not
// the objective is not to perform validation here
func IsServiceIPSet(service *v1.Service) bool {

View file

@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
@ -11,7 +9,6 @@ load(
go_library(
name = "go_default_library",
srcs = ["util.go"],
tags = ["automanaged"],
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
@ -23,7 +20,6 @@ go_test(
name = "go_default_test",
srcs = ["util_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

View file

@ -17,7 +17,6 @@ limitations under the License.
package pod
import (
"encoding/json"
"fmt"
"time"
@ -49,67 +48,6 @@ func FindPort(pod *v1.Pod, svcPort *v1.ServicePort) (int, error) {
return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
}
// TODO: remove this function when init containers becomes a stable feature
func SetInitContainersAndStatuses(pod *v1.Pod) error {
var initContainersAnnotation string
initContainersAnnotation = pod.Annotations[v1.PodInitContainersAnnotationKey]
initContainersAnnotation = pod.Annotations[v1.PodInitContainersBetaAnnotationKey]
if len(initContainersAnnotation) > 0 {
var values []v1.Container
if err := json.Unmarshal([]byte(initContainersAnnotation), &values); err != nil {
return err
}
pod.Spec.InitContainers = values
}
var initContainerStatusesAnnotation string
initContainerStatusesAnnotation = pod.Annotations[v1.PodInitContainerStatusesAnnotationKey]
initContainerStatusesAnnotation = pod.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey]
if len(initContainerStatusesAnnotation) > 0 {
var values []v1.ContainerStatus
if err := json.Unmarshal([]byte(initContainerStatusesAnnotation), &values); err != nil {
return err
}
pod.Status.InitContainerStatuses = values
}
return nil
}
// TODO: remove this function when init containers becomes a stable feature
func SetInitContainersAnnotations(pod *v1.Pod) error {
if len(pod.Spec.InitContainers) > 0 {
value, err := json.Marshal(pod.Spec.InitContainers)
if err != nil {
return err
}
if pod.Annotations == nil {
pod.Annotations = make(map[string]string)
}
pod.Annotations[v1.PodInitContainersAnnotationKey] = string(value)
pod.Annotations[v1.PodInitContainersBetaAnnotationKey] = string(value)
}
return nil
}
// TODO: remove this function when init containers becomes a stable feature
func SetInitContainersStatusesAnnotations(pod *v1.Pod) error {
if len(pod.Status.InitContainerStatuses) > 0 {
value, err := json.Marshal(pod.Status.InitContainerStatuses)
if err != nil {
return err
}
if pod.Annotations == nil {
pod.Annotations = make(map[string]string)
}
pod.Annotations[v1.PodInitContainerStatusesAnnotationKey] = string(value)
pod.Annotations[v1.PodInitContainerStatusesBetaAnnotationKey] = string(value)
} else {
delete(pod.Annotations, v1.PodInitContainerStatusesAnnotationKey)
delete(pod.Annotations, v1.PodInitContainerStatusesBetaAnnotationKey)
}
return nil
}
// Visitor is called with each object name, and returns true if visiting should continue
type Visitor func(name string) (shouldContinue bool)
@ -348,8 +286,8 @@ func UpdatePodCondition(status *v1.PodStatus, condition *v1.PodCondition) bool {
isEqual := condition.Status == oldCondition.Status &&
condition.Reason == oldCondition.Reason &&
condition.Message == oldCondition.Message &&
condition.LastProbeTime.Equal(oldCondition.LastProbeTime) &&
condition.LastTransitionTime.Equal(oldCondition.LastTransitionTime)
condition.LastProbeTime.Equal(&oldCondition.LastProbeTime) &&
condition.LastTransitionTime.Equal(&oldCondition.LastTransitionTime)
status.Conditions[conditionIndex] = *condition
// Return true if one of the fields have changed.

View file

@ -1,7 +1,5 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
@ -11,10 +9,8 @@ load(
go_library(
name = "go_default_library",
srcs = ["util.go"],
tags = ["automanaged"],
deps = [
"//pkg/util/net/sets:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
],
)
@ -23,12 +19,9 @@ go_test(
name = "go_default_test",
srcs = ["util_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/util/net/sets:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
],
)

View file

@ -18,13 +18,10 @@ package service
import (
"fmt"
"strconv"
"strings"
"k8s.io/api/core/v1"
netsets "k8s.io/kubernetes/pkg/util/net/sets"
"github.com/golang/glog"
)
const (
@ -76,25 +73,10 @@ func RequestsOnlyLocalTraffic(service *v1.Service) bool {
service.Spec.Type != v1.ServiceTypeNodePort {
return false
}
// First check the beta annotation and then the first class field. This is so that
// existing Services continue to work till the user decides to transition to the
// first class field.
if l, ok := service.Annotations[v1.BetaAnnotationExternalTraffic]; ok {
switch l {
case v1.AnnotationValueExternalTrafficLocal:
return true
case v1.AnnotationValueExternalTrafficGlobal:
return false
default:
glog.Errorf("Invalid value for annotation %v: %v", v1.BetaAnnotationExternalTraffic, l)
return false
}
}
return service.Spec.ExternalTrafficPolicy == v1.ServiceExternalTrafficPolicyTypeLocal
}
// NeedsHealthCheck Check if service needs health check.
// NeedsHealthCheck checks if service needs health check.
func NeedsHealthCheck(service *v1.Service) bool {
if service.Spec.Type != v1.ServiceTypeLoadBalancer {
return false
@ -102,56 +84,12 @@ func NeedsHealthCheck(service *v1.Service) bool {
return RequestsOnlyLocalTraffic(service)
}
// GetServiceHealthCheckNodePort Return health check node port for service, if one exists
func GetServiceHealthCheckNodePort(service *v1.Service) int32 {
// First check the beta annotation and then the first class field. This is so that
// existing Services continue to work till the user decides to transition to the
// first class field.
if l, ok := service.Annotations[v1.BetaAnnotationHealthCheckNodePort]; ok {
p, err := strconv.Atoi(l)
if err != nil {
glog.Errorf("Failed to parse annotation %v: %v", v1.BetaAnnotationHealthCheckNodePort, err)
return 0
}
return int32(p)
}
return service.Spec.HealthCheckNodePort
}
// ClearExternalTrafficPolicy resets the ExternalTrafficPolicy field.
func ClearExternalTrafficPolicy(service *v1.Service) {
// First check the beta annotation and then the first class field. This is so existing
// Services continue to work till the user decides to transition to the first class field.
if _, ok := service.Annotations[v1.BetaAnnotationExternalTraffic]; ok {
delete(service.Annotations, v1.BetaAnnotationExternalTraffic)
return
}
service.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyType("")
}
// SetServiceHealthCheckNodePort sets the given health check node port on service.
// It does not check whether this service needs healthCheckNodePort.
func SetServiceHealthCheckNodePort(service *v1.Service, hcNodePort int32) {
// First check the beta annotation and then the first class field. This is so that
// existing Services continue to work till the user decides to transition to the
// first class field.
if _, ok := service.Annotations[v1.BetaAnnotationExternalTraffic]; ok {
if hcNodePort == 0 {
delete(service.Annotations, v1.BetaAnnotationHealthCheckNodePort)
} else {
service.Annotations[v1.BetaAnnotationHealthCheckNodePort] = fmt.Sprintf("%d", hcNodePort)
}
return
}
service.Spec.HealthCheckNodePort = hcNodePort
}
// GetServiceHealthCheckPathPort Return the path and nodePort programmed into the Cloud LB Health Check
// GetServiceHealthCheckPathPort returns the path and nodePort programmed into the Cloud LB Health Check
func GetServiceHealthCheckPathPort(service *v1.Service) (string, int32) {
if !NeedsHealthCheck(service) {
return "", 0
}
port := GetServiceHealthCheckNodePort(service)
port := service.Spec.HealthCheckNodePort
if port == 0 {
return "", 0
}

View file

@ -22,6 +22,7 @@ package v1
import (
v1 "k8s.io/api/core/v1"
resource "k8s.io/apimachinery/pkg/api/resource"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
@ -48,16 +49,22 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_api_AvoidPods_To_v1_AvoidPods,
Convert_v1_AzureDiskVolumeSource_To_api_AzureDiskVolumeSource,
Convert_api_AzureDiskVolumeSource_To_v1_AzureDiskVolumeSource,
Convert_v1_AzureFilePersistentVolumeSource_To_api_AzureFilePersistentVolumeSource,
Convert_api_AzureFilePersistentVolumeSource_To_v1_AzureFilePersistentVolumeSource,
Convert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource,
Convert_api_AzureFileVolumeSource_To_v1_AzureFileVolumeSource,
Convert_v1_Binding_To_api_Binding,
Convert_api_Binding_To_v1_Binding,
Convert_v1_Capabilities_To_api_Capabilities,
Convert_api_Capabilities_To_v1_Capabilities,
Convert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource,
Convert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource,
Convert_v1_CephFSVolumeSource_To_api_CephFSVolumeSource,
Convert_api_CephFSVolumeSource_To_v1_CephFSVolumeSource,
Convert_v1_CinderVolumeSource_To_api_CinderVolumeSource,
Convert_api_CinderVolumeSource_To_v1_CinderVolumeSource,
Convert_v1_ClientIPConfig_To_api_ClientIPConfig,
Convert_api_ClientIPConfig_To_v1_ClientIPConfig,
Convert_v1_ComponentCondition_To_api_ComponentCondition,
Convert_api_ComponentCondition_To_v1_ComponentCondition,
Convert_v1_ComponentStatus_To_api_ComponentStatus,
@ -194,6 +201,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_api_NodeAffinity_To_v1_NodeAffinity,
Convert_v1_NodeCondition_To_api_NodeCondition,
Convert_api_NodeCondition_To_v1_NodeCondition,
Convert_v1_NodeConfigSource_To_api_NodeConfigSource,
Convert_api_NodeConfigSource_To_v1_NodeConfigSource,
Convert_v1_NodeDaemonEndpoints_To_api_NodeDaemonEndpoints,
Convert_api_NodeDaemonEndpoints_To_v1_NodeDaemonEndpoints,
Convert_v1_NodeList_To_api_NodeList,
@ -224,6 +233,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_api_PersistentVolume_To_v1_PersistentVolume,
Convert_v1_PersistentVolumeClaim_To_api_PersistentVolumeClaim,
Convert_api_PersistentVolumeClaim_To_v1_PersistentVolumeClaim,
Convert_v1_PersistentVolumeClaimCondition_To_api_PersistentVolumeClaimCondition,
Convert_api_PersistentVolumeClaimCondition_To_v1_PersistentVolumeClaimCondition,
Convert_v1_PersistentVolumeClaimList_To_api_PersistentVolumeClaimList,
Convert_api_PersistentVolumeClaimList_To_v1_PersistentVolumeClaimList,
Convert_v1_PersistentVolumeClaimSpec_To_api_PersistentVolumeClaimSpec,
@ -334,6 +345,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_api_SecretList_To_v1_SecretList,
Convert_v1_SecretProjection_To_api_SecretProjection,
Convert_api_SecretProjection_To_v1_SecretProjection,
Convert_v1_SecretReference_To_api_SecretReference,
Convert_api_SecretReference_To_v1_SecretReference,
Convert_v1_SecretVolumeSource_To_api_SecretVolumeSource,
Convert_api_SecretVolumeSource_To_v1_SecretVolumeSource,
Convert_v1_SecurityContext_To_api_SecurityContext,
@ -356,6 +369,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
Convert_api_ServiceSpec_To_v1_ServiceSpec,
Convert_v1_ServiceStatus_To_api_ServiceStatus,
Convert_api_ServiceStatus_To_v1_ServiceStatus,
Convert_v1_SessionAffinityConfig_To_api_SessionAffinityConfig,
Convert_api_SessionAffinityConfig_To_v1_SessionAffinityConfig,
Convert_v1_StorageOSPersistentVolumeSource_To_api_StorageOSPersistentVolumeSource,
Convert_api_StorageOSPersistentVolumeSource_To_v1_StorageOSPersistentVolumeSource,
Convert_v1_StorageOSVolumeSource_To_api_StorageOSVolumeSource,
@ -505,6 +520,32 @@ func Convert_api_AzureDiskVolumeSource_To_v1_AzureDiskVolumeSource(in *api.Azure
return autoConvert_api_AzureDiskVolumeSource_To_v1_AzureDiskVolumeSource(in, out, s)
}
func autoConvert_v1_AzureFilePersistentVolumeSource_To_api_AzureFilePersistentVolumeSource(in *v1.AzureFilePersistentVolumeSource, out *api.AzureFilePersistentVolumeSource, s conversion.Scope) error {
out.SecretName = in.SecretName
out.ShareName = in.ShareName
out.ReadOnly = in.ReadOnly
out.SecretNamespace = (*string)(unsafe.Pointer(in.SecretNamespace))
return nil
}
// Convert_v1_AzureFilePersistentVolumeSource_To_api_AzureFilePersistentVolumeSource is an autogenerated conversion function.
func Convert_v1_AzureFilePersistentVolumeSource_To_api_AzureFilePersistentVolumeSource(in *v1.AzureFilePersistentVolumeSource, out *api.AzureFilePersistentVolumeSource, s conversion.Scope) error {
return autoConvert_v1_AzureFilePersistentVolumeSource_To_api_AzureFilePersistentVolumeSource(in, out, s)
}
func autoConvert_api_AzureFilePersistentVolumeSource_To_v1_AzureFilePersistentVolumeSource(in *api.AzureFilePersistentVolumeSource, out *v1.AzureFilePersistentVolumeSource, s conversion.Scope) error {
out.SecretName = in.SecretName
out.ShareName = in.ShareName
out.ReadOnly = in.ReadOnly
out.SecretNamespace = (*string)(unsafe.Pointer(in.SecretNamespace))
return nil
}
// Convert_api_AzureFilePersistentVolumeSource_To_v1_AzureFilePersistentVolumeSource is an autogenerated conversion function.
func Convert_api_AzureFilePersistentVolumeSource_To_v1_AzureFilePersistentVolumeSource(in *api.AzureFilePersistentVolumeSource, out *v1.AzureFilePersistentVolumeSource, s conversion.Scope) error {
return autoConvert_api_AzureFilePersistentVolumeSource_To_v1_AzureFilePersistentVolumeSource(in, out, s)
}
func autoConvert_v1_AzureFileVolumeSource_To_api_AzureFileVolumeSource(in *v1.AzureFileVolumeSource, out *api.AzureFileVolumeSource, s conversion.Scope) error {
out.SecretName = in.SecretName
out.ShareName = in.ShareName
@ -577,6 +618,36 @@ func Convert_api_Capabilities_To_v1_Capabilities(in *api.Capabilities, out *v1.C
return autoConvert_api_Capabilities_To_v1_Capabilities(in, out, s)
}
func autoConvert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource(in *v1.CephFSPersistentVolumeSource, out *api.CephFSPersistentVolumeSource, s conversion.Scope) error {
out.Monitors = *(*[]string)(unsafe.Pointer(&in.Monitors))
out.Path = in.Path
out.User = in.User
out.SecretFile = in.SecretFile
out.SecretRef = (*api.SecretReference)(unsafe.Pointer(in.SecretRef))
out.ReadOnly = in.ReadOnly
return nil
}
// Convert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource is an autogenerated conversion function.
func Convert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource(in *v1.CephFSPersistentVolumeSource, out *api.CephFSPersistentVolumeSource, s conversion.Scope) error {
return autoConvert_v1_CephFSPersistentVolumeSource_To_api_CephFSPersistentVolumeSource(in, out, s)
}
func autoConvert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource(in *api.CephFSPersistentVolumeSource, out *v1.CephFSPersistentVolumeSource, s conversion.Scope) error {
out.Monitors = *(*[]string)(unsafe.Pointer(&in.Monitors))
out.Path = in.Path
out.User = in.User
out.SecretFile = in.SecretFile
out.SecretRef = (*v1.SecretReference)(unsafe.Pointer(in.SecretRef))
out.ReadOnly = in.ReadOnly
return nil
}
// Convert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource is an autogenerated conversion function.
func Convert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource(in *api.CephFSPersistentVolumeSource, out *v1.CephFSPersistentVolumeSource, s conversion.Scope) error {
return autoConvert_api_CephFSPersistentVolumeSource_To_v1_CephFSPersistentVolumeSource(in, out, s)
}
func autoConvert_v1_CephFSVolumeSource_To_api_CephFSVolumeSource(in *v1.CephFSVolumeSource, out *api.CephFSVolumeSource, s conversion.Scope) error {
out.Monitors = *(*[]string)(unsafe.Pointer(&in.Monitors))
out.Path = in.Path
@ -593,11 +664,7 @@ func Convert_v1_CephFSVolumeSource_To_api_CephFSVolumeSource(in *v1.CephFSVolume
}
func autoConvert_api_CephFSVolumeSource_To_v1_CephFSVolumeSource(in *api.CephFSVolumeSource, out *v1.CephFSVolumeSource, s conversion.Scope) error {
if in.Monitors == nil {
out.Monitors = make([]string, 0)
} else {
out.Monitors = *(*[]string)(unsafe.Pointer(&in.Monitors))
}
out.Monitors = *(*[]string)(unsafe.Pointer(&in.Monitors))
out.Path = in.Path
out.User = in.User
out.SecretFile = in.SecretFile
@ -635,6 +702,26 @@ func Convert_api_CinderVolumeSource_To_v1_CinderVolumeSource(in *api.CinderVolum
return autoConvert_api_CinderVolumeSource_To_v1_CinderVolumeSource(in, out, s)
}
func autoConvert_v1_ClientIPConfig_To_api_ClientIPConfig(in *v1.ClientIPConfig, out *api.ClientIPConfig, s conversion.Scope) error {
out.TimeoutSeconds = (*int32)(unsafe.Pointer(in.TimeoutSeconds))
return nil
}
// Convert_v1_ClientIPConfig_To_api_ClientIPConfig is an autogenerated conversion function.
func Convert_v1_ClientIPConfig_To_api_ClientIPConfig(in *v1.ClientIPConfig, out *api.ClientIPConfig, s conversion.Scope) error {
return autoConvert_v1_ClientIPConfig_To_api_ClientIPConfig(in, out, s)
}
func autoConvert_api_ClientIPConfig_To_v1_ClientIPConfig(in *api.ClientIPConfig, out *v1.ClientIPConfig, s conversion.Scope) error {
out.TimeoutSeconds = (*int32)(unsafe.Pointer(in.TimeoutSeconds))
return nil
}
// Convert_api_ClientIPConfig_To_v1_ClientIPConfig is an autogenerated conversion function.
func Convert_api_ClientIPConfig_To_v1_ClientIPConfig(in *api.ClientIPConfig, out *v1.ClientIPConfig, s conversion.Scope) error {
return autoConvert_api_ClientIPConfig_To_v1_ClientIPConfig(in, out, s)
}
func autoConvert_v1_ComponentCondition_To_api_ComponentCondition(in *v1.ComponentCondition, out *api.ComponentCondition, s conversion.Scope) error {
out.Type = api.ComponentConditionType(in.Type)
out.Status = api.ConditionStatus(in.Status)
@ -696,11 +783,7 @@ func Convert_v1_ComponentStatusList_To_api_ComponentStatusList(in *v1.ComponentS
func autoConvert_api_ComponentStatusList_To_v1_ComponentStatusList(in *api.ComponentStatusList, out *v1.ComponentStatusList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.ComponentStatus, 0)
} else {
out.Items = *(*[]v1.ComponentStatus)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.ComponentStatus)(unsafe.Pointer(&in.Items))
return nil
}
@ -798,11 +881,7 @@ func Convert_v1_ConfigMapList_To_api_ConfigMapList(in *v1.ConfigMapList, out *ap
func autoConvert_api_ConfigMapList_To_v1_ConfigMapList(in *api.ConfigMapList, out *v1.ConfigMapList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.ConfigMap, 0)
} else {
out.Items = *(*[]v1.ConfigMap)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.ConfigMap)(unsafe.Pointer(&in.Items))
return nil
}
@ -888,7 +967,15 @@ func autoConvert_v1_Container_To_api_Container(in *v1.Container, out *api.Contai
out.TerminationMessagePath = in.TerminationMessagePath
out.TerminationMessagePolicy = api.TerminationMessagePolicy(in.TerminationMessagePolicy)
out.ImagePullPolicy = api.PullPolicy(in.ImagePullPolicy)
out.SecurityContext = (*api.SecurityContext)(unsafe.Pointer(in.SecurityContext))
if in.SecurityContext != nil {
in, out := &in.SecurityContext, &out.SecurityContext
*out = new(api.SecurityContext)
if err := Convert_v1_SecurityContext_To_api_SecurityContext(*in, *out, s); err != nil {
return err
}
} else {
out.SecurityContext = nil
}
out.Stdin = in.Stdin
out.StdinOnce = in.StdinOnce
out.TTY = in.TTY
@ -919,7 +1006,15 @@ func autoConvert_api_Container_To_v1_Container(in *api.Container, out *v1.Contai
out.TerminationMessagePath = in.TerminationMessagePath
out.TerminationMessagePolicy = v1.TerminationMessagePolicy(in.TerminationMessagePolicy)
out.ImagePullPolicy = v1.PullPolicy(in.ImagePullPolicy)
out.SecurityContext = (*v1.SecurityContext)(unsafe.Pointer(in.SecurityContext))
if in.SecurityContext != nil {
in, out := &in.SecurityContext, &out.SecurityContext
*out = new(v1.SecurityContext)
if err := Convert_api_SecurityContext_To_v1_SecurityContext(*in, *out, s); err != nil {
return err
}
} else {
out.SecurityContext = nil
}
out.Stdin = in.Stdin
out.StdinOnce = in.StdinOnce
out.TTY = in.TTY
@ -943,11 +1038,7 @@ func Convert_v1_ContainerImage_To_api_ContainerImage(in *v1.ContainerImage, out
}
func autoConvert_api_ContainerImage_To_v1_ContainerImage(in *api.ContainerImage, out *v1.ContainerImage, s conversion.Scope) error {
if in.Names == nil {
out.Names = make([]string, 0)
} else {
out.Names = *(*[]string)(unsafe.Pointer(&in.Names))
}
out.Names = *(*[]string)(unsafe.Pointer(&in.Names))
out.SizeBytes = in.SizeBytes
return nil
}
@ -1241,7 +1332,7 @@ func Convert_api_DownwardAPIVolumeSource_To_v1_DownwardAPIVolumeSource(in *api.D
func autoConvert_v1_EmptyDirVolumeSource_To_api_EmptyDirVolumeSource(in *v1.EmptyDirVolumeSource, out *api.EmptyDirVolumeSource, s conversion.Scope) error {
out.Medium = api.StorageMedium(in.Medium)
out.SizeLimit = in.SizeLimit
out.SizeLimit = (*resource.Quantity)(unsafe.Pointer(in.SizeLimit))
return nil
}
@ -1252,7 +1343,7 @@ func Convert_v1_EmptyDirVolumeSource_To_api_EmptyDirVolumeSource(in *v1.EmptyDir
func autoConvert_api_EmptyDirVolumeSource_To_v1_EmptyDirVolumeSource(in *api.EmptyDirVolumeSource, out *v1.EmptyDirVolumeSource, s conversion.Scope) error {
out.Medium = v1.StorageMedium(in.Medium)
out.SizeLimit = in.SizeLimit
out.SizeLimit = (*resource.Quantity)(unsafe.Pointer(in.SizeLimit))
return nil
}
@ -1348,11 +1439,7 @@ func Convert_v1_Endpoints_To_api_Endpoints(in *v1.Endpoints, out *api.Endpoints,
func autoConvert_api_Endpoints_To_v1_Endpoints(in *api.Endpoints, out *v1.Endpoints, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if in.Subsets == nil {
out.Subsets = make([]v1.EndpointSubset, 0)
} else {
out.Subsets = *(*[]v1.EndpointSubset)(unsafe.Pointer(&in.Subsets))
}
out.Subsets = *(*[]v1.EndpointSubset)(unsafe.Pointer(&in.Subsets))
return nil
}
@ -1374,11 +1461,7 @@ func Convert_v1_EndpointsList_To_api_EndpointsList(in *v1.EndpointsList, out *ap
func autoConvert_api_EndpointsList_To_v1_EndpointsList(in *api.EndpointsList, out *v1.EndpointsList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.Endpoints, 0)
} else {
out.Items = *(*[]v1.Endpoints)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.Endpoints)(unsafe.Pointer(&in.Items))
return nil
}
@ -1518,11 +1601,7 @@ func Convert_v1_EventList_To_api_EventList(in *v1.EventList, out *api.EventList,
func autoConvert_api_EventList_To_v1_EventList(in *api.EventList, out *v1.EventList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.Event, 0)
} else {
out.Items = *(*[]v1.Event)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.Event)(unsafe.Pointer(&in.Items))
return nil
}
@ -1578,6 +1657,7 @@ func autoConvert_v1_FCVolumeSource_To_api_FCVolumeSource(in *v1.FCVolumeSource,
out.Lun = (*int32)(unsafe.Pointer(in.Lun))
out.FSType = in.FSType
out.ReadOnly = in.ReadOnly
out.WWIDs = *(*[]string)(unsafe.Pointer(&in.WWIDs))
return nil
}
@ -1587,14 +1667,11 @@ func Convert_v1_FCVolumeSource_To_api_FCVolumeSource(in *v1.FCVolumeSource, out
}
func autoConvert_api_FCVolumeSource_To_v1_FCVolumeSource(in *api.FCVolumeSource, out *v1.FCVolumeSource, s conversion.Scope) error {
if in.TargetWWNs == nil {
out.TargetWWNs = make([]string, 0)
} else {
out.TargetWWNs = *(*[]string)(unsafe.Pointer(&in.TargetWWNs))
}
out.TargetWWNs = *(*[]string)(unsafe.Pointer(&in.TargetWWNs))
out.Lun = (*int32)(unsafe.Pointer(in.Lun))
out.FSType = in.FSType
out.ReadOnly = in.ReadOnly
out.WWIDs = *(*[]string)(unsafe.Pointer(&in.WWIDs))
return nil
}
@ -1825,6 +1902,7 @@ func Convert_api_HostAlias_To_v1_HostAlias(in *api.HostAlias, out *v1.HostAlias,
func autoConvert_v1_HostPathVolumeSource_To_api_HostPathVolumeSource(in *v1.HostPathVolumeSource, out *api.HostPathVolumeSource, s conversion.Scope) error {
out.Path = in.Path
out.Type = (*api.HostPathType)(unsafe.Pointer(in.Type))
return nil
}
@ -1835,6 +1913,7 @@ func Convert_v1_HostPathVolumeSource_To_api_HostPathVolumeSource(in *v1.HostPath
func autoConvert_api_HostPathVolumeSource_To_v1_HostPathVolumeSource(in *api.HostPathVolumeSource, out *v1.HostPathVolumeSource, s conversion.Scope) error {
out.Path = in.Path
out.Type = (*v1.HostPathType)(unsafe.Pointer(in.Type))
return nil
}
@ -1854,6 +1933,7 @@ func autoConvert_v1_ISCSIVolumeSource_To_api_ISCSIVolumeSource(in *v1.ISCSIVolum
out.DiscoveryCHAPAuth = in.DiscoveryCHAPAuth
out.SessionCHAPAuth = in.SessionCHAPAuth
out.SecretRef = (*api.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
out.InitiatorName = (*string)(unsafe.Pointer(in.InitiatorName))
return nil
}
@ -1873,6 +1953,7 @@ func autoConvert_api_ISCSIVolumeSource_To_v1_ISCSIVolumeSource(in *api.ISCSIVolu
out.DiscoveryCHAPAuth = in.DiscoveryCHAPAuth
out.SessionCHAPAuth = in.SessionCHAPAuth
out.SecretRef = (*v1.LocalObjectReference)(unsafe.Pointer(in.SecretRef))
out.InitiatorName = (*string)(unsafe.Pointer(in.InitiatorName))
return nil
}
@ -1996,11 +2077,7 @@ func Convert_v1_LimitRangeList_To_api_LimitRangeList(in *v1.LimitRangeList, out
func autoConvert_api_LimitRangeList_To_v1_LimitRangeList(in *api.LimitRangeList, out *v1.LimitRangeList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.LimitRange, 0)
} else {
out.Items = *(*[]v1.LimitRange)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.LimitRange)(unsafe.Pointer(&in.Items))
return nil
}
@ -2020,11 +2097,7 @@ func Convert_v1_LimitRangeSpec_To_api_LimitRangeSpec(in *v1.LimitRangeSpec, out
}
func autoConvert_api_LimitRangeSpec_To_v1_LimitRangeSpec(in *api.LimitRangeSpec, out *v1.LimitRangeSpec, s conversion.Scope) error {
if in.Limits == nil {
out.Limits = make([]v1.LimitRangeItem, 0)
} else {
out.Limits = *(*[]v1.LimitRangeItem)(unsafe.Pointer(&in.Limits))
}
out.Limits = *(*[]v1.LimitRangeItem)(unsafe.Pointer(&in.Limits))
return nil
}
@ -2065,7 +2138,7 @@ func autoConvert_api_List_To_v1_List(in *api.List, out *v1.List, s conversion.Sc
}
}
} else {
out.Items = make([]runtime.RawExtension, 0)
out.Items = nil
}
return nil
}
@ -2264,11 +2337,7 @@ func Convert_v1_NamespaceList_To_api_NamespaceList(in *v1.NamespaceList, out *ap
func autoConvert_api_NamespaceList_To_v1_NamespaceList(in *api.NamespaceList, out *v1.NamespaceList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.Namespace, 0)
} else {
out.Items = *(*[]v1.Namespace)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.Namespace)(unsafe.Pointer(&in.Items))
return nil
}
@ -2423,6 +2492,26 @@ func Convert_api_NodeCondition_To_v1_NodeCondition(in *api.NodeCondition, out *v
return autoConvert_api_NodeCondition_To_v1_NodeCondition(in, out, s)
}
func autoConvert_v1_NodeConfigSource_To_api_NodeConfigSource(in *v1.NodeConfigSource, out *api.NodeConfigSource, s conversion.Scope) error {
out.ConfigMapRef = (*api.ObjectReference)(unsafe.Pointer(in.ConfigMapRef))
return nil
}
// Convert_v1_NodeConfigSource_To_api_NodeConfigSource is an autogenerated conversion function.
func Convert_v1_NodeConfigSource_To_api_NodeConfigSource(in *v1.NodeConfigSource, out *api.NodeConfigSource, s conversion.Scope) error {
return autoConvert_v1_NodeConfigSource_To_api_NodeConfigSource(in, out, s)
}
func autoConvert_api_NodeConfigSource_To_v1_NodeConfigSource(in *api.NodeConfigSource, out *v1.NodeConfigSource, s conversion.Scope) error {
out.ConfigMapRef = (*v1.ObjectReference)(unsafe.Pointer(in.ConfigMapRef))
return nil
}
// Convert_api_NodeConfigSource_To_v1_NodeConfigSource is an autogenerated conversion function.
func Convert_api_NodeConfigSource_To_v1_NodeConfigSource(in *api.NodeConfigSource, out *v1.NodeConfigSource, s conversion.Scope) error {
return autoConvert_api_NodeConfigSource_To_v1_NodeConfigSource(in, out, s)
}
func autoConvert_v1_NodeDaemonEndpoints_To_api_NodeDaemonEndpoints(in *v1.NodeDaemonEndpoints, out *api.NodeDaemonEndpoints, s conversion.Scope) error {
if err := Convert_v1_DaemonEndpoint_To_api_DaemonEndpoint(&in.KubeletEndpoint, &out.KubeletEndpoint, s); err != nil {
return err
@ -2460,11 +2549,7 @@ func Convert_v1_NodeList_To_api_NodeList(in *v1.NodeList, out *api.NodeList, s c
func autoConvert_api_NodeList_To_v1_NodeList(in *api.NodeList, out *v1.NodeList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.Node, 0)
} else {
out.Items = *(*[]v1.Node)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.Node)(unsafe.Pointer(&in.Items))
return nil
}
@ -2524,11 +2609,7 @@ func Convert_v1_NodeSelector_To_api_NodeSelector(in *v1.NodeSelector, out *api.N
}
func autoConvert_api_NodeSelector_To_v1_NodeSelector(in *api.NodeSelector, out *v1.NodeSelector, s conversion.Scope) error {
if in.NodeSelectorTerms == nil {
out.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 0)
} else {
out.NodeSelectorTerms = *(*[]v1.NodeSelectorTerm)(unsafe.Pointer(&in.NodeSelectorTerms))
}
out.NodeSelectorTerms = *(*[]v1.NodeSelectorTerm)(unsafe.Pointer(&in.NodeSelectorTerms))
return nil
}
@ -2572,11 +2653,7 @@ func Convert_v1_NodeSelectorTerm_To_api_NodeSelectorTerm(in *v1.NodeSelectorTerm
}
func autoConvert_api_NodeSelectorTerm_To_v1_NodeSelectorTerm(in *api.NodeSelectorTerm, out *v1.NodeSelectorTerm, s conversion.Scope) error {
if in.MatchExpressions == nil {
out.MatchExpressions = make([]v1.NodeSelectorRequirement, 0)
} else {
out.MatchExpressions = *(*[]v1.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions))
}
out.MatchExpressions = *(*[]v1.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions))
return nil
}
@ -2591,6 +2668,7 @@ func autoConvert_v1_NodeSpec_To_api_NodeSpec(in *v1.NodeSpec, out *api.NodeSpec,
out.ProviderID = in.ProviderID
out.Unschedulable = in.Unschedulable
out.Taints = *(*[]api.Taint)(unsafe.Pointer(&in.Taints))
out.ConfigSource = (*api.NodeConfigSource)(unsafe.Pointer(in.ConfigSource))
return nil
}
@ -2605,6 +2683,7 @@ func autoConvert_api_NodeSpec_To_v1_NodeSpec(in *api.NodeSpec, out *v1.NodeSpec,
out.ProviderID = in.ProviderID
out.Unschedulable = in.Unschedulable
out.Taints = *(*[]v1.Taint)(unsafe.Pointer(&in.Taints))
out.ConfigSource = (*v1.NodeConfigSource)(unsafe.Pointer(in.ConfigSource))
return nil
}
@ -2865,6 +2944,36 @@ func Convert_api_PersistentVolumeClaim_To_v1_PersistentVolumeClaim(in *api.Persi
return autoConvert_api_PersistentVolumeClaim_To_v1_PersistentVolumeClaim(in, out, s)
}
func autoConvert_v1_PersistentVolumeClaimCondition_To_api_PersistentVolumeClaimCondition(in *v1.PersistentVolumeClaimCondition, out *api.PersistentVolumeClaimCondition, s conversion.Scope) error {
out.Type = api.PersistentVolumeClaimConditionType(in.Type)
out.Status = api.ConditionStatus(in.Status)
out.LastProbeTime = in.LastProbeTime
out.LastTransitionTime = in.LastTransitionTime
out.Reason = in.Reason
out.Message = in.Message
return nil
}
// Convert_v1_PersistentVolumeClaimCondition_To_api_PersistentVolumeClaimCondition is an autogenerated conversion function.
func Convert_v1_PersistentVolumeClaimCondition_To_api_PersistentVolumeClaimCondition(in *v1.PersistentVolumeClaimCondition, out *api.PersistentVolumeClaimCondition, s conversion.Scope) error {
return autoConvert_v1_PersistentVolumeClaimCondition_To_api_PersistentVolumeClaimCondition(in, out, s)
}
func autoConvert_api_PersistentVolumeClaimCondition_To_v1_PersistentVolumeClaimCondition(in *api.PersistentVolumeClaimCondition, out *v1.PersistentVolumeClaimCondition, s conversion.Scope) error {
out.Type = v1.PersistentVolumeClaimConditionType(in.Type)
out.Status = v1.ConditionStatus(in.Status)
out.LastProbeTime = in.LastProbeTime
out.LastTransitionTime = in.LastTransitionTime
out.Reason = in.Reason
out.Message = in.Message
return nil
}
// Convert_api_PersistentVolumeClaimCondition_To_v1_PersistentVolumeClaimCondition is an autogenerated conversion function.
func Convert_api_PersistentVolumeClaimCondition_To_v1_PersistentVolumeClaimCondition(in *api.PersistentVolumeClaimCondition, out *v1.PersistentVolumeClaimCondition, s conversion.Scope) error {
return autoConvert_api_PersistentVolumeClaimCondition_To_v1_PersistentVolumeClaimCondition(in, out, s)
}
func autoConvert_v1_PersistentVolumeClaimList_To_api_PersistentVolumeClaimList(in *v1.PersistentVolumeClaimList, out *api.PersistentVolumeClaimList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]api.PersistentVolumeClaim)(unsafe.Pointer(&in.Items))
@ -2878,11 +2987,7 @@ func Convert_v1_PersistentVolumeClaimList_To_api_PersistentVolumeClaimList(in *v
func autoConvert_api_PersistentVolumeClaimList_To_v1_PersistentVolumeClaimList(in *api.PersistentVolumeClaimList, out *v1.PersistentVolumeClaimList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.PersistentVolumeClaim, 0)
} else {
out.Items = *(*[]v1.PersistentVolumeClaim)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.PersistentVolumeClaim)(unsafe.Pointer(&in.Items))
return nil
}
@ -2927,6 +3032,7 @@ func autoConvert_v1_PersistentVolumeClaimStatus_To_api_PersistentVolumeClaimStat
out.Phase = api.PersistentVolumeClaimPhase(in.Phase)
out.AccessModes = *(*[]api.PersistentVolumeAccessMode)(unsafe.Pointer(&in.AccessModes))
out.Capacity = *(*api.ResourceList)(unsafe.Pointer(&in.Capacity))
out.Conditions = *(*[]api.PersistentVolumeClaimCondition)(unsafe.Pointer(&in.Conditions))
return nil
}
@ -2939,6 +3045,7 @@ func autoConvert_api_PersistentVolumeClaimStatus_To_v1_PersistentVolumeClaimStat
out.Phase = v1.PersistentVolumeClaimPhase(in.Phase)
out.AccessModes = *(*[]v1.PersistentVolumeAccessMode)(unsafe.Pointer(&in.AccessModes))
out.Capacity = *(*v1.ResourceList)(unsafe.Pointer(&in.Capacity))
out.Conditions = *(*[]v1.PersistentVolumeClaimCondition)(unsafe.Pointer(&in.Conditions))
return nil
}
@ -3001,7 +3108,7 @@ func autoConvert_api_PersistentVolumeList_To_v1_PersistentVolumeList(in *api.Per
}
}
} else {
out.Items = make([]v1.PersistentVolume, 0)
out.Items = nil
}
return nil
}
@ -3020,11 +3127,11 @@ func autoConvert_v1_PersistentVolumeSource_To_api_PersistentVolumeSource(in *v1.
out.RBD = (*api.RBDVolumeSource)(unsafe.Pointer(in.RBD))
out.ISCSI = (*api.ISCSIVolumeSource)(unsafe.Pointer(in.ISCSI))
out.Cinder = (*api.CinderVolumeSource)(unsafe.Pointer(in.Cinder))
out.CephFS = (*api.CephFSVolumeSource)(unsafe.Pointer(in.CephFS))
out.CephFS = (*api.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS))
out.FC = (*api.FCVolumeSource)(unsafe.Pointer(in.FC))
out.Flocker = (*api.FlockerVolumeSource)(unsafe.Pointer(in.Flocker))
out.FlexVolume = (*api.FlexVolumeSource)(unsafe.Pointer(in.FlexVolume))
out.AzureFile = (*api.AzureFileVolumeSource)(unsafe.Pointer(in.AzureFile))
out.AzureFile = (*api.AzureFilePersistentVolumeSource)(unsafe.Pointer(in.AzureFile))
out.VsphereVolume = (*api.VsphereVirtualDiskVolumeSource)(unsafe.Pointer(in.VsphereVolume))
out.Quobyte = (*api.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte))
out.AzureDisk = (*api.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
@ -3052,10 +3159,10 @@ func autoConvert_api_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *api
out.ISCSI = (*v1.ISCSIVolumeSource)(unsafe.Pointer(in.ISCSI))
out.FlexVolume = (*v1.FlexVolumeSource)(unsafe.Pointer(in.FlexVolume))
out.Cinder = (*v1.CinderVolumeSource)(unsafe.Pointer(in.Cinder))
out.CephFS = (*v1.CephFSVolumeSource)(unsafe.Pointer(in.CephFS))
out.CephFS = (*v1.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS))
out.FC = (*v1.FCVolumeSource)(unsafe.Pointer(in.FC))
out.Flocker = (*v1.FlockerVolumeSource)(unsafe.Pointer(in.Flocker))
out.AzureFile = (*v1.AzureFileVolumeSource)(unsafe.Pointer(in.AzureFile))
out.AzureFile = (*v1.AzureFilePersistentVolumeSource)(unsafe.Pointer(in.AzureFile))
out.VsphereVolume = (*v1.VsphereVirtualDiskVolumeSource)(unsafe.Pointer(in.VsphereVolume))
out.AzureDisk = (*v1.AzureDiskVolumeSource)(unsafe.Pointer(in.AzureDisk))
out.PhotonPersistentDisk = (*v1.PhotonPersistentDiskVolumeSource)(unsafe.Pointer(in.PhotonPersistentDisk))
@ -3080,6 +3187,7 @@ func autoConvert_v1_PersistentVolumeSpec_To_api_PersistentVolumeSpec(in *v1.Pers
out.ClaimRef = (*api.ObjectReference)(unsafe.Pointer(in.ClaimRef))
out.PersistentVolumeReclaimPolicy = api.PersistentVolumeReclaimPolicy(in.PersistentVolumeReclaimPolicy)
out.StorageClassName = in.StorageClassName
out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions))
return nil
}
@ -3097,6 +3205,7 @@ func autoConvert_api_PersistentVolumeSpec_To_v1_PersistentVolumeSpec(in *api.Per
out.ClaimRef = (*v1.ObjectReference)(unsafe.Pointer(in.ClaimRef))
out.PersistentVolumeReclaimPolicy = v1.PersistentVolumeReclaimPolicy(in.PersistentVolumeReclaimPolicy)
out.StorageClassName = in.StorageClassName
out.MountOptions = *(*[]string)(unsafe.Pointer(&in.MountOptions))
return nil
}
@ -3162,6 +3271,11 @@ func autoConvert_v1_Pod_To_api_Pod(in *v1.Pod, out *api.Pod, s conversion.Scope)
return nil
}
// Convert_v1_Pod_To_api_Pod is an autogenerated conversion function.
func Convert_v1_Pod_To_api_Pod(in *v1.Pod, out *api.Pod, s conversion.Scope) error {
return autoConvert_v1_Pod_To_api_Pod(in, out, s)
}
func autoConvert_api_Pod_To_v1_Pod(in *api.Pod, out *v1.Pod, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_api_PodSpec_To_v1_PodSpec(&in.Spec, &out.Spec, s); err != nil {
@ -3320,11 +3434,7 @@ func autoConvert_api_PodExecOptions_To_v1_PodExecOptions(in *api.PodExecOptions,
out.Stderr = in.Stderr
out.TTY = in.TTY
out.Container = in.Container
if in.Command == nil {
out.Command = make([]string, 0)
} else {
out.Command = *(*[]string)(unsafe.Pointer(&in.Command))
}
out.Command = *(*[]string)(unsafe.Pointer(&in.Command))
return nil
}
@ -3365,7 +3475,7 @@ func autoConvert_api_PodList_To_v1_PodList(in *api.PodList, out *v1.PodList, s c
}
}
} else {
out.Items = make([]v1.Pod, 0)
out.Items = nil
}
return nil
}
@ -3502,8 +3612,28 @@ func autoConvert_v1_PodSpec_To_api_PodSpec(in *v1.PodSpec, out *api.PodSpec, s c
} else {
out.Volumes = nil
}
out.InitContainers = *(*[]api.Container)(unsafe.Pointer(&in.InitContainers))
out.Containers = *(*[]api.Container)(unsafe.Pointer(&in.Containers))
if in.InitContainers != nil {
in, out := &in.InitContainers, &out.InitContainers
*out = make([]api.Container, len(*in))
for i := range *in {
if err := Convert_v1_Container_To_api_Container(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.InitContainers = nil
}
if in.Containers != nil {
in, out := &in.Containers, &out.Containers
*out = make([]api.Container, len(*in))
for i := range *in {
if err := Convert_v1_Container_To_api_Container(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Containers = nil
}
out.RestartPolicy = api.RestartPolicy(in.RestartPolicy)
out.TerminationGracePeriodSeconds = (*int64)(unsafe.Pointer(in.TerminationGracePeriodSeconds))
out.ActiveDeadlineSeconds = (*int64)(unsafe.Pointer(in.ActiveDeadlineSeconds))
@ -3549,11 +3679,27 @@ func autoConvert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *v1.PodSpec, s c
} else {
out.Volumes = nil
}
out.InitContainers = *(*[]v1.Container)(unsafe.Pointer(&in.InitContainers))
if in.Containers == nil {
out.Containers = make([]v1.Container, 0)
if in.InitContainers != nil {
in, out := &in.InitContainers, &out.InitContainers
*out = make([]v1.Container, len(*in))
for i := range *in {
if err := Convert_api_Container_To_v1_Container(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Containers = *(*[]v1.Container)(unsafe.Pointer(&in.Containers))
out.InitContainers = nil
}
if in.Containers != nil {
in, out := &in.Containers, &out.Containers
*out = make([]v1.Container, len(*in))
for i := range *in {
if err := Convert_api_Container_To_v1_Container(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Containers = nil
}
out.RestartPolicy = v1.RestartPolicy(in.RestartPolicy)
out.TerminationGracePeriodSeconds = (*int64)(unsafe.Pointer(in.TerminationGracePeriodSeconds))
@ -3630,6 +3776,11 @@ func autoConvert_v1_PodStatusResult_To_api_PodStatusResult(in *v1.PodStatusResul
return nil
}
// Convert_v1_PodStatusResult_To_api_PodStatusResult is an autogenerated conversion function.
func Convert_v1_PodStatusResult_To_api_PodStatusResult(in *v1.PodStatusResult, out *api.PodStatusResult, s conversion.Scope) error {
return autoConvert_v1_PodStatusResult_To_api_PodStatusResult(in, out, s)
}
func autoConvert_api_PodStatusResult_To_v1_PodStatusResult(in *api.PodStatusResult, out *v1.PodStatusResult, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_api_PodStatus_To_v1_PodStatus(&in.Status, &out.Status, s); err != nil {
@ -3638,6 +3789,11 @@ func autoConvert_api_PodStatusResult_To_v1_PodStatusResult(in *api.PodStatusResu
return nil
}
// Convert_api_PodStatusResult_To_v1_PodStatusResult is an autogenerated conversion function.
func Convert_api_PodStatusResult_To_v1_PodStatusResult(in *api.PodStatusResult, out *v1.PodStatusResult, s conversion.Scope) error {
return autoConvert_api_PodStatusResult_To_v1_PodStatusResult(in, out, s)
}
func autoConvert_v1_PodTemplate_To_api_PodTemplate(in *v1.PodTemplate, out *api.PodTemplate, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(&in.Template, &out.Template, s); err != nil {
@ -3696,7 +3852,7 @@ func autoConvert_api_PodTemplateList_To_v1_PodTemplateList(in *api.PodTemplateLi
}
}
} else {
out.Items = make([]v1.PodTemplate, 0)
out.Items = nil
}
return nil
}
@ -3868,11 +4024,7 @@ func Convert_v1_ProjectedVolumeSource_To_api_ProjectedVolumeSource(in *v1.Projec
}
func autoConvert_api_ProjectedVolumeSource_To_v1_ProjectedVolumeSource(in *api.ProjectedVolumeSource, out *v1.ProjectedVolumeSource, s conversion.Scope) error {
if in.Sources == nil {
out.Sources = make([]v1.VolumeProjection, 0)
} else {
out.Sources = *(*[]v1.VolumeProjection)(unsafe.Pointer(&in.Sources))
}
out.Sources = *(*[]v1.VolumeProjection)(unsafe.Pointer(&in.Sources))
out.DefaultMode = (*int32)(unsafe.Pointer(in.DefaultMode))
return nil
}
@ -3928,11 +4080,7 @@ func Convert_v1_RBDVolumeSource_To_api_RBDVolumeSource(in *v1.RBDVolumeSource, o
}
func autoConvert_api_RBDVolumeSource_To_v1_RBDVolumeSource(in *api.RBDVolumeSource, out *v1.RBDVolumeSource, s conversion.Scope) error {
if in.CephMonitors == nil {
out.CephMonitors = make([]string, 0)
} else {
out.CephMonitors = *(*[]string)(unsafe.Pointer(&in.CephMonitors))
}
out.CephMonitors = *(*[]string)(unsafe.Pointer(&in.CephMonitors))
out.RBDImage = in.RBDImage
out.FSType = in.FSType
out.RBDPool = in.RBDPool
@ -3963,11 +4111,7 @@ func Convert_v1_RangeAllocation_To_api_RangeAllocation(in *v1.RangeAllocation, o
func autoConvert_api_RangeAllocation_To_v1_RangeAllocation(in *api.RangeAllocation, out *v1.RangeAllocation, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
out.Range = in.Range
if in.Data == nil {
out.Data = make([]byte, 0)
} else {
out.Data = *(*[]byte)(unsafe.Pointer(&in.Data))
}
out.Data = *(*[]byte)(unsafe.Pointer(&in.Data))
return nil
}
@ -4068,7 +4212,7 @@ func autoConvert_api_ReplicationControllerList_To_v1_ReplicationControllerList(i
}
}
} else {
out.Items = make([]v1.ReplicationController, 0)
out.Items = nil
}
return nil
}
@ -4213,11 +4357,7 @@ func Convert_v1_ResourceQuotaList_To_api_ResourceQuotaList(in *v1.ResourceQuotaL
func autoConvert_api_ResourceQuotaList_To_v1_ResourceQuotaList(in *api.ResourceQuotaList, out *v1.ResourceQuotaList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.ResourceQuota, 0)
} else {
out.Items = *(*[]v1.ResourceQuota)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.ResourceQuota)(unsafe.Pointer(&in.Items))
return nil
}
@ -4462,7 +4602,7 @@ func autoConvert_api_SecretList_To_v1_SecretList(in *api.SecretList, out *v1.Sec
}
}
} else {
out.Items = make([]v1.Secret, 0)
out.Items = nil
}
return nil
}
@ -4500,6 +4640,28 @@ func Convert_api_SecretProjection_To_v1_SecretProjection(in *api.SecretProjectio
return autoConvert_api_SecretProjection_To_v1_SecretProjection(in, out, s)
}
func autoConvert_v1_SecretReference_To_api_SecretReference(in *v1.SecretReference, out *api.SecretReference, s conversion.Scope) error {
out.Name = in.Name
out.Namespace = in.Namespace
return nil
}
// Convert_v1_SecretReference_To_api_SecretReference is an autogenerated conversion function.
func Convert_v1_SecretReference_To_api_SecretReference(in *v1.SecretReference, out *api.SecretReference, s conversion.Scope) error {
return autoConvert_v1_SecretReference_To_api_SecretReference(in, out, s)
}
func autoConvert_api_SecretReference_To_v1_SecretReference(in *api.SecretReference, out *v1.SecretReference, s conversion.Scope) error {
out.Name = in.Name
out.Namespace = in.Namespace
return nil
}
// Convert_api_SecretReference_To_v1_SecretReference is an autogenerated conversion function.
func Convert_api_SecretReference_To_v1_SecretReference(in *api.SecretReference, out *v1.SecretReference, s conversion.Scope) error {
return autoConvert_api_SecretReference_To_v1_SecretReference(in, out, s)
}
func autoConvert_v1_SecretVolumeSource_To_api_SecretVolumeSource(in *v1.SecretVolumeSource, out *api.SecretVolumeSource, s conversion.Scope) error {
out.SecretName = in.SecretName
out.Items = *(*[]api.KeyToPath)(unsafe.Pointer(&in.Items))
@ -4533,6 +4695,7 @@ func autoConvert_v1_SecurityContext_To_api_SecurityContext(in *v1.SecurityContex
out.RunAsUser = (*int64)(unsafe.Pointer(in.RunAsUser))
out.RunAsNonRoot = (*bool)(unsafe.Pointer(in.RunAsNonRoot))
out.ReadOnlyRootFilesystem = (*bool)(unsafe.Pointer(in.ReadOnlyRootFilesystem))
out.AllowPrivilegeEscalation = (*bool)(unsafe.Pointer(in.AllowPrivilegeEscalation))
return nil
}
@ -4548,14 +4711,10 @@ func autoConvert_api_SecurityContext_To_v1_SecurityContext(in *api.SecurityConte
out.RunAsUser = (*int64)(unsafe.Pointer(in.RunAsUser))
out.RunAsNonRoot = (*bool)(unsafe.Pointer(in.RunAsNonRoot))
out.ReadOnlyRootFilesystem = (*bool)(unsafe.Pointer(in.ReadOnlyRootFilesystem))
out.AllowPrivilegeEscalation = (*bool)(unsafe.Pointer(in.AllowPrivilegeEscalation))
return nil
}
// Convert_api_SecurityContext_To_v1_SecurityContext is an autogenerated conversion function.
func Convert_api_SecurityContext_To_v1_SecurityContext(in *api.SecurityContext, out *v1.SecurityContext, s conversion.Scope) error {
return autoConvert_api_SecurityContext_To_v1_SecurityContext(in, out, s)
}
func autoConvert_v1_SerializedReference_To_api_SerializedReference(in *v1.SerializedReference, out *api.SerializedReference, s conversion.Scope) error {
if err := Convert_v1_ObjectReference_To_api_ObjectReference(&in.Reference, &out.Reference, s); err != nil {
return err
@ -4651,11 +4810,7 @@ func Convert_v1_ServiceAccountList_To_api_ServiceAccountList(in *v1.ServiceAccou
func autoConvert_api_ServiceAccountList_To_v1_ServiceAccountList(in *api.ServiceAccountList, out *v1.ServiceAccountList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items == nil {
out.Items = make([]v1.ServiceAccount, 0)
} else {
out.Items = *(*[]v1.ServiceAccount)(unsafe.Pointer(&in.Items))
}
out.Items = *(*[]v1.ServiceAccount)(unsafe.Pointer(&in.Items))
return nil
}
@ -4696,7 +4851,7 @@ func autoConvert_api_ServiceList_To_v1_ServiceList(in *api.ServiceList, out *v1.
}
}
} else {
out.Items = make([]v1.Service, 0)
out.Items = nil
}
return nil
}
@ -4766,6 +4921,8 @@ func autoConvert_v1_ServiceSpec_To_api_ServiceSpec(in *v1.ServiceSpec, out *api.
out.ExternalName = in.ExternalName
out.ExternalTrafficPolicy = api.ServiceExternalTrafficPolicyType(in.ExternalTrafficPolicy)
out.HealthCheckNodePort = in.HealthCheckNodePort
out.PublishNotReadyAddresses = in.PublishNotReadyAddresses
out.SessionAffinityConfig = (*api.SessionAffinityConfig)(unsafe.Pointer(in.SessionAffinityConfig))
return nil
}
@ -4783,9 +4940,11 @@ func autoConvert_api_ServiceSpec_To_v1_ServiceSpec(in *api.ServiceSpec, out *v1.
out.ExternalIPs = *(*[]string)(unsafe.Pointer(&in.ExternalIPs))
out.LoadBalancerIP = in.LoadBalancerIP
out.SessionAffinity = v1.ServiceAffinity(in.SessionAffinity)
out.SessionAffinityConfig = (*v1.SessionAffinityConfig)(unsafe.Pointer(in.SessionAffinityConfig))
out.LoadBalancerSourceRanges = *(*[]string)(unsafe.Pointer(&in.LoadBalancerSourceRanges))
out.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyType(in.ExternalTrafficPolicy)
out.HealthCheckNodePort = in.HealthCheckNodePort
out.PublishNotReadyAddresses = in.PublishNotReadyAddresses
return nil
}
@ -4818,6 +4977,26 @@ func Convert_api_ServiceStatus_To_v1_ServiceStatus(in *api.ServiceStatus, out *v
return autoConvert_api_ServiceStatus_To_v1_ServiceStatus(in, out, s)
}
func autoConvert_v1_SessionAffinityConfig_To_api_SessionAffinityConfig(in *v1.SessionAffinityConfig, out *api.SessionAffinityConfig, s conversion.Scope) error {
out.ClientIP = (*api.ClientIPConfig)(unsafe.Pointer(in.ClientIP))
return nil
}
// Convert_v1_SessionAffinityConfig_To_api_SessionAffinityConfig is an autogenerated conversion function.
func Convert_v1_SessionAffinityConfig_To_api_SessionAffinityConfig(in *v1.SessionAffinityConfig, out *api.SessionAffinityConfig, s conversion.Scope) error {
return autoConvert_v1_SessionAffinityConfig_To_api_SessionAffinityConfig(in, out, s)
}
func autoConvert_api_SessionAffinityConfig_To_v1_SessionAffinityConfig(in *api.SessionAffinityConfig, out *v1.SessionAffinityConfig, s conversion.Scope) error {
out.ClientIP = (*v1.ClientIPConfig)(unsafe.Pointer(in.ClientIP))
return nil
}
// Convert_api_SessionAffinityConfig_To_v1_SessionAffinityConfig is an autogenerated conversion function.
func Convert_api_SessionAffinityConfig_To_v1_SessionAffinityConfig(in *api.SessionAffinityConfig, out *v1.SessionAffinityConfig, s conversion.Scope) error {
return autoConvert_api_SessionAffinityConfig_To_v1_SessionAffinityConfig(in, out, s)
}
func autoConvert_v1_StorageOSPersistentVolumeSource_To_api_StorageOSPersistentVolumeSource(in *v1.StorageOSPersistentVolumeSource, out *api.StorageOSPersistentVolumeSource, s conversion.Scope) error {
out.VolumeName = in.VolumeName
out.VolumeNamespace = in.VolumeNamespace
@ -5003,6 +5182,7 @@ func autoConvert_v1_VolumeMount_To_api_VolumeMount(in *v1.VolumeMount, out *api.
out.ReadOnly = in.ReadOnly
out.MountPath = in.MountPath
out.SubPath = in.SubPath
out.MountPropagation = (*api.MountPropagationMode)(unsafe.Pointer(in.MountPropagation))
return nil
}
@ -5016,6 +5196,7 @@ func autoConvert_api_VolumeMount_To_v1_VolumeMount(in *api.VolumeMount, out *v1.
out.ReadOnly = in.ReadOnly
out.MountPath = in.MountPath
out.SubPath = in.SubPath
out.MountPropagation = (*v1.MountPropagationMode)(unsafe.Pointer(in.MountPropagation))
return nil
}

View file

@ -133,6 +133,9 @@ func SetObjectDefaults_NodeList(in *v1.NodeList) {
func SetObjectDefaults_PersistentVolume(in *v1.PersistentVolume) {
SetDefaults_PersistentVolume(in)
SetDefaults_ResourceList(&in.Spec.Capacity)
if in.Spec.PersistentVolumeSource.HostPath != nil {
SetDefaults_HostPathVolumeSource(in.Spec.PersistentVolumeSource.HostPath)
}
if in.Spec.PersistentVolumeSource.RBD != nil {
SetDefaults_RBDVolumeSource(in.Spec.PersistentVolumeSource.RBD)
}
@ -174,6 +177,9 @@ func SetObjectDefaults_Pod(in *v1.Pod) {
for i := range in.Spec.Volumes {
a := &in.Spec.Volumes[i]
SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil {
SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
}
@ -322,6 +328,9 @@ func SetObjectDefaults_PodTemplate(in *v1.PodTemplate) {
for i := range in.Template.Spec.Volumes {
a := &in.Template.Spec.Volumes[i]
SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil {
SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
}
@ -464,6 +473,9 @@ func SetObjectDefaults_ReplicationController(in *v1.ReplicationController) {
for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i]
SetDefaults_Volume(a)
if a.VolumeSource.HostPath != nil {
SetDefaults_HostPathVolumeSource(a.VolumeSource.HostPath)
}
if a.VolumeSource.Secret != nil {
SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
}

View file

@ -1,7 +1,3 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
@ -13,10 +9,9 @@ go_library(
srcs = [
"doc.go",
"events.go",
"schema.go",
"validation.go",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/helper:go_default_library",
@ -27,8 +22,6 @@ go_library(
"//pkg/capabilities:go_default_library",
"//pkg/features:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//vendor/github.com/emicklei/go-restful-swagger12:go_default_library",
"//vendor/github.com/exponent-io/jsonpath:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
@ -36,16 +29,14 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)
@ -54,38 +45,22 @@ go_test(
name = "go_default_test",
srcs = [
"events_test.go",
"schema_test.go",
"validation_test.go",
],
data = [
"testdata/v1/invalidPod.yaml",
"testdata/v1/invalidPod1.json",
"testdata/v1/invalidPod2.json",
"testdata/v1/invalidPod3.json",
"testdata/v1/invalidPod4.yaml",
"testdata/v1/validPod.yaml",
"//api/swagger-spec",
],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/helper:go_default_library",
"//pkg/api/testapi:go_default_library",
"//pkg/api/testing:go_default_library",
"//pkg/capabilities:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)
@ -94,11 +69,11 @@ filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View file

@ -1,435 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"regexp"
"strings"
"github.com/emicklei/go-restful-swagger12"
ejson "github.com/exponent-io/jsonpath"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/yaml"
apiutil "k8s.io/kubernetes/pkg/api/util"
)
type InvalidTypeError struct {
ExpectedKind reflect.Kind
ObservedKind reflect.Kind
FieldName string
}
func (i *InvalidTypeError) Error() string {
return fmt.Sprintf("expected type %s, for field %s, got %s", i.ExpectedKind.String(), i.FieldName, i.ObservedKind.String())
}
func NewInvalidTypeError(expected reflect.Kind, observed reflect.Kind, fieldName string) error {
return &InvalidTypeError{expected, observed, fieldName}
}
// TypeNotFoundError is returned when specified type
// can not found in schema
type TypeNotFoundError string
func (tnfe TypeNotFoundError) Error() string {
return fmt.Sprintf("couldn't find type: %s", string(tnfe))
}
// Schema is an interface that knows how to validate an API object serialized to a byte array.
type Schema interface {
ValidateBytes(data []byte) error
}
type NullSchema struct{}
func (NullSchema) ValidateBytes(data []byte) error { return nil }
type NoDoubleKeySchema struct{}
func (NoDoubleKeySchema) ValidateBytes(data []byte) error {
var list []error = nil
if err := validateNoDuplicateKeys(data, "metadata", "labels"); err != nil {
list = append(list, err)
}
if err := validateNoDuplicateKeys(data, "metadata", "annotations"); err != nil {
list = append(list, err)
}
return utilerrors.NewAggregate(list)
}
func validateNoDuplicateKeys(data []byte, path ...string) error {
r := ejson.NewDecoder(bytes.NewReader(data))
// This is Go being unfriendly. The 'path ...string' comes in as a
// []string, and SeekTo takes ...interface{}, so we can't just pass
// the path straight in, we have to copy it. *sigh*
ifacePath := []interface{}{}
for ix := range path {
ifacePath = append(ifacePath, path[ix])
}
found, err := r.SeekTo(ifacePath...)
if err != nil {
return err
}
if !found {
return nil
}
seen := map[string]bool{}
for {
tok, err := r.Token()
if err != nil {
return err
}
switch t := tok.(type) {
case json.Delim:
if t.String() == "}" {
return nil
}
case ejson.KeyString:
if seen[string(t)] {
return fmt.Errorf("duplicate key: %s", string(t))
} else {
seen[string(t)] = true
}
}
}
}
type ConjunctiveSchema []Schema
func (c ConjunctiveSchema) ValidateBytes(data []byte) error {
var list []error = nil
schemas := []Schema(c)
for ix := range schemas {
if err := schemas[ix].ValidateBytes(data); err != nil {
list = append(list, err)
}
}
return utilerrors.NewAggregate(list)
}
type SwaggerSchema struct {
api swagger.ApiDeclaration
delegate Schema // For delegating to other api groups
}
func NewSwaggerSchemaFromBytes(data []byte, factory Schema) (Schema, error) {
schema := &SwaggerSchema{}
err := json.Unmarshal(data, &schema.api)
if err != nil {
return nil, err
}
schema.delegate = factory
return schema, nil
}
// validateList unpacks a list and validate every item in the list.
// It return nil if every item is ok.
// Otherwise it return an error list contain errors of every item.
func (s *SwaggerSchema) validateList(obj map[string]interface{}) []error {
items, exists := obj["items"]
if !exists {
return []error{fmt.Errorf("no items field in %#v", obj)}
}
return s.validateItems(items)
}
func (s *SwaggerSchema) validateItems(items interface{}) []error {
allErrs := []error{}
itemList, ok := items.([]interface{})
if !ok {
return append(allErrs, fmt.Errorf("items isn't a slice"))
}
for i, item := range itemList {
fields, ok := item.(map[string]interface{})
if !ok {
allErrs = append(allErrs, fmt.Errorf("items[%d] isn't a map[string]interface{}", i))
continue
}
groupVersion := fields["apiVersion"]
if groupVersion == nil {
allErrs = append(allErrs, fmt.Errorf("items[%d].apiVersion not set", i))
continue
}
itemVersion, ok := groupVersion.(string)
if !ok {
allErrs = append(allErrs, fmt.Errorf("items[%d].apiVersion isn't string type", i))
continue
}
if len(itemVersion) == 0 {
allErrs = append(allErrs, fmt.Errorf("items[%d].apiVersion is empty", i))
}
kind := fields["kind"]
if kind == nil {
allErrs = append(allErrs, fmt.Errorf("items[%d].kind not set", i))
continue
}
itemKind, ok := kind.(string)
if !ok {
allErrs = append(allErrs, fmt.Errorf("items[%d].kind isn't string type", i))
continue
}
if len(itemKind) == 0 {
allErrs = append(allErrs, fmt.Errorf("items[%d].kind is empty", i))
}
version := apiutil.GetVersion(itemVersion)
errs := s.ValidateObject(item, "", version+"."+itemKind)
if len(errs) >= 1 {
allErrs = append(allErrs, errs...)
}
}
return allErrs
}
func (s *SwaggerSchema) ValidateBytes(data []byte) error {
var obj interface{}
out, err := yaml.ToJSON(data)
if err != nil {
return err
}
data = out
if err := json.Unmarshal(data, &obj); err != nil {
return err
}
fields, ok := obj.(map[string]interface{})
if !ok {
return fmt.Errorf("error in unmarshaling data %s", string(data))
}
groupVersion := fields["apiVersion"]
if groupVersion == nil {
return fmt.Errorf("apiVersion not set")
}
if _, ok := groupVersion.(string); !ok {
return fmt.Errorf("apiVersion isn't string type")
}
kind := fields["kind"]
if kind == nil {
return fmt.Errorf("kind not set")
}
if _, ok := kind.(string); !ok {
return fmt.Errorf("kind isn't string type")
}
if strings.HasSuffix(kind.(string), "List") {
return utilerrors.NewAggregate(s.validateList(fields))
}
version := apiutil.GetVersion(groupVersion.(string))
allErrs := s.ValidateObject(obj, "", version+"."+kind.(string))
if len(allErrs) == 1 {
return allErrs[0]
}
return utilerrors.NewAggregate(allErrs)
}
func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName string) []error {
allErrs := []error{}
models := s.api.Models
model, ok := models.At(typeName)
// Verify the api version matches. This is required for nested types with differing api versions because
// s.api only has schema for 1 api version (the parent object type's version).
// e.g. an extensions/v1beta1 Template embedding a /v1 Service requires the schema for the extensions/v1beta1
// api to delegate to the schema for the /v1 api.
// Only do this for !ok objects so that cross ApiVersion vendored types take precedence.
if !ok && s.delegate != nil {
fields, mapOk := obj.(map[string]interface{})
if !mapOk {
return append(allErrs, fmt.Errorf("field %s for %s: expected object of type map[string]interface{}, but the actual type is %T", fieldName, typeName, obj))
}
if delegated, err := s.delegateIfDifferentApiVersion(&unstructured.Unstructured{Object: fields}); delegated {
if err != nil {
allErrs = append(allErrs, err)
}
return allErrs
}
}
if !ok {
return append(allErrs, TypeNotFoundError(typeName))
}
properties := model.Properties
if len(properties.List) == 0 {
// The object does not have any sub-fields.
return nil
}
fields, ok := obj.(map[string]interface{})
if !ok {
return append(allErrs, fmt.Errorf("field %s for %s: expected object of type map[string]interface{}, but the actual type is %T", fieldName, typeName, obj))
}
if len(fieldName) > 0 {
fieldName = fieldName + "."
}
// handle required fields
for _, requiredKey := range model.Required {
if _, ok := fields[requiredKey]; !ok {
allErrs = append(allErrs, fmt.Errorf("field %s%s for %s is required", fieldName, requiredKey, typeName))
}
}
for key, value := range fields {
details, ok := properties.At(key)
// Special case for runtime.RawExtension and runtime.Objects because they always fail to validate
// This is because the actual values will be of some sub-type (e.g. Deployment) not the expected
// super-type (RawExtension)
if s.isGenericArray(details) {
errs := s.validateItems(value)
if len(errs) > 0 {
allErrs = append(allErrs, errs...)
}
continue
}
if !ok {
allErrs = append(allErrs, fmt.Errorf("found invalid field %s for %s", key, typeName))
continue
}
if details.Type == nil && details.Ref == nil {
allErrs = append(allErrs, fmt.Errorf("could not find the type of %s%s from object %v", fieldName, key, details))
}
var fieldType string
if details.Type != nil {
fieldType = *details.Type
} else {
fieldType = *details.Ref
}
if value == nil {
glog.V(2).Infof("Skipping nil field: %s%s", fieldName, key)
continue
}
errs := s.validateField(value, fieldName+key, fieldType, &details)
if len(errs) > 0 {
allErrs = append(allErrs, errs...)
}
}
return allErrs
}
// delegateIfDifferentApiVersion delegates the validation of an object if its ApiGroup does not match the
// current SwaggerSchema.
// First return value is true if the validation was delegated (by a different ApiGroup SwaggerSchema)
// Second return value is the result of the delegated validation if performed.
func (s *SwaggerSchema) delegateIfDifferentApiVersion(obj *unstructured.Unstructured) (bool, error) {
// Never delegate objects in the same ApiVersion or we will get infinite recursion
if !s.isDifferentApiVersion(obj) {
return false, nil
}
// Convert the object back into bytes so that we can pass it to the ValidateBytes function
m, err := json.Marshal(obj.Object)
if err != nil {
return true, err
}
// Delegate validation of this object to the correct SwaggerSchema for its ApiGroup
return true, s.delegate.ValidateBytes(m)
}
// isDifferentApiVersion Returns true if obj lives in a different ApiVersion than the SwaggerSchema does.
// The SwaggerSchema will not be able to process objects in different ApiVersions unless they are vendored.
func (s *SwaggerSchema) isDifferentApiVersion(obj *unstructured.Unstructured) bool {
groupVersion := obj.GetAPIVersion()
return len(groupVersion) > 0 && s.api.ApiVersion != groupVersion
}
// isGenericArray Returns true if p is an array of generic Objects - either RawExtension or Object.
func (s *SwaggerSchema) isGenericArray(p swagger.ModelProperty) bool {
return p.DataTypeFields.Type != nil &&
*p.DataTypeFields.Type == "array" &&
p.Items != nil &&
p.Items.Ref != nil &&
(*p.Items.Ref == "runtime.RawExtension" || *p.Items.Ref == "runtime.Object")
}
// This matches type name in the swagger spec, such as "v1.Binding".
var versionRegexp = regexp.MustCompile(`^(v.+|unversioned|types)\..*`)
func (s *SwaggerSchema) validateField(value interface{}, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) []error {
allErrs := []error{}
if reflect.TypeOf(value) == nil {
return append(allErrs, fmt.Errorf("unexpected nil value for field %v", fieldName))
}
// TODO: caesarxuchao: because we have multiple group/versions and objects
// may reference objects in other group, the commented out way of checking
// if a filedType is a type defined by us is outdated. We use a hacky way
// for now.
// TODO: the type name in the swagger spec is something like "v1.Binding",
// and the "v1" is generated from the package name, not the groupVersion of
// the type. We need to fix go-restful to embed the group name in the type
// name, otherwise we couldn't handle identically named types in different
// groups correctly.
if versionRegexp.MatchString(fieldType) {
// if strings.HasPrefix(fieldType, apiVersion) {
return s.ValidateObject(value, fieldName, fieldType)
}
switch fieldType {
case "string":
// Be loose about what we accept for 'string' since we use IntOrString in a couple of places
_, isString := value.(string)
_, isNumber := value.(float64)
_, isInteger := value.(int)
if !isString && !isNumber && !isInteger {
return append(allErrs, NewInvalidTypeError(reflect.String, reflect.TypeOf(value).Kind(), fieldName))
}
case "array":
arr, ok := value.([]interface{})
if !ok {
return append(allErrs, NewInvalidTypeError(reflect.Array, reflect.TypeOf(value).Kind(), fieldName))
}
var arrType string
if fieldDetails.Items.Ref == nil && fieldDetails.Items.Type == nil {
return append(allErrs, NewInvalidTypeError(reflect.Array, reflect.TypeOf(value).Kind(), fieldName))
}
if fieldDetails.Items.Ref != nil {
arrType = *fieldDetails.Items.Ref
} else {
arrType = *fieldDetails.Items.Type
}
for ix := range arr {
errs := s.validateField(arr[ix], fmt.Sprintf("%s[%d]", fieldName, ix), arrType, nil)
if len(errs) > 0 {
allErrs = append(allErrs, errs...)
}
}
case "uint64":
case "int64":
case "integer":
_, isNumber := value.(float64)
_, isInteger := value.(int)
if !isNumber && !isInteger {
return append(allErrs, NewInvalidTypeError(reflect.Int, reflect.TypeOf(value).Kind(), fieldName))
}
case "float64":
if _, ok := value.(float64); !ok {
return append(allErrs, NewInvalidTypeError(reflect.Float64, reflect.TypeOf(value).Kind(), fieldName))
}
case "boolean":
if _, ok := value.(bool); !ok {
return append(allErrs, NewInvalidTypeError(reflect.Bool, reflect.TypeOf(value).Kind(), fieldName))
}
// API servers before release 1.3 produce swagger spec with `type: "any"` as the fallback type, while newer servers produce spec with `type: "object"`.
// We have both here so that kubectl can work with both old and new api servers.
case "object":
case "any":
default:
return append(allErrs, fmt.Errorf("unexpected type: %v", fieldType))
}
return allErrs
}

View file

@ -19,18 +19,16 @@ package validation
import (
"encoding/json"
"fmt"
"math"
"net"
"path"
"path/filepath"
"reflect"
"regexp"
"strconv"
"strings"
"github.com/golang/glog"
"math"
"k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/resource"
@ -39,6 +37,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation"
@ -69,6 +68,10 @@ var volumeModeErrorMsg string = "must be a number between 0 and 0777 (octal), bo
// BannedOwners is a black list of object that are not allowed to be owners.
var BannedOwners = genericvalidation.BannedOwners
var iscsiInitiatorIqnRegex = regexp.MustCompile(`iqn\.\d{4}-\d{2}\.([[:alnum:]-.]+)(:[^,;*&$|\s]+)$`)
var iscsiInitiatorEuiRegex = regexp.MustCompile(`^eui.[[:alnum:]]{16}$`)
var iscsiInitiatorNaaRegex = regexp.MustCompile(`^naa.[[:alnum:]]{32}$`)
// ValidateHasLabel requires that metav1.ObjectMeta has a Label with key and expectedValue
func ValidateHasLabel(meta metav1.ObjectMeta, fldPath *field.Path, key, expectedValue string) field.ErrorList {
allErrs := field.ErrorList{}
@ -358,7 +361,7 @@ func ValidateVolumes(volumes []api.Volume, fldPath *field.Path) (sets.String, fi
for i, vol := range volumes {
idxPath := fldPath.Index(i)
namePath := idxPath.Child("name")
el := validateVolumeSource(&vol.VolumeSource, idxPath)
el := validateVolumeSource(&vol.VolumeSource, idxPath, vol.Name)
if len(vol.Name) == 0 {
el = append(el, field.Required(namePath, ""))
} else {
@ -377,16 +380,22 @@ func ValidateVolumes(volumes []api.Volume, fldPath *field.Path) (sets.String, fi
return allNames, allErrs
}
func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.ErrorList {
func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path, volName string) field.ErrorList {
numVolumes := 0
allErrs := field.ErrorList{}
if source.EmptyDir != nil {
numVolumes++
if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
unsetSizeLimit := resource.Quantity{}
if unsetSizeLimit.Cmp(source.EmptyDir.SizeLimit) != 0 {
if source.EmptyDir.SizeLimit != nil && source.EmptyDir.SizeLimit.Cmp(resource.Quantity{}) != 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("emptyDir").Child("sizeLimit"), "SizeLimit field disabled by feature-gate for EmptyDir volumes"))
}
} else {
if source.EmptyDir.SizeLimit != nil && source.EmptyDir.SizeLimit.Cmp(resource.Quantity{}) < 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("emptyDir").Child("sizeLimit"), "SizeLimit field must be a valid resource quantity"))
}
}
if !utilfeature.DefaultFeatureGate.Enabled(features.HugePages) && source.EmptyDir.Medium == api.StorageMediumHugePages {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("emptyDir").Child("medium"), "HugePages medium is disabled by feature-gate for EmptyDir volumes"))
}
}
if source.HostPath != nil {
@ -444,13 +453,17 @@ func validateVolumeSource(source *api.VolumeSource, fldPath *field.Path) field.E
numVolumes++
allErrs = append(allErrs, validateISCSIVolumeSource(source.ISCSI, fldPath.Child("iscsi"))...)
}
if source.ISCSI.InitiatorName != nil && len(volName+":"+source.ISCSI.TargetPortal) > 64 {
tooLongErr := "Total length of <volume name>:<iscsi.targetPortal> must be under 64 characters if iscsi.initiatorName is specified."
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), volName, tooLongErr))
}
}
if source.Glusterfs != nil {
if numVolumes > 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("glusterfs"), "may not specify more than 1 volume type"))
} else {
numVolumes++
allErrs = append(allErrs, validateGlusterfs(source.Glusterfs, fldPath.Child("glusterfs"))...)
allErrs = append(allErrs, validateGlusterfsVolumeSource(source.Glusterfs, fldPath.Child("glusterfs"))...)
}
}
if source.Flocker != nil {
@ -615,6 +628,7 @@ func validateHostPathVolumeSource(hostPath *api.HostPathVolumeSource, fldPath *f
}
allErrs = append(allErrs, validatePathNoBacksteps(hostPath.Path, fldPath.Child("path"))...)
allErrs = append(allErrs, validateHostPathType(hostPath.Type, fldPath.Child("type"))...)
return allErrs
}
@ -636,6 +650,16 @@ func validateISCSIVolumeSource(iscsi *api.ISCSIVolumeSource, fldPath *field.Path
}
if len(iscsi.IQN) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("iqn"), ""))
} else {
if !strings.HasPrefix(iscsi.IQN, "iqn") && !strings.HasPrefix(iscsi.IQN, "eui") && !strings.HasPrefix(iscsi.IQN, "naa") {
allErrs = append(allErrs, field.Invalid(fldPath.Child("iqn"), iscsi.IQN, "must be valid format"))
} else if strings.HasPrefix(iscsi.IQN, "iqn") && !iscsiInitiatorIqnRegex.MatchString(iscsi.IQN) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("iqn"), iscsi.IQN, "must be valid format"))
} else if strings.HasPrefix(iscsi.IQN, "eui") && !iscsiInitiatorEuiRegex.MatchString(iscsi.IQN) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("iqn"), iscsi.IQN, "must be valid format"))
} else if strings.HasPrefix(iscsi.IQN, "naa") && !iscsiInitiatorNaaRegex.MatchString(iscsi.IQN) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("iqn"), iscsi.IQN, "must be valid format"))
}
}
if iscsi.Lun < 0 || iscsi.Lun > 255 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("lun"), iscsi.Lun, validation.InclusiveRangeError(0, 255)))
@ -643,20 +667,39 @@ func validateISCSIVolumeSource(iscsi *api.ISCSIVolumeSource, fldPath *field.Path
if (iscsi.DiscoveryCHAPAuth || iscsi.SessionCHAPAuth) && iscsi.SecretRef == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("secretRef"), ""))
}
if iscsi.InitiatorName != nil {
initiator := *iscsi.InitiatorName
if !strings.HasPrefix(initiator, "iqn") && !strings.HasPrefix(initiator, "eui") && !strings.HasPrefix(initiator, "naa") {
allErrs = append(allErrs, field.Invalid(fldPath.Child("initiatorname"), initiator, "must be valid format"))
}
if strings.HasPrefix(initiator, "iqn") && !iscsiInitiatorIqnRegex.MatchString(initiator) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("initiatorname"), initiator, "must be valid format"))
} else if strings.HasPrefix(initiator, "eui") && !iscsiInitiatorEuiRegex.MatchString(initiator) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("initiatorname"), initiator, "must be valid format"))
} else if strings.HasPrefix(initiator, "naa") && !iscsiInitiatorNaaRegex.MatchString(initiator) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("initiatorname"), initiator, "must be valid format"))
}
}
return allErrs
}
func validateFCVolumeSource(fc *api.FCVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(fc.TargetWWNs) < 1 {
allErrs = append(allErrs, field.Required(fldPath.Child("targetWWNs"), ""))
if len(fc.TargetWWNs) < 1 && len(fc.WWIDs) < 1 {
allErrs = append(allErrs, field.Required(fldPath.Child("targetWWNs"), "must specify either targetWWNs or wwids, but not both"))
}
if fc.Lun == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("lun"), ""))
} else {
if *fc.Lun < 0 || *fc.Lun > 255 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("lun"), fc.Lun, validation.InclusiveRangeError(0, 255)))
if len(fc.TargetWWNs) != 0 && len(fc.WWIDs) != 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("targetWWNs"), fc.TargetWWNs, "targetWWNs and wwids can not be specified simultaneously"))
}
if len(fc.TargetWWNs) != 0 {
if fc.Lun == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("lun"), "lun is required if targetWWNs is specified"))
} else {
if *fc.Lun < 0 || *fc.Lun > 255 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("lun"), fc.Lun, validation.InclusiveRangeError(0, 255)))
}
}
}
return allErrs
@ -778,7 +821,7 @@ func validateQuobyteVolumeSource(quobyte *api.QuobyteVolumeSource, fldPath *fiel
return allErrs
}
func validateGlusterfs(glusterfs *api.GlusterfsVolumeSource, fldPath *field.Path) field.ErrorList {
func validateGlusterfsVolumeSource(glusterfs *api.GlusterfsVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(glusterfs.EndpointsName) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("endpoints"), ""))
@ -937,6 +980,26 @@ func validateProjectedVolumeSource(projection *api.ProjectedVolumeSource, fldPat
return allErrs
}
var supportedHostPathTypes = sets.NewString(
string(api.HostPathUnset),
string(api.HostPathDirectoryOrCreate),
string(api.HostPathDirectory),
string(api.HostPathFileOrCreate),
string(api.HostPathFile),
string(api.HostPathSocket),
string(api.HostPathCharDev),
string(api.HostPathBlockDev))
func validateHostPathType(hostPathType *api.HostPathType, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if hostPathType != nil && !supportedHostPathTypes.Has(string(*hostPathType)) {
allErrs = append(allErrs, field.NotSupported(fldPath, hostPathType, supportedHostPathTypes.List()))
}
return allErrs
}
// This validate will make sure targetPath:
// 1. is not abs path
// 2. does not have any element which is ".."
@ -967,6 +1030,38 @@ func validatePathNoBacksteps(targetPath string, fldPath *field.Path) field.Error
return allErrs
}
// validateMountPropagation verifies that MountPropagation field is valid and
// allowed for given container.
func validateMountPropagation(mountPropagation *api.MountPropagationMode, container *api.Container, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if mountPropagation == nil {
return allErrs
}
if !utilfeature.DefaultFeatureGate.Enabled(features.MountPropagation) {
allErrs = append(allErrs, field.Forbidden(fldPath, "mount propagation is disabled by feature-gate"))
return allErrs
}
supportedMountPropagations := sets.NewString(string(api.MountPropagationBidirectional), string(api.MountPropagationHostToContainer))
if !supportedMountPropagations.Has(string(*mountPropagation)) {
allErrs = append(allErrs, field.NotSupported(fldPath, *mountPropagation, supportedMountPropagations.List()))
}
if container == nil {
// The container is not available yet, e.g. during validation of
// PodPreset. Stop validation now, Pod validation will refuse final
// Pods with Bidirectional propagation in non-privileged containers.
return allErrs
}
privileged := container.SecurityContext != nil && container.SecurityContext.Privileged != nil && *container.SecurityContext.Privileged
if *mountPropagation == api.MountPropagationBidirectional && !privileged {
allErrs = append(allErrs, field.Forbidden(fldPath, "Bidirectional mount propagation is available only to privileged containers"))
}
return allErrs
}
// This validate will make sure targetPath:
// 1. is not abs path
// 2. does not contain any '..' elements
@ -1008,6 +1103,14 @@ func validateCephFSVolumeSource(cephfs *api.CephFSVolumeSource, fldPath *field.P
return allErrs
}
func validateCephFSPersistentVolumeSource(cephfs *api.CephFSPersistentVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(cephfs.Monitors) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("monitors"), ""))
}
return allErrs
}
func validateFlexVolumeSource(fv *api.FlexVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(fv.Driver) == 0 {
@ -1040,6 +1143,22 @@ func validateAzureFile(azure *api.AzureFileVolumeSource, fldPath *field.Path) fi
return allErrs
}
func validateAzureFilePV(azure *api.AzureFilePersistentVolumeSource, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if azure.SecretName == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("secretName"), ""))
}
if azure.ShareName == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("shareName"), ""))
}
if azure.SecretNamespace != nil {
if len(*azure.SecretNamespace) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("secretNamespace"), ""))
}
}
return allErrs
}
func validateAzureDisk(azure *api.AzureDiskVolumeSource, fldPath *field.Path) field.ErrorList {
var supportedCachingModes = sets.NewString(string(api.AzureDataDiskCachingNone), string(api.AzureDataDiskCachingReadOnly), string(api.AzureDataDiskCachingReadWrite))
var supportedDiskKinds = sets.NewString(string(api.AzureSharedBlobDisk), string(api.AzureDedicatedBlobDisk), string(api.AzureManagedDisk))
@ -1236,7 +1355,7 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
allErrs = append(allErrs, field.Forbidden(specPath.Child("glusterfs"), "may not specify more than 1 volume type"))
} else {
numVolumes++
allErrs = append(allErrs, validateGlusterfs(pv.Spec.Glusterfs, specPath.Child("glusterfs"))...)
allErrs = append(allErrs, validateGlusterfsVolumeSource(pv.Spec.Glusterfs, specPath.Child("glusterfs"))...)
}
}
if pv.Spec.Flocker != nil {
@ -1276,7 +1395,7 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
allErrs = append(allErrs, field.Forbidden(specPath.Child("cephFS"), "may not specify more than 1 volume type"))
} else {
numVolumes++
allErrs = append(allErrs, validateCephFSVolumeSource(pv.Spec.CephFS, specPath.Child("cephfs"))...)
allErrs = append(allErrs, validateCephFSPersistentVolumeSource(pv.Spec.CephFS, specPath.Child("cephfs"))...)
}
}
if pv.Spec.ISCSI != nil {
@ -1286,6 +1405,10 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
numVolumes++
allErrs = append(allErrs, validateISCSIVolumeSource(pv.Spec.ISCSI, specPath.Child("iscsi"))...)
}
if pv.Spec.ISCSI.InitiatorName != nil && len(pv.ObjectMeta.Name+":"+pv.Spec.ISCSI.TargetPortal) > 64 {
tooLongErr := "Total length of <volume name>:<iscsi.targetPortal> must be under 64 characters if iscsi.initiatorName is specified."
allErrs = append(allErrs, field.Invalid(metaPath.Child("name"), pv.ObjectMeta.Name, tooLongErr))
}
}
if pv.Spec.Cinder != nil {
if numVolumes > 0 {
@ -1313,7 +1436,7 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
} else {
numVolumes++
allErrs = append(allErrs, validateAzureFile(pv.Spec.AzureFile, specPath.Child("azureFile"))...)
allErrs = append(allErrs, validateAzureFilePV(pv.Spec.AzureFile, specPath.Child("azureFile"))...)
}
}
@ -1468,10 +1591,31 @@ func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *api.PersistentVolumeCla
oldPvc.Spec.VolumeName = newPvc.Spec.VolumeName
defer func() { oldPvc.Spec.VolumeName = "" }()
}
// changes to Spec are not allowed, but updates to label/and some annotations are OK.
// no-op updates pass validation.
if !apiequality.Semantic.DeepEqual(newPvc.Spec, oldPvc.Spec) {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "field is immutable after creation"))
if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
newPVCSpecCopy := newPvc.Spec.DeepCopy()
// lets make sure storage values are same.
if newPvc.Status.Phase == api.ClaimBound && newPVCSpecCopy.Resources.Requests != nil {
newPVCSpecCopy.Resources.Requests["storage"] = oldPvc.Spec.Resources.Requests["storage"]
}
oldSize := oldPvc.Spec.Resources.Requests["storage"]
newSize := newPvc.Spec.Resources.Requests["storage"]
if !apiequality.Semantic.DeepEqual(*newPVCSpecCopy, oldPvc.Spec) {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "is immutable after creation except resources.requests for bound claims"))
}
if newSize.Cmp(oldSize) < 0 {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "resources", "requests", "storage"), "field can not be less than previous value"))
}
} else {
// changes to Spec are not allowed, but updates to label/and some annotations are OK.
// no-op updates pass validation.
if !apiequality.Semantic.DeepEqual(newPvc.Spec, oldPvc.Spec) {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "field is immutable after creation"))
}
}
// storageclass annotation should be immutable after creation
@ -1491,6 +1635,10 @@ func ValidatePersistentVolumeClaimStatusUpdate(newPvc, oldPvc *api.PersistentVol
if len(newPvc.Spec.AccessModes) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("Spec", "accessModes"), ""))
}
if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) && len(newPvc.Status.Conditions) > 0 {
conditionPath := field.NewPath("status", "conditions")
allErrs = append(allErrs, field.Forbidden(conditionPath, "invalid field"))
}
capPath := field.NewPath("status", "capacity")
for r, qty := range newPvc.Status.Capacity {
allErrs = append(allErrs, validateBasicResource(qty, capPath.Key(string(r)))...)
@ -1548,7 +1696,7 @@ func ValidateEnv(vars []api.EnvVar, fldPath *field.Path) field.ErrorList {
if len(ev.Name) == 0 {
allErrs = append(allErrs, field.Required(idxPath.Child("name"), ""))
} else {
for _, msg := range validation.IsCIdentifier(ev.Name) {
for _, msg := range validation.IsEnvVarName(ev.Name) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), ev.Name, msg))
}
}
@ -1558,7 +1706,7 @@ func ValidateEnv(vars []api.EnvVar, fldPath *field.Path) field.ErrorList {
}
var validFieldPathExpressionsEnv = sets.NewString("metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP")
var validContainerResourceFieldPathExpressions = sets.NewString("limits.cpu", "limits.memory", "requests.cpu", "requests.memory")
var validContainerResourceFieldPathExpressions = sets.NewString("limits.cpu", "limits.memory", "limits.ephemeral-storage", "requests.cpu", "requests.memory", "requests.ephemeral-storage")
func validateEnvVarValueFrom(ev api.EnvVar, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
@ -1618,6 +1766,13 @@ func validateObjectFieldSelector(fs *api.ObjectFieldSelector, expressions *sets.
return allErrs
}
func fsResourceIsEphemeralStorage(resource string) bool {
if resource == "limits.ephemeral-storage" || resource == "requests.ephemeral-storage" {
return true
}
return false
}
func validateContainerResourceFieldSelector(fs *api.ResourceFieldSelector, expressions *sets.String, fldPath *field.Path, volume bool) field.ErrorList {
allErrs := field.ErrorList{}
@ -1627,6 +1782,8 @@ func validateContainerResourceFieldSelector(fs *api.ResourceFieldSelector, expre
allErrs = append(allErrs, field.Required(fldPath.Child("resource"), ""))
} else if !expressions.Has(fs.Resource) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("resource"), fs.Resource, expressions.List()))
} else if fsResourceIsEphemeralStorage(fs.Resource) && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
allErrs = append(allErrs, field.Forbidden(fldPath, "Containers' ephemeral storage requests/limits disabled by feature-gate for Downward API"))
}
allErrs = append(allErrs, validateContainerResourceDivisor(fs.Resource, fs.Divisor, fldPath)...)
return allErrs
@ -1637,7 +1794,7 @@ func ValidateEnvFrom(vars []api.EnvFromSource, fldPath *field.Path) field.ErrorL
for i, ev := range vars {
idxPath := fldPath.Index(i)
if len(ev.Prefix) > 0 {
for _, msg := range validation.IsCIdentifier(ev.Prefix) {
for _, msg := range validation.IsEnvVarName(ev.Prefix) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("prefix"), ev.Prefix, msg))
}
}
@ -1687,6 +1844,7 @@ func validateSecretEnvSource(secretSource *api.SecretEnvSource, fldPath *field.P
var validContainerResourceDivisorForCPU = sets.NewString("1m", "1")
var validContainerResourceDivisorForMemory = sets.NewString("1", "1k", "1M", "1G", "1T", "1P", "1E", "1Ki", "1Mi", "1Gi", "1Ti", "1Pi", "1Ei")
var validContainerResourceDivisorForEphemeralStorage = sets.NewString("1", "1k", "1M", "1G", "1T", "1P", "1E", "1Ki", "1Mi", "1Gi", "1Ti", "1Pi", "1Ei")
func validateContainerResourceDivisor(rName string, divisor resource.Quantity, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
@ -1703,6 +1861,10 @@ func validateContainerResourceDivisor(rName string, divisor resource.Quantity, f
if !validContainerResourceDivisorForMemory.Has(divisor.String()) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("divisor"), rName, "only divisor's values 1, 1k, 1M, 1G, 1T, 1P, 1E, 1Ki, 1Mi, 1Gi, 1Ti, 1Pi, 1Ei are supported with the memory resource"))
}
case "limits.ephemeral-storage", "requests.ephemeral-storage":
if !validContainerResourceDivisorForEphemeralStorage.Has(divisor.String()) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("divisor"), rName, "only divisor's values 1, 1k, 1M, 1G, 1T, 1P, 1E, 1Ki, 1Mi, 1Gi, 1Ti, 1Pi, 1Ei are supported with the local ephemeral storage resource"))
}
}
return allErrs
}
@ -1743,7 +1905,7 @@ func validateSecretKeySelector(s *api.SecretKeySelector, fldPath *field.Path) fi
return allErrs
}
func ValidateVolumeMounts(mounts []api.VolumeMount, volumes sets.String, fldPath *field.Path) field.ErrorList {
func ValidateVolumeMounts(mounts []api.VolumeMount, volumes sets.String, container *api.Container, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
mountpoints := sets.NewString()
@ -1767,6 +1929,10 @@ func ValidateVolumeMounts(mounts []api.VolumeMount, volumes sets.String, fldPath
if len(mnt.SubPath) > 0 {
allErrs = append(allErrs, validateLocalDescendingPath(mnt.SubPath, fldPath.Child("subPath"))...)
}
if mnt.MountPropagation != nil {
allErrs = append(allErrs, validateMountPropagation(mnt.MountPropagation, container, fldPath.Child("mountPropagation"))...)
}
}
return allErrs
}
@ -1787,6 +1953,33 @@ func validateProbe(probe *api.Probe, fldPath *field.Path) field.ErrorList {
return allErrs
}
func validateClientIPAffinityConfig(config *api.SessionAffinityConfig, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if config == nil {
allErrs = append(allErrs, field.Required(fldPath, fmt.Sprintf("when session affinity type is %s", api.ServiceAffinityClientIP)))
return allErrs
}
if config.ClientIP == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("clientIP"), fmt.Sprintf("when session affinity type is %s", api.ServiceAffinityClientIP)))
return allErrs
}
if config.ClientIP.TimeoutSeconds == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("clientIP").Child("timeoutSeconds"), fmt.Sprintf("when session affinity type is %s", api.ServiceAffinityClientIP)))
return allErrs
}
allErrs = append(allErrs, validateAffinityTimeout(config.ClientIP.TimeoutSeconds, fldPath.Child("clientIP").Child("timeoutSeconds"))...)
return allErrs
}
func validateAffinityTimeout(timeout *int32, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if *timeout <= 0 || *timeout > api.MaxClientIPServiceAffinitySeconds {
allErrs = append(allErrs, field.Invalid(fldPath, timeout, fmt.Sprintf("must be greater than 0 and less than %d", api.MaxClientIPServiceAffinitySeconds)))
}
return allErrs
}
// AccumulateUniqueHostPorts extracts each HostPort of each Container,
// accumulating the results and returning an error if any ports conflict.
func AccumulateUniqueHostPorts(containers []api.Container, accumulator *sets.String, fldPath *field.Path) field.ErrorList {
@ -2006,7 +2199,7 @@ func validateContainers(containers []api.Container, volumes sets.String, fldPath
allErrs = append(allErrs, validateContainerPorts(ctr.Ports, idxPath.Child("ports"))...)
allErrs = append(allErrs, ValidateEnv(ctr.Env, idxPath.Child("env"))...)
allErrs = append(allErrs, ValidateEnvFrom(ctr.EnvFrom, idxPath.Child("envFrom"))...)
allErrs = append(allErrs, ValidateVolumeMounts(ctr.VolumeMounts, volumes, idxPath.Child("volumeMounts"))...)
allErrs = append(allErrs, ValidateVolumeMounts(ctr.VolumeMounts, volumes, &ctr, idxPath.Child("volumeMounts"))...)
allErrs = append(allErrs, validatePullPolicy(ctr.ImagePullPolicy, idxPath.Child("imagePullPolicy"))...)
allErrs = append(allErrs, ValidateResourceRequirements(&ctr.Resources, idxPath.Child("resources"))...)
allErrs = append(allErrs, ValidateSecurityContext(ctr.SecurityContext, idxPath.Child("securityContext"))...)
@ -2062,16 +2255,6 @@ func validateHostNetwork(hostNetwork bool, containers []api.Container, fldPath *
return allErrors
}
func validateHostNetworkNoHostAliases(hostNetwork bool, hostAliases []api.HostAlias, fldPath *field.Path) field.ErrorList {
allErrors := field.ErrorList{}
if hostNetwork {
if len(hostAliases) > 0 {
allErrors = append(allErrors, field.Forbidden(fldPath, "may not be set when `hostNetwork` is true"))
}
}
return allErrors
}
// validateImagePullSecrets checks to make sure the pull secrets are well
// formed. Right now, we only expect name to be set (it's the only field). If
// this ever changes and someone decides to set those fields, we'd like to
@ -2222,6 +2405,28 @@ func ValidateTolerations(tolerations []api.Toleration, fldPath *field.Path) fiel
return allErrors
}
func toResourceNames(resources api.ResourceList) []api.ResourceName {
result := []api.ResourceName{}
for resourceName := range resources {
result = append(result, resourceName)
}
return result
}
func toSet(resourceNames []api.ResourceName) sets.String {
result := sets.NewString()
for _, resourceName := range resourceNames {
result.Insert(string(resourceName))
}
return result
}
func toContainerResourcesSet(ctr *api.Container) sets.String {
resourceNames := toResourceNames(ctr.Resources.Requests)
resourceNames = append(resourceNames, toResourceNames(ctr.Resources.Limits)...)
return toSet(resourceNames)
}
// validateContainersOnlyForPod does additional validation for containers on a pod versus a pod template
// it only does additive validation of fields not covered in validateContainers
func validateContainersOnlyForPod(containers []api.Container, fldPath *field.Path) field.ErrorList {
@ -2249,6 +2454,21 @@ func ValidatePod(pod *api.Pod) field.ErrorList {
allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.Containers, specPath.Child("containers"))...)
allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.InitContainers, specPath.Child("initContainers"))...)
if utilfeature.DefaultFeatureGate.Enabled(features.HugePages) {
hugePageResources := sets.NewString()
for i := range pod.Spec.Containers {
resourceSet := toContainerResourcesSet(&pod.Spec.Containers[i])
for resourceStr := range resourceSet {
if v1helper.IsHugePageResourceName(v1.ResourceName(resourceStr)) {
hugePageResources.Insert(resourceStr)
}
}
}
if len(hugePageResources) > 1 {
allErrs = append(allErrs, field.Invalid(specPath, hugePageResources, "must use a single hugepage size in a pod spec"))
}
}
return allErrs
}
@ -2429,7 +2649,7 @@ func ValidatePreferredSchedulingTerms(terms []api.PreferredSchedulingTerm, fldPa
}
// validatePodAffinityTerm tests that the specified podAffinityTerm fields have valid data
func validatePodAffinityTerm(podAffinityTerm api.PodAffinityTerm, allowEmptyTopologyKey bool, fldPath *field.Path) field.ErrorList {
func validatePodAffinityTerm(podAffinityTerm api.PodAffinityTerm, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(podAffinityTerm.LabelSelector, fldPath.Child("matchExpressions"))...)
@ -2438,32 +2658,29 @@ func validatePodAffinityTerm(podAffinityTerm api.PodAffinityTerm, allowEmptyTopo
allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), name, msg))
}
}
if !allowEmptyTopologyKey && len(podAffinityTerm.TopologyKey) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("topologyKey"), "can only be empty for PreferredDuringScheduling pod anti affinity"))
if len(podAffinityTerm.TopologyKey) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("topologyKey"), "can not be empty"))
}
if len(podAffinityTerm.TopologyKey) != 0 {
allErrs = append(allErrs, unversionedvalidation.ValidateLabelName(podAffinityTerm.TopologyKey, fldPath.Child("topologyKey"))...)
}
return allErrs
return append(allErrs, unversionedvalidation.ValidateLabelName(podAffinityTerm.TopologyKey, fldPath.Child("topologyKey"))...)
}
// validatePodAffinityTerms tests that the specified podAffinityTerms fields have valid data
func validatePodAffinityTerms(podAffinityTerms []api.PodAffinityTerm, allowEmptyTopologyKey bool, fldPath *field.Path) field.ErrorList {
func validatePodAffinityTerms(podAffinityTerms []api.PodAffinityTerm, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for i, podAffinityTerm := range podAffinityTerms {
allErrs = append(allErrs, validatePodAffinityTerm(podAffinityTerm, allowEmptyTopologyKey, fldPath.Index(i))...)
allErrs = append(allErrs, validatePodAffinityTerm(podAffinityTerm, fldPath.Index(i))...)
}
return allErrs
}
// validateWeightedPodAffinityTerms tests that the specified weightedPodAffinityTerms fields have valid data
func validateWeightedPodAffinityTerms(weightedPodAffinityTerms []api.WeightedPodAffinityTerm, allowEmptyTopologyKey bool, fldPath *field.Path) field.ErrorList {
func validateWeightedPodAffinityTerms(weightedPodAffinityTerms []api.WeightedPodAffinityTerm, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for j, weightedTerm := range weightedPodAffinityTerms {
if weightedTerm.Weight <= 0 || weightedTerm.Weight > 100 {
allErrs = append(allErrs, field.Invalid(fldPath.Index(j).Child("weight"), weightedTerm.Weight, "must be in the range 1-100"))
}
allErrs = append(allErrs, validatePodAffinityTerm(weightedTerm.PodAffinityTerm, allowEmptyTopologyKey, fldPath.Index(j).Child("podAffinityTerm"))...)
allErrs = append(allErrs, validatePodAffinityTerm(weightedTerm.PodAffinityTerm, fldPath.Index(j).Child("podAffinityTerm"))...)
}
return allErrs
}
@ -2477,13 +2694,11 @@ func validatePodAntiAffinity(podAntiAffinity *api.PodAntiAffinity, fldPath *fiel
// fldPath.Child("requiredDuringSchedulingRequiredDuringExecution"))...)
//}
if podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil {
// empty topologyKey is not allowed for hard pod anti-affinity
allErrs = append(allErrs, validatePodAffinityTerms(podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution, false,
allErrs = append(allErrs, validatePodAffinityTerms(podAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution,
fldPath.Child("requiredDuringSchedulingIgnoredDuringExecution"))...)
}
if podAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution != nil {
// empty topologyKey is allowed for soft pod anti-affinity
allErrs = append(allErrs, validateWeightedPodAffinityTerms(podAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution, true,
allErrs = append(allErrs, validateWeightedPodAffinityTerms(podAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution,
fldPath.Child("preferredDuringSchedulingIgnoredDuringExecution"))...)
}
return allErrs
@ -2498,13 +2713,11 @@ func validatePodAffinity(podAffinity *api.PodAffinity, fldPath *field.Path) fiel
// fldPath.Child("requiredDuringSchedulingRequiredDuringExecution"))...)
//}
if podAffinity.RequiredDuringSchedulingIgnoredDuringExecution != nil {
// empty topologyKey is not allowed for hard pod affinity
allErrs = append(allErrs, validatePodAffinityTerms(podAffinity.RequiredDuringSchedulingIgnoredDuringExecution, false,
allErrs = append(allErrs, validatePodAffinityTerms(podAffinity.RequiredDuringSchedulingIgnoredDuringExecution,
fldPath.Child("requiredDuringSchedulingIgnoredDuringExecution"))...)
}
if podAffinity.PreferredDuringSchedulingIgnoredDuringExecution != nil {
// empty topologyKey is not allowed for soft pod affinity
allErrs = append(allErrs, validateWeightedPodAffinityTerms(podAffinity.PreferredDuringSchedulingIgnoredDuringExecution, false,
allErrs = append(allErrs, validateWeightedPodAffinityTerms(podAffinity.PreferredDuringSchedulingIgnoredDuringExecution,
fldPath.Child("preferredDuringSchedulingIgnoredDuringExecution"))...)
}
return allErrs
@ -2615,7 +2828,6 @@ func ValidatePodSecurityContext(securityContext *api.PodSecurityContext, spec *a
if securityContext != nil {
allErrs = append(allErrs, validateHostNetwork(securityContext.HostNetwork, spec.Containers, specPath.Child("containers"))...)
allErrs = append(allErrs, validateHostNetworkNoHostAliases(securityContext.HostNetwork, spec.HostAliases, specPath)...)
if securityContext.FSGroup != nil {
for _, msg := range validation.IsValidGroupID(*securityContext.FSGroup) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("fsGroup"), *(securityContext.FSGroup), msg))
@ -2729,8 +2941,10 @@ func ValidatePodUpdate(newPod, oldPod *api.Pod) field.ErrorList {
allErrs = append(allErrs, validateOnlyAddedTolerations(newPod.Spec.Tolerations, oldPod.Spec.Tolerations, specPath.Child("tolerations"))...)
if !apiequality.Semantic.DeepEqual(mungedPod.Spec, oldPod.Spec) {
// This diff isn't perfect, but it's a helluva lot better an "I'm not going to tell you what the difference is".
//TODO: Pinpoint the specific field that causes the invalid error after we have strategic merge diff
allErrs = append(allErrs, field.Forbidden(specPath, "pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)"))
specDiff := diff.ObjectDiff(mungedPod.Spec, oldPod.Spec)
allErrs = append(allErrs, field.Forbidden(specPath, fmt.Sprintf("pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n%v", specDiff)))
}
return allErrs
@ -2844,6 +3058,14 @@ func ValidateService(service *api.Service) field.ErrorList {
allErrs = append(allErrs, field.NotSupported(specPath.Child("sessionAffinity"), service.Spec.SessionAffinity, supportedSessionAffinityType.List()))
}
if service.Spec.SessionAffinity == api.ServiceAffinityClientIP {
allErrs = append(allErrs, validateClientIPAffinityConfig(service.Spec.SessionAffinityConfig, specPath.Child("sessionAffinityConfig"))...)
} else if service.Spec.SessionAffinity == api.ServiceAffinityNone {
if service.Spec.SessionAffinityConfig != nil {
allErrs = append(allErrs, field.Forbidden(specPath.Child("sessionAffinityConfig"), fmt.Sprintf("must not be set when session affinity is %s", string(api.ServiceAffinityNone))))
}
}
if helper.IsServiceIPSet(service) {
if ip := net.ParseIP(service.Spec.ClusterIP); ip == nil {
allErrs = append(allErrs, field.Invalid(specPath.Child("clusterIP"), service.Spec.ClusterIP, "must be empty, 'None', or a valid IP address"))
@ -2913,6 +3135,19 @@ func ValidateService(service *api.Service) field.ErrorList {
nodePorts[key] = true
}
// Check for duplicate Ports, considering (protocol,port) pairs
portsPath = specPath.Child("ports")
ports := make(map[api.ServicePort]bool)
for i, port := range service.Spec.Ports {
portPath := portsPath.Index(i)
key := api.ServicePort{Protocol: port.Protocol, Port: port.Port}
_, found := ports[key]
if found {
allErrs = append(allErrs, field.Duplicate(portPath, key))
}
ports[key] = true
}
// Check for duplicate TargetPort
portsPath = specPath.Child("ports")
targetPorts := make(map[api.ServicePort]bool)
@ -2951,7 +3186,6 @@ func ValidateService(service *api.Service) field.ErrorList {
}
allErrs = append(allErrs, validateServiceExternalTrafficFieldsValue(service)...)
allErrs = append(allErrs, validateServiceExternalTrafficAPIVersion(service)...)
return allErrs
}
@ -2999,25 +3233,6 @@ func validateServicePort(sp *api.ServicePort, requireName, isHeadlessService boo
func validateServiceExternalTrafficFieldsValue(service *api.Service) field.ErrorList {
allErrs := field.ErrorList{}
// Check beta annotations.
if l, ok := service.Annotations[api.BetaAnnotationExternalTraffic]; ok {
if l != api.AnnotationValueExternalTrafficLocal &&
l != api.AnnotationValueExternalTrafficGlobal {
allErrs = append(allErrs, field.Invalid(field.NewPath("metadata", "annotations").Key(api.BetaAnnotationExternalTraffic), l,
fmt.Sprintf("ExternalTraffic must be %v or %v", api.AnnotationValueExternalTrafficLocal, api.AnnotationValueExternalTrafficGlobal)))
}
}
if l, ok := service.Annotations[api.BetaAnnotationHealthCheckNodePort]; ok {
p, err := strconv.Atoi(l)
if err != nil {
allErrs = append(allErrs, field.Invalid(field.NewPath("metadata", "annotations").Key(api.BetaAnnotationHealthCheckNodePort), l,
"HealthCheckNodePort must be a valid port number"))
} else if p <= 0 {
allErrs = append(allErrs, field.Invalid(field.NewPath("metadata", "annotations").Key(api.BetaAnnotationHealthCheckNodePort), l,
"HealthCheckNodePort must be greater than 0"))
}
}
// Check first class fields.
if service.Spec.ExternalTrafficPolicy != "" &&
service.Spec.ExternalTrafficPolicy != api.ServiceExternalTrafficPolicyTypeCluster &&
@ -3033,54 +3248,6 @@ func validateServiceExternalTrafficFieldsValue(service *api.Service) field.Error
return allErrs
}
// serviceExternalTrafficStatus stores flags indicating whether ExternalTraffic
// related beta annotations and GA fields are set on service.
type serviceExternalTrafficStatus struct {
betaExternalTrafficIsSet bool
betaHealthCheckIsSet bool
gaExternalTrafficIsSet bool
gaHealthCheckIsSet bool
}
func (s *serviceExternalTrafficStatus) useBetaExternalTrafficWithGA() bool {
return s.betaExternalTrafficIsSet && (s.gaExternalTrafficIsSet || s.gaHealthCheckIsSet)
}
func (s *serviceExternalTrafficStatus) useBetaHealthCheckWithGA() bool {
return s.betaHealthCheckIsSet && (s.gaExternalTrafficIsSet || s.gaHealthCheckIsSet)
}
func getServiceExternalTrafficStatus(service *api.Service) *serviceExternalTrafficStatus {
s := serviceExternalTrafficStatus{}
_, s.betaExternalTrafficIsSet = service.Annotations[api.BetaAnnotationExternalTraffic]
_, s.betaHealthCheckIsSet = service.Annotations[api.BetaAnnotationHealthCheckNodePort]
s.gaExternalTrafficIsSet = service.Spec.ExternalTrafficPolicy != ""
s.gaHealthCheckIsSet = service.Spec.HealthCheckNodePort != 0
return &s
}
// validateServiceExternalTrafficAPIVersion checks if user mixes ExternalTraffic
// API versions.
func validateServiceExternalTrafficAPIVersion(service *api.Service) field.ErrorList {
allErrs := field.ErrorList{}
status := getServiceExternalTrafficStatus(service)
if status.useBetaExternalTrafficWithGA() {
fieldPath := field.NewPath("metadata", "annotations").Key(api.BetaAnnotationExternalTraffic)
msg := fmt.Sprintf("please replace the beta annotation with 'ExternalTrafficPolicy' field")
allErrs = append(allErrs, field.Invalid(fieldPath, api.BetaAnnotationExternalTraffic, msg))
}
if status.useBetaHealthCheckWithGA() {
fieldPath := field.NewPath("metadata", "annotations").Key(api.BetaAnnotationHealthCheckNodePort)
msg := fmt.Sprintf("please replace the beta annotation with 'HealthCheckNodePort' field")
allErrs = append(allErrs, field.Invalid(fieldPath, api.BetaAnnotationHealthCheckNodePort, msg))
}
return allErrs
}
// ValidateServiceExternalTrafficFieldsCombination validates if ExternalTrafficPolicy,
// HealthCheckNodePort and Type combination are legal. For update, it should be called
// after clearing externalTraffic related fields for the ease of transitioning between
@ -3318,17 +3485,57 @@ func ValidateNode(node *api.Node) field.ErrorList {
allErrs = append(allErrs, validateNodeTaints(node.Spec.Taints, fldPath.Child("taints"))...)
}
// Only validate spec. All status fields are optional and can be updated later.
// Only validate spec.
// All status fields are optional and can be updated later.
// That said, if specified, we need to ensure they are valid.
allErrs = append(allErrs, ValidateNodeResources(node)...)
// external ID is required.
if len(node.Spec.ExternalID) == 0 {
allErrs = append(allErrs, field.Required(field.NewPath("spec", "externalID"), ""))
}
// Only allow Node.Spec.ConfigSource to be set if the DynamicKubeletConfig feature gate is enabled
if node.Spec.ConfigSource != nil && !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "configSource"), "configSource may only be set if the DynamicKubeletConfig feature gate is enabled)"))
}
// TODO(rjnagal): Ignore PodCIDR till its completely implemented.
return allErrs
}
// ValidateNodeResources is used to make sure a node has valid capacity and allocatable values.
func ValidateNodeResources(node *api.Node) field.ErrorList {
allErrs := field.ErrorList{}
// Validate resource quantities in capacity.
hugePageSizes := sets.NewString()
for k, v := range node.Status.Capacity {
resPath := field.NewPath("status", "capacity", string(k))
allErrs = append(allErrs, ValidateResourceQuantityValue(string(k), v, resPath)...)
// track any huge page size that has a positive value
if helper.IsHugePageResourceName(k) && v.Value() > int64(0) {
hugePageSizes.Insert(string(k))
}
if len(hugePageSizes) > 1 {
allErrs = append(allErrs, field.Invalid(resPath, v, "may not have pre-allocated hugepages for multiple page sizes"))
}
}
// Validate resource quantities in allocatable.
hugePageSizes = sets.NewString()
for k, v := range node.Status.Allocatable {
resPath := field.NewPath("status", "allocatable", string(k))
allErrs = append(allErrs, ValidateResourceQuantityValue(string(k), v, resPath)...)
// track any huge page size that has a positive value
if helper.IsHugePageResourceName(k) && v.Value() > int64(0) {
hugePageSizes.Insert(string(k))
}
if len(hugePageSizes) > 1 {
allErrs = append(allErrs, field.Invalid(resPath, v, "may not have pre-allocated hugepages for multiple page sizes"))
}
}
return allErrs
}
// ValidateNodeUpdate tests to make sure a node update can be applied. Modifies oldNode.
func ValidateNodeUpdate(node, oldNode *api.Node) field.ErrorList {
fldPath := field.NewPath("metadata")
@ -3341,18 +3548,9 @@ func ValidateNodeUpdate(node, oldNode *api.Node) field.ErrorList {
// allErrs = append(allErrs, field.Invalid("status", node.Status, "must be empty"))
// }
// Validate resource quantities in capacity.
for k, v := range node.Status.Capacity {
resPath := field.NewPath("status", "capacity", string(k))
allErrs = append(allErrs, ValidateResourceQuantityValue(string(k), v, resPath)...)
}
// Validate resource quantities in allocatable.
for k, v := range node.Status.Allocatable {
resPath := field.NewPath("status", "allocatable", string(k))
allErrs = append(allErrs, ValidateResourceQuantityValue(string(k), v, resPath)...)
}
allErrs = append(allErrs, ValidateNodeResources(node)...)
// Validte no duplicate addresses in node status.
// Validate no duplicate addresses in node status.
addresses := make(map[api.NodeAddress]bool)
for i, address := range node.Status.Addresses {
if _, ok := addresses[address]; ok {
@ -3369,6 +3567,16 @@ func ValidateNodeUpdate(node, oldNode *api.Node) field.ErrorList {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "podCIDR"), "node updates may not change podCIDR except from \"\" to valid"))
}
}
// Allow controller manager updating provider ID when not set
if len(oldNode.Spec.ProviderID) == 0 {
oldNode.Spec.ProviderID = node.Spec.ProviderID
} else {
if oldNode.Spec.ProviderID != node.Spec.ProviderID {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "providerID"), "node updates may not change providerID except from \"\" to valid"))
}
}
// TODO: move reset function to its own location
// Ignore metadata changes now that they have been tested
oldNode.ObjectMeta = node.ObjectMeta
@ -3385,10 +3593,16 @@ func ValidateNodeUpdate(node, oldNode *api.Node) field.ErrorList {
}
oldNode.Spec.Taints = node.Spec.Taints
// Allow updates to Node.Spec.ConfigSource if DynamicKubeletConfig feature gate is enabled
if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) {
oldNode.Spec.ConfigSource = node.Spec.ConfigSource
}
// We made allowed changes to oldNode, and now we compare oldNode to node. Any remaining differences indicate changes to protected fields.
// TODO: Add a 'real' error type for this error and provide print actual diffs.
if !apiequality.Semantic.DeepEqual(oldNode, node) {
glog.V(4).Infof("Update failed validation %#v vs %#v", oldNode, node)
allErrs = append(allErrs, field.Forbidden(field.NewPath(""), "node updates may only change labels, taints or capacity"))
allErrs = append(allErrs, field.Forbidden(field.NewPath(""), "node updates may only change labels, taints, or capacity (or configSource, if the DynamicKubeletConfig feature gate is enabled)"))
}
return allErrs
@ -3397,6 +3611,12 @@ func ValidateNodeUpdate(node, oldNode *api.Node) field.ErrorList {
// Validate compute resource typename.
// Refer to docs/design/resources.md for more details.
func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
// Opaque integer resources (OIR) deprecation began in v1.8
// TODO: Remove warning after OIR deprecation cycle.
if helper.IsOpaqueIntResourceName(api.ResourceName(value)) {
glog.Errorf("DEPRECATION WARNING! Opaque integer resources are deprecated starting with v1.8: %s", value)
}
allErrs := field.ErrorList{}
for _, msg := range validation.IsQualifiedName(value) {
allErrs = append(allErrs, field.Invalid(fldPath, value, msg))
@ -3411,7 +3631,7 @@ func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
}
}
return field.ErrorList{}
return allErrs
}
// Validate container resource name
@ -3424,19 +3644,32 @@ func validateContainerResourceName(value string, fldPath *field.Path) field.Erro
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers"))
}
}
return field.ErrorList{}
return allErrs
}
// isLocalStorageResource checks whether the resource is local ephemeral storage
func isLocalStorageResource(name string) bool {
if name == string(api.ResourceEphemeralStorage) || name == string(api.ResourceRequestsEphemeralStorage) ||
name == string(api.ResourceLimitsEphemeralStorage) {
return true
} else {
return false
}
}
// Validate resource names that can go in a resource quota
// Refer to docs/design/resources.md for more details.
func ValidateResourceQuotaResourceName(value string, fldPath *field.Path) field.ErrorList {
allErrs := validateResourceName(value, fldPath)
if isLocalStorageResource(value) && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
return append(allErrs, field.Forbidden(fldPath, "ResourceEphemeralStorage field disabled by feature-gate for ResourceQuota"))
}
if len(strings.Split(value, "/")) == 1 {
if !helper.IsStandardQuotaResourceName(value) {
return append(allErrs, field.Invalid(fldPath, value, isInvalidQuotaResource))
}
}
return field.ErrorList{}
return allErrs
}
// Validate limit range types
@ -3461,6 +3694,10 @@ func validateLimitRangeTypeName(value string, fldPath *field.Path) field.ErrorLi
// Validate limit range resource name
// limit types (other than Pod/Container) could contain storage not just cpu or memory
func validateLimitRangeResourceName(limitType api.LimitType, value string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if value == string(api.ResourceEphemeralStorage) && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
return append(allErrs, field.Forbidden(fldPath, "ResourceEphemeralStorage field disabled by feature-gate for Resource LimitRange"))
}
switch limitType {
case api.LimitTypePod, api.LimitTypeContainer:
return validateContainerResourceName(value, fldPath)
@ -3751,19 +3988,13 @@ func ValidateResourceRequirements(requirements *api.ResourceRequirements, fldPat
// Validate resource quantity.
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
// Check that request <= limit.
requestQuantity, exists := requirements.Requests[resourceName]
if exists {
// For GPUs, not only requests can't exceed limits, they also can't be lower, i.e. must be equal.
if resourceName == api.ResourceNvidiaGPU && quantity.Cmp(requestQuantity) != 0 {
allErrs = append(allErrs, field.Invalid(reqPath, requestQuantity.String(), fmt.Sprintf("must be equal to %s limit", api.ResourceNvidiaGPU)))
} else if quantity.Cmp(requestQuantity) < 0 {
allErrs = append(allErrs, field.Invalid(limPath, quantity.String(), fmt.Sprintf("must be greater than or equal to %s request", resourceName)))
}
if resourceName == api.ResourceEphemeralStorage && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
allErrs = append(allErrs, field.Forbidden(limPath, "ResourceEphemeralStorage field disabled by feature-gate for ResourceRequirements"))
}
if resourceName == api.ResourceStorageOverlay && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
allErrs = append(allErrs, field.Forbidden(limPath, "ResourceStorageOverlay field disabled by feature-gate for ResourceRequirements"))
if helper.IsHugePageResourceName(resourceName) && !utilfeature.DefaultFeatureGate.Enabled(features.HugePages) {
allErrs = append(allErrs, field.Forbidden(limPath, fmt.Sprintf("%s field disabled by feature-gate for ResourceRequirements", resourceName)))
}
}
for resourceName, quantity := range requirements.Requests {
fldPath := reqPath.Key(string(resourceName))
@ -3771,6 +4002,19 @@ func ValidateResourceRequirements(requirements *api.ResourceRequirements, fldPat
allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...)
// Validate resource quantity.
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
// Check that request <= limit.
limitQuantity, exists := requirements.Limits[resourceName]
if exists {
// For GPUs, not only requests can't exceed limits, they also can't be lower, i.e. must be equal.
if quantity.Cmp(limitQuantity) != 0 && !helper.IsOvercommitAllowed(resourceName) {
allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s limit", api.ResourceNvidiaGPU)))
} else if quantity.Cmp(limitQuantity) > 0 {
allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be less than or equal to %s limit", resourceName)))
}
} else if resourceName == api.ResourceNvidiaGPU {
allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s request", api.ResourceNvidiaGPU)))
}
}
return allErrs
@ -4144,6 +4388,21 @@ func ValidateSecurityContext(sc *api.SecurityContext, fldPath *field.Path) field
allErrs = append(allErrs, field.Invalid(fldPath.Child("runAsUser"), *sc.RunAsUser, isNegativeErrorMsg))
}
}
if sc.AllowPrivilegeEscalation != nil && !*sc.AllowPrivilegeEscalation {
if sc.Privileged != nil && *sc.Privileged {
allErrs = append(allErrs, field.Invalid(fldPath, sc, "cannot set `allowPrivilegeEscalation` to false and `privileged` to true"))
}
if sc.Capabilities != nil {
for _, cap := range sc.Capabilities.Add {
if string(cap) == "CAP_SYS_ADMIN" {
allErrs = append(allErrs, field.Invalid(fldPath, sc, "cannot set `allowPrivilegeEscalation` to false and `capabilities.Add` CAP_SYS_ADMIN"))
}
}
}
}
return allErrs
}

File diff suppressed because it is too large Load diff