Update dependencies to K8s 1.8
This commit is contained in:
parent
ba6c89672d
commit
6a59f4c9a2
1114 changed files with 160955 additions and 262845 deletions
25
vendor/k8s.io/kubernetes/pkg/api/BUILD
generated
vendored
25
vendor/k8s.io/kubernetes/pkg/api/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/api/OWNERS
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/api/OWNERS
generated
vendored
|
|
@ -3,6 +3,8 @@ approvers:
|
|||
- lavalamp
|
||||
- smarterclayton
|
||||
- thockin
|
||||
- liggitt
|
||||
# - bgrant0607 # manual escalations only
|
||||
reviewers:
|
||||
- thockin
|
||||
- lavalamp
|
||||
|
|
|
|||
18
vendor/k8s.io/kubernetes/pkg/api/annotation_key_constants.go
generated
vendored
18
vendor/k8s.io/kubernetes/pkg/api/annotation_key_constants.go
generated
vendored
|
|
@ -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"
|
||||
)
|
||||
|
|
|
|||
4
vendor/k8s.io/kubernetes/pkg/api/helper/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/api/helper/BUILD
generated
vendored
|
|
@ -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",
|
||||
|
|
|
|||
67
vendor/k8s.io/kubernetes/pkg/api/helper/helpers.go
generated
vendored
67
vendor/k8s.io/kubernetes/pkg/api/helper/helpers.go
generated
vendored
|
|
@ -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
|
||||
|
|
|
|||
4
vendor/k8s.io/kubernetes/pkg/api/install/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/api/install/BUILD
generated
vendored
|
|
@ -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",
|
||||
|
|
|
|||
1
vendor/k8s.io/kubernetes/pkg/api/install/install.go
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/api/install/install.go
generated
vendored
|
|
@ -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",
|
||||
|
|
|
|||
1
vendor/k8s.io/kubernetes/pkg/api/register.go
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/api/register.go
generated
vendored
|
|
@ -85,6 +85,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
|||
&ServiceProxyOptions{},
|
||||
&NodeList{},
|
||||
&Node{},
|
||||
&NodeConfigSource{},
|
||||
&NodeProxyOptions{},
|
||||
&Endpoints{},
|
||||
&EndpointsList{},
|
||||
|
|
|
|||
4
vendor/k8s.io/kubernetes/pkg/api/resource.go
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/api/resource.go
generated
vendored
|
|
@ -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{}
|
||||
|
|
|
|||
7
vendor/k8s.io/kubernetes/pkg/api/service/BUILD
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/api/service/BUILD
generated
vendored
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
64
vendor/k8s.io/kubernetes/pkg/api/service/util.go
generated
vendored
64
vendor/k8s.io/kubernetes/pkg/api/service/util.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
261
vendor/k8s.io/kubernetes/pkg/api/types.go
generated
vendored
261
vendor/k8s.io/kubernetes/pkg/api/types.go
generated
vendored
|
|
@ -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.
|
||||
|
|
|
|||
4
vendor/k8s.io/kubernetes/pkg/api/util/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/api/util/BUILD
generated
vendored
|
|
@ -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(
|
||||
|
|
|
|||
7
vendor/k8s.io/kubernetes/pkg/api/v1/BUILD
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/api/v1/BUILD
generated
vendored
|
|
@ -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",
|
||||
|
|
|
|||
289
vendor/k8s.io/kubernetes/pkg/api/v1/conversion.go
generated
vendored
289
vendor/k8s.io/kubernetes/pkg/api/v1/conversion.go
generated
vendored
|
|
@ -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
|
||||
|
|
|
|||
25
vendor/k8s.io/kubernetes/pkg/api/v1/defaults.go
generated
vendored
25
vendor/k8s.io/kubernetes/pkg/api/v1/defaults.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
vendor/k8s.io/kubernetes/pkg/api/v1/helper/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/api/v1/helper/BUILD
generated
vendored
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
51
vendor/k8s.io/kubernetes/pkg/api/v1/helper/helpers.go
generated
vendored
51
vendor/k8s.io/kubernetes/pkg/api/v1/helper/helpers.go
generated
vendored
|
|
@ -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 {
|
||||
|
|
|
|||
4
vendor/k8s.io/kubernetes/pkg/api/v1/pod/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/api/v1/pod/BUILD
generated
vendored
|
|
@ -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",
|
||||
|
|
|
|||
66
vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go
generated
vendored
66
vendor/k8s.io/kubernetes/pkg/api/v1/pod/util.go
generated
vendored
|
|
@ -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.
|
||||
|
|
|
|||
7
vendor/k8s.io/kubernetes/pkg/api/v1/service/BUILD
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/api/v1/service/BUILD
generated
vendored
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
68
vendor/k8s.io/kubernetes/pkg/api/v1/service/util.go
generated
vendored
68
vendor/k8s.io/kubernetes/pkg/api/v1/service/util.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
443
vendor/k8s.io/kubernetes/pkg/api/v1/zz_generated.conversion.go
generated
vendored
443
vendor/k8s.io/kubernetes/pkg/api/v1/zz_generated.conversion.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
12
vendor/k8s.io/kubernetes/pkg/api/v1/zz_generated.defaults.go
generated
vendored
12
vendor/k8s.io/kubernetes/pkg/api/v1/zz_generated.defaults.go
generated
vendored
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
33
vendor/k8s.io/kubernetes/pkg/api/validation/BUILD
generated
vendored
33
vendor/k8s.io/kubernetes/pkg/api/validation/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
|
|
|
|||
435
vendor/k8s.io/kubernetes/pkg/api/validation/schema.go
generated
vendored
435
vendor/k8s.io/kubernetes/pkg/api/validation/schema.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
567
vendor/k8s.io/kubernetes/pkg/api/validation/validation.go
generated
vendored
567
vendor/k8s.io/kubernetes/pkg/api/validation/validation.go
generated
vendored
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
1859
vendor/k8s.io/kubernetes/pkg/api/zz_generated.deepcopy.go
generated
vendored
1859
vendor/k8s.io/kubernetes/pkg/api/zz_generated.deepcopy.go
generated
vendored
File diff suppressed because it is too large
Load diff
6
vendor/k8s.io/kubernetes/pkg/apis/extensions/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/apis/extensions/BUILD
generated
vendored
|
|
@ -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"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
|
|
@ -24,9 +21,9 @@ go_library(
|
|||
"types.go",
|
||||
"zz_generated.deepcopy.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/networking: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",
|
||||
|
|
@ -47,6 +44,7 @@ filegroup(
|
|||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/apis/extensions/fuzzer:all-srcs",
|
||||
"//pkg/apis/extensions/install:all-srcs",
|
||||
"//pkg/apis/extensions/v1beta1:all-srcs",
|
||||
"//pkg/apis/extensions/validation:all-srcs",
|
||||
|
|
|
|||
5
vendor/k8s.io/kubernetes/pkg/apis/extensions/register.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/apis/extensions/register.go
generated
vendored
|
|
@ -19,6 +19,7 @@ package extensions
|
|||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/kubernetes/pkg/apis/networking"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
|
|
@ -63,8 +64,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
|||
&ReplicaSetList{},
|
||||
&PodSecurityPolicy{},
|
||||
&PodSecurityPolicyList{},
|
||||
&NetworkPolicy{},
|
||||
&NetworkPolicyList{},
|
||||
&networking.NetworkPolicy{},
|
||||
&networking.NetworkPolicyList{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
147
vendor/k8s.io/kubernetes/pkg/apis/extensions/types.go
generated
vendored
147
vendor/k8s.io/kubernetes/pkg/apis/extensions/types.go
generated
vendored
|
|
@ -166,6 +166,8 @@ type ThirdPartyResourceData struct {
|
|||
}
|
||||
|
||||
// +genclient
|
||||
// +genclient:method=GetScale,verb=get,subresource=scale,result=Scale
|
||||
// +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
type Deployment struct {
|
||||
|
|
@ -216,6 +218,7 @@ type DeploymentSpec struct {
|
|||
// +optional
|
||||
Paused bool
|
||||
|
||||
// DEPRECATED.
|
||||
// The config this deployment is rolling back to. Will be cleared after rollback is done.
|
||||
// +optional
|
||||
RollbackTo *RollbackConfig
|
||||
|
|
@ -223,15 +226,16 @@ type DeploymentSpec struct {
|
|||
// The maximum time in seconds for a deployment to make progress before it
|
||||
// is considered to be failed. The deployment controller will continue to
|
||||
// process failed deployments and a condition with a ProgressDeadlineExceeded
|
||||
// reason will be surfaced in the deployment status. Once autoRollback is
|
||||
// implemented, the deployment controller will automatically rollback failed
|
||||
// deployments. Note that progress will not be estimated during the time a
|
||||
// deployment is paused. This is not set by default.
|
||||
// reason will be surfaced in the deployment status. Note that progress will
|
||||
// not be estimated during the time a deployment is paused. This is not set
|
||||
// by default.
|
||||
// +optional
|
||||
ProgressDeadlineSeconds *int32
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// DEPRECATED.
|
||||
// DeploymentRollback stores the information required to rollback a deployment.
|
||||
type DeploymentRollback struct {
|
||||
metav1.TypeMeta
|
||||
|
|
@ -244,6 +248,7 @@ type DeploymentRollback struct {
|
|||
RollbackTo RollbackConfig
|
||||
}
|
||||
|
||||
// DEPRECATED.
|
||||
type RollbackConfig struct {
|
||||
// The revision to rollback to. If set to 0, rollback to the last revision.
|
||||
// +optional
|
||||
|
|
@ -331,7 +336,9 @@ type DeploymentStatus struct {
|
|||
// +optional
|
||||
AvailableReplicas int32
|
||||
|
||||
// Total number of unavailable pods targeted by this deployment.
|
||||
// Total number of unavailable pods targeted by this deployment. This is the total number of
|
||||
// pods that are still required for the deployment to have 100% available capacity. They may
|
||||
// either be pods that are running but not yet available or pods that still have not been created.
|
||||
// +optional
|
||||
UnavailableReplicas int32
|
||||
|
||||
|
|
@ -342,7 +349,7 @@ type DeploymentStatus struct {
|
|||
// field as a collision avoidance mechanism when it needs to create the name for the
|
||||
// newest ReplicaSet.
|
||||
// +optional
|
||||
CollisionCount *int64
|
||||
CollisionCount *int32
|
||||
}
|
||||
|
||||
type DeploymentConditionType string
|
||||
|
|
@ -516,7 +523,7 @@ type DaemonSetStatus struct {
|
|||
// uses this field as a collision avoidance mechanism when it needs to
|
||||
// create the name for the newest ControllerRevision.
|
||||
// +optional
|
||||
CollisionCount *int64
|
||||
CollisionCount *int32
|
||||
}
|
||||
|
||||
// +genclient
|
||||
|
|
@ -748,6 +755,8 @@ type IngressBackend struct {
|
|||
}
|
||||
|
||||
// +genclient
|
||||
// +genclient:method=GetScale,verb=get,subresource=scale,result=Scale
|
||||
// +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ReplicaSet represents the configuration of a replica set.
|
||||
|
|
@ -889,6 +898,7 @@ type PodSecurityPolicySpec struct {
|
|||
// AllowedCapabilities is a list of capabilities that can be requested to add to the container.
|
||||
// Capabilities in this field may be added at the pod author's discretion.
|
||||
// You must not list a capability in both AllowedCapabilities and RequiredDropCapabilities.
|
||||
// To allow all capabilities you may use '*'.
|
||||
// +optional
|
||||
AllowedCapabilities []api.Capability
|
||||
// Volumes is a white list of allowed volume plugins. Empty indicates that all plugins
|
||||
|
|
@ -922,6 +932,30 @@ type PodSecurityPolicySpec struct {
|
|||
// will not be forced to.
|
||||
// +optional
|
||||
ReadOnlyRootFilesystem bool
|
||||
// DefaultAllowPrivilegeEscalation controls the default setting for whether a
|
||||
// process can gain more privileges than its parent process.
|
||||
// +optional
|
||||
DefaultAllowPrivilegeEscalation *bool
|
||||
// AllowPrivilegeEscalation determines if a pod can request to allow
|
||||
// privilege escalation.
|
||||
// +optional
|
||||
AllowPrivilegeEscalation bool
|
||||
// AllowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.
|
||||
// +optional
|
||||
AllowedHostPaths []AllowedHostPath
|
||||
}
|
||||
|
||||
// AllowedHostPath defines the host volume conditions that will be enabled by a policy
|
||||
// for pods to use. It requires the path prefix to be defined.
|
||||
type AllowedHostPath struct {
|
||||
// PathPrefix is the path prefix that the host volume must match.
|
||||
// PathPrefix does not support `*`.
|
||||
// Trailing slashes are trimmed when validating the path prefix with a host path.
|
||||
//
|
||||
// Examples:
|
||||
// `/foo` would allow `/foo`, `/foo/` and `/foo/bar`
|
||||
// `/foo` would not allow `/food` or `/etc/foo`
|
||||
PathPrefix string
|
||||
}
|
||||
|
||||
// HostPortRange defines a range of host ports that will be enabled by a policy
|
||||
|
|
@ -933,6 +967,10 @@ type HostPortRange struct {
|
|||
Max int
|
||||
}
|
||||
|
||||
// AllowAllCapabilities can be used as a value for the PodSecurityPolicy.AllowAllCapabilities
|
||||
// field and means that any capabilities are allowed to be requested.
|
||||
var AllowAllCapabilities api.Capability = "*"
|
||||
|
||||
// FSType gives strong typing to different file systems that are used by volumes.
|
||||
type FSType string
|
||||
|
||||
|
|
@ -1080,98 +1118,3 @@ type PodSecurityPolicyList struct {
|
|||
|
||||
Items []PodSecurityPolicy
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// NetworkPolicy describes what network traffic is allowed for a set of Pods
|
||||
type NetworkPolicy struct {
|
||||
metav1.TypeMeta
|
||||
// +optional
|
||||
metav1.ObjectMeta
|
||||
|
||||
// Specification of the desired behavior for this NetworkPolicy.
|
||||
// +optional
|
||||
Spec NetworkPolicySpec
|
||||
}
|
||||
|
||||
type NetworkPolicySpec struct {
|
||||
// Selects the pods to which this NetworkPolicy object applies. The array of ingress rules
|
||||
// is applied to any pods selected by this field. Multiple network policies can select the
|
||||
// same set of pods. In this case, the ingress rules for each are combined additively.
|
||||
// This field is NOT optional and follows standard label selector semantics.
|
||||
// An empty podSelector matches all pods in this namespace.
|
||||
PodSelector metav1.LabelSelector
|
||||
|
||||
// List of ingress rules to be applied to the selected pods.
|
||||
// Traffic is allowed to a pod if there are no NetworkPolicies selecting the pod
|
||||
// OR if the traffic source is the pod's local node,
|
||||
// OR if the traffic matches at least one ingress rule across all of the NetworkPolicy
|
||||
// objects whose podSelector matches the pod.
|
||||
// If this field is empty then this NetworkPolicy does not allow any traffic
|
||||
// (and serves solely to ensure that the pods it selects are isolated by default).
|
||||
// +optional
|
||||
Ingress []NetworkPolicyIngressRule
|
||||
}
|
||||
|
||||
// This NetworkPolicyIngressRule matches traffic if and only if the traffic matches both ports AND from.
|
||||
type NetworkPolicyIngressRule struct {
|
||||
// List of ports which should be made accessible on the pods selected for this rule.
|
||||
// Each item in this list is combined using a logical OR.
|
||||
// If this field is empty or missing, this rule matches all ports (traffic not restricted by port).
|
||||
// If this field is present and contains at least one item, then this rule allows traffic
|
||||
// only if the traffic matches at least one port in the list.
|
||||
// +optional
|
||||
Ports []NetworkPolicyPort
|
||||
|
||||
// List of sources which should be able to access the pods selected for this rule.
|
||||
// Items in this list are combined using a logical OR operation.
|
||||
// If this field is empty or missing, this rule matches all sources (traffic not restricted by source).
|
||||
// If this field is present and contains at least on item, this rule allows traffic only if the
|
||||
// traffic matches at least one item in the from list.
|
||||
// +optional
|
||||
From []NetworkPolicyPeer
|
||||
}
|
||||
|
||||
type NetworkPolicyPort struct {
|
||||
// Optional. The protocol (TCP or UDP) which traffic must match.
|
||||
// If not specified, this field defaults to TCP.
|
||||
// +optional
|
||||
Protocol *api.Protocol
|
||||
|
||||
// If specified, the port on the given protocol. This can
|
||||
// either be a numerical or named port on a pod. If this field is not provided,
|
||||
// this matches all port names and numbers.
|
||||
// If present, only traffic on the specified protocol AND port
|
||||
// will be matched.
|
||||
// +optional
|
||||
Port *intstr.IntOrString
|
||||
}
|
||||
|
||||
type NetworkPolicyPeer struct {
|
||||
// Exactly one of the following must be specified.
|
||||
|
||||
// This is a label selector which selects Pods in this namespace.
|
||||
// This field follows standard label selector semantics.
|
||||
// If present but empty, this selector selects all pods in this namespace.
|
||||
// +optional
|
||||
PodSelector *metav1.LabelSelector
|
||||
|
||||
// Selects Namespaces using cluster scoped-labels. This
|
||||
// matches all pods in all namespaces selected by this label selector.
|
||||
// This field follows standard label selector semantics.
|
||||
// If present but empty, this selector selects all namespaces.
|
||||
// +optional
|
||||
NamespaceSelector *metav1.LabelSelector
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// NetworkPolicyList is a list of NetworkPolicy objects.
|
||||
type NetworkPolicyList struct {
|
||||
metav1.TypeMeta
|
||||
// +optional
|
||||
metav1.ListMeta
|
||||
|
||||
Items []NetworkPolicy
|
||||
}
|
||||
|
|
|
|||
744
vendor/k8s.io/kubernetes/pkg/apis/extensions/zz_generated.deepcopy.go
generated
vendored
744
vendor/k8s.io/kubernetes/pkg/apis/extensions/zz_generated.deepcopy.go
generated
vendored
File diff suppressed because it is too large
Load diff
43
vendor/k8s.io/kubernetes/pkg/apis/networking/BUILD
generated
vendored
Normal file
43
vendor/k8s.io/kubernetes/pkg/apis/networking/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
"zz_generated.deepcopy.go",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/api: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",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/apis/networking/fuzzer:all-srcs",
|
||||
"//pkg/apis/networking/install:all-srcs",
|
||||
"//pkg/apis/networking/v1:all-srcs",
|
||||
"//pkg/apis/networking/validation:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
4
vendor/k8s.io/kubernetes/pkg/apis/networking/OWNERS
generated
vendored
Executable file
4
vendor/k8s.io/kubernetes/pkg/apis/networking/OWNERS
generated
vendored
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
reviewers:
|
||||
- caseydavenport
|
||||
- danwinship
|
||||
- thockin
|
||||
19
vendor/k8s.io/kubernetes/pkg/apis/networking/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/apis/networking/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2017 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.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +groupName=networking.k8s.io
|
||||
package networking
|
||||
51
vendor/k8s.io/kubernetes/pkg/apis/networking/register.go
generated
vendored
Normal file
51
vendor/k8s.io/kubernetes/pkg/apis/networking/register.go
generated
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright 2017 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 networking
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "networking.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||
|
||||
// Kind takes an unqualified kind and returns a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&NetworkPolicy{},
|
||||
&NetworkPolicyList{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
191
vendor/k8s.io/kubernetes/pkg/apis/networking/types.go
generated
vendored
Normal file
191
vendor/k8s.io/kubernetes/pkg/apis/networking/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
Copyright 2017 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 networking
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// NetworkPolicy describes what network traffic is allowed for a set of Pods
|
||||
type NetworkPolicy struct {
|
||||
metav1.TypeMeta
|
||||
// +optional
|
||||
metav1.ObjectMeta
|
||||
|
||||
// Specification of the desired behavior for this NetworkPolicy.
|
||||
// +optional
|
||||
Spec NetworkPolicySpec
|
||||
}
|
||||
|
||||
// Policy Type string describes the NetworkPolicy type
|
||||
// This type is beta-level in 1.8
|
||||
type PolicyType string
|
||||
|
||||
const (
|
||||
// PolicyTypeIngress is a NetworkPolicy that affects ingress traffic on selected pods
|
||||
PolicyTypeIngress PolicyType = "Ingress"
|
||||
// PolicyTypeEgress is a NetworkPolicy that affects egress traffic on selected pods
|
||||
PolicyTypeEgress PolicyType = "Egress"
|
||||
)
|
||||
|
||||
// NetworkPolicySpec provides the specification of a NetworkPolicy
|
||||
type NetworkPolicySpec struct {
|
||||
// Selects the pods to which this NetworkPolicy object applies. The array of
|
||||
// ingress rules is applied to any pods selected by this field. Multiple network
|
||||
// policies can select the same set of pods. In this case, the ingress rules for
|
||||
// each are combined additively. This field is NOT optional and follows standard
|
||||
// label selector semantics. An empty podSelector matches all pods in this
|
||||
// namespace.
|
||||
PodSelector metav1.LabelSelector
|
||||
|
||||
// List of ingress rules to be applied to the selected pods. Traffic is allowed to
|
||||
// a pod if there are no NetworkPolicies selecting the pod
|
||||
// (and cluster policy otherwise allows the traffic), OR if the traffic source is
|
||||
// the pod's local node, OR if the traffic matches at least one ingress rule
|
||||
// across all of the NetworkPolicy objects whose podSelector matches the pod. If
|
||||
// this field is empty then this NetworkPolicy does not allow any traffic (and serves
|
||||
// solely to ensure that the pods it selects are isolated by default)
|
||||
// +optional
|
||||
Ingress []NetworkPolicyIngressRule
|
||||
|
||||
// List of egress rules to be applied to the selected pods. Outgoing traffic is
|
||||
// allowed if there are no NetworkPolicies selecting the pod (and cluster policy
|
||||
// otherwise allows the traffic), OR if the traffic matches at least one egress rule
|
||||
// across all of the NetworkPolicy objects whose podSelector matches the pod. If
|
||||
// this field is empty then this NetworkPolicy limits all outgoing traffic (and serves
|
||||
// solely to ensure that the pods it selects are isolated by default).
|
||||
// This field is beta-level in 1.8
|
||||
// +optional
|
||||
Egress []NetworkPolicyEgressRule
|
||||
|
||||
// List of rule types that the NetworkPolicy relates to.
|
||||
// Valid options are Ingress, Egress, or Ingress,Egress.
|
||||
// If this field is not specified, it will default based on the existence of Ingress or Egress rules;
|
||||
// policies that contain an Egress section are assumed to affect Egress, and all policies
|
||||
// (whether or not they contain an Ingress section) are assumed to affect Ingress.
|
||||
// If you want to write an egress-only policy, you must explicitly specify policyTypes [ "Egress" ].
|
||||
// Likewise, if you want to write a policy that specifies that no egress is allowed,
|
||||
// you must specify a policyTypes value that include "Egress" (since such a policy would not include
|
||||
// an Egress section and would otherwise default to just [ "Ingress" ]).
|
||||
// This field is beta-level in 1.8
|
||||
// +optional
|
||||
PolicyTypes []PolicyType
|
||||
}
|
||||
|
||||
// NetworkPolicyIngressRule describes a particular set of traffic that is allowed to the pods
|
||||
// matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and from.
|
||||
type NetworkPolicyIngressRule struct {
|
||||
// List of ports which should be made accessible on the pods selected for this
|
||||
// rule. Each item in this list is combined using a logical OR. If this field is
|
||||
// empty or missing, this rule matches all ports (traffic not restricted by port).
|
||||
// If this field is present and contains at least one item, then this rule allows
|
||||
// traffic only if the traffic matches at least one port in the list.
|
||||
// +optional
|
||||
Ports []NetworkPolicyPort
|
||||
|
||||
// List of sources which should be able to access the pods selected for this rule.
|
||||
// Items in this list are combined using a logical OR operation. If this field is
|
||||
// empty or missing, this rule matches all sources (traffic not restricted by
|
||||
// source). If this field is present and contains at least on item, this rule
|
||||
// allows traffic only if the traffic matches at least one item in the from list.
|
||||
// +optional
|
||||
From []NetworkPolicyPeer
|
||||
}
|
||||
|
||||
// NetworkPolicyEgressRule describes a particular set of traffic that is allowed out of pods
|
||||
// matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and to.
|
||||
// This type is beta-level in 1.8
|
||||
type NetworkPolicyEgressRule struct {
|
||||
// List of destination ports for outgoing traffic.
|
||||
// Each item in this list is combined using a logical OR. If this field is
|
||||
// empty or missing, this rule matches all ports (traffic not restricted by port).
|
||||
// If this field is present and contains at least one item, then this rule allows
|
||||
// traffic only if the traffic matches at least one port in the list.
|
||||
// +optional
|
||||
Ports []NetworkPolicyPort
|
||||
|
||||
// List of destinations for outgoing traffic of pods selected for this rule.
|
||||
// Items in this list are combined using a logical OR operation. If this field is
|
||||
// empty or missing, this rule matches all destinations (traffic not restricted by
|
||||
// destination). If this field is present and contains at least one item, this rule
|
||||
// allows traffic only if the traffic matches at least one item in the to list.
|
||||
// +optional
|
||||
To []NetworkPolicyPeer
|
||||
}
|
||||
|
||||
// NetworkPolicyPort describes a port to allow traffic on
|
||||
type NetworkPolicyPort struct {
|
||||
// The protocol (TCP or UDP) which traffic must match. If not specified, this
|
||||
// field defaults to TCP.
|
||||
// +optional
|
||||
Protocol *api.Protocol
|
||||
|
||||
// The port on the given protocol. This can either be a numerical or named port on
|
||||
// a pod. If this field is not provided, this matches all port names and numbers.
|
||||
// +optional
|
||||
Port *intstr.IntOrString
|
||||
}
|
||||
|
||||
// IPBlock describes a particular CIDR (Ex. "192.168.1.1/24") that is allowed to the pods
|
||||
// matched by a NetworkPolicySpec's podSelector. The except entry describes CIDRs that should
|
||||
// not be included within this rule.
|
||||
type IPBlock struct {
|
||||
// CIDR is a string representing the IP Block
|
||||
// Valid examples are "192.168.1.1/24"
|
||||
CIDR string
|
||||
// Except is a slice of CIDRs that should not be included within an IP Block
|
||||
// Valid examples are "192.168.1.1/24"
|
||||
// Except values will be rejected if they are outside the CIDR range
|
||||
// +optional
|
||||
Except []string
|
||||
}
|
||||
|
||||
// NetworkPolicyPeer describes a peer to allow traffic from. Exactly one of its fields
|
||||
// must be specified.
|
||||
type NetworkPolicyPeer struct {
|
||||
// This is a label selector which selects Pods in this namespace. This field
|
||||
// follows standard label selector semantics. If present but empty, this selector
|
||||
// selects all pods in this namespace.
|
||||
// +optional
|
||||
PodSelector *metav1.LabelSelector
|
||||
|
||||
// Selects Namespaces using cluster scoped-labels. This matches all pods in all
|
||||
// namespaces selected by this label selector. This field follows standard label
|
||||
// selector semantics. If present but empty, this selector selects all namespaces.
|
||||
// +optional
|
||||
NamespaceSelector *metav1.LabelSelector
|
||||
|
||||
// IPBlock defines policy on a particular IPBlock
|
||||
// +optional
|
||||
IPBlock *IPBlock
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// NetworkPolicyList is a list of NetworkPolicy objects.
|
||||
type NetworkPolicyList struct {
|
||||
metav1.TypeMeta
|
||||
// +optional
|
||||
metav1.ListMeta
|
||||
|
||||
Items []NetworkPolicy
|
||||
}
|
||||
331
vendor/k8s.io/kubernetes/pkg/apis/networking/zz_generated.deepcopy.go
generated
vendored
Normal file
331
vendor/k8s.io/kubernetes/pkg/apis/networking/zz_generated.deepcopy.go
generated
vendored
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2017 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.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
|
||||
package networking
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
intstr "k8s.io/apimachinery/pkg/util/intstr"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(RegisterDeepCopies)
|
||||
}
|
||||
|
||||
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
|
||||
// to allow building arbitrary schemes.
|
||||
//
|
||||
// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented.
|
||||
func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
||||
return scheme.AddGeneratedDeepCopyFuncs(
|
||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
in.(*IPBlock).DeepCopyInto(out.(*IPBlock))
|
||||
return nil
|
||||
}, InType: reflect.TypeOf(&IPBlock{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
in.(*NetworkPolicy).DeepCopyInto(out.(*NetworkPolicy))
|
||||
return nil
|
||||
}, InType: reflect.TypeOf(&NetworkPolicy{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
in.(*NetworkPolicyEgressRule).DeepCopyInto(out.(*NetworkPolicyEgressRule))
|
||||
return nil
|
||||
}, InType: reflect.TypeOf(&NetworkPolicyEgressRule{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
in.(*NetworkPolicyIngressRule).DeepCopyInto(out.(*NetworkPolicyIngressRule))
|
||||
return nil
|
||||
}, InType: reflect.TypeOf(&NetworkPolicyIngressRule{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
in.(*NetworkPolicyList).DeepCopyInto(out.(*NetworkPolicyList))
|
||||
return nil
|
||||
}, InType: reflect.TypeOf(&NetworkPolicyList{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
in.(*NetworkPolicyPeer).DeepCopyInto(out.(*NetworkPolicyPeer))
|
||||
return nil
|
||||
}, InType: reflect.TypeOf(&NetworkPolicyPeer{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
in.(*NetworkPolicyPort).DeepCopyInto(out.(*NetworkPolicyPort))
|
||||
return nil
|
||||
}, InType: reflect.TypeOf(&NetworkPolicyPort{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
in.(*NetworkPolicySpec).DeepCopyInto(out.(*NetworkPolicySpec))
|
||||
return nil
|
||||
}, InType: reflect.TypeOf(&NetworkPolicySpec{})},
|
||||
)
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *IPBlock) DeepCopyInto(out *IPBlock) {
|
||||
*out = *in
|
||||
if in.Except != nil {
|
||||
in, out := &in.Except, &out.Except
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPBlock.
|
||||
func (in *IPBlock) DeepCopy() *IPBlock {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(IPBlock)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkPolicy) DeepCopyInto(out *NetworkPolicy) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicy.
|
||||
func (in *NetworkPolicy) DeepCopy() *NetworkPolicy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkPolicy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *NetworkPolicy) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkPolicyEgressRule) DeepCopyInto(out *NetworkPolicyEgressRule) {
|
||||
*out = *in
|
||||
if in.Ports != nil {
|
||||
in, out := &in.Ports, &out.Ports
|
||||
*out = make([]NetworkPolicyPort, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.To != nil {
|
||||
in, out := &in.To, &out.To
|
||||
*out = make([]NetworkPolicyPeer, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyEgressRule.
|
||||
func (in *NetworkPolicyEgressRule) DeepCopy() *NetworkPolicyEgressRule {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkPolicyEgressRule)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkPolicyIngressRule) DeepCopyInto(out *NetworkPolicyIngressRule) {
|
||||
*out = *in
|
||||
if in.Ports != nil {
|
||||
in, out := &in.Ports, &out.Ports
|
||||
*out = make([]NetworkPolicyPort, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.From != nil {
|
||||
in, out := &in.From, &out.From
|
||||
*out = make([]NetworkPolicyPeer, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyIngressRule.
|
||||
func (in *NetworkPolicyIngressRule) DeepCopy() *NetworkPolicyIngressRule {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkPolicyIngressRule)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkPolicyList) DeepCopyInto(out *NetworkPolicyList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]NetworkPolicy, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyList.
|
||||
func (in *NetworkPolicyList) DeepCopy() *NetworkPolicyList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkPolicyList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *NetworkPolicyList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkPolicyPeer) DeepCopyInto(out *NetworkPolicyPeer) {
|
||||
*out = *in
|
||||
if in.PodSelector != nil {
|
||||
in, out := &in.PodSelector, &out.PodSelector
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.NamespaceSelector != nil {
|
||||
in, out := &in.NamespaceSelector, &out.NamespaceSelector
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.IPBlock != nil {
|
||||
in, out := &in.IPBlock, &out.IPBlock
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(IPBlock)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyPeer.
|
||||
func (in *NetworkPolicyPeer) DeepCopy() *NetworkPolicyPeer {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkPolicyPeer)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkPolicyPort) DeepCopyInto(out *NetworkPolicyPort) {
|
||||
*out = *in
|
||||
if in.Protocol != nil {
|
||||
in, out := &in.Protocol, &out.Protocol
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(api.Protocol)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Port != nil {
|
||||
in, out := &in.Port, &out.Port
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicyPort.
|
||||
func (in *NetworkPolicyPort) DeepCopy() *NetworkPolicyPort {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkPolicyPort)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkPolicySpec) DeepCopyInto(out *NetworkPolicySpec) {
|
||||
*out = *in
|
||||
in.PodSelector.DeepCopyInto(&out.PodSelector)
|
||||
if in.Ingress != nil {
|
||||
in, out := &in.Ingress, &out.Ingress
|
||||
*out = make([]NetworkPolicyIngressRule, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Egress != nil {
|
||||
in, out := &in.Egress, &out.Egress
|
||||
*out = make([]NetworkPolicyEgressRule, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.PolicyTypes != nil {
|
||||
in, out := &in.PolicyTypes, &out.PolicyTypes
|
||||
*out = make([]PolicyType, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPolicySpec.
|
||||
func (in *NetworkPolicySpec) DeepCopy() *NetworkPolicySpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkPolicySpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
9
vendor/k8s.io/kubernetes/pkg/capabilities/BUILD
generated
vendored
9
vendor/k8s.io/kubernetes/pkg/capabilities/BUILD
generated
vendored
|
|
@ -1,10 +1,9 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
|
|
@ -13,6 +12,12 @@ go_library(
|
|||
"capabilities.go",
|
||||
"doc.go",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["capabilities_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
|
|
|
|||
27
vendor/k8s.io/kubernetes/pkg/capabilities/capabilities.go
generated
vendored
27
vendor/k8s.io/kubernetes/pkg/capabilities/capabilities.go
generated
vendored
|
|
@ -46,16 +46,17 @@ type PrivilegedSources struct {
|
|||
HostIPCSources []string
|
||||
}
|
||||
|
||||
// TODO: Clean these up into a singleton
|
||||
var once sync.Once
|
||||
var lock sync.Mutex
|
||||
var capabilities *Capabilities
|
||||
var capInstance struct {
|
||||
once sync.Once
|
||||
lock sync.Mutex
|
||||
capabilities *Capabilities
|
||||
}
|
||||
|
||||
// Initialize the capability set. This can only be done once per binary, subsequent calls are ignored.
|
||||
func Initialize(c Capabilities) {
|
||||
// Only do this once
|
||||
once.Do(func() {
|
||||
capabilities = &c
|
||||
capInstance.once.Do(func() {
|
||||
capInstance.capabilities = &c
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -70,17 +71,17 @@ func Setup(allowPrivileged bool, privilegedSources PrivilegedSources, perConnect
|
|||
|
||||
// SetForTests sets capabilities for tests. Convenience method for testing. This should only be called from tests.
|
||||
func SetForTests(c Capabilities) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
capabilities = &c
|
||||
capInstance.lock.Lock()
|
||||
defer capInstance.lock.Unlock()
|
||||
capInstance.capabilities = &c
|
||||
}
|
||||
|
||||
// Returns a read-only copy of the system capabilities.
|
||||
func Get() Capabilities {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
capInstance.lock.Lock()
|
||||
defer capInstance.lock.Unlock()
|
||||
// This check prevents clobbering of capabilities that might've been set via SetForTests
|
||||
if capabilities == nil {
|
||||
if capInstance.capabilities == nil {
|
||||
Initialize(Capabilities{
|
||||
AllowPrivileged: false,
|
||||
PrivilegedSources: PrivilegedSources{
|
||||
|
|
@ -90,5 +91,5 @@ func Get() Capabilities {
|
|||
},
|
||||
})
|
||||
}
|
||||
return *capabilities
|
||||
return *capInstance.capabilities
|
||||
}
|
||||
|
|
|
|||
44
vendor/k8s.io/kubernetes/pkg/client/retry/BUILD
generated
vendored
44
vendor/k8s.io/kubernetes/pkg/client/retry/BUILD
generated
vendored
|
|
@ -1,44 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["util.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
2
vendor/k8s.io/kubernetes/pkg/client/retry/OWNERS
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/client/retry/OWNERS
generated
vendored
|
|
@ -1,2 +0,0 @@
|
|||
reviewers:
|
||||
- caesarxuchao
|
||||
79
vendor/k8s.io/kubernetes/pkg/client/retry/util.go
generated
vendored
79
vendor/k8s.io/kubernetes/pkg/client/retry/util.go
generated
vendored
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 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 retry
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
// DefaultRetry is the recommended retry for a conflict where multiple clients
|
||||
// are making changes to the same resource.
|
||||
var DefaultRetry = wait.Backoff{
|
||||
Steps: 5,
|
||||
Duration: 10 * time.Millisecond,
|
||||
Factor: 1.0,
|
||||
Jitter: 0.1,
|
||||
}
|
||||
|
||||
// DefaultBackoff is the recommended backoff for a conflict where a client
|
||||
// may be attempting to make an unrelated modification to a resource under
|
||||
// active management by one or more controllers.
|
||||
var DefaultBackoff = wait.Backoff{
|
||||
Steps: 4,
|
||||
Duration: 10 * time.Millisecond,
|
||||
Factor: 5.0,
|
||||
Jitter: 0.1,
|
||||
}
|
||||
|
||||
// RetryConflict executes the provided function repeatedly, retrying if the server returns a conflicting
|
||||
// write. Callers should preserve previous executions if they wish to retry changes. It performs an
|
||||
// exponential backoff.
|
||||
//
|
||||
// var pod *api.Pod
|
||||
// err := RetryOnConflict(DefaultBackoff, func() (err error) {
|
||||
// pod, err = c.Pods("mynamespace").UpdateStatus(podStatus)
|
||||
// return
|
||||
// })
|
||||
// if err != nil {
|
||||
// // may be conflict if max retries were hit
|
||||
// return err
|
||||
// }
|
||||
// ...
|
||||
//
|
||||
// TODO: Make Backoff an interface?
|
||||
func RetryOnConflict(backoff wait.Backoff, fn func() error) error {
|
||||
var lastConflictErr error
|
||||
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
|
||||
err := fn()
|
||||
switch {
|
||||
case err == nil:
|
||||
return true, nil
|
||||
case errors.IsConflict(err):
|
||||
lastConflictErr = err
|
||||
return false, nil
|
||||
default:
|
||||
return false, err
|
||||
}
|
||||
})
|
||||
if err == wait.ErrWaitTimeout {
|
||||
err = lastConflictErr
|
||||
}
|
||||
return err
|
||||
}
|
||||
3
vendor/k8s.io/kubernetes/pkg/cloudprovider/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/cloudprovider/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -14,7 +12,6 @@ go_library(
|
|||
"doc.go",
|
||||
"plugins.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/controller:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
|
|
|
|||
1
vendor/k8s.io/kubernetes/pkg/cloudprovider/OWNERS
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/cloudprovider/OWNERS
generated
vendored
|
|
@ -38,3 +38,4 @@ reviewers:
|
|||
- jdef
|
||||
- freehan
|
||||
- jingxu97
|
||||
- wlan0
|
||||
|
|
|
|||
25
vendor/k8s.io/kubernetes/pkg/cloudprovider/cloud.go
generated
vendored
25
vendor/k8s.io/kubernetes/pkg/cloudprovider/cloud.go
generated
vendored
|
|
@ -45,6 +45,8 @@ type Interface interface {
|
|||
ProviderName() string
|
||||
// ScrubDNS provides an opportunity for cloud-provider-specific code to process DNS settings for pods.
|
||||
ScrubDNS(nameservers, searches []string) (nsOut, srchOut []string)
|
||||
// HasClusterID returns true if a ClusterID is required and set
|
||||
HasClusterID() bool
|
||||
}
|
||||
|
||||
// Clusters is an abstract, pluggable interface for clusters of containers.
|
||||
|
|
@ -122,7 +124,7 @@ type Instances interface {
|
|||
// ProviderID is a unique identifier of the node. This will not be called
|
||||
// from the node whose nodeaddresses are being queried. i.e. local metadata
|
||||
// services cannot be used in this method to obtain nodeaddresses
|
||||
NodeAddressesByProviderID(providerId string) ([]v1.NodeAddress, error)
|
||||
NodeAddressesByProviderID(providerID string) ([]v1.NodeAddress, error)
|
||||
// ExternalID returns the cloud provider ID of the node with the specified NodeName.
|
||||
// Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound)
|
||||
ExternalID(nodeName types.NodeName) (string, error)
|
||||
|
|
@ -138,6 +140,9 @@ type Instances interface {
|
|||
// CurrentNodeName returns the name of the node we are currently running on
|
||||
// On most clouds (e.g. GCE) this is the hostname, so we provide the hostname
|
||||
CurrentNodeName(hostname string) (types.NodeName, error)
|
||||
// InstanceExistsByProviderID returns true if the instance for the given provider id still is running.
|
||||
// If false is returned with no error, the instance will be immediately deleted by the cloud controller manager.
|
||||
InstanceExistsByProviderID(providerID string) (bool, error)
|
||||
}
|
||||
|
||||
// Route is a representation of an advanced routing rule.
|
||||
|
|
@ -182,5 +187,23 @@ type Zone struct {
|
|||
// Zones is an abstract, pluggable interface for zone enumeration.
|
||||
type Zones interface {
|
||||
// GetZone returns the Zone containing the current failure zone and locality region that the program is running in
|
||||
// In most cases, this method is called from the kubelet querying a local metadata service to aquire its zone.
|
||||
// For the case of external cloud providers, use GetZoneByProviderID or GetZoneByNodeName since GetZone
|
||||
// can no longer be called from the kubelets.
|
||||
GetZone() (Zone, error)
|
||||
|
||||
// GetZoneByProviderID returns the Zone containing the current zone and locality region of the node specified by providerId
|
||||
// This method is particularly used in the context of external cloud providers where node initialization must be down
|
||||
// outside the kubelets.
|
||||
GetZoneByProviderID(providerID string) (Zone, error)
|
||||
|
||||
// GetZoneByNodeName returns the Zone containing the current zone and locality region of the node specified by node name
|
||||
// This method is particularly used in the context of external cloud providers where node initialization must be down
|
||||
// outside the kubelets.
|
||||
GetZoneByNodeName(nodeName types.NodeName) (Zone, error)
|
||||
}
|
||||
|
||||
// PVLabeler is an abstract, pluggable interface for fetching labels for volumes
|
||||
type PVLabeler interface {
|
||||
GetLabelsForVolume(pv *v1.PersistentVolume) (map[string]string, error)
|
||||
}
|
||||
|
|
|
|||
24
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/BUILD
generated
vendored
24
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -13,8 +11,10 @@ go_library(
|
|||
srcs = [
|
||||
"doc.go",
|
||||
"gce.go",
|
||||
"gce_address_manager.go",
|
||||
"gce_addresses.go",
|
||||
"gce_addresses_fakes.go",
|
||||
"gce_alpha.go",
|
||||
"gce_annotations.go",
|
||||
"gce_backendservice.go",
|
||||
"gce_cert.go",
|
||||
|
|
@ -23,6 +23,7 @@ go_library(
|
|||
"gce_disks.go",
|
||||
"gce_firewall.go",
|
||||
"gce_forwardingrule.go",
|
||||
"gce_forwardingrule_fakes.go",
|
||||
"gce_healthchecks.go",
|
||||
"gce_instancegroup.go",
|
||||
"gce_instances.go",
|
||||
|
|
@ -38,10 +39,10 @@ go_library(
|
|||
"gce_urlmap.go",
|
||||
"gce_util.go",
|
||||
"gce_zones.go",
|
||||
"kms.go",
|
||||
"metrics.go",
|
||||
"token_source.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1/service:go_default_library",
|
||||
"//pkg/cloudprovider:go_default_library",
|
||||
|
|
@ -51,6 +52,7 @@ go_library(
|
|||
"//pkg/util/net/sets:go_default_library",
|
||||
"//pkg/util/version:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//vendor/cloud.google.com/go/compute/metadata:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
|
|
@ -72,8 +74,13 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/record:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
@ -81,19 +88,28 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"gce_address_manager_test.go",
|
||||
"gce_annotations_test.go",
|
||||
"gce_disks_test.go",
|
||||
"gce_healthchecks_test.go",
|
||||
"gce_loadbalancer_external_test.go",
|
||||
"gce_test.go",
|
||||
"metrics_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/cloudprovider:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
"//vendor/golang.org/x/oauth2/google:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v0.alpha:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v0.beta:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
||||
"//vendor/google.golang.org/api/googleapi:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
843
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce.go
generated
vendored
843
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce.go
generated
vendored
File diff suppressed because it is too large
Load diff
198
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager.go
generated
vendored
Normal file
198
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager.go
generated
vendored
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
Copyright 2017 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 gce
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
type addressManager struct {
|
||||
logPrefix string
|
||||
svc CloudAddressService
|
||||
name string
|
||||
serviceName string
|
||||
targetIP string
|
||||
addressType lbScheme
|
||||
region string
|
||||
subnetURL string
|
||||
tryRelease bool
|
||||
}
|
||||
|
||||
func newAddressManager(svc CloudAddressService, serviceName, region, subnetURL, name, targetIP string, addressType lbScheme) *addressManager {
|
||||
return &addressManager{
|
||||
svc: svc,
|
||||
logPrefix: fmt.Sprintf("AddressManager(%q)", name),
|
||||
region: region,
|
||||
serviceName: serviceName,
|
||||
name: name,
|
||||
targetIP: targetIP,
|
||||
addressType: addressType,
|
||||
tryRelease: true,
|
||||
subnetURL: subnetURL,
|
||||
}
|
||||
}
|
||||
|
||||
// HoldAddress will ensure that the IP is reserved with an address - either owned by the controller
|
||||
// or by a user. If the address is not the addressManager.name, then it's assumed to be a user's address.
|
||||
// The string returned is the reserved IP address.
|
||||
func (am *addressManager) HoldAddress() (string, error) {
|
||||
// HoldAddress starts with retrieving the address that we use for this load balancer (by name).
|
||||
// Retrieving an address by IP will indicate if the IP is reserved and if reserved by the user
|
||||
// or the controller, but won't tell us the current state of the controller's IP. The address
|
||||
// could be reserving another address; therefore, it would need to be deleted. In the normal
|
||||
// case of using a controller address, retrieving the address by name results in the fewest API
|
||||
// calls since it indicates whether a Delete is necessary before Reserve.
|
||||
glog.V(4).Infof("%v: attempting hold of IP %q Type %q", am.logPrefix, am.targetIP, am.addressType)
|
||||
// Get the address in case it was orphaned earlier
|
||||
addr, err := am.svc.GetBetaRegionAddress(am.name, am.region)
|
||||
if err != nil && !isNotFound(err) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if addr != nil {
|
||||
// If address exists, check if the address had the expected attributes.
|
||||
validationError := am.validateAddress(addr)
|
||||
if validationError == nil {
|
||||
glog.V(4).Infof("%v: address %q already reserves IP %q Type %q. No further action required.", am.logPrefix, addr.Name, addr.Address, addr.AddressType)
|
||||
return addr.Address, nil
|
||||
}
|
||||
|
||||
glog.V(2).Infof("%v: deleting existing address because %v", am.logPrefix, validationError)
|
||||
err := am.svc.DeleteRegionAddress(addr.Name, am.region)
|
||||
if err != nil {
|
||||
if isNotFound(err) {
|
||||
glog.V(4).Infof("%v: address %q was not found. Ignoring.", am.logPrefix, addr.Name)
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
glog.V(4).Infof("%v: successfully deleted previous address %q", am.logPrefix, addr.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return am.ensureAddressReservation()
|
||||
}
|
||||
|
||||
// ReleaseAddress will release the address if it's owned by the controller.
|
||||
func (am *addressManager) ReleaseAddress() error {
|
||||
if !am.tryRelease {
|
||||
glog.V(4).Infof("%v: not attempting release of address %q.", am.logPrefix, am.targetIP)
|
||||
return nil
|
||||
}
|
||||
|
||||
glog.V(4).Infof("%v: releasing address %q named %q", am.logPrefix, am.targetIP, am.name)
|
||||
// Controller only ever tries to unreserve the address named with the load balancer's name.
|
||||
err := am.svc.DeleteRegionAddress(am.name, am.region)
|
||||
if err != nil {
|
||||
if isNotFound(err) {
|
||||
glog.Warningf("%v: address %q was not found. Ignoring.", am.logPrefix, am.name)
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
glog.V(4).Infof("%v: successfully released IP %q named %q", am.logPrefix, am.targetIP, am.name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *addressManager) ensureAddressReservation() (string, error) {
|
||||
// Try reserving the IP with controller-owned address name
|
||||
// If am.targetIP is an empty string, a new IP will be created.
|
||||
newAddr := &computebeta.Address{
|
||||
Name: am.name,
|
||||
Description: fmt.Sprintf(`{"kubernetes.io/service-name":"%s"}`, am.serviceName),
|
||||
Address: am.targetIP,
|
||||
AddressType: string(am.addressType),
|
||||
Subnetwork: am.subnetURL,
|
||||
}
|
||||
|
||||
reserveErr := am.svc.ReserveBetaRegionAddress(newAddr, am.region)
|
||||
if reserveErr == nil {
|
||||
if newAddr.Address != "" {
|
||||
glog.V(4).Infof("%v: successfully reserved IP %q with name %q", am.logPrefix, newAddr.Address, newAddr.Name)
|
||||
return newAddr.Address, nil
|
||||
}
|
||||
|
||||
addr, err := am.svc.GetRegionAddress(newAddr.Name, am.region)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
glog.V(4).Infof("%v: successfully created address %q which reserved IP %q", am.logPrefix, addr.Name, addr.Address)
|
||||
return addr.Address, nil
|
||||
} else if !isHTTPErrorCode(reserveErr, http.StatusConflict) && !isHTTPErrorCode(reserveErr, http.StatusBadRequest) {
|
||||
// If the IP is already reserved:
|
||||
// by an internal address: a StatusConflict is returned
|
||||
// by an external address: a BadRequest is returned
|
||||
return "", reserveErr
|
||||
}
|
||||
|
||||
// If the target IP was empty, we cannot try to find which IP caused a conflict.
|
||||
// If the name was already used, then the next sync will attempt deletion of that address.
|
||||
if am.targetIP == "" {
|
||||
return "", fmt.Errorf("failed to reserve address %q with no specific IP, err: %v", am.name, reserveErr)
|
||||
}
|
||||
|
||||
// Reserving the address failed due to a conflict or bad request. The address manager just checked that no address
|
||||
// exists with the name, so it may belong to the user.
|
||||
addr, err := am.svc.GetBetaRegionAddressByIP(am.region, am.targetIP)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get address by IP %q after reservation attempt, err: %q, reservation err: %q", am.targetIP, err, reserveErr)
|
||||
}
|
||||
|
||||
// Check that the address attributes are as required.
|
||||
if err := am.validateAddress(addr); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if am.isManagedAddress(addr) {
|
||||
// The address with this name is checked at the beginning of 'HoldAddress()', but for some reason
|
||||
// it was re-created by this point. May be possible that two controllers are running.
|
||||
glog.Warning("%v: address %q unexpectedly existed with IP %q.", am.logPrefix, addr.Name, am.targetIP)
|
||||
} else {
|
||||
// If the retrieved address is not named with the loadbalancer name, then the controller does not own it, but will allow use of it.
|
||||
glog.V(4).Infof("%v: address %q was already reserved with name: %q, description: %q", am.logPrefix, am.targetIP, addr.Name, addr.Description)
|
||||
am.tryRelease = false
|
||||
}
|
||||
|
||||
return addr.Address, nil
|
||||
}
|
||||
|
||||
func (am *addressManager) validateAddress(addr *computebeta.Address) error {
|
||||
if am.targetIP != "" && am.targetIP != addr.Address {
|
||||
return fmt.Errorf("address %q does not have the expected IP %q, actual: %q", addr.Name, am.targetIP, addr.Address)
|
||||
}
|
||||
if addr.AddressType != string(am.addressType) {
|
||||
return fmt.Errorf("address %q does not have the expected address type %q, actual: %q", addr.Name, am.addressType, addr.AddressType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *addressManager) isManagedAddress(addr *computebeta.Address) bool {
|
||||
return addr.Name == am.name
|
||||
}
|
||||
|
||||
func ensureAddressDeleted(svc CloudAddressService, name, region string) error {
|
||||
return ignoreNotFound(svc.DeleteRegionAddress(name, region))
|
||||
}
|
||||
113
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses.go
generated
vendored
113
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses.go
generated
vendored
|
|
@ -17,16 +17,21 @@ limitations under the License.
|
|||
package gce
|
||||
|
||||
import (
|
||||
"time"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
func newAddressMetricContext(request, region string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"address_" + request, region, unusedMetricLabel},
|
||||
}
|
||||
return newAddressMetricContextWithVersion(request, region, computeV1Version)
|
||||
}
|
||||
|
||||
func newAddressMetricContextWithVersion(request, region, version string) *metricContext {
|
||||
return newGenericMetricContext("address", request, region, unusedMetricLabel, version)
|
||||
}
|
||||
|
||||
// ReserveGlobalAddress creates a global address.
|
||||
|
|
@ -69,6 +74,26 @@ func (gce *GCECloud) ReserveRegionAddress(addr *compute.Address, region string)
|
|||
return gce.waitForRegionOp(op, region, mc)
|
||||
}
|
||||
|
||||
// ReserveAlphaRegionAddress creates an Alpha, regional address.
|
||||
func (gce *GCECloud) ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error {
|
||||
mc := newAddressMetricContextWithVersion("reserve", region, computeAlphaVersion)
|
||||
op, err := gce.serviceAlpha.Addresses.Insert(gce.projectID, region, addr).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
}
|
||||
|
||||
// ReserveBetaRegionAddress creates a beta region address
|
||||
func (gce *GCECloud) ReserveBetaRegionAddress(addr *computebeta.Address, region string) error {
|
||||
mc := newAddressMetricContextWithVersion("reserve", region, computeBetaVersion)
|
||||
op, err := gce.serviceBeta.Addresses.Insert(gce.projectID, region, addr).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
}
|
||||
|
||||
// DeleteRegionAddress deletes a region address by name.
|
||||
func (gce *GCECloud) DeleteRegionAddress(name, region string) error {
|
||||
mc := newAddressMetricContext("delete", region)
|
||||
|
|
@ -85,3 +110,81 @@ func (gce *GCECloud) GetRegionAddress(name, region string) (*compute.Address, er
|
|||
v, err := gce.service.Addresses.Get(gce.projectID, region, name).Do()
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetAlphaRegionAddress returns the Alpha, regional address by name.
|
||||
func (gce *GCECloud) GetAlphaRegionAddress(name, region string) (*computealpha.Address, error) {
|
||||
mc := newAddressMetricContextWithVersion("get", region, computeAlphaVersion)
|
||||
v, err := gce.serviceAlpha.Addresses.Get(gce.projectID, region, name).Do()
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetBetaRegionAddress returns the beta region address by name
|
||||
func (gce *GCECloud) GetBetaRegionAddress(name, region string) (*computebeta.Address, error) {
|
||||
mc := newAddressMetricContextWithVersion("get", region, computeBetaVersion)
|
||||
v, err := gce.serviceBeta.Addresses.Get(gce.projectID, region, name).Do()
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetRegionAddressByIP returns the regional address matching the given IP address.
|
||||
func (gce *GCECloud) GetRegionAddressByIP(region, ipAddress string) (*compute.Address, error) {
|
||||
mc := newAddressMetricContext("list", region)
|
||||
addrs, err := gce.service.Addresses.List(gce.projectID, region).Filter("address eq " + ipAddress).Do()
|
||||
// Record the metrics for the call.
|
||||
mc.Observe(err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(addrs.Items) > 1 {
|
||||
// We don't expect more than one match.
|
||||
addrsToPrint := []compute.Address{}
|
||||
for _, addr := range addrs.Items {
|
||||
addrsToPrint = append(addrsToPrint, *addr)
|
||||
}
|
||||
glog.Errorf("More than one addresses matching the IP %q: %+v", ipAddress, addrsToPrint)
|
||||
}
|
||||
for _, addr := range addrs.Items {
|
||||
if addr.Address == ipAddress {
|
||||
return addr, nil
|
||||
}
|
||||
}
|
||||
return nil, makeGoogleAPINotFoundError(fmt.Sprintf("Address with IP %q was not found in region %q", ipAddress, region))
|
||||
}
|
||||
|
||||
// GetBetaRegionAddressByIP returns the beta regional address matching the given IP address.
|
||||
func (gce *GCECloud) GetBetaRegionAddressByIP(region, ipAddress string) (*computebeta.Address, error) {
|
||||
mc := newAddressMetricContext("list", region)
|
||||
addrs, err := gce.serviceBeta.Addresses.List(gce.projectID, region).Filter("address eq " + ipAddress).Do()
|
||||
// Record the metrics for the call.
|
||||
mc.Observe(err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(addrs.Items) > 1 {
|
||||
// We don't expect more than one match.
|
||||
addrsToPrint := []computebeta.Address{}
|
||||
for _, addr := range addrs.Items {
|
||||
addrsToPrint = append(addrsToPrint, *addr)
|
||||
}
|
||||
glog.Errorf("More than one addresses matching the IP %q: %+v", ipAddress, addrsToPrint)
|
||||
}
|
||||
for _, addr := range addrs.Items {
|
||||
if addr.Address == ipAddress {
|
||||
return addr, nil
|
||||
}
|
||||
}
|
||||
return nil, makeGoogleAPINotFoundError(fmt.Sprintf("Address with IP %q was not found in region %q", ipAddress, region))
|
||||
}
|
||||
|
||||
// TODO(#51665): retire this function once Network Tiers becomes Beta in GCP.
|
||||
func (gce *GCECloud) getNetworkTierFromAddress(name, region string) (string, error) {
|
||||
if !gce.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
||||
return NetworkTierDefault.ToGCEValue(), nil
|
||||
}
|
||||
addr, err := gce.GetAlphaRegionAddress(name, region)
|
||||
if err != nil {
|
||||
return handleAlphaNetworkTierGetError(err)
|
||||
}
|
||||
return addr.NetworkTier, nil
|
||||
}
|
||||
|
|
|
|||
180
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go
generated
vendored
180
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go
generated
vendored
|
|
@ -17,13 +17,18 @@ limitations under the License.
|
|||
package gce
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
// test
|
||||
|
||||
type FakeCloudAddressService struct {
|
||||
count int
|
||||
// reservedAddrs tracks usage of IP addresses
|
||||
|
|
@ -31,32 +36,60 @@ type FakeCloudAddressService struct {
|
|||
reservedAddrs map[string]bool
|
||||
// addrsByRegionAndName
|
||||
// Outer key is for region string; inner key is for address name.
|
||||
addrsByRegionAndName map[string]map[string]*compute.Address
|
||||
addrsByRegionAndName map[string]map[string]*computealpha.Address
|
||||
}
|
||||
|
||||
// FakeCloudAddressService Implements CloudAddressService
|
||||
var _ CloudAddressService = &FakeCloudAddressService{}
|
||||
|
||||
func NewFakeCloudAddressService() *FakeCloudAddressService {
|
||||
return &FakeCloudAddressService{
|
||||
reservedAddrs: make(map[string]bool),
|
||||
addrsByRegionAndName: make(map[string]map[string]*compute.Address),
|
||||
addrsByRegionAndName: make(map[string]map[string]*computealpha.Address),
|
||||
}
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) ReserveRegionAddress(addr *compute.Address, region string) error {
|
||||
// SetRegionalAddresses sets the addresses of ther region. This is used for
|
||||
// setting the test environment.
|
||||
func (cas *FakeCloudAddressService) SetRegionalAddresses(region string, addrs []*computealpha.Address) {
|
||||
// Reset addresses in the region.
|
||||
cas.addrsByRegionAndName[region] = make(map[string]*computealpha.Address)
|
||||
|
||||
for _, addr := range addrs {
|
||||
cas.reservedAddrs[addr.Address] = true
|
||||
cas.addrsByRegionAndName[region][addr.Name] = addr
|
||||
}
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error {
|
||||
if addr.Address == "" {
|
||||
addr.Address = fmt.Sprintf("1.2.3.%d", cas.count)
|
||||
cas.count++
|
||||
}
|
||||
|
||||
if addr.AddressType == "" {
|
||||
addr.AddressType = string(schemeExternal)
|
||||
}
|
||||
|
||||
if cas.reservedAddrs[addr.Address] {
|
||||
return &googleapi.Error{Code: http.StatusConflict}
|
||||
msg := "IP in use"
|
||||
// When the IP is already in use, this call returns an error code based
|
||||
// on the type (internal vs external) of the address. This is to be
|
||||
// consistent with actual GCE API.
|
||||
switch lbScheme(addr.AddressType) {
|
||||
case schemeExternal:
|
||||
return makeGoogleAPIError(http.StatusBadRequest, msg)
|
||||
default:
|
||||
return makeGoogleAPIError(http.StatusConflict, msg)
|
||||
}
|
||||
}
|
||||
|
||||
if _, exists := cas.addrsByRegionAndName[region]; !exists {
|
||||
cas.addrsByRegionAndName[region] = make(map[string]*compute.Address)
|
||||
cas.addrsByRegionAndName[region] = make(map[string]*computealpha.Address)
|
||||
}
|
||||
|
||||
if _, exists := cas.addrsByRegionAndName[region][addr.Name]; exists {
|
||||
return &googleapi.Error{Code: http.StatusConflict}
|
||||
return makeGoogleAPIError(http.StatusConflict, "name in use")
|
||||
}
|
||||
|
||||
cas.addrsByRegionAndName[region][addr.Name] = addr
|
||||
|
|
@ -64,14 +97,141 @@ func (cas *FakeCloudAddressService) ReserveRegionAddress(addr *compute.Address,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) GetRegionAddress(name, region string) (*compute.Address, error) {
|
||||
func (cas *FakeCloudAddressService) ReserveBetaRegionAddress(addr *computebeta.Address, region string) error {
|
||||
alphaAddr := convertToAlphaAddress(addr)
|
||||
return cas.ReserveAlphaRegionAddress(alphaAddr, region)
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) ReserveRegionAddress(addr *compute.Address, region string) error {
|
||||
alphaAddr := convertToAlphaAddress(addr)
|
||||
return cas.ReserveAlphaRegionAddress(alphaAddr, region)
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) GetAlphaRegionAddress(name, region string) (*computealpha.Address, error) {
|
||||
if _, exists := cas.addrsByRegionAndName[region]; !exists {
|
||||
return nil, &googleapi.Error{Code: http.StatusNotFound}
|
||||
return nil, makeGoogleAPINotFoundError("")
|
||||
}
|
||||
|
||||
if addr, exists := cas.addrsByRegionAndName[region][name]; !exists {
|
||||
return nil, &googleapi.Error{Code: http.StatusNotFound}
|
||||
return nil, makeGoogleAPINotFoundError("")
|
||||
} else {
|
||||
return addr, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) GetBetaRegionAddress(name, region string) (*computebeta.Address, error) {
|
||||
addr, err := cas.GetAlphaRegionAddress(name, region)
|
||||
if addr != nil {
|
||||
return convertToBetaAddress(addr), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) GetRegionAddress(name, region string) (*compute.Address, error) {
|
||||
addr, err := cas.GetAlphaRegionAddress(name, region)
|
||||
if addr != nil {
|
||||
return convertToV1Address(addr), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) DeleteRegionAddress(name, region string) error {
|
||||
if _, exists := cas.addrsByRegionAndName[region]; !exists {
|
||||
return makeGoogleAPINotFoundError("")
|
||||
}
|
||||
|
||||
addr, exists := cas.addrsByRegionAndName[region][name]
|
||||
if !exists {
|
||||
return makeGoogleAPINotFoundError("")
|
||||
}
|
||||
|
||||
delete(cas.reservedAddrs, addr.Address)
|
||||
delete(cas.addrsByRegionAndName[region], name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) GetAlphaRegionAddressByIP(region, ipAddress string) (*computealpha.Address, error) {
|
||||
if _, exists := cas.addrsByRegionAndName[region]; !exists {
|
||||
return nil, makeGoogleAPINotFoundError("")
|
||||
}
|
||||
|
||||
for _, addr := range cas.addrsByRegionAndName[region] {
|
||||
if addr.Address == ipAddress {
|
||||
return addr, nil
|
||||
}
|
||||
}
|
||||
return nil, makeGoogleAPINotFoundError("")
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) GetBetaRegionAddressByIP(name, region string) (*computebeta.Address, error) {
|
||||
addr, err := cas.GetAlphaRegionAddressByIP(name, region)
|
||||
if addr != nil {
|
||||
return convertToBetaAddress(addr), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) GetRegionAddressByIP(name, region string) (*compute.Address, error) {
|
||||
addr, err := cas.GetAlphaRegionAddressByIP(name, region)
|
||||
if addr != nil {
|
||||
return convertToV1Address(addr), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) getNetworkTierFromAddress(name, region string) (string, error) {
|
||||
addr, err := cas.GetAlphaRegionAddress(name, region)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return addr.NetworkTier, nil
|
||||
}
|
||||
|
||||
func convertToV1Address(object gceObject) *compute.Address {
|
||||
enc, err := object.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to encode to json: %v", err))
|
||||
}
|
||||
var addr compute.Address
|
||||
if err := json.Unmarshal(enc, &addr); err != nil {
|
||||
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to v1 address: %v", object, err))
|
||||
}
|
||||
return &addr
|
||||
}
|
||||
|
||||
func convertToAlphaAddress(object gceObject) *computealpha.Address {
|
||||
enc, err := object.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to encode to json: %v", err))
|
||||
}
|
||||
var addr computealpha.Address
|
||||
if err := json.Unmarshal(enc, &addr); err != nil {
|
||||
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to alpha address: %v", object, err))
|
||||
}
|
||||
// Set the default values for the Alpha fields.
|
||||
addr.NetworkTier = NetworkTierDefault.ToGCEValue()
|
||||
return &addr
|
||||
}
|
||||
|
||||
func convertToBetaAddress(object gceObject) *computebeta.Address {
|
||||
enc, err := object.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to encode to json: %v", err))
|
||||
}
|
||||
var addr computebeta.Address
|
||||
if err := json.Unmarshal(enc, &addr); err != nil {
|
||||
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to beta address: %v", object, err))
|
||||
}
|
||||
return &addr
|
||||
}
|
||||
|
||||
func (cas *FakeCloudAddressService) String() string {
|
||||
var b bytes.Buffer
|
||||
for region, regAddresses := range cas.addrsByRegionAndName {
|
||||
b.WriteString(fmt.Sprintf("%v:\n", region))
|
||||
for name, addr := range regAddresses {
|
||||
b.WriteString(fmt.Sprintf(" %v: %v\n", name, addr.Address))
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
|
|
|||
60
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_alpha.go
generated
vendored
Normal file
60
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_alpha.go
generated
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Copyright 2017 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 gce
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// alpha: v1.8 (for Services)
|
||||
//
|
||||
// Allows Services backed by a GCP load balancer to choose what network
|
||||
// tier to use. Currently supports "Standard" and "Premium" (default).
|
||||
AlphaFeatureNetworkTiers = "NetworkTiers"
|
||||
|
||||
GCEDiskAlphaFeatureGate = "DiskAlphaAPI"
|
||||
)
|
||||
|
||||
// All known alpha features
|
||||
var knownAlphaFeatures = map[string]bool{
|
||||
AlphaFeatureNetworkTiers: true,
|
||||
GCEDiskAlphaFeatureGate: true,
|
||||
}
|
||||
|
||||
type AlphaFeatureGate struct {
|
||||
features map[string]bool
|
||||
}
|
||||
|
||||
func (af *AlphaFeatureGate) Enabled(key string) bool {
|
||||
return af.features[key]
|
||||
}
|
||||
|
||||
func NewAlphaFeatureGate(features []string) (*AlphaFeatureGate, error) {
|
||||
errList := []error{}
|
||||
featureMap := make(map[string]bool)
|
||||
for _, name := range features {
|
||||
if _, ok := knownAlphaFeatures[name]; !ok {
|
||||
errList = append(errList, fmt.Errorf("alpha feature %q is not supported.", name))
|
||||
} else {
|
||||
featureMap[name] = true
|
||||
}
|
||||
}
|
||||
return &AlphaFeatureGate{featureMap}, utilerrors.NewAggregate(errList)
|
||||
}
|
||||
81
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_annotations.go
generated
vendored
81
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_annotations.go
generated
vendored
|
|
@ -16,9 +16,17 @@ limitations under the License.
|
|||
|
||||
package gce
|
||||
|
||||
import "k8s.io/api/core/v1"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
type LoadBalancerType string
|
||||
type NetworkTier string
|
||||
|
||||
const (
|
||||
// ServiceAnnotationLoadBalancerType is annotated on a service with type LoadBalancer
|
||||
|
|
@ -26,12 +34,27 @@ const (
|
|||
// Currently, only "internal" is supported.
|
||||
ServiceAnnotationLoadBalancerType = "cloud.google.com/load-balancer-type"
|
||||
|
||||
LBTypeInternal LoadBalancerType = "internal"
|
||||
LBTypeInternal LoadBalancerType = "Internal"
|
||||
// Deprecating the lowercase spelling of Internal.
|
||||
deprecatedTypeInternalLowerCase LoadBalancerType = "internal"
|
||||
|
||||
// ServiceAnnotationInternalBackendShare is annotated on a service with "true" when users
|
||||
// want to share GCP Backend Services for a set of internal load balancers.
|
||||
// ALPHA feature - this may be removed in a future release.
|
||||
ServiceAnnotationILBBackendShare = "cloud.google.com/load-balancer-backend-share"
|
||||
ServiceAnnotationILBBackendShare = "alpha.cloud.google.com/load-balancer-backend-share"
|
||||
// This annotation did not correctly specify "alpha", so both annotations will be checked.
|
||||
deprecatedServiceAnnotationILBBackendShare = "cloud.google.com/load-balancer-backend-share"
|
||||
|
||||
// NetworkTierAnnotationKey is annotated on a Service object to indicate which
|
||||
// network tier a GCP LB should use. The valid values are "Standard" and
|
||||
// "Premium" (default).
|
||||
NetworkTierAnnotationKey = "cloud.google.com/network-tier"
|
||||
NetworkTierAnnotationStandard = "Standard"
|
||||
NetworkTierAnnotationPremium = "Premium"
|
||||
|
||||
NetworkTierStandard NetworkTier = NetworkTierAnnotationStandard
|
||||
NetworkTierPremium NetworkTier = NetworkTierAnnotationPremium
|
||||
NetworkTierDefault NetworkTier = NetworkTierPremium
|
||||
)
|
||||
|
||||
// GetLoadBalancerAnnotationType returns the type of GCP load balancer which should be assembled.
|
||||
|
|
@ -48,8 +71,8 @@ func GetLoadBalancerAnnotationType(service *v1.Service) (LoadBalancerType, bool)
|
|||
}
|
||||
|
||||
switch v {
|
||||
case LBTypeInternal:
|
||||
return v, true
|
||||
case LBTypeInternal, deprecatedTypeInternalLowerCase:
|
||||
return LBTypeInternal, true
|
||||
default:
|
||||
return v, false
|
||||
}
|
||||
|
|
@ -58,10 +81,54 @@ func GetLoadBalancerAnnotationType(service *v1.Service) (LoadBalancerType, bool)
|
|||
// GetLoadBalancerAnnotationBackendShare returns whether this service's backend service should be
|
||||
// shared with other load balancers. Health checks and the healthcheck firewall will be shared regardless.
|
||||
func GetLoadBalancerAnnotationBackendShare(service *v1.Service) bool {
|
||||
l, exists := service.Annotations[ServiceAnnotationILBBackendShare]
|
||||
if exists && l == "true" {
|
||||
if l, exists := service.Annotations[ServiceAnnotationILBBackendShare]; exists && l == "true" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check for deprecated annotation key
|
||||
if l, exists := service.Annotations[deprecatedServiceAnnotationILBBackendShare]; exists && l == "true" {
|
||||
glog.Warningf("Annotation %q is deprecated and replaced with an alpha-specific key: %q", deprecatedServiceAnnotationILBBackendShare, ServiceAnnotationILBBackendShare)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// GetServiceNetworkTier returns the network tier of GCP load balancer
|
||||
// which should be assembled, and an error if the specified tier is not
|
||||
// supported.
|
||||
func GetServiceNetworkTier(service *v1.Service) (NetworkTier, error) {
|
||||
l, ok := service.Annotations[NetworkTierAnnotationKey]
|
||||
if !ok {
|
||||
return NetworkTierDefault, nil
|
||||
}
|
||||
|
||||
v := NetworkTier(l)
|
||||
switch v {
|
||||
case NetworkTierStandard:
|
||||
fallthrough
|
||||
case NetworkTierPremium:
|
||||
return v, nil
|
||||
default:
|
||||
return NetworkTierDefault, fmt.Errorf("unsupported network tier: %q", v)
|
||||
}
|
||||
}
|
||||
|
||||
// ToGCEValue converts NetworkTier to a string that we can populate the
|
||||
// NetworkTier field of GCE objects.
|
||||
func (n NetworkTier) ToGCEValue() string {
|
||||
return strings.ToUpper(string(n))
|
||||
}
|
||||
|
||||
// NetworkTierGCEValueToType converts the value of the NetworkTier field of a
|
||||
// GCE object to the NetworkTier type.
|
||||
func NetworkTierGCEValueToType(s string) NetworkTier {
|
||||
switch s {
|
||||
case "STANDARD":
|
||||
return NetworkTierStandard
|
||||
case "PREMIUM":
|
||||
return NetworkTierPremium
|
||||
default:
|
||||
return NetworkTier(s)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_backendservice.go
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_backendservice.go
generated
vendored
|
|
@ -18,16 +18,12 @@ package gce
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
func newBackendServiceMetricContext(request, region string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"backendservice_" + request, region, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("backendservice", request, region, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
// GetGlobalBackendService retrieves a backend by name.
|
||||
|
|
|
|||
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_cert.go
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_cert.go
generated
vendored
|
|
@ -18,16 +18,12 @@ package gce
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
func newCertMetricContext(request string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"cert_" + request, unusedMetricLabel, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("cert", request, unusedMetricLabel, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
// GetSslCertificate returns the SslCertificate by name.
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_clusterid.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_clusterid.go
generated
vendored
|
|
@ -62,7 +62,7 @@ type ClusterID struct {
|
|||
func (gce *GCECloud) watchClusterID() {
|
||||
gce.ClusterID = ClusterID{
|
||||
cfgMapKey: fmt.Sprintf("%v/%v", UIDNamespace, UIDConfigMapName),
|
||||
client: gce.clientBuilder.ClientOrDie("cloud-provider"),
|
||||
client: gce.client,
|
||||
}
|
||||
|
||||
mapEventHandler := cache.ResourceEventHandlerFuncs{
|
||||
|
|
|
|||
7
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_clusters.go
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_clusters.go
generated
vendored
|
|
@ -16,13 +16,8 @@ limitations under the License.
|
|||
|
||||
package gce
|
||||
|
||||
import "time"
|
||||
|
||||
func newClustersMetricContext(request, zone string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"clusters_" + request, unusedMetricLabel, zone},
|
||||
}
|
||||
return newGenericMetricContext("clusters", request, unusedMetricLabel, zone, computeV1Version)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ListClusters() ([]string, error) {
|
||||
|
|
|
|||
378
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks.go
generated
vendored
378
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks.go
generated
vendored
|
|
@ -21,15 +21,17 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
|
||||
"github.com/golang/glog"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
|
|
@ -39,8 +41,15 @@ const (
|
|||
DiskTypeSSD = "pd-ssd"
|
||||
DiskTypeStandard = "pd-standard"
|
||||
|
||||
diskTypeDefault = DiskTypeStandard
|
||||
diskTypeUriTemplate = "%s/zones/%s/diskTypes/%s"
|
||||
diskTypeDefault = DiskTypeStandard
|
||||
diskTypeURITemplateSingleZone = "%s/zones/%s/diskTypes/%s" // {gce.projectID}/zones/{disk.Zone}/diskTypes/{disk.Type}"
|
||||
diskTypeURITemplateRegional = "%s/regions/%s/diskTypes/%s" // {gce.projectID}/regions/{disk.Region}/diskTypes/{disk.Type}"
|
||||
diskTypePersistent = "PERSISTENT"
|
||||
|
||||
diskSourceURITemplateSingleZone = "%s/zones/%s/disks/%s" // {gce.projectID}/zones/{disk.Zone}/disks/{disk.Name}"
|
||||
diskSourceURITemplateRegional = "%s/regions/%s/disks/%s" //{gce.projectID}/regions/{disk.Region}/disks/repd"
|
||||
|
||||
replicaZoneURITemplateSingleZone = "%s/zones/%s" // {gce.projectID}/zones/{disk.Zone}
|
||||
)
|
||||
|
||||
// Disks is interface for manipulation with GCE PDs.
|
||||
|
|
@ -64,6 +73,11 @@ type Disks interface {
|
|||
// as JSON into Description field.
|
||||
CreateDisk(name string, diskType string, zone string, sizeGb int64, tags map[string]string) error
|
||||
|
||||
// CreateRegionalDisk creates a new Regional Persistent Disk, with the
|
||||
// specified properties, replicated to the specified zones. Tags are
|
||||
// serialized as JSON into Description field.
|
||||
CreateRegionalDisk(name string, diskType string, replicaZones sets.String, sizeGb int64, tags map[string]string) error
|
||||
|
||||
// DeleteDisk deletes PD.
|
||||
DeleteDisk(diskToDelete string) error
|
||||
|
||||
|
|
@ -77,18 +91,55 @@ type Disks interface {
|
|||
// GCECloud implements Disks.
|
||||
var _ Disks = (*GCECloud)(nil)
|
||||
|
||||
// GCECloud implements PVLabeler.
|
||||
var _ cloudprovider.PVLabeler = (*GCECloud)(nil)
|
||||
|
||||
type GCEDisk struct {
|
||||
Zone string
|
||||
Name string
|
||||
Kind string
|
||||
Type string
|
||||
ZoneInfo zoneType
|
||||
Region string
|
||||
Name string
|
||||
Kind string
|
||||
Type string
|
||||
}
|
||||
|
||||
func newDiskMetricContext(request, zone string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"disk_" + request, unusedMetricLabel, zone},
|
||||
type zoneType interface {
|
||||
isZoneType()
|
||||
}
|
||||
|
||||
type multiZone struct {
|
||||
replicaZones sets.String
|
||||
}
|
||||
|
||||
type singleZone struct {
|
||||
zone string
|
||||
}
|
||||
|
||||
func (m multiZone) isZoneType() {}
|
||||
func (s singleZone) isZoneType() {}
|
||||
|
||||
func newDiskMetricContextZonal(request, region, zone string) *metricContext {
|
||||
return newGenericMetricContext("disk", request, region, zone, computeV1Version)
|
||||
}
|
||||
|
||||
func newDiskMetricContextRegional(request, region string) *metricContext {
|
||||
return newGenericMetricContext("disk", request, region, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) GetLabelsForVolume(pv *v1.PersistentVolume) (map[string]string, error) {
|
||||
// Ignore any volumes that are being provisioned
|
||||
if pv.Spec.GCEPersistentDisk.PDName == volume.ProvisionedVolumeName {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// If the zone is already labeled, honor the hint
|
||||
zone := pv.Labels[kubeletapis.LabelZoneFailureDomain]
|
||||
|
||||
labels, err := gce.GetAutoLabelsForPD(pv.Spec.GCEPersistentDisk.PDName, zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return labels, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOnly bool) error {
|
||||
|
|
@ -97,25 +148,41 @@ func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOn
|
|||
if err != nil {
|
||||
return fmt.Errorf("error getting instance %q", instanceName)
|
||||
}
|
||||
disk, err := gce.getDiskByName(diskName, instance.Zone)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
// Try fetching as regional PD
|
||||
var disk *GCEDisk
|
||||
var mc *metricContext
|
||||
if gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||
disk, err = gce.getRegionalDiskByName(diskName)
|
||||
if err != nil {
|
||||
glog.V(5).Infof("Could not find regional PD named %q to Attach. Will look for a zonal PD", diskName)
|
||||
err = nil
|
||||
} else {
|
||||
mc = newDiskMetricContextRegional("attach", gce.region)
|
||||
}
|
||||
}
|
||||
|
||||
if disk == nil {
|
||||
disk, err = gce.getDiskByName(diskName, instance.Zone)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mc = newDiskMetricContextZonal("attach", gce.region, instance.Zone)
|
||||
}
|
||||
|
||||
readWrite := "READ_WRITE"
|
||||
if readOnly {
|
||||
readWrite = "READ_ONLY"
|
||||
}
|
||||
attachedDisk := gce.convertDiskToAttachedDisk(disk, readWrite)
|
||||
|
||||
mc := newDiskMetricContext("attach", instance.Zone)
|
||||
attachOp, err := gce.service.Instances.AttachDisk(
|
||||
gce.projectID, disk.Zone, instance.Name, attachedDisk).Do()
|
||||
attachOp, err := gce.manager.AttachDisk(
|
||||
disk, readWrite, instance.Zone, instance.Name)
|
||||
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForZoneOp(attachOp, disk.Zone, mc)
|
||||
return gce.manager.WaitForZoneOp(attachOp, instance.Zone, mc)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) DetachDisk(devicePath string, nodeName types.NodeName) error {
|
||||
|
|
@ -134,13 +201,13 @@ func (gce *GCECloud) DetachDisk(devicePath string, nodeName types.NodeName) erro
|
|||
return fmt.Errorf("error getting instance %q", instanceName)
|
||||
}
|
||||
|
||||
mc := newDiskMetricContext("detach", inst.Zone)
|
||||
detachOp, err := gce.service.Instances.DetachDisk(gce.projectID, inst.Zone, inst.Name, devicePath).Do()
|
||||
mc := newDiskMetricContextZonal("detach", gce.region, inst.Zone)
|
||||
detachOp, err := gce.manager.DetachDisk(inst.Zone, inst.Name, devicePath)
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForZoneOp(detachOp, inst.Zone, mc)
|
||||
return gce.manager.WaitForZoneOp(detachOp, inst.Zone, mc)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) DiskIsAttached(diskName string, nodeName types.NodeName) (bool, error) {
|
||||
|
|
@ -209,14 +276,7 @@ func (gce *GCECloud) CreateDisk(
|
|||
|
||||
// Do not allow creation of PDs in zones that are not managed. Such PDs
|
||||
// then cannot be deleted by DeleteDisk.
|
||||
isManaged := false
|
||||
for _, managedZone := range gce.managedZones {
|
||||
if zone == managedZone {
|
||||
isManaged = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isManaged {
|
||||
if isManaged := gce.verifyZoneIsManaged(zone); !isManaged {
|
||||
return fmt.Errorf("kubernetes does not manage zone %q", zone)
|
||||
}
|
||||
|
||||
|
|
@ -225,30 +285,16 @@ func (gce *GCECloud) CreateDisk(
|
|||
return err
|
||||
}
|
||||
|
||||
switch diskType {
|
||||
case DiskTypeSSD, DiskTypeStandard:
|
||||
// noop
|
||||
case "":
|
||||
diskType = diskTypeDefault
|
||||
default:
|
||||
return fmt.Errorf("invalid GCE disk type %q", diskType)
|
||||
diskType, err = getDiskType(diskType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
projectsApiEndpoint := gceComputeAPIEndpoint + "projects/"
|
||||
if gce.service != nil {
|
||||
projectsApiEndpoint = gce.service.BasePath
|
||||
}
|
||||
diskTypeUri := projectsApiEndpoint + fmt.Sprintf(diskTypeUriTemplate, gce.projectID, zone, diskType)
|
||||
mc := newDiskMetricContextZonal("create", gce.region, zone)
|
||||
|
||||
diskToCreate := &compute.Disk{
|
||||
Name: name,
|
||||
SizeGb: sizeGb,
|
||||
Description: tagsStr,
|
||||
Type: diskTypeUri,
|
||||
}
|
||||
createOp, err := gce.manager.CreateDisk(
|
||||
name, sizeGb, tagsStr, diskType, zone)
|
||||
|
||||
mc := newDiskMetricContext("create", zone)
|
||||
createOp, err := gce.manager.CreateDisk(gce.projectID, zone, diskToCreate)
|
||||
if isGCEError(err, "alreadyExists") {
|
||||
glog.Warningf("GCE PD %q already exists, reusing", name)
|
||||
return nil
|
||||
|
|
@ -264,6 +310,76 @@ func (gce *GCECloud) CreateDisk(
|
|||
return err
|
||||
}
|
||||
|
||||
// CreateRegionalDisk creates a new Regional Persistent Disk, with the specified
|
||||
// name & size, replicated to the specified zones. It stores specified tags
|
||||
// encoded in JSON in Description field.
|
||||
func (gce *GCECloud) CreateRegionalDisk(
|
||||
name string, diskType string, replicaZones sets.String, sizeGb int64, tags map[string]string) error {
|
||||
|
||||
// Do not allow creation of PDs in zones that are not managed. Such PDs
|
||||
// then cannot be deleted by DeleteDisk.
|
||||
unmanagedZones := []string{}
|
||||
for _, zone := range replicaZones.UnsortedList() {
|
||||
if isManaged := gce.verifyZoneIsManaged(zone); !isManaged {
|
||||
unmanagedZones = append(unmanagedZones, zone)
|
||||
}
|
||||
}
|
||||
|
||||
if len(unmanagedZones) > 0 {
|
||||
return fmt.Errorf("kubernetes does not manage specified zones: %q. Managed Zones: %q", unmanagedZones, gce.managedZones)
|
||||
}
|
||||
|
||||
tagsStr, err := gce.encodeDiskTags(tags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
diskType, err = getDiskType(diskType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mc := newDiskMetricContextRegional("create", gce.region)
|
||||
|
||||
createOp, err := gce.manager.CreateRegionalDisk(
|
||||
name, sizeGb, tagsStr, diskType, replicaZones)
|
||||
|
||||
if isGCEError(err, "alreadyExists") {
|
||||
glog.Warningf("GCE PD %q already exists, reusing", name)
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
err = gce.manager.WaitForRegionalOp(createOp, mc)
|
||||
if isGCEError(err, "alreadyExists") {
|
||||
glog.Warningf("GCE PD %q already exists, reusing", name)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (gce *GCECloud) verifyZoneIsManaged(zone string) bool {
|
||||
for _, managedZone := range gce.managedZones {
|
||||
if zone == managedZone {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func getDiskType(diskType string) (string, error) {
|
||||
switch diskType {
|
||||
case DiskTypeSSD, DiskTypeStandard:
|
||||
return diskType, nil
|
||||
case "":
|
||||
return diskTypeDefault, nil
|
||||
default:
|
||||
return "", fmt.Errorf("invalid GCE disk type %q", diskType)
|
||||
}
|
||||
}
|
||||
|
||||
func (gce *GCECloud) DeleteDisk(diskToDelete string) error {
|
||||
err := gce.doDeleteDisk(diskToDelete)
|
||||
if isGCEError(err, "resourceInUseByAnotherResource") {
|
||||
|
|
@ -285,40 +401,66 @@ func (gce *GCECloud) GetAutoLabelsForPD(name string, zone string) (map[string]st
|
|||
var disk *GCEDisk
|
||||
var err error
|
||||
if zone == "" {
|
||||
// We would like as far as possible to avoid this case,
|
||||
// because GCE doesn't guarantee that volumes are uniquely named per region,
|
||||
// just per zone. However, creation of GCE PDs was originally done only
|
||||
// by name, so we have to continue to support that.
|
||||
// However, wherever possible the zone should be passed (and it is passed
|
||||
// for most cases that we can control, e.g. dynamic volume provisioning)
|
||||
// For regional PDs this is fine, but for zonal PDs we would like as far
|
||||
// as possible to avoid this case, because GCE doesn't guarantee that
|
||||
// volumes are uniquely named per region, just per zone. However,
|
||||
// creation of GCE PDs was originally done only by name, so we have to
|
||||
// continue to support that.
|
||||
// However, wherever possible the zone should be passed (and it is
|
||||
// passed for most cases that we can control, e.g. dynamic volume
|
||||
// provisioning).
|
||||
disk, err = gce.GetDiskByNameUnknownZone(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zone = disk.Zone
|
||||
} else {
|
||||
// We could assume the disks exists; we have all the information we need
|
||||
// However it is more consistent to ensure the disk exists,
|
||||
// and in future we may gather addition information (e.g. disk type, IOPS etc)
|
||||
disk, err = gce.getDiskByName(name, zone)
|
||||
zoneSet, err := volumeutil.LabelZonesToSet(zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
glog.Warningf("Failed to parse zone field: %q. Will use raw field.", zone)
|
||||
}
|
||||
|
||||
if len(zoneSet) > 1 {
|
||||
// Regional PD
|
||||
disk, err = gce.getRegionalDiskByName(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// Zonal PD
|
||||
disk, err = gce.getDiskByName(name, zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
region, err := GetGCERegion(zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if zone == "" || region == "" {
|
||||
// Unexpected, but sanity-check
|
||||
return nil, fmt.Errorf("PD did not have zone/region information: %q", disk.Name)
|
||||
}
|
||||
|
||||
labels := make(map[string]string)
|
||||
labels[kubeletapis.LabelZoneFailureDomain] = zone
|
||||
labels[kubeletapis.LabelZoneRegion] = region
|
||||
switch zoneInfo := disk.ZoneInfo.(type) {
|
||||
case singleZone:
|
||||
if zoneInfo.zone == "" || disk.Region == "" {
|
||||
// Unexpected, but sanity-check
|
||||
return nil, fmt.Errorf("PD did not have zone/region information: %v", disk)
|
||||
}
|
||||
labels[kubeletapis.LabelZoneFailureDomain] = zoneInfo.zone
|
||||
labels[kubeletapis.LabelZoneRegion] = disk.Region
|
||||
case multiZone:
|
||||
if zoneInfo.replicaZones == nil || zoneInfo.replicaZones.Len() <= 0 {
|
||||
// Unexpected, but sanity-check
|
||||
return nil, fmt.Errorf("PD is regional but does not have any replicaZones specified: %v", disk)
|
||||
}
|
||||
labels[kubeletapis.LabelZoneFailureDomain] =
|
||||
volumeutil.ZonesSetToLabelValue(zoneInfo.replicaZones)
|
||||
labels[kubeletapis.LabelZoneRegion] = disk.Region
|
||||
case nil:
|
||||
// Unexpected, but sanity-check
|
||||
return nil, fmt.Errorf("PD did not have ZoneInfo: %v", disk)
|
||||
default:
|
||||
// Unexpected, but sanity-check
|
||||
return nil, fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo)
|
||||
}
|
||||
|
||||
return labels, nil
|
||||
}
|
||||
|
|
@ -326,16 +468,10 @@ func (gce *GCECloud) GetAutoLabelsForPD(name string, zone string) (map[string]st
|
|||
// Returns a GCEDisk for the disk, if it is found in the specified zone.
|
||||
// If not found, returns (nil, nil)
|
||||
func (gce *GCECloud) findDiskByName(diskName string, zone string) (*GCEDisk, error) {
|
||||
mc := newDiskMetricContext("get", zone)
|
||||
disk, err := gce.manager.GetDisk(gce.projectID, zone, diskName)
|
||||
mc := newDiskMetricContextZonal("get", gce.region, zone)
|
||||
disk, err := gce.manager.GetDisk(zone, diskName)
|
||||
if err == nil {
|
||||
d := &GCEDisk{
|
||||
Zone: lastComponent(disk.Zone),
|
||||
Name: disk.Name,
|
||||
Kind: disk.Kind,
|
||||
Type: disk.Type,
|
||||
}
|
||||
return d, mc.Observe(nil)
|
||||
return disk, mc.Observe(nil)
|
||||
}
|
||||
if !isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return nil, mc.Observe(err)
|
||||
|
|
@ -352,10 +488,40 @@ func (gce *GCECloud) getDiskByName(diskName string, zone string) (*GCEDisk, erro
|
|||
return disk, err
|
||||
}
|
||||
|
||||
// Returns a GCEDisk for the regional disk, if it is found.
|
||||
// If not found, returns (nil, nil)
|
||||
func (gce *GCECloud) findRegionalDiskByName(diskName string) (*GCEDisk, error) {
|
||||
mc := newDiskMetricContextRegional("get", gce.region)
|
||||
disk, err := gce.manager.GetRegionalDisk(diskName)
|
||||
if err == nil {
|
||||
return disk, mc.Observe(nil)
|
||||
}
|
||||
if !isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
return nil, mc.Observe(nil)
|
||||
}
|
||||
|
||||
// Like findRegionalDiskByName, but returns an error if the disk is not found
|
||||
func (gce *GCECloud) getRegionalDiskByName(diskName string) (*GCEDisk, error) {
|
||||
disk, err := gce.findRegionalDiskByName(diskName)
|
||||
if disk == nil && err == nil {
|
||||
return nil, fmt.Errorf("GCE regional persistent disk not found: diskName=%q", diskName)
|
||||
}
|
||||
return disk, err
|
||||
}
|
||||
|
||||
// Scans all managed zones to return the GCE PD
|
||||
// Prefer getDiskByName, if the zone can be established
|
||||
// Return cloudprovider.DiskNotFound if the given disk cannot be found in any zone
|
||||
func (gce *GCECloud) GetDiskByNameUnknownZone(diskName string) (*GCEDisk, error) {
|
||||
if gce.AlphaFeatureGate.Enabled(GCEDiskAlphaFeatureGate) {
|
||||
regionalDisk, err := gce.getRegionalDiskByName(diskName)
|
||||
if err == nil {
|
||||
return regionalDisk, err
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this is the gotcha right now with GCE PD support:
|
||||
// disk names are not unique per-region.
|
||||
// (I can create two volumes with name "myvol" in e.g. us-central1-b & us-central1-f)
|
||||
|
|
@ -378,7 +544,17 @@ func (gce *GCECloud) GetDiskByNameUnknownZone(diskName string) (*GCEDisk, error)
|
|||
continue
|
||||
}
|
||||
if found != nil {
|
||||
return nil, fmt.Errorf("GCE persistent disk name was found in multiple zones: %q", diskName)
|
||||
switch zoneInfo := disk.ZoneInfo.(type) {
|
||||
case multiZone:
|
||||
if zoneInfo.replicaZones.Has(zone) {
|
||||
glog.Warningf("GCE PD name (%q) was found in multiple zones (%q), but ok because it is a RegionalDisk.",
|
||||
diskName, zoneInfo.replicaZones)
|
||||
continue
|
||||
}
|
||||
return nil, fmt.Errorf("GCE PD name was found in multiple zones: %q", diskName)
|
||||
default:
|
||||
return nil, fmt.Errorf("GCE PD name was found in multiple zones: %q", diskName)
|
||||
}
|
||||
}
|
||||
found = disk
|
||||
}
|
||||
|
|
@ -412,25 +588,27 @@ func (gce *GCECloud) doDeleteDisk(diskToDelete string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
mc := newDiskMetricContext("delete", disk.Zone)
|
||||
var mc *metricContext
|
||||
|
||||
deleteOp, err := gce.manager.DeleteDisk(gce.projectID, disk.Zone, disk.Name)
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.manager.WaitForZoneOp(deleteOp, disk.Zone, mc)
|
||||
}
|
||||
|
||||
// Converts a Disk resource to an AttachedDisk resource.
|
||||
func (gce *GCECloud) convertDiskToAttachedDisk(disk *GCEDisk, readWrite string) *compute.AttachedDisk {
|
||||
return &compute.AttachedDisk{
|
||||
DeviceName: disk.Name,
|
||||
Kind: disk.Kind,
|
||||
Mode: readWrite,
|
||||
Source: gce.service.BasePath + strings.Join([]string{
|
||||
gce.projectID, "zones", disk.Zone, "disks", disk.Name}, "/"),
|
||||
Type: "PERSISTENT",
|
||||
switch zoneInfo := disk.ZoneInfo.(type) {
|
||||
case singleZone:
|
||||
mc = newDiskMetricContextZonal("delete", disk.Region, zoneInfo.zone)
|
||||
deleteOp, err := gce.manager.DeleteDisk(zoneInfo.zone, disk.Name)
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.manager.WaitForZoneOp(deleteOp, zoneInfo.zone, mc)
|
||||
case multiZone:
|
||||
mc = newDiskMetricContextRegional("delete", disk.Region)
|
||||
deleteOp, err := gce.manager.DeleteRegionalDisk(disk.Name)
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.manager.WaitForRegionalOp(deleteOp, mc)
|
||||
case nil:
|
||||
return fmt.Errorf("PD has nil ZoneInfo: %v", disk)
|
||||
default:
|
||||
return fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
21
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_firewall.go
generated
vendored
21
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_firewall.go
generated
vendored
|
|
@ -17,53 +17,48 @@ limitations under the License.
|
|||
package gce
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
func newFirewallMetricContext(request string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"firewall_" + request, unusedMetricLabel, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("firewall", request, unusedMetricLabel, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
// GetFirewall returns the Firewall by name.
|
||||
func (gce *GCECloud) GetFirewall(name string) (*compute.Firewall, error) {
|
||||
mc := newFirewallMetricContext("get")
|
||||
v, err := gce.service.Firewalls.Get(gce.projectID, name).Do()
|
||||
v, err := gce.service.Firewalls.Get(gce.NetworkProjectID(), name).Do()
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// CreateFirewall creates the passed firewall
|
||||
func (gce *GCECloud) CreateFirewall(f *compute.Firewall) error {
|
||||
mc := newFirewallMetricContext("create")
|
||||
op, err := gce.service.Firewalls.Insert(gce.projectID, f).Do()
|
||||
op, err := gce.service.Firewalls.Insert(gce.NetworkProjectID(), f).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return gce.waitForGlobalOpInProject(op, gce.NetworkProjectID(), mc)
|
||||
}
|
||||
|
||||
// DeleteFirewall deletes the given firewall rule.
|
||||
func (gce *GCECloud) DeleteFirewall(name string) error {
|
||||
mc := newFirewallMetricContext("delete")
|
||||
op, err := gce.service.Firewalls.Delete(gce.projectID, name).Do()
|
||||
op, err := gce.service.Firewalls.Delete(gce.NetworkProjectID(), name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return gce.waitForGlobalOpInProject(op, gce.NetworkProjectID(), mc)
|
||||
}
|
||||
|
||||
// UpdateFirewall applies the given firewall as an update to an existing service.
|
||||
func (gce *GCECloud) UpdateFirewall(f *compute.Firewall) error {
|
||||
mc := newFirewallMetricContext("update")
|
||||
op, err := gce.service.Firewalls.Update(gce.projectID, f.Name, f).Do()
|
||||
op, err := gce.service.Firewalls.Update(gce.NetworkProjectID(), f.Name, f).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return gce.waitForGlobalOpInProject(op, gce.NetworkProjectID(), mc)
|
||||
}
|
||||
|
|
|
|||
50
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule.go
generated
vendored
50
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule.go
generated
vendored
|
|
@ -17,16 +17,15 @@ limitations under the License.
|
|||
package gce
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
func newForwardingRuleMetricContext(request, region string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"forwardingrule_" + request, region, unusedMetricLabel},
|
||||
}
|
||||
return newForwardingRuleMetricContextWithVersion(request, region, computeV1Version)
|
||||
}
|
||||
func newForwardingRuleMetricContextWithVersion(request, region, version string) *metricContext {
|
||||
return newGenericMetricContext("forwardingrule", request, region, unusedMetricLabel, version)
|
||||
}
|
||||
|
||||
// CreateGlobalForwardingRule creates the passed GlobalForwardingRule
|
||||
|
|
@ -85,6 +84,13 @@ func (gce *GCECloud) GetRegionForwardingRule(name, region string) (*compute.Forw
|
|||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetAlphaRegionForwardingRule returns the Alpha forwarding rule by name & region.
|
||||
func (gce *GCECloud) GetAlphaRegionForwardingRule(name, region string) (*computealpha.ForwardingRule, error) {
|
||||
mc := newForwardingRuleMetricContextWithVersion("get", region, computeAlphaVersion)
|
||||
v, err := gce.serviceAlpha.ForwardingRules.Get(gce.projectID, region, name).Do()
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// ListRegionForwardingRules lists all RegionalForwardingRules in the project & region.
|
||||
func (gce *GCECloud) ListRegionForwardingRules(region string) (*compute.ForwardingRuleList, error) {
|
||||
mc := newForwardingRuleMetricContext("list", region)
|
||||
|
|
@ -93,6 +99,14 @@ func (gce *GCECloud) ListRegionForwardingRules(region string) (*compute.Forwardi
|
|||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// ListRegionForwardingRules lists all RegionalForwardingRules in the project & region.
|
||||
func (gce *GCECloud) ListAlphaRegionForwardingRules(region string) (*computealpha.ForwardingRuleList, error) {
|
||||
mc := newForwardingRuleMetricContextWithVersion("list", region, computeAlphaVersion)
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.serviceAlpha.ForwardingRules.List(gce.projectID, region).Do()
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// CreateRegionForwardingRule creates and returns a
|
||||
// RegionalForwardingRule that points to the given BackendService
|
||||
func (gce *GCECloud) CreateRegionForwardingRule(rule *compute.ForwardingRule, region string) error {
|
||||
|
|
@ -105,6 +119,18 @@ func (gce *GCECloud) CreateRegionForwardingRule(rule *compute.ForwardingRule, re
|
|||
return gce.waitForRegionOp(op, region, mc)
|
||||
}
|
||||
|
||||
// CreateAlphaRegionForwardingRule creates and returns an Alpha
|
||||
// forwarding fule in the given region.
|
||||
func (gce *GCECloud) CreateAlphaRegionForwardingRule(rule *computealpha.ForwardingRule, region string) error {
|
||||
mc := newForwardingRuleMetricContextWithVersion("create", region, computeAlphaVersion)
|
||||
op, err := gce.serviceAlpha.ForwardingRules.Insert(gce.projectID, region, rule).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
}
|
||||
|
||||
// DeleteRegionForwardingRule deletes the RegionalForwardingRule by name & region.
|
||||
func (gce *GCECloud) DeleteRegionForwardingRule(name, region string) error {
|
||||
mc := newForwardingRuleMetricContext("delete", region)
|
||||
|
|
@ -115,3 +141,15 @@ func (gce *GCECloud) DeleteRegionForwardingRule(name, region string) error {
|
|||
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
}
|
||||
|
||||
// TODO(#51665): retire this function once Network Tiers becomes Beta in GCP.
|
||||
func (gce *GCECloud) getNetworkTierFromForwardingRule(name, region string) (string, error) {
|
||||
if !gce.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
||||
return NetworkTierDefault.ToGCEValue(), nil
|
||||
}
|
||||
fwdRule, err := gce.GetAlphaRegionForwardingRule(name, region)
|
||||
if err != nil {
|
||||
return handleAlphaNetworkTierGetError(err)
|
||||
}
|
||||
return fwdRule.NetworkTier, nil
|
||||
}
|
||||
|
|
|
|||
138
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule_fakes.go
generated
vendored
Normal file
138
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule_fakes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
Copyright 2017 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 gce
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
type FakeCloudForwardingRuleService struct {
|
||||
// fwdRulesByRegionAndName
|
||||
// Outer key is for region string; inner key is for fwdRuleess name.
|
||||
fwdRulesByRegionAndName map[string]map[string]*computealpha.ForwardingRule
|
||||
}
|
||||
|
||||
// FakeCloudForwardingRuleService Implements CloudForwardingRuleService
|
||||
var _ CloudForwardingRuleService = &FakeCloudForwardingRuleService{}
|
||||
|
||||
func NewFakeCloudForwardingRuleService() *FakeCloudForwardingRuleService {
|
||||
return &FakeCloudForwardingRuleService{
|
||||
fwdRulesByRegionAndName: make(map[string]map[string]*computealpha.ForwardingRule),
|
||||
}
|
||||
}
|
||||
|
||||
// SetRegionalForwardingRulees sets the fwdRuleesses of ther region. This is used for
|
||||
// setting the test environment.
|
||||
func (f *FakeCloudForwardingRuleService) SetRegionalForwardingRulees(region string, fwdRules []*computealpha.ForwardingRule) {
|
||||
// Reset fwdRuleesses in the region.
|
||||
f.fwdRulesByRegionAndName[region] = make(map[string]*computealpha.ForwardingRule)
|
||||
|
||||
for _, fwdRule := range fwdRules {
|
||||
f.fwdRulesByRegionAndName[region][fwdRule.Name] = fwdRule
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) CreateAlphaRegionForwardingRule(fwdRule *computealpha.ForwardingRule, region string) error {
|
||||
if _, exists := f.fwdRulesByRegionAndName[region]; !exists {
|
||||
f.fwdRulesByRegionAndName[region] = make(map[string]*computealpha.ForwardingRule)
|
||||
}
|
||||
|
||||
if _, exists := f.fwdRulesByRegionAndName[region][fwdRule.Name]; exists {
|
||||
return &googleapi.Error{Code: http.StatusConflict}
|
||||
}
|
||||
|
||||
f.fwdRulesByRegionAndName[region][fwdRule.Name] = fwdRule
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) CreateRegionForwardingRule(fwdRule *compute.ForwardingRule, region string) error {
|
||||
alphafwdRule := convertToAlphaForwardingRule(fwdRule)
|
||||
return f.CreateAlphaRegionForwardingRule(alphafwdRule, region)
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) DeleteRegionForwardingRule(name, region string) error {
|
||||
if _, exists := f.fwdRulesByRegionAndName[region]; !exists {
|
||||
return makeGoogleAPINotFoundError("")
|
||||
}
|
||||
|
||||
if _, exists := f.fwdRulesByRegionAndName[region][name]; !exists {
|
||||
return makeGoogleAPINotFoundError("")
|
||||
}
|
||||
delete(f.fwdRulesByRegionAndName[region], name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) GetAlphaRegionForwardingRule(name, region string) (*computealpha.ForwardingRule, error) {
|
||||
if _, exists := f.fwdRulesByRegionAndName[region]; !exists {
|
||||
return nil, makeGoogleAPINotFoundError("")
|
||||
}
|
||||
|
||||
if fwdRule, exists := f.fwdRulesByRegionAndName[region][name]; !exists {
|
||||
return nil, makeGoogleAPINotFoundError("")
|
||||
} else {
|
||||
return fwdRule, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) GetRegionForwardingRule(name, region string) (*compute.ForwardingRule, error) {
|
||||
fwdRule, err := f.GetAlphaRegionForwardingRule(name, region)
|
||||
if fwdRule != nil {
|
||||
return convertToV1ForwardingRule(fwdRule), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) getNetworkTierFromForwardingRule(name, region string) (string, error) {
|
||||
fwdRule, err := f.GetAlphaRegionForwardingRule(name, region)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fwdRule.NetworkTier, nil
|
||||
}
|
||||
|
||||
func convertToV1ForwardingRule(object gceObject) *compute.ForwardingRule {
|
||||
enc, err := object.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to encode to json: %v", err))
|
||||
}
|
||||
var fwdRule compute.ForwardingRule
|
||||
if err := json.Unmarshal(enc, &fwdRule); err != nil {
|
||||
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to v1 fwdRuleess: %v", object, err))
|
||||
}
|
||||
return &fwdRule
|
||||
}
|
||||
|
||||
func convertToAlphaForwardingRule(object gceObject) *computealpha.ForwardingRule {
|
||||
enc, err := object.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to encode to json: %v", err))
|
||||
}
|
||||
var fwdRule computealpha.ForwardingRule
|
||||
if err := json.Unmarshal(enc, &fwdRule); err != nil {
|
||||
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to alpha fwdRuleess: %v", object, err))
|
||||
}
|
||||
// Set the default values for the Alpha fields.
|
||||
fwdRule.NetworkTier = NetworkTierDefault.ToGCEValue()
|
||||
|
||||
return &fwdRule
|
||||
}
|
||||
7
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_healthchecks.go
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_healthchecks.go
generated
vendored
|
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||
package gce
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/kubernetes/pkg/master/ports"
|
||||
utilversion "k8s.io/kubernetes/pkg/util/version"
|
||||
|
|
@ -45,10 +43,7 @@ func init() {
|
|||
}
|
||||
|
||||
func newHealthcheckMetricContext(request string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"healthcheck_" + request, unusedMetricLabel, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("healthcheck", request, unusedMetricLabel, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
// GetHttpHealthCheck returns the given HttpHealthCheck by name.
|
||||
|
|
|
|||
11
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instancegroup.go
generated
vendored
11
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instancegroup.go
generated
vendored
|
|
@ -16,17 +16,10 @@ limitations under the License.
|
|||
|
||||
package gce
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
import compute "google.golang.org/api/compute/v1"
|
||||
|
||||
func newInstanceGroupMetricContext(request string, zone string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"instancegroup_" + request, unusedMetricLabel, zone},
|
||||
}
|
||||
return newGenericMetricContext("instancegroup", request, unusedMetricLabel, zone, computeV1Version)
|
||||
}
|
||||
|
||||
// CreateInstanceGroup creates an instance group with the given
|
||||
|
|
|
|||
51
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instances.go
generated
vendored
51
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instances.go
generated
vendored
|
|
@ -17,7 +17,9 @@ limitations under the License.
|
|||
package gce
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -25,6 +27,7 @@ import (
|
|||
|
||||
"cloud.google.com/go/compute/metadata"
|
||||
"github.com/golang/glog"
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
|
|
@ -41,10 +44,7 @@ const (
|
|||
)
|
||||
|
||||
func newInstancesMetricContext(request, zone string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"instances_" + request, unusedMetricLabel, zone},
|
||||
}
|
||||
return newGenericMetricContext("instances", request, unusedMetricLabel, zone, computeV1Version)
|
||||
}
|
||||
|
||||
func splitNodesByZone(nodes []*v1.Node) map[string][]*v1.Node {
|
||||
|
|
@ -154,6 +154,12 @@ func (gce *GCECloud) ExternalID(nodeName types.NodeName) (string, error) {
|
|||
return strconv.FormatUint(inst.ID, 10), nil
|
||||
}
|
||||
|
||||
// InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running.
|
||||
// If false is returned with no error, the instance will be immediately deleted by the cloud controller manager.
|
||||
func (gce *GCECloud) InstanceExistsByProviderID(providerID string) (bool, error) {
|
||||
return false, errors.New("unimplemented")
|
||||
}
|
||||
|
||||
// InstanceID returns the cloud provider ID of the node with the specified NodeName.
|
||||
func (gce *GCECloud) InstanceID(nodeName types.NodeName) (string, error) {
|
||||
instanceName := mapNodeNameToInstanceName(nodeName)
|
||||
|
|
@ -318,6 +324,43 @@ func (gce *GCECloud) AliasRanges(nodeName types.NodeName) (cidrs []string, err e
|
|||
return
|
||||
}
|
||||
|
||||
// AddAliasToInstance adds an alias to the given instance from the named
|
||||
// secondary range.
|
||||
func (gce *GCECloud) AddAliasToInstance(nodeName types.NodeName, alias *net.IPNet) error {
|
||||
|
||||
v1instance, err := gce.getInstanceByName(mapNodeNameToInstanceName(nodeName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
instance, err := gce.serviceAlpha.Instances.Get(gce.projectID, v1instance.Zone, v1instance.Name).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch len(instance.NetworkInterfaces) {
|
||||
case 0:
|
||||
return fmt.Errorf("Instance %q has no network interfaces", nodeName)
|
||||
case 1:
|
||||
default:
|
||||
glog.Warningf("Instance %q has more than one network interface, using only the first (%v)",
|
||||
nodeName, instance.NetworkInterfaces)
|
||||
}
|
||||
|
||||
iface := instance.NetworkInterfaces[0]
|
||||
iface.AliasIpRanges = append(iface.AliasIpRanges, &computealpha.AliasIpRange{
|
||||
IpCidrRange: alias.String(),
|
||||
SubnetworkRangeName: gce.secondaryRangeName,
|
||||
})
|
||||
|
||||
mc := newInstancesMetricContext("addalias", v1instance.Zone)
|
||||
op, err := gce.serviceAlpha.Instances.UpdateNetworkInterface(
|
||||
gce.projectID, instance.Zone, instance.Name, iface.Name, iface).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForZoneOp(op, v1instance.Zone, mc)
|
||||
}
|
||||
|
||||
// Gets the named instances, returning cloudprovider.InstanceNotFound if any instance is not found
|
||||
func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error) {
|
||||
instances := make(map[string]*gceInstance)
|
||||
|
|
|
|||
42
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_interfaces.go
generated
vendored
42
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_interfaces.go
generated
vendored
|
|
@ -16,12 +16,46 @@ limitations under the License.
|
|||
|
||||
package gce
|
||||
|
||||
import compute "google.golang.org/api/compute/v1"
|
||||
import (
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
// These interfaces are added for testability.
|
||||
|
||||
// CloudAddressService is an interface for managing addresses
|
||||
type CloudAddressService interface {
|
||||
ReserveRegionAddress(*compute.Address, string) error
|
||||
GetRegionAddress(string, string) (*compute.Address, error)
|
||||
// TODO: Mock `DeleteRegionAddress(name, region string) endpoint
|
||||
ReserveRegionAddress(address *compute.Address, region string) error
|
||||
GetRegionAddress(name string, region string) (*compute.Address, error)
|
||||
GetRegionAddressByIP(region, ipAddress string) (*compute.Address, error)
|
||||
DeleteRegionAddress(name, region string) error
|
||||
// TODO: Mock Global endpoints
|
||||
|
||||
// Alpha API.
|
||||
GetAlphaRegionAddress(name, region string) (*computealpha.Address, error)
|
||||
ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error
|
||||
|
||||
// Beta API
|
||||
ReserveBetaRegionAddress(address *computebeta.Address, region string) error
|
||||
GetBetaRegionAddress(name string, region string) (*computebeta.Address, error)
|
||||
GetBetaRegionAddressByIP(region, ipAddress string) (*computebeta.Address, error)
|
||||
|
||||
// TODO(#51665): Remove this once the Network Tiers becomes Alpha in GCP.
|
||||
getNetworkTierFromAddress(name, region string) (string, error)
|
||||
}
|
||||
|
||||
// CloudForwardingRuleService is an interface for managing forwarding rules.
|
||||
// TODO: Expand the interface to include more methods.
|
||||
type CloudForwardingRuleService interface {
|
||||
GetRegionForwardingRule(name, region string) (*compute.ForwardingRule, error)
|
||||
CreateRegionForwardingRule(rule *compute.ForwardingRule, region string) error
|
||||
DeleteRegionForwardingRule(name, region string) error
|
||||
|
||||
// Alpha API.
|
||||
GetAlphaRegionForwardingRule(name, region string) (*computealpha.ForwardingRule, error)
|
||||
CreateAlphaRegionForwardingRule(rule *computealpha.ForwardingRule, region string) error
|
||||
|
||||
// Needed for the Alpha "Network Tiers" feature.
|
||||
getNetworkTierFromForwardingRule(name, region string) (string, error)
|
||||
}
|
||||
|
|
|
|||
9
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer.go
generated
vendored
9
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer.go
generated
vendored
|
|
@ -21,7 +21,6 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
|
|
@ -40,10 +39,7 @@ var (
|
|||
)
|
||||
|
||||
func newLoadBalancerMetricContext(request, region string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"loadbalancer_" + request, region, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("loadbalancer", request, region, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
type lbScheme string
|
||||
|
|
@ -141,6 +137,9 @@ func (gce *GCECloud) EnsureLoadBalancer(clusterName string, svc *v1.Service, nod
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Assume the ensureDeleted function successfully deleted the forwarding rule.
|
||||
existingFwdRule = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
447
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go
generated
vendored
447
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go
generated
vendored
|
|
@ -31,6 +31,7 @@ import (
|
|||
netsets "k8s.io/kubernetes/pkg/util/net/sets"
|
||||
|
||||
"github.com/golang/glog"
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
|
|
@ -55,7 +56,7 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
|||
}
|
||||
|
||||
loadBalancerName := cloudprovider.GetLoadBalancerName(apiService)
|
||||
loadBalancerIP := apiService.Spec.LoadBalancerIP
|
||||
requestedIP := apiService.Spec.LoadBalancerIP
|
||||
ports := apiService.Spec.Ports
|
||||
portStr := []string{}
|
||||
for _, p := range apiService.Spec.Ports {
|
||||
|
|
@ -66,10 +67,23 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
|||
|
||||
serviceName := types.NamespacedName{Namespace: apiService.Namespace, Name: apiService.Name}
|
||||
glog.V(2).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v, %v, %v)",
|
||||
loadBalancerName, gce.region, loadBalancerIP, portStr, hostNames, serviceName, apiService.Annotations)
|
||||
loadBalancerName, gce.region, requestedIP, portStr, hostNames, serviceName, apiService.Annotations)
|
||||
|
||||
lbRefStr := fmt.Sprintf("%v(%v)", loadBalancerName, serviceName)
|
||||
// Check the current and the desired network tiers. If they do not match,
|
||||
// tear down the existing resources with the wrong tier.
|
||||
netTier, err := gce.getServiceNetworkTier(apiService)
|
||||
if err != nil {
|
||||
glog.Errorf("EnsureLoadBalancer(%s): failed to get the desired network tier: %v", lbRefStr, err)
|
||||
return nil, err
|
||||
}
|
||||
glog.V(4).Infof("EnsureLoadBalancer(%s): desired network tier %q ", lbRefStr, netTier)
|
||||
if gce.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
||||
gce.deleteWrongNetworkTieredResources(loadBalancerName, lbRefStr, netTier)
|
||||
}
|
||||
|
||||
// Check if the forwarding rule exists, and if so, what its IP is.
|
||||
fwdRuleExists, fwdRuleNeedsUpdate, fwdRuleIP, err := gce.forwardingRuleNeedsUpdate(loadBalancerName, gce.region, loadBalancerIP, ports)
|
||||
fwdRuleExists, fwdRuleNeedsUpdate, fwdRuleIP, err := gce.forwardingRuleNeedsUpdate(loadBalancerName, gce.region, requestedIP, ports)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -93,7 +107,7 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
|||
// forwarding rule creation as the last thing that needs to be done in this
|
||||
// function in order to maintain the invariant that "if the forwarding rule
|
||||
// exists, the LB has been fully created".
|
||||
ipAddress := ""
|
||||
ipAddressToUse := ""
|
||||
|
||||
// Through this process we try to keep track of whether it is safe to
|
||||
// release the IP that was allocated. If the user specifically asked for
|
||||
|
|
@ -110,75 +124,41 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
|||
}
|
||||
if isSafeToReleaseIP {
|
||||
if err := gce.DeleteRegionAddress(loadBalancerName, gce.region); err != nil && !isNotFound(err) {
|
||||
glog.Errorf("failed to release static IP %s for load balancer (%v(%v), %v): %v", ipAddress, loadBalancerName, serviceName, gce.region, err)
|
||||
glog.Errorf("Failed to release static IP %s for load balancer (%v(%v), %v): %v", ipAddressToUse, loadBalancerName, serviceName, gce.region, err)
|
||||
} else if isNotFound(err) {
|
||||
glog.V(2).Infof("EnsureLoadBalancer(%v(%v)): address %s is not reserved.", loadBalancerName, serviceName, ipAddress)
|
||||
glog.V(2).Infof("EnsureLoadBalancer(%v(%v)): address %s is not reserved.", loadBalancerName, serviceName, ipAddressToUse)
|
||||
} else {
|
||||
glog.V(2).Infof("EnsureLoadBalancer(%v(%v)): released static IP %s", loadBalancerName, serviceName, ipAddress)
|
||||
glog.V(2).Infof("EnsureLoadBalancer(%v(%v)): released static IP %s", loadBalancerName, serviceName, ipAddressToUse)
|
||||
}
|
||||
} else {
|
||||
glog.Warningf("orphaning static IP %s during update of load balancer (%v(%v), %v): %v", ipAddress, loadBalancerName, serviceName, gce.region, err)
|
||||
glog.Warningf("orphaning static IP %s during update of load balancer (%v(%v), %v): %v", ipAddressToUse, loadBalancerName, serviceName, gce.region, err)
|
||||
}
|
||||
}()
|
||||
|
||||
if loadBalancerIP != "" {
|
||||
// If a specific IP address has been requested, we have to respect the
|
||||
// user's request and use that IP. If the forwarding rule was already using
|
||||
// a different IP, it will be harmlessly abandoned because it was only an
|
||||
// ephemeral IP (or it was a different static IP owned by the user, in which
|
||||
// case we shouldn't delete it anyway).
|
||||
if isStatic, err := gce.projectOwnsStaticIP(loadBalancerName, gce.region, loadBalancerIP); err != nil {
|
||||
return nil, fmt.Errorf("failed to test if this GCE project owns the static IP %s: %v", loadBalancerIP, err)
|
||||
} else if isStatic {
|
||||
// The requested IP is a static IP, owned and managed by the user.
|
||||
isUserOwnedIP = true
|
||||
isSafeToReleaseIP = false
|
||||
ipAddress = loadBalancerIP
|
||||
glog.V(4).Infof("EnsureLoadBalancer(%v(%v)): using user-provided static IP %s", loadBalancerName, serviceName, ipAddress)
|
||||
} else if loadBalancerIP == fwdRuleIP {
|
||||
// The requested IP is not a static IP, but is currently assigned
|
||||
// to this forwarding rule, so we can keep it.
|
||||
isUserOwnedIP = false
|
||||
isSafeToReleaseIP = true
|
||||
ipAddress, _, err = ensureStaticIP(gce, loadBalancerName, serviceName.String(), gce.region, fwdRuleIP)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to ensure static IP %s: %v", fwdRuleIP, err)
|
||||
}
|
||||
glog.V(4).Infof("EnsureLoadBalancer(%v(%v)): using user-provided non-static IP %s", loadBalancerName, serviceName, ipAddress)
|
||||
} else {
|
||||
// The requested IP is not static and it is not assigned to the
|
||||
// current forwarding rule. It might be attached to a different
|
||||
// rule or it might not be part of this project at all. Either
|
||||
// way, we can't use it.
|
||||
return nil, fmt.Errorf("requested ip %s is neither static nor assigned to LB %s(%v): %v", loadBalancerIP, loadBalancerName, serviceName, err)
|
||||
}
|
||||
} else {
|
||||
// The user did not request a specific IP.
|
||||
isUserOwnedIP = false
|
||||
|
||||
// This will either allocate a new static IP if the forwarding rule didn't
|
||||
// already have an IP, or it will promote the forwarding rule's current
|
||||
// IP from ephemeral to static, or it will just get the IP if it is
|
||||
// already static.
|
||||
existed := false
|
||||
ipAddress, existed, err = ensureStaticIP(gce, loadBalancerName, serviceName.String(), gce.region, fwdRuleIP)
|
||||
if requestedIP != "" {
|
||||
// If user requests a specific IP address, verify first. No mutation to
|
||||
// the GCE resources will be performed in the verification process.
|
||||
isUserOwnedIP, err = verifyUserRequestedIP(gce, gce.region, requestedIP, fwdRuleIP, lbRefStr, netTier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to ensure static IP %s: %v", fwdRuleIP, err)
|
||||
return nil, err
|
||||
}
|
||||
if existed {
|
||||
// If the IP was not specifically requested by the user, but it
|
||||
// already existed, it seems to be a failed update cycle. We can
|
||||
// use this IP and try to run through the process again, but we
|
||||
// should not release the IP unless it is explicitly flagged as OK.
|
||||
isSafeToReleaseIP = false
|
||||
glog.V(4).Infof("EnsureLoadBalancer(%v(%v)): adopting static IP %s", loadBalancerName, serviceName, ipAddress)
|
||||
} else {
|
||||
// For total clarity. The IP did not pre-exist and the user did
|
||||
// not ask for a particular one, so we can release the IP in case
|
||||
// of failure or success.
|
||||
isSafeToReleaseIP = true
|
||||
glog.V(4).Infof("EnsureLoadBalancer(%v(%v)): allocated static IP %s", loadBalancerName, serviceName, ipAddress)
|
||||
ipAddressToUse = requestedIP
|
||||
}
|
||||
|
||||
if !isUserOwnedIP {
|
||||
// If we are not using the user-owned IP, either promote the
|
||||
// emphemeral IP used by the fwd rule, or create a new static IP.
|
||||
ipAddr, existed, err := ensureStaticIP(gce, loadBalancerName, serviceName.String(), gce.region, fwdRuleIP, netTier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to ensure a static IP for the LB: %v", err)
|
||||
}
|
||||
glog.V(4).Infof("EnsureLoadBalancer(%s): ensured IP address %s (tier: %s)", lbRefStr, ipAddr, netTier)
|
||||
// If the IP was not owned by the user, but it already existed, it
|
||||
// could indicate that the previous update cycle failed. We can use
|
||||
// this IP and try to run through the process again, but we should
|
||||
// not release the IP unless it is explicitly flagged as OK.
|
||||
isSafeToReleaseIP = !existed
|
||||
ipAddressToUse = ipAddr
|
||||
}
|
||||
|
||||
// Deal with the firewall next. The reason we do this here rather than last
|
||||
|
|
@ -190,24 +170,24 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
|||
return nil, err
|
||||
}
|
||||
|
||||
firewallExists, firewallNeedsUpdate, err := gce.firewallNeedsUpdate(loadBalancerName, serviceName.String(), gce.region, ipAddress, ports, sourceRanges)
|
||||
firewallExists, firewallNeedsUpdate, err := gce.firewallNeedsUpdate(loadBalancerName, serviceName.String(), gce.region, ipAddressToUse, ports, sourceRanges)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if firewallNeedsUpdate {
|
||||
desc := makeFirewallDescription(serviceName.String(), ipAddress)
|
||||
desc := makeFirewallDescription(serviceName.String(), ipAddressToUse)
|
||||
// Unlike forwarding rules and target pools, firewalls can be updated
|
||||
// without needing to be deleted and recreated.
|
||||
if firewallExists {
|
||||
glog.Infof("EnsureLoadBalancer(%v(%v)): updating firewall", loadBalancerName, serviceName)
|
||||
if err := gce.updateFirewall(makeFirewallName(loadBalancerName), gce.region, desc, sourceRanges, ports, hosts); err != nil {
|
||||
if err := gce.updateFirewall(apiService, makeFirewallName(loadBalancerName), gce.region, desc, sourceRanges, ports, hosts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.Infof("EnsureLoadBalancer(%v(%v)): updated firewall", loadBalancerName, serviceName)
|
||||
} else {
|
||||
glog.Infof("EnsureLoadBalancer(%v(%v)): creating firewall", loadBalancerName, serviceName)
|
||||
if err := gce.createFirewall(makeFirewallName(loadBalancerName), gce.region, desc, sourceRanges, ports, hosts); err != nil {
|
||||
if err := gce.createFirewall(apiService, makeFirewallName(loadBalancerName), gce.region, desc, sourceRanges, ports, hosts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.Infof("EnsureLoadBalancer(%v(%v)): created firewall", loadBalancerName, serviceName)
|
||||
|
|
@ -279,7 +259,7 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
|||
if hcToDelete != nil {
|
||||
hcNames = append(hcNames, hcToDelete.Name)
|
||||
}
|
||||
if err := gce.DeleteExternalTargetPoolAndChecks(loadBalancerName, gce.region, clusterID, hcNames...); err != nil {
|
||||
if err := gce.DeleteExternalTargetPoolAndChecks(apiService, loadBalancerName, gce.region, clusterID, hcNames...); err != nil {
|
||||
return nil, fmt.Errorf("failed to delete existing target pool %s for load balancer update: %v", loadBalancerName, err)
|
||||
}
|
||||
glog.Infof("EnsureLoadBalancer(%v(%v)): deleted target pool", loadBalancerName, serviceName)
|
||||
|
|
@ -293,7 +273,7 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
|||
createInstances = createInstances[:maxTargetPoolCreateInstances]
|
||||
}
|
||||
// Pass healthchecks to createTargetPool which needs them as health check links in the target pool
|
||||
if err := gce.createTargetPool(loadBalancerName, serviceName.String(), ipAddress, gce.region, clusterID, createInstances, affinityType, hcToCreate); err != nil {
|
||||
if err := gce.createTargetPool(apiService, loadBalancerName, serviceName.String(), ipAddressToUse, gce.region, clusterID, createInstances, affinityType, hcToCreate); err != nil {
|
||||
return nil, fmt.Errorf("failed to create target pool %s: %v", loadBalancerName, err)
|
||||
}
|
||||
if hcToCreate != nil {
|
||||
|
|
@ -315,8 +295,8 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
|||
}
|
||||
}
|
||||
if tpNeedsUpdate || fwdRuleNeedsUpdate {
|
||||
glog.Infof("EnsureLoadBalancer(%v(%v)): creating forwarding rule, IP %s", loadBalancerName, serviceName, ipAddress)
|
||||
if err := gce.createForwardingRule(loadBalancerName, serviceName.String(), gce.region, ipAddress, ports); err != nil {
|
||||
glog.Infof("EnsureLoadBalancer(%v(%v)): creating forwarding rule, IP %s (tier: %s)", loadBalancerName, serviceName, ipAddressToUse, netTier)
|
||||
if err := createForwardingRule(gce, loadBalancerName, serviceName.String(), gce.region, ipAddressToUse, gce.targetPoolURL(loadBalancerName), ports, netTier); err != nil {
|
||||
return nil, fmt.Errorf("failed to create forwarding rule %s: %v", loadBalancerName, err)
|
||||
}
|
||||
// End critical section. It is safe to release the static IP (which
|
||||
|
|
@ -324,11 +304,11 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
|||
// of a user-requested IP, the "is user-owned" flag will be set,
|
||||
// preventing it from actually being released.
|
||||
isSafeToReleaseIP = true
|
||||
glog.Infof("EnsureLoadBalancer(%v(%v)): created forwarding rule, IP %s", loadBalancerName, serviceName, ipAddress)
|
||||
glog.Infof("EnsureLoadBalancer(%v(%v)): created forwarding rule, IP %s", loadBalancerName, serviceName, ipAddressToUse)
|
||||
}
|
||||
|
||||
status := &v1.LoadBalancerStatus{}
|
||||
status.Ingress = []v1.LoadBalancerIngress{{IP: ipAddress}}
|
||||
status.Ingress = []v1.LoadBalancerIngress{{IP: ipAddressToUse}}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
|
|
@ -375,7 +355,16 @@ func (gce *GCECloud) ensureExternalLoadBalancerDeleted(clusterName, clusterID st
|
|||
}
|
||||
|
||||
errs := utilerrors.AggregateGoroutines(
|
||||
func() error { return ignoreNotFound(gce.DeleteFirewall(makeFirewallName(loadBalancerName))) },
|
||||
func() error {
|
||||
fwName := makeFirewallName(loadBalancerName)
|
||||
err := ignoreNotFound(gce.DeleteFirewall(fwName))
|
||||
if isForbidden(err) && gce.OnXPN() {
|
||||
glog.V(4).Infof("ensureExternalLoadBalancerDeleted(%v): do not have permission to delete firewall rule (on XPN). Raising event.", loadBalancerName)
|
||||
gce.raiseFirewallChangeNeededEvent(service, FirewallToGCloudDeleteCmd(fwName, gce.NetworkProjectID()))
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
},
|
||||
// Even though we don't hold on to static IPs for load balancers, it's
|
||||
// possible that EnsureLoadBalancer left one around in a failed
|
||||
// creation/update attempt, so make sure we clean it up here just in case.
|
||||
|
|
@ -386,7 +375,7 @@ func (gce *GCECloud) ensureExternalLoadBalancerDeleted(clusterName, clusterID st
|
|||
if err := ignoreNotFound(gce.DeleteRegionForwardingRule(loadBalancerName, gce.region)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := gce.DeleteExternalTargetPoolAndChecks(loadBalancerName, gce.region, clusterID, hcNames...); err != nil {
|
||||
if err := gce.DeleteExternalTargetPoolAndChecks(service, loadBalancerName, gce.region, clusterID, hcNames...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
@ -398,7 +387,7 @@ func (gce *GCECloud) ensureExternalLoadBalancerDeleted(clusterName, clusterID st
|
|||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) DeleteExternalTargetPoolAndChecks(name, region, clusterID string, hcNames ...string) error {
|
||||
func (gce *GCECloud) DeleteExternalTargetPoolAndChecks(service *v1.Service, name, region, clusterID string, hcNames ...string) error {
|
||||
if err := gce.DeleteTargetPool(name, region); err != nil && isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
glog.Infof("Target pool %s already deleted. Continuing to delete other resources.", name)
|
||||
} else if err != nil {
|
||||
|
|
@ -440,9 +429,10 @@ func (gce *GCECloud) DeleteExternalTargetPoolAndChecks(name, region, clusterID s
|
|||
// So we should delete the health check firewall as well.
|
||||
fwName := MakeHealthCheckFirewallName(clusterID, hcName, isNodesHealthCheck)
|
||||
glog.Infof("Deleting firewall %v.", fwName)
|
||||
if err := gce.DeleteFirewall(fwName); err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
glog.V(4).Infof("Firewall %v is already deleted.", fwName)
|
||||
if err := ignoreNotFound(gce.DeleteFirewall(fwName)); err != nil {
|
||||
if isForbidden(err) && gce.OnXPN() {
|
||||
glog.V(4).Infof("DeleteExternalTargetPoolAndChecks(%v): do not have permission to delete firewall rule (on XPN). Raising event.", hcName)
|
||||
gce.raiseFirewallChangeNeededEvent(service, FirewallToGCloudDeleteCmd(fwName, gce.NetworkProjectID()))
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
|
@ -456,7 +446,57 @@ func (gce *GCECloud) DeleteExternalTargetPoolAndChecks(name, region, clusterID s
|
|||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) createTargetPool(name, serviceName, ipAddress, region, clusterID string, hosts []*gceInstance, affinityType v1.ServiceAffinity, hc *compute.HttpHealthCheck) error {
|
||||
// verifyUserRequestedIP checks the user-provided IP to see whether it meets
|
||||
// all the expected attributes for the load balancer, and returns an error if
|
||||
// the verification failed. It also returns a boolean to indicate whether the
|
||||
// IP address is considered owned by the user (i.e., not managed by the
|
||||
// controller.
|
||||
func verifyUserRequestedIP(s CloudAddressService, region, requestedIP, fwdRuleIP, lbRef string, desiredNetTier NetworkTier) (isUserOwnedIP bool, err error) {
|
||||
if requestedIP == "" {
|
||||
return false, nil
|
||||
}
|
||||
// If a specific IP address has been requested, we have to respect the
|
||||
// user's request and use that IP. If the forwarding rule was already using
|
||||
// a different IP, it will be harmlessly abandoned because it was only an
|
||||
// ephemeral IP (or it was a different static IP owned by the user, in which
|
||||
// case we shouldn't delete it anyway).
|
||||
existingAddress, err := s.GetRegionAddressByIP(region, requestedIP)
|
||||
if err != nil && !isNotFound(err) {
|
||||
glog.Errorf("verifyUserRequestedIP: failed to check whether the requested IP %q for LB %s exists: %v", requestedIP, lbRef, err)
|
||||
return false, err
|
||||
}
|
||||
if err == nil {
|
||||
// The requested IP is a static IP, owned and managed by the user.
|
||||
|
||||
// Check if the network tier of the static IP matches the desired
|
||||
// network tier.
|
||||
netTierStr, err := s.getNetworkTierFromAddress(existingAddress.Name, region)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to check the network tier of the IP %q: %v", requestedIP, err)
|
||||
}
|
||||
netTier := NetworkTierGCEValueToType(netTierStr)
|
||||
if netTier != desiredNetTier {
|
||||
glog.Errorf("verifyUserRequestedIP: requested static IP %q (name: %s) for LB %s has network tier %s, need %s.", requestedIP, existingAddress.Name, lbRef, netTier, desiredNetTier)
|
||||
return false, fmt.Errorf("requrested IP %q belongs to the %s network tier; expected %s", requestedIP, netTier, desiredNetTier)
|
||||
}
|
||||
glog.V(4).Infof("verifyUserRequestedIP: the requested static IP %q (name: %s, tier: %s) for LB %s exists.", requestedIP, existingAddress.Name, netTier, lbRef)
|
||||
return true, nil
|
||||
}
|
||||
if requestedIP == fwdRuleIP {
|
||||
// The requested IP is not a static IP, but is currently assigned
|
||||
// to this forwarding rule, so we can just use it.
|
||||
glog.V(4).Infof("verifyUserRequestedIP: the requested IP %q is not static, but is currently in use by for LB %s", requestedIP, lbRef)
|
||||
return false, nil
|
||||
}
|
||||
// The requested IP is not static and it is not assigned to the
|
||||
// current forwarding rule. It might be attached to a different
|
||||
// rule or it might not be part of this project at all. Either
|
||||
// way, we can't use it.
|
||||
glog.Errorf("verifyUserRequestedIP: requested IP %q for LB %s is neither static nor assigned to the LB", requestedIP, lbRef)
|
||||
return false, fmt.Errorf("requested ip %q is neither static nor assigned to the LB", requestedIP)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) createTargetPool(svc *v1.Service, name, serviceName, ipAddress, region, clusterID string, hosts []*gceInstance, affinityType v1.ServiceAffinity, hc *compute.HttpHealthCheck) error {
|
||||
// health check management is coupled with targetPools to prevent leaks. A
|
||||
// target pool is the only thing that requires a health check, so we delete
|
||||
// associated checks on teardown, and ensure checks on setup.
|
||||
|
|
@ -469,14 +509,14 @@ func (gce *GCECloud) createTargetPool(name, serviceName, ipAddress, region, clus
|
|||
gce.sharedResourceLock.Lock()
|
||||
defer gce.sharedResourceLock.Unlock()
|
||||
}
|
||||
if !gce.OnXPN() {
|
||||
if err := gce.ensureHttpHealthCheckFirewall(serviceName, ipAddress, region, clusterID, hosts, hc.Name, int32(hc.Port), isNodesHealthCheck); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := gce.ensureHttpHealthCheckFirewall(svc, serviceName, ipAddress, region, clusterID, hosts, hc.Name, int32(hc.Port), isNodesHealthCheck); err != nil {
|
||||
return err
|
||||
}
|
||||
var err error
|
||||
hcRequestPath, hcPort := hc.RequestPath, hc.Port
|
||||
if hc, err = gce.ensureHttpHealthCheck(hc.Name, hc.RequestPath, int32(hc.Port)); err != nil || hc == nil {
|
||||
return fmt.Errorf("Failed to ensure health check for %v port %d path %v: %v", name, hc.Port, hc.RequestPath, err)
|
||||
return fmt.Errorf("Failed to ensure health check for %v port %d path %v: %v", name, hcPort, hcRequestPath, err)
|
||||
}
|
||||
hcLinks = append(hcLinks, hc.SelfLink)
|
||||
}
|
||||
|
|
@ -541,8 +581,8 @@ func (gce *GCECloud) updateTargetPool(loadBalancerName string, existing sets.Str
|
|||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) targetPoolURL(name, region string) string {
|
||||
return gce.service.BasePath + strings.Join([]string{gce.projectID, "regions", region, "targetPools", name}, "/")
|
||||
func (gce *GCECloud) targetPoolURL(name string) string {
|
||||
return gce.service.BasePath + strings.Join([]string{gce.projectID, "regions", gce.region, "targetPools", name}, "/")
|
||||
}
|
||||
|
||||
func makeHttpHealthCheck(name, path string, port int32) *compute.HttpHealthCheck {
|
||||
|
|
@ -721,12 +761,7 @@ func translateAffinityType(affinityType v1.ServiceAffinity) string {
|
|||
}
|
||||
|
||||
func (gce *GCECloud) firewallNeedsUpdate(name, serviceName, region, ipAddress string, ports []v1.ServicePort, sourceRanges netsets.IPNet) (exists bool, needsUpdate bool, err error) {
|
||||
if gce.OnXPN() {
|
||||
glog.V(2).Infoln("firewallNeedsUpdate: Cluster is on XPN network - skipping firewall creation")
|
||||
return false, false, nil
|
||||
}
|
||||
|
||||
fw, err := gce.service.Firewalls.Get(gce.projectID, makeFirewallName(name)).Do()
|
||||
fw, err := gce.service.Firewalls.Get(gce.NetworkProjectID(), makeFirewallName(name)).Do()
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return false, true, nil
|
||||
|
|
@ -763,7 +798,7 @@ func (gce *GCECloud) firewallNeedsUpdate(name, serviceName, region, ipAddress st
|
|||
return true, false, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ensureHttpHealthCheckFirewall(serviceName, ipAddress, region, clusterID string, hosts []*gceInstance, hcName string, hcPort int32, isNodesHealthCheck bool) error {
|
||||
func (gce *GCECloud) ensureHttpHealthCheckFirewall(svc *v1.Service, serviceName, ipAddress, region, clusterID string, hosts []*gceInstance, hcName string, hcPort int32, isNodesHealthCheck bool) error {
|
||||
// Prepare the firewall params for creating / checking.
|
||||
desc := fmt.Sprintf(`{"kubernetes.io/cluster-id":"%s"}`, clusterID)
|
||||
if !isNodesHealthCheck {
|
||||
|
|
@ -773,13 +808,13 @@ func (gce *GCECloud) ensureHttpHealthCheckFirewall(serviceName, ipAddress, regio
|
|||
ports := []v1.ServicePort{{Protocol: "tcp", Port: hcPort}}
|
||||
|
||||
fwName := MakeHealthCheckFirewallName(clusterID, hcName, isNodesHealthCheck)
|
||||
fw, err := gce.service.Firewalls.Get(gce.projectID, fwName).Do()
|
||||
fw, err := gce.service.Firewalls.Get(gce.NetworkProjectID(), fwName).Do()
|
||||
if err != nil {
|
||||
if !isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return fmt.Errorf("error getting firewall for health checks: %v", err)
|
||||
}
|
||||
glog.Infof("Creating firewall %v for health checks.", fwName)
|
||||
if err := gce.createFirewall(fwName, region, desc, sourceRanges, ports, hosts); err != nil {
|
||||
if err := gce.createFirewall(svc, fwName, region, desc, sourceRanges, ports, hosts); err != nil {
|
||||
return err
|
||||
}
|
||||
glog.Infof("Created firewall %v for health checks.", fwName)
|
||||
|
|
@ -789,10 +824,10 @@ func (gce *GCECloud) ensureHttpHealthCheckFirewall(serviceName, ipAddress, regio
|
|||
if fw.Description != desc ||
|
||||
len(fw.Allowed) != 1 ||
|
||||
fw.Allowed[0].IPProtocol != string(ports[0].Protocol) ||
|
||||
!equalStringSets(fw.Allowed[0].Ports, []string{string(ports[0].Port)}) ||
|
||||
!equalStringSets(fw.Allowed[0].Ports, []string{strconv.Itoa(int(ports[0].Port))}) ||
|
||||
!equalStringSets(fw.SourceRanges, sourceRanges.StringSlice()) {
|
||||
glog.Warningf("Firewall %v exists but parameters have drifted - updating...", fwName)
|
||||
if err := gce.updateFirewall(fwName, region, desc, sourceRanges, ports, hosts); err != nil {
|
||||
if err := gce.updateFirewall(svc, fwName, region, desc, sourceRanges, ports, hosts); err != nil {
|
||||
glog.Warningf("Failed to reconcile firewall %v parameters.", fwName)
|
||||
return err
|
||||
}
|
||||
|
|
@ -801,44 +836,77 @@ func (gce *GCECloud) ensureHttpHealthCheckFirewall(serviceName, ipAddress, regio
|
|||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) createForwardingRule(name, serviceName, region, ipAddress string, ports []v1.ServicePort) error {
|
||||
func createForwardingRule(s CloudForwardingRuleService, name, serviceName, region, ipAddress, target string, ports []v1.ServicePort, netTier NetworkTier) error {
|
||||
portRange, err := loadBalancerPortRange(ports)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req := &compute.ForwardingRule{
|
||||
Name: name,
|
||||
Description: fmt.Sprintf(`{"kubernetes.io/service-name":"%s"}`, serviceName),
|
||||
IPAddress: ipAddress,
|
||||
IPProtocol: string(ports[0].Protocol),
|
||||
PortRange: portRange,
|
||||
Target: gce.targetPoolURL(name, region),
|
||||
desc := makeServiceDescription(serviceName)
|
||||
ipProtocol := string(ports[0].Protocol)
|
||||
|
||||
switch netTier {
|
||||
case NetworkTierPremium:
|
||||
rule := &compute.ForwardingRule{
|
||||
Name: name,
|
||||
Description: desc,
|
||||
IPAddress: ipAddress,
|
||||
IPProtocol: ipProtocol,
|
||||
PortRange: portRange,
|
||||
Target: target,
|
||||
}
|
||||
err = s.CreateRegionForwardingRule(rule, region)
|
||||
default:
|
||||
rule := &computealpha.ForwardingRule{
|
||||
Name: name,
|
||||
Description: desc,
|
||||
IPAddress: ipAddress,
|
||||
IPProtocol: ipProtocol,
|
||||
PortRange: portRange,
|
||||
Target: target,
|
||||
NetworkTier: netTier.ToGCEValue(),
|
||||
}
|
||||
err = s.CreateAlphaRegionForwardingRule(rule, region)
|
||||
}
|
||||
|
||||
if err = gce.CreateRegionForwardingRule(req, region); err != nil && !isHTTPErrorCode(err, http.StatusConflict) {
|
||||
if err != nil && !isHTTPErrorCode(err, http.StatusConflict) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) createFirewall(svc *v1.Service, name, region, desc string, sourceRanges netsets.IPNet, ports []v1.ServicePort, hosts []*gceInstance) error {
|
||||
firewall, err := gce.firewallObject(name, region, desc, sourceRanges, ports, hosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = gce.CreateFirewall(firewall); err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusConflict) {
|
||||
return nil
|
||||
} else if isForbidden(err) && gce.OnXPN() {
|
||||
glog.V(4).Infof("createFirewall(%v): do not have permission to create firewall rule (on XPN). Raising event.", firewall.Name)
|
||||
gce.raiseFirewallChangeNeededEvent(svc, FirewallToGCloudCreateCmd(firewall, gce.NetworkProjectID()))
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) createFirewall(name, region, desc string, sourceRanges netsets.IPNet, ports []v1.ServicePort, hosts []*gceInstance) error {
|
||||
firewall, err := gce.firewallObject(name, region, desc, sourceRanges, ports, hosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = gce.CreateFirewall(firewall); err != nil && !isHTTPErrorCode(err, http.StatusConflict) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) updateFirewall(name, region, desc string, sourceRanges netsets.IPNet, ports []v1.ServicePort, hosts []*gceInstance) error {
|
||||
func (gce *GCECloud) updateFirewall(svc *v1.Service, name, region, desc string, sourceRanges netsets.IPNet, ports []v1.ServicePort, hosts []*gceInstance) error {
|
||||
firewall, err := gce.firewallObject(name, region, desc, sourceRanges, ports, hosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = gce.UpdateFirewall(firewall); err != nil && !isHTTPErrorCode(err, http.StatusConflict) {
|
||||
if err = gce.UpdateFirewall(firewall); err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusConflict) {
|
||||
return nil
|
||||
} else if isForbidden(err) && gce.OnXPN() {
|
||||
glog.V(4).Infof("updateFirewall(%v): do not have permission to update firewall rule (on XPN). Raising event.", firewall.Name)
|
||||
gce.raiseFirewallChangeNeededEvent(svc, FirewallToGCloudUpdateCmd(firewall, gce.NetworkProjectID()))
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
@ -880,52 +948,43 @@ func (gce *GCECloud) firewallObject(name, region, desc string, sourceRanges nets
|
|||
return firewall, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) projectOwnsStaticIP(name, region string, ipAddress string) (bool, error) {
|
||||
pageToken := ""
|
||||
page := 0
|
||||
for ; page == 0 || (pageToken != "" && page < maxPages); page++ {
|
||||
listCall := gce.service.Addresses.List(gce.projectID, region)
|
||||
if pageToken != "" {
|
||||
listCall = listCall.PageToken(pageToken)
|
||||
}
|
||||
addresses, err := listCall.Do()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to list gce IP addresses: %v", err)
|
||||
}
|
||||
pageToken = addresses.NextPageToken
|
||||
for _, addr := range addresses.Items {
|
||||
if addr.Address == ipAddress {
|
||||
// This project does own the address, so return success.
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if page >= maxPages {
|
||||
glog.Errorf("projectOwnsStaticIP exceeded maxPages=%d for Addresses.List; truncating.", maxPages)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func ensureStaticIP(s CloudAddressService, name, serviceName, region, existingIP string) (ipAddress string, existing bool, err error) {
|
||||
func ensureStaticIP(s CloudAddressService, name, serviceName, region, existingIP string, netTier NetworkTier) (ipAddress string, existing bool, err error) {
|
||||
// If the address doesn't exist, this will create it.
|
||||
// If the existingIP exists but is ephemeral, this will promote it to static.
|
||||
// If the address already exists, this will harmlessly return a StatusConflict
|
||||
// and we'll grab the IP before returning.
|
||||
existed := false
|
||||
addressObj := &compute.Address{
|
||||
Name: name,
|
||||
Description: fmt.Sprintf(`{"kubernetes.io/service-name":"%s"}`, serviceName),
|
||||
}
|
||||
desc := makeServiceDescription(serviceName)
|
||||
|
||||
if existingIP != "" {
|
||||
addressObj.Address = existingIP
|
||||
}
|
||||
|
||||
if err = s.ReserveRegionAddress(addressObj, region); err != nil {
|
||||
if !isHTTPErrorCode(err, http.StatusConflict) {
|
||||
return "", false, fmt.Errorf("error creating gce static IP address: %v", err)
|
||||
var creationErr error
|
||||
switch netTier {
|
||||
case NetworkTierPremium:
|
||||
addressObj := &compute.Address{
|
||||
Name: name,
|
||||
Description: desc,
|
||||
}
|
||||
if existingIP != "" {
|
||||
addressObj.Address = existingIP
|
||||
}
|
||||
creationErr = s.ReserveRegionAddress(addressObj, region)
|
||||
default:
|
||||
addressObj := &computealpha.Address{
|
||||
Name: name,
|
||||
Description: desc,
|
||||
NetworkTier: netTier.ToGCEValue(),
|
||||
}
|
||||
if existingIP != "" {
|
||||
addressObj.Address = existingIP
|
||||
}
|
||||
creationErr = s.ReserveAlphaRegionAddress(addressObj, region)
|
||||
}
|
||||
|
||||
if creationErr != nil {
|
||||
// GCE returns StatusConflict if the name conflicts; it returns
|
||||
// StatusBadRequest if the IP conflicts.
|
||||
if !isHTTPErrorCode(creationErr, http.StatusConflict) && !isHTTPErrorCode(creationErr, http.StatusBadRequest) {
|
||||
return "", false, fmt.Errorf("error creating gce static IP address: %v", creationErr)
|
||||
}
|
||||
// StatusConflict == the IP exists already.
|
||||
existed = true
|
||||
}
|
||||
|
||||
|
|
@ -936,3 +995,73 @@ func ensureStaticIP(s CloudAddressService, name, serviceName, region, existingIP
|
|||
|
||||
return addr.Address, existed, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) getServiceNetworkTier(svc *v1.Service) (NetworkTier, error) {
|
||||
if !gce.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
||||
return NetworkTierDefault, nil
|
||||
}
|
||||
tier, err := GetServiceNetworkTier(svc)
|
||||
if err != nil {
|
||||
// Returns an error if the annotation is invalid.
|
||||
return NetworkTier(""), err
|
||||
}
|
||||
return tier, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) deleteWrongNetworkTieredResources(lbName, lbRef string, desiredNetTier NetworkTier) error {
|
||||
logPrefix := fmt.Sprintf("deleteWrongNetworkTieredResources:(%s)", lbRef)
|
||||
if err := deleteFWDRuleWithWrongTier(gce, gce.region, lbName, logPrefix, desiredNetTier); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := deleteAddressWithWrongTier(gce, gce.region, lbName, logPrefix, desiredNetTier); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// deleteFWDRuleWithWrongTier checks the network tier of existing forwarding
|
||||
// rule and delete the rule if the tier does not matched the desired tier.
|
||||
func deleteFWDRuleWithWrongTier(s CloudForwardingRuleService, region, name, logPrefix string, desiredNetTier NetworkTier) error {
|
||||
tierStr, err := s.getNetworkTierFromForwardingRule(name, region)
|
||||
if isNotFound(err) {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
existingTier := NetworkTierGCEValueToType(tierStr)
|
||||
if existingTier == desiredNetTier {
|
||||
return nil
|
||||
}
|
||||
glog.V(2).Infof("%s: Network tiers do not match; existing forwarding rule: %q, desired: %q. Deleting the forwarding rule",
|
||||
logPrefix, existingTier, desiredNetTier)
|
||||
err = s.DeleteRegionForwardingRule(name, region)
|
||||
return ignoreNotFound(err)
|
||||
}
|
||||
|
||||
// deleteAddressWithWrongTier checks the network tier of existing address
|
||||
// and delete the address if the tier does not matched the desired tier.
|
||||
func deleteAddressWithWrongTier(s CloudAddressService, region, name, logPrefix string, desiredNetTier NetworkTier) error {
|
||||
// We only check the IP address matching the reserved name that the
|
||||
// controller assigned to the LB. We make the assumption that an address of
|
||||
// such name is owned by the controller and is safe to release. Whether an
|
||||
// IP is owned by the user is not clearly defined in the current code, and
|
||||
// this assumption may not match some of the existing logic in the code.
|
||||
// However, this is okay since network tiering is still Alpha and will be
|
||||
// properly gated.
|
||||
// TODO(#51665): Re-evaluate the "ownership" of the IP address to ensure
|
||||
// we don't release IP unintentionally.
|
||||
tierStr, err := s.getNetworkTierFromAddress(name, region)
|
||||
if isNotFound(err) {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
existingTier := NetworkTierGCEValueToType(tierStr)
|
||||
if existingTier == desiredNetTier {
|
||||
return nil
|
||||
}
|
||||
glog.V(2).Infof("%s: Network tiers do not match; existing address: %q, desired: %q. Deleting the address",
|
||||
logPrefix, existingTier, desiredNetTier)
|
||||
err = s.DeleteRegionAddress(name, region)
|
||||
return ignoreNotFound(err)
|
||||
}
|
||||
|
|
|
|||
110
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go
generated
vendored
110
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go
generated
vendored
|
|
@ -34,8 +34,6 @@ const (
|
|||
allInstances = "ALL"
|
||||
)
|
||||
|
||||
type lbBalancingMode string
|
||||
|
||||
func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, svc *v1.Service, existingFwdRule *compute.ForwardingRule, nodes []*v1.Node) (*v1.LoadBalancerStatus, error) {
|
||||
nm := types.NamespacedName{Name: svc.Name, Namespace: svc.Namespace}
|
||||
ports, protocol := getPortsAndProtocol(svc.Spec.Ports)
|
||||
|
|
@ -79,19 +77,25 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Determine IP which will be used for this LB. If no forwarding rule has been established
|
||||
// or specified in the Service spec, then requestedIP = "".
|
||||
requestedIP := determineRequestedIP(svc, existingFwdRule)
|
||||
addrMgr := newAddressManager(gce, nm.String(), gce.Region(), gce.getInternalSubnetURL(), loadBalancerName, requestedIP, schemeInternal)
|
||||
ipToUse, err := addrMgr.HoldAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.V(2).Infof("ensureInternalLoadBalancer(%v): reserved IP %q for the forwarding rule", loadBalancerName, ipToUse)
|
||||
|
||||
// Ensure firewall rules if necessary
|
||||
if gce.OnXPN() {
|
||||
glog.V(2).Infof("ensureInternalLoadBalancer: cluster is on a cross-project network (XPN) network project %v, compute project %v - skipping firewall creation", gce.networkProjectID, gce.projectID)
|
||||
} else {
|
||||
if err = gce.ensureInternalFirewalls(loadBalancerName, clusterID, nm, svc, strconv.Itoa(int(hcPort)), sharedHealthCheck, nodes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = gce.ensureInternalFirewalls(loadBalancerName, ipToUse, clusterID, nm, svc, strconv.Itoa(int(hcPort)), sharedHealthCheck, nodes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
expectedFwdRule := &compute.ForwardingRule{
|
||||
Name: loadBalancerName,
|
||||
Description: fmt.Sprintf(`{"kubernetes.io/service-name":"%s"}`, nm.String()),
|
||||
IPAddress: svc.Spec.LoadBalancerIP,
|
||||
IPAddress: ipToUse,
|
||||
BackendService: backendServiceLink,
|
||||
Ports: ports,
|
||||
IPProtocol: string(protocol),
|
||||
|
|
@ -126,25 +130,25 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
|
|||
if err = gce.CreateRegionForwardingRule(expectedFwdRule, gce.region); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.V(2).Infof("ensureInternalLoadBalancer(%v): created forwarding rule", loadBalancerName)
|
||||
}
|
||||
|
||||
// Delete the previous internal load balancer resources if necessary
|
||||
if existingBackendService != nil {
|
||||
gce.clearPreviousInternalResources(loadBalancerName, existingBackendService, backendServiceName, hcName)
|
||||
gce.clearPreviousInternalResources(svc, loadBalancerName, existingBackendService, backendServiceName, hcName)
|
||||
}
|
||||
|
||||
// Get the most recent forwarding rule for the new address.
|
||||
existingFwdRule, err = gce.GetRegionForwardingRule(loadBalancerName, gce.region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Now that the controller knows the forwarding rule exists, we can release the address.
|
||||
if err := addrMgr.ReleaseAddress(); err != nil {
|
||||
glog.Errorf("ensureInternalLoadBalancer: failed to release address reservation, possibly causing an orphan: %v", err)
|
||||
}
|
||||
|
||||
status := &v1.LoadBalancerStatus{}
|
||||
status.Ingress = []v1.LoadBalancerIngress{{IP: existingFwdRule.IPAddress}}
|
||||
status.Ingress = []v1.LoadBalancerIngress{{IP: ipToUse}}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) clearPreviousInternalResources(loadBalancerName string, existingBackendService *compute.BackendService, expectedBSName, expectedHCName string) {
|
||||
func (gce *GCECloud) clearPreviousInternalResources(svc *v1.Service, loadBalancerName string, existingBackendService *compute.BackendService, expectedBSName, expectedHCName string) {
|
||||
// If a new backend service was created, delete the old one.
|
||||
if existingBackendService.Name != expectedBSName {
|
||||
glog.V(2).Infof("clearPreviousInternalResources(%v): expected backend service %q does not match previous %q - deleting backend service", loadBalancerName, expectedBSName, existingBackendService.Name)
|
||||
|
|
@ -158,7 +162,7 @@ func (gce *GCECloud) clearPreviousInternalResources(loadBalancerName string, exi
|
|||
existingHCName := getNameFromLink(existingBackendService.HealthChecks[0])
|
||||
if existingHCName != expectedHCName {
|
||||
glog.V(2).Infof("clearPreviousInternalResources(%v): expected health check %q does not match previous %q - deleting health check", loadBalancerName, expectedHCName, existingHCName)
|
||||
if err := gce.teardownInternalHealthCheckAndFirewall(existingHCName); err != nil {
|
||||
if err := gce.teardownInternalHealthCheckAndFirewall(svc, existingHCName); err != nil {
|
||||
glog.Warningf("clearPreviousInternalResources: could not delete existing healthcheck: %v, err: %v", existingHCName, err)
|
||||
}
|
||||
}
|
||||
|
|
@ -198,6 +202,9 @@ func (gce *GCECloud) ensureInternalLoadBalancerDeleted(clusterName, clusterID st
|
|||
gce.sharedResourceLock.Lock()
|
||||
defer gce.sharedResourceLock.Unlock()
|
||||
|
||||
glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): attempting delete of region internal address", loadBalancerName)
|
||||
ensureAddressDeleted(gce, loadBalancerName, gce.region)
|
||||
|
||||
glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting region internal forwarding rule", loadBalancerName)
|
||||
if err := gce.DeleteRegionForwardingRule(loadBalancerName, gce.region); err != nil && !isNotFound(err) {
|
||||
return err
|
||||
|
|
@ -211,12 +218,17 @@ func (gce *GCECloud) ensureInternalLoadBalancerDeleted(clusterName, clusterID st
|
|||
|
||||
glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting firewall for traffic", loadBalancerName)
|
||||
if err := gce.DeleteFirewall(loadBalancerName); err != nil {
|
||||
return err
|
||||
if isForbidden(err) && gce.OnXPN() {
|
||||
glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): could not delete traffic firewall on XPN cluster. Raising event.", loadBalancerName)
|
||||
gce.raiseFirewallChangeNeededEvent(svc, FirewallToGCloudDeleteCmd(loadBalancerName, gce.NetworkProjectID()))
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
hcName := makeHealthCheckName(loadBalancerName, clusterID, sharedHealthCheck)
|
||||
glog.V(2).Infof("ensureInternalLoadBalancerDeleted(%v): deleting health check %v and its firewall", loadBalancerName, hcName)
|
||||
if err := gce.teardownInternalHealthCheckAndFirewall(hcName); err != nil {
|
||||
if err := gce.teardownInternalHealthCheckAndFirewall(svc, hcName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +257,7 @@ func (gce *GCECloud) teardownInternalBackendService(bsName string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) teardownInternalHealthCheckAndFirewall(hcName string) error {
|
||||
func (gce *GCECloud) teardownInternalHealthCheckAndFirewall(svc *v1.Service, hcName string) error {
|
||||
if err := gce.DeleteHealthCheck(hcName); err != nil {
|
||||
if isNotFound(err) {
|
||||
glog.V(2).Infof("teardownInternalHealthCheckAndFirewall(%v): health check does not exist.", hcName)
|
||||
|
|
@ -261,13 +273,19 @@ func (gce *GCECloud) teardownInternalHealthCheckAndFirewall(hcName string) error
|
|||
|
||||
hcFirewallName := makeHealthCheckFirewallNameFromHC(hcName)
|
||||
if err := gce.DeleteFirewall(hcFirewallName); err != nil && !isNotFound(err) {
|
||||
if isForbidden(err) && gce.OnXPN() {
|
||||
glog.V(2).Infof("teardownInternalHealthCheckAndFirewall(%v): could not delete health check traffic firewall on XPN cluster. Raising Event.", hcName)
|
||||
gce.raiseFirewallChangeNeededEvent(svc, FirewallToGCloudDeleteCmd(hcFirewallName, gce.NetworkProjectID()))
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to delete health check firewall: %v, err: %v", hcFirewallName, err)
|
||||
}
|
||||
glog.V(2).Infof("teardownInternalHealthCheckAndFirewall(%v): health check firewall deleted", hcFirewallName)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ensureInternalFirewall(fwName, fwDesc string, sourceRanges []string, ports []string, protocol v1.Protocol, nodes []*v1.Node) error {
|
||||
func (gce *GCECloud) ensureInternalFirewall(svc *v1.Service, fwName, fwDesc string, sourceRanges []string, ports []string, protocol v1.Protocol, nodes []*v1.Node) error {
|
||||
glog.V(2).Infof("ensureInternalFirewall(%v): checking existing firewall", fwName)
|
||||
targetTags, err := gce.GetNodeTags(nodeNames(nodes))
|
||||
if err != nil {
|
||||
|
|
@ -295,7 +313,13 @@ func (gce *GCECloud) ensureInternalFirewall(fwName, fwDesc string, sourceRanges
|
|||
|
||||
if existingFirewall == nil {
|
||||
glog.V(2).Infof("ensureInternalFirewall(%v): creating firewall", fwName)
|
||||
return gce.CreateFirewall(expectedFirewall)
|
||||
err = gce.CreateFirewall(expectedFirewall)
|
||||
if err != nil && isForbidden(err) && gce.OnXPN() {
|
||||
glog.V(2).Infof("ensureInternalFirewall(%v): do not have permission to create firewall rule (on XPN). Raising event.", fwName)
|
||||
gce.raiseFirewallChangeNeededEvent(svc, FirewallToGCloudCreateCmd(expectedFirewall, gce.NetworkProjectID()))
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if firewallRuleEqual(expectedFirewall, existingFirewall) {
|
||||
|
|
@ -303,18 +327,24 @@ func (gce *GCECloud) ensureInternalFirewall(fwName, fwDesc string, sourceRanges
|
|||
}
|
||||
|
||||
glog.V(2).Infof("ensureInternalFirewall(%v): updating firewall", fwName)
|
||||
return gce.UpdateFirewall(expectedFirewall)
|
||||
err = gce.UpdateFirewall(expectedFirewall)
|
||||
if err != nil && isForbidden(err) && gce.OnXPN() {
|
||||
glog.V(2).Infof("ensureInternalFirewall(%v): do not have permission to update firewall rule (on XPN). Raising event.", fwName)
|
||||
gce.raiseFirewallChangeNeededEvent(svc, FirewallToGCloudUpdateCmd(expectedFirewall, gce.NetworkProjectID()))
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ensureInternalFirewalls(loadBalancerName, clusterID string, nm types.NamespacedName, svc *v1.Service, healthCheckPort string, sharedHealthCheck bool, nodes []*v1.Node) error {
|
||||
func (gce *GCECloud) ensureInternalFirewalls(loadBalancerName, ipAddress, clusterID string, nm types.NamespacedName, svc *v1.Service, healthCheckPort string, sharedHealthCheck bool, nodes []*v1.Node) error {
|
||||
// First firewall is for ingress traffic
|
||||
fwDesc := makeFirewallDescription(nm.String(), svc.Spec.LoadBalancerIP)
|
||||
fwDesc := makeFirewallDescription(nm.String(), ipAddress)
|
||||
ports, protocol := getPortsAndProtocol(svc.Spec.Ports)
|
||||
sourceRanges, err := v1_service.GetLoadBalancerSourceRanges(svc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = gce.ensureInternalFirewall(loadBalancerName, fwDesc, sourceRanges.StringSlice(), ports, protocol, nodes)
|
||||
err = gce.ensureInternalFirewall(svc, loadBalancerName, fwDesc, sourceRanges.StringSlice(), ports, protocol, nodes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -322,7 +352,7 @@ func (gce *GCECloud) ensureInternalFirewalls(loadBalancerName, clusterID string,
|
|||
// Second firewall is for health checking nodes / services
|
||||
fwHCName := makeHealthCheckFirewallName(loadBalancerName, clusterID, sharedHealthCheck)
|
||||
hcSrcRanges := LoadBalancerSrcRanges()
|
||||
return gce.ensureInternalFirewall(fwHCName, "", hcSrcRanges, []string{healthCheckPort}, v1.ProtocolTCP, nodes)
|
||||
return gce.ensureInternalFirewall(svc, fwHCName, "", hcSrcRanges, []string{healthCheckPort}, v1.ProtocolTCP, nodes)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ensureInternalHealthCheck(name string, svcName types.NamespacedName, shared bool, path string, port int32) (*compute.HealthCheck, error) {
|
||||
|
|
@ -632,6 +662,20 @@ func (gce *GCECloud) getBackendServiceLink(name string) string {
|
|||
return gce.service.BasePath + strings.Join([]string{gce.projectID, "regions", gce.region, "backendServices", name}, "/")
|
||||
}
|
||||
|
||||
// getInternalSubnetURL first attempts to return the configured SubnetURL.
|
||||
// If subnetwork-name was not specified, then a best-effort generation is made.
|
||||
// Note subnet names might not be the network name for some auto networks.
|
||||
func (gce *GCECloud) getInternalSubnetURL() string {
|
||||
if gce.SubnetworkURL() != "" {
|
||||
return gce.SubnetworkURL()
|
||||
}
|
||||
|
||||
networkName := getNameFromLink(gce.NetworkURL())
|
||||
v := gceSubnetworkURL("", gce.NetworkProjectID(), gce.Region(), networkName)
|
||||
glog.Warningf("Generating subnetwork URL based off network since subnet name/URL was not configured: %q", v)
|
||||
return v
|
||||
}
|
||||
|
||||
func getNameFromLink(link string) string {
|
||||
if link == "" {
|
||||
return ""
|
||||
|
|
@ -640,3 +684,15 @@ func getNameFromLink(link string) string {
|
|||
fields := strings.Split(link, "/")
|
||||
return fields[len(fields)-1]
|
||||
}
|
||||
|
||||
func determineRequestedIP(svc *v1.Service, fwdRule *compute.ForwardingRule) string {
|
||||
if svc.Spec.LoadBalancerIP != "" {
|
||||
return svc.Spec.LoadBalancerIP
|
||||
}
|
||||
|
||||
if fwdRule != nil {
|
||||
return fwdRule.IPAddress
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
5
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_naming.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_naming.go
generated
vendored
|
|
@ -84,6 +84,11 @@ func makeBackendServiceDescription(nm types.NamespacedName, shared bool) string
|
|||
|
||||
// External Load Balancer
|
||||
|
||||
// makeServiceDescription is used to generate descriptions for forwarding rules and addresses.
|
||||
func makeServiceDescription(serviceName string) string {
|
||||
return fmt.Sprintf(`{"kubernetes.io/service-name":"%s"}`, serviceName)
|
||||
}
|
||||
|
||||
// makeNodesHealthCheckName returns name of the health check resource used by
|
||||
// the GCE load balancers (l4) for performing health checks on nodes.
|
||||
func makeNodesHealthCheckName(clusterID string) string {
|
||||
|
|
|
|||
104
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_op.go
generated
vendored
104
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_op.go
generated
vendored
|
|
@ -17,17 +17,20 @@ limitations under the License.
|
|||
package gce
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
||||
"github.com/golang/glog"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
computev1 "google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
func (gce *GCECloud) waitForOp(op *compute.Operation, getOperation func(operationName string) (*compute.Operation, error), mc *metricContext) error {
|
||||
func (gce *GCECloud) waitForOp(op *computev1.Operation, getOperation func(operationName string) (*computev1.Operation, error), mc *metricContext) error {
|
||||
if op == nil {
|
||||
return mc.Observe(fmt.Errorf("operation must not be nil"))
|
||||
}
|
||||
|
|
@ -72,11 +75,11 @@ func (gce *GCECloud) waitForOp(op *compute.Operation, getOperation func(operatio
|
|||
})
|
||||
}
|
||||
|
||||
func opIsDone(op *compute.Operation) bool {
|
||||
func opIsDone(op *computev1.Operation) bool {
|
||||
return op != nil && op.Status == "DONE"
|
||||
}
|
||||
|
||||
func getErrorFromOp(op *compute.Operation) error {
|
||||
func getErrorFromOp(op *computev1.Operation) error {
|
||||
if op != nil && op.Error != nil && len(op.Error.Errors) > 0 {
|
||||
err := &googleapi.Error{
|
||||
Code: int(op.HttpErrorStatusCode),
|
||||
|
|
@ -89,20 +92,89 @@ func getErrorFromOp(op *compute.Operation) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) waitForGlobalOp(op *compute.Operation, mc *metricContext) error {
|
||||
return gce.waitForOp(op, func(operationName string) (*compute.Operation, error) {
|
||||
return gce.service.GlobalOperations.Get(gce.projectID, operationName).Do()
|
||||
}, mc)
|
||||
func (gce *GCECloud) waitForGlobalOp(op gceObject, mc *metricContext) error {
|
||||
return gce.waitForGlobalOpInProject(op, gce.ProjectID(), mc)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) waitForRegionOp(op *compute.Operation, region string, mc *metricContext) error {
|
||||
return gce.waitForOp(op, func(operationName string) (*compute.Operation, error) {
|
||||
return gce.service.RegionOperations.Get(gce.projectID, region, operationName).Do()
|
||||
}, mc)
|
||||
func (gce *GCECloud) waitForRegionOp(op gceObject, region string, mc *metricContext) error {
|
||||
return gce.waitForRegionOpInProject(op, gce.ProjectID(), region, mc)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) waitForZoneOp(op *compute.Operation, zone string, mc *metricContext) error {
|
||||
return gce.waitForOp(op, func(operationName string) (*compute.Operation, error) {
|
||||
return gce.service.ZoneOperations.Get(gce.projectID, zone, operationName).Do()
|
||||
}, mc)
|
||||
func (gce *GCECloud) waitForZoneOp(op gceObject, zone string, mc *metricContext) error {
|
||||
return gce.waitForZoneOpInProject(op, gce.ProjectID(), zone, mc)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) waitForGlobalOpInProject(op gceObject, projectID string, mc *metricContext) error {
|
||||
switch v := op.(type) {
|
||||
case *computealpha.Operation:
|
||||
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||
op, err := gce.serviceAlpha.GlobalOperations.Get(projectID, operationName).Do()
|
||||
return convertToV1Operation(op), err
|
||||
}, mc)
|
||||
case *computebeta.Operation:
|
||||
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||
op, err := gce.serviceBeta.GlobalOperations.Get(projectID, operationName).Do()
|
||||
return convertToV1Operation(op), err
|
||||
}, mc)
|
||||
case *computev1.Operation:
|
||||
return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) {
|
||||
return gce.service.GlobalOperations.Get(projectID, operationName).Do()
|
||||
}, mc)
|
||||
default:
|
||||
return fmt.Errorf("unexpected type: %T", v)
|
||||
}
|
||||
}
|
||||
|
||||
func (gce *GCECloud) waitForRegionOpInProject(op gceObject, projectID, region string, mc *metricContext) error {
|
||||
switch v := op.(type) {
|
||||
case *computealpha.Operation:
|
||||
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||
op, err := gce.serviceAlpha.RegionOperations.Get(projectID, region, operationName).Do()
|
||||
return convertToV1Operation(op), err
|
||||
}, mc)
|
||||
case *computebeta.Operation:
|
||||
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||
op, err := gce.serviceBeta.RegionOperations.Get(projectID, region, operationName).Do()
|
||||
return convertToV1Operation(op), err
|
||||
}, mc)
|
||||
case *computev1.Operation:
|
||||
return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) {
|
||||
return gce.service.RegionOperations.Get(projectID, region, operationName).Do()
|
||||
}, mc)
|
||||
default:
|
||||
return fmt.Errorf("unexpected type: %T", v)
|
||||
}
|
||||
}
|
||||
|
||||
func (gce *GCECloud) waitForZoneOpInProject(op gceObject, projectID, zone string, mc *metricContext) error {
|
||||
switch v := op.(type) {
|
||||
case *computealpha.Operation:
|
||||
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||
op, err := gce.serviceAlpha.ZoneOperations.Get(projectID, zone, operationName).Do()
|
||||
return convertToV1Operation(op), err
|
||||
}, mc)
|
||||
case *computebeta.Operation:
|
||||
return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) {
|
||||
op, err := gce.serviceBeta.ZoneOperations.Get(projectID, zone, operationName).Do()
|
||||
return convertToV1Operation(op), err
|
||||
}, mc)
|
||||
case *computev1.Operation:
|
||||
return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) {
|
||||
return gce.service.ZoneOperations.Get(projectID, zone, operationName).Do()
|
||||
}, mc)
|
||||
default:
|
||||
return fmt.Errorf("unexpected type: %T", v)
|
||||
}
|
||||
}
|
||||
|
||||
func convertToV1Operation(object gceObject) *computev1.Operation {
|
||||
enc, err := object.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to encode to json: %v", err))
|
||||
}
|
||||
var op computev1.Operation
|
||||
if err := json.Unmarshal(enc, &op); err != nil {
|
||||
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to v1 operation: %v", object, err))
|
||||
}
|
||||
return &op
|
||||
}
|
||||
|
|
|
|||
38
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_routes.go
generated
vendored
38
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_routes.go
generated
vendored
|
|
@ -20,8 +20,6 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
|
|
@ -31,10 +29,7 @@ import (
|
|||
)
|
||||
|
||||
func newRoutesMetricContext(request string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"routes_" + request, unusedMetricLabel, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("routes", request, unusedMetricLabel, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) {
|
||||
|
|
@ -43,10 +38,15 @@ func (gce *GCECloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, err
|
|||
page := 0
|
||||
for ; page == 0 || (pageToken != "" && page < maxPages); page++ {
|
||||
mc := newRoutesMetricContext("list_page")
|
||||
listCall := gce.service.Routes.List(gce.projectID)
|
||||
listCall := gce.service.Routes.List(gce.NetworkProjectID())
|
||||
|
||||
prefix := truncateClusterName(clusterName)
|
||||
listCall = listCall.Filter("name eq " + prefix + "-.*")
|
||||
// Filter for routes starting with clustername AND belonging to the
|
||||
// relevant gcp network AND having description = "k8s-node-route".
|
||||
filter := "(name eq " + prefix + "-.*) "
|
||||
filter = filter + "(network eq " + gce.NetworkURL() + ") "
|
||||
filter = filter + "(description eq " + k8sNodeRouteTag + ")"
|
||||
listCall = listCall.Filter(filter)
|
||||
if pageToken != "" {
|
||||
listCall = listCall.PageToken(pageToken)
|
||||
}
|
||||
|
|
@ -58,18 +58,6 @@ func (gce *GCECloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, err
|
|||
}
|
||||
pageToken = res.NextPageToken
|
||||
for _, r := range res.Items {
|
||||
if r.Network != gce.networkURL {
|
||||
continue
|
||||
}
|
||||
// Not managed if route description != "k8s-node-route"
|
||||
if r.Description != k8sNodeRouteTag {
|
||||
continue
|
||||
}
|
||||
// Not managed if route name doesn't start with <clusterName>
|
||||
if !strings.HasPrefix(r.Name, prefix) {
|
||||
continue
|
||||
}
|
||||
|
||||
target := path.Base(r.NextHopInstance)
|
||||
// TODO: Should we lastComponent(target) this?
|
||||
targetNodeName := types.NodeName(target) // NodeName == Instance Name on GCE
|
||||
|
|
@ -92,11 +80,11 @@ func (gce *GCECloud) CreateRoute(clusterName string, nameHint string, route *clo
|
|||
}
|
||||
|
||||
mc := newRoutesMetricContext("create")
|
||||
insertOp, err := gce.service.Routes.Insert(gce.projectID, &compute.Route{
|
||||
insertOp, err := gce.service.Routes.Insert(gce.NetworkProjectID(), &compute.Route{
|
||||
Name: routeName,
|
||||
DestRange: route.DestinationCIDR,
|
||||
NextHopInstance: fmt.Sprintf("zones/%s/instances/%s", targetInstance.Zone, targetInstance.Name),
|
||||
Network: gce.networkURL,
|
||||
Network: gce.NetworkURL(),
|
||||
Priority: 1000,
|
||||
Description: k8sNodeRouteTag,
|
||||
}).Do()
|
||||
|
|
@ -108,16 +96,16 @@ func (gce *GCECloud) CreateRoute(clusterName string, nameHint string, route *clo
|
|||
return mc.Observe(err)
|
||||
}
|
||||
}
|
||||
return gce.waitForGlobalOp(insertOp, mc)
|
||||
return gce.waitForGlobalOpInProject(insertOp, gce.NetworkProjectID(), mc)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) DeleteRoute(clusterName string, route *cloudprovider.Route) error {
|
||||
mc := newRoutesMetricContext("delete")
|
||||
deleteOp, err := gce.service.Routes.Delete(gce.projectID, route.Name).Do()
|
||||
deleteOp, err := gce.service.Routes.Delete(gce.NetworkProjectID(), route.Name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(deleteOp, mc)
|
||||
return gce.waitForGlobalOpInProject(deleteOp, gce.NetworkProjectID(), mc)
|
||||
}
|
||||
|
||||
func truncateClusterName(clusterName string) string {
|
||||
|
|
|
|||
11
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetpool.go
generated
vendored
11
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetpool.go
generated
vendored
|
|
@ -16,17 +16,10 @@ limitations under the License.
|
|||
|
||||
package gce
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
import compute "google.golang.org/api/compute/v1"
|
||||
|
||||
func newTargetPoolMetricContext(request, region string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"targetpool_" + request, region, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("targetpool", request, region, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
// GetTargetPool returns the TargetPool by name.
|
||||
|
|
|
|||
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetproxy.go
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetproxy.go
generated
vendored
|
|
@ -18,16 +18,12 @@ package gce
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
func newTargetProxyMetricContext(request string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"targetproxy_" + request, unusedMetricLabel, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("targetproxy", request, unusedMetricLabel, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
// GetTargetHttpProxy returns the UrlMap by name.
|
||||
|
|
|
|||
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_urlmap.go
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_urlmap.go
generated
vendored
|
|
@ -18,16 +18,12 @@ package gce
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
func newUrlMapMetricContext(request string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"urlmap_" + request, unusedMetricLabel, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("urlmap", request, unusedMetricLabel, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
// GetUrlMap returns the UrlMap by name.
|
||||
|
|
|
|||
62
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_util.go
generated
vendored
62
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_util.go
generated
vendored
|
|
@ -23,6 +23,7 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
|
|
@ -58,6 +59,43 @@ func getProjectAndZone() (string, string, error) {
|
|||
return projectID, zone, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) raiseFirewallChangeNeededEvent(svc *v1.Service, cmd string) {
|
||||
msg := fmt.Sprintf("Firewall change required by network admin: `%v`", cmd)
|
||||
if gce.eventRecorder != nil && svc != nil {
|
||||
gce.eventRecorder.Event(svc, v1.EventTypeNormal, "LoadBalancerManualChange", msg)
|
||||
}
|
||||
}
|
||||
|
||||
// FirewallToGCloudCreateCmd generates a gcloud command to create a firewall with specified params
|
||||
func FirewallToGCloudCreateCmd(fw *compute.Firewall, projectID string) string {
|
||||
args := firewallToGcloudArgs(fw, projectID)
|
||||
return fmt.Sprintf("gcloud compute firewall-rules create %v --network %v %v", fw.Name, getNameFromLink(fw.Network), args)
|
||||
}
|
||||
|
||||
// FirewallToGCloudCreateCmd generates a gcloud command to update a firewall to specified params
|
||||
func FirewallToGCloudUpdateCmd(fw *compute.Firewall, projectID string) string {
|
||||
args := firewallToGcloudArgs(fw, projectID)
|
||||
return fmt.Sprintf("gcloud compute firewall-rules update %v %v", fw.Name, args)
|
||||
}
|
||||
|
||||
// FirewallToGCloudCreateCmd generates a gcloud command to delete a firewall to specified params
|
||||
func FirewallToGCloudDeleteCmd(fwName, projectID string) string {
|
||||
return fmt.Sprintf("gcloud compute firewall-rules delete %v --project %v", fwName, projectID)
|
||||
}
|
||||
|
||||
func firewallToGcloudArgs(fw *compute.Firewall, projectID string) string {
|
||||
var allPorts []string
|
||||
for _, a := range fw.Allowed {
|
||||
for _, p := range a.Ports {
|
||||
allPorts = append(allPorts, fmt.Sprintf("%v:%v", a.IPProtocol, p))
|
||||
}
|
||||
}
|
||||
allow := strings.Join(allPorts, ",")
|
||||
srcRngs := strings.Join(fw.SourceRanges, ",")
|
||||
targets := strings.Join(fw.TargetTags, ",")
|
||||
return fmt.Sprintf("--description %q --allow %v --source-ranges %v --target-tags %v --project %v", fw.Description, allow, srcRngs, targets, projectID)
|
||||
}
|
||||
|
||||
// Take a GCE instance 'hostname' and break it down to something that can be fed
|
||||
// to the GCE API client library. Basically this means reducing 'kubernetes-
|
||||
// node-2.c.my-proj.internal' to 'kubernetes-node-2' if necessary.
|
||||
|
|
@ -149,3 +187,27 @@ func ignoreNotFound(err error) error {
|
|||
func isNotFoundOrInUse(err error) bool {
|
||||
return isNotFound(err) || isInUsedByError(err)
|
||||
}
|
||||
|
||||
func isForbidden(err error) bool {
|
||||
return isHTTPErrorCode(err, http.StatusForbidden)
|
||||
}
|
||||
|
||||
func makeGoogleAPINotFoundError(message string) error {
|
||||
return &googleapi.Error{Code: http.StatusNotFound, Message: message}
|
||||
}
|
||||
|
||||
func makeGoogleAPIError(code int, message string) error {
|
||||
return &googleapi.Error{Code: code, Message: message}
|
||||
}
|
||||
|
||||
// TODO(#51665): Remove this once Network Tiers becomes Beta in GCP.
|
||||
func handleAlphaNetworkTierGetError(err error) (string, error) {
|
||||
if isForbidden(err) {
|
||||
// Network tier is still an Alpha feature in GCP, and not every project
|
||||
// is whitelisted to access the API. If we cannot access the API, just
|
||||
// assume the tier is premium.
|
||||
return NetworkTierDefault.ToGCEValue(), nil
|
||||
}
|
||||
// Can't get the network tier, just return an error.
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
40
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_zones.go
generated
vendored
40
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_zones.go
generated
vendored
|
|
@ -18,19 +18,16 @@ package gce
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"strings"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func newZonesMetricContext(request, region string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{"zones_" + request, region, unusedMetricLabel},
|
||||
}
|
||||
return newGenericMetricContext("zones", request, region, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
// GetZone creates a cloudprovider.Zone of the current zone and region
|
||||
|
|
@ -41,6 +38,37 @@ func (gce *GCECloud) GetZone() (cloudprovider.Zone, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// GetZoneByProviderID implements Zones.GetZoneByProviderID
|
||||
// This is particularly useful in external cloud providers where the kubelet
|
||||
// does not initialize node data.
|
||||
func (gce *GCECloud) GetZoneByProviderID(providerID string) (cloudprovider.Zone, error) {
|
||||
_, zone, _, err := splitProviderID(providerID)
|
||||
if err != nil {
|
||||
return cloudprovider.Zone{}, err
|
||||
}
|
||||
region, err := GetGCERegion(zone)
|
||||
if err != nil {
|
||||
return cloudprovider.Zone{}, err
|
||||
}
|
||||
return cloudprovider.Zone{FailureDomain: zone, Region: region}, nil
|
||||
}
|
||||
|
||||
// GetZoneByNodeName implements Zones.GetZoneByNodeName
|
||||
// This is particularly useful in external cloud providers where the kubelet
|
||||
// does not initialize node data.
|
||||
func (gce *GCECloud) GetZoneByNodeName(nodeName types.NodeName) (cloudprovider.Zone, error) {
|
||||
instanceName := mapNodeNameToInstanceName(nodeName)
|
||||
instance, err := gce.getInstanceByName(instanceName)
|
||||
if err != nil {
|
||||
return cloudprovider.Zone{}, err
|
||||
}
|
||||
region, err := GetGCERegion(instance.Zone)
|
||||
if err != nil {
|
||||
return cloudprovider.Zone{}, err
|
||||
}
|
||||
return cloudprovider.Zone{FailureDomain: instance.Zone, Region: region}, nil
|
||||
}
|
||||
|
||||
// ListZonesInRegion returns all zones in a GCP region
|
||||
func (gce *GCECloud) ListZonesInRegion(region string) ([]*compute.Zone, error) {
|
||||
mc := newZonesMetricContext("list", region)
|
||||
|
|
|
|||
167
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/kms.go
generated
vendored
Normal file
167
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/kms.go
generated
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
Copyright 2017 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 gce
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
cloudkms "google.golang.org/api/cloudkms/v1"
|
||||
"google.golang.org/api/googleapi"
|
||||
gcfg "gopkg.in/gcfg.v1"
|
||||
"k8s.io/apiserver/pkg/storage/value/encrypt/envelope"
|
||||
)
|
||||
|
||||
const (
|
||||
// KMSServiceName is the name of the cloudkms provider registered by this cloud.
|
||||
KMSServiceName = "gcp-cloudkms"
|
||||
|
||||
defaultGKMSKeyRing = "google-container-engine"
|
||||
defaultGKMSKeyRingLocation = "global"
|
||||
)
|
||||
|
||||
// gkmsConfig contains the GCE specific KMS configuration for setting up a KMS connection.
|
||||
type gkmsConfig struct {
|
||||
Global struct {
|
||||
// location is the KMS location of the KeyRing to be used for encryption.
|
||||
// It can be found by checking the available KeyRings in the IAM UI.
|
||||
// This is not the same as the GCP location of the project.
|
||||
// +optional
|
||||
Location string `gcfg:"kms-location"`
|
||||
// keyRing is the keyRing of the hosted key to be used. The default value is "google-kubernetes".
|
||||
// +optional
|
||||
KeyRing string `gcfg:"kms-keyring"`
|
||||
// cryptoKey is the name of the key to be used for encryption of Data-Encryption-Keys.
|
||||
CryptoKey string `gcfg:"kms-cryptokey"`
|
||||
}
|
||||
}
|
||||
|
||||
// readGCPCloudKMSConfig parses and returns the configuration parameters for Google Cloud KMS.
|
||||
func readGCPCloudKMSConfig(reader io.Reader) (*gkmsConfig, error) {
|
||||
cfg := &gkmsConfig{}
|
||||
if err := gcfg.FatalOnly(gcfg.ReadInto(cfg, reader)); err != nil {
|
||||
glog.Errorf("Couldn't read Google Cloud KMS config: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// gkmsService provides Encrypt and Decrypt methods which allow cryptographic operations
|
||||
// using Google Cloud KMS service.
|
||||
type gkmsService struct {
|
||||
parentName string
|
||||
cloudkmsService *cloudkms.Service
|
||||
}
|
||||
|
||||
// getGCPCloudKMSService provides a Google Cloud KMS based implementation of envelope.Service.
|
||||
func (gce *GCECloud) getGCPCloudKMSService(config io.Reader) (envelope.Service, error) {
|
||||
kmsConfig, err := readGCPCloudKMSConfig(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Hosting on GCE/GKE with Google KMS encryption provider
|
||||
cloudkmsService := gce.GetKMSService()
|
||||
|
||||
// Set defaults for location and keyRing.
|
||||
location := kmsConfig.Global.Location
|
||||
if len(location) == 0 {
|
||||
location = defaultGKMSKeyRingLocation
|
||||
}
|
||||
keyRing := kmsConfig.Global.KeyRing
|
||||
if len(keyRing) == 0 {
|
||||
keyRing = defaultGKMSKeyRing
|
||||
}
|
||||
|
||||
cryptoKey := kmsConfig.Global.CryptoKey
|
||||
if len(cryptoKey) == 0 {
|
||||
return nil, fmt.Errorf("missing cryptoKey for cloudprovided KMS: " + KMSServiceName)
|
||||
}
|
||||
|
||||
parentName := fmt.Sprintf("projects/%s/locations/%s", gce.projectID, location)
|
||||
|
||||
// Create the keyRing if it does not exist yet
|
||||
_, err = cloudkmsService.Projects.Locations.KeyRings.Create(parentName,
|
||||
&cloudkms.KeyRing{}).KeyRingId(keyRing).Do()
|
||||
if err != nil && unrecoverableCreationError(err) {
|
||||
return nil, err
|
||||
}
|
||||
parentName = parentName + "/keyRings/" + keyRing
|
||||
|
||||
// Create the cryptoKey if it does not exist yet
|
||||
_, err = cloudkmsService.Projects.Locations.KeyRings.CryptoKeys.Create(parentName,
|
||||
&cloudkms.CryptoKey{
|
||||
Purpose: "ENCRYPT_DECRYPT",
|
||||
}).CryptoKeyId(cryptoKey).Do()
|
||||
if err != nil && unrecoverableCreationError(err) {
|
||||
return nil, err
|
||||
}
|
||||
parentName = parentName + "/cryptoKeys/" + cryptoKey
|
||||
|
||||
service := &gkmsService{
|
||||
parentName: parentName,
|
||||
cloudkmsService: cloudkmsService,
|
||||
}
|
||||
|
||||
// Sanity check before startup. For non-GCP clusters, the user's account may not have permissions to create
|
||||
// the key. We need to verify the existence of the key before apiserver startup.
|
||||
_, err = service.Encrypt([]byte("test"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encrypt data using Google cloudkms, using key %s. Ensure that the keyRing and cryptoKey exist. Got error: %v", parentName, err)
|
||||
}
|
||||
|
||||
return service, nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts a base64 representation of encrypted bytes.
|
||||
func (t *gkmsService) Decrypt(data string) ([]byte, error) {
|
||||
resp, err := t.cloudkmsService.Projects.Locations.KeyRings.CryptoKeys.
|
||||
Decrypt(t.parentName, &cloudkms.DecryptRequest{
|
||||
Ciphertext: data,
|
||||
}).Do()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return base64.StdEncoding.DecodeString(resp.Plaintext)
|
||||
}
|
||||
|
||||
// Encrypt encrypts bytes, and returns base64 representation of the ciphertext.
|
||||
func (t *gkmsService) Encrypt(data []byte) (string, error) {
|
||||
resp, err := t.cloudkmsService.Projects.Locations.KeyRings.CryptoKeys.
|
||||
Encrypt(t.parentName, &cloudkms.EncryptRequest{
|
||||
Plaintext: base64.StdEncoding.EncodeToString(data),
|
||||
}).Do()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.Ciphertext, nil
|
||||
}
|
||||
|
||||
// unrecoverableCreationError decides if Kubernetes should ignore the encountered Google KMS
|
||||
// error. Only to be used for errors seen while creating a KeyRing or CryptoKey.
|
||||
func unrecoverableCreationError(err error) bool {
|
||||
apiError, isAPIError := err.(*googleapi.Error)
|
||||
// 409 means the object exists.
|
||||
// 403 means we do not have permission to create the object, the user must do it.
|
||||
// Else, it is an unrecoverable error.
|
||||
if !isAPIError || (apiError.Code != 409 && apiError.Code != 403) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
25
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/metrics.go
generated
vendored
25
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/metrics.go
generated
vendored
|
|
@ -22,21 +22,33 @@ import (
|
|||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
// Version strings for recording metrics.
|
||||
computeV1Version = "v1"
|
||||
computeAlphaVersion = "alpha"
|
||||
computeBetaVersion = "beta"
|
||||
)
|
||||
|
||||
type apiCallMetrics struct {
|
||||
latency *prometheus.HistogramVec
|
||||
errors *prometheus.CounterVec
|
||||
}
|
||||
|
||||
var (
|
||||
apiMetrics = registerAPIMetrics(
|
||||
metricLabels = []string{
|
||||
"request", // API function that is begin invoked.
|
||||
"region", // region (optional).
|
||||
"zone", // zone (optional).
|
||||
)
|
||||
"version", // API version.
|
||||
}
|
||||
|
||||
apiMetrics = registerAPIMetrics(metricLabels...)
|
||||
)
|
||||
|
||||
type metricContext struct {
|
||||
start time.Time
|
||||
start time.Time
|
||||
// The cardinalities of attributes and metricLabels (defined above) must
|
||||
// match, or prometheus will panic.
|
||||
attributes []string
|
||||
}
|
||||
|
||||
|
|
@ -54,6 +66,13 @@ func (mc *metricContext) Observe(err error) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func newGenericMetricContext(prefix, request, region, zone, version string) *metricContext {
|
||||
return &metricContext{
|
||||
start: time.Now(),
|
||||
attributes: []string{prefix + "_" + request, region, zone, version},
|
||||
}
|
||||
}
|
||||
|
||||
// registerApiMetrics adds metrics definitions for a category of API calls.
|
||||
func registerAPIMetrics(attributes ...string) *apiCallMetrics {
|
||||
metrics := &apiCallMetrics{
|
||||
|
|
|
|||
11
vendor/k8s.io/kubernetes/pkg/controller/BUILD
generated
vendored
11
vendor/k8s.io/kubernetes/pkg/controller/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -15,10 +13,11 @@ go_test(
|
|||
"controller_utils_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/install:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/controller/testutil:go_default_library",
|
||||
"//pkg/securitycontext:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
|
||||
|
|
@ -32,6 +31,7 @@ go_test(
|
|||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/record:go_default_library",
|
||||
|
|
@ -48,13 +48,11 @@ go_library(
|
|||
"doc.go",
|
||||
"lookup_cache.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/install:go_default_library",
|
||||
"//pkg/api/v1/pod:go_default_library",
|
||||
"//pkg/api/validation:go_default_library",
|
||||
"//pkg/client/retry:go_default_library",
|
||||
"//pkg/serviceaccount:go_default_library",
|
||||
"//pkg/util/hash:go_default_library",
|
||||
"//pkg/util/taints:go_default_library",
|
||||
|
|
@ -89,6 +87,7 @@ go_library(
|
|||
"//vendor/k8s.io/client-go/tools/record:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/reference:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/integer:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/retry:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -125,9 +124,11 @@ filegroup(
|
|||
"//pkg/controller/service:all-srcs",
|
||||
"//pkg/controller/serviceaccount:all-srcs",
|
||||
"//pkg/controller/statefulset:all-srcs",
|
||||
"//pkg/controller/testutil:all-srcs",
|
||||
"//pkg/controller/ttl:all-srcs",
|
||||
"//pkg/controller/volume/attachdetach:all-srcs",
|
||||
"//pkg/controller/volume/events:all-srcs",
|
||||
"//pkg/controller/volume/expand:all-srcs",
|
||||
"//pkg/controller/volume/persistentvolume:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
|
|
|
|||
15
vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go
generated
vendored
15
vendor/k8s.io/kubernetes/pkg/controller/controller_ref_manager.go
generated
vendored
|
|
@ -31,19 +31,6 @@ import (
|
|||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
)
|
||||
|
||||
// GetControllerOf returns the controllerRef if controllee has a controller,
|
||||
// otherwise returns nil.
|
||||
func GetControllerOf(controllee metav1.Object) *metav1.OwnerReference {
|
||||
ownerRefs := controllee.GetOwnerReferences()
|
||||
for i := range ownerRefs {
|
||||
owner := &ownerRefs[i]
|
||||
if owner.Controller != nil && *owner.Controller == true {
|
||||
return owner
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type BaseControllerRefManager struct {
|
||||
Controller metav1.Object
|
||||
Selector labels.Selector
|
||||
|
|
@ -78,7 +65,7 @@ func (m *BaseControllerRefManager) CanAdopt() error {
|
|||
//
|
||||
// No reconciliation will be attempted if the controller is being deleted.
|
||||
func (m *BaseControllerRefManager) ClaimObject(obj metav1.Object, match func(metav1.Object) bool, adopt, release func(metav1.Object) error) (bool, error) {
|
||||
controllerRef := GetControllerOf(obj)
|
||||
controllerRef := metav1.GetControllerOf(obj)
|
||||
if controllerRef != nil {
|
||||
if controllerRef.UID != m.Controller.GetUID() {
|
||||
// Owned by someone else. Ignore.
|
||||
|
|
|
|||
217
vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go
generated
vendored
217
vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go
generated
vendored
|
|
@ -43,10 +43,10 @@ import (
|
|||
"k8s.io/client-go/tools/record"
|
||||
ref "k8s.io/client-go/tools/reference"
|
||||
"k8s.io/client-go/util/integer"
|
||||
clientretry "k8s.io/client-go/util/retry"
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
clientretry "k8s.io/kubernetes/pkg/client/retry"
|
||||
hashutil "k8s.io/kubernetes/pkg/util/hash"
|
||||
taintutils "k8s.io/kubernetes/pkg/util/taints"
|
||||
|
||||
|
|
@ -65,6 +65,21 @@ const (
|
|||
// 500 pods. Just creation is limited to 20qps, and watching happens with ~10-30s
|
||||
// latency/pod at the scale of 3000 pods over 100 nodes.
|
||||
ExpectationsTimeout = 5 * time.Minute
|
||||
// When batching pod creates, SlowStartInitialBatchSize is the size of the
|
||||
// inital batch. The size of each successive batch is twice the size of
|
||||
// the previous batch. For example, for a value of 1, batch sizes would be
|
||||
// 1, 2, 4, 8, ... and for a value of 10, batch sizes would be
|
||||
// 10, 20, 40, 80, ... Setting the value higher means that quota denials
|
||||
// will result in more doomed API calls and associated event spam. Setting
|
||||
// the value lower will result in more API call round trip periods for
|
||||
// large batches.
|
||||
//
|
||||
// Given a number of pods to start "N":
|
||||
// The number of doomed calls per sync once quota is exceeded is given by:
|
||||
// min(N,SlowStartInitialBatchSize)
|
||||
// The number of batches is given by:
|
||||
// 1+floor(log_2(ceil(N/SlowStartInitialBatchSize)))
|
||||
SlowStartInitialBatchSize = 1
|
||||
)
|
||||
|
||||
var UpdateTaintBackoff = wait.Backoff{
|
||||
|
|
@ -559,11 +574,7 @@ func GetPodFromTemplate(template *v1.PodTemplateSpec, parentObject runtime.Objec
|
|||
if controllerRef != nil {
|
||||
pod.OwnerReferences = append(pod.OwnerReferences, *controllerRef)
|
||||
}
|
||||
clone, err := scheme.Scheme.DeepCopy(&template.Spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pod.Spec = *clone.(*v1.PodSpec)
|
||||
pod.Spec = *template.Spec.DeepCopy()
|
||||
return pod, nil
|
||||
}
|
||||
|
||||
|
|
@ -580,7 +591,7 @@ func (r RealPodControl) createPods(nodeName, namespace string, template *v1.PodT
|
|||
}
|
||||
if newPod, err := r.KubeClient.Core().Pods(namespace).Create(pod); err != nil {
|
||||
r.Recorder.Eventf(object, v1.EventTypeWarning, FailedCreatePodReason, "Error creating: %v", err)
|
||||
return fmt.Errorf("unable to create pods: %v", err)
|
||||
return err
|
||||
} else {
|
||||
accessor, err := meta.Accessor(object)
|
||||
if err != nil {
|
||||
|
|
@ -610,11 +621,13 @@ func (r RealPodControl) DeletePod(namespace string, podID string, object runtime
|
|||
|
||||
type FakePodControl struct {
|
||||
sync.Mutex
|
||||
Templates []v1.PodTemplateSpec
|
||||
ControllerRefs []metav1.OwnerReference
|
||||
DeletePodName []string
|
||||
Patches [][]byte
|
||||
Err error
|
||||
Templates []v1.PodTemplateSpec
|
||||
ControllerRefs []metav1.OwnerReference
|
||||
DeletePodName []string
|
||||
Patches [][]byte
|
||||
Err error
|
||||
CreateLimit int
|
||||
CreateCallCount int
|
||||
}
|
||||
|
||||
var _ PodControlInterface = &FakePodControl{}
|
||||
|
|
@ -632,6 +645,10 @@ func (f *FakePodControl) PatchPod(namespace, name string, data []byte) error {
|
|||
func (f *FakePodControl) CreatePods(namespace string, spec *v1.PodTemplateSpec, object runtime.Object) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.CreateCallCount++
|
||||
if f.CreateLimit != 0 && f.CreateCallCount > f.CreateLimit {
|
||||
return fmt.Errorf("Not creating pod, limit %d already reached (create call %d)", f.CreateLimit, f.CreateCallCount)
|
||||
}
|
||||
f.Templates = append(f.Templates, *spec)
|
||||
if f.Err != nil {
|
||||
return f.Err
|
||||
|
|
@ -642,6 +659,10 @@ func (f *FakePodControl) CreatePods(namespace string, spec *v1.PodTemplateSpec,
|
|||
func (f *FakePodControl) CreatePodsWithControllerRef(namespace string, spec *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.CreateCallCount++
|
||||
if f.CreateLimit != 0 && f.CreateCallCount > f.CreateLimit {
|
||||
return fmt.Errorf("Not creating pod, limit %d already reached (create call %d)", f.CreateLimit, f.CreateCallCount)
|
||||
}
|
||||
f.Templates = append(f.Templates, *spec)
|
||||
f.ControllerRefs = append(f.ControllerRefs, *controllerRef)
|
||||
if f.Err != nil {
|
||||
|
|
@ -653,6 +674,10 @@ func (f *FakePodControl) CreatePodsWithControllerRef(namespace string, spec *v1.
|
|||
func (f *FakePodControl) CreatePodsOnNode(nodeName, namespace string, template *v1.PodTemplateSpec, object runtime.Object, controllerRef *metav1.OwnerReference) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.CreateCallCount++
|
||||
if f.CreateLimit != 0 && f.CreateCallCount > f.CreateLimit {
|
||||
return fmt.Errorf("Not creating pod, limit %d already reached (create call %d)", f.CreateLimit, f.CreateCallCount)
|
||||
}
|
||||
f.Templates = append(f.Templates, *template)
|
||||
f.ControllerRefs = append(f.ControllerRefs, *controllerRef)
|
||||
if f.Err != nil {
|
||||
|
|
@ -678,6 +703,8 @@ func (f *FakePodControl) Clear() {
|
|||
f.Templates = []v1.PodTemplateSpec{}
|
||||
f.ControllerRefs = []metav1.OwnerReference{}
|
||||
f.Patches = [][]byte{}
|
||||
f.CreateLimit = 0
|
||||
f.CreateCallCount = 0
|
||||
}
|
||||
|
||||
// ByLogging allows custom sorting of pods so the best one can be picked for getting its logs.
|
||||
|
|
@ -711,8 +738,8 @@ func (s ByLogging) Less(i, j int) bool {
|
|||
return maxContainerRestarts(s[i]) > maxContainerRestarts(s[j])
|
||||
}
|
||||
// 6. older pods < newer pods < empty timestamp pods
|
||||
if !s[i].CreationTimestamp.Equal(s[j].CreationTimestamp) {
|
||||
return afterOrZero(s[j].CreationTimestamp, s[i].CreationTimestamp)
|
||||
if !s[i].CreationTimestamp.Equal(&s[j].CreationTimestamp) {
|
||||
return afterOrZero(&s[j].CreationTimestamp, &s[i].CreationTimestamp)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -751,31 +778,31 @@ func (s ActivePods) Less(i, j int) bool {
|
|||
return maxContainerRestarts(s[i]) > maxContainerRestarts(s[j])
|
||||
}
|
||||
// 6. Empty creation time pods < newer pods < older pods
|
||||
if !s[i].CreationTimestamp.Equal(s[j].CreationTimestamp) {
|
||||
return afterOrZero(s[i].CreationTimestamp, s[j].CreationTimestamp)
|
||||
if !s[i].CreationTimestamp.Equal(&s[j].CreationTimestamp) {
|
||||
return afterOrZero(&s[i].CreationTimestamp, &s[j].CreationTimestamp)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// afterOrZero checks if time t1 is after time t2; if one of them
|
||||
// is zero, the zero time is seen as after non-zero time.
|
||||
func afterOrZero(t1, t2 metav1.Time) bool {
|
||||
func afterOrZero(t1, t2 *metav1.Time) bool {
|
||||
if t1.Time.IsZero() || t2.Time.IsZero() {
|
||||
return t1.Time.IsZero()
|
||||
}
|
||||
return t1.After(t2.Time)
|
||||
}
|
||||
|
||||
func podReadyTime(pod *v1.Pod) metav1.Time {
|
||||
func podReadyTime(pod *v1.Pod) *metav1.Time {
|
||||
if podutil.IsPodReady(pod) {
|
||||
for _, c := range pod.Status.Conditions {
|
||||
// we only care about pod ready conditions
|
||||
if c.Type == v1.PodReady && c.Status == v1.ConditionTrue {
|
||||
return c.LastTransitionTime
|
||||
return &c.LastTransitionTime
|
||||
}
|
||||
}
|
||||
}
|
||||
return metav1.Time{}
|
||||
return &metav1.Time{}
|
||||
}
|
||||
|
||||
func maxContainerRestarts(pod *v1.Pod) int {
|
||||
|
|
@ -841,10 +868,10 @@ type ControllersByCreationTimestamp []*v1.ReplicationController
|
|||
func (o ControllersByCreationTimestamp) Len() int { return len(o) }
|
||||
func (o ControllersByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
|
||||
func (o ControllersByCreationTimestamp) Less(i, j int) bool {
|
||||
if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) {
|
||||
if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) {
|
||||
return o[i].Name < o[j].Name
|
||||
}
|
||||
return o[i].CreationTimestamp.Before(o[j].CreationTimestamp)
|
||||
return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp)
|
||||
}
|
||||
|
||||
// ReplicaSetsByCreationTimestamp sorts a list of ReplicaSet by creation timestamp, using their names as a tie breaker.
|
||||
|
|
@ -853,10 +880,10 @@ type ReplicaSetsByCreationTimestamp []*extensions.ReplicaSet
|
|||
func (o ReplicaSetsByCreationTimestamp) Len() int { return len(o) }
|
||||
func (o ReplicaSetsByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
|
||||
func (o ReplicaSetsByCreationTimestamp) Less(i, j int) bool {
|
||||
if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) {
|
||||
if o[i].CreationTimestamp.Equal(&o[j].CreationTimestamp) {
|
||||
return o[i].Name < o[j].Name
|
||||
}
|
||||
return o[i].CreationTimestamp.Before(o[j].CreationTimestamp)
|
||||
return o[i].CreationTimestamp.Before(&o[j].CreationTimestamp)
|
||||
}
|
||||
|
||||
// ReplicaSetsBySizeOlder sorts a list of ReplicaSet by size in descending order, using their creation timestamp or name as a tie breaker.
|
||||
|
|
@ -885,50 +912,11 @@ func (o ReplicaSetsBySizeNewer) Less(i, j int) bool {
|
|||
return *(o[i].Spec.Replicas) > *(o[j].Spec.Replicas)
|
||||
}
|
||||
|
||||
func AddOrUpdateTaintOnNode(c clientset.Interface, nodeName string, taint *v1.Taint) error {
|
||||
firstTry := true
|
||||
return clientretry.RetryOnConflict(UpdateTaintBackoff, func() error {
|
||||
var err error
|
||||
var oldNode *v1.Node
|
||||
// First we try getting node from the API server cache, as it's cheaper. If it fails
|
||||
// we get it from etcd to be sure to have fresh data.
|
||||
if firstTry {
|
||||
oldNode, err = c.Core().Nodes().Get(nodeName, metav1.GetOptions{ResourceVersion: "0"})
|
||||
firstTry = false
|
||||
} else {
|
||||
oldNode, err = c.Core().Nodes().Get(nodeName, metav1.GetOptions{})
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newNode, ok, err := taintutils.AddOrUpdateTaint(oldNode, taint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to update taint annotation!")
|
||||
}
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return PatchNodeTaints(c, nodeName, oldNode, newNode)
|
||||
})
|
||||
}
|
||||
|
||||
// RemoveTaintOffNode is for cleaning up taints temporarily added to node,
|
||||
// won't fail if target taint doesn't exist or has been removed.
|
||||
// If passed a node it'll check if there's anything to be done, if taint is not present it won't issue
|
||||
// any API calls.
|
||||
func RemoveTaintOffNode(c clientset.Interface, nodeName string, taint *v1.Taint, node *v1.Node) error {
|
||||
// Short circuit for limiting amount of API calls.
|
||||
if node != nil {
|
||||
match := false
|
||||
for i := range node.Spec.Taints {
|
||||
if node.Spec.Taints[i].MatchTaint(taint) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
return nil
|
||||
}
|
||||
// AddOrUpdateTaintOnNode add taints to the node. If taint was added into node, it'll issue API calls
|
||||
// to update nodes; otherwise, no API calls. Return error if any.
|
||||
func AddOrUpdateTaintOnNode(c clientset.Interface, nodeName string, taints ...*v1.Taint) error {
|
||||
if len(taints) == 0 {
|
||||
return nil
|
||||
}
|
||||
firstTry := true
|
||||
return clientretry.RetryOnConflict(UpdateTaintBackoff, func() error {
|
||||
|
|
@ -945,11 +933,77 @@ func RemoveTaintOffNode(c clientset.Interface, nodeName string, taint *v1.Taint,
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newNode, ok, err := taintutils.RemoveTaint(oldNode, taint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to update taint annotation!")
|
||||
|
||||
var newNode *v1.Node
|
||||
oldNodeCopy := oldNode
|
||||
updated := false
|
||||
for _, taint := range taints {
|
||||
curNewNode, ok, err := taintutils.AddOrUpdateTaint(oldNodeCopy, taint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to update taint of node!")
|
||||
}
|
||||
updated = updated || ok
|
||||
newNode = curNewNode
|
||||
oldNodeCopy = curNewNode
|
||||
}
|
||||
if !ok {
|
||||
if !updated {
|
||||
return nil
|
||||
}
|
||||
return PatchNodeTaints(c, nodeName, oldNode, newNode)
|
||||
})
|
||||
}
|
||||
|
||||
// RemoveTaintOffNode is for cleaning up taints temporarily added to node,
|
||||
// won't fail if target taint doesn't exist or has been removed.
|
||||
// If passed a node it'll check if there's anything to be done, if taint is not present it won't issue
|
||||
// any API calls.
|
||||
func RemoveTaintOffNode(c clientset.Interface, nodeName string, node *v1.Node, taints ...*v1.Taint) error {
|
||||
if len(taints) == 0 {
|
||||
return nil
|
||||
}
|
||||
// Short circuit for limiting amount of API calls.
|
||||
if node != nil {
|
||||
match := false
|
||||
for _, taint := range taints {
|
||||
if taintutils.TaintExists(node.Spec.Taints, taint) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
firstTry := true
|
||||
return clientretry.RetryOnConflict(UpdateTaintBackoff, func() error {
|
||||
var err error
|
||||
var oldNode *v1.Node
|
||||
// First we try getting node from the API server cache, as it's cheaper. If it fails
|
||||
// we get it from etcd to be sure to have fresh data.
|
||||
if firstTry {
|
||||
oldNode, err = c.Core().Nodes().Get(nodeName, metav1.GetOptions{ResourceVersion: "0"})
|
||||
firstTry = false
|
||||
} else {
|
||||
oldNode, err = c.Core().Nodes().Get(nodeName, metav1.GetOptions{})
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var newNode *v1.Node
|
||||
oldNodeCopy := oldNode
|
||||
updated := false
|
||||
for _, taint := range taints {
|
||||
curNewNode, ok, err := taintutils.RemoveTaint(oldNodeCopy, taint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to remove taint of node!")
|
||||
}
|
||||
updated = updated || ok
|
||||
newNode = curNewNode
|
||||
oldNodeCopy = curNewNode
|
||||
}
|
||||
if !updated {
|
||||
return nil
|
||||
}
|
||||
return PatchNodeTaints(c, nodeName, oldNode, newNode)
|
||||
|
|
@ -964,18 +1018,11 @@ func PatchNodeTaints(c clientset.Interface, nodeName string, oldNode *v1.Node, n
|
|||
}
|
||||
|
||||
newTaints := newNode.Spec.Taints
|
||||
objCopy, err := scheme.Scheme.DeepCopy(oldNode)
|
||||
newNodeClone := oldNode.DeepCopy()
|
||||
newNodeClone.Spec.Taints = newTaints
|
||||
newData, err := json.Marshal(newNodeClone)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to copy node object %#v: %v", oldNode, err)
|
||||
}
|
||||
newNode, ok := (objCopy).(*v1.Node)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to cast copy onto node object %#v: %v", newNode, err)
|
||||
}
|
||||
newNode.Spec.Taints = newTaints
|
||||
newData, err := json.Marshal(newNode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal new node %#v for node %q: %v", newNode, nodeName, err)
|
||||
return fmt.Errorf("failed to marshal new node %#v for node %q: %v", newNodeClone, nodeName, err)
|
||||
}
|
||||
|
||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{})
|
||||
|
|
@ -1003,14 +1050,14 @@ func WaitForCacheSync(controllerName string, stopCh <-chan struct{}, cacheSyncs
|
|||
}
|
||||
|
||||
// ComputeHash returns a hash value calculated from pod template and a collisionCount to avoid hash collision
|
||||
func ComputeHash(template *v1.PodTemplateSpec, collisionCount *int64) uint32 {
|
||||
func ComputeHash(template *v1.PodTemplateSpec, collisionCount *int32) uint32 {
|
||||
podTemplateSpecHasher := fnv.New32a()
|
||||
hashutil.DeepHashObject(podTemplateSpecHasher, *template)
|
||||
|
||||
// Add collisionCount in the hash if it exists.
|
||||
if collisionCount != nil {
|
||||
collisionCountBytes := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(collisionCountBytes, uint64(*collisionCount))
|
||||
binary.LittleEndian.PutUint32(collisionCountBytes, uint32(*collisionCount))
|
||||
podTemplateSpecHasher.Write(collisionCountBytes)
|
||||
}
|
||||
|
||||
|
|
|
|||
4
vendor/k8s.io/kubernetes/pkg/features/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/features/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -10,8 +8,8 @@ load(
|
|||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["kube_features.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/features:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
],
|
||||
|
|
|
|||
79
vendor/k8s.io/kubernetes/pkg/features/kube_features.go
generated
vendored
79
vendor/k8s.io/kubernetes/pkg/features/kube_features.go
generated
vendored
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package features
|
||||
|
||||
import (
|
||||
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
|
||||
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
)
|
||||
|
|
@ -36,20 +37,13 @@ const (
|
|||
// alpha: v1.4
|
||||
ExternalTrafficLocalOnly utilfeature.Feature = "AllowExtTrafficLocalEndpoints"
|
||||
|
||||
// owner: @saad-ali
|
||||
// alpha: v1.3
|
||||
DynamicVolumeProvisioning utilfeature.Feature = "DynamicVolumeProvisioning"
|
||||
|
||||
// owner: @mtaufen
|
||||
// alpha: v1.4
|
||||
DynamicKubeletConfig utilfeature.Feature = "DynamicKubeletConfig"
|
||||
|
||||
// owner: tallclair
|
||||
// alpha: v1.5
|
||||
//
|
||||
// StreamingProxyRedirects controls whether the apiserver should intercept (and follow)
|
||||
// redirects from the backend (Kubelet) for streaming requests (exec/attach/port-forward).
|
||||
StreamingProxyRedirects utilfeature.Feature = genericfeatures.StreamingProxyRedirects
|
||||
// owner: @mtaufen
|
||||
// alpha: v1.8
|
||||
KubeletConfigFile utilfeature.Feature = "KubeletConfigFile"
|
||||
|
||||
// owner: @pweil-
|
||||
// alpha: v1.5
|
||||
|
|
@ -75,6 +69,13 @@ const (
|
|||
// Works only with Docker Container Runtime.
|
||||
Accelerators utilfeature.Feature = "Accelerators"
|
||||
|
||||
// owner: @jiayingz
|
||||
// alpha: v1.8
|
||||
//
|
||||
// Enables support for Device Plugins
|
||||
// Only Nvidia GPUs are tested as of v1.8.
|
||||
DevicePlugins utilfeature.Feature = "DevicePlugins"
|
||||
|
||||
// owner: @gmarek
|
||||
// alpha: v1.6
|
||||
//
|
||||
|
|
@ -109,6 +110,11 @@ const (
|
|||
// New local storage types to support local storage capacity isolation
|
||||
LocalStorageCapacityIsolation utilfeature.Feature = "LocalStorageCapacityIsolation"
|
||||
|
||||
// owner: @gnufied
|
||||
// alpha: v1.8
|
||||
// Ability to Expand persistent volumes
|
||||
ExpandPersistentVolumes utilfeature.Feature = "ExpandPersistentVolumes"
|
||||
|
||||
// owner: @verb
|
||||
// alpha: v1.8
|
||||
//
|
||||
|
|
@ -126,6 +132,37 @@ const (
|
|||
//
|
||||
// Enable equivalence class cache for scheduler.
|
||||
EnableEquivalenceClassCache utilfeature.Feature = "EnableEquivalenceClassCache"
|
||||
|
||||
// owner: @k82cn
|
||||
// alpha: v1.8
|
||||
//
|
||||
// Taint nodes based on their condition status for 'NetworkUnavailable',
|
||||
// 'MemoryPressure', 'OutOfDisk' and 'DiskPressure'.
|
||||
TaintNodesByCondition utilfeature.Feature = "TaintNodesByCondition"
|
||||
|
||||
// owner: @haibinxie
|
||||
// alpha: v1.8
|
||||
//
|
||||
// Implement IPVS-based in-cluster service load balancing
|
||||
SupportIPVSProxyMode utilfeature.Feature = "SupportIPVSProxyMode"
|
||||
|
||||
// owner: @jsafrane
|
||||
// alpha: v1.8
|
||||
//
|
||||
// Enable mount propagation of volumes.
|
||||
MountPropagation utilfeature.Feature = "MountPropagation"
|
||||
|
||||
// owner: @ConnorDoyle
|
||||
// alpha: v1.8
|
||||
//
|
||||
// Alternative container-level CPU affinity policies.
|
||||
CPUManager utilfeature.Feature = "CPUManager"
|
||||
|
||||
// owner: @derekwaynecarr
|
||||
// alpha: v1.8
|
||||
//
|
||||
// Enable pods to consume pre-allocated huge pages of varying page sizes
|
||||
HugePages utilfeature.Feature = "HugePages"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -139,21 +176,35 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
|
|||
ExternalTrafficLocalOnly: {Default: true, PreRelease: utilfeature.GA},
|
||||
AppArmor: {Default: true, PreRelease: utilfeature.Beta},
|
||||
DynamicKubeletConfig: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
DynamicVolumeProvisioning: {Default: true, PreRelease: utilfeature.Alpha},
|
||||
KubeletConfigFile: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
ExperimentalHostUserNamespaceDefaultingGate: {Default: false, PreRelease: utilfeature.Beta},
|
||||
ExperimentalCriticalPodAnnotation: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
Accelerators: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
DevicePlugins: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
TaintBasedEvictions: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
RotateKubeletServerCertificate: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
RotateKubeletClientCertificate: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
RotateKubeletClientCertificate: {Default: true, PreRelease: utilfeature.Beta},
|
||||
PersistentLocalVolumes: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
LocalStorageCapacityIsolation: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
HugePages: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
DebugContainers: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
PodPriority: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
EnableEquivalenceClassCache: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
TaintNodesByCondition: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
MountPropagation: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
ExpandPersistentVolumes: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
CPUManager: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
|
||||
// inherited features from generic apiserver, relisted here to get a conflict if it is changed
|
||||
// unintentionally on either side:
|
||||
StreamingProxyRedirects: {Default: true, PreRelease: utilfeature.Beta},
|
||||
genericfeatures.AdvancedAuditing: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
genericfeatures.StreamingProxyRedirects: {Default: true, PreRelease: utilfeature.Beta},
|
||||
genericfeatures.AdvancedAuditing: {Default: true, PreRelease: utilfeature.Beta},
|
||||
genericfeatures.APIResponseCompression: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
genericfeatures.Initializers: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
genericfeatures.APIListChunking: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
|
||||
// inherited features from apiextensions-apiserver, relisted here to get a conflict if it is changed
|
||||
// unintentionally on either side:
|
||||
apiextensionsfeatures.CustomResourceValidation: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
SupportIPVSProxyMode: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
}
|
||||
|
|
|
|||
5
vendor/k8s.io/kubernetes/pkg/kubelet/apis/BUILD
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/kubelet/apis/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -13,7 +11,6 @@ go_library(
|
|||
"well_known_annotations.go",
|
||||
"well_known_labels.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
@ -28,6 +25,8 @@ filegroup(
|
|||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/kubelet/apis/cri:all-srcs",
|
||||
"//pkg/kubelet/apis/deviceplugin/v1alpha1:all-srcs",
|
||||
"//pkg/kubelet/apis/kubeletconfig:all-srcs",
|
||||
"//pkg/kubelet/apis/stats/v1alpha1:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
|
|
|
|||
7
vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_labels.go
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_labels.go
generated
vendored
|
|
@ -17,9 +17,10 @@ limitations under the License.
|
|||
package apis
|
||||
|
||||
const (
|
||||
LabelHostname = "kubernetes.io/hostname"
|
||||
LabelZoneFailureDomain = "failure-domain.beta.kubernetes.io/zone"
|
||||
LabelZoneRegion = "failure-domain.beta.kubernetes.io/region"
|
||||
LabelHostname = "kubernetes.io/hostname"
|
||||
LabelZoneFailureDomain = "failure-domain.beta.kubernetes.io/zone"
|
||||
LabelMultiZoneDelimiter = "__"
|
||||
LabelZoneRegion = "failure-domain.beta.kubernetes.io/region"
|
||||
|
||||
LabelInstanceType = "beta.kubernetes.io/instance-type"
|
||||
|
||||
|
|
|
|||
53
vendor/k8s.io/kubernetes/pkg/kubelet/types/BUILD
generated
vendored
Normal file
53
vendor/k8s.io/kubernetes/pkg/kubelet/types/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"constants.go",
|
||||
"doc.go",
|
||||
"labels.go",
|
||||
"pod_update.go",
|
||||
"types.go",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"labels_test.go",
|
||||
"pod_update_test.go",
|
||||
"types_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
27
vendor/k8s.io/kubernetes/pkg/kubelet/types/constants.go
generated
vendored
Normal file
27
vendor/k8s.io/kubernetes/pkg/kubelet/types/constants.go
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Copyright 2015 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 types
|
||||
|
||||
const (
|
||||
// system default DNS resolver configuration
|
||||
ResolvConfDefault = "/etc/resolv.conf"
|
||||
|
||||
// different container runtimes
|
||||
DockerContainerRuntime = "docker"
|
||||
RktContainerRuntime = "rkt"
|
||||
RemoteContainerRuntime = "remote"
|
||||
)
|
||||
18
vendor/k8s.io/kubernetes/pkg/kubelet/types/doc.go
generated
vendored
Normal file
18
vendor/k8s.io/kubernetes/pkg/kubelet/types/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
Copyright 2015 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.
|
||||
*/
|
||||
|
||||
// Common types in the Kubelet.
|
||||
package types
|
||||
40
vendor/k8s.io/kubernetes/pkg/kubelet/types/labels.go
generated
vendored
Normal file
40
vendor/k8s.io/kubernetes/pkg/kubelet/types/labels.go
generated
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2016 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 types
|
||||
|
||||
const (
|
||||
KubernetesPodNameLabel = "io.kubernetes.pod.name"
|
||||
KubernetesPodNamespaceLabel = "io.kubernetes.pod.namespace"
|
||||
KubernetesPodUIDLabel = "io.kubernetes.pod.uid"
|
||||
KubernetesContainerNameLabel = "io.kubernetes.container.name"
|
||||
)
|
||||
|
||||
func GetContainerName(labels map[string]string) string {
|
||||
return labels[KubernetesContainerNameLabel]
|
||||
}
|
||||
|
||||
func GetPodName(labels map[string]string) string {
|
||||
return labels[KubernetesPodNameLabel]
|
||||
}
|
||||
|
||||
func GetPodUID(labels map[string]string) string {
|
||||
return labels[KubernetesPodUIDLabel]
|
||||
}
|
||||
|
||||
func GetPodNamespace(labels map[string]string) string {
|
||||
return labels[KubernetesPodNamespaceLabel]
|
||||
}
|
||||
159
vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update.go
generated
vendored
Normal file
159
vendor/k8s.io/kubernetes/pkg/kubelet/types/pod_update.go
generated
vendored
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
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 types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeapi "k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
const (
|
||||
ConfigSourceAnnotationKey = "kubernetes.io/config.source"
|
||||
ConfigMirrorAnnotationKey = v1.MirrorPodAnnotationKey
|
||||
ConfigFirstSeenAnnotationKey = "kubernetes.io/config.seen"
|
||||
ConfigHashAnnotationKey = "kubernetes.io/config.hash"
|
||||
CriticalPodAnnotationKey = "scheduler.alpha.kubernetes.io/critical-pod"
|
||||
)
|
||||
|
||||
// PodOperation defines what changes will be made on a pod configuration.
|
||||
type PodOperation int
|
||||
|
||||
const (
|
||||
// This is the current pod configuration
|
||||
SET PodOperation = iota
|
||||
// Pods with the given ids are new to this source
|
||||
ADD
|
||||
// Pods with the given ids are gracefully deleted from this source
|
||||
DELETE
|
||||
// Pods with the given ids have been removed from this source
|
||||
REMOVE
|
||||
// Pods with the given ids have been updated in this source
|
||||
UPDATE
|
||||
// Pods with the given ids have unexpected status in this source,
|
||||
// kubelet should reconcile status with this source
|
||||
RECONCILE
|
||||
|
||||
// These constants identify the sources of pods
|
||||
// Updates from a file
|
||||
FileSource = "file"
|
||||
// Updates from querying a web page
|
||||
HTTPSource = "http"
|
||||
// Updates from Kubernetes API Server
|
||||
ApiserverSource = "api"
|
||||
// Updates from all sources
|
||||
AllSource = "*"
|
||||
|
||||
NamespaceDefault = metav1.NamespaceDefault
|
||||
)
|
||||
|
||||
// PodUpdate defines an operation sent on the channel. You can add or remove single services by
|
||||
// sending an array of size one and Op == ADD|REMOVE (with REMOVE, only the ID is required).
|
||||
// For setting the state of the system to a given state for this source configuration, set
|
||||
// Pods as desired and Op to SET, which will reset the system state to that specified in this
|
||||
// operation for this source channel. To remove all pods, set Pods to empty object and Op to SET.
|
||||
//
|
||||
// Additionally, Pods should never be nil - it should always point to an empty slice. While
|
||||
// functionally similar, this helps our unit tests properly check that the correct PodUpdates
|
||||
// are generated.
|
||||
type PodUpdate struct {
|
||||
Pods []*v1.Pod
|
||||
Op PodOperation
|
||||
Source string
|
||||
}
|
||||
|
||||
// Gets all validated sources from the specified sources.
|
||||
func GetValidatedSources(sources []string) ([]string, error) {
|
||||
validated := make([]string, 0, len(sources))
|
||||
for _, source := range sources {
|
||||
switch source {
|
||||
case AllSource:
|
||||
return []string{FileSource, HTTPSource, ApiserverSource}, nil
|
||||
case FileSource, HTTPSource, ApiserverSource:
|
||||
validated = append(validated, source)
|
||||
break
|
||||
case "":
|
||||
break
|
||||
default:
|
||||
return []string{}, fmt.Errorf("unknown pod source %q", source)
|
||||
}
|
||||
}
|
||||
return validated, nil
|
||||
}
|
||||
|
||||
// GetPodSource returns the source of the pod based on the annotation.
|
||||
func GetPodSource(pod *v1.Pod) (string, error) {
|
||||
if pod.Annotations != nil {
|
||||
if source, ok := pod.Annotations[ConfigSourceAnnotationKey]; ok {
|
||||
return source, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("cannot get source of pod %q", pod.UID)
|
||||
}
|
||||
|
||||
// SyncPodType classifies pod updates, eg: create, update.
|
||||
type SyncPodType int
|
||||
|
||||
const (
|
||||
// SyncPodSync is when the pod is synced to ensure desired state
|
||||
SyncPodSync SyncPodType = iota
|
||||
// SyncPodUpdate is when the pod is updated from source
|
||||
SyncPodUpdate
|
||||
// SyncPodCreate is when the pod is created from source
|
||||
SyncPodCreate
|
||||
// SyncPodKill is when the pod is killed based on a trigger internal to the kubelet for eviction.
|
||||
// If a SyncPodKill request is made to pod workers, the request is never dropped, and will always be processed.
|
||||
SyncPodKill
|
||||
)
|
||||
|
||||
func (sp SyncPodType) String() string {
|
||||
switch sp {
|
||||
case SyncPodCreate:
|
||||
return "create"
|
||||
case SyncPodUpdate:
|
||||
return "update"
|
||||
case SyncPodSync:
|
||||
return "sync"
|
||||
case SyncPodKill:
|
||||
return "kill"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// IsCriticalPod returns true if the pod bears the critical pod annotation
|
||||
// key. Both the rescheduler and the kubelet use this key to make admission
|
||||
// and scheduling decisions.
|
||||
func IsCriticalPod(pod *v1.Pod) bool {
|
||||
return IsCritical(pod.Namespace, pod.Annotations)
|
||||
}
|
||||
|
||||
// IsCritical returns true if parameters bear the critical pod annotation
|
||||
// key. The DaemonSetController use this key directly to make scheduling decisions.
|
||||
func IsCritical(ns string, annotations map[string]string) bool {
|
||||
// Critical pods are restricted to "kube-system" namespace as of now.
|
||||
if ns != kubeapi.NamespaceSystem {
|
||||
return false
|
||||
}
|
||||
val, ok := annotations[CriticalPodAnnotationKey]
|
||||
if ok && val == "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
100
vendor/k8s.io/kubernetes/pkg/kubelet/types/types.go
generated
vendored
Normal file
100
vendor/k8s.io/kubernetes/pkg/kubelet/types/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
Copyright 2015 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 types
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// TODO: Reconcile custom types in kubelet/types and this subpackage
|
||||
|
||||
type HttpGetter interface {
|
||||
Get(url string) (*http.Response, error)
|
||||
}
|
||||
|
||||
// Timestamp wraps around time.Time and offers utilities to format and parse
|
||||
// the time using RFC3339Nano
|
||||
type Timestamp struct {
|
||||
time time.Time
|
||||
}
|
||||
|
||||
// NewTimestamp returns a Timestamp object using the current time.
|
||||
func NewTimestamp() *Timestamp {
|
||||
return &Timestamp{time.Now()}
|
||||
}
|
||||
|
||||
// ConvertToTimestamp takes a string, parses it using the RFC3339Nano layout,
|
||||
// and converts it to a Timestamp object.
|
||||
func ConvertToTimestamp(timeString string) *Timestamp {
|
||||
parsed, _ := time.Parse(time.RFC3339Nano, timeString)
|
||||
return &Timestamp{parsed}
|
||||
}
|
||||
|
||||
// Get returns the time as time.Time.
|
||||
func (t *Timestamp) Get() time.Time {
|
||||
return t.time
|
||||
}
|
||||
|
||||
// GetString returns the time in the string format using the RFC3339Nano
|
||||
// layout.
|
||||
func (t *Timestamp) GetString() string {
|
||||
return t.time.Format(time.RFC3339Nano)
|
||||
}
|
||||
|
||||
// A type to help sort container statuses based on container names.
|
||||
type SortedContainerStatuses []v1.ContainerStatus
|
||||
|
||||
func (s SortedContainerStatuses) Len() int { return len(s) }
|
||||
func (s SortedContainerStatuses) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
func (s SortedContainerStatuses) Less(i, j int) bool {
|
||||
return s[i].Name < s[j].Name
|
||||
}
|
||||
|
||||
// SortInitContainerStatuses ensures that statuses are in the order that their
|
||||
// init container appears in the pod spec
|
||||
func SortInitContainerStatuses(p *v1.Pod, statuses []v1.ContainerStatus) {
|
||||
containers := p.Spec.InitContainers
|
||||
current := 0
|
||||
for _, container := range containers {
|
||||
for j := current; j < len(statuses); j++ {
|
||||
if container.Name == statuses[j].Name {
|
||||
statuses[current], statuses[j] = statuses[j], statuses[current]
|
||||
current++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reservation represents reserved resources for non-pod components.
|
||||
type Reservation struct {
|
||||
// System represents resources reserved for non-kubernetes components.
|
||||
System v1.ResourceList
|
||||
// Kubernetes represents resources reserved for kubernetes system components.
|
||||
Kubernetes v1.ResourceList
|
||||
}
|
||||
|
||||
// A pod UID which has been translated/resolved to the representation known to kubelets.
|
||||
type ResolvedPodUID types.UID
|
||||
|
||||
// A pod UID for a mirror pod.
|
||||
type MirrorPodUID types.UID
|
||||
3
vendor/k8s.io/kubernetes/pkg/master/ports/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/master/ports/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -13,7 +11,6 @@ go_library(
|
|||
"doc.go",
|
||||
"ports.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
|||
6
vendor/k8s.io/kubernetes/pkg/security/apparmor/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/security/apparmor/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -13,10 +11,11 @@ go_library(
|
|||
srcs = [
|
||||
"helpers.go",
|
||||
"validate.go",
|
||||
"validate_disabled.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubelet/types:go_default_library",
|
||||
"//pkg/util/file:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
|
|
@ -30,7 +29,6 @@ go_test(
|
|||
"testdata/profiles",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
|
|
|
|||
5
vendor/k8s.io/kubernetes/pkg/security/apparmor/validate.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/security/apparmor/validate.go
generated
vendored
|
|
@ -28,6 +28,7 @@ import (
|
|||
"k8s.io/api/core/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
||||
)
|
||||
|
||||
|
|
@ -111,8 +112,8 @@ func validateHost(runtime string) error {
|
|||
}
|
||||
|
||||
// Check runtime support. Currently only Docker is supported.
|
||||
if runtime != "docker" {
|
||||
return fmt.Errorf("AppArmor is only enabled for 'docker' runtime. Found: %q.", runtime)
|
||||
if runtime != kubetypes.DockerContainerRuntime && runtime != kubetypes.RemoteContainerRuntime {
|
||||
return fmt.Errorf("AppArmor is only enabled for 'docker' and 'remote' runtimes. Found: %q.", runtime)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
7
vendor/k8s.io/kubernetes/pkg/serviceaccount/BUILD
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/serviceaccount/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -14,7 +12,6 @@ go_library(
|
|||
"jwt.go",
|
||||
"util.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/github.com/dgrijalva/jwt-go:go_default_library",
|
||||
|
|
@ -23,17 +20,15 @@ go_library(
|
|||
"//vendor/k8s.io/apiserver/pkg/authentication/authenticator:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/cert:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_xtest",
|
||||
srcs = ["jwt_test.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//pkg/controller/serviceaccount:go_default_library",
|
||||
"//pkg/serviceaccount:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
|
||||
|
|
|
|||
1
vendor/k8s.io/kubernetes/pkg/serviceaccount/OWNERS
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/serviceaccount/OWNERS
generated
vendored
|
|
@ -6,3 +6,4 @@ reviewers:
|
|||
- deads2k
|
||||
- mikedanese
|
||||
- ericchiang
|
||||
- enj
|
||||
|
|
|
|||
72
vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt.go
generated
vendored
72
vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt.go
generated
vendored
|
|
@ -21,16 +21,13 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
apiserverserviceaccount "k8s.io/apiserver/pkg/authentication/serviceaccount"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/client-go/util/cert"
|
||||
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
"github.com/golang/glog"
|
||||
|
|
@ -59,75 +56,6 @@ type TokenGenerator interface {
|
|||
GenerateToken(serviceAccount v1.ServiceAccount, secret v1.Secret) (string, error)
|
||||
}
|
||||
|
||||
// ReadPrivateKey is a helper function for reading a private key from a PEM-encoded file
|
||||
func ReadPrivateKey(file string) (interface{}, error) {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := cert.ParsePrivateKeyPEM(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading private key file %s: %v", file, err)
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// ReadPublicKeys is a helper function for reading an array of rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded file.
|
||||
// Reads public keys from both public and private key files.
|
||||
func ReadPublicKeys(file string) ([]interface{}, error) {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keys, err := ReadPublicKeysFromPEM(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading public key file %s: %v", file, err)
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
// ReadPublicKeysFromPEM is a helper function for reading an array of rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded byte array.
|
||||
// Reads public keys from both public and private key files.
|
||||
func ReadPublicKeysFromPEM(data []byte) ([]interface{}, error) {
|
||||
var block *pem.Block
|
||||
keys := []interface{}{}
|
||||
for {
|
||||
// read the next block
|
||||
block, data = pem.Decode(data)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
|
||||
// get PEM bytes for just this block
|
||||
blockData := pem.EncodeToMemory(block)
|
||||
if privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(blockData); err == nil {
|
||||
keys = append(keys, &privateKey.PublicKey)
|
||||
continue
|
||||
}
|
||||
if publicKey, err := jwt.ParseRSAPublicKeyFromPEM(blockData); err == nil {
|
||||
keys = append(keys, publicKey)
|
||||
continue
|
||||
}
|
||||
|
||||
if privateKey, err := jwt.ParseECPrivateKeyFromPEM(blockData); err == nil {
|
||||
keys = append(keys, &privateKey.PublicKey)
|
||||
continue
|
||||
}
|
||||
if publicKey, err := jwt.ParseECPublicKeyFromPEM(blockData); err == nil {
|
||||
keys = append(keys, publicKey)
|
||||
continue
|
||||
}
|
||||
|
||||
// tolerate non-key PEM blocks for backwards compatibility
|
||||
// originally, only the first PEM block was parsed and expected to be a key block
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA key")
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
// JWTTokenGenerator returns a TokenGenerator that generates signed JWT tokens, using the given privateKey.
|
||||
// privateKey is a PEM-encoded byte array of a private RSA key.
|
||||
// JWTTokenAuthenticator()
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/serviceaccount/util.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/serviceaccount/util.go
generated
vendored
|
|
@ -28,7 +28,7 @@ func UserInfo(namespace, name, uid string) user.Info {
|
|||
return &user.DefaultInfo{
|
||||
Name: apiserverserviceaccount.MakeUsername(namespace, name),
|
||||
UID: uid,
|
||||
Groups: apiserverserviceaccount.MakeGroupNames(namespace, name),
|
||||
Groups: apiserverserviceaccount.MakeGroupNames(namespace),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
3
vendor/k8s.io/kubernetes/pkg/util/file/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/util/file/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -10,7 +8,6 @@ load(
|
|||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["file.go"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
|||
4
vendor/k8s.io/kubernetes/pkg/util/hash/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/util/hash/BUILD
generated
vendored
|
|
@ -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 = ["hash.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//vendor/github.com/davecgh/go-spew/spew:go_default_library"],
|
||||
)
|
||||
|
||||
|
|
@ -19,7 +16,6 @@ go_test(
|
|||
name = "go_default_test",
|
||||
srcs = ["hash_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = ["//vendor/github.com/davecgh/go-spew/spew:go_default_library"],
|
||||
)
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue