Update go dependencies (#2234)
This commit is contained in:
parent
6e099c5f57
commit
93c72ef646
1236 changed files with 37226 additions and 49844 deletions
3
vendor/k8s.io/kubernetes/pkg/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/BUILD
generated
vendored
|
|
@ -28,7 +28,6 @@ filegroup(
|
|||
"//pkg/api/v1/pod:all-srcs",
|
||||
"//pkg/api/v1/resource:all-srcs",
|
||||
"//pkg/api/v1/service:all-srcs",
|
||||
"//pkg/apimachinery/tests:all-srcs",
|
||||
"//pkg/apis/abac:all-srcs",
|
||||
"//pkg/apis/admission:all-srcs",
|
||||
"//pkg/apis/admissionregistration:all-srcs",
|
||||
|
|
@ -85,7 +84,6 @@ filegroup(
|
|||
"//pkg/features:all-srcs",
|
||||
"//pkg/fieldpath:all-srcs",
|
||||
"//pkg/generated:all-srcs",
|
||||
"//pkg/hyperkube:all-srcs",
|
||||
"//pkg/kubeapiserver:all-srcs",
|
||||
"//pkg/kubectl:all-srcs",
|
||||
"//pkg/kubelet:all-srcs",
|
||||
|
|
@ -97,6 +95,7 @@ filegroup(
|
|||
"//pkg/quota:all-srcs",
|
||||
"//pkg/registry:all-srcs",
|
||||
"//pkg/routes:all-srcs",
|
||||
"//pkg/scheduler:all-srcs",
|
||||
"//pkg/security:all-srcs",
|
||||
"//pkg/securitycontext:all-srcs",
|
||||
"//pkg/serviceaccount:all-srcs",
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/api/service/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/api/service/BUILD
generated
vendored
|
|
@ -19,8 +19,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/api/service",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/util/net/sets:go_default_library",
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/api/v1/pod/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/api/v1/pod/BUILD
generated
vendored
|
|
@ -20,8 +20,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/api/v1/pod",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
|
|
|
|||
6
vendor/k8s.io/kubernetes/pkg/apis/autoscaling/types.go
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/apis/autoscaling/types.go
generated
vendored
|
|
@ -116,7 +116,8 @@ var (
|
|||
// MetricSpec specifies how to scale based on a single metric
|
||||
// (only `type` and one other matching field should be set at once).
|
||||
type MetricSpec struct {
|
||||
// Type is the type of metric source. It should match one of the fields below.
|
||||
// Type is the type of metric source. It should be one of "Object",
|
||||
// "Pods" or "Resource", each mapping to a matching field in the object.
|
||||
Type MetricSourceType
|
||||
|
||||
// Object refers to a metric describing a single kubernetes object
|
||||
|
|
@ -261,7 +262,8 @@ type HorizontalPodAutoscalerCondition struct {
|
|||
|
||||
// MetricStatus describes the last-read state of a single metric.
|
||||
type MetricStatus struct {
|
||||
// Type is the type of metric source. It will match one of the fields below.
|
||||
// Type is the type of metric source. It will be one of "Object",
|
||||
// "Pods" or "Resource", each corresponds to a matching field in the object.
|
||||
Type MetricSourceType
|
||||
|
||||
// Object refers to a metric describing a single kubernetes object
|
||||
|
|
|
|||
7
vendor/k8s.io/kubernetes/pkg/apis/core/BUILD
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/apis/core/BUILD
generated
vendored
|
|
@ -32,9 +32,12 @@ go_library(
|
|||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["taint_test.go"],
|
||||
srcs = [
|
||||
"taint_test.go",
|
||||
"toleration_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/apis/core",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/apis/core/helper/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/apis/core/helper/BUILD
generated
vendored
|
|
@ -9,8 +9,8 @@ load(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["helpers_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/apis/core/helper",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
|
|
|
|||
59
vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers.go
generated
vendored
59
vendor/k8s.io/kubernetes/pkg/apis/core/helper/helpers.go
generated
vendored
|
|
@ -254,46 +254,18 @@ func IsIntegerResourceName(str string) bool {
|
|||
return integerResources.Has(str) || IsExtendedResourceName(core.ResourceName(str))
|
||||
}
|
||||
|
||||
// Extended and HugePages resources
|
||||
func IsScalarResourceName(name core.ResourceName) bool {
|
||||
return IsExtendedResourceName(name) || IsHugePageResourceName(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 *core.Service) bool {
|
||||
return service.Spec.ClusterIP != core.ClusterIPNone && service.Spec.ClusterIP != ""
|
||||
}
|
||||
|
||||
// this function aims to check if the service's cluster IP is requested or not
|
||||
func IsServiceIPRequested(service *core.Service) bool {
|
||||
// ExternalName services are CNAME aliases to external ones. Ignore the IP.
|
||||
if service.Spec.Type == core.ServiceTypeExternalName {
|
||||
return false
|
||||
}
|
||||
return service.Spec.ClusterIP == ""
|
||||
}
|
||||
|
||||
var standardFinalizers = sets.NewString(
|
||||
string(core.FinalizerKubernetes),
|
||||
metav1.FinalizerOrphanDependents,
|
||||
metav1.FinalizerDeleteDependents,
|
||||
)
|
||||
|
||||
// HasAnnotation returns a bool if passed in annotation exists
|
||||
func HasAnnotation(obj core.ObjectMeta, ann string) bool {
|
||||
_, found := obj.Annotations[ann]
|
||||
return found
|
||||
}
|
||||
|
||||
// SetMetaDataAnnotation sets the annotation and value
|
||||
func SetMetaDataAnnotation(obj *core.ObjectMeta, ann string, value string) {
|
||||
if obj.Annotations == nil {
|
||||
obj.Annotations = make(map[string]string)
|
||||
}
|
||||
obj.Annotations[ann] = value
|
||||
}
|
||||
|
||||
func IsStandardFinalizerName(str string) bool {
|
||||
return standardFinalizers.Has(str)
|
||||
}
|
||||
|
|
@ -482,37 +454,6 @@ func AddOrUpdateTolerationInPod(pod *core.Pod, toleration *core.Toleration) bool
|
|||
return true
|
||||
}
|
||||
|
||||
// TolerationToleratesTaint checks if the toleration tolerates the taint.
|
||||
func TolerationToleratesTaint(toleration *core.Toleration, taint *core.Taint) bool {
|
||||
if len(toleration.Effect) != 0 && toleration.Effect != taint.Effect {
|
||||
return false
|
||||
}
|
||||
|
||||
if toleration.Key != taint.Key {
|
||||
return false
|
||||
}
|
||||
// TODO: Use proper defaulting when Toleration becomes a field of PodSpec
|
||||
if (len(toleration.Operator) == 0 || toleration.Operator == core.TolerationOpEqual) && toleration.Value == taint.Value {
|
||||
return true
|
||||
}
|
||||
if toleration.Operator == core.TolerationOpExists {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TaintToleratedByTolerations checks if taint is tolerated by any of the tolerations.
|
||||
func TaintToleratedByTolerations(taint *core.Taint, tolerations []core.Toleration) bool {
|
||||
tolerated := false
|
||||
for i := range tolerations {
|
||||
if TolerationToleratesTaint(&tolerations[i], taint) {
|
||||
tolerated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return tolerated
|
||||
}
|
||||
|
||||
// GetTaintsFromNodeAnnotations gets the json serialized taints data from Pod.Annotations
|
||||
// and converts it to the []Taint type in core.
|
||||
func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]core.Taint, error) {
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/apis/core/install/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/apis/core/install/BUILD
generated
vendored
|
|
@ -24,8 +24,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["install_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/apis/core/install",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/apis/core/pods/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/apis/core/pods/BUILD
generated
vendored
|
|
@ -11,8 +11,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["helpers_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/apis/core/pods",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
|||
136
vendor/k8s.io/kubernetes/pkg/apis/core/toleration_test.go
generated
vendored
Normal file
136
vendor/k8s.io/kubernetes/pkg/apis/core/toleration_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
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 core
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestMatchToleration(t *testing.T) {
|
||||
|
||||
tolerationSeconds := int64(5)
|
||||
tolerationToMatchSeconds := int64(3)
|
||||
testCases := []struct {
|
||||
description string
|
||||
toleration *Toleration
|
||||
tolerationToMatch *Toleration
|
||||
expectMatch bool
|
||||
}{
|
||||
{
|
||||
description: "two taints with the same key,operator,value,effect should match",
|
||||
toleration: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
tolerationToMatch: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: true,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different key cannot match",
|
||||
toleration: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
tolerationToMatch: &Toleration{
|
||||
Key: "different-key",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different operator cannot match",
|
||||
toleration: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
tolerationToMatch: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "different-operator",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different value cannot match",
|
||||
toleration: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
tolerationToMatch: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "different-value",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different effect cannot match",
|
||||
toleration: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
tolerationToMatch: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectPreferNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different tolerationSeconds should match",
|
||||
toleration: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
TolerationSeconds: &tolerationSeconds,
|
||||
},
|
||||
tolerationToMatch: &Toleration{
|
||||
Key: "foo",
|
||||
Operator: "Exists",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
TolerationSeconds: &tolerationToMatchSeconds,
|
||||
},
|
||||
expectMatch: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
if actual := tc.toleration.MatchToleration(tc.tolerationToMatch); actual != tc.expectMatch {
|
||||
t.Errorf("[%s] expect: %v , got: %v", tc.description, tc.expectMatch, !tc.expectMatch)
|
||||
}
|
||||
}
|
||||
}
|
||||
30
vendor/k8s.io/kubernetes/pkg/apis/core/types.go
generated
vendored
30
vendor/k8s.io/kubernetes/pkg/apis/core/types.go
generated
vendored
|
|
@ -354,7 +354,7 @@ type PersistentVolumeSource struct {
|
|||
// FlexVolume represents a generic volume resource that is
|
||||
// provisioned/attached using an exec based plugin.
|
||||
// +optional
|
||||
FlexVolume *FlexVolumeSource
|
||||
FlexVolume *FlexPersistentVolumeSource
|
||||
// Cinder represents a cinder volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
Cinder *CinderVolumeSource
|
||||
|
|
@ -867,6 +867,32 @@ type FCVolumeSource struct {
|
|||
WWIDs []string
|
||||
}
|
||||
|
||||
// FlexPersistentVolumeSource represents a generic persistent volume resource that is
|
||||
// provisioned/attached using an exec based plugin.
|
||||
type FlexPersistentVolumeSource struct {
|
||||
// Driver is the name of the driver to use for this volume.
|
||||
Driver string
|
||||
// Filesystem type to mount.
|
||||
// Must be a filesystem type supported by the host operating system.
|
||||
// Ex. "ext4", "xfs", "ntfs". The default filesystem depends on FlexVolume script.
|
||||
// +optional
|
||||
FSType string
|
||||
// Optional: SecretRef is reference to the secret object containing
|
||||
// sensitive information to pass to the plugin scripts. This may be
|
||||
// empty if no secret object is specified. If the secret object
|
||||
// contains more than one secret, all secrets are passed to the plugin
|
||||
// scripts.
|
||||
// +optional
|
||||
SecretRef *SecretReference
|
||||
// Optional: Defaults to false (read/write). ReadOnly here will force
|
||||
// the ReadOnly setting in VolumeMounts.
|
||||
// +optional
|
||||
ReadOnly bool
|
||||
// Optional: Extra driver options if any.
|
||||
// +optional
|
||||
Options map[string]string
|
||||
}
|
||||
|
||||
// FlexVolume represents a generic volume resource that is
|
||||
// provisioned/attached using an exec based plugin.
|
||||
type FlexVolumeSource struct {
|
||||
|
|
@ -2338,13 +2364,13 @@ type PodAffinityTerm struct {
|
|||
LabelSelector *metav1.LabelSelector
|
||||
// namespaces specifies which namespaces the labelSelector applies to (matches against);
|
||||
// null or empty list means "this pod's namespace"
|
||||
// +optional
|
||||
Namespaces []string
|
||||
// This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching
|
||||
// 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.
|
||||
// Empty topologyKey is not allowed.
|
||||
// +optional
|
||||
TopologyKey string
|
||||
}
|
||||
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/BUILD
generated
vendored
|
|
@ -9,8 +9,8 @@ load(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["helpers_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/apis/core/v1/helper",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
|
|
|
|||
23
vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers.go
generated
vendored
23
vendor/k8s.io/kubernetes/pkg/apis/core/v1/helper/helpers.go
generated
vendored
|
|
@ -89,15 +89,6 @@ func IsServiceIPSet(service *v1.Service) bool {
|
|||
return service.Spec.ClusterIP != v1.ClusterIPNone && service.Spec.ClusterIP != ""
|
||||
}
|
||||
|
||||
// this function aims to check if the service's cluster IP is requested or not
|
||||
func IsServiceIPRequested(service *v1.Service) bool {
|
||||
// ExternalName services are CNAME aliases to external ones. Ignore the IP.
|
||||
if service.Spec.Type == v1.ServiceTypeExternalName {
|
||||
return false
|
||||
}
|
||||
return service.Spec.ClusterIP == ""
|
||||
}
|
||||
|
||||
// AddToNodeAddresses appends the NodeAddresses to the passed-by-pointer slice,
|
||||
// only if they do not already exist
|
||||
func AddToNodeAddresses(addresses *[]v1.NodeAddress, addAddresses ...v1.NodeAddress) {
|
||||
|
|
@ -416,20 +407,6 @@ func GetPersistentVolumeClaimClass(claim *v1.PersistentVolumeClaim) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimHasClass returns true if given claim has set StorageClassName field.
|
||||
func PersistentVolumeClaimHasClass(claim *v1.PersistentVolumeClaim) bool {
|
||||
// Use beta annotation first
|
||||
if _, found := claim.Annotations[v1.BetaStorageClassAnnotation]; found {
|
||||
return true
|
||||
}
|
||||
|
||||
if claim.Spec.StorageClassName != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// GetStorageNodeAffinityFromAnnotation gets the json serialized data from PersistentVolume.Annotations
|
||||
// and converts it to the NodeAffinity type in api.
|
||||
// TODO: update when storage node affinity graduates to beta
|
||||
|
|
|
|||
37
vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go
generated
vendored
37
vendor/k8s.io/kubernetes/pkg/apis/core/v1/zz_generated.conversion.go
generated
vendored
|
|
@ -21,6 +21,8 @@ limitations under the License.
|
|||
package v1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
resource "k8s.io/apimachinery/pkg/api/resource"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
@ -28,7 +30,6 @@ import (
|
|||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
core "k8s.io/kubernetes/pkg/apis/core"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -141,6 +142,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
|||
Convert_core_ExecAction_To_v1_ExecAction,
|
||||
Convert_v1_FCVolumeSource_To_core_FCVolumeSource,
|
||||
Convert_core_FCVolumeSource_To_v1_FCVolumeSource,
|
||||
Convert_v1_FlexPersistentVolumeSource_To_core_FlexPersistentVolumeSource,
|
||||
Convert_core_FlexPersistentVolumeSource_To_v1_FlexPersistentVolumeSource,
|
||||
Convert_v1_FlexVolumeSource_To_core_FlexVolumeSource,
|
||||
Convert_core_FlexVolumeSource_To_v1_FlexVolumeSource,
|
||||
Convert_v1_FlockerVolumeSource_To_core_FlockerVolumeSource,
|
||||
|
|
@ -1758,6 +1761,34 @@ func Convert_core_FCVolumeSource_To_v1_FCVolumeSource(in *core.FCVolumeSource, o
|
|||
return autoConvert_core_FCVolumeSource_To_v1_FCVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_FlexPersistentVolumeSource_To_core_FlexPersistentVolumeSource(in *v1.FlexPersistentVolumeSource, out *core.FlexPersistentVolumeSource, s conversion.Scope) error {
|
||||
out.Driver = in.Driver
|
||||
out.FSType = in.FSType
|
||||
out.SecretRef = (*core.SecretReference)(unsafe.Pointer(in.SecretRef))
|
||||
out.ReadOnly = in.ReadOnly
|
||||
out.Options = *(*map[string]string)(unsafe.Pointer(&in.Options))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_FlexPersistentVolumeSource_To_core_FlexPersistentVolumeSource is an autogenerated conversion function.
|
||||
func Convert_v1_FlexPersistentVolumeSource_To_core_FlexPersistentVolumeSource(in *v1.FlexPersistentVolumeSource, out *core.FlexPersistentVolumeSource, s conversion.Scope) error {
|
||||
return autoConvert_v1_FlexPersistentVolumeSource_To_core_FlexPersistentVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_core_FlexPersistentVolumeSource_To_v1_FlexPersistentVolumeSource(in *core.FlexPersistentVolumeSource, out *v1.FlexPersistentVolumeSource, s conversion.Scope) error {
|
||||
out.Driver = in.Driver
|
||||
out.FSType = in.FSType
|
||||
out.SecretRef = (*v1.SecretReference)(unsafe.Pointer(in.SecretRef))
|
||||
out.ReadOnly = in.ReadOnly
|
||||
out.Options = *(*map[string]string)(unsafe.Pointer(&in.Options))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_core_FlexPersistentVolumeSource_To_v1_FlexPersistentVolumeSource is an autogenerated conversion function.
|
||||
func Convert_core_FlexPersistentVolumeSource_To_v1_FlexPersistentVolumeSource(in *core.FlexPersistentVolumeSource, out *v1.FlexPersistentVolumeSource, s conversion.Scope) error {
|
||||
return autoConvert_core_FlexPersistentVolumeSource_To_v1_FlexPersistentVolumeSource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_FlexVolumeSource_To_core_FlexVolumeSource(in *v1.FlexVolumeSource, out *core.FlexVolumeSource, s conversion.Scope) error {
|
||||
out.Driver = in.Driver
|
||||
out.FSType = in.FSType
|
||||
|
|
@ -3250,7 +3281,7 @@ func autoConvert_v1_PersistentVolumeSource_To_core_PersistentVolumeSource(in *v1
|
|||
out.CephFS = (*core.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS))
|
||||
out.FC = (*core.FCVolumeSource)(unsafe.Pointer(in.FC))
|
||||
out.Flocker = (*core.FlockerVolumeSource)(unsafe.Pointer(in.Flocker))
|
||||
out.FlexVolume = (*core.FlexVolumeSource)(unsafe.Pointer(in.FlexVolume))
|
||||
out.FlexVolume = (*core.FlexPersistentVolumeSource)(unsafe.Pointer(in.FlexVolume))
|
||||
out.AzureFile = (*core.AzureFilePersistentVolumeSource)(unsafe.Pointer(in.AzureFile))
|
||||
out.VsphereVolume = (*core.VsphereVirtualDiskVolumeSource)(unsafe.Pointer(in.VsphereVolume))
|
||||
out.Quobyte = (*core.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte))
|
||||
|
|
@ -3278,7 +3309,7 @@ func autoConvert_core_PersistentVolumeSource_To_v1_PersistentVolumeSource(in *co
|
|||
out.RBD = (*v1.RBDPersistentVolumeSource)(unsafe.Pointer(in.RBD))
|
||||
out.Quobyte = (*v1.QuobyteVolumeSource)(unsafe.Pointer(in.Quobyte))
|
||||
out.ISCSI = (*v1.ISCSIPersistentVolumeSource)(unsafe.Pointer(in.ISCSI))
|
||||
out.FlexVolume = (*v1.FlexVolumeSource)(unsafe.Pointer(in.FlexVolume))
|
||||
out.FlexVolume = (*v1.FlexPersistentVolumeSource)(unsafe.Pointer(in.FlexVolume))
|
||||
out.Cinder = (*v1.CinderVolumeSource)(unsafe.Pointer(in.Cinder))
|
||||
out.CephFS = (*v1.CephFSPersistentVolumeSource)(unsafe.Pointer(in.CephFS))
|
||||
out.FC = (*v1.FCVolumeSource)(unsafe.Pointer(in.FC))
|
||||
|
|
|
|||
3
vendor/k8s.io/kubernetes/pkg/apis/core/validation/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/apis/core/validation/BUILD
generated
vendored
|
|
@ -24,6 +24,7 @@ go_library(
|
|||
"//pkg/capabilities:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/fieldpath:go_default_library",
|
||||
"//pkg/master/ports:go_default_library",
|
||||
"//pkg/security/apparmor:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
|
|
@ -50,8 +51,8 @@ go_test(
|
|||
"events_test.go",
|
||||
"validation_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/apis/core/validation",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
|
|
|
|||
128
vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation.go
generated
vendored
128
vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation.go
generated
vendored
|
|
@ -51,6 +51,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/capabilities"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/fieldpath"
|
||||
"k8s.io/kubernetes/pkg/master/ports"
|
||||
"k8s.io/kubernetes/pkg/security/apparmor"
|
||||
)
|
||||
|
||||
|
|
@ -212,15 +213,6 @@ func ValidateOwnerReferences(ownerReferences []metav1.OwnerReference, fldPath *f
|
|||
// value that were not valid. Otherwise this returns an empty list or nil.
|
||||
type ValidateNameFunc apimachineryvalidation.ValidateNameFunc
|
||||
|
||||
// maskTrailingDash replaces the final character of a string with a subdomain safe
|
||||
// value if is a dash.
|
||||
func maskTrailingDash(name string) string {
|
||||
if strings.HasSuffix(name, "-") {
|
||||
return name[:len(name)-2] + "a"
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// ValidatePodName can be used to check whether the given pod name is valid.
|
||||
// Prefix indicates this name will be used as part of generation, in which case
|
||||
// trailing dashes are allowed.
|
||||
|
|
@ -1257,6 +1249,27 @@ func validateFlexVolumeSource(fv *core.FlexVolumeSource, fldPath *field.Path) fi
|
|||
return allErrs
|
||||
}
|
||||
|
||||
func validateFlexPersistentVolumeSource(fv *core.FlexPersistentVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(fv.Driver) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("driver"), ""))
|
||||
}
|
||||
|
||||
// Make sure user-specified options don't use kubernetes namespaces
|
||||
for k := range fv.Options {
|
||||
namespace := k
|
||||
if parts := strings.SplitN(k, "/", 2); len(parts) == 2 {
|
||||
namespace = parts[0]
|
||||
}
|
||||
normalized := "." + strings.ToLower(namespace)
|
||||
if strings.HasSuffix(normalized, ".kubernetes.io") || strings.HasSuffix(normalized, ".k8s.io") {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("options").Key(k), k, "kubernetes.io and k8s.io namespaces are reserved"))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateAzureFile(azure *core.AzureFileVolumeSource, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if azure.SecretName == "" {
|
||||
|
|
@ -1588,7 +1601,7 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList {
|
|||
}
|
||||
if pv.Spec.FlexVolume != nil {
|
||||
numVolumes++
|
||||
allErrs = append(allErrs, validateFlexVolumeSource(pv.Spec.FlexVolume, specPath.Child("flexVolume"))...)
|
||||
allErrs = append(allErrs, validateFlexPersistentVolumeSource(pv.Spec.FlexVolume, specPath.Child("flexVolume"))...)
|
||||
}
|
||||
if pv.Spec.AzureFile != nil {
|
||||
if numVolumes > 0 {
|
||||
|
|
@ -1773,27 +1786,26 @@ func ValidatePersistentVolumeClaimSpec(spec *core.PersistentVolumeClaimSpec, fld
|
|||
func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *core.PersistentVolumeClaim) field.ErrorList {
|
||||
allErrs := ValidateObjectMetaUpdate(&newPvc.ObjectMeta, &oldPvc.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidatePersistentVolumeClaim(newPvc)...)
|
||||
newPvcClone := newPvc.DeepCopy()
|
||||
oldPvcClone := oldPvc.DeepCopy()
|
||||
|
||||
// PVController needs to update PVC.Spec w/ VolumeName.
|
||||
// Claims are immutable in order to enforce quota, range limits, etc. without gaming the system.
|
||||
if len(oldPvc.Spec.VolumeName) == 0 {
|
||||
// volumeName changes are allowed once.
|
||||
// Reset back to empty string after equality check
|
||||
oldPvc.Spec.VolumeName = newPvc.Spec.VolumeName
|
||||
defer func() { oldPvc.Spec.VolumeName = "" }()
|
||||
oldPvcClone.Spec.VolumeName = newPvcClone.Spec.VolumeName
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
||||
newPVCSpecCopy := newPvc.Spec.DeepCopy()
|
||||
|
||||
// lets make sure storage values are same.
|
||||
if newPvc.Status.Phase == core.ClaimBound && newPVCSpecCopy.Resources.Requests != nil {
|
||||
newPVCSpecCopy.Resources.Requests["storage"] = oldPvc.Spec.Resources.Requests["storage"]
|
||||
if newPvc.Status.Phase == core.ClaimBound && newPvcClone.Spec.Resources.Requests != nil {
|
||||
newPvcClone.Spec.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) {
|
||||
if !apiequality.Semantic.DeepEqual(newPvcClone.Spec, oldPvcClone.Spec) {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "is immutable after creation except resources.requests for bound claims"))
|
||||
}
|
||||
if newSize.Cmp(oldSize) < 0 {
|
||||
|
|
@ -1803,7 +1815,7 @@ func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *core.PersistentVolumeCl
|
|||
} 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) {
|
||||
if !apiequality.Semantic.DeepEqual(newPvcClone.Spec, oldPvcClone.Spec) {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "field is immutable after creation"))
|
||||
}
|
||||
}
|
||||
|
|
@ -1815,8 +1827,6 @@ func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *core.PersistentVolumeCl
|
|||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
allErrs = append(allErrs, ValidateImmutableField(newPvc.Spec.VolumeMode, oldPvc.Spec.VolumeMode, field.NewPath("volumeMode"))...)
|
||||
}
|
||||
|
||||
newPvc.Status = oldPvc.Status
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
|
@ -3322,6 +3332,31 @@ func ValidatePodUpdate(newPod, oldPod *core.Pod) field.ErrorList {
|
|||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateContainerStateTransition test to if any illegal container state transitions are being attempted
|
||||
func ValidateContainerStateTransition(newStatuses, oldStatuses []core.ContainerStatus, fldpath *field.Path, restartPolicy core.RestartPolicy) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
// If we should always restart, containers are allowed to leave the terminated state
|
||||
if restartPolicy == core.RestartPolicyAlways {
|
||||
return allErrs
|
||||
}
|
||||
for i, oldStatus := range oldStatuses {
|
||||
// Skip any container that is not terminated
|
||||
if oldStatus.State.Terminated == nil {
|
||||
continue
|
||||
}
|
||||
// Skip any container that failed but is allowed to restart
|
||||
if oldStatus.State.Terminated.ExitCode != 0 && restartPolicy == core.RestartPolicyOnFailure {
|
||||
continue
|
||||
}
|
||||
for _, newStatus := range newStatuses {
|
||||
if oldStatus.Name == newStatus.Name && newStatus.State.Terminated == nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldpath.Index(i).Child("state"), "may not be transitioned to non-terminated state"))
|
||||
}
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidatePodStatusUpdate tests to see if the update is legal for an end user to make. newPod is updated with fields
|
||||
// that cannot be changed.
|
||||
func ValidatePodStatusUpdate(newPod, oldPod *core.Pod) field.ErrorList {
|
||||
|
|
@ -3329,10 +3364,16 @@ func ValidatePodStatusUpdate(newPod, oldPod *core.Pod) field.ErrorList {
|
|||
allErrs := ValidateObjectMetaUpdate(&newPod.ObjectMeta, &oldPod.ObjectMeta, fldPath)
|
||||
allErrs = append(allErrs, ValidatePodSpecificAnnotationUpdates(newPod, oldPod, fldPath.Child("annotations"))...)
|
||||
|
||||
fldPath = field.NewPath("status")
|
||||
if newPod.Spec.NodeName != oldPod.Spec.NodeName {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("status", "nodeName"), "may not be changed directly"))
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("nodeName"), "may not be changed directly"))
|
||||
}
|
||||
|
||||
// If pod should not restart, make sure the status update does not transition
|
||||
// any terminated containers to a non-terminated state.
|
||||
allErrs = append(allErrs, ValidateContainerStateTransition(newPod.Status.ContainerStatuses, oldPod.Status.ContainerStatuses, fldPath.Child("containerStatuses"), oldPod.Spec.RestartPolicy)...)
|
||||
allErrs = append(allErrs, ValidateContainerStateTransition(newPod.Status.InitContainerStatuses, oldPod.Status.InitContainerStatuses, fldPath.Child("initContainerStatuses"), oldPod.Spec.RestartPolicy)...)
|
||||
|
||||
// For status update we ignore changes to pod spec.
|
||||
newPod.Spec = oldPod.Spec
|
||||
|
||||
|
|
@ -3390,9 +3431,9 @@ func ValidateService(service *core.Service) field.ErrorList {
|
|||
// This is a workaround for broken cloud environments that
|
||||
// over-open firewalls. Hopefully it can go away when more clouds
|
||||
// understand containers better.
|
||||
if port.Port == 10250 {
|
||||
if port.Port == ports.KubeletPort {
|
||||
portPath := specPath.Child("ports").Index(ix)
|
||||
allErrs = append(allErrs, field.Invalid(portPath, port.Port, "may not expose port 10250 externally since it is used by kubelet"))
|
||||
allErrs = append(allErrs, field.Invalid(portPath, port.Port, fmt.Sprintf("may not expose port %v externally since it is used by kubelet", ports.KubeletPort)))
|
||||
}
|
||||
}
|
||||
if service.Spec.ClusterIP == "None" {
|
||||
|
|
@ -3404,7 +3445,7 @@ func ValidateService(service *core.Service) field.ErrorList {
|
|||
}
|
||||
case core.ServiceTypeExternalName:
|
||||
if service.Spec.ClusterIP != "" {
|
||||
allErrs = append(allErrs, field.Invalid(specPath.Child("clusterIP"), service.Spec.ClusterIP, "must be empty for ExternalName services"))
|
||||
allErrs = append(allErrs, field.Forbidden(specPath.Child("clusterIP"), "must be empty for ExternalName services"))
|
||||
}
|
||||
if len(service.Spec.ExternalName) > 0 {
|
||||
allErrs = append(allErrs, ValidateDNS1123Subdomain(service.Spec.ExternalName, specPath.Child("externalName"))...)
|
||||
|
|
@ -3483,7 +3524,7 @@ func ValidateService(service *core.Service) field.ErrorList {
|
|||
for i := range service.Spec.Ports {
|
||||
portPath := portsPath.Index(i)
|
||||
if service.Spec.Ports[i].NodePort != 0 {
|
||||
allErrs = append(allErrs, field.Invalid(portPath.Child("nodePort"), service.Spec.Ports[i].NodePort, "may not be used when `type` is 'ClusterIP'"))
|
||||
allErrs = append(allErrs, field.Forbidden(portPath.Child("nodePort"), "may not be used when `type` is 'ClusterIP'"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3533,7 +3574,7 @@ func ValidateService(service *core.Service) field.ErrorList {
|
|||
val = service.Annotations[core.AnnotationLoadBalancerSourceRangesKey]
|
||||
}
|
||||
if service.Spec.Type != core.ServiceTypeLoadBalancer {
|
||||
allErrs = append(allErrs, field.Invalid(fieldPath, "", "may only be used when `type` is 'LoadBalancer'"))
|
||||
allErrs = append(allErrs, field.Forbidden(fieldPath, "may only be used when `type` is 'LoadBalancer'"))
|
||||
}
|
||||
_, err := apiservice.GetLoadBalancerSourceRanges(service)
|
||||
if err != nil {
|
||||
|
|
@ -4340,7 +4381,13 @@ func ValidateResourceRequirements(requirements *core.ResourceRequirements, fldPa
|
|||
allErrs := field.ErrorList{}
|
||||
limPath := fldPath.Child("limits")
|
||||
reqPath := fldPath.Child("requests")
|
||||
limContainsCpuOrMemory := false
|
||||
reqContainsCpuOrMemory := false
|
||||
limContainsHugePages := false
|
||||
reqContainsHugePages := false
|
||||
supportedQoSComputeResources := sets.NewString(string(core.ResourceCPU), string(core.ResourceMemory))
|
||||
for resourceName, quantity := range requirements.Limits {
|
||||
|
||||
fldPath := limPath.Key(string(resourceName))
|
||||
// Validate resource name.
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...)
|
||||
|
|
@ -4351,10 +4398,17 @@ func ValidateResourceRequirements(requirements *core.ResourceRequirements, fldPa
|
|||
if resourceName == core.ResourceEphemeralStorage && !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
|
||||
allErrs = append(allErrs, field.Forbidden(limPath, "ResourceEphemeralStorage 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)))
|
||||
if helper.IsHugePageResourceName(resourceName) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.HugePages) {
|
||||
allErrs = append(allErrs, field.Forbidden(limPath, fmt.Sprintf("%s field disabled by feature-gate for ResourceRequirements", resourceName)))
|
||||
} else {
|
||||
limContainsHugePages = true
|
||||
}
|
||||
}
|
||||
|
||||
if supportedQoSComputeResources.Has(string(resourceName)) {
|
||||
limContainsCpuOrMemory = true
|
||||
}
|
||||
}
|
||||
for resourceName, quantity := range requirements.Requests {
|
||||
fldPath := reqPath.Key(string(resourceName))
|
||||
|
|
@ -4366,15 +4420,25 @@ func ValidateResourceRequirements(requirements *core.ResourceRequirements, fldPa
|
|||
// 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.
|
||||
// For non overcommitable resources, 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", resourceName)))
|
||||
} 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 == core.ResourceNvidiaGPU {
|
||||
allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s request", core.ResourceNvidiaGPU)))
|
||||
} else if !helper.IsOvercommitAllowed(resourceName) {
|
||||
allErrs = append(allErrs, field.Required(limPath, "Limit must be set for non overcommitable resources"))
|
||||
}
|
||||
if helper.IsHugePageResourceName(resourceName) {
|
||||
reqContainsHugePages = true
|
||||
}
|
||||
if supportedQoSComputeResources.Has(string(resourceName)) {
|
||||
reqContainsCpuOrMemory = true
|
||||
}
|
||||
|
||||
}
|
||||
if !limContainsCpuOrMemory && !reqContainsCpuOrMemory && (reqContainsHugePages || limContainsHugePages) {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath, fmt.Sprintf("HugePages require cpu or memory")))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
|
|
|
|||
71
vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation_test.go
generated
vendored
71
vendor/k8s.io/kubernetes/pkg/apis/core/validation/validation_test.go
generated
vendored
|
|
@ -469,7 +469,7 @@ func TestValidatePersistentVolumeSourceUpdate(t *testing.T) {
|
|||
validPvSourceNoUpdate := validVolume.DeepCopy()
|
||||
invalidPvSourceUpdateType := validVolume.DeepCopy()
|
||||
invalidPvSourceUpdateType.Spec.PersistentVolumeSource = core.PersistentVolumeSource{
|
||||
FlexVolume: &core.FlexVolumeSource{
|
||||
FlexVolume: &core.FlexPersistentVolumeSource{
|
||||
Driver: "kubernetes.io/blue",
|
||||
FSType: "ext4",
|
||||
},
|
||||
|
|
@ -3345,6 +3345,32 @@ func TestAlphaHugePagesIsolation(t *testing.T) {
|
|||
successCases := []core.Pod{
|
||||
{ // Basic fields.
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: "ns"},
|
||||
Spec: core.PodSpec{
|
||||
Containers: []core.Container{
|
||||
{
|
||||
Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File",
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
|
||||
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
|
||||
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
|
||||
},
|
||||
Limits: core.ResourceList{
|
||||
core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
|
||||
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
|
||||
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RestartPolicy: core.RestartPolicyAlways,
|
||||
DNSPolicy: core.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
}
|
||||
failureCases := []core.Pod{
|
||||
{ // Basic fields.
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "hugepages-requireCpuOrMemory", Namespace: "ns"},
|
||||
Spec: core.PodSpec{
|
||||
Containers: []core.Container{
|
||||
{
|
||||
|
|
@ -3363,8 +3389,6 @@ func TestAlphaHugePagesIsolation(t *testing.T) {
|
|||
DNSPolicy: core.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
}
|
||||
failureCases := []core.Pod{
|
||||
{ // Basic fields.
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "hugepages-shared", Namespace: "ns"},
|
||||
Spec: core.PodSpec{
|
||||
|
|
@ -3373,10 +3397,14 @@ func TestAlphaHugePagesIsolation(t *testing.T) {
|
|||
Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File",
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
|
||||
core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
|
||||
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
|
||||
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
|
||||
},
|
||||
Limits: core.ResourceList{
|
||||
core.ResourceName("hugepages-2Mi"): resource.MustParse("2Gi"),
|
||||
core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
|
||||
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
|
||||
core.ResourceName("hugepages-2Mi"): resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -3393,12 +3421,15 @@ func TestAlphaHugePagesIsolation(t *testing.T) {
|
|||
Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File",
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
|
||||
core.ResourceName("hugepages-1Gi"): resource.MustParse("2Gi"),
|
||||
core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
|
||||
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
|
||||
core.ResourceName("hugepages-1Gi"): resource.MustParse("2Gi"),
|
||||
},
|
||||
Limits: core.ResourceList{
|
||||
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
|
||||
core.ResourceName("hugepages-1Gi"): resource.MustParse("2Gi"),
|
||||
core.ResourceName(core.ResourceCPU): resource.MustParse("10"),
|
||||
core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
|
||||
core.ResourceName("hugepages-2Mi"): resource.MustParse("1Gi"),
|
||||
core.ResourceName("hugepages-1Gi"): resource.MustParse("2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -6848,6 +6879,28 @@ func TestValidatePod(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
"invalid extended resource requirement without limit": {
|
||||
expectedError: "Limit must be set",
|
||||
spec: core.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: "ns"},
|
||||
Spec: core.PodSpec{
|
||||
Containers: []core.Container{
|
||||
{
|
||||
Name: "invalid",
|
||||
Image: "image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName("example.com/a"): resource.MustParse("2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RestartPolicy: core.RestartPolicyAlways,
|
||||
DNSPolicy: core.DNSClusterFirst,
|
||||
},
|
||||
},
|
||||
},
|
||||
"invalid fractional extended resource in container request": {
|
||||
expectedError: "must be an integer",
|
||||
spec: core.Pod{
|
||||
|
|
|
|||
34
vendor/k8s.io/kubernetes/pkg/apis/core/zz_generated.deepcopy.go
generated
vendored
34
vendor/k8s.io/kubernetes/pkg/apis/core/zz_generated.deepcopy.go
generated
vendored
|
|
@ -1547,6 +1547,38 @@ func (in *FCVolumeSource) DeepCopy() *FCVolumeSource {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FlexPersistentVolumeSource) DeepCopyInto(out *FlexPersistentVolumeSource) {
|
||||
*out = *in
|
||||
if in.SecretRef != nil {
|
||||
in, out := &in.SecretRef, &out.SecretRef
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(SecretReference)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Options != nil {
|
||||
in, out := &in.Options, &out.Options
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexPersistentVolumeSource.
|
||||
func (in *FlexPersistentVolumeSource) DeepCopy() *FlexPersistentVolumeSource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FlexPersistentVolumeSource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FlexVolumeSource) DeepCopyInto(out *FlexVolumeSource) {
|
||||
*out = *in
|
||||
|
|
@ -3152,7 +3184,7 @@ func (in *PersistentVolumeSource) DeepCopyInto(out *PersistentVolumeSource) {
|
|||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(FlexVolumeSource)
|
||||
*out = new(FlexPersistentVolumeSource)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/apis/extensions/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/apis/extensions/BUILD
generated
vendored
|
|
@ -9,8 +9,8 @@ load(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["helpers_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/apis/extensions",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/capabilities/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/capabilities/BUILD
generated
vendored
|
|
@ -18,8 +18,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["capabilities_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/capabilities",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/cloudprovider/cloud.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/cloudprovider/cloud.go
generated
vendored
|
|
@ -44,8 +44,6 @@ type Interface interface {
|
|||
Routes() (Routes, bool)
|
||||
// ProviderName returns the cloud provider ID.
|
||||
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
|
||||
}
|
||||
|
|
|
|||
12
vendor/k8s.io/kubernetes/pkg/cloudprovider/plugins.go
generated
vendored
12
vendor/k8s.io/kubernetes/pkg/cloudprovider/plugins.go
generated
vendored
|
|
@ -60,18 +60,6 @@ func IsCloudProvider(name string) bool {
|
|||
return found
|
||||
}
|
||||
|
||||
// CloudProviders returns the name of all registered cloud providers in a
|
||||
// string slice
|
||||
func CloudProviders() []string {
|
||||
names := []string{}
|
||||
providersMutex.Lock()
|
||||
defer providersMutex.Unlock()
|
||||
for name := range providers {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// GetCloudProvider creates an instance of the named cloud provider, or nil if
|
||||
// the name is unknown. The error return is only used if the named provider
|
||||
// was known but failed to initialize. The config parameter specifies the
|
||||
|
|
|
|||
6
vendor/k8s.io/kubernetes/pkg/controller/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/controller/BUILD
generated
vendored
|
|
@ -12,8 +12,8 @@ go_test(
|
|||
"controller_ref_manager_test.go",
|
||||
"controller_utils_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/controller",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
|
|
@ -117,7 +117,8 @@ filegroup(
|
|||
"//pkg/controller/history:all-srcs",
|
||||
"//pkg/controller/job:all-srcs",
|
||||
"//pkg/controller/namespace:all-srcs",
|
||||
"//pkg/controller/node:all-srcs",
|
||||
"//pkg/controller/nodeipam:all-srcs",
|
||||
"//pkg/controller/nodelifecycle:all-srcs",
|
||||
"//pkg/controller/podautoscaler:all-srcs",
|
||||
"//pkg/controller/podgc:all-srcs",
|
||||
"//pkg/controller/replicaset:all-srcs",
|
||||
|
|
@ -129,6 +130,7 @@ filegroup(
|
|||
"//pkg/controller/statefulset:all-srcs",
|
||||
"//pkg/controller/testutil:all-srcs",
|
||||
"//pkg/controller/ttl:all-srcs",
|
||||
"//pkg/controller/util/node:all-srcs",
|
||||
"//pkg/controller/volume/attachdetach:all-srcs",
|
||||
"//pkg/controller/volume/events:all-srcs",
|
||||
"//pkg/controller/volume/expand:all-srcs",
|
||||
|
|
|
|||
10
vendor/k8s.io/kubernetes/pkg/features/kube_features.go
generated
vendored
10
vendor/k8s.io/kubernetes/pkg/features/kube_features.go
generated
vendored
|
|
@ -64,6 +64,8 @@ const (
|
|||
// owner: @vishh
|
||||
// alpha: v1.6
|
||||
//
|
||||
// This is deprecated and will be removed in v1.11. Use DevicePlugins instead.
|
||||
//
|
||||
// Enables support for GPUs as a schedulable resource.
|
||||
// Only Nvidia GPUs are supported as of v1.6.
|
||||
// Works only with Docker Container Runtime.
|
||||
|
|
@ -153,13 +155,13 @@ const (
|
|||
CPUManager utilfeature.Feature = "CPUManager"
|
||||
|
||||
// owner: @derekwaynecarr
|
||||
// alpha: v1.8
|
||||
// beta: v1.10
|
||||
//
|
||||
// Enable pods to consume pre-allocated huge pages of varying page sizes
|
||||
HugePages utilfeature.Feature = "HugePages"
|
||||
|
||||
// owner @brendandburns
|
||||
// alpha: v1.8
|
||||
// alpha: v1.9
|
||||
//
|
||||
// Enable nodes to exclude themselves from service load balancers
|
||||
ServiceNodeExclusion utilfeature.Feature = "ServiceNodeExclusion"
|
||||
|
|
@ -235,14 +237,14 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
|
|||
RotateKubeletClientCertificate: {Default: true, PreRelease: utilfeature.Beta},
|
||||
PersistentLocalVolumes: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
LocalStorageCapacityIsolation: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
HugePages: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
HugePages: {Default: true, PreRelease: utilfeature.Beta},
|
||||
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},
|
||||
CPUManager: {Default: true, PreRelease: utilfeature.Beta},
|
||||
ServiceNodeExclusion: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
MountContainers: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
VolumeScheduling: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/fieldpath/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/fieldpath/BUILD
generated
vendored
|
|
@ -22,8 +22,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["fieldpath_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/fieldpath",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
|
|
|
|||
13
vendor/k8s.io/kubernetes/pkg/kubelet/BUILD
generated
vendored
13
vendor/k8s.io/kubernetes/pkg/kubelet/BUILD
generated
vendored
|
|
@ -36,7 +36,6 @@ go_library(
|
|||
"//pkg/apis/core/v1:go_default_library",
|
||||
"//pkg/apis/core/v1/helper:go_default_library",
|
||||
"//pkg/apis/core/v1/helper/qos:go_default_library",
|
||||
"//pkg/apis/core/v1/validation:go_default_library",
|
||||
"//pkg/capabilities:go_default_library",
|
||||
"//pkg/cloudprovider:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
|
|
@ -45,7 +44,6 @@ go_library(
|
|||
"//pkg/kubelet/apis/cri:go_default_library",
|
||||
"//pkg/kubelet/apis/cri/v1alpha1/runtime:go_default_library",
|
||||
"//pkg/kubelet/apis/kubeletconfig:go_default_library",
|
||||
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
|
||||
"//pkg/kubelet/cadvisor:go_default_library",
|
||||
"//pkg/kubelet/certificate:go_default_library",
|
||||
"//pkg/kubelet/cm:go_default_library",
|
||||
|
|
@ -89,6 +87,8 @@ go_library(
|
|||
"//pkg/kubelet/util/queue:go_default_library",
|
||||
"//pkg/kubelet/util/sliceutils:go_default_library",
|
||||
"//pkg/kubelet/volumemanager:go_default_library",
|
||||
"//pkg/scheduler/algorithm:go_default_library",
|
||||
"//pkg/scheduler/algorithm/predicates:go_default_library",
|
||||
"//pkg/security/apparmor:go_default_library",
|
||||
"//pkg/securitycontext:go_default_library",
|
||||
"//pkg/util/dbus:go_default_library",
|
||||
|
|
@ -105,8 +105,6 @@ go_library(
|
|||
"//pkg/volume/util/types:go_default_library",
|
||||
"//pkg/volume/util/volumehelper:go_default_library",
|
||||
"//pkg/volume/validation:go_default_library",
|
||||
"//plugin/pkg/scheduler/algorithm:go_default_library",
|
||||
"//plugin/pkg/scheduler/algorithm/predicates:go_default_library",
|
||||
"//third_party/forked/golang/expansion:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/golang/groupcache/lru:go_default_library",
|
||||
|
|
@ -126,7 +124,6 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/util/runtime: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/wait:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
|
|
@ -159,13 +156,13 @@ go_test(
|
|||
"reason_cache_test.go",
|
||||
"runonce_test.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:windows_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"kubelet_pods_windows_test.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core/install:go_default_library",
|
||||
|
|
@ -202,13 +199,13 @@ go_test(
|
|||
"//pkg/kubelet/util/queue:go_default_library",
|
||||
"//pkg/kubelet/util/sliceutils:go_default_library",
|
||||
"//pkg/kubelet/volumemanager:go_default_library",
|
||||
"//pkg/scheduler/schedulercache:go_default_library",
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/host_path:go_default_library",
|
||||
"//pkg/volume/testing:go_default_library",
|
||||
"//pkg/volume/util/volumehelper:go_default_library",
|
||||
"//plugin/pkg/scheduler/schedulercache:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/info/v2:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
|
|
|
|||
37
vendor/k8s.io/kubernetes/pkg/kubelet/container/BUILD
generated
vendored
37
vendor/k8s.io/kubernetes/pkg/kubelet/container/BUILD
generated
vendored
|
|
@ -8,7 +8,6 @@ go_library(
|
|||
"container_reference_manager.go",
|
||||
"helpers.go",
|
||||
"os.go",
|
||||
"pty_unsupported.go",
|
||||
"ref.go",
|
||||
"resize.go",
|
||||
"runtime.go",
|
||||
|
|
@ -16,9 +15,39 @@ go_library(
|
|||
"runtime_cache_fake.go",
|
||||
"sync_result.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"pty_linux.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"pty_unsupported.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/container",
|
||||
|
|
@ -43,7 +72,7 @@ go_library(
|
|||
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/github.com/kr/pty:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
|
|
@ -58,8 +87,8 @@ go_test(
|
|||
"ref_test.go",
|
||||
"sync_result_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/container",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core/install:go_default_library",
|
||||
|
|
|
|||
35
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go
generated
vendored
35
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet.go
generated
vendored
|
|
@ -57,7 +57,6 @@ import (
|
|||
"k8s.io/kubernetes/pkg/features"
|
||||
internalapi "k8s.io/kubernetes/pkg/kubelet/apis/cri"
|
||||
kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
|
||||
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cadvisor"
|
||||
kubeletcertificate "k8s.io/kubernetes/pkg/kubelet/certificate"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cm"
|
||||
|
|
@ -96,6 +95,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/kubelet/util/queue"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/sliceutils"
|
||||
"k8s.io/kubernetes/pkg/kubelet/volumemanager"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm/predicates"
|
||||
"k8s.io/kubernetes/pkg/security/apparmor"
|
||||
utildbus "k8s.io/kubernetes/pkg/util/dbus"
|
||||
kubeio "k8s.io/kubernetes/pkg/util/io"
|
||||
|
|
@ -104,7 +104,6 @@ import (
|
|||
nodeutil "k8s.io/kubernetes/pkg/util/node"
|
||||
"k8s.io/kubernetes/pkg/util/oom"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
|
|
@ -203,7 +202,6 @@ type Builder func(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
|||
registerNode bool,
|
||||
registerWithTaints []api.Taint,
|
||||
allowedUnsafeSysctls []string,
|
||||
containerized bool,
|
||||
remoteRuntimeEndpoint string,
|
||||
remoteImageEndpoint string,
|
||||
experimentalMounterPath string,
|
||||
|
|
@ -225,27 +223,7 @@ type Builder func(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
|||
// at runtime that are necessary for running the Kubelet. This is a temporary solution for grouping
|
||||
// these objects while we figure out a more comprehensive dependency injection story for the Kubelet.
|
||||
type Dependencies struct {
|
||||
// TODO(mtaufen): KubeletBuilder:
|
||||
// Mesos currently uses this as a hook to let them make their own call to
|
||||
// let them wrap the KubeletBootstrap that CreateAndInitKubelet returns with
|
||||
// their own KubeletBootstrap. It's a useful hook. I need to think about what
|
||||
// a nice home for it would be. There seems to be a trend, between this and
|
||||
// the Options fields below, of providing hooks where you can add extra functionality
|
||||
// to the Kubelet for your solution. Maybe we should centralize these sorts of things?
|
||||
Builder Builder
|
||||
|
||||
// TODO(mtaufen): ContainerRuntimeOptions and Options:
|
||||
// Arrays of functions that can do arbitrary things to the Kubelet and the Runtime
|
||||
// seem like a difficult path to trace when it's time to debug something.
|
||||
// I'm leaving these fields here for now, but there is likely an easier-to-follow
|
||||
// way to support their intended use cases. E.g. ContainerRuntimeOptions
|
||||
// is used by Mesos to set an environment variable in containers which has
|
||||
// some connection to their container GC. It seems that Mesos intends to use
|
||||
// Options to add additional node conditions that are updated as part of the
|
||||
// Kubelet lifecycle (see https://github.com/kubernetes/kubernetes/pull/21521).
|
||||
// We should think about providing more explicit ways of doing these things.
|
||||
ContainerRuntimeOptions []kubecontainer.Option
|
||||
Options []Option
|
||||
Options []Option
|
||||
|
||||
// Injected Dependencies
|
||||
Auth server.AuthInterface
|
||||
|
|
@ -344,7 +322,6 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
|||
registerNode bool,
|
||||
registerWithTaints []api.Taint,
|
||||
allowedUnsafeSysctls []string,
|
||||
containerized bool,
|
||||
remoteRuntimeEndpoint string,
|
||||
remoteImageEndpoint string,
|
||||
experimentalMounterPath string,
|
||||
|
|
@ -521,7 +498,6 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
|||
recorder: kubeDeps.Recorder,
|
||||
cadvisor: kubeDeps.CAdvisorInterface,
|
||||
cloud: kubeDeps.Cloud,
|
||||
autoDetectCloudProvider: (kubeletconfigv1alpha1.AutoDetectCloudProvider == cloudProvider),
|
||||
externalCloudProvider: cloudprovider.IsExternal(cloudProvider),
|
||||
providerID: providerID,
|
||||
nodeRef: nodeRef,
|
||||
|
|
@ -899,6 +875,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
|||
klet.softAdmitHandlers.AddPodAdmitHandler(lifecycle.NewNoNewPrivsAdmitHandler(klet.containerRuntime))
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.Accelerators) {
|
||||
if containerRuntime == kubetypes.DockerContainerRuntime {
|
||||
glog.Warningln("Accelerators feature is deprecated and will be removed in v1.11. Please use device plugins instead. They can be enabled using the DevicePlugins feature gate.")
|
||||
if klet.gpuManager, err = nvidia.NewNvidiaGPUManager(klet, kubeDeps.DockerClientConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -1032,11 +1009,7 @@ type Kubelet struct {
|
|||
|
||||
// Cloud provider interface.
|
||||
cloud cloudprovider.Interface
|
||||
// DEPRECATED: auto detecting cloud providers goes against the initiative
|
||||
// for out-of-tree cloud providers as we'll now depend on cAdvisor integrations
|
||||
// with cloud providers instead of in the core repo.
|
||||
// More details here: https://github.com/kubernetes/kubernetes/issues/50986
|
||||
autoDetectCloudProvider bool
|
||||
|
||||
// Indicates that the node initialization happens in an external cloud controller
|
||||
externalCloudProvider bool
|
||||
// Reference to this node.
|
||||
|
|
|
|||
5
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_getters.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_getters.go
generated
vendored
|
|
@ -179,9 +179,8 @@ func (kl *Kubelet) GetHostname() string {
|
|||
return kl.hostname
|
||||
}
|
||||
|
||||
// GetRuntime returns the current Runtime implementation in use by the kubelet. This func
|
||||
// is exported to simplify integration with third party kubelet extensions (e.g. kubernetes-mesos).
|
||||
func (kl *Kubelet) GetRuntime() kubecontainer.Runtime {
|
||||
// getRuntime returns the current Runtime implementation in use by the kubelet.
|
||||
func (kl *Kubelet) getRuntime() kubecontainer.Runtime {
|
||||
return kl.containerRuntime
|
||||
}
|
||||
|
||||
|
|
|
|||
8
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network.go
generated
vendored
8
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_network.go
generated
vendored
|
|
@ -65,7 +65,7 @@ func (nh *networkHost) GetKubeClient() clientset.Interface {
|
|||
}
|
||||
|
||||
func (nh *networkHost) GetRuntime() kubecontainer.Runtime {
|
||||
return nh.kubelet.GetRuntime()
|
||||
return nh.kubelet.getRuntime()
|
||||
}
|
||||
|
||||
func (nh *networkHost) SupportsLegacyFeatures() bool {
|
||||
|
|
@ -88,7 +88,7 @@ type criNetworkHost struct {
|
|||
// Any network plugin invoked by a cri must implement NamespaceGetter
|
||||
// to talk directly to the runtime instead.
|
||||
func (c *criNetworkHost) GetNetNS(containerID string) (string, error) {
|
||||
return c.kubelet.GetRuntime().GetNetNS(kubecontainer.ContainerID{Type: "", ID: containerID})
|
||||
return c.kubelet.getRuntime().GetNetNS(kubecontainer.ContainerID{Type: "", ID: containerID})
|
||||
}
|
||||
|
||||
// NoOpLegacyHost implements the network.LegacyHost interface for the remote
|
||||
|
|
@ -106,7 +106,7 @@ func (n *NoOpLegacyHost) GetKubeClient() clientset.Interface {
|
|||
return nil
|
||||
}
|
||||
|
||||
// GetRuntime always returns "nil" for 'NoOpLegacyHost'
|
||||
// getRuntime always returns "nil" for 'NoOpLegacyHost'
|
||||
func (n *NoOpLegacyHost) GetRuntime() kubecontainer.Runtime {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -188,7 +188,7 @@ func (kl *Kubelet) updatePodCIDR(cidr string) {
|
|||
|
||||
// kubelet -> generic runtime -> runtime shim -> network plugin
|
||||
// docker/rkt non-cri implementations have a passthrough UpdatePodCIDR
|
||||
if err := kl.GetRuntime().UpdatePodCIDR(cidr); err != nil {
|
||||
if err := kl.getRuntime().UpdatePodCIDR(cidr); err != nil {
|
||||
glog.Errorf("Failed to update pod CIDR: %v", err)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
17
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status.go
generated
vendored
17
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_node_status.go
generated
vendored
|
|
@ -42,10 +42,10 @@ import (
|
|||
"k8s.io/kubernetes/pkg/kubelet/events"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/sliceutils"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||
nodeutil "k8s.io/kubernetes/pkg/util/node"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumehelper"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -132,8 +132,7 @@ func (kl *Kubelet) tryRegisterWithAPIServer(node *v1.Node) bool {
|
|||
requiresUpdate := kl.reconcileCMADAnnotationWithExistingNode(node, existingNode)
|
||||
requiresUpdate = kl.updateDefaultLabels(node, existingNode) || requiresUpdate
|
||||
if requiresUpdate {
|
||||
if _, err := nodeutil.PatchNodeStatus(kl.kubeClient.CoreV1(), types.NodeName(kl.nodeName),
|
||||
originalNode, existingNode); err != nil {
|
||||
if _, _, err := nodeutil.PatchNodeStatus(kl.kubeClient.CoreV1(), types.NodeName(kl.nodeName), originalNode, existingNode); err != nil {
|
||||
glog.Errorf("Unable to reconcile node %q with API server: error updating node: %v", kl.nodeName, err)
|
||||
return false
|
||||
}
|
||||
|
|
@ -142,8 +141,7 @@ func (kl *Kubelet) tryRegisterWithAPIServer(node *v1.Node) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
glog.Errorf(
|
||||
"Previously node %q had externalID %q; now it is %q; will delete and recreate.",
|
||||
glog.Errorf("Previously node %q had externalID %q; now it is %q; will delete and recreate.",
|
||||
kl.nodeName, node.Spec.ExternalID, existingNode.Spec.ExternalID,
|
||||
)
|
||||
if err := kl.kubeClient.CoreV1().Nodes().Delete(node.Name, nil); err != nil {
|
||||
|
|
@ -347,13 +345,6 @@ func (kl *Kubelet) initialNode() (*v1.Node, error) {
|
|||
}
|
||||
} else {
|
||||
node.Spec.ExternalID = kl.hostname
|
||||
if kl.autoDetectCloudProvider {
|
||||
// If no cloud provider is defined - use the one detected by cadvisor
|
||||
info, err := kl.GetCachedMachineInfo()
|
||||
if err == nil {
|
||||
kl.updateCloudProviderFromMachineInfo(node, info)
|
||||
}
|
||||
}
|
||||
}
|
||||
kl.setNodeStatus(node)
|
||||
|
||||
|
|
@ -415,7 +406,7 @@ func (kl *Kubelet) tryUpdateNodeStatus(tryNumber int) error {
|
|||
|
||||
kl.setNodeStatus(node)
|
||||
// Patch the current status on the API server
|
||||
updatedNode, err := nodeutil.PatchNodeStatus(kl.heartbeatClient, types.NodeName(kl.nodeName), originalNode, node)
|
||||
updatedNode, _, err := nodeutil.PatchNodeStatus(kl.heartbeatClient, types.NodeName(kl.nodeName), originalNode, node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
28
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods.go
generated
vendored
28
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods.go
generated
vendored
|
|
@ -40,7 +40,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilvalidation "k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
|
|
@ -48,7 +47,6 @@ import (
|
|||
podshelper "k8s.io/kubernetes/pkg/apis/core/pods"
|
||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||
v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
|
||||
"k8s.io/kubernetes/pkg/apis/core/v1/validation"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/fieldpath"
|
||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||
|
|
@ -814,7 +812,7 @@ func (kl *Kubelet) killPod(pod *v1.Pod, runningPod *kubecontainer.Pod, status *k
|
|||
if runningPod != nil {
|
||||
p = *runningPod
|
||||
} else if status != nil {
|
||||
p = kubecontainer.ConvertPodStatusToRunningPod(kl.GetRuntime().Type(), status)
|
||||
p = kubecontainer.ConvertPodStatusToRunningPod(kl.getRuntime().Type(), status)
|
||||
} else {
|
||||
return fmt.Errorf("one of the two arguments must be non-nil: runningPod, status")
|
||||
}
|
||||
|
|
@ -1109,22 +1107,6 @@ func (kl *Kubelet) podKiller() {
|
|||
}
|
||||
}
|
||||
|
||||
// hasHostPortConflicts detects pods with conflicted host ports.
|
||||
func hasHostPortConflicts(pods []*v1.Pod) bool {
|
||||
ports := sets.String{}
|
||||
for _, pod := range pods {
|
||||
if errs := validation.AccumulateUniqueHostPorts(pod.Spec.Containers, &ports, field.NewPath("spec", "containers")); len(errs) > 0 {
|
||||
glog.Errorf("Pod %q: HostPort is already allocated, ignoring: %v", format.Pod(pod), errs)
|
||||
return true
|
||||
}
|
||||
if errs := validation.AccumulateUniqueHostPorts(pod.Spec.InitContainers, &ports, field.NewPath("spec", "initContainers")); len(errs) > 0 {
|
||||
glog.Errorf("Pod %q: HostPort is already allocated, ignoring: %v", format.Pod(pod), errs)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// validateContainerLogStatus returns the container ID for the desired container to retrieve logs for, based on the state
|
||||
// of the container. The previous flag will only return the logs for the last terminated container, otherwise, the current
|
||||
// running container is preferred over a previous termination. If info about the container is not available then a specific
|
||||
|
|
@ -1231,10 +1213,8 @@ func (kl *Kubelet) GetKubeletContainerLogs(podFullName, containerName string, lo
|
|||
return kl.containerRuntime.GetContainerLogs(pod, containerID, logOptions, stdout, stderr)
|
||||
}
|
||||
|
||||
// GetPhase returns the phase of a pod given its container info.
|
||||
// This func is exported to simplify integration with 3rd party kubelet
|
||||
// integrations like kubernetes-mesos.
|
||||
func GetPhase(spec *v1.PodSpec, info []v1.ContainerStatus) v1.PodPhase {
|
||||
// getPhase returns the phase of a pod given its container info.
|
||||
func getPhase(spec *v1.PodSpec, info []v1.ContainerStatus) v1.PodPhase {
|
||||
initialized := 0
|
||||
pendingInitialization := 0
|
||||
failedInitialization := 0
|
||||
|
|
@ -1364,7 +1344,7 @@ func (kl *Kubelet) generateAPIPodStatus(pod *v1.Pod, podStatus *kubecontainer.Po
|
|||
// Assume info is ready to process
|
||||
spec := &pod.Spec
|
||||
allStatus := append(append([]v1.ContainerStatus{}, s.ContainerStatuses...), s.InitContainerStatuses...)
|
||||
s.Phase = GetPhase(spec, allStatus)
|
||||
s.Phase = getPhase(spec, allStatus)
|
||||
kl.probeManager.UpdatePodStatus(pod.UID, s)
|
||||
s.Conditions = append(s.Conditions, status.GeneratePodInitializedCondition(spec, s.InitContainerStatuses, s.Phase))
|
||||
s.Conditions = append(s.Conditions, status.GeneratePodReadyCondition(spec, s.ContainerStatuses, s.Phase))
|
||||
|
|
|
|||
25
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_test.go
generated
vendored
25
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_pods_test.go
generated
vendored
|
|
@ -1845,7 +1845,7 @@ func TestPodPhaseWithRestartAlways(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
status := GetPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses)
|
||||
status := getPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses)
|
||||
assert.Equal(t, test.status, status, "[test %s]", test.test)
|
||||
}
|
||||
}
|
||||
|
|
@ -1945,7 +1945,7 @@ func TestPodPhaseWithRestartNever(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
status := GetPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses)
|
||||
status := getPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses)
|
||||
assert.Equal(t, test.status, status, "[test %s]", test.test)
|
||||
}
|
||||
}
|
||||
|
|
@ -2058,7 +2058,7 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
status := GetPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses)
|
||||
status := getPhase(&test.pod.Spec, test.pod.Status.ContainerStatuses)
|
||||
assert.Equal(t, test.status, status, "[test %s]", test.test)
|
||||
}
|
||||
}
|
||||
|
|
@ -2270,25 +2270,6 @@ func TestPortForward(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Tests that identify the host port conflicts are detected correctly.
|
||||
func TestGetHostPortConflicts(t *testing.T) {
|
||||
pods := []*v1.Pod{
|
||||
{Spec: v1.PodSpec{Containers: []v1.Container{{Ports: []v1.ContainerPort{{HostPort: 80}}}}}},
|
||||
{Spec: v1.PodSpec{Containers: []v1.Container{{Ports: []v1.ContainerPort{{HostPort: 81}}}}}},
|
||||
{Spec: v1.PodSpec{Containers: []v1.Container{{Ports: []v1.ContainerPort{{HostPort: 82}}}}}},
|
||||
{Spec: v1.PodSpec{Containers: []v1.Container{{Ports: []v1.ContainerPort{{HostPort: 83}}}}}},
|
||||
}
|
||||
// Pods should not cause any conflict.
|
||||
assert.False(t, hasHostPortConflicts(pods), "Should not have port conflicts")
|
||||
|
||||
expected := &v1.Pod{
|
||||
Spec: v1.PodSpec{Containers: []v1.Container{{Ports: []v1.ContainerPort{{HostPort: 81}}}}},
|
||||
}
|
||||
// The new pod should cause conflict and be reported.
|
||||
pods = append(pods, expected)
|
||||
assert.True(t, hasHostPortConflicts(pods), "Should have port conflicts")
|
||||
}
|
||||
|
||||
func TestHasHostMountPVC(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
pvError error
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_test.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/kubelet/kubelet_test.go
generated
vendored
|
|
@ -67,12 +67,12 @@ import (
|
|||
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/queue"
|
||||
kubeletvolume "k8s.io/kubernetes/pkg/kubelet/volumemanager"
|
||||
"k8s.io/kubernetes/pkg/scheduler/schedulercache"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
_ "k8s.io/kubernetes/pkg/volume/host_path"
|
||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumehelper"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/kubelet/types/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/kubelet/types/BUILD
generated
vendored
|
|
@ -31,8 +31,8 @@ go_test(
|
|||
"pod_update_test.go",
|
||||
"types_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/types",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
|
|
|
|||
5
vendor/k8s.io/kubernetes/pkg/kubelet/types/constants.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/kubelet/types/constants.go
generated
vendored
|
|
@ -24,4 +24,9 @@ const (
|
|||
DockerContainerRuntime = "docker"
|
||||
RktContainerRuntime = "rkt"
|
||||
RemoteContainerRuntime = "remote"
|
||||
|
||||
// User visible keys for managing node allocatable enforcement on the node.
|
||||
NodeAllocatableEnforcementKey = "pods"
|
||||
SystemReservedEnforcementKey = "system-reserved"
|
||||
KubeReservedEnforcementKey = "kube-reserved"
|
||||
)
|
||||
|
|
|
|||
41
vendor/k8s.io/kubernetes/pkg/kubelet/util/BUILD
generated
vendored
41
vendor/k8s.io/kubernetes/pkg/kubelet/util/BUILD
generated
vendored
|
|
@ -9,8 +9,8 @@ load(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/util",
|
||||
library = ":go_default_library",
|
||||
deps = ["//vendor/github.com/stretchr/testify/assert:go_default_library"],
|
||||
)
|
||||
|
||||
|
|
@ -19,15 +19,38 @@ go_library(
|
|||
srcs = [
|
||||
"doc.go",
|
||||
"util.go",
|
||||
"util_unsupported.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:darwin_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"util_unix.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"util_unix.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"util_unix.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"util_windows.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
|
|
@ -36,11 +59,15 @@ go_library(
|
|||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:darwin_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
],
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/kubelet/util/format/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/kubelet/util/format/BUILD
generated
vendored
|
|
@ -22,8 +22,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["resources_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/util/format",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/kubelet/util/sliceutils/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/kubelet/util/sliceutils/BUILD
generated
vendored
|
|
@ -32,8 +32,8 @@ filegroup(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["sliceutils_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/util/sliceutils",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/kubelet/container:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
|
|
|
|||
193
vendor/k8s.io/kubernetes/pkg/master/BUILD
generated
vendored
Normal file
193
vendor/k8s.io/kubernetes/pkg/master/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"client_ca_hook.go",
|
||||
"controller.go",
|
||||
"doc.go",
|
||||
"import_known_versions.go",
|
||||
"master.go",
|
||||
"services.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/master",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/admission/install:go_default_library",
|
||||
"//pkg/apis/admissionregistration/install:go_default_library",
|
||||
"//pkg/apis/apps/install:go_default_library",
|
||||
"//pkg/apis/authentication/install:go_default_library",
|
||||
"//pkg/apis/authorization/install:go_default_library",
|
||||
"//pkg/apis/autoscaling/install:go_default_library",
|
||||
"//pkg/apis/batch/install:go_default_library",
|
||||
"//pkg/apis/certificates/install:go_default_library",
|
||||
"//pkg/apis/componentconfig/install:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/install:go_default_library",
|
||||
"//pkg/apis/events/install:go_default_library",
|
||||
"//pkg/apis/extensions/install:go_default_library",
|
||||
"//pkg/apis/imagepolicy/install:go_default_library",
|
||||
"//pkg/apis/networking/install:go_default_library",
|
||||
"//pkg/apis/policy/install:go_default_library",
|
||||
"//pkg/apis/rbac/install:go_default_library",
|
||||
"//pkg/apis/scheduling/install:go_default_library",
|
||||
"//pkg/apis/settings/install:go_default_library",
|
||||
"//pkg/apis/storage/install:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/options:go_default_library",
|
||||
"//pkg/kubelet/client:go_default_library",
|
||||
"//pkg/master/reconcilers:go_default_library",
|
||||
"//pkg/master/tunneler:go_default_library",
|
||||
"//pkg/registry/admissionregistration/rest:go_default_library",
|
||||
"//pkg/registry/apps/rest:go_default_library",
|
||||
"//pkg/registry/authentication/rest:go_default_library",
|
||||
"//pkg/registry/authorization/rest:go_default_library",
|
||||
"//pkg/registry/autoscaling/rest:go_default_library",
|
||||
"//pkg/registry/batch/rest:go_default_library",
|
||||
"//pkg/registry/certificates/rest:go_default_library",
|
||||
"//pkg/registry/core/endpoint:go_default_library",
|
||||
"//pkg/registry/core/endpoint/storage:go_default_library",
|
||||
"//pkg/registry/core/rangeallocation:go_default_library",
|
||||
"//pkg/registry/core/rest:go_default_library",
|
||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||
"//pkg/registry/core/service/ipallocator/controller:go_default_library",
|
||||
"//pkg/registry/core/service/portallocator/controller:go_default_library",
|
||||
"//pkg/registry/events/rest:go_default_library",
|
||||
"//pkg/registry/extensions/rest:go_default_library",
|
||||
"//pkg/registry/networking/rest:go_default_library",
|
||||
"//pkg/registry/policy/rest:go_default_library",
|
||||
"//pkg/registry/rbac/rest:go_default_library",
|
||||
"//pkg/registry/scheduling/rest:go_default_library",
|
||||
"//pkg/registry/settings/rest:go_default_library",
|
||||
"//pkg/registry/storage/rest:go_default_library",
|
||||
"//pkg/routes:go_default_library",
|
||||
"//pkg/util/async:go_default_library",
|
||||
"//pkg/util/node:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
"//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/apps/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/apps/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/apps/v1beta2:go_default_library",
|
||||
"//vendor/k8s.io/api/authentication/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/authentication/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/authorization/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/authorization/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/autoscaling/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/batch/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/batch/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/certificates/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/events/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/networking/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/policy/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/rbac/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/storage/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/storage/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/endpoints/discovery:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"client_ca_hook_test.go",
|
||||
"controller_test.go",
|
||||
"import_known_versions_test.go",
|
||||
"master_openapi_test.go",
|
||||
"master_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/master",
|
||||
race = "off",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/apis/apps:go_default_library",
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/batch:go_default_library",
|
||||
"//pkg/apis/certificates:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/generated/openapi:go_default_library",
|
||||
"//pkg/kubelet/client:go_default_library",
|
||||
"//pkg/master/reconcilers:go_default_library",
|
||||
"//pkg/registry/certificates/rest:go_default_library",
|
||||
"//pkg/registry/core/rest:go_default_library",
|
||||
"//pkg/registry/registrytest:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
"//vendor/github.com/go-openapi/loads:go_default_library",
|
||||
"//vendor/github.com/go-openapi/spec:go_default_library",
|
||||
"//vendor/github.com/go-openapi/strfmt:go_default_library",
|
||||
"//vendor/github.com/go-openapi/validate:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/k8s.io/api/apps/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/autoscaling/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/batch/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/batch/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/certificates/v1beta1: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/apis/meta/v1: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/diff:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/version:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/options:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers: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/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/master/controller/crdregistration:all-srcs",
|
||||
"//pkg/master/ports:all-srcs",
|
||||
"//pkg/master/reconcilers:all-srcs",
|
||||
"//pkg/master/tunneler:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
41
vendor/k8s.io/kubernetes/pkg/master/OWNERS
generated
vendored
Normal file
41
vendor/k8s.io/kubernetes/pkg/master/OWNERS
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
approvers:
|
||||
- deads2k
|
||||
- derekwaynecarr
|
||||
- lavalamp
|
||||
- mikedanese
|
||||
- nikhiljindal
|
||||
- sttts
|
||||
- wojtek-t
|
||||
reviewers:
|
||||
- thockin
|
||||
- lavalamp
|
||||
- smarterclayton
|
||||
- wojtek-t
|
||||
- deads2k
|
||||
- yujuhong
|
||||
- derekwaynecarr
|
||||
- caesarxuchao
|
||||
- mikedanese
|
||||
- liggitt
|
||||
- nikhiljindal
|
||||
- gmarek
|
||||
- erictune
|
||||
- davidopp
|
||||
- pmorie
|
||||
- sttts
|
||||
- dchen1107
|
||||
- saad-ali
|
||||
- luxas
|
||||
- janetkuo
|
||||
- justinsb
|
||||
- roberthbailey
|
||||
- ncdc
|
||||
- tallclair
|
||||
- mwielgus
|
||||
- timothysc
|
||||
- soltysh
|
||||
- piosz
|
||||
- madhusudancs
|
||||
- hongchaodeng
|
||||
- jszczepkowski
|
||||
- enj
|
||||
143
vendor/k8s.io/kubernetes/pkg/master/client_ca_hook.go
generated
vendored
Normal file
143
vendor/k8s.io/kubernetes/pkg/master/client_ca_hook.go
generated
vendored
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
)
|
||||
|
||||
type ClientCARegistrationHook struct {
|
||||
ClientCA []byte
|
||||
|
||||
RequestHeaderUsernameHeaders []string
|
||||
RequestHeaderGroupHeaders []string
|
||||
RequestHeaderExtraHeaderPrefixes []string
|
||||
RequestHeaderCA []byte
|
||||
RequestHeaderAllowedNames []string
|
||||
}
|
||||
|
||||
func (h ClientCARegistrationHook) PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
|
||||
// no work to do
|
||||
if len(h.ClientCA) == 0 && len(h.RequestHeaderCA) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// initializing CAs is important so that aggregated API servers can come up with "normal" config.
|
||||
// We've seen lagging etcd before, so we want to retry this a few times before we decide to crashloop
|
||||
// the API server on it.
|
||||
err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) {
|
||||
// retry building the config since sometimes the server can be in an inbetween state which caused
|
||||
// some kind of auto detection failure as I recall from other post start hooks.
|
||||
// TODO see if this is still true and fix the RBAC one too if it isn't.
|
||||
client, err := coreclient.NewForConfig(hookContext.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return h.tryToWriteClientCAs(client)
|
||||
})
|
||||
|
||||
// if we're never able to make it through initialization, kill the API server
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to initialize client CA configmap: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// tryToWriteClientCAs is here for unit testing with a fake client. This is a wait.ConditionFunc so the bool
|
||||
// indicates if the condition was met. True when its finished, false when it should retry.
|
||||
func (h ClientCARegistrationHook) tryToWriteClientCAs(client coreclient.CoreInterface) (bool, error) {
|
||||
if _, err := client.Namespaces().Create(&api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: metav1.NamespaceSystem}}); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
utilruntime.HandleError(err)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
data := map[string]string{}
|
||||
if len(h.ClientCA) > 0 {
|
||||
data["client-ca-file"] = string(h.ClientCA)
|
||||
}
|
||||
|
||||
if len(h.RequestHeaderCA) > 0 {
|
||||
var err error
|
||||
|
||||
// encoding errors aren't going to get better, so just fail on them.
|
||||
data["requestheader-username-headers"], err = jsonSerializeStringSlice(h.RequestHeaderUsernameHeaders)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
data["requestheader-group-headers"], err = jsonSerializeStringSlice(h.RequestHeaderGroupHeaders)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
data["requestheader-extra-headers-prefix"], err = jsonSerializeStringSlice(h.RequestHeaderExtraHeaderPrefixes)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
data["requestheader-client-ca-file"] = string(h.RequestHeaderCA)
|
||||
data["requestheader-allowed-names"], err = jsonSerializeStringSlice(h.RequestHeaderAllowedNames)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// write errors may work next time if we retry, so queue for retry
|
||||
if err := writeConfigMap(client, "extension-apiserver-authentication", data); err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func jsonSerializeStringSlice(in []string) (string, error) {
|
||||
out, err := json.Marshal(in)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(out), err
|
||||
}
|
||||
|
||||
func writeConfigMap(client coreclient.ConfigMapsGetter, name string, data map[string]string) error {
|
||||
existing, err := client.ConfigMaps(metav1.NamespaceSystem).Get(name, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
_, err := client.ConfigMaps(metav1.NamespaceSystem).Create(&api.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: name},
|
||||
Data: data,
|
||||
})
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
existing.Data = data
|
||||
_, err = client.ConfigMaps(metav1.NamespaceSystem).Update(existing)
|
||||
return err
|
||||
}
|
||||
223
vendor/k8s.io/kubernetes/pkg/master/client_ca_hook_test.go
generated
vendored
Normal file
223
vendor/k8s.io/kubernetes/pkg/master/client_ca_hook_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
clienttesting "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
)
|
||||
|
||||
func TestWriteClientCAs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
hook ClientCARegistrationHook
|
||||
preexistingObjs []runtime.Object
|
||||
expectedConfigMaps map[string]*api.ConfigMap
|
||||
expectUpdate bool
|
||||
}{
|
||||
{
|
||||
name: "basic",
|
||||
hook: ClientCARegistrationHook{
|
||||
ClientCA: []byte("foo"),
|
||||
RequestHeaderUsernameHeaders: []string{"alfa", "bravo", "charlie"},
|
||||
RequestHeaderGroupHeaders: []string{"delta"},
|
||||
RequestHeaderExtraHeaderPrefixes: []string{"echo", "foxtrot"},
|
||||
RequestHeaderCA: []byte("bar"),
|
||||
RequestHeaderAllowedNames: []string{"first", "second"},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "foo",
|
||||
"requestheader-username-headers": `["alfa","bravo","charlie"]`,
|
||||
"requestheader-group-headers": `["delta"]`,
|
||||
"requestheader-extra-headers-prefix": `["echo","foxtrot"]`,
|
||||
"requestheader-client-ca-file": "bar",
|
||||
"requestheader-allowed-names": `["first","second"]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "skip extension-apiserver-authentication",
|
||||
hook: ClientCARegistrationHook{
|
||||
RequestHeaderCA: []byte("bar"),
|
||||
RequestHeaderAllowedNames: []string{"first", "second"},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"requestheader-username-headers": `null`,
|
||||
"requestheader-group-headers": `null`,
|
||||
"requestheader-extra-headers-prefix": `null`,
|
||||
"requestheader-client-ca-file": "bar",
|
||||
"requestheader-allowed-names": `["first","second"]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "skip extension-apiserver-authentication",
|
||||
hook: ClientCARegistrationHook{
|
||||
ClientCA: []byte("foo"),
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty allowed names",
|
||||
hook: ClientCARegistrationHook{
|
||||
RequestHeaderCA: []byte("bar"),
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"requestheader-username-headers": `null`,
|
||||
"requestheader-group-headers": `null`,
|
||||
"requestheader-extra-headers-prefix": `null`,
|
||||
"requestheader-client-ca-file": "bar",
|
||||
"requestheader-allowed-names": `null`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "overwrite extension-apiserver-authentication",
|
||||
hook: ClientCARegistrationHook{
|
||||
ClientCA: []byte("foo"),
|
||||
},
|
||||
preexistingObjs: []runtime.Object{
|
||||
&api.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "other",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
name: "overwrite extension-apiserver-authentication requestheader",
|
||||
hook: ClientCARegistrationHook{
|
||||
RequestHeaderUsernameHeaders: []string{},
|
||||
RequestHeaderGroupHeaders: []string{},
|
||||
RequestHeaderExtraHeaderPrefixes: []string{},
|
||||
RequestHeaderCA: []byte("bar"),
|
||||
RequestHeaderAllowedNames: []string{},
|
||||
},
|
||||
preexistingObjs: []runtime.Object{
|
||||
&api.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"requestheader-username-headers": `null`,
|
||||
"requestheader-group-headers": `null`,
|
||||
"requestheader-extra-headers-prefix": `null`,
|
||||
"requestheader-client-ca-file": "something",
|
||||
"requestheader-allowed-names": `null`,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"requestheader-username-headers": `[]`,
|
||||
"requestheader-group-headers": `[]`,
|
||||
"requestheader-extra-headers-prefix": `[]`,
|
||||
"requestheader-client-ca-file": "bar",
|
||||
"requestheader-allowed-names": `[]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
name: "namespace exists",
|
||||
hook: ClientCARegistrationHook{
|
||||
ClientCA: []byte("foo"),
|
||||
},
|
||||
preexistingObjs: []runtime.Object{
|
||||
&api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: metav1.NamespaceSystem}},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
client := fake.NewSimpleClientset(test.preexistingObjs...)
|
||||
test.hook.tryToWriteClientCAs(client.Core())
|
||||
|
||||
actualConfigMaps, updated := getFinalConfiMaps(client)
|
||||
if !reflect.DeepEqual(test.expectedConfigMaps, actualConfigMaps) {
|
||||
t.Errorf("%s: %v", test.name, diff.ObjectReflectDiff(test.expectedConfigMaps, actualConfigMaps))
|
||||
continue
|
||||
}
|
||||
if test.expectUpdate != updated {
|
||||
t.Errorf("%s: expected %v, got %v", test.name, test.expectUpdate, updated)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getFinalConfiMaps(client *fake.Clientset) (map[string]*api.ConfigMap, bool) {
|
||||
ret := map[string]*api.ConfigMap{}
|
||||
updated := false
|
||||
|
||||
for _, action := range client.Actions() {
|
||||
if action.Matches("create", "configmaps") {
|
||||
obj := action.(clienttesting.CreateAction).GetObject().(*api.ConfigMap)
|
||||
ret[obj.Name] = obj
|
||||
}
|
||||
if action.Matches("update", "configmaps") {
|
||||
updated = true
|
||||
obj := action.(clienttesting.UpdateAction).GetObject().(*api.ConfigMap)
|
||||
ret[obj.Name] = obj
|
||||
}
|
||||
}
|
||||
return ret, updated
|
||||
}
|
||||
289
vendor/k8s.io/kubernetes/pkg/master/controller.go
generated
vendored
Normal file
289
vendor/k8s.io/kubernetes/pkg/master/controller.go
generated
vendored
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/master/reconcilers"
|
||||
"k8s.io/kubernetes/pkg/registry/core/rangeallocation"
|
||||
corerest "k8s.io/kubernetes/pkg/registry/core/rest"
|
||||
servicecontroller "k8s.io/kubernetes/pkg/registry/core/service/ipallocator/controller"
|
||||
portallocatorcontroller "k8s.io/kubernetes/pkg/registry/core/service/portallocator/controller"
|
||||
"k8s.io/kubernetes/pkg/util/async"
|
||||
)
|
||||
|
||||
const kubernetesServiceName = "kubernetes"
|
||||
|
||||
// Controller is the controller manager for the core bootstrap Kubernetes
|
||||
// controller loops, which manage creating the "kubernetes" service, the
|
||||
// "default", "kube-system" and "kube-public" namespaces, and provide the IP
|
||||
// repair check on service IPs
|
||||
type Controller struct {
|
||||
ServiceClient coreclient.ServicesGetter
|
||||
NamespaceClient coreclient.NamespacesGetter
|
||||
EventClient coreclient.EventsGetter
|
||||
|
||||
ServiceClusterIPRegistry rangeallocation.RangeRegistry
|
||||
ServiceClusterIPInterval time.Duration
|
||||
ServiceClusterIPRange net.IPNet
|
||||
|
||||
ServiceNodePortRegistry rangeallocation.RangeRegistry
|
||||
ServiceNodePortInterval time.Duration
|
||||
ServiceNodePortRange utilnet.PortRange
|
||||
|
||||
EndpointReconciler reconcilers.EndpointReconciler
|
||||
EndpointInterval time.Duration
|
||||
|
||||
SystemNamespaces []string
|
||||
SystemNamespacesInterval time.Duration
|
||||
|
||||
PublicIP net.IP
|
||||
|
||||
// ServiceIP indicates where the kubernetes service will live. It may not be nil.
|
||||
ServiceIP net.IP
|
||||
ServicePort int
|
||||
ExtraServicePorts []api.ServicePort
|
||||
ExtraEndpointPorts []api.EndpointPort
|
||||
PublicServicePort int
|
||||
KubernetesServiceNodePort int
|
||||
|
||||
runner *async.Runner
|
||||
}
|
||||
|
||||
// NewBootstrapController returns a controller for watching the core capabilities of the master
|
||||
func (c *completedConfig) NewBootstrapController(legacyRESTStorage corerest.LegacyRESTStorage, serviceClient coreclient.ServicesGetter, nsClient coreclient.NamespacesGetter, eventClient coreclient.EventsGetter) *Controller {
|
||||
return &Controller{
|
||||
ServiceClient: serviceClient,
|
||||
NamespaceClient: nsClient,
|
||||
EventClient: eventClient,
|
||||
|
||||
EndpointReconciler: c.ExtraConfig.EndpointReconcilerConfig.Reconciler,
|
||||
EndpointInterval: c.ExtraConfig.EndpointReconcilerConfig.Interval,
|
||||
|
||||
SystemNamespaces: []string{metav1.NamespaceSystem, metav1.NamespacePublic},
|
||||
SystemNamespacesInterval: 1 * time.Minute,
|
||||
|
||||
ServiceClusterIPRegistry: legacyRESTStorage.ServiceClusterIPAllocator,
|
||||
ServiceClusterIPRange: c.ExtraConfig.ServiceIPRange,
|
||||
ServiceClusterIPInterval: 3 * time.Minute,
|
||||
|
||||
ServiceNodePortRegistry: legacyRESTStorage.ServiceNodePortAllocator,
|
||||
ServiceNodePortRange: c.ExtraConfig.ServiceNodePortRange,
|
||||
ServiceNodePortInterval: 3 * time.Minute,
|
||||
|
||||
PublicIP: c.GenericConfig.PublicAddress,
|
||||
|
||||
ServiceIP: c.ExtraConfig.APIServerServiceIP,
|
||||
ServicePort: c.ExtraConfig.APIServerServicePort,
|
||||
ExtraServicePorts: c.ExtraConfig.ExtraServicePorts,
|
||||
ExtraEndpointPorts: c.ExtraConfig.ExtraEndpointPorts,
|
||||
PublicServicePort: c.GenericConfig.ReadWritePort,
|
||||
KubernetesServiceNodePort: c.ExtraConfig.KubernetesServiceNodePort,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
|
||||
c.Start()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) PreShutdownHook() error {
|
||||
c.Stop()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start begins the core controller loops that must exist for bootstrapping
|
||||
// a cluster.
|
||||
func (c *Controller) Start() {
|
||||
if c.runner != nil {
|
||||
return
|
||||
}
|
||||
|
||||
repairClusterIPs := servicecontroller.NewRepair(c.ServiceClusterIPInterval, c.ServiceClient, c.EventClient, &c.ServiceClusterIPRange, c.ServiceClusterIPRegistry)
|
||||
repairNodePorts := portallocatorcontroller.NewRepair(c.ServiceNodePortInterval, c.ServiceClient, c.EventClient, c.ServiceNodePortRange, c.ServiceNodePortRegistry)
|
||||
|
||||
// run all of the controllers once prior to returning from Start.
|
||||
if err := repairClusterIPs.RunOnce(); err != nil {
|
||||
// If we fail to repair cluster IPs apiserver is useless. We should restart and retry.
|
||||
glog.Fatalf("Unable to perform initial IP allocation check: %v", err)
|
||||
}
|
||||
if err := repairNodePorts.RunOnce(); err != nil {
|
||||
// If we fail to repair node ports apiserver is useless. We should restart and retry.
|
||||
glog.Fatalf("Unable to perform initial service nodePort check: %v", err)
|
||||
}
|
||||
// Service definition is reconciled during first run to correct port and type per expectations.
|
||||
if err := c.UpdateKubernetesService(true); err != nil {
|
||||
glog.Errorf("Unable to perform initial Kubernetes service initialization: %v", err)
|
||||
}
|
||||
|
||||
c.runner = async.NewRunner(c.RunKubernetesNamespaces, c.RunKubernetesService, repairClusterIPs.RunUntil, repairNodePorts.RunUntil)
|
||||
c.runner.Start()
|
||||
}
|
||||
|
||||
func (c *Controller) Stop() {
|
||||
if c.runner != nil {
|
||||
c.runner.Stop()
|
||||
}
|
||||
endpointPorts := createEndpointPortSpec(c.PublicServicePort, "https", c.ExtraEndpointPorts)
|
||||
c.EndpointReconciler.StopReconciling("kubernetes", c.PublicIP, endpointPorts)
|
||||
}
|
||||
|
||||
// RunKubernetesNamespaces periodically makes sure that all internal namespaces exist
|
||||
func (c *Controller) RunKubernetesNamespaces(ch chan struct{}) {
|
||||
wait.Until(func() {
|
||||
// Loop the system namespace list, and create them if they do not exist
|
||||
for _, ns := range c.SystemNamespaces {
|
||||
if err := c.CreateNamespaceIfNeeded(ns); err != nil {
|
||||
runtime.HandleError(fmt.Errorf("unable to create required kubernetes system namespace %s: %v", ns, err))
|
||||
}
|
||||
}
|
||||
}, c.SystemNamespacesInterval, ch)
|
||||
}
|
||||
|
||||
// RunKubernetesService periodically updates the kubernetes service
|
||||
func (c *Controller) RunKubernetesService(ch chan struct{}) {
|
||||
wait.Until(func() {
|
||||
// Service definition is not reconciled after first
|
||||
// run, ports and type will be corrected only during
|
||||
// start.
|
||||
if err := c.UpdateKubernetesService(false); err != nil {
|
||||
runtime.HandleError(fmt.Errorf("unable to sync kubernetes service: %v", err))
|
||||
}
|
||||
}, c.EndpointInterval, ch)
|
||||
}
|
||||
|
||||
// UpdateKubernetesService attempts to update the default Kube service.
|
||||
func (c *Controller) UpdateKubernetesService(reconcile bool) error {
|
||||
// Update service & endpoint records.
|
||||
// TODO: when it becomes possible to change this stuff,
|
||||
// stop polling and start watching.
|
||||
// TODO: add endpoints of all replicas, not just the elected master.
|
||||
if err := c.CreateNamespaceIfNeeded(metav1.NamespaceDefault); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
servicePorts, serviceType := createPortAndServiceSpec(c.ServicePort, c.PublicServicePort, c.KubernetesServiceNodePort, "https", c.ExtraServicePorts)
|
||||
if err := c.CreateOrUpdateMasterServiceIfNeeded(kubernetesServiceName, c.ServiceIP, servicePorts, serviceType, reconcile); err != nil {
|
||||
return err
|
||||
}
|
||||
endpointPorts := createEndpointPortSpec(c.PublicServicePort, "https", c.ExtraEndpointPorts)
|
||||
if err := c.EndpointReconciler.ReconcileEndpoints(kubernetesServiceName, c.PublicIP, endpointPorts, reconcile); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateNamespaceIfNeeded will create a namespace if it doesn't already exist
|
||||
func (c *Controller) CreateNamespaceIfNeeded(ns string) error {
|
||||
if _, err := c.NamespaceClient.Namespaces().Get(ns, metav1.GetOptions{}); err == nil {
|
||||
// the namespace already exists
|
||||
return nil
|
||||
}
|
||||
newNs := &api.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ns,
|
||||
Namespace: "",
|
||||
},
|
||||
}
|
||||
_, err := c.NamespaceClient.Namespaces().Create(newNs)
|
||||
if err != nil && errors.IsAlreadyExists(err) {
|
||||
err = nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// createPortAndServiceSpec creates an array of service ports.
|
||||
// If the NodePort value is 0, just the servicePort is used, otherwise, a node port is exposed.
|
||||
func createPortAndServiceSpec(servicePort int, targetServicePort int, nodePort int, servicePortName string, extraServicePorts []api.ServicePort) ([]api.ServicePort, api.ServiceType) {
|
||||
//Use the Cluster IP type for the service port if NodePort isn't provided.
|
||||
//Otherwise, we will be binding the master service to a NodePort.
|
||||
servicePorts := []api.ServicePort{{Protocol: api.ProtocolTCP,
|
||||
Port: int32(servicePort),
|
||||
Name: servicePortName,
|
||||
TargetPort: intstr.FromInt(targetServicePort)}}
|
||||
serviceType := api.ServiceTypeClusterIP
|
||||
if nodePort > 0 {
|
||||
servicePorts[0].NodePort = int32(nodePort)
|
||||
serviceType = api.ServiceTypeNodePort
|
||||
}
|
||||
if extraServicePorts != nil {
|
||||
servicePorts = append(servicePorts, extraServicePorts...)
|
||||
}
|
||||
return servicePorts, serviceType
|
||||
}
|
||||
|
||||
// createEndpointPortSpec creates an array of endpoint ports
|
||||
func createEndpointPortSpec(endpointPort int, endpointPortName string, extraEndpointPorts []api.EndpointPort) []api.EndpointPort {
|
||||
endpointPorts := []api.EndpointPort{{Protocol: api.ProtocolTCP,
|
||||
Port: int32(endpointPort),
|
||||
Name: endpointPortName,
|
||||
}}
|
||||
if extraEndpointPorts != nil {
|
||||
endpointPorts = append(endpointPorts, extraEndpointPorts...)
|
||||
}
|
||||
return endpointPorts
|
||||
}
|
||||
|
||||
// CreateMasterServiceIfNeeded will create the specified service if it
|
||||
// doesn't already exist.
|
||||
func (c *Controller) CreateOrUpdateMasterServiceIfNeeded(serviceName string, serviceIP net.IP, servicePorts []api.ServicePort, serviceType api.ServiceType, reconcile bool) error {
|
||||
if s, err := c.ServiceClient.Services(metav1.NamespaceDefault).Get(serviceName, metav1.GetOptions{}); err == nil {
|
||||
// The service already exists.
|
||||
if reconcile {
|
||||
if svc, updated := reconcilers.GetMasterServiceUpdateIfNeeded(s, servicePorts, serviceType); updated {
|
||||
glog.Warningf("Resetting master service %q to %#v", serviceName, svc)
|
||||
_, err := c.ServiceClient.Services(metav1.NamespaceDefault).Update(svc)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
svc := &api.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: serviceName,
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
Labels: map[string]string{"provider": "kubernetes", "component": "apiserver"},
|
||||
},
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: servicePorts,
|
||||
// maintained by this code, not by the pod selector
|
||||
Selector: nil,
|
||||
ClusterIP: serviceIP.String(),
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: serviceType,
|
||||
},
|
||||
}
|
||||
|
||||
_, err := c.ServiceClient.Services(metav1.NamespaceDefault).Create(svc)
|
||||
if errors.IsAlreadyExists(err) {
|
||||
return c.CreateOrUpdateMasterServiceIfNeeded(serviceName, serviceIP, servicePorts, serviceType, reconcile)
|
||||
}
|
||||
return err
|
||||
}
|
||||
948
vendor/k8s.io/kubernetes/pkg/master/controller_test.go
generated
vendored
Normal file
948
vendor/k8s.io/kubernetes/pkg/master/controller_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,948 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
core "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
"k8s.io/kubernetes/pkg/master/reconcilers"
|
||||
)
|
||||
|
||||
func TestReconcileEndpoints(t *testing.T) {
|
||||
ns := metav1.NamespaceDefault
|
||||
om := func(name string) metav1.ObjectMeta {
|
||||
return metav1.ObjectMeta{Namespace: ns, Name: name}
|
||||
}
|
||||
reconcile_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
ip string
|
||||
endpointPorts []api.EndpointPort
|
||||
additionalMasters int
|
||||
endpoints *api.EndpointsList
|
||||
expectUpdate *api.Endpoints // nil means none expected
|
||||
expectCreate *api.Endpoints // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "no existing endpoints",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: nil,
|
||||
expectCreate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy but too many",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "4.3.2.1"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy but too many + extra masters",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
additionalMasters: 3,
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
{IP: "4.3.2.3"},
|
||||
{IP: "4.3.2.4"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "4.3.2.2"},
|
||||
{IP: "4.3.2.3"},
|
||||
{IP: "4.3.2.4"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy but too many + extra masters + delete first",
|
||||
serviceName: "foo",
|
||||
ip: "4.3.2.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
additionalMasters: 3,
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
{IP: "4.3.2.3"},
|
||||
{IP: "4.3.2.4"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
{IP: "4.3.2.3"},
|
||||
{IP: "4.3.2.4"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy and endpoint addresses length less than master count",
|
||||
serviceName: "foo",
|
||||
ip: "4.3.2.2",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
additionalMasters: 3,
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: nil,
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints current IP missing and address length less than master count",
|
||||
serviceName: "foo",
|
||||
ip: "4.3.2.2",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
additionalMasters: 3,
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "4.3.2.1"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong name",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("bar"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectCreate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong IP",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "4.3.2.1"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong port",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 9090, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong protocol",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "UDP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong port name",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "baz", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "baz", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints extra service ports satisfy",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
{Name: "baz", Port: 1010, Protocol: "TCP"},
|
||||
},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
{Name: "baz", Port: 1010, Protocol: "TCP"},
|
||||
},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints extra service ports missing port",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range reconcile_tests {
|
||||
fakeClient := fake.NewSimpleClientset()
|
||||
if test.endpoints != nil {
|
||||
fakeClient = fake.NewSimpleClientset(test.endpoints)
|
||||
}
|
||||
reconciler := reconcilers.NewMasterCountEndpointReconciler(test.additionalMasters+1, fakeClient.Core())
|
||||
err := reconciler.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, true)
|
||||
if err != nil {
|
||||
t.Errorf("case %q: unexpected error: %v", test.testName, err)
|
||||
}
|
||||
|
||||
updates := []core.UpdateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() != "update" {
|
||||
continue
|
||||
}
|
||||
updates = append(updates, action.(core.UpdateAction))
|
||||
}
|
||||
if test.expectUpdate != nil {
|
||||
if len(updates) != 1 {
|
||||
t.Errorf("case %q: unexpected updates: %v", test.testName, updates)
|
||||
} else if e, a := test.expectUpdate, updates[0].GetObject(); !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
if test.expectUpdate == nil && len(updates) > 0 {
|
||||
t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates)
|
||||
}
|
||||
|
||||
creates := []core.CreateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() != "create" {
|
||||
continue
|
||||
}
|
||||
creates = append(creates, action.(core.CreateAction))
|
||||
}
|
||||
if test.expectCreate != nil {
|
||||
if len(creates) != 1 {
|
||||
t.Errorf("case %q: unexpected creates: %v", test.testName, creates)
|
||||
} else if e, a := test.expectCreate, creates[0].GetObject(); !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected create:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
if test.expectCreate == nil && len(creates) > 0 {
|
||||
t.Errorf("case %q: no create expected, yet saw: %v", test.testName, creates)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
non_reconcile_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
ip string
|
||||
endpointPorts []api.EndpointPort
|
||||
additionalMasters int
|
||||
endpoints *api.EndpointsList
|
||||
expectUpdate *api.Endpoints // nil means none expected
|
||||
expectCreate *api.Endpoints // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "existing endpoints extra service ports missing port no update",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: nil,
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints extra service ports, wrong ports, wrong IP",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "4.3.2.1"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "no existing endpoints",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: nil,
|
||||
expectCreate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range non_reconcile_tests {
|
||||
fakeClient := fake.NewSimpleClientset()
|
||||
if test.endpoints != nil {
|
||||
fakeClient = fake.NewSimpleClientset(test.endpoints)
|
||||
}
|
||||
reconciler := reconcilers.NewMasterCountEndpointReconciler(test.additionalMasters+1, fakeClient.Core())
|
||||
err := reconciler.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, false)
|
||||
if err != nil {
|
||||
t.Errorf("case %q: unexpected error: %v", test.testName, err)
|
||||
}
|
||||
|
||||
updates := []core.UpdateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() != "update" {
|
||||
continue
|
||||
}
|
||||
updates = append(updates, action.(core.UpdateAction))
|
||||
}
|
||||
if test.expectUpdate != nil {
|
||||
if len(updates) != 1 {
|
||||
t.Errorf("case %q: unexpected updates: %v", test.testName, updates)
|
||||
} else if e, a := test.expectUpdate, updates[0].GetObject(); !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
if test.expectUpdate == nil && len(updates) > 0 {
|
||||
t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates)
|
||||
}
|
||||
|
||||
creates := []core.CreateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() != "create" {
|
||||
continue
|
||||
}
|
||||
creates = append(creates, action.(core.CreateAction))
|
||||
}
|
||||
if test.expectCreate != nil {
|
||||
if len(creates) != 1 {
|
||||
t.Errorf("case %q: unexpected creates: %v", test.testName, creates)
|
||||
} else if e, a := test.expectCreate, creates[0].GetObject(); !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected create:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
if test.expectCreate == nil && len(creates) > 0 {
|
||||
t.Errorf("case %q: no create expected, yet saw: %v", test.testName, creates)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCreateOrUpdateMasterService(t *testing.T) {
|
||||
ns := metav1.NamespaceDefault
|
||||
om := func(name string) metav1.ObjectMeta {
|
||||
return metav1.ObjectMeta{Namespace: ns, Name: name}
|
||||
}
|
||||
|
||||
create_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
servicePorts []api.ServicePort
|
||||
serviceType api.ServiceType
|
||||
expectCreate *api.Service // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "service does not exist",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
expectCreate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range create_tests {
|
||||
master := Controller{}
|
||||
fakeClient := fake.NewSimpleClientset()
|
||||
master.ServiceClient = fakeClient.Core()
|
||||
master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, net.ParseIP("1.2.3.4"), test.servicePorts, test.serviceType, false)
|
||||
creates := []core.CreateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() == "create" {
|
||||
creates = append(creates, action.(core.CreateAction))
|
||||
}
|
||||
}
|
||||
if test.expectCreate != nil {
|
||||
if len(creates) != 1 {
|
||||
t.Errorf("case %q: unexpected creations: %v", test.testName, creates)
|
||||
} else {
|
||||
obj := creates[0].GetObject()
|
||||
if e, a := test.expectCreate.Spec, obj.(*api.Service).Spec; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected create:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
if test.expectCreate == nil && len(creates) > 1 {
|
||||
t.Errorf("case %q: no create expected, yet saw: %v", test.testName, creates)
|
||||
}
|
||||
}
|
||||
|
||||
reconcile_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
servicePorts []api.ServicePort
|
||||
serviceType api.ServiceType
|
||||
service *api.Service
|
||||
expectUpdate *api.Service // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "service definition wrong port",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8000, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition missing port",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
{Name: "baz", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
{Name: "baz", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition incorrect port",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "bar", Port: 1000, Protocol: "UDP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition incorrect port name",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 1000, Protocol: "UDP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition incorrect target port",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition incorrect protocol",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "UDP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition has incorrect type",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeNodePort,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition satisfies",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: nil,
|
||||
},
|
||||
}
|
||||
for _, test := range reconcile_tests {
|
||||
master := Controller{}
|
||||
fakeClient := fake.NewSimpleClientset(test.service)
|
||||
master.ServiceClient = fakeClient.Core()
|
||||
err := master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, net.ParseIP("1.2.3.4"), test.servicePorts, test.serviceType, true)
|
||||
if err != nil {
|
||||
t.Errorf("case %q: unexpected error: %v", test.testName, err)
|
||||
}
|
||||
updates := []core.UpdateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() == "update" {
|
||||
updates = append(updates, action.(core.UpdateAction))
|
||||
}
|
||||
}
|
||||
if test.expectUpdate != nil {
|
||||
if len(updates) != 1 {
|
||||
t.Errorf("case %q: unexpected updates: %v", test.testName, updates)
|
||||
} else {
|
||||
obj := updates[0].GetObject()
|
||||
if e, a := test.expectUpdate.Spec, obj.(*api.Service).Spec; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
if test.expectUpdate == nil && len(updates) > 0 {
|
||||
t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates)
|
||||
}
|
||||
}
|
||||
|
||||
non_reconcile_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
servicePorts []api.ServicePort
|
||||
serviceType api.ServiceType
|
||||
service *api.Service
|
||||
expectUpdate *api.Service // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "service definition wrong port, no expected update",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: nil,
|
||||
},
|
||||
}
|
||||
for _, test := range non_reconcile_tests {
|
||||
master := Controller{}
|
||||
fakeClient := fake.NewSimpleClientset(test.service)
|
||||
master.ServiceClient = fakeClient.Core()
|
||||
err := master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, net.ParseIP("1.2.3.4"), test.servicePorts, test.serviceType, false)
|
||||
if err != nil {
|
||||
t.Errorf("case %q: unexpected error: %v", test.testName, err)
|
||||
}
|
||||
updates := []core.UpdateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() == "update" {
|
||||
updates = append(updates, action.(core.UpdateAction))
|
||||
}
|
||||
}
|
||||
if test.expectUpdate != nil {
|
||||
if len(updates) != 1 {
|
||||
t.Errorf("case %q: unexpected updates: %v", test.testName, updates)
|
||||
} else {
|
||||
obj := updates[0].GetObject()
|
||||
if e, a := test.expectUpdate.Spec, obj.(*api.Service).Spec; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
if test.expectUpdate == nil && len(updates) > 0 {
|
||||
t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates)
|
||||
}
|
||||
}
|
||||
}
|
||||
19
vendor/k8s.io/kubernetes/pkg/master/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/master/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 master contains code for setting up and running a Kubernetes
|
||||
// cluster master.
|
||||
package master // import "k8s.io/kubernetes/pkg/master"
|
||||
50
vendor/k8s.io/kubernetes/pkg/master/import_known_versions.go
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/pkg/master/import_known_versions.go
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
// These imports are the API groups the API server will support.
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
|
||||
_ "k8s.io/kubernetes/pkg/apis/admission/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/admissionregistration/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/apps/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/authentication/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/authorization/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/certificates/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/events/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/networking/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/policy/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/scheduling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/settings/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/storage/install"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if missingVersions := legacyscheme.Registry.ValidateEnvRequestedVersions(); len(missingVersions) != 0 {
|
||||
panic(fmt.Sprintf("KUBE_API_VERSIONS contains versions that are not installed: %q.", missingVersions))
|
||||
}
|
||||
}
|
||||
187
vendor/k8s.io/kubernetes/pkg/master/import_known_versions_test.go
generated
vendored
Normal file
187
vendor/k8s.io/kubernetes/pkg/master/import_known_versions_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
)
|
||||
|
||||
func TestGroupVersions(t *testing.T) {
|
||||
// legacyUnsuffixedGroups contains the groups released prior to deciding that kubernetes API groups should be dns-suffixed
|
||||
// new groups should be suffixed with ".k8s.io" (https://github.com/kubernetes/kubernetes/pull/31887#issuecomment-244462396)
|
||||
legacyUnsuffixedGroups := sets.NewString(
|
||||
"",
|
||||
"apps",
|
||||
"autoscaling",
|
||||
"batch",
|
||||
"componentconfig",
|
||||
"extensions",
|
||||
"policy",
|
||||
)
|
||||
|
||||
// No new groups should be added to the legacyUnsuffixedGroups exclusion list
|
||||
if len(legacyUnsuffixedGroups) != 7 {
|
||||
t.Errorf("No additional unnamespaced groups should be created")
|
||||
}
|
||||
|
||||
for _, gv := range legacyscheme.Registry.RegisteredGroupVersions() {
|
||||
if !strings.HasSuffix(gv.Group, ".k8s.io") && !legacyUnsuffixedGroups.Has(gv.Group) {
|
||||
t.Errorf("Group %s does not have the standard kubernetes API group suffix of .k8s.io", gv.Group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypeTags(t *testing.T) {
|
||||
for gvk, knownType := range legacyscheme.Scheme.AllKnownTypes() {
|
||||
if gvk.Version == runtime.APIVersionInternal {
|
||||
ensureNoTags(t, gvk, knownType, nil)
|
||||
} else {
|
||||
ensureTags(t, gvk, knownType, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These types are registered in external versions, and therefore include json tags,
|
||||
// but are also registered in internal versions (or referenced from internal types),
|
||||
// so we explicitly allow tags for them
|
||||
var typesAllowedTags = map[reflect.Type]bool{
|
||||
reflect.TypeOf(intstr.IntOrString{}): true,
|
||||
reflect.TypeOf(metav1.Time{}): true,
|
||||
reflect.TypeOf(metav1.MicroTime{}): true,
|
||||
reflect.TypeOf(metav1.Duration{}): true,
|
||||
reflect.TypeOf(metav1.TypeMeta{}): true,
|
||||
reflect.TypeOf(metav1.ListMeta{}): true,
|
||||
reflect.TypeOf(metav1.ObjectMeta{}): true,
|
||||
reflect.TypeOf(metav1.OwnerReference{}): true,
|
||||
reflect.TypeOf(metav1.LabelSelector{}): true,
|
||||
reflect.TypeOf(metav1.GetOptions{}): true,
|
||||
reflect.TypeOf(metav1.ExportOptions{}): true,
|
||||
reflect.TypeOf(metav1.ListOptions{}): true,
|
||||
reflect.TypeOf(metav1.DeleteOptions{}): true,
|
||||
reflect.TypeOf(metav1.GroupVersionKind{}): true,
|
||||
reflect.TypeOf(metav1.GroupVersionResource{}): true,
|
||||
reflect.TypeOf(metav1.Status{}): true,
|
||||
}
|
||||
|
||||
func ensureNoTags(t *testing.T, gvk schema.GroupVersionKind, tp reflect.Type, parents []reflect.Type) {
|
||||
if _, ok := typesAllowedTags[tp]; ok {
|
||||
return
|
||||
}
|
||||
|
||||
parents = append(parents, tp)
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Map, reflect.Slice, reflect.Ptr:
|
||||
ensureNoTags(t, gvk, tp.Elem(), parents)
|
||||
|
||||
case reflect.String, reflect.Bool, reflect.Float32, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uintptr, reflect.Uint32, reflect.Uint64, reflect.Interface:
|
||||
// no-op
|
||||
|
||||
case reflect.Struct:
|
||||
for i := 0; i < tp.NumField(); i++ {
|
||||
f := tp.Field(i)
|
||||
if f.PkgPath != "" {
|
||||
continue // Ignore unexported fields
|
||||
}
|
||||
jsonTag := f.Tag.Get("json")
|
||||
protoTag := f.Tag.Get("protobuf")
|
||||
if len(jsonTag) > 0 || len(protoTag) > 0 {
|
||||
t.Errorf("Internal types should not have json or protobuf tags. %#v has tag on field %v: %v", gvk, f.Name, f.Tag)
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v:", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
|
||||
ensureNoTags(t, gvk, f.Type, parents)
|
||||
}
|
||||
|
||||
default:
|
||||
t.Errorf("Unexpected type %v in %#v", tp.Kind(), gvk)
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v:", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
// These fields are limited exceptions to the standard JSON naming structure.
|
||||
// Additions should only be made if a non-standard field name was released and cannot be changed for compatibility reasons.
|
||||
var allowedNonstandardJSONNames = map[reflect.Type]string{
|
||||
reflect.TypeOf(v1.DaemonEndpoint{}): "Port",
|
||||
}
|
||||
|
||||
func ensureTags(t *testing.T, gvk schema.GroupVersionKind, tp reflect.Type, parents []reflect.Type) {
|
||||
// This type handles its own encoding/decoding and doesn't need json tags
|
||||
if tp.Implements(marshalerType) && (tp.Implements(unmarshalerType) || reflect.PtrTo(tp).Implements(unmarshalerType)) {
|
||||
return
|
||||
}
|
||||
|
||||
parents = append(parents, tp)
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Map, reflect.Slice, reflect.Ptr:
|
||||
ensureTags(t, gvk, tp.Elem(), parents)
|
||||
|
||||
case reflect.String, reflect.Bool, reflect.Float32, reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uintptr, reflect.Uint32, reflect.Uint64, reflect.Interface:
|
||||
// no-op
|
||||
|
||||
case reflect.Struct:
|
||||
for i := 0; i < tp.NumField(); i++ {
|
||||
f := tp.Field(i)
|
||||
jsonTag := f.Tag.Get("json")
|
||||
if len(jsonTag) == 0 {
|
||||
t.Errorf("External types should have json tags. %#v tags on field %v are: %s", gvk, f.Name, f.Tag)
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
|
||||
jsonTagName := strings.Split(jsonTag, ",")[0]
|
||||
if len(jsonTagName) > 0 && (jsonTagName[0] < 'a' || jsonTagName[0] > 'z') && jsonTagName != "-" && allowedNonstandardJSONNames[tp] != jsonTagName {
|
||||
t.Errorf("External types should have json names starting with lowercase letter. %#v has json tag on field %v with name %s", gvk, f.Name, jsonTagName)
|
||||
t.Log(tp)
|
||||
t.Log(allowedNonstandardJSONNames[tp])
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
|
||||
ensureTags(t, gvk, f.Type, parents)
|
||||
}
|
||||
|
||||
default:
|
||||
t.Errorf("Unexpected type %v in %#v", tp.Kind(), gvk)
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v:", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
}
|
||||
501
vendor/k8s.io/kubernetes/pkg/master/master.go
generated
vendored
Normal file
501
vendor/k8s.io/kubernetes/pkg/master/master.go
generated
vendored
Normal file
|
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
appsv1beta1 "k8s.io/api/apps/v1beta1"
|
||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
authenticationv1beta1 "k8s.io/api/authentication/v1beta1"
|
||||
authorizationapiv1 "k8s.io/api/authorization/v1"
|
||||
authorizationapiv1beta1 "k8s.io/api/authorization/v1beta1"
|
||||
autoscalingapiv1 "k8s.io/api/autoscaling/v1"
|
||||
autoscalingapiv2beta1 "k8s.io/api/autoscaling/v2beta1"
|
||||
batchapiv1 "k8s.io/api/batch/v1"
|
||||
batchapiv1beta1 "k8s.io/api/batch/v1beta1"
|
||||
certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
eventsv1beta1 "k8s.io/api/events/v1beta1"
|
||||
extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
networkingapiv1 "k8s.io/api/networking/v1"
|
||||
policyapiv1beta1 "k8s.io/api/policy/v1beta1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
rbacv1beta1 "k8s.io/api/rbac/v1beta1"
|
||||
storageapiv1 "k8s.io/api/storage/v1"
|
||||
storageapiv1beta1 "k8s.io/api/storage/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apiserver/pkg/endpoints/discovery"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/healthz"
|
||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||
storagefactory "k8s.io/apiserver/pkg/storage/storagebackend/factory"
|
||||
"k8s.io/client-go/informers"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
|
||||
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
||||
"k8s.io/kubernetes/pkg/master/reconcilers"
|
||||
"k8s.io/kubernetes/pkg/master/tunneler"
|
||||
"k8s.io/kubernetes/pkg/registry/core/endpoint"
|
||||
endpointsstorage "k8s.io/kubernetes/pkg/registry/core/endpoint/storage"
|
||||
"k8s.io/kubernetes/pkg/routes"
|
||||
nodeutil "k8s.io/kubernetes/pkg/util/node"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
// RESTStorage installers
|
||||
admissionregistrationrest "k8s.io/kubernetes/pkg/registry/admissionregistration/rest"
|
||||
appsrest "k8s.io/kubernetes/pkg/registry/apps/rest"
|
||||
authenticationrest "k8s.io/kubernetes/pkg/registry/authentication/rest"
|
||||
authorizationrest "k8s.io/kubernetes/pkg/registry/authorization/rest"
|
||||
autoscalingrest "k8s.io/kubernetes/pkg/registry/autoscaling/rest"
|
||||
batchrest "k8s.io/kubernetes/pkg/registry/batch/rest"
|
||||
certificatesrest "k8s.io/kubernetes/pkg/registry/certificates/rest"
|
||||
corerest "k8s.io/kubernetes/pkg/registry/core/rest"
|
||||
eventsrest "k8s.io/kubernetes/pkg/registry/events/rest"
|
||||
extensionsrest "k8s.io/kubernetes/pkg/registry/extensions/rest"
|
||||
networkingrest "k8s.io/kubernetes/pkg/registry/networking/rest"
|
||||
policyrest "k8s.io/kubernetes/pkg/registry/policy/rest"
|
||||
rbacrest "k8s.io/kubernetes/pkg/registry/rbac/rest"
|
||||
schedulingrest "k8s.io/kubernetes/pkg/registry/scheduling/rest"
|
||||
settingsrest "k8s.io/kubernetes/pkg/registry/settings/rest"
|
||||
storagerest "k8s.io/kubernetes/pkg/registry/storage/rest"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultEndpointReconcilerInterval is the default amount of time for how often the endpoints for
|
||||
// the kubernetes Service are reconciled.
|
||||
DefaultEndpointReconcilerInterval = 10 * time.Second
|
||||
// DefaultEndpointReconcilerTTL is the default TTL timeout for the storage layer
|
||||
DefaultEndpointReconcilerTTL = 15 * time.Second
|
||||
)
|
||||
|
||||
type ExtraConfig struct {
|
||||
ClientCARegistrationHook ClientCARegistrationHook
|
||||
|
||||
APIResourceConfigSource serverstorage.APIResourceConfigSource
|
||||
StorageFactory serverstorage.StorageFactory
|
||||
EnableCoreControllers bool
|
||||
EndpointReconcilerConfig EndpointReconcilerConfig
|
||||
EventTTL time.Duration
|
||||
KubeletClientConfig kubeletclient.KubeletClientConfig
|
||||
|
||||
// Used to start and monitor tunneling
|
||||
Tunneler tunneler.Tunneler
|
||||
EnableUISupport bool
|
||||
EnableLogsSupport bool
|
||||
ProxyTransport http.RoundTripper
|
||||
|
||||
// Values to build the IP addresses used by discovery
|
||||
// The range of IPs to be assigned to services with type=ClusterIP or greater
|
||||
ServiceIPRange net.IPNet
|
||||
// The IP address for the GenericAPIServer service (must be inside ServiceIPRange)
|
||||
APIServerServiceIP net.IP
|
||||
// Port for the apiserver service.
|
||||
APIServerServicePort int
|
||||
|
||||
// TODO, we can probably group service related items into a substruct to make it easier to configure
|
||||
// the API server items and `Extra*` fields likely fit nicely together.
|
||||
|
||||
// The range of ports to be assigned to services with type=NodePort or greater
|
||||
ServiceNodePortRange utilnet.PortRange
|
||||
// Additional ports to be exposed on the GenericAPIServer service
|
||||
// extraServicePorts is injectable in the event that more ports
|
||||
// (other than the default 443/tcp) are exposed on the GenericAPIServer
|
||||
// and those ports need to be load balanced by the GenericAPIServer
|
||||
// service because this pkg is linked by out-of-tree projects
|
||||
// like openshift which want to use the GenericAPIServer but also do
|
||||
// more stuff.
|
||||
ExtraServicePorts []api.ServicePort
|
||||
// Additional ports to be exposed on the GenericAPIServer endpoints
|
||||
// Port names should align with ports defined in ExtraServicePorts
|
||||
ExtraEndpointPorts []api.EndpointPort
|
||||
// If non-zero, the "kubernetes" services uses this port as NodePort.
|
||||
KubernetesServiceNodePort int
|
||||
|
||||
// Number of masters running; all masters must be started with the
|
||||
// same value for this field. (Numbers > 1 currently untested.)
|
||||
MasterCount int
|
||||
|
||||
// MasterEndpointReconcileTTL sets the time to live in seconds of an
|
||||
// endpoint record recorded by each master. The endpoints are checked at an
|
||||
// interval that is 2/3 of this value and this value defaults to 15s if
|
||||
// unset. In very large clusters, this value may be increased to reduce the
|
||||
// possibility that the master endpoint record expires (due to other load
|
||||
// on the etcd server) and causes masters to drop in and out of the
|
||||
// kubernetes service record. It is not recommended to set this value below
|
||||
// 15s.
|
||||
MasterEndpointReconcileTTL time.Duration
|
||||
|
||||
// Selects which reconciler to use
|
||||
EndpointReconcilerType reconcilers.Type
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.Config
|
||||
ExtraConfig ExtraConfig
|
||||
}
|
||||
|
||||
type completedConfig struct {
|
||||
GenericConfig genericapiserver.CompletedConfig
|
||||
ExtraConfig *ExtraConfig
|
||||
}
|
||||
|
||||
type CompletedConfig struct {
|
||||
// Embed a private pointer that cannot be instantiated outside of this package.
|
||||
*completedConfig
|
||||
}
|
||||
|
||||
// EndpointReconcilerConfig holds the endpoint reconciler and endpoint reconciliation interval to be
|
||||
// used by the master.
|
||||
type EndpointReconcilerConfig struct {
|
||||
Reconciler reconcilers.EndpointReconciler
|
||||
Interval time.Duration
|
||||
}
|
||||
|
||||
// Master contains state for a Kubernetes cluster master/api server.
|
||||
type Master struct {
|
||||
GenericAPIServer *genericapiserver.GenericAPIServer
|
||||
|
||||
ClientCARegistrationHook ClientCARegistrationHook
|
||||
}
|
||||
|
||||
func (c *Config) createMasterCountReconciler() reconcilers.EndpointReconciler {
|
||||
endpointClient := coreclient.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig)
|
||||
return reconcilers.NewMasterCountEndpointReconciler(c.ExtraConfig.MasterCount, endpointClient)
|
||||
}
|
||||
|
||||
func (c *Config) createNoneReconciler() reconcilers.EndpointReconciler {
|
||||
return reconcilers.NewNoneEndpointReconciler()
|
||||
}
|
||||
|
||||
func (c *Config) createLeaseReconciler() reconcilers.EndpointReconciler {
|
||||
ttl := c.ExtraConfig.MasterEndpointReconcileTTL
|
||||
config, err := c.ExtraConfig.StorageFactory.NewConfig(api.Resource("apiServerIPInfo"))
|
||||
if err != nil {
|
||||
glog.Fatalf("Error determining service IP ranges: %v", err)
|
||||
}
|
||||
leaseStorage, _, err := storagefactory.Create(*config)
|
||||
if err != nil {
|
||||
glog.Fatalf("Error creating storage factory: %v", err)
|
||||
}
|
||||
endpointConfig, err := c.ExtraConfig.StorageFactory.NewConfig(api.Resource("endpoints"))
|
||||
if err != nil {
|
||||
glog.Fatalf("Error getting storage config: %v", err)
|
||||
}
|
||||
endpointsStorage := endpointsstorage.NewREST(generic.RESTOptions{
|
||||
StorageConfig: endpointConfig,
|
||||
Decorator: generic.UndecoratedStorage,
|
||||
DeleteCollectionWorkers: 0,
|
||||
ResourcePrefix: c.ExtraConfig.StorageFactory.ResourcePrefix(api.Resource("endpoints")),
|
||||
})
|
||||
endpointRegistry := endpoint.NewRegistry(endpointsStorage)
|
||||
masterLeases := reconcilers.NewLeases(leaseStorage, "/masterleases/", ttl)
|
||||
return reconcilers.NewLeaseEndpointReconciler(endpointRegistry, masterLeases)
|
||||
}
|
||||
|
||||
func (c *Config) createEndpointReconciler() reconcilers.EndpointReconciler {
|
||||
glog.Infof("Using reconciler: %v", c.ExtraConfig.EndpointReconcilerType)
|
||||
switch c.ExtraConfig.EndpointReconcilerType {
|
||||
// there are numerous test dependencies that depend on a default controller
|
||||
case "", reconcilers.MasterCountReconcilerType:
|
||||
return c.createMasterCountReconciler()
|
||||
case reconcilers.LeaseEndpointReconcilerType:
|
||||
return c.createLeaseReconciler()
|
||||
case reconcilers.NoneEndpointReconcilerType:
|
||||
return c.createNoneReconciler()
|
||||
default:
|
||||
glog.Fatalf("Reconciler not implemented: %v", c.ExtraConfig.EndpointReconcilerType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
|
||||
func (cfg *Config) Complete(informers informers.SharedInformerFactory) CompletedConfig {
|
||||
c := completedConfig{
|
||||
cfg.GenericConfig.Complete(informers),
|
||||
&cfg.ExtraConfig,
|
||||
}
|
||||
|
||||
serviceIPRange, apiServerServiceIP, err := DefaultServiceIPRange(c.ExtraConfig.ServiceIPRange)
|
||||
if err != nil {
|
||||
glog.Fatalf("Error determining service IP ranges: %v", err)
|
||||
}
|
||||
if c.ExtraConfig.ServiceIPRange.IP == nil {
|
||||
c.ExtraConfig.ServiceIPRange = serviceIPRange
|
||||
}
|
||||
if c.ExtraConfig.APIServerServiceIP == nil {
|
||||
c.ExtraConfig.APIServerServiceIP = apiServerServiceIP
|
||||
}
|
||||
|
||||
discoveryAddresses := discovery.DefaultAddresses{DefaultAddress: c.GenericConfig.ExternalAddress}
|
||||
discoveryAddresses.CIDRRules = append(discoveryAddresses.CIDRRules,
|
||||
discovery.CIDRRule{IPRange: c.ExtraConfig.ServiceIPRange, Address: net.JoinHostPort(c.ExtraConfig.APIServerServiceIP.String(), strconv.Itoa(c.ExtraConfig.APIServerServicePort))})
|
||||
c.GenericConfig.DiscoveryAddresses = discoveryAddresses
|
||||
|
||||
if c.ExtraConfig.ServiceNodePortRange.Size == 0 {
|
||||
// TODO: Currently no way to specify an empty range (do we need to allow this?)
|
||||
// We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE)
|
||||
// but then that breaks the strict nestedness of ServiceType.
|
||||
// Review post-v1
|
||||
c.ExtraConfig.ServiceNodePortRange = kubeoptions.DefaultServiceNodePortRange
|
||||
glog.Infof("Node port range unspecified. Defaulting to %v.", c.ExtraConfig.ServiceNodePortRange)
|
||||
}
|
||||
|
||||
// enable swagger UI only if general UI support is on
|
||||
c.GenericConfig.EnableSwaggerUI = c.GenericConfig.EnableSwaggerUI && c.ExtraConfig.EnableUISupport
|
||||
|
||||
if c.ExtraConfig.EndpointReconcilerConfig.Interval == 0 {
|
||||
c.ExtraConfig.EndpointReconcilerConfig.Interval = DefaultEndpointReconcilerInterval
|
||||
}
|
||||
|
||||
if c.ExtraConfig.MasterEndpointReconcileTTL == 0 {
|
||||
c.ExtraConfig.MasterEndpointReconcileTTL = DefaultEndpointReconcilerTTL
|
||||
}
|
||||
|
||||
if c.ExtraConfig.EndpointReconcilerConfig.Reconciler == nil {
|
||||
c.ExtraConfig.EndpointReconcilerConfig.Reconciler = cfg.createEndpointReconciler()
|
||||
}
|
||||
|
||||
// this has always been hardcoded true in the past
|
||||
c.GenericConfig.EnableMetrics = true
|
||||
|
||||
return CompletedConfig{&c}
|
||||
}
|
||||
|
||||
// New returns a new instance of Master from the given config.
|
||||
// Certain config fields will be set to a default value if unset.
|
||||
// Certain config fields must be specified, including:
|
||||
// KubeletClientConfig
|
||||
func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*Master, error) {
|
||||
if reflect.DeepEqual(c.ExtraConfig.KubeletClientConfig, kubeletclient.KubeletClientConfig{}) {
|
||||
return nil, fmt.Errorf("Master.New() called with empty config.KubeletClientConfig")
|
||||
}
|
||||
|
||||
s, err := c.GenericConfig.New("kube-apiserver", delegationTarget)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.ExtraConfig.EnableUISupport {
|
||||
routes.UIRedirect{}.Install(s.Handler.NonGoRestfulMux)
|
||||
}
|
||||
if c.ExtraConfig.EnableLogsSupport {
|
||||
routes.Logs{}.Install(s.Handler.GoRestfulContainer)
|
||||
}
|
||||
|
||||
m := &Master{
|
||||
GenericAPIServer: s,
|
||||
}
|
||||
|
||||
// install legacy rest storage
|
||||
if c.ExtraConfig.APIResourceConfigSource.AnyResourcesForVersionEnabled(apiv1.SchemeGroupVersion) {
|
||||
legacyRESTStorageProvider := corerest.LegacyRESTStorageProvider{
|
||||
StorageFactory: c.ExtraConfig.StorageFactory,
|
||||
ProxyTransport: c.ExtraConfig.ProxyTransport,
|
||||
KubeletClientConfig: c.ExtraConfig.KubeletClientConfig,
|
||||
EventTTL: c.ExtraConfig.EventTTL,
|
||||
ServiceIPRange: c.ExtraConfig.ServiceIPRange,
|
||||
ServiceNodePortRange: c.ExtraConfig.ServiceNodePortRange,
|
||||
LoopbackClientConfig: c.GenericConfig.LoopbackClientConfig,
|
||||
}
|
||||
m.InstallLegacyAPI(&c, c.GenericConfig.RESTOptionsGetter, legacyRESTStorageProvider)
|
||||
}
|
||||
|
||||
// The order here is preserved in discovery.
|
||||
// If resources with identical names exist in more than one of these groups (e.g. "deployments.apps"" and "deployments.extensions"),
|
||||
// the order of this list determines which group an unqualified resource name (e.g. "deployments") should prefer.
|
||||
// This priority order is used for local discovery, but it ends up aggregated in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go
|
||||
// with specific priorities.
|
||||
// TODO: describe the priority all the way down in the RESTStorageProviders and plumb it back through the various discovery
|
||||
// handlers that we have.
|
||||
restStorageProviders := []RESTStorageProvider{
|
||||
authenticationrest.RESTStorageProvider{Authenticator: c.GenericConfig.Authenticator},
|
||||
authorizationrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorizer, RuleResolver: c.GenericConfig.RuleResolver},
|
||||
autoscalingrest.RESTStorageProvider{},
|
||||
batchrest.RESTStorageProvider{},
|
||||
certificatesrest.RESTStorageProvider{},
|
||||
extensionsrest.RESTStorageProvider{},
|
||||
networkingrest.RESTStorageProvider{},
|
||||
policyrest.RESTStorageProvider{},
|
||||
rbacrest.RESTStorageProvider{Authorizer: c.GenericConfig.Authorizer},
|
||||
schedulingrest.RESTStorageProvider{},
|
||||
settingsrest.RESTStorageProvider{},
|
||||
storagerest.RESTStorageProvider{},
|
||||
// keep apps after extensions so legacy clients resolve the extensions versions of shared resource names.
|
||||
// See https://github.com/kubernetes/kubernetes/issues/42392
|
||||
appsrest.RESTStorageProvider{},
|
||||
admissionregistrationrest.RESTStorageProvider{},
|
||||
eventsrest.RESTStorageProvider{TTL: c.ExtraConfig.EventTTL},
|
||||
}
|
||||
m.InstallAPIs(c.ExtraConfig.APIResourceConfigSource, c.GenericConfig.RESTOptionsGetter, restStorageProviders...)
|
||||
|
||||
if c.ExtraConfig.Tunneler != nil {
|
||||
m.installTunneler(c.ExtraConfig.Tunneler, corev1client.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig).Nodes())
|
||||
}
|
||||
|
||||
m.GenericAPIServer.AddPostStartHookOrDie("ca-registration", c.ExtraConfig.ClientCARegistrationHook.PostStartHook)
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *Master) InstallLegacyAPI(c *completedConfig, restOptionsGetter generic.RESTOptionsGetter, legacyRESTStorageProvider corerest.LegacyRESTStorageProvider) {
|
||||
legacyRESTStorage, apiGroupInfo, err := legacyRESTStorageProvider.NewLegacyRESTStorage(restOptionsGetter)
|
||||
if err != nil {
|
||||
glog.Fatalf("Error building core storage: %v", err)
|
||||
}
|
||||
|
||||
if c.ExtraConfig.EnableCoreControllers {
|
||||
controllerName := "bootstrap-controller"
|
||||
coreClient := coreclient.NewForConfigOrDie(c.GenericConfig.LoopbackClientConfig)
|
||||
bootstrapController := c.NewBootstrapController(legacyRESTStorage, coreClient, coreClient, coreClient)
|
||||
m.GenericAPIServer.AddPostStartHookOrDie(controllerName, bootstrapController.PostStartHook)
|
||||
m.GenericAPIServer.AddPreShutdownHookOrDie(controllerName, bootstrapController.PreShutdownHook)
|
||||
}
|
||||
|
||||
if err := m.GenericAPIServer.InstallLegacyAPIGroup(genericapiserver.DefaultLegacyAPIPrefix, &apiGroupInfo); err != nil {
|
||||
glog.Fatalf("Error in registering group versions: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Master) installTunneler(nodeTunneler tunneler.Tunneler, nodeClient corev1client.NodeInterface) {
|
||||
nodeTunneler.Run(nodeAddressProvider{nodeClient}.externalAddresses)
|
||||
m.GenericAPIServer.AddHealthzChecks(healthz.NamedCheck("SSH Tunnel Check", tunneler.TunnelSyncHealthChecker(nodeTunneler)))
|
||||
prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
||||
Name: "apiserver_proxy_tunnel_sync_latency_secs",
|
||||
Help: "The time since the last successful synchronization of the SSH tunnels for proxy requests.",
|
||||
}, func() float64 { return float64(nodeTunneler.SecondsSinceSync()) })
|
||||
}
|
||||
|
||||
// RESTStorageProvider is a factory type for REST storage.
|
||||
type RESTStorageProvider interface {
|
||||
GroupName() string
|
||||
NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool)
|
||||
}
|
||||
|
||||
// InstallAPIs will install the APIs for the restStorageProviders if they are enabled.
|
||||
func (m *Master) InstallAPIs(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter, restStorageProviders ...RESTStorageProvider) {
|
||||
apiGroupsInfo := []genericapiserver.APIGroupInfo{}
|
||||
|
||||
for _, restStorageBuilder := range restStorageProviders {
|
||||
groupName := restStorageBuilder.GroupName()
|
||||
if !apiResourceConfigSource.AnyResourcesForGroupEnabled(groupName) {
|
||||
glog.V(1).Infof("Skipping disabled API group %q.", groupName)
|
||||
continue
|
||||
}
|
||||
apiGroupInfo, enabled := restStorageBuilder.NewRESTStorage(apiResourceConfigSource, restOptionsGetter)
|
||||
if !enabled {
|
||||
glog.Warningf("Problem initializing API group %q, skipping.", groupName)
|
||||
continue
|
||||
}
|
||||
glog.V(1).Infof("Enabling API group %q.", groupName)
|
||||
|
||||
if postHookProvider, ok := restStorageBuilder.(genericapiserver.PostStartHookProvider); ok {
|
||||
name, hook, err := postHookProvider.PostStartHook()
|
||||
if err != nil {
|
||||
glog.Fatalf("Error building PostStartHook: %v", err)
|
||||
}
|
||||
m.GenericAPIServer.AddPostStartHookOrDie(name, hook)
|
||||
}
|
||||
|
||||
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
||||
}
|
||||
|
||||
for i := range apiGroupsInfo {
|
||||
if err := m.GenericAPIServer.InstallAPIGroup(&apiGroupsInfo[i]); err != nil {
|
||||
glog.Fatalf("Error in registering group versions: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type nodeAddressProvider struct {
|
||||
nodeClient corev1client.NodeInterface
|
||||
}
|
||||
|
||||
func (n nodeAddressProvider) externalAddresses() ([]string, error) {
|
||||
preferredAddressTypes := []apiv1.NodeAddressType{
|
||||
apiv1.NodeExternalIP,
|
||||
}
|
||||
nodes, err := n.nodeClient.List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addrs := []string{}
|
||||
for ix := range nodes.Items {
|
||||
node := &nodes.Items[ix]
|
||||
addr, err := nodeutil.GetPreferredNodeAddress(node, preferredAddressTypes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addrs = append(addrs, addr)
|
||||
}
|
||||
return addrs, nil
|
||||
}
|
||||
|
||||
func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig {
|
||||
ret := serverstorage.NewResourceConfig()
|
||||
// NOTE: GroupVersions listed here will be enabled by default. Don't put alpha versions in the list.
|
||||
ret.EnableVersions(
|
||||
apiv1.SchemeGroupVersion,
|
||||
extensionsapiv1beta1.SchemeGroupVersion,
|
||||
batchapiv1.SchemeGroupVersion,
|
||||
batchapiv1beta1.SchemeGroupVersion,
|
||||
authenticationv1.SchemeGroupVersion,
|
||||
authenticationv1beta1.SchemeGroupVersion,
|
||||
autoscalingapiv1.SchemeGroupVersion,
|
||||
autoscalingapiv2beta1.SchemeGroupVersion,
|
||||
appsv1beta1.SchemeGroupVersion,
|
||||
appsv1beta2.SchemeGroupVersion,
|
||||
appsv1.SchemeGroupVersion,
|
||||
policyapiv1beta1.SchemeGroupVersion,
|
||||
rbacv1.SchemeGroupVersion,
|
||||
rbacv1beta1.SchemeGroupVersion,
|
||||
storageapiv1.SchemeGroupVersion,
|
||||
storageapiv1beta1.SchemeGroupVersion,
|
||||
certificatesapiv1beta1.SchemeGroupVersion,
|
||||
authorizationapiv1.SchemeGroupVersion,
|
||||
authorizationapiv1beta1.SchemeGroupVersion,
|
||||
networkingapiv1.SchemeGroupVersion,
|
||||
eventsv1beta1.SchemeGroupVersion,
|
||||
admissionregistrationv1beta1.SchemeGroupVersion,
|
||||
)
|
||||
|
||||
// all extensions resources except these are disabled by default
|
||||
ret.EnableResources(
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("networkpolicies"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"),
|
||||
extensionsapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies"),
|
||||
)
|
||||
|
||||
return ret
|
||||
}
|
||||
97
vendor/k8s.io/kubernetes/pkg/master/master_openapi_test.go
generated
vendored
Normal file
97
vendor/k8s.io/kubernetes/pkg/master/master_openapi_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// +build !race
|
||||
|
||||
/*
|
||||
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 master
|
||||
|
||||
// This test file is separated from master_test.go so we would be able to disable
|
||||
// race check for it. TestValidOpenAPISpec will became extremely slow if -race
|
||||
// flag exists, and will cause the tests to timeout.
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
openapigen "k8s.io/kubernetes/pkg/generated/openapi"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// TestValidOpenAPISpec verifies that the open api is added
|
||||
// at the proper endpoint and the spec is valid.
|
||||
func TestValidOpenAPISpec(t *testing.T) {
|
||||
etcdserver, config, sharedInformers, assert := setUp(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
config.GenericConfig.EnableIndex = true
|
||||
config.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapigen.GetOpenAPIDefinitions, legacyscheme.Scheme)
|
||||
config.GenericConfig.OpenAPIConfig.Info = &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Title: "Kubernetes",
|
||||
Version: "unversioned",
|
||||
},
|
||||
}
|
||||
config.GenericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig()
|
||||
|
||||
master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the master: %v", err)
|
||||
}
|
||||
|
||||
// make sure swagger.json is not registered before calling PrepareRun.
|
||||
server := httptest.NewServer(apirequest.WithRequestContext(master.GenericAPIServer.Handler.Director, master.GenericAPIServer.RequestContextMapper()))
|
||||
defer server.Close()
|
||||
resp, err := http.Get(server.URL + "/swagger.json")
|
||||
if !assert.NoError(err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
assert.Equal(http.StatusNotFound, resp.StatusCode)
|
||||
|
||||
master.GenericAPIServer.PrepareRun()
|
||||
|
||||
resp, err = http.Get(server.URL + "/swagger.json")
|
||||
if !assert.NoError(err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
assert.Equal(http.StatusOK, resp.StatusCode)
|
||||
|
||||
// as json schema
|
||||
var sch spec.Schema
|
||||
if assert.NoError(decodeResponse(resp, &sch)) {
|
||||
validator := validate.NewSchemaValidator(spec.MustLoadSwagger20Schema(), nil, "", strfmt.Default)
|
||||
res := validator.Validate(&sch)
|
||||
assert.NoError(res.AsError())
|
||||
}
|
||||
|
||||
// Validate OpenApi spec
|
||||
doc, err := loads.Spec(server.URL + "/swagger.json")
|
||||
if assert.NoError(err) {
|
||||
validator := validate.NewSpecValidator(doc.Schema(), strfmt.Default)
|
||||
res, warns := validator.Validate(doc)
|
||||
assert.NoError(res.AsError())
|
||||
if !warns.IsValid() {
|
||||
t.Logf("Open API spec on root has some warnings : %v", warns)
|
||||
}
|
||||
}
|
||||
}
|
||||
385
vendor/k8s.io/kubernetes/pkg/master/master_test.go
generated
vendored
Normal file
385
vendor/k8s.io/kubernetes/pkg/master/master_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
appsapiv1beta1 "k8s.io/api/apps/v1beta1"
|
||||
autoscalingapiv1 "k8s.io/api/autoscaling/v1"
|
||||
batchapiv1 "k8s.io/api/batch/v1"
|
||||
batchapiv1beta1 "k8s.io/api/batch/v1beta1"
|
||||
certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/options"
|
||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
||||
"k8s.io/kubernetes/pkg/master/reconcilers"
|
||||
certificatesrest "k8s.io/kubernetes/pkg/registry/certificates/rest"
|
||||
corerest "k8s.io/kubernetes/pkg/registry/core/rest"
|
||||
"k8s.io/kubernetes/pkg/registry/registrytest"
|
||||
kubeversion "k8s.io/kubernetes/pkg/version"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// setUp is a convience function for setting up for (most) tests.
|
||||
func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, informers.SharedInformerFactory, *assert.Assertions) {
|
||||
server, storageConfig := etcdtesting.NewUnsecuredEtcd3TestClientServer(t)
|
||||
|
||||
config := &Config{
|
||||
GenericConfig: genericapiserver.NewConfig(legacyscheme.Codecs),
|
||||
ExtraConfig: ExtraConfig{
|
||||
APIResourceConfigSource: DefaultAPIResourceConfigSource(),
|
||||
APIServerServicePort: 443,
|
||||
MasterCount: 1,
|
||||
EndpointReconcilerType: reconcilers.MasterCountReconcilerType,
|
||||
},
|
||||
}
|
||||
|
||||
resourceEncoding := serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Registry)
|
||||
resourceEncoding.SetVersionEncoding(api.GroupName, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, schema.GroupVersion{Group: api.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(autoscaling.GroupName, *testapi.Autoscaling.GroupVersion(), schema.GroupVersion{Group: autoscaling.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(batch.GroupName, *testapi.Batch.GroupVersion(), schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal})
|
||||
// FIXME (soltysh): this GroupVersionResource override should be configurable
|
||||
resourceEncoding.SetResourceEncoding(schema.GroupResource{Group: "batch", Resource: "cronjobs"}, schema.GroupVersion{Group: batch.GroupName, Version: "v1beta1"}, schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(apps.GroupName, *testapi.Apps.GroupVersion(), schema.GroupVersion{Group: apps.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(extensions.GroupName, *testapi.Extensions.GroupVersion(), schema.GroupVersion{Group: extensions.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(rbac.GroupName, *testapi.Rbac.GroupVersion(), schema.GroupVersion{Group: rbac.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(certificates.GroupName, *testapi.Certificates.GroupVersion(), schema.GroupVersion{Group: certificates.GroupName, Version: runtime.APIVersionInternal})
|
||||
storageFactory := serverstorage.NewDefaultStorageFactory(*storageConfig, testapi.StorageMediaType(), legacyscheme.Codecs, resourceEncoding, DefaultAPIResourceConfigSource(), nil)
|
||||
|
||||
err := options.NewEtcdOptions(storageConfig).ApplyWithStorageFactoryTo(storageFactory, config.GenericConfig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
kubeVersion := kubeversion.Get()
|
||||
config.GenericConfig.Version = &kubeVersion
|
||||
config.ExtraConfig.StorageFactory = storageFactory
|
||||
config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs}}
|
||||
config.GenericConfig.PublicAddress = net.ParseIP("192.168.10.4")
|
||||
config.GenericConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
|
||||
config.GenericConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper()
|
||||
config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs}}
|
||||
config.GenericConfig.EnableMetrics = true
|
||||
config.ExtraConfig.EnableCoreControllers = false
|
||||
config.ExtraConfig.KubeletClientConfig = kubeletclient.KubeletClientConfig{Port: 10250}
|
||||
config.ExtraConfig.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{
|
||||
Dial: func(network, addr string) (net.Conn, error) { return nil, nil },
|
||||
TLSClientConfig: &tls.Config{},
|
||||
})
|
||||
|
||||
clientset, err := kubernetes.NewForConfig(config.GenericConfig.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create client set due to %v", err)
|
||||
}
|
||||
sharedInformers := informers.NewSharedInformerFactory(clientset, config.GenericConfig.LoopbackClientConfig.Timeout)
|
||||
|
||||
return server, *config, sharedInformers, assert.New(t)
|
||||
}
|
||||
|
||||
// TestLegacyRestStorageStrategies ensures that all Storage objects which are using the generic registry Store have
|
||||
// their various strategies properly wired up. This surfaced as a bug where strategies defined Export functions, but
|
||||
// they were never used outside of unit tests because the export strategies were not assigned inside the Store.
|
||||
func TestLegacyRestStorageStrategies(t *testing.T) {
|
||||
_, etcdserver, masterCfg, _ := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
storageProvider := corerest.LegacyRESTStorageProvider{
|
||||
StorageFactory: masterCfg.ExtraConfig.StorageFactory,
|
||||
ProxyTransport: masterCfg.ExtraConfig.ProxyTransport,
|
||||
KubeletClientConfig: masterCfg.ExtraConfig.KubeletClientConfig,
|
||||
EventTTL: masterCfg.ExtraConfig.EventTTL,
|
||||
ServiceIPRange: masterCfg.ExtraConfig.ServiceIPRange,
|
||||
ServiceNodePortRange: masterCfg.ExtraConfig.ServiceNodePortRange,
|
||||
LoopbackClientConfig: masterCfg.GenericConfig.LoopbackClientConfig,
|
||||
}
|
||||
|
||||
_, apiGroupInfo, err := storageProvider.NewLegacyRESTStorage(masterCfg.GenericConfig.RESTOptionsGetter)
|
||||
if err != nil {
|
||||
t.Errorf("failed to create legacy REST storage: %v", err)
|
||||
}
|
||||
|
||||
// Any new stores with export logic will need to be added here:
|
||||
exceptions := registrytest.StrategyExceptions{
|
||||
// Only these stores should have an export strategy defined:
|
||||
HasExportStrategy: []string{
|
||||
"secrets",
|
||||
"limitRanges",
|
||||
"nodes",
|
||||
"podTemplates",
|
||||
},
|
||||
}
|
||||
|
||||
strategyErrors := registrytest.ValidateStorageStrategies(apiGroupInfo.VersionedResourcesStorageMap["v1"], exceptions)
|
||||
for _, err := range strategyErrors {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCertificatesRestStorageStrategies(t *testing.T) {
|
||||
_, etcdserver, masterCfg, _ := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
certStorageProvider := certificatesrest.RESTStorageProvider{}
|
||||
apiGroupInfo, _ := certStorageProvider.NewRESTStorage(masterCfg.ExtraConfig.APIResourceConfigSource, masterCfg.GenericConfig.RESTOptionsGetter)
|
||||
|
||||
exceptions := registrytest.StrategyExceptions{
|
||||
HasExportStrategy: []string{
|
||||
"certificatesigningrequests",
|
||||
},
|
||||
}
|
||||
|
||||
strategyErrors := registrytest.ValidateStorageStrategies(
|
||||
apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1beta1.SchemeGroupVersion.Version], exceptions)
|
||||
for _, err := range strategyErrors {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
|
||||
etcdserver, config, sharedInformers, assert := setUp(t)
|
||||
|
||||
master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the master: %v", err)
|
||||
}
|
||||
|
||||
return master, etcdserver, config, assert
|
||||
}
|
||||
|
||||
// limitedAPIResourceConfigSource only enables the core group, the extensions group, the batch group, and the autoscaling group.
|
||||
func limitedAPIResourceConfigSource() *serverstorage.ResourceConfig {
|
||||
ret := serverstorage.NewResourceConfig()
|
||||
ret.EnableVersions(
|
||||
apiv1.SchemeGroupVersion,
|
||||
extensionsapiv1beta1.SchemeGroupVersion,
|
||||
batchapiv1.SchemeGroupVersion,
|
||||
batchapiv1beta1.SchemeGroupVersion,
|
||||
appsapiv1beta1.SchemeGroupVersion,
|
||||
autoscalingapiv1.SchemeGroupVersion,
|
||||
)
|
||||
return ret
|
||||
}
|
||||
|
||||
// newLimitedMaster only enables the core group, the extensions group, the batch group, and the autoscaling group.
|
||||
func newLimitedMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
|
||||
etcdserver, config, sharedInformers, assert := setUp(t)
|
||||
config.ExtraConfig.APIResourceConfigSource = limitedAPIResourceConfigSource()
|
||||
master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the master: %v", err)
|
||||
}
|
||||
|
||||
return master, etcdserver, config, assert
|
||||
}
|
||||
|
||||
// TestVersion tests /version
|
||||
func TestVersion(t *testing.T) {
|
||||
s, etcdserver, _, _ := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/version", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
s.GenericAPIServer.Handler.ServeHTTP(resp, req)
|
||||
if resp.Code != 200 {
|
||||
t.Fatalf("expected http 200, got: %d", resp.Code)
|
||||
}
|
||||
|
||||
var info version.Info
|
||||
err := json.NewDecoder(resp.Body).Decode(&info)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(kubeversion.Get(), info) {
|
||||
t.Errorf("Expected %#v, Got %#v", kubeversion.Get(), info)
|
||||
}
|
||||
}
|
||||
|
||||
type fakeEndpointReconciler struct{}
|
||||
|
||||
func (*fakeEndpointReconciler) ReconcileEndpoints(serviceName string, ip net.IP, endpointPorts []api.EndpointPort, reconcilePorts bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeNodeList(nodes []string, nodeResources apiv1.NodeResources) *apiv1.NodeList {
|
||||
list := apiv1.NodeList{
|
||||
Items: make([]apiv1.Node, len(nodes)),
|
||||
}
|
||||
for i := range nodes {
|
||||
list.Items[i].Name = nodes[i]
|
||||
list.Items[i].Status.Capacity = nodeResources.Capacity
|
||||
}
|
||||
return &list
|
||||
}
|
||||
|
||||
// TestGetNodeAddresses verifies that proper results are returned
|
||||
// when requesting node addresses.
|
||||
func TestGetNodeAddresses(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
fakeNodeClient := fake.NewSimpleClientset(makeNodeList([]string{"node1", "node2"}, apiv1.NodeResources{})).Core().Nodes()
|
||||
addressProvider := nodeAddressProvider{fakeNodeClient}
|
||||
|
||||
// Fail case (no addresses associated with nodes)
|
||||
nodes, _ := fakeNodeClient.List(metav1.ListOptions{})
|
||||
addrs, err := addressProvider.externalAddresses()
|
||||
|
||||
assert.Error(err, "addresses should have caused an error as there are no addresses.")
|
||||
assert.Equal([]string(nil), addrs)
|
||||
|
||||
// Pass case with External type IP
|
||||
nodes, _ = fakeNodeClient.List(metav1.ListOptions{})
|
||||
for index := range nodes.Items {
|
||||
nodes.Items[index].Status.Addresses = []apiv1.NodeAddress{{Type: apiv1.NodeExternalIP, Address: "127.0.0.1"}}
|
||||
fakeNodeClient.Update(&nodes.Items[index])
|
||||
}
|
||||
addrs, err = addressProvider.externalAddresses()
|
||||
assert.NoError(err, "addresses should not have returned an error.")
|
||||
assert.Equal([]string{"127.0.0.1", "127.0.0.1"}, addrs)
|
||||
}
|
||||
|
||||
func decodeResponse(resp *http.Response, obj interface{}) error {
|
||||
defer resp.Body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(data, obj); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Because we need to be backwards compatible with release 1.1, at endpoints
|
||||
// that exist in release 1.1, the responses should have empty APIVersion.
|
||||
func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) {
|
||||
master, etcdserver, _, assert := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
server := httptest.NewServer(genericapirequest.WithRequestContext(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux, master.GenericAPIServer.RequestContextMapper()))
|
||||
|
||||
// /api exists in release-1.1
|
||||
resp, err := http.Get(server.URL + "/api")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
apiVersions := metav1.APIVersions{}
|
||||
assert.NoError(decodeResponse(resp, &apiVersions))
|
||||
assert.Equal(apiVersions.APIVersion, "")
|
||||
|
||||
// /api/v1 exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/api/v1")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
resourceList := metav1.APIResourceList{}
|
||||
assert.NoError(decodeResponse(resp, &resourceList))
|
||||
assert.Equal(resourceList.APIVersion, "")
|
||||
|
||||
// /apis exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/apis")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
groupList := metav1.APIGroupList{}
|
||||
assert.NoError(decodeResponse(resp, &groupList))
|
||||
assert.Equal(groupList.APIVersion, "")
|
||||
|
||||
// /apis/extensions exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/apis/extensions")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
group := metav1.APIGroup{}
|
||||
assert.NoError(decodeResponse(resp, &group))
|
||||
assert.Equal(group.APIVersion, "")
|
||||
|
||||
// /apis/extensions/v1beta1 exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/apis/extensions/v1beta1")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
resourceList = metav1.APIResourceList{}
|
||||
assert.NoError(decodeResponse(resp, &resourceList))
|
||||
assert.Equal(resourceList.APIVersion, "")
|
||||
|
||||
// /apis/autoscaling doesn't exist in release-1.1, so the APIVersion field
|
||||
// should be non-empty in the results returned by the server.
|
||||
resp, err = http.Get(server.URL + "/apis/autoscaling")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
group = metav1.APIGroup{}
|
||||
assert.NoError(decodeResponse(resp, &group))
|
||||
assert.Equal(group.APIVersion, "v1")
|
||||
|
||||
// apis/autoscaling/v1 doesn't exist in release-1.1, so the APIVersion field
|
||||
// should be non-empty in the results returned by the server.
|
||||
|
||||
resp, err = http.Get(server.URL + "/apis/autoscaling/v1")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
resourceList = metav1.APIResourceList{}
|
||||
assert.NoError(decodeResponse(resp, &resourceList))
|
||||
assert.Equal(resourceList.APIVersion, "v1")
|
||||
|
||||
}
|
||||
|
||||
func TestNoAlphaVersionsEnabledByDefault(t *testing.T) {
|
||||
config := DefaultAPIResourceConfigSource()
|
||||
for gv, gvConfig := range config.GroupVersionResourceConfigs {
|
||||
if gvConfig.Enable && strings.Contains(gv.Version, "alpha") {
|
||||
t.Errorf("Alpha API version %s enabled by default", gv.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
28
vendor/k8s.io/kubernetes/pkg/master/ports/BUILD
generated
vendored
Normal file
28
vendor/k8s.io/kubernetes/pkg/master/ports/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"ports.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/master/ports",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
19
vendor/k8s.io/kubernetes/pkg/master/ports/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/master/ports/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 ports defines ports used by various pieces of the kubernetes
|
||||
// infrastructure.
|
||||
package ports // import "k8s.io/kubernetes/pkg/master/ports"
|
||||
44
vendor/k8s.io/kubernetes/pkg/master/ports/ports.go
generated
vendored
Normal file
44
vendor/k8s.io/kubernetes/pkg/master/ports/ports.go
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
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 ports
|
||||
|
||||
const (
|
||||
// ProxyStatusPort is the default port for the proxy metrics server.
|
||||
// May be overridden by a flag at startup.
|
||||
ProxyStatusPort = 10249
|
||||
// KubeletPort is the default port for the kubelet server on each host machine.
|
||||
// May be overridden by a flag at startup.
|
||||
KubeletPort = 10250
|
||||
// SchedulerPort is the default port for the scheduler status server.
|
||||
// May be overridden by a flag at startup.
|
||||
SchedulerPort = 10251
|
||||
// ControllerManagerPort is the default port for the controller manager status server.
|
||||
// May be overridden by a flag at startup.
|
||||
ControllerManagerPort = 10252
|
||||
// CloudControllerManagerPort is the default port for the cloud controller manager server.
|
||||
// This value may be overriden by a flag at startup.
|
||||
CloudControllerManagerPort = 10253
|
||||
// KubeletReadOnlyPort exposes basic read-only services from the kubelet.
|
||||
// May be overridden by a flag at startup.
|
||||
// This is necessary for heapster to collect monitoring stats from the kubelet
|
||||
// until heapster can transition to using the SSL endpoint.
|
||||
// TODO(roberthbailey): Remove this once we have a better solution for heapster.
|
||||
KubeletReadOnlyPort = 10255
|
||||
// ProxyHealthzPort is the default port for the proxy healthz server.
|
||||
// May be overridden by a flag at startup.
|
||||
ProxyHealthzPort = 10256
|
||||
)
|
||||
54
vendor/k8s.io/kubernetes/pkg/master/services.go
generated
vendored
Normal file
54
vendor/k8s.io/kubernetes/pkg/master/services.go
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
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 master
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||
)
|
||||
|
||||
// DefaultServiceIPRange takes a the serviceIPRange flag and returns the defaulted service ip range (if needed),
|
||||
// api server service IP, and an error
|
||||
// TODO move this out of the genericapiserver package
|
||||
func DefaultServiceIPRange(passedServiceClusterIPRange net.IPNet) (net.IPNet, net.IP, error) {
|
||||
serviceClusterIPRange := passedServiceClusterIPRange
|
||||
if passedServiceClusterIPRange.IP == nil {
|
||||
defaultNet := "10.0.0.0/24"
|
||||
glog.Infof("Network range for service cluster IPs is unspecified. Defaulting to %v.", defaultNet)
|
||||
_, defaultServiceClusterIPRange, err := net.ParseCIDR(defaultNet)
|
||||
if err != nil {
|
||||
return net.IPNet{}, net.IP{}, err
|
||||
}
|
||||
serviceClusterIPRange = *defaultServiceClusterIPRange
|
||||
}
|
||||
if size := ipallocator.RangeSize(&serviceClusterIPRange); size < 8 {
|
||||
return net.IPNet{}, net.IP{}, fmt.Errorf("The service cluster IP range must be at least %d IP addresses", 8)
|
||||
}
|
||||
|
||||
// Select the first valid IP from ServiceClusterIPRange to use as the GenericAPIServer service IP.
|
||||
apiServerServiceIP, err := ipallocator.GetIndexedIP(&serviceClusterIPRange, 1)
|
||||
if err != nil {
|
||||
return net.IPNet{}, net.IP{}, err
|
||||
}
|
||||
glog.V(4).Infof("Setting service IP to %q (read-write).", apiServerServiceIP)
|
||||
|
||||
return serviceClusterIPRange, apiServerServiceIP, nil
|
||||
}
|
||||
37
vendor/k8s.io/kubernetes/pkg/security/apparmor/BUILD
generated
vendored
37
vendor/k8s.io/kubernetes/pkg/security/apparmor/BUILD
generated
vendored
|
|
@ -11,8 +11,39 @@ go_library(
|
|||
srcs = [
|
||||
"helpers.go",
|
||||
"validate.go",
|
||||
"validate_disabled.go",
|
||||
],
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"validate_disabled.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
importpath = "k8s.io/kubernetes/pkg/security/apparmor",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
|
|
@ -29,8 +60,8 @@ go_test(
|
|||
data = [
|
||||
"testdata/profiles",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/security/apparmor",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/serviceaccount/jwt.go
generated
vendored
|
|
@ -194,7 +194,7 @@ func (j *jwtTokenAuthenticator) AuthenticateToken(token string) (user.Info, bool
|
|||
return nil, false, errors.New("namespace claim is missing")
|
||||
}
|
||||
secretName, _ := claims[SecretNameClaim].(string)
|
||||
if len(namespace) == 0 {
|
||||
if len(secretName) == 0 {
|
||||
return nil, false, errors.New("secretName claim is missing")
|
||||
}
|
||||
serviceAccountName, _ := claims[ServiceAccountNameClaim].(string)
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/util/file/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/util/file/BUILD
generated
vendored
|
|
@ -28,8 +28,8 @@ filegroup(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["file_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/util/file",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/github.com/spf13/afero:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/util/hash/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/util/hash/BUILD
generated
vendored
|
|
@ -16,8 +16,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["hash_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/util/hash",
|
||||
library = ":go_default_library",
|
||||
deps = ["//vendor/github.com/davecgh/go-spew/spew:go_default_library"],
|
||||
)
|
||||
|
||||
|
|
|
|||
66
vendor/k8s.io/kubernetes/pkg/util/mount/BUILD
generated
vendored
66
vendor/k8s.io/kubernetes/pkg/util/mount/BUILD
generated
vendored
|
|
@ -11,19 +11,63 @@ go_library(
|
|||
srcs = [
|
||||
"doc.go",
|
||||
"exec.go",
|
||||
"exec_mount_unsupported.go",
|
||||
"fake.go",
|
||||
"mount.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"exec_mount.go",
|
||||
"mount_linux.go",
|
||||
"nsenter_mount.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_unsupported.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"exec_mount_unsupported.go",
|
||||
"mount_windows.go",
|
||||
"nsenter_mount_unsupported.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
|
|
@ -32,7 +76,7 @@ go_library(
|
|||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//pkg/util/io:go_default_library",
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
|
|
@ -47,19 +91,21 @@ go_test(
|
|||
srcs = [
|
||||
"safe_format_and_mount_test.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"exec_mount_test.go",
|
||||
"mount_linux_test.go",
|
||||
"nsenter_mount_test.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"mount_windows_test.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/util/mount",
|
||||
library = ":go_default_library",
|
||||
deps = ["//vendor/k8s.io/utils/exec/testing:go_default_library"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/util/net/sets/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/util/net/sets/BUILD
generated
vendored
|
|
@ -18,8 +18,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["ipnet_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/util/net/sets",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
|||
73
vendor/k8s.io/kubernetes/pkg/util/nsenter/BUILD
generated
vendored
73
vendor/k8s.io/kubernetes/pkg/util/nsenter/BUILD
generated
vendored
|
|
@ -2,21 +2,78 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"nsenter_unsupported.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
srcs = select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"nsenter.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"nsenter_unsupported.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
importpath = "k8s.io/kubernetes/pkg/util/nsenter",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
deps = select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/util/parsers/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/util/parsers/BUILD
generated
vendored
|
|
@ -16,8 +16,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["parsers_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/util/parsers",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/util/pointer/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/util/pointer/BUILD
generated
vendored
|
|
@ -9,8 +9,8 @@ load(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["pointer_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/util/pointer",
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
|
|
|
|||
2
vendor/k8s.io/kubernetes/pkg/util/taints/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/util/taints/BUILD
generated
vendored
|
|
@ -23,8 +23,8 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["taints_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/util/taints",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
|
|
|
|||
39
vendor/k8s.io/kubernetes/pkg/volume/BUILD
generated
vendored
39
vendor/k8s.io/kubernetes/pkg/volume/BUILD
generated
vendored
|
|
@ -18,11 +18,40 @@ go_library(
|
|||
"plugins.go",
|
||||
"util.go",
|
||||
"volume.go",
|
||||
"volume_unsupported.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"volume_linux.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"volume_unsupported.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
importpath = "k8s.io/kubernetes/pkg/volume",
|
||||
|
|
@ -53,8 +82,8 @@ go_test(
|
|||
"plugins_test.go",
|
||||
"util_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/util/slice:go_default_library",
|
||||
|
|
@ -73,7 +102,7 @@ go_test(
|
|||
srcs = [
|
||||
"metrics_statfs_test.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"metrics_du_test.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
|
|
@ -84,7 +113,7 @@ go_test(
|
|||
"//pkg/volume/testing:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/testing:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
|
|
|
|||
29
vendor/k8s.io/kubernetes/pkg/volume/util.go
generated
vendored
29
vendor/k8s.io/kubernetes/pkg/volume/util.go
generated
vendored
|
|
@ -38,6 +38,13 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
const (
|
||||
// GB - GigaByte size
|
||||
GB = 1000 * 1000 * 1000
|
||||
// GIB - GibiByte size
|
||||
GIB = 1024 * 1024 * 1024
|
||||
)
|
||||
|
||||
type RecycleEventRecorder func(eventtype, message string)
|
||||
|
||||
// RecycleVolumeByWatchingPodUntilCompletion is intended for use with volume
|
||||
|
|
@ -87,9 +94,8 @@ func internalRecycleVolumeByWatchingPodUntilCompletion(pvName string, pod *v1.Po
|
|||
// Recycler will try again and the old pod will be hopefuly deleted
|
||||
// at that time.
|
||||
return fmt.Errorf("old recycler pod found, will retry later")
|
||||
} else {
|
||||
return fmt.Errorf("unexpected error creating recycler pod: %+v\n", err)
|
||||
}
|
||||
return fmt.Errorf("unexpected error creating recycler pod: %+v", err)
|
||||
}
|
||||
err = waitForPod(pod, recyclerClient, podCh)
|
||||
|
||||
|
|
@ -274,9 +280,8 @@ func CalculateTimeoutForVolume(minimumTimeout, timeoutIncrement int, pv *v1.Pers
|
|||
timeout := (pvSize / giSize) * int64(timeoutIncrement)
|
||||
if timeout < int64(minimumTimeout) {
|
||||
return int64(minimumTimeout)
|
||||
} else {
|
||||
return timeout
|
||||
}
|
||||
return timeout
|
||||
}
|
||||
|
||||
// RoundUpSize calculates how many allocation units are needed to accommodate
|
||||
|
|
@ -288,6 +293,18 @@ func RoundUpSize(volumeSizeBytes int64, allocationUnitBytes int64) int64 {
|
|||
return (volumeSizeBytes + allocationUnitBytes - 1) / allocationUnitBytes
|
||||
}
|
||||
|
||||
// RoundUpToGB rounds up given quantity to chunks of GB
|
||||
func RoundUpToGB(size resource.Quantity) int64 {
|
||||
requestBytes := size.Value()
|
||||
return RoundUpSize(requestBytes, GB)
|
||||
}
|
||||
|
||||
// RoundUpToGiB rounds up given quantity upto chunks of GiB
|
||||
func RoundUpToGiB(size resource.Quantity) int64 {
|
||||
requestBytes := size.Value()
|
||||
return RoundUpSize(requestBytes, GIB)
|
||||
}
|
||||
|
||||
// GenerateVolumeName returns a PV name with clusterName prefix. The function
|
||||
// should be used to generate a name of GCE PD or Cinder volume. It basically
|
||||
// adds "<clusterName>-dynamic-" before the PV name, making sure the resulting
|
||||
|
|
@ -304,7 +321,7 @@ func GenerateVolumeName(clusterName, pvName string, maxLength int) string {
|
|||
return prefix + "-" + pvName
|
||||
}
|
||||
|
||||
// Check if the path from the mounter is empty.
|
||||
// GetPath checks if the path from the mounter is empty.
|
||||
func GetPath(mounter Mounter) (string, error) {
|
||||
path := mounter.GetPath()
|
||||
if path == "" {
|
||||
|
|
@ -313,7 +330,7 @@ func GetPath(mounter Mounter) (string, error) {
|
|||
return path, nil
|
||||
}
|
||||
|
||||
// ChooseZone implements our heuristics for choosing a zone for volume creation based on the volume name
|
||||
// ChooseZoneForVolume implements our heuristics for choosing a zone for volume creation based on the volume name
|
||||
// Volumes are generally round-robin-ed across all active zones, using the hash of the PVC Name.
|
||||
// However, if the PVCName ends with `-<integer>`, we will hash the prefix, and then add the integer to the hash.
|
||||
// This means that a StatefulSet's volumes (`claimname-statefulsetname-id`) will spread across available zones,
|
||||
|
|
|
|||
100
vendor/k8s.io/kubernetes/pkg/volume/util/BUILD
generated
vendored
100
vendor/k8s.io/kubernetes/pkg/volume/util/BUILD
generated
vendored
|
|
@ -11,24 +11,68 @@ go_library(
|
|||
srcs = [
|
||||
"atomic_writer.go",
|
||||
"device_util.go",
|
||||
"device_util_unsupported.go",
|
||||
"doc.go",
|
||||
"error.go",
|
||||
"finalizer.go",
|
||||
"fs_unsupported.go",
|
||||
"io_util.go",
|
||||
"metrics.go",
|
||||
"util.go",
|
||||
"util_unsupported.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:darwin_amd64": [
|
||||
"fs.go",
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"device_util_unsupported.go",
|
||||
"fs_unsupported.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"device_util_unsupported.go",
|
||||
"fs.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"device_util_unsupported.go",
|
||||
"fs_unsupported.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"device_util_unsupported.go",
|
||||
"fs_unsupported.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"device_util_linux.go",
|
||||
"fs.go",
|
||||
"util_linux.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"device_util_unsupported.go",
|
||||
"fs_unsupported.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"device_util_unsupported.go",
|
||||
"fs_unsupported.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"device_util_unsupported.go",
|
||||
"fs_unsupported.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"device_util_unsupported.go",
|
||||
"fs_unsupported.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"device_util_unsupported.go",
|
||||
"fs_unsupported.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"device_util_unsupported.go",
|
||||
"fs_unsupported.go",
|
||||
"util_unsupported.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/util",
|
||||
|
|
@ -41,7 +85,6 @@ go_library(
|
|||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/storage/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/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
|
|
@ -49,11 +92,40 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:darwin_amd64": [
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
|
|
@ -62,26 +134,24 @@ go_library(
|
|||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"finalizer_test.go",
|
||||
"util_test.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"atomic_writer_test.go",
|
||||
"device_util_linux_test.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
embed = [":go_default_library"],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/util",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/apis/core/install:go_default_library",
|
||||
"//pkg/apis/core/v1/helper: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",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/k8s.io/client-go/util/testing:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
|
|
|
|||
1
vendor/k8s.io/kubernetes/pkg/volume/util/device_util.go
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/volume/util/device_util.go
generated
vendored
|
|
@ -19,6 +19,7 @@ package util
|
|||
//DeviceUtil is a util for common device methods
|
||||
type DeviceUtil interface {
|
||||
FindMultipathDeviceForDevice(disk string) string
|
||||
FindSlaveDevicesOnMultipath(disk string) []string
|
||||
}
|
||||
|
||||
type deviceHandler struct {
|
||||
|
|
|
|||
21
vendor/k8s.io/kubernetes/pkg/volume/util/device_util_linux.go
generated
vendored
21
vendor/k8s.io/kubernetes/pkg/volume/util/device_util_linux.go
generated
vendored
|
|
@ -20,6 +20,7 @@ package util
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -59,3 +60,23 @@ func findDeviceForPath(path string, io IoUtil) (string, error) {
|
|||
}
|
||||
return "", errors.New("Illegal path for device " + devicePath)
|
||||
}
|
||||
|
||||
// FindSlaveDevicesOnMultipath given a dm name like /dev/dm-1, find all devices
|
||||
// which are managed by the devicemapper dm-1.
|
||||
func (handler *deviceHandler) FindSlaveDevicesOnMultipath(dm string) []string {
|
||||
var devices []string
|
||||
io := handler.get_io
|
||||
// Split path /dev/dm-1 into "", "dev", "dm-1"
|
||||
parts := strings.Split(dm, "/")
|
||||
if len(parts) != 3 || !strings.HasPrefix(parts[1], "dev") {
|
||||
return devices
|
||||
}
|
||||
disk := parts[2]
|
||||
slavesPath := path.Join("/sys/block/", disk, "/slaves/")
|
||||
if files, err := io.ReadDir(slavesPath); err == nil {
|
||||
for _, f := range files {
|
||||
devices = append(devices, path.Join("/dev/", f.Name()))
|
||||
}
|
||||
}
|
||||
return devices
|
||||
}
|
||||
|
|
|
|||
24
vendor/k8s.io/kubernetes/pkg/volume/util/device_util_linux_test.go
generated
vendored
24
vendor/k8s.io/kubernetes/pkg/volume/util/device_util_linux_test.go
generated
vendored
|
|
@ -21,6 +21,7 @@ package util
|
|||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -29,11 +30,14 @@ type mockOsIOHandler struct{}
|
|||
|
||||
func (handler *mockOsIOHandler) ReadDir(dirname string) ([]os.FileInfo, error) {
|
||||
switch dirname {
|
||||
case "/sys/block/dm-2/slaves/":
|
||||
f := &fakeFileInfo{
|
||||
case "/sys/block/dm-1/slaves":
|
||||
f1 := &fakeFileInfo{
|
||||
name: "sda",
|
||||
}
|
||||
return []os.FileInfo{f}, nil
|
||||
f2 := &fakeFileInfo{
|
||||
name: "sdb",
|
||||
}
|
||||
return []os.FileInfo{f1, f2}, nil
|
||||
case "/sys/block/":
|
||||
f1 := &fakeFileInfo{
|
||||
name: "sda",
|
||||
|
|
@ -62,8 +66,10 @@ func (handler *mockOsIOHandler) EvalSymlinks(path string) (string, error) {
|
|||
"/returns/a/dev": "/dev/sde",
|
||||
"/returns/non/dev": "/sys/block",
|
||||
"/dev/disk/by-path/127.0.0.1:3260-eui.02004567A425678D-lun-0": "/dev/sda",
|
||||
"/dev/disk/by-path/127.0.0.3:3260-eui.03004567A425678D-lun-0": "/dev/sdb",
|
||||
"/dev/dm-2": "/dev/dm-2",
|
||||
"/dev/dm-3": "/dev/dm-3",
|
||||
"/dev/sdc": "/dev/sdc",
|
||||
"/dev/sde": "/dev/sde",
|
||||
}
|
||||
return links[path], nil
|
||||
|
|
@ -140,3 +146,15 @@ func TestFindDeviceForPath(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFindSlaveDevicesOnMultipath(t *testing.T) {
|
||||
mockDeviceUtil := NewDeviceHandler(&mockOsIOHandler{})
|
||||
devices := mockDeviceUtil.FindSlaveDevicesOnMultipath("/dev/dm-1")
|
||||
if !reflect.DeepEqual(devices, []string{"/dev/sda", "/dev/sdb"}) {
|
||||
t.Fatalf("failed to find devices managed by mpio device. /dev/sda, /dev/sdb expected got [%s]", devices)
|
||||
}
|
||||
dev := mockDeviceUtil.FindSlaveDevicesOnMultipath("/dev/sdc")
|
||||
if len(dev) != 0 {
|
||||
t.Fatalf("mpio device not found '' expected got [%s]", dev)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
vendor/k8s.io/kubernetes/pkg/volume/util/device_util_unsupported.go
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/volume/util/device_util_unsupported.go
generated
vendored
|
|
@ -22,3 +22,9 @@ package util
|
|||
func (handler *deviceHandler) FindMultipathDeviceForDevice(device string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// FindSlaveDevicesOnMultipath unsupported returns ""
|
||||
func (handler *deviceHandler) FindSlaveDevicesOnMultipath(disk string) []string {
|
||||
out := []string{}
|
||||
return out
|
||||
}
|
||||
|
|
|
|||
46
vendor/k8s.io/kubernetes/pkg/volume/util/finalizer.go
generated
vendored
46
vendor/k8s.io/kubernetes/pkg/volume/util/finalizer.go
generated
vendored
|
|
@ -16,53 +16,7 @@ limitations under the License.
|
|||
|
||||
package util
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
// Name of finalizer on PVCs that have a running pod.
|
||||
PVCProtectionFinalizer = "kubernetes.io/pvc-protection"
|
||||
)
|
||||
|
||||
// IsPVCBeingDeleted returns:
|
||||
// true: in case PVC is being deleted, i.e. ObjectMeta.DeletionTimestamp is set
|
||||
// false: in case PVC is not being deleted, i.e. ObjectMeta.DeletionTimestamp is nil
|
||||
func IsPVCBeingDeleted(pvc *v1.PersistentVolumeClaim) bool {
|
||||
return pvc.ObjectMeta.DeletionTimestamp != nil
|
||||
}
|
||||
|
||||
// IsProtectionFinalizerPresent returns true in case PVCProtectionFinalizer is
|
||||
// present among the pvc.Finalizers
|
||||
func IsProtectionFinalizerPresent(pvc *v1.PersistentVolumeClaim) bool {
|
||||
for _, finalizer := range pvc.Finalizers {
|
||||
if finalizer == PVCProtectionFinalizer {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RemoveProtectionFinalizer returns pvc without PVCProtectionFinalizer in case
|
||||
// it's present in pvc.Finalizers. It expects that pvc is writable (i.e. is not
|
||||
// informer's cached copy.)
|
||||
func RemoveProtectionFinalizer(pvc *v1.PersistentVolumeClaim) {
|
||||
newFinalizers := make([]string, 0)
|
||||
for _, finalizer := range pvc.Finalizers {
|
||||
if finalizer != PVCProtectionFinalizer {
|
||||
newFinalizers = append(newFinalizers, finalizer)
|
||||
}
|
||||
}
|
||||
if len(newFinalizers) == 0 {
|
||||
// Sanitize for unit tests so we don't need to distinguish empty array
|
||||
// and nil.
|
||||
newFinalizers = nil
|
||||
}
|
||||
pvc.Finalizers = newFinalizers
|
||||
}
|
||||
|
||||
// AddProtectionFinalizer adds PVCProtectionFinalizer to pvc. It expects that
|
||||
// pvc is writable (i.e. is not informer's cached copy.)
|
||||
func AddProtectionFinalizer(pvc *v1.PersistentVolumeClaim) {
|
||||
pvc.Finalizers = append(pvc.Finalizers, PVCProtectionFinalizer)
|
||||
}
|
||||
|
|
|
|||
231
vendor/k8s.io/kubernetes/pkg/volume/util/finalizer_test.go
generated
vendored
231
vendor/k8s.io/kubernetes/pkg/volume/util/finalizer_test.go
generated
vendored
|
|
@ -1,231 +0,0 @@
|
|||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
arbitraryTime = metav1.Date(2017, 11, 1, 14, 28, 47, 0, time.FixedZone("CET", 0))
|
||||
)
|
||||
|
||||
func TestIsPVCBeingDeleted(t *testing.T) {
|
||||
tests := []struct {
|
||||
pvc *v1.PersistentVolumeClaim
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
pvc: &v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
DeletionTimestamp: nil,
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
pvc: &v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
DeletionTimestamp: &arbitraryTime,
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := IsPVCBeingDeleted(tt.pvc); got != tt.want {
|
||||
t.Errorf("IsPVCBeingDeleted(%v) = %v WANT %v", tt.pvc, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddProtectionFinalizer(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pvc *v1.PersistentVolumeClaim
|
||||
want *v1.PersistentVolumeClaim
|
||||
}{
|
||||
{
|
||||
"PVC without finalizer",
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
},
|
||||
},
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{PVCProtectionFinalizer},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"PVC with some finalizers",
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{"1", "2", "3", PVCProtectionFinalizer + "suffix", "prefix" + PVCProtectionFinalizer},
|
||||
},
|
||||
},
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{"1", "2", "3", PVCProtectionFinalizer + "suffix", "prefix" + PVCProtectionFinalizer, PVCProtectionFinalizer},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
got := test.pvc.DeepCopy()
|
||||
AddProtectionFinalizer(got)
|
||||
if !reflect.DeepEqual(got, test.want) {
|
||||
t.Errorf("Test %q: expected:\n%s\n\ngot:\n%s", test.name, spew.Sdump(test.want), spew.Sdump(got))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveProtectionFinalizer(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pvc *v1.PersistentVolumeClaim
|
||||
want *v1.PersistentVolumeClaim
|
||||
}{
|
||||
{
|
||||
"PVC without finalizer",
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
},
|
||||
},
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"PVC with finalizer",
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{PVCProtectionFinalizer},
|
||||
},
|
||||
},
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"PVC with many finalizers",
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{"1", "2", "3", PVCProtectionFinalizer + "suffix", "prefix" + PVCProtectionFinalizer, PVCProtectionFinalizer},
|
||||
},
|
||||
},
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{"1", "2", "3", PVCProtectionFinalizer + "suffix", "prefix" + PVCProtectionFinalizer},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
got := test.pvc.DeepCopy()
|
||||
RemoveProtectionFinalizer(got)
|
||||
if !reflect.DeepEqual(got, test.want) {
|
||||
t.Errorf("Test %q: expected:\n%s\n\ngot:\n%s", test.name, spew.Sdump(test.want), spew.Sdump(got))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsProtectionFinalizerPresent(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pvc *v1.PersistentVolumeClaim
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
"PVC without finalizer",
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"PVC with many unrelated finalizers",
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{"1", "2", "3", PVCProtectionFinalizer + "suffix", "prefix" + PVCProtectionFinalizer},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"PVC with many finalizers",
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{"1", "2", "3", PVCProtectionFinalizer + "suffix", "prefix" + PVCProtectionFinalizer, PVCProtectionFinalizer},
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"PVC with finalizer",
|
||||
&v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pvc",
|
||||
Namespace: "ns",
|
||||
Finalizers: []string{PVCProtectionFinalizer},
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
got := IsProtectionFinalizerPresent(test.pvc)
|
||||
if got != test.want {
|
||||
t.Errorf("Test %q: expected %v, got %v", test.name, test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
6
vendor/k8s.io/kubernetes/pkg/volume/util/metrics.go
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/volume/util/metrics.go
generated
vendored
|
|
@ -49,12 +49,12 @@ func registerMetrics() {
|
|||
}
|
||||
|
||||
// OperationCompleteHook returns a hook to call when an operation is completed
|
||||
func OperationCompleteHook(plugin, operationName string) func(error) {
|
||||
func OperationCompleteHook(plugin, operationName string) func(*error) {
|
||||
requestTime := time.Now()
|
||||
opComplete := func(err error) {
|
||||
opComplete := func(err *error) {
|
||||
timeTaken := time.Since(requestTime).Seconds()
|
||||
// Create metric with operation name and plugin name
|
||||
if err != nil {
|
||||
if *err != nil {
|
||||
storageOperationErrorMetric.WithLabelValues(plugin, operationName).Inc()
|
||||
} else {
|
||||
storageOperationMetric.WithLabelValues(plugin, operationName).Observe(timeTaken)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue