Merge pull request #44296 from caesarxuchao/move-api-helpers.go
Automatic merge from submit-queue
Move api helpers.go to a subpackage
Part of https://github.com/kubernetes/kubernetes/issues/44065.
This PR moves the pkg/api/helpers.go to its own subpackage. It's mostly a mechanic move, except that
* I removed ConversionError in helpers.go, it's not used by anyone
* I moved the 3 methods of Taint and Toleration to pkg/api/methods.go, and left a TODO saying refactoring these methods to functions.
I'll send a few more PRs to make the k8s.io/kubernetes/pkg/api package only contains the code we want in the k8s.io/api repo, then we can run a [script](a0015fd1be (diff-7a2fbb4371972350ee414c6b88aee1c8)
) to cut the new repo.
This commit is contained in:
commit
abd92fab1e
@ -47,6 +47,7 @@ go_test(
|
||||
"//federation/pkg/kubefed/testing:go_default_library",
|
||||
"//federation/pkg/kubefed/util:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
|
@ -46,6 +46,7 @@ import (
|
||||
kubefedtesting "k8s.io/kubernetes/federation/pkg/kubefed/testing"
|
||||
"k8s.io/kubernetes/federation/pkg/kubefed/util"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
@ -1243,7 +1244,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !api.Semantic.DeepEqual(got, sa) {
|
||||
if !helper.Semantic.DeepEqual(got, sa) {
|
||||
return nil, fmt.Errorf("unexpected service account object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, sa))
|
||||
}
|
||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(codec, &sa)}, nil
|
||||
@ -1257,7 +1258,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !api.Semantic.DeepEqual(got, role) {
|
||||
if !helper.Semantic.DeepEqual(got, role) {
|
||||
return nil, fmt.Errorf("unexpected role object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, role))
|
||||
}
|
||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(rbacCodec, &role)}, nil
|
||||
@ -1271,7 +1272,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !api.Semantic.DeepEqual(got, rolebinding) {
|
||||
if !helper.Semantic.DeepEqual(got, rolebinding) {
|
||||
return nil, fmt.Errorf("unexpected rolebinding object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, rolebinding))
|
||||
}
|
||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(rbacCodec, &rolebinding)}, nil
|
||||
|
@ -15,8 +15,8 @@ go_library(
|
||||
"defaults.go",
|
||||
"doc.go",
|
||||
"field_constants.go",
|
||||
"helpers.go",
|
||||
"json.go",
|
||||
"methods.go",
|
||||
"ref.go",
|
||||
"register.go",
|
||||
"resource_helpers.go",
|
||||
@ -25,7 +25,6 @@ go_library(
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:github.com/davecgh/go-spew/spew",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apimachinery/announced",
|
||||
@ -37,17 +36,15 @@ go_library(
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer",
|
||||
"//vendor:k8s.io/apimachinery/pkg/selection",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/intstr",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"helpers_test.go",
|
||||
"methods_test.go",
|
||||
"ref_test.go",
|
||||
"resource_helpers_test.go",
|
||||
],
|
||||
@ -56,7 +53,6 @@ go_test(
|
||||
deps = [
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
],
|
||||
@ -120,6 +116,7 @@ filegroup(
|
||||
"//pkg/api/endpoints:all-srcs",
|
||||
"//pkg/api/errors:all-srcs",
|
||||
"//pkg/api/events:all-srcs",
|
||||
"//pkg/api/helper:all-srcs",
|
||||
"//pkg/api/install:all-srcs",
|
||||
"//pkg/api/meta:all-srcs",
|
||||
"//pkg/api/pod:all-srcs",
|
||||
|
@ -64,4 +64,7 @@ const (
|
||||
// in the Annotations of a Pod.
|
||||
// TODO: remove when alpha support for affinity is removed
|
||||
AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity"
|
||||
|
||||
// annotation key prefix used to identify non-convertible json paths.
|
||||
NonConvertibleAnnotationPrefix = "non-convertible.kubernetes.io"
|
||||
)
|
||||
|
51
pkg/api/helper/BUILD
Normal file
51
pkg/api/helper/BUILD
Normal file
@ -0,0 +1,51 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["helpers_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["helpers.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/conversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/selection",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
@ -14,18 +14,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package helper
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
@ -34,25 +31,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// Conversion error conveniently packages up errors in conversions.
|
||||
type ConversionError struct {
|
||||
In, Out interface{}
|
||||
Message string
|
||||
}
|
||||
|
||||
// Return a helpful string about the error
|
||||
func (c *ConversionError) Error() string {
|
||||
return spew.Sprintf(
|
||||
"Conversion error: %s. (in: %v(%+v) out: %v)",
|
||||
c.Message, reflect.TypeOf(c.In), c.In, reflect.TypeOf(c.Out),
|
||||
)
|
||||
}
|
||||
|
||||
const (
|
||||
// annotation key prefix used to identify non-convertible json paths.
|
||||
NonConvertibleAnnotationPrefix = "non-convertible.kubernetes.io"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// NonConvertibleFields iterates over the provided map and filters out all but
|
||||
@ -60,7 +39,7 @@ const (
|
||||
func NonConvertibleFields(annotations map[string]string) map[string]string {
|
||||
nonConvertibleKeys := map[string]string{}
|
||||
for key, value := range annotations {
|
||||
if strings.HasPrefix(key, NonConvertibleAnnotationPrefix) {
|
||||
if strings.HasPrefix(key, api.NonConvertibleAnnotationPrefix) {
|
||||
nonConvertibleKeys[key] = value
|
||||
}
|
||||
}
|
||||
@ -89,10 +68,10 @@ var Semantic = conversion.EqualitiesOrDie(
|
||||
)
|
||||
|
||||
var standardResourceQuotaScopes = sets.NewString(
|
||||
string(ResourceQuotaScopeTerminating),
|
||||
string(ResourceQuotaScopeNotTerminating),
|
||||
string(ResourceQuotaScopeBestEffort),
|
||||
string(ResourceQuotaScopeNotBestEffort),
|
||||
string(api.ResourceQuotaScopeTerminating),
|
||||
string(api.ResourceQuotaScopeNotTerminating),
|
||||
string(api.ResourceQuotaScopeBestEffort),
|
||||
string(api.ResourceQuotaScopeNotBestEffort),
|
||||
)
|
||||
|
||||
// IsStandardResourceQuotaScope returns true if the scope is a standard value
|
||||
@ -101,24 +80,24 @@ func IsStandardResourceQuotaScope(str string) bool {
|
||||
}
|
||||
|
||||
var podObjectCountQuotaResources = sets.NewString(
|
||||
string(ResourcePods),
|
||||
string(api.ResourcePods),
|
||||
)
|
||||
|
||||
var podComputeQuotaResources = sets.NewString(
|
||||
string(ResourceCPU),
|
||||
string(ResourceMemory),
|
||||
string(ResourceLimitsCPU),
|
||||
string(ResourceLimitsMemory),
|
||||
string(ResourceRequestsCPU),
|
||||
string(ResourceRequestsMemory),
|
||||
string(api.ResourceCPU),
|
||||
string(api.ResourceMemory),
|
||||
string(api.ResourceLimitsCPU),
|
||||
string(api.ResourceLimitsMemory),
|
||||
string(api.ResourceRequestsCPU),
|
||||
string(api.ResourceRequestsMemory),
|
||||
)
|
||||
|
||||
// IsResourceQuotaScopeValidForResource returns true if the resource applies to the specified scope
|
||||
func IsResourceQuotaScopeValidForResource(scope ResourceQuotaScope, resource string) bool {
|
||||
func IsResourceQuotaScopeValidForResource(scope api.ResourceQuotaScope, resource string) bool {
|
||||
switch scope {
|
||||
case ResourceQuotaScopeTerminating, ResourceQuotaScopeNotTerminating, ResourceQuotaScopeNotBestEffort:
|
||||
case api.ResourceQuotaScopeTerminating, api.ResourceQuotaScopeNotTerminating, api.ResourceQuotaScopeNotBestEffort:
|
||||
return podObjectCountQuotaResources.Has(resource) || podComputeQuotaResources.Has(resource)
|
||||
case ResourceQuotaScopeBestEffort:
|
||||
case api.ResourceQuotaScopeBestEffort:
|
||||
return podObjectCountQuotaResources.Has(resource)
|
||||
default:
|
||||
return true
|
||||
@ -126,8 +105,8 @@ func IsResourceQuotaScopeValidForResource(scope ResourceQuotaScope, resource str
|
||||
}
|
||||
|
||||
var standardContainerResources = sets.NewString(
|
||||
string(ResourceCPU),
|
||||
string(ResourceMemory),
|
||||
string(api.ResourceCPU),
|
||||
string(api.ResourceMemory),
|
||||
)
|
||||
|
||||
// IsStandardContainerResourceName returns true if the container can make a resource request
|
||||
@ -138,24 +117,24 @@ func IsStandardContainerResourceName(str string) bool {
|
||||
|
||||
// IsOpaqueIntResourceName returns true if the resource name has the opaque
|
||||
// integer resource prefix.
|
||||
func IsOpaqueIntResourceName(name ResourceName) bool {
|
||||
return strings.HasPrefix(string(name), ResourceOpaqueIntPrefix)
|
||||
func IsOpaqueIntResourceName(name api.ResourceName) bool {
|
||||
return strings.HasPrefix(string(name), api.ResourceOpaqueIntPrefix)
|
||||
}
|
||||
|
||||
// OpaqueIntResourceName returns a ResourceName with the canonical opaque
|
||||
// integer prefix prepended. If the argument already has the prefix, it is
|
||||
// returned unmodified.
|
||||
func OpaqueIntResourceName(name string) ResourceName {
|
||||
if IsOpaqueIntResourceName(ResourceName(name)) {
|
||||
return ResourceName(name)
|
||||
func OpaqueIntResourceName(name string) api.ResourceName {
|
||||
if IsOpaqueIntResourceName(api.ResourceName(name)) {
|
||||
return api.ResourceName(name)
|
||||
}
|
||||
return ResourceName(fmt.Sprintf("%s%s", ResourceOpaqueIntPrefix, name))
|
||||
return api.ResourceName(fmt.Sprintf("%s%s", api.ResourceOpaqueIntPrefix, name))
|
||||
}
|
||||
|
||||
var standardLimitRangeTypes = sets.NewString(
|
||||
string(LimitTypePod),
|
||||
string(LimitTypeContainer),
|
||||
string(LimitTypePersistentVolumeClaim),
|
||||
string(api.LimitTypePod),
|
||||
string(api.LimitTypeContainer),
|
||||
string(api.LimitTypePersistentVolumeClaim),
|
||||
)
|
||||
|
||||
// IsStandardLimitRangeType returns true if the type is Pod or Container
|
||||
@ -164,22 +143,22 @@ func IsStandardLimitRangeType(str string) bool {
|
||||
}
|
||||
|
||||
var standardQuotaResources = sets.NewString(
|
||||
string(ResourceCPU),
|
||||
string(ResourceMemory),
|
||||
string(ResourceRequestsCPU),
|
||||
string(ResourceRequestsMemory),
|
||||
string(ResourceRequestsStorage),
|
||||
string(ResourceLimitsCPU),
|
||||
string(ResourceLimitsMemory),
|
||||
string(ResourcePods),
|
||||
string(ResourceQuotas),
|
||||
string(ResourceServices),
|
||||
string(ResourceReplicationControllers),
|
||||
string(ResourceSecrets),
|
||||
string(ResourcePersistentVolumeClaims),
|
||||
string(ResourceConfigMaps),
|
||||
string(ResourceServicesNodePorts),
|
||||
string(ResourceServicesLoadBalancers),
|
||||
string(api.ResourceCPU),
|
||||
string(api.ResourceMemory),
|
||||
string(api.ResourceRequestsCPU),
|
||||
string(api.ResourceRequestsMemory),
|
||||
string(api.ResourceRequestsStorage),
|
||||
string(api.ResourceLimitsCPU),
|
||||
string(api.ResourceLimitsMemory),
|
||||
string(api.ResourcePods),
|
||||
string(api.ResourceQuotas),
|
||||
string(api.ResourceServices),
|
||||
string(api.ResourceReplicationControllers),
|
||||
string(api.ResourceSecrets),
|
||||
string(api.ResourcePersistentVolumeClaims),
|
||||
string(api.ResourceConfigMaps),
|
||||
string(api.ResourceServicesNodePorts),
|
||||
string(api.ResourceServicesLoadBalancers),
|
||||
)
|
||||
|
||||
// IsStandardQuotaResourceName returns true if the resource is known to
|
||||
@ -189,21 +168,21 @@ func IsStandardQuotaResourceName(str string) bool {
|
||||
}
|
||||
|
||||
var standardResources = sets.NewString(
|
||||
string(ResourceCPU),
|
||||
string(ResourceMemory),
|
||||
string(ResourceRequestsCPU),
|
||||
string(ResourceRequestsMemory),
|
||||
string(ResourceLimitsCPU),
|
||||
string(ResourceLimitsMemory),
|
||||
string(ResourcePods),
|
||||
string(ResourceQuotas),
|
||||
string(ResourceServices),
|
||||
string(ResourceReplicationControllers),
|
||||
string(ResourceSecrets),
|
||||
string(ResourceConfigMaps),
|
||||
string(ResourcePersistentVolumeClaims),
|
||||
string(ResourceStorage),
|
||||
string(ResourceRequestsStorage),
|
||||
string(api.ResourceCPU),
|
||||
string(api.ResourceMemory),
|
||||
string(api.ResourceRequestsCPU),
|
||||
string(api.ResourceRequestsMemory),
|
||||
string(api.ResourceLimitsCPU),
|
||||
string(api.ResourceLimitsMemory),
|
||||
string(api.ResourcePods),
|
||||
string(api.ResourceQuotas),
|
||||
string(api.ResourceServices),
|
||||
string(api.ResourceReplicationControllers),
|
||||
string(api.ResourceSecrets),
|
||||
string(api.ResourceConfigMaps),
|
||||
string(api.ResourcePersistentVolumeClaims),
|
||||
string(api.ResourceStorage),
|
||||
string(api.ResourceRequestsStorage),
|
||||
)
|
||||
|
||||
// IsStandardResourceName returns true if the resource is known to the system
|
||||
@ -212,50 +191,50 @@ func IsStandardResourceName(str string) bool {
|
||||
}
|
||||
|
||||
var integerResources = sets.NewString(
|
||||
string(ResourcePods),
|
||||
string(ResourceQuotas),
|
||||
string(ResourceServices),
|
||||
string(ResourceReplicationControllers),
|
||||
string(ResourceSecrets),
|
||||
string(ResourceConfigMaps),
|
||||
string(ResourcePersistentVolumeClaims),
|
||||
string(ResourceServicesNodePorts),
|
||||
string(ResourceServicesLoadBalancers),
|
||||
string(api.ResourcePods),
|
||||
string(api.ResourceQuotas),
|
||||
string(api.ResourceServices),
|
||||
string(api.ResourceReplicationControllers),
|
||||
string(api.ResourceSecrets),
|
||||
string(api.ResourceConfigMaps),
|
||||
string(api.ResourcePersistentVolumeClaims),
|
||||
string(api.ResourceServicesNodePorts),
|
||||
string(api.ResourceServicesLoadBalancers),
|
||||
)
|
||||
|
||||
// IsIntegerResourceName returns true if the resource is measured in integer values
|
||||
func IsIntegerResourceName(str string) bool {
|
||||
return integerResources.Has(str) || IsOpaqueIntResourceName(ResourceName(str))
|
||||
return integerResources.Has(str) || IsOpaqueIntResourceName(api.ResourceName(str))
|
||||
}
|
||||
|
||||
// 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 *Service) bool {
|
||||
return service.Spec.ClusterIP != ClusterIPNone && service.Spec.ClusterIP != ""
|
||||
func IsServiceIPSet(service *api.Service) bool {
|
||||
return service.Spec.ClusterIP != api.ClusterIPNone && service.Spec.ClusterIP != ""
|
||||
}
|
||||
|
||||
// this function aims to check if the service's cluster IP is requested or not
|
||||
func IsServiceIPRequested(service *Service) bool {
|
||||
func IsServiceIPRequested(service *api.Service) bool {
|
||||
// ExternalName services are CNAME aliases to external ones. Ignore the IP.
|
||||
if service.Spec.Type == ServiceTypeExternalName {
|
||||
if service.Spec.Type == api.ServiceTypeExternalName {
|
||||
return false
|
||||
}
|
||||
return service.Spec.ClusterIP == ""
|
||||
}
|
||||
|
||||
var standardFinalizers = sets.NewString(
|
||||
string(FinalizerKubernetes),
|
||||
string(api.FinalizerKubernetes),
|
||||
metav1.FinalizerOrphanDependents,
|
||||
)
|
||||
|
||||
// HasAnnotation returns a bool if passed in annotation exists
|
||||
func HasAnnotation(obj ObjectMeta, ann string) bool {
|
||||
func HasAnnotation(obj api.ObjectMeta, ann string) bool {
|
||||
_, found := obj.Annotations[ann]
|
||||
return found
|
||||
}
|
||||
|
||||
// SetMetaDataAnnotation sets the annotation and value
|
||||
func SetMetaDataAnnotation(obj *ObjectMeta, ann string, value string) {
|
||||
func SetMetaDataAnnotation(obj *api.ObjectMeta, ann string, value string) {
|
||||
if obj.Annotations == nil {
|
||||
obj.Annotations = make(map[string]string)
|
||||
}
|
||||
@ -268,7 +247,7 @@ func IsStandardFinalizerName(str string) bool {
|
||||
|
||||
// AddToNodeAddresses appends the NodeAddresses to the passed-by-pointer slice,
|
||||
// only if they do not already exist
|
||||
func AddToNodeAddresses(addresses *[]NodeAddress, addAddresses ...NodeAddress) {
|
||||
func AddToNodeAddresses(addresses *[]api.NodeAddress, addAddresses ...api.NodeAddress) {
|
||||
for _, add := range addAddresses {
|
||||
exists := false
|
||||
for _, existing := range *addresses {
|
||||
@ -292,11 +271,11 @@ func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) {
|
||||
}
|
||||
|
||||
// TODO: make method on LoadBalancerStatus?
|
||||
func LoadBalancerStatusEqual(l, r *LoadBalancerStatus) bool {
|
||||
func LoadBalancerStatusEqual(l, r *api.LoadBalancerStatus) bool {
|
||||
return ingressSliceEqual(l.Ingress, r.Ingress)
|
||||
}
|
||||
|
||||
func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool {
|
||||
func ingressSliceEqual(lhs, rhs []api.LoadBalancerIngress) bool {
|
||||
if len(lhs) != len(rhs) {
|
||||
return false
|
||||
}
|
||||
@ -308,7 +287,7 @@ func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func ingressEqual(lhs, rhs *LoadBalancerIngress) bool {
|
||||
func ingressEqual(lhs, rhs *api.LoadBalancerIngress) bool {
|
||||
if lhs.IP != rhs.IP {
|
||||
return false
|
||||
}
|
||||
@ -319,9 +298,9 @@ func ingressEqual(lhs, rhs *LoadBalancerIngress) bool {
|
||||
}
|
||||
|
||||
// TODO: make method on LoadBalancerStatus?
|
||||
func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus {
|
||||
c := &LoadBalancerStatus{}
|
||||
c.Ingress = make([]LoadBalancerIngress, len(lb.Ingress))
|
||||
func LoadBalancerStatusDeepCopy(lb *api.LoadBalancerStatus) *api.LoadBalancerStatus {
|
||||
c := &api.LoadBalancerStatus{}
|
||||
c.Ingress = make([]api.LoadBalancerIngress, len(lb.Ingress))
|
||||
for i := range lb.Ingress {
|
||||
c.Ingress[i] = lb.Ingress[i]
|
||||
}
|
||||
@ -330,42 +309,42 @@ func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus {
|
||||
|
||||
// GetAccessModesAsString returns a string representation of an array of access modes.
|
||||
// modes, when present, are always in the same order: RWO,ROX,RWX.
|
||||
func GetAccessModesAsString(modes []PersistentVolumeAccessMode) string {
|
||||
func GetAccessModesAsString(modes []api.PersistentVolumeAccessMode) string {
|
||||
modes = removeDuplicateAccessModes(modes)
|
||||
modesStr := []string{}
|
||||
if containsAccessMode(modes, ReadWriteOnce) {
|
||||
if containsAccessMode(modes, api.ReadWriteOnce) {
|
||||
modesStr = append(modesStr, "RWO")
|
||||
}
|
||||
if containsAccessMode(modes, ReadOnlyMany) {
|
||||
if containsAccessMode(modes, api.ReadOnlyMany) {
|
||||
modesStr = append(modesStr, "ROX")
|
||||
}
|
||||
if containsAccessMode(modes, ReadWriteMany) {
|
||||
if containsAccessMode(modes, api.ReadWriteMany) {
|
||||
modesStr = append(modesStr, "RWX")
|
||||
}
|
||||
return strings.Join(modesStr, ",")
|
||||
}
|
||||
|
||||
// GetAccessModesAsString returns an array of AccessModes from a string created by GetAccessModesAsString
|
||||
func GetAccessModesFromString(modes string) []PersistentVolumeAccessMode {
|
||||
func GetAccessModesFromString(modes string) []api.PersistentVolumeAccessMode {
|
||||
strmodes := strings.Split(modes, ",")
|
||||
accessModes := []PersistentVolumeAccessMode{}
|
||||
accessModes := []api.PersistentVolumeAccessMode{}
|
||||
for _, s := range strmodes {
|
||||
s = strings.Trim(s, " ")
|
||||
switch {
|
||||
case s == "RWO":
|
||||
accessModes = append(accessModes, ReadWriteOnce)
|
||||
accessModes = append(accessModes, api.ReadWriteOnce)
|
||||
case s == "ROX":
|
||||
accessModes = append(accessModes, ReadOnlyMany)
|
||||
accessModes = append(accessModes, api.ReadOnlyMany)
|
||||
case s == "RWX":
|
||||
accessModes = append(accessModes, ReadWriteMany)
|
||||
accessModes = append(accessModes, api.ReadWriteMany)
|
||||
}
|
||||
}
|
||||
return accessModes
|
||||
}
|
||||
|
||||
// removeDuplicateAccessModes returns an array of access modes without any duplicates
|
||||
func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []PersistentVolumeAccessMode {
|
||||
accessModes := []PersistentVolumeAccessMode{}
|
||||
func removeDuplicateAccessModes(modes []api.PersistentVolumeAccessMode) []api.PersistentVolumeAccessMode {
|
||||
accessModes := []api.PersistentVolumeAccessMode{}
|
||||
for _, m := range modes {
|
||||
if !containsAccessMode(accessModes, m) {
|
||||
accessModes = append(accessModes, m)
|
||||
@ -374,7 +353,7 @@ func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []Persistent
|
||||
return accessModes
|
||||
}
|
||||
|
||||
func containsAccessMode(modes []PersistentVolumeAccessMode, mode PersistentVolumeAccessMode) bool {
|
||||
func containsAccessMode(modes []api.PersistentVolumeAccessMode, mode api.PersistentVolumeAccessMode) bool {
|
||||
for _, m := range modes {
|
||||
if m == mode {
|
||||
return true
|
||||
@ -397,7 +376,7 @@ func ParseRFC3339(s string, nowFn func() metav1.Time) (metav1.Time, error) {
|
||||
|
||||
// NodeSelectorRequirementsAsSelector converts the []NodeSelectorRequirement api type into a struct that implements
|
||||
// labels.Selector.
|
||||
func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.Selector, error) {
|
||||
func NodeSelectorRequirementsAsSelector(nsm []api.NodeSelectorRequirement) (labels.Selector, error) {
|
||||
if len(nsm) == 0 {
|
||||
return labels.Nothing(), nil
|
||||
}
|
||||
@ -405,17 +384,17 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S
|
||||
for _, expr := range nsm {
|
||||
var op selection.Operator
|
||||
switch expr.Operator {
|
||||
case NodeSelectorOpIn:
|
||||
case api.NodeSelectorOpIn:
|
||||
op = selection.In
|
||||
case NodeSelectorOpNotIn:
|
||||
case api.NodeSelectorOpNotIn:
|
||||
op = selection.NotIn
|
||||
case NodeSelectorOpExists:
|
||||
case api.NodeSelectorOpExists:
|
||||
op = selection.Exists
|
||||
case NodeSelectorOpDoesNotExist:
|
||||
case api.NodeSelectorOpDoesNotExist:
|
||||
op = selection.DoesNotExist
|
||||
case NodeSelectorOpGt:
|
||||
case api.NodeSelectorOpGt:
|
||||
op = selection.GreaterThan
|
||||
case NodeSelectorOpLt:
|
||||
case api.NodeSelectorOpLt:
|
||||
op = selection.LessThan
|
||||
default:
|
||||
return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
|
||||
@ -431,10 +410,10 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S
|
||||
|
||||
// GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations
|
||||
// and converts it to the []Toleration type in api.
|
||||
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Toleration, error) {
|
||||
var tolerations []Toleration
|
||||
if len(annotations) > 0 && annotations[TolerationsAnnotationKey] != "" {
|
||||
err := json.Unmarshal([]byte(annotations[TolerationsAnnotationKey]), &tolerations)
|
||||
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]api.Toleration, error) {
|
||||
var tolerations []api.Toleration
|
||||
if len(annotations) > 0 && annotations[api.TolerationsAnnotationKey] != "" {
|
||||
err := json.Unmarshal([]byte(annotations[api.TolerationsAnnotationKey]), &tolerations)
|
||||
if err != nil {
|
||||
return tolerations, err
|
||||
}
|
||||
@ -444,10 +423,10 @@ func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Tolerati
|
||||
|
||||
// AddOrUpdateTolerationInPod tries to add a toleration to the pod's toleration list.
|
||||
// Returns true if something was updated, false otherwise.
|
||||
func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool {
|
||||
func AddOrUpdateTolerationInPod(pod *api.Pod, toleration *api.Toleration) bool {
|
||||
podTolerations := pod.Spec.Tolerations
|
||||
|
||||
var newTolerations []Toleration
|
||||
var newTolerations []api.Toleration
|
||||
updated := false
|
||||
for i := range podTolerations {
|
||||
if toleration.MatchToleration(&podTolerations[i]) {
|
||||
@ -470,18 +449,8 @@ func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// MatchToleration checks if the toleration matches tolerationToMatch. Tolerations are unique by <key,effect,operator,value>,
|
||||
// if the two tolerations have same <key,effect,operator,value> combination, regard as they match.
|
||||
// TODO: uniqueness check for tolerations in api validations.
|
||||
func (t *Toleration) MatchToleration(tolerationToMatch *Toleration) bool {
|
||||
return t.Key == tolerationToMatch.Key &&
|
||||
t.Effect == tolerationToMatch.Effect &&
|
||||
t.Operator == tolerationToMatch.Operator &&
|
||||
t.Value == tolerationToMatch.Value
|
||||
}
|
||||
|
||||
// TolerationToleratesTaint checks if the toleration tolerates the taint.
|
||||
func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
|
||||
func TolerationToleratesTaint(toleration *api.Toleration, taint *api.Taint) bool {
|
||||
if len(toleration.Effect) != 0 && toleration.Effect != taint.Effect {
|
||||
return false
|
||||
}
|
||||
@ -490,17 +459,17 @@ func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
|
||||
return false
|
||||
}
|
||||
// TODO: Use proper defaulting when Toleration becomes a field of PodSpec
|
||||
if (len(toleration.Operator) == 0 || toleration.Operator == TolerationOpEqual) && toleration.Value == taint.Value {
|
||||
if (len(toleration.Operator) == 0 || toleration.Operator == api.TolerationOpEqual) && toleration.Value == taint.Value {
|
||||
return true
|
||||
}
|
||||
if toleration.Operator == TolerationOpExists {
|
||||
if toleration.Operator == api.TolerationOpExists {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TaintToleratedByTolerations checks if taint is tolerated by any of the tolerations.
|
||||
func TaintToleratedByTolerations(taint *Taint, tolerations []Toleration) bool {
|
||||
func TaintToleratedByTolerations(taint *api.Taint, tolerations []api.Toleration) bool {
|
||||
tolerated := false
|
||||
for i := range tolerations {
|
||||
if TolerationToleratesTaint(&tolerations[i], taint) {
|
||||
@ -511,28 +480,14 @@ func TaintToleratedByTolerations(taint *Taint, tolerations []Toleration) bool {
|
||||
return tolerated
|
||||
}
|
||||
|
||||
// MatchTaint checks if the taint matches taintToMatch. Taints are unique by key:effect,
|
||||
// if the two taints have same key:effect, regard as they match.
|
||||
func (t *Taint) MatchTaint(taintToMatch Taint) bool {
|
||||
return t.Key == taintToMatch.Key && t.Effect == taintToMatch.Effect
|
||||
}
|
||||
|
||||
// taint.ToString() converts taint struct to string in format key=value:effect or key:effect.
|
||||
func (t *Taint) ToString() string {
|
||||
if len(t.Value) == 0 {
|
||||
return fmt.Sprintf("%v:%v", t.Key, t.Effect)
|
||||
}
|
||||
return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect)
|
||||
}
|
||||
|
||||
// GetTaintsFromNodeAnnotations gets the json serialized taints data from Pod.Annotations
|
||||
// and converts it to the []Taint type in api.
|
||||
func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]Taint, error) {
|
||||
var taints []Taint
|
||||
if len(annotations) > 0 && annotations[TaintsAnnotationKey] != "" {
|
||||
err := json.Unmarshal([]byte(annotations[TaintsAnnotationKey]), &taints)
|
||||
func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]api.Taint, error) {
|
||||
var taints []api.Taint
|
||||
if len(annotations) > 0 && annotations[api.TaintsAnnotationKey] != "" {
|
||||
err := json.Unmarshal([]byte(annotations[api.TaintsAnnotationKey]), &taints)
|
||||
if err != nil {
|
||||
return []Taint{}, err
|
||||
return []api.Taint{}, err
|
||||
}
|
||||
}
|
||||
return taints, nil
|
||||
@ -541,12 +496,12 @@ func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]Taint, error
|
||||
// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls
|
||||
// and a slice of unsafe Sysctls. This is only a convenience wrapper around
|
||||
// SysctlsFromPodAnnotation.
|
||||
func SysctlsFromPodAnnotations(a map[string]string) ([]Sysctl, []Sysctl, error) {
|
||||
safe, err := SysctlsFromPodAnnotation(a[SysctlsPodAnnotationKey])
|
||||
func SysctlsFromPodAnnotations(a map[string]string) ([]api.Sysctl, []api.Sysctl, error) {
|
||||
safe, err := SysctlsFromPodAnnotation(a[api.SysctlsPodAnnotationKey])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
unsafe, err := SysctlsFromPodAnnotation(a[UnsafeSysctlsPodAnnotationKey])
|
||||
unsafe, err := SysctlsFromPodAnnotation(a[api.UnsafeSysctlsPodAnnotationKey])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -555,13 +510,13 @@ func SysctlsFromPodAnnotations(a map[string]string) ([]Sysctl, []Sysctl, error)
|
||||
}
|
||||
|
||||
// SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls.
|
||||
func SysctlsFromPodAnnotation(annotation string) ([]Sysctl, error) {
|
||||
func SysctlsFromPodAnnotation(annotation string) ([]api.Sysctl, error) {
|
||||
if len(annotation) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
kvs := strings.Split(annotation, ",")
|
||||
sysctls := make([]Sysctl, len(kvs))
|
||||
sysctls := make([]api.Sysctl, len(kvs))
|
||||
for i, kv := range kvs {
|
||||
cs := strings.Split(kv, "=")
|
||||
if len(cs) != 2 || len(cs[0]) == 0 {
|
||||
@ -574,7 +529,7 @@ func SysctlsFromPodAnnotation(annotation string) ([]Sysctl, error) {
|
||||
}
|
||||
|
||||
// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls.
|
||||
func PodAnnotationsFromSysctls(sysctls []Sysctl) string {
|
||||
func PodAnnotationsFromSysctls(sysctls []api.Sysctl) string {
|
||||
if len(sysctls) == 0 {
|
||||
return ""
|
||||
}
|
||||
@ -589,10 +544,10 @@ func PodAnnotationsFromSysctls(sysctls []Sysctl) string {
|
||||
// GetAffinityFromPodAnnotations gets the json serialized affinity data from Pod.Annotations
|
||||
// and converts it to the Affinity type in api.
|
||||
// TODO: remove when alpha support for affinity is removed
|
||||
func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, error) {
|
||||
if len(annotations) > 0 && annotations[AffinityAnnotationKey] != "" {
|
||||
var affinity Affinity
|
||||
err := json.Unmarshal([]byte(annotations[AffinityAnnotationKey]), &affinity)
|
||||
func GetAffinityFromPodAnnotations(annotations map[string]string) (*api.Affinity, error) {
|
||||
if len(annotations) > 0 && annotations[api.AffinityAnnotationKey] != "" {
|
||||
var affinity api.Affinity
|
||||
err := json.Unmarshal([]byte(annotations[api.AffinityAnnotationKey]), &affinity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -602,9 +557,9 @@ func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, er
|
||||
}
|
||||
|
||||
// GetPersistentVolumeClass returns StorageClassName.
|
||||
func GetPersistentVolumeClass(volume *PersistentVolume) string {
|
||||
func GetPersistentVolumeClass(volume *api.PersistentVolume) string {
|
||||
// Use beta annotation first
|
||||
if class, found := volume.Annotations[BetaStorageClassAnnotation]; found {
|
||||
if class, found := volume.Annotations[api.BetaStorageClassAnnotation]; found {
|
||||
return class
|
||||
}
|
||||
|
||||
@ -613,9 +568,9 @@ func GetPersistentVolumeClass(volume *PersistentVolume) string {
|
||||
|
||||
// GetPersistentVolumeClaimClass returns StorageClassName. If no storage class was
|
||||
// requested, it returns "".
|
||||
func GetPersistentVolumeClaimClass(claim *PersistentVolumeClaim) string {
|
||||
func GetPersistentVolumeClaimClass(claim *api.PersistentVolumeClaim) string {
|
||||
// Use beta annotation first
|
||||
if class, found := claim.Annotations[BetaStorageClassAnnotation]; found {
|
||||
if class, found := claim.Annotations[api.BetaStorageClassAnnotation]; found {
|
||||
return class
|
||||
}
|
||||
|
||||
@ -627,9 +582,9 @@ func GetPersistentVolumeClaimClass(claim *PersistentVolumeClaim) string {
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimHasClass returns true if given claim has set StorageClassName field.
|
||||
func PersistentVolumeClaimHasClass(claim *PersistentVolumeClaim) bool {
|
||||
func PersistentVolumeClaimHasClass(claim *api.PersistentVolumeClaim) bool {
|
||||
// Use beta annotation first
|
||||
if _, found := claim.Annotations[BetaStorageClassAnnotation]; found {
|
||||
if _, found := claim.Annotations[api.BetaStorageClassAnnotation]; found {
|
||||
return true
|
||||
}
|
||||
|
268
pkg/api/helper/helpers_test.go
Normal file
268
pkg/api/helper/helpers_test.go
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
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 helper
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func TestSemantic(t *testing.T) {
|
||||
table := []struct {
|
||||
a, b interface{}
|
||||
shouldEqual bool
|
||||
}{
|
||||
{resource.MustParse("0"), resource.Quantity{}, true},
|
||||
{resource.Quantity{}, resource.MustParse("0"), true},
|
||||
{resource.Quantity{}, resource.MustParse("1m"), false},
|
||||
{
|
||||
resource.NewQuantity(5, resource.BinarySI),
|
||||
resource.NewQuantity(5, resource.DecimalSI),
|
||||
true,
|
||||
},
|
||||
{resource.MustParse("2m"), resource.MustParse("1m"), false},
|
||||
}
|
||||
|
||||
for index, item := range table {
|
||||
if e, a := item.shouldEqual, Semantic.DeepEqual(item.a, item.b); e != a {
|
||||
t.Errorf("case[%d], expected %v, got %v.", index, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsStandardResource(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
output bool
|
||||
}{
|
||||
{"cpu", true},
|
||||
{"memory", true},
|
||||
{"disk", false},
|
||||
{"blah", false},
|
||||
{"x.y.z", false},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
if IsStandardResourceName(tc.input) != tc.output {
|
||||
t.Errorf("case[%d], expected: %t, got: %t", i, tc.output, !tc.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddToNodeAddresses(t *testing.T) {
|
||||
testCases := []struct {
|
||||
existing []api.NodeAddress
|
||||
toAdd []api.NodeAddress
|
||||
expected []api.NodeAddress
|
||||
}{
|
||||
{
|
||||
existing: []api.NodeAddress{},
|
||||
toAdd: []api.NodeAddress{},
|
||||
expected: []api.NodeAddress{},
|
||||
},
|
||||
{
|
||||
existing: []api.NodeAddress{},
|
||||
toAdd: []api.NodeAddress{
|
||||
{Type: api.NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: api.NodeHostName, Address: "localhost"},
|
||||
},
|
||||
expected: []api.NodeAddress{
|
||||
{Type: api.NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: api.NodeHostName, Address: "localhost"},
|
||||
},
|
||||
},
|
||||
{
|
||||
existing: []api.NodeAddress{},
|
||||
toAdd: []api.NodeAddress{
|
||||
{Type: api.NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: api.NodeExternalIP, Address: "1.1.1.1"},
|
||||
},
|
||||
expected: []api.NodeAddress{
|
||||
{Type: api.NodeExternalIP, Address: "1.1.1.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
existing: []api.NodeAddress{
|
||||
{Type: api.NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: api.NodeInternalIP, Address: "10.1.1.1"},
|
||||
},
|
||||
toAdd: []api.NodeAddress{
|
||||
{Type: api.NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: api.NodeHostName, Address: "localhost"},
|
||||
},
|
||||
expected: []api.NodeAddress{
|
||||
{Type: api.NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: api.NodeInternalIP, Address: "10.1.1.1"},
|
||||
{Type: api.NodeHostName, Address: "localhost"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
AddToNodeAddresses(&tc.existing, tc.toAdd...)
|
||||
if !Semantic.DeepEqual(tc.expected, tc.existing) {
|
||||
t.Errorf("case[%d], expected: %v, got: %v", i, tc.expected, tc.existing)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccessModesFromString(t *testing.T) {
|
||||
modes := GetAccessModesFromString("ROX")
|
||||
if !containsAccessMode(modes, api.ReadOnlyMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", api.ReadOnlyMany, modes)
|
||||
}
|
||||
|
||||
modes = GetAccessModesFromString("ROX,RWX")
|
||||
if !containsAccessMode(modes, api.ReadOnlyMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", api.ReadOnlyMany, modes)
|
||||
}
|
||||
if !containsAccessMode(modes, api.ReadWriteMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", api.ReadWriteMany, modes)
|
||||
}
|
||||
|
||||
modes = GetAccessModesFromString("RWO,ROX,RWX")
|
||||
if !containsAccessMode(modes, api.ReadOnlyMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", api.ReadOnlyMany, modes)
|
||||
}
|
||||
if !containsAccessMode(modes, api.ReadWriteMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", api.ReadWriteMany, modes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveDuplicateAccessModes(t *testing.T) {
|
||||
modes := []api.PersistentVolumeAccessMode{
|
||||
api.ReadWriteOnce, api.ReadOnlyMany, api.ReadOnlyMany, api.ReadOnlyMany,
|
||||
}
|
||||
modes = removeDuplicateAccessModes(modes)
|
||||
if len(modes) != 2 {
|
||||
t.Errorf("Expected 2 distinct modes in set but found %v", len(modes))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
|
||||
matchExpressions := []api.NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: api.NodeSelectorOpIn,
|
||||
Values: []string{"bar", "baz"},
|
||||
}}
|
||||
mustParse := func(s string) labels.Selector {
|
||||
out, e := labels.Parse(s)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return out
|
||||
}
|
||||
tc := []struct {
|
||||
in []api.NodeSelectorRequirement
|
||||
out labels.Selector
|
||||
expectErr bool
|
||||
}{
|
||||
{in: nil, out: labels.Nothing()},
|
||||
{in: []api.NodeSelectorRequirement{}, out: labels.Nothing()},
|
||||
{
|
||||
in: matchExpressions,
|
||||
out: mustParse("foo in (baz,bar)"),
|
||||
},
|
||||
{
|
||||
in: []api.NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: api.NodeSelectorOpExists,
|
||||
Values: []string{"bar", "baz"},
|
||||
}},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
in: []api.NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: api.NodeSelectorOpGt,
|
||||
Values: []string{"1"},
|
||||
}},
|
||||
out: mustParse("foo>1"),
|
||||
},
|
||||
{
|
||||
in: []api.NodeSelectorRequirement{{
|
||||
Key: "bar",
|
||||
Operator: api.NodeSelectorOpLt,
|
||||
Values: []string{"7"},
|
||||
}},
|
||||
out: mustParse("bar<7"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tc {
|
||||
out, err := NodeSelectorRequirementsAsSelector(tc.in)
|
||||
if err == nil && tc.expectErr {
|
||||
t.Errorf("[%v]expected error but got none.", i)
|
||||
}
|
||||
if err != nil && !tc.expectErr {
|
||||
t.Errorf("[%v]did not expect error but got: %v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(out, tc.out) {
|
||||
t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSysctlsFromPodAnnotation(t *testing.T) {
|
||||
type Test struct {
|
||||
annotation string
|
||||
expectValue []api.Sysctl
|
||||
expectErr bool
|
||||
}
|
||||
for i, test := range []Test{
|
||||
{
|
||||
annotation: "",
|
||||
expectValue: nil,
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
annotation: "=123",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=",
|
||||
expectValue: []api.Sysctl{{Name: "foo.bar", Value: ""}},
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=42",
|
||||
expectValue: []api.Sysctl{{Name: "foo.bar", Value: "42"}},
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=42,",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=42,abc.def=1",
|
||||
expectValue: []api.Sysctl{{Name: "foo.bar", Value: "42"}, {Name: "abc.def", Value: "1"}},
|
||||
},
|
||||
} {
|
||||
sysctls, err := SysctlsFromPodAnnotation(test.annotation)
|
||||
if test.expectErr && err == nil {
|
||||
t.Errorf("[%v]expected error but got none", i)
|
||||
} else if !test.expectErr && err != nil {
|
||||
t.Errorf("[%v]did not expect error but got: %v", i, err)
|
||||
} else if !reflect.DeepEqual(sysctls, test.expectValue) {
|
||||
t.Errorf("[%v]expect value %v but got %v", i, test.expectValue, sysctls)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,389 +0,0 @@
|
||||
/*
|
||||
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 api
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
func TestConversionError(t *testing.T) {
|
||||
var i int
|
||||
var s string
|
||||
i = 3
|
||||
s = "foo"
|
||||
c := ConversionError{
|
||||
In: &i, Out: &s,
|
||||
Message: "Can't make x into y, silly",
|
||||
}
|
||||
var e error
|
||||
e = &c // ensure it implements error
|
||||
msg := e.Error()
|
||||
t.Logf("Message is %v", msg)
|
||||
for _, part := range []string{"3", "int", "string", "Can't"} {
|
||||
if !strings.Contains(msg, part) {
|
||||
t.Errorf("didn't find %v", part)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSemantic(t *testing.T) {
|
||||
table := []struct {
|
||||
a, b interface{}
|
||||
shouldEqual bool
|
||||
}{
|
||||
{resource.MustParse("0"), resource.Quantity{}, true},
|
||||
{resource.Quantity{}, resource.MustParse("0"), true},
|
||||
{resource.Quantity{}, resource.MustParse("1m"), false},
|
||||
{
|
||||
resource.NewQuantity(5, resource.BinarySI),
|
||||
resource.NewQuantity(5, resource.DecimalSI),
|
||||
true,
|
||||
},
|
||||
{resource.MustParse("2m"), resource.MustParse("1m"), false},
|
||||
}
|
||||
|
||||
for index, item := range table {
|
||||
if e, a := item.shouldEqual, Semantic.DeepEqual(item.a, item.b); e != a {
|
||||
t.Errorf("case[%d], expected %v, got %v.", index, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsStandardResource(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
output bool
|
||||
}{
|
||||
{"cpu", true},
|
||||
{"memory", true},
|
||||
{"disk", false},
|
||||
{"blah", false},
|
||||
{"x.y.z", false},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
if IsStandardResourceName(tc.input) != tc.output {
|
||||
t.Errorf("case[%d], expected: %t, got: %t", i, tc.output, !tc.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddToNodeAddresses(t *testing.T) {
|
||||
testCases := []struct {
|
||||
existing []NodeAddress
|
||||
toAdd []NodeAddress
|
||||
expected []NodeAddress
|
||||
}{
|
||||
{
|
||||
existing: []NodeAddress{},
|
||||
toAdd: []NodeAddress{},
|
||||
expected: []NodeAddress{},
|
||||
},
|
||||
{
|
||||
existing: []NodeAddress{},
|
||||
toAdd: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeHostName, Address: "localhost"},
|
||||
},
|
||||
expected: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeHostName, Address: "localhost"},
|
||||
},
|
||||
},
|
||||
{
|
||||
existing: []NodeAddress{},
|
||||
toAdd: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
},
|
||||
expected: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
existing: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeInternalIP, Address: "10.1.1.1"},
|
||||
},
|
||||
toAdd: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeHostName, Address: "localhost"},
|
||||
},
|
||||
expected: []NodeAddress{
|
||||
{Type: NodeExternalIP, Address: "1.1.1.1"},
|
||||
{Type: NodeInternalIP, Address: "10.1.1.1"},
|
||||
{Type: NodeHostName, Address: "localhost"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
AddToNodeAddresses(&tc.existing, tc.toAdd...)
|
||||
if !Semantic.DeepEqual(tc.expected, tc.existing) {
|
||||
t.Errorf("case[%d], expected: %v, got: %v", i, tc.expected, tc.existing)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccessModesFromString(t *testing.T) {
|
||||
modes := GetAccessModesFromString("ROX")
|
||||
if !containsAccessMode(modes, ReadOnlyMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadOnlyMany, modes)
|
||||
}
|
||||
|
||||
modes = GetAccessModesFromString("ROX,RWX")
|
||||
if !containsAccessMode(modes, ReadOnlyMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadOnlyMany, modes)
|
||||
}
|
||||
if !containsAccessMode(modes, ReadWriteMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadWriteMany, modes)
|
||||
}
|
||||
|
||||
modes = GetAccessModesFromString("RWO,ROX,RWX")
|
||||
if !containsAccessMode(modes, ReadOnlyMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadOnlyMany, modes)
|
||||
}
|
||||
if !containsAccessMode(modes, ReadWriteMany) {
|
||||
t.Errorf("Expected mode %s, but got %+v", ReadWriteMany, modes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveDuplicateAccessModes(t *testing.T) {
|
||||
modes := []PersistentVolumeAccessMode{
|
||||
ReadWriteOnce, ReadOnlyMany, ReadOnlyMany, ReadOnlyMany,
|
||||
}
|
||||
modes = removeDuplicateAccessModes(modes)
|
||||
if len(modes) != 2 {
|
||||
t.Errorf("Expected 2 distinct modes in set but found %v", len(modes))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeSelectorRequirementsAsSelector(t *testing.T) {
|
||||
matchExpressions := []NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: NodeSelectorOpIn,
|
||||
Values: []string{"bar", "baz"},
|
||||
}}
|
||||
mustParse := func(s string) labels.Selector {
|
||||
out, e := labels.Parse(s)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return out
|
||||
}
|
||||
tc := []struct {
|
||||
in []NodeSelectorRequirement
|
||||
out labels.Selector
|
||||
expectErr bool
|
||||
}{
|
||||
{in: nil, out: labels.Nothing()},
|
||||
{in: []NodeSelectorRequirement{}, out: labels.Nothing()},
|
||||
{
|
||||
in: matchExpressions,
|
||||
out: mustParse("foo in (baz,bar)"),
|
||||
},
|
||||
{
|
||||
in: []NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: NodeSelectorOpExists,
|
||||
Values: []string{"bar", "baz"},
|
||||
}},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
in: []NodeSelectorRequirement{{
|
||||
Key: "foo",
|
||||
Operator: NodeSelectorOpGt,
|
||||
Values: []string{"1"},
|
||||
}},
|
||||
out: mustParse("foo>1"),
|
||||
},
|
||||
{
|
||||
in: []NodeSelectorRequirement{{
|
||||
Key: "bar",
|
||||
Operator: NodeSelectorOpLt,
|
||||
Values: []string{"7"},
|
||||
}},
|
||||
out: mustParse("bar<7"),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tc {
|
||||
out, err := NodeSelectorRequirementsAsSelector(tc.in)
|
||||
if err == nil && tc.expectErr {
|
||||
t.Errorf("[%v]expected error but got none.", i)
|
||||
}
|
||||
if err != nil && !tc.expectErr {
|
||||
t.Errorf("[%v]did not expect error but got: %v", i, err)
|
||||
}
|
||||
if !reflect.DeepEqual(out, tc.out) {
|
||||
t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaintToString(t *testing.T) {
|
||||
testCases := []struct {
|
||||
taint *Taint
|
||||
expectedString string
|
||||
}{
|
||||
{
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectedString: "foo=bar:NoSchedule",
|
||||
},
|
||||
{
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectedString: "foo:NoSchedule",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
if tc.expectedString != tc.taint.ToString() {
|
||||
t.Errorf("[%v] expected taint %v converted to %s, got %s", i, tc.taint, tc.expectedString, tc.taint.ToString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchTaint(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
taint *Taint
|
||||
taintToMatch Taint
|
||||
expectMatch bool
|
||||
}{
|
||||
{
|
||||
description: "two taints with the same key,value,effect should match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: true,
|
||||
},
|
||||
{
|
||||
description: "two taints with the same key,effect but different value should match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "foo",
|
||||
Value: "different-value",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: true,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different key cannot match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "different-key",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different effect cannot match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectPreferNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
if tc.expectMatch != tc.taint.MatchTaint(tc.taintToMatch) {
|
||||
t.Errorf("[%s] expect taint %s match taint %s", tc.description, tc.taint.ToString(), tc.taintToMatch.ToString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSysctlsFromPodAnnotation(t *testing.T) {
|
||||
type Test struct {
|
||||
annotation string
|
||||
expectValue []Sysctl
|
||||
expectErr bool
|
||||
}
|
||||
for i, test := range []Test{
|
||||
{
|
||||
annotation: "",
|
||||
expectValue: nil,
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
annotation: "=123",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=",
|
||||
expectValue: []Sysctl{{Name: "foo.bar", Value: ""}},
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=42",
|
||||
expectValue: []Sysctl{{Name: "foo.bar", Value: "42"}},
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=42,",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
annotation: "foo.bar=42,abc.def=1",
|
||||
expectValue: []Sysctl{{Name: "foo.bar", Value: "42"}, {Name: "abc.def", Value: "1"}},
|
||||
},
|
||||
} {
|
||||
sysctls, err := SysctlsFromPodAnnotation(test.annotation)
|
||||
if test.expectErr && err == nil {
|
||||
t.Errorf("[%v]expected error but got none", i)
|
||||
} else if !test.expectErr && err != nil {
|
||||
t.Errorf("[%v]did not expect error but got: %v", i, err)
|
||||
} else if !reflect.DeepEqual(sysctls, test.expectValue) {
|
||||
t.Errorf("[%v]expect value %v but got %v", i, test.expectValue, sysctls)
|
||||
}
|
||||
}
|
||||
}
|
46
pkg/api/methods.go
Normal file
46
pkg/api/methods.go
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
//TODO: consider making these methods functions, because we don't want helper
|
||||
//functions in the k8s.io/api repo.
|
||||
|
||||
package api
|
||||
|
||||
import "fmt"
|
||||
|
||||
// MatchToleration checks if the toleration matches tolerationToMatch. Tolerations are unique by <key,effect,operator,value>,
|
||||
// if the two tolerations have same <key,effect,operator,value> combination, regard as they match.
|
||||
// TODO: uniqueness check for tolerations in api validations.
|
||||
func (t *Toleration) MatchToleration(tolerationToMatch *Toleration) bool {
|
||||
return t.Key == tolerationToMatch.Key &&
|
||||
t.Effect == tolerationToMatch.Effect &&
|
||||
t.Operator == tolerationToMatch.Operator &&
|
||||
t.Value == tolerationToMatch.Value
|
||||
}
|
||||
|
||||
// MatchTaint checks if the taint matches taintToMatch. Taints are unique by key:effect,
|
||||
// if the two taints have same key:effect, regard as they match.
|
||||
func (t *Taint) MatchTaint(taintToMatch Taint) bool {
|
||||
return t.Key == taintToMatch.Key && t.Effect == taintToMatch.Effect
|
||||
}
|
||||
|
||||
// taint.ToString() converts taint struct to string in format key=value:effect or key:effect.
|
||||
func (t *Taint) ToString() string {
|
||||
if len(t.Value) == 0 {
|
||||
return fmt.Sprintf("%v:%v", t.Key, t.Effect)
|
||||
}
|
||||
return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect)
|
||||
}
|
120
pkg/api/methods_test.go
Normal file
120
pkg/api/methods_test.go
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
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 api
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestTaintToString(t *testing.T) {
|
||||
testCases := []struct {
|
||||
taint *Taint
|
||||
expectedString string
|
||||
}{
|
||||
{
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectedString: "foo=bar:NoSchedule",
|
||||
},
|
||||
{
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectedString: "foo:NoSchedule",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
if tc.expectedString != tc.taint.ToString() {
|
||||
t.Errorf("[%v] expected taint %v converted to %s, got %s", i, tc.taint, tc.expectedString, tc.taint.ToString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchTaint(t *testing.T) {
|
||||
testCases := []struct {
|
||||
description string
|
||||
taint *Taint
|
||||
taintToMatch Taint
|
||||
expectMatch bool
|
||||
}{
|
||||
{
|
||||
description: "two taints with the same key,value,effect should match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: true,
|
||||
},
|
||||
{
|
||||
description: "two taints with the same key,effect but different value should match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "foo",
|
||||
Value: "different-value",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: true,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different key cannot match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "different-key",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
{
|
||||
description: "two taints with the different effect cannot match",
|
||||
taint: &Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectNoSchedule,
|
||||
},
|
||||
taintToMatch: Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: TaintEffectPreferNoSchedule,
|
||||
},
|
||||
expectMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
if tc.expectMatch != tc.taint.MatchTaint(tc.taintToMatch) {
|
||||
t.Errorf("[%s] expect taint %s match taint %s", tc.description, tc.taint.ToString(), tc.taintToMatch.ToString())
|
||||
}
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/util:go_default_library",
|
||||
"//pkg/util/parsers:go_default_library",
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
)
|
||||
|
||||
// IsOpaqueIntResourceName returns true if the resource name has the opaque
|
||||
@ -285,7 +286,7 @@ func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool {
|
||||
updated := false
|
||||
for i := range podTolerations {
|
||||
if toleration.MatchToleration(&podTolerations[i]) {
|
||||
if api.Semantic.DeepEqual(toleration, podTolerations[i]) {
|
||||
if helper.Semantic.DeepEqual(toleration, podTolerations[i]) {
|
||||
return false
|
||||
}
|
||||
newTolerations = append(newTolerations, *toleration)
|
||||
@ -527,7 +528,7 @@ func AddOrUpdateTaint(node *Node, taint *Taint) (*Node, bool, error) {
|
||||
updated := false
|
||||
for i := range nodeTaints {
|
||||
if taint.MatchTaint(&nodeTaints[i]) {
|
||||
if api.Semantic.DeepEqual(taint, nodeTaints[i]) {
|
||||
if helper.Semantic.DeepEqual(taint, nodeTaints[i]) {
|
||||
return newNode, false, nil
|
||||
}
|
||||
newTaints = append(newTaints, *taint)
|
||||
|
@ -12,7 +12,7 @@ go_library(
|
||||
srcs = ["validation.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
@ -68,7 +68,7 @@ func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath
|
||||
func validateContainerResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := validateResourceName(value, fldPath)
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !api.IsStandardContainerResourceName(value) {
|
||||
if !helper.IsStandardContainerResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers"))
|
||||
}
|
||||
}
|
||||
@ -79,7 +79,7 @@ func validateContainerResourceName(value string, fldPath *field.Path) field.Erro
|
||||
func ValidateResourceQuantityValue(resource string, value resource.Quantity, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateNonnegativeQuantity(value, fldPath)...)
|
||||
if api.IsIntegerResourceName(resource) {
|
||||
if helper.IsIntegerResourceName(resource) {
|
||||
if value.MilliValue()%int64(1000) != int64(0) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value, isNotIntegerErrorMsg))
|
||||
}
|
||||
@ -108,7 +108,7 @@ func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
}
|
||||
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !api.IsStandardResourceName(value) {
|
||||
if !helper.IsStandardResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource type or fully qualified"))
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/service:go_default_library",
|
||||
"//pkg/api/util:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
@ -67,6 +68,7 @@ go_test(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/service:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/testing:go_default_library",
|
||||
|
@ -41,6 +41,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
apiservice "k8s.io/kubernetes/pkg/api/service"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/capabilities"
|
||||
@ -115,13 +116,13 @@ func ValidatePodSpecificAnnotations(annotations map[string]string, spec *api.Pod
|
||||
allErrs = append(allErrs, ValidateSeccompPodAnnotations(annotations, fldPath)...)
|
||||
allErrs = append(allErrs, ValidateAppArmorPodAnnotations(annotations, spec, fldPath)...)
|
||||
|
||||
sysctls, err := api.SysctlsFromPodAnnotation(annotations[api.SysctlsPodAnnotationKey])
|
||||
sysctls, err := helper.SysctlsFromPodAnnotation(annotations[api.SysctlsPodAnnotationKey])
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Key(api.SysctlsPodAnnotationKey), annotations[api.SysctlsPodAnnotationKey], err.Error()))
|
||||
} else {
|
||||
allErrs = append(allErrs, validateSysctls(sysctls, fldPath.Key(api.SysctlsPodAnnotationKey))...)
|
||||
}
|
||||
unsafeSysctls, err := api.SysctlsFromPodAnnotation(annotations[api.UnsafeSysctlsPodAnnotationKey])
|
||||
unsafeSysctls, err := helper.SysctlsFromPodAnnotation(annotations[api.UnsafeSysctlsPodAnnotationKey])
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Key(api.UnsafeSysctlsPodAnnotationKey), annotations[api.UnsafeSysctlsPodAnnotationKey], err.Error()))
|
||||
} else {
|
||||
@ -139,7 +140,7 @@ func ValidatePodSpecificAnnotations(annotations map[string]string, spec *api.Pod
|
||||
func ValidateTolerationsInPodAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
tolerations, err := api.GetTolerationsFromPodAnnotations(annotations)
|
||||
tolerations, err := helper.GetTolerationsFromPodAnnotations(annotations)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, api.TolerationsAnnotationKey, err.Error()))
|
||||
return allErrs
|
||||
@ -156,7 +157,7 @@ func ValidateTolerationsInPodAnnotations(annotations map[string]string, fldPath
|
||||
func ValidateAffinityInPodAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
affinity, err := api.GetAffinityFromPodAnnotations(annotations)
|
||||
affinity, err := helper.GetAffinityFromPodAnnotations(annotations)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, api.AffinityAnnotationKey, err.Error()))
|
||||
return allErrs
|
||||
@ -2625,7 +2626,7 @@ func validateServiceFields(service *api.Service) field.ErrorList {
|
||||
allErrs = append(allErrs, field.NotSupported(specPath.Child("sessionAffinity"), service.Spec.SessionAffinity, supportedSessionAffinityType.List()))
|
||||
}
|
||||
|
||||
if api.IsServiceIPSet(service) {
|
||||
if helper.IsServiceIPSet(service) {
|
||||
if ip := net.ParseIP(service.Spec.ClusterIP); ip == nil {
|
||||
allErrs = append(allErrs, field.Invalid(specPath.Child("clusterIP"), service.Spec.ClusterIP, "must be empty, 'None', or a valid IP address"))
|
||||
}
|
||||
@ -2958,7 +2959,7 @@ func ValidateReadOnlyPersistentDisks(volumes []api.Volume, fldPath *field.Path)
|
||||
func ValidateTaintsInNodeAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
taints, err := api.GetTaintsFromNodeAnnotations(annotations)
|
||||
taints, err := helper.GetTaintsFromNodeAnnotations(annotations)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, api.TaintsAnnotationKey, err.Error()))
|
||||
return allErrs
|
||||
@ -3115,7 +3116,7 @@ func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
}
|
||||
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !api.IsStandardResourceName(value) {
|
||||
if !helper.IsStandardResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource type or fully qualified"))
|
||||
}
|
||||
}
|
||||
@ -3128,7 +3129,7 @@ func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
func validateContainerResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := validateResourceName(value, fldPath)
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !api.IsStandardContainerResourceName(value) {
|
||||
if !helper.IsStandardContainerResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers"))
|
||||
}
|
||||
}
|
||||
@ -3140,7 +3141,7 @@ func validateContainerResourceName(value string, fldPath *field.Path) field.Erro
|
||||
func ValidateResourceQuotaResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := validateResourceName(value, fldPath)
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !api.IsStandardQuotaResourceName(value) {
|
||||
if !helper.IsStandardQuotaResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, isInvalidQuotaResource))
|
||||
}
|
||||
}
|
||||
@ -3158,7 +3159,7 @@ func validateLimitRangeTypeName(value string, fldPath *field.Path) field.ErrorLi
|
||||
}
|
||||
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !api.IsStandardLimitRangeType(value) {
|
||||
if !helper.IsStandardLimitRangeType(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard limit type or fully qualified"))
|
||||
}
|
||||
}
|
||||
@ -3494,11 +3495,11 @@ func validateResourceQuotaScopes(resourceQuotaSpec *api.ResourceQuotaSpec, fld *
|
||||
fldPath := fld.Child("scopes")
|
||||
scopeSet := sets.NewString()
|
||||
for _, scope := range resourceQuotaSpec.Scopes {
|
||||
if !api.IsStandardResourceQuotaScope(string(scope)) {
|
||||
if !helper.IsStandardResourceQuotaScope(string(scope)) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, resourceQuotaSpec.Scopes, "unsupported scope"))
|
||||
}
|
||||
for _, k := range hardLimits.List() {
|
||||
if api.IsStandardQuotaResourceName(k) && !api.IsResourceQuotaScopeValidForResource(scope, k) {
|
||||
if helper.IsStandardQuotaResourceName(k) && !helper.IsResourceQuotaScopeValidForResource(scope, k) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, resourceQuotaSpec.Scopes, "unsupported scope applied to resource"))
|
||||
}
|
||||
}
|
||||
@ -3563,7 +3564,7 @@ func ValidateResourceQuotaSpec(resourceQuotaSpec *api.ResourceQuotaSpec, fld *fi
|
||||
func ValidateResourceQuantityValue(resource string, value resource.Quantity, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateNonnegativeQuantity(value, fldPath)...)
|
||||
if api.IsIntegerResourceName(resource) {
|
||||
if helper.IsIntegerResourceName(resource) {
|
||||
if value.MilliValue()%int64(1000) != int64(0) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value, isNotIntegerErrorMsg))
|
||||
}
|
||||
@ -3641,7 +3642,7 @@ func validateFinalizerName(stringValue string, fldPath *field.Path) field.ErrorL
|
||||
func validateKubeFinalizerName(stringValue string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(strings.Split(stringValue, "/")) == 1 {
|
||||
if !api.IsStandardFinalizerName(stringValue) {
|
||||
if !helper.IsStandardFinalizerName(stringValue) {
|
||||
return append(allErrs, field.Invalid(fldPath, stringValue, "name is neither a standard finalizer name nor is it fully qualified"))
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/service"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/capabilities"
|
||||
@ -3712,10 +3713,10 @@ func TestValidatePod(t *testing.T) {
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("10"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("10"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("20"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("20"),
|
||||
},
|
||||
},
|
||||
TerminationMessagePolicy: "File",
|
||||
@ -3737,10 +3738,10 @@ func TestValidatePod(t *testing.T) {
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("10"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("10"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("20"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("20"),
|
||||
},
|
||||
},
|
||||
TerminationMessagePolicy: "File",
|
||||
@ -4211,10 +4212,10 @@ func TestValidatePod(t *testing.T) {
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("2"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("2"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("1"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -4233,7 +4234,7 @@ func TestValidatePod(t *testing.T) {
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("500m"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("500m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -4252,7 +4253,7 @@ func TestValidatePod(t *testing.T) {
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("500m"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("500m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -4272,10 +4273,10 @@ func TestValidatePod(t *testing.T) {
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("2.5"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("2.5"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -4294,10 +4295,10 @@ func TestValidatePod(t *testing.T) {
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Resources: api.ResourceRequirements{
|
||||
Requests: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
},
|
||||
Limits: api.ResourceList{
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("2.5"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("2.5"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -6739,8 +6740,8 @@ func TestValidateNodeUpdate(t *testing.T) {
|
||||
Capacity: api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("10"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("10G"),
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
api.OpaqueIntResourceName("B"): resource.MustParse("10"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
helper.OpaqueIntResourceName("B"): resource.MustParse("10"),
|
||||
},
|
||||
},
|
||||
}, true},
|
||||
@ -6756,7 +6757,7 @@ func TestValidateNodeUpdate(t *testing.T) {
|
||||
Capacity: api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("10"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("10G"),
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("500m"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("500m"),
|
||||
},
|
||||
},
|
||||
}, false},
|
||||
@ -6772,12 +6773,12 @@ func TestValidateNodeUpdate(t *testing.T) {
|
||||
Capacity: api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("10"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("10G"),
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("5"),
|
||||
},
|
||||
Allocatable: api.ResourceList{
|
||||
api.ResourceName(api.ResourceCPU): resource.MustParse("10"),
|
||||
api.ResourceName(api.ResourceMemory): resource.MustParse("10G"),
|
||||
api.OpaqueIntResourceName("A"): resource.MustParse("4.5"),
|
||||
helper.OpaqueIntResourceName("A"): resource.MustParse("4.5"),
|
||||
},
|
||||
},
|
||||
}, false},
|
||||
|
@ -65,7 +65,6 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStateTerminated, InType: reflect.TypeOf(&ContainerStateTerminated{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStateWaiting, InType: reflect.TypeOf(&ContainerStateWaiting{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStatus, InType: reflect.TypeOf(&ContainerStatus{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ConversionError, InType: reflect.TypeOf(&ConversionError{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DaemonEndpoint, InType: reflect.TypeOf(&DaemonEndpoint{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DeleteOptions, InType: reflect.TypeOf(&DeleteOptions{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DownwardAPIProjection, InType: reflect.TypeOf(&DownwardAPIProjection{})},
|
||||
@ -707,31 +706,6 @@ func DeepCopy_api_ContainerStatus(in interface{}, out interface{}, c *conversion
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_api_ConversionError(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*ConversionError)
|
||||
out := out.(*ConversionError)
|
||||
*out = *in
|
||||
// in.In is kind 'Interface'
|
||||
if in.In != nil {
|
||||
if newVal, err := c.DeepCopy(&in.In); err != nil {
|
||||
return err
|
||||
} else {
|
||||
out.In = *newVal.(*interface{})
|
||||
}
|
||||
}
|
||||
// in.Out is kind 'Interface'
|
||||
if in.Out != nil {
|
||||
if newVal, err := c.DeepCopy(&in.Out); err != nil {
|
||||
return err
|
||||
} else {
|
||||
out.Out = *newVal.(*interface{})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_api_DaemonEndpoint(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*DaemonEndpoint)
|
||||
|
@ -27,6 +27,7 @@ go_test(
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/client-go/kubernetes/fake",
|
||||
"//vendor:k8s.io/client-go/pkg/api",
|
||||
"//vendor:k8s.io/client-go/pkg/api/helper",
|
||||
"//vendor:k8s.io/client-go/pkg/api/v1",
|
||||
"//vendor:k8s.io/client-go/testing",
|
||||
],
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/pkg/api"
|
||||
"k8s.io/client-go/pkg/api/helper"
|
||||
"k8s.io/client-go/pkg/api/v1"
|
||||
core "k8s.io/client-go/testing"
|
||||
bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api"
|
||||
@ -59,7 +59,7 @@ func verifyActions(t *testing.T, expected, actual []core.Action) {
|
||||
}
|
||||
|
||||
e := expected[i]
|
||||
if !api.Semantic.DeepEqual(e, a) {
|
||||
if !helper.Semantic.DeepEqual(e, a) {
|
||||
t.Errorf("Expected\n\t%s\ngot\n\t%s", spew.Sdump(e), spew.Sdump(a))
|
||||
continue
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/externalversions/core/v1:go_default_library",
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
|
||||
@ -248,7 +249,7 @@ func (tc *NoExecuteTaintManager) PodUpdated(oldPod *v1.Pod, newPod *v1.Pod) {
|
||||
newTolerations = newPod.Spec.Tolerations
|
||||
}
|
||||
|
||||
if oldPod != nil && newPod != nil && api.Semantic.DeepEqual(oldTolerations, newTolerations) && oldPod.Spec.NodeName == newPod.Spec.NodeName {
|
||||
if oldPod != nil && newPod != nil && helper.Semantic.DeepEqual(oldTolerations, newTolerations) && oldPod.Spec.NodeName == newPod.Spec.NodeName {
|
||||
return
|
||||
}
|
||||
updateItem := &podUpdateItem{
|
||||
@ -274,7 +275,7 @@ func (tc *NoExecuteTaintManager) NodeUpdated(oldNode *v1.Node, newNode *v1.Node)
|
||||
}
|
||||
newTaints = getNoExecuteTaints(newTaints)
|
||||
|
||||
if oldNode != nil && newNode != nil && api.Semantic.DeepEqual(oldTaints, newTaints) {
|
||||
if oldNode != nil && newNode != nil && helper.Semantic.DeepEqual(oldTaints, newTaints) {
|
||||
return
|
||||
}
|
||||
updateItem := &nodeUpdateItem{
|
||||
|
@ -51,6 +51,7 @@ go_library(
|
||||
"//federation/apis/federation/v1beta1:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/annotations:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/util:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/apps:go_default_library",
|
||||
@ -139,6 +140,7 @@ go_test(
|
||||
deps = [
|
||||
"//federation/apis/federation/v1beta1:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/testing:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
|
@ -68,6 +68,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/annotations:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/api/validation:go_default_library",
|
||||
"//pkg/apis/apps/v1beta1:go_default_library",
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
@ -157,7 +158,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm
|
||||
Timestamps: cmdutil.GetFlagBool(cmd, "timestamps"),
|
||||
}
|
||||
if sinceTime := cmdutil.GetFlagString(cmd, "since-time"); len(sinceTime) > 0 {
|
||||
t, err := api.ParseRFC3339(sinceTime, metav1.Now)
|
||||
t, err := helper.ParseRFC3339(sinceTime, metav1.Now)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
@ -278,7 +279,7 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args
|
||||
}
|
||||
// Update the existing replication controller with pointers to the 'next' controller
|
||||
// and adding the <deploymentKey> label if necessary to distinguish it from the 'next' controller.
|
||||
oldHash, err := api.HashObject(oldRc, codec)
|
||||
oldHash, err := helper.HashObject(oldRc, codec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/util/integer"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/client/retry"
|
||||
@ -625,7 +626,7 @@ func CreateNewControllerFromCurrentController(rcClient coreclient.ReplicationCon
|
||||
newRc.Spec.Template.Spec.Containers[containerIndex].ImagePullPolicy = cfg.PullPolicy
|
||||
}
|
||||
|
||||
newHash, err := api.HashObject(newRc, codec)
|
||||
newHash, err := helper.HashObject(newRc, codec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import (
|
||||
manualfake "k8s.io/client-go/rest/fake"
|
||||
testcore "k8s.io/client-go/testing"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
@ -1076,7 +1077,7 @@ func TestRollingUpdater_multipleContainersInPod(t *testing.T) {
|
||||
|
||||
codec := testapi.Default.Codec()
|
||||
|
||||
deploymentHash, err := api.HashObject(test.newRc, codec)
|
||||
deploymentHash, err := helper.HashObject(test.newRc, codec)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/api/v1/pod:go_default_library",
|
||||
"//pkg/api/validation:go_default_library",
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilyaml "k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
||||
@ -76,7 +77,7 @@ func applyDefaults(pod *api.Pod, source string, isFile bool, nodeName types.Node
|
||||
if isFile {
|
||||
// Applying the default Taint tolerations to static pods,
|
||||
// so they are not evicted when there are node problems.
|
||||
api.AddOrUpdateTolerationInPod(pod, &api.Toleration{
|
||||
helper.AddOrUpdateTolerationInPod(pod, &api.Toleration{
|
||||
Operator: "Exists",
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
})
|
||||
|
@ -62,6 +62,7 @@ go_library(
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/annotations:go_default_library",
|
||||
"//pkg/api/events:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/apis/apps:go_default_library",
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/batch:go_default_library",
|
||||
|
@ -47,6 +47,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/annotations"
|
||||
"k8s.io/kubernetes/pkg/api/events"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
@ -847,7 +848,7 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSe
|
||||
w.Write(LEVEL_0, "Name:\t%s\n", pv.Name)
|
||||
printLabelsMultiline(w, "Labels", pv.Labels)
|
||||
printAnnotationsMultiline(w, "Annotations", pv.Annotations)
|
||||
w.Write(LEVEL_0, "StorageClass:\t%s\n", api.GetPersistentVolumeClass(pv))
|
||||
w.Write(LEVEL_0, "StorageClass:\t%s\n", helper.GetPersistentVolumeClass(pv))
|
||||
w.Write(LEVEL_0, "Status:\t%s\n", pv.Status.Phase)
|
||||
if pv.Spec.ClaimRef != nil {
|
||||
w.Write(LEVEL_0, "Claim:\t%s\n", pv.Spec.ClaimRef.Namespace+"/"+pv.Spec.ClaimRef.Name)
|
||||
@ -855,7 +856,7 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSe
|
||||
w.Write(LEVEL_0, "Claim:\t%s\n", "")
|
||||
}
|
||||
w.Write(LEVEL_0, "Reclaim Policy:\t%v\n", pv.Spec.PersistentVolumeReclaimPolicy)
|
||||
w.Write(LEVEL_0, "Access Modes:\t%s\n", api.GetAccessModesAsString(pv.Spec.AccessModes))
|
||||
w.Write(LEVEL_0, "Access Modes:\t%s\n", helper.GetAccessModesAsString(pv.Spec.AccessModes))
|
||||
w.Write(LEVEL_0, "Capacity:\t%s\n", storage.String())
|
||||
w.Write(LEVEL_0, "Message:\t%s\n", pv.Status.Message)
|
||||
w.Write(LEVEL_0, "Source:\n")
|
||||
@ -915,7 +916,7 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, descri
|
||||
capacity := ""
|
||||
accessModes := ""
|
||||
if pvc.Spec.VolumeName != "" {
|
||||
accessModes = api.GetAccessModesAsString(pvc.Status.AccessModes)
|
||||
accessModes = helper.GetAccessModesAsString(pvc.Status.AccessModes)
|
||||
storage = pvc.Status.Capacity[api.ResourceStorage]
|
||||
capacity = storage.String()
|
||||
}
|
||||
@ -926,7 +927,7 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, descri
|
||||
w := NewPrefixWriter(out)
|
||||
w.Write(LEVEL_0, "Name:\t%s\n", pvc.Name)
|
||||
w.Write(LEVEL_0, "Namespace:\t%s\n", pvc.Namespace)
|
||||
w.Write(LEVEL_0, "StorageClass:\t%s\n", api.GetPersistentVolumeClaimClass(pvc))
|
||||
w.Write(LEVEL_0, "StorageClass:\t%s\n", helper.GetPersistentVolumeClaimClass(pvc))
|
||||
w.Write(LEVEL_0, "Status:\t%v\n", pvc.Status.Phase)
|
||||
w.Write(LEVEL_0, "Volume:\t%s\n", pvc.Spec.VolumeName)
|
||||
printLabelsMultiline(w, "Labels", pvc.Labels)
|
||||
@ -1225,7 +1226,7 @@ func describeVolumeClaimTemplates(templates []api.PersistentVolumeClaim, w Prefi
|
||||
w.Write(LEVEL_0, "Volume Claims:\n")
|
||||
for _, pvc := range templates {
|
||||
w.Write(LEVEL_1, "Name:\t%s\n", pvc.Name)
|
||||
w.Write(LEVEL_1, "StorageClass:\t%s\n", api.GetPersistentVolumeClaimClass(&pvc))
|
||||
w.Write(LEVEL_1, "StorageClass:\t%s\n", helper.GetPersistentVolumeClaimClass(&pvc))
|
||||
printLabelsMultilineWithIndent(w, " ", "Labels", "\t", pvc.Labels, sets.NewString())
|
||||
printLabelsMultilineWithIndent(w, " ", "Annotations", "\t", pvc.Annotations, sets.NewString())
|
||||
if capacity, ok := pvc.Spec.Resources.Requests[api.ResourceStorage]; ok {
|
||||
|
@ -32,6 +32,7 @@ import (
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/events"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
@ -1175,7 +1176,7 @@ func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, options printe
|
||||
claimRefUID += pv.Spec.ClaimRef.Name
|
||||
}
|
||||
|
||||
modesStr := api.GetAccessModesAsString(pv.Spec.AccessModes)
|
||||
modesStr := helper.GetAccessModesAsString(pv.Spec.AccessModes)
|
||||
reclaimPolicyStr := string(pv.Spec.PersistentVolumeReclaimPolicy)
|
||||
|
||||
aQty := pv.Spec.Capacity[api.ResourceStorage]
|
||||
@ -1186,7 +1187,7 @@ func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, options printe
|
||||
aSize, modesStr, reclaimPolicyStr,
|
||||
pv.Status.Phase,
|
||||
claimRefUID,
|
||||
api.GetPersistentVolumeClass(pv),
|
||||
helper.GetPersistentVolumeClass(pv),
|
||||
pv.Status.Reason,
|
||||
translateTimestamp(pv.CreationTimestamp),
|
||||
); err != nil {
|
||||
@ -1224,12 +1225,12 @@ func printPersistentVolumeClaim(pvc *api.PersistentVolumeClaim, w io.Writer, opt
|
||||
capacity := ""
|
||||
accessModes := ""
|
||||
if pvc.Spec.VolumeName != "" {
|
||||
accessModes = api.GetAccessModesAsString(pvc.Status.AccessModes)
|
||||
accessModes = helper.GetAccessModesAsString(pvc.Status.AccessModes)
|
||||
storage = pvc.Status.Capacity[api.ResourceStorage]
|
||||
capacity = storage.String()
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s", name, phase, pvc.Spec.VolumeName, capacity, accessModes, api.GetPersistentVolumeClaimClass(pvc), translateTimestamp(pvc.CreationTimestamp)); err != nil {
|
||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s", name, phase, pvc.Spec.VolumeName, capacity, accessModes, helper.GetPersistentVolumeClaimClass(pvc), translateTimestamp(pvc.CreationTimestamp)); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := fmt.Fprint(w, AppendLabels(pvc.Labels, options.ColumnLabels)); err != nil {
|
||||
|
@ -14,6 +14,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/service:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/proxy:go_default_library",
|
||||
|
@ -42,6 +42,7 @@ import (
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/client-go/util/flowcontrol"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
apiservice "k8s.io/kubernetes/pkg/api/service"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/proxy"
|
||||
@ -172,7 +173,7 @@ func newServiceInfo(serviceName proxy.ServicePortName, port *api.ServicePort, se
|
||||
protocol: port.Protocol,
|
||||
nodePort: int(port.NodePort),
|
||||
// Deep-copy in case the service instance changes
|
||||
loadBalancerStatus: *api.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer),
|
||||
loadBalancerStatus: *helper.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer),
|
||||
sessionAffinityType: service.Spec.SessionAffinity,
|
||||
stickyMaxAgeMinutes: 180, // TODO: paramaterize this in the API.
|
||||
externalIPs: make([]string, len(service.Spec.ExternalIPs)),
|
||||
@ -462,7 +463,7 @@ func buildNewServiceMap(allServices []*api.Service, oldServiceMap proxyServiceMa
|
||||
}
|
||||
|
||||
// if ClusterIP is "None" or empty, skip proxying
|
||||
if !api.IsServiceIPSet(service) {
|
||||
if !helper.IsServiceIPSet(service) {
|
||||
glog.V(3).Infof("Skipping service %s due to clusterIP = %q", svcName, service.Spec.ClusterIP)
|
||||
continue
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/proxy:go_default_library",
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//pkg/util/exec:go_default_library",
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/proxy"
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
@ -405,7 +406,7 @@ func (proxier *Proxier) OnServiceUpdate(services []*api.Service) {
|
||||
activeServices := make(map[proxy.ServicePortName]bool) // use a map as a set
|
||||
for _, service := range services {
|
||||
// if ClusterIP is "None" or empty, skip proxying
|
||||
if !api.IsServiceIPSet(service) {
|
||||
if !helper.IsServiceIPSet(service) {
|
||||
glog.V(3).Infof("Skipping service %s due to clusterIP = %q", types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, service.Spec.ClusterIP)
|
||||
continue
|
||||
}
|
||||
@ -460,7 +461,7 @@ func (proxier *Proxier) OnServiceUpdate(services []*api.Service) {
|
||||
info.portal.port = int(servicePort.Port)
|
||||
info.externalIPs = service.Spec.ExternalIPs
|
||||
// Deep-copy in case the service instance changes
|
||||
info.loadBalancerStatus = *api.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer)
|
||||
info.loadBalancerStatus = *helper.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer)
|
||||
info.nodePort = int(servicePort.NodePort)
|
||||
info.sessionAffinityType = service.Spec.SessionAffinity
|
||||
glog.V(4).Infof("info: %#v", info)
|
||||
@ -509,7 +510,7 @@ func sameConfig(info *ServiceInfo, service *api.Service, port *api.ServicePort)
|
||||
if !ipsEqual(info.externalIPs, service.Spec.ExternalIPs) {
|
||||
return false
|
||||
}
|
||||
if !api.LoadBalancerStatusEqual(&info.loadBalancerStatus, &service.Status.LoadBalancer) {
|
||||
if !helper.LoadBalancerStatusEqual(&info.loadBalancerStatus, &service.Status.LoadBalancer) {
|
||||
return false
|
||||
}
|
||||
if info.sessionAffinityType != service.Spec.SessionAffinity {
|
||||
|
@ -21,6 +21,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/proxy:go_default_library",
|
||||
"//pkg/util/exec:go_default_library",
|
||||
"//pkg/util/ipconfig:go_default_library",
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/proxy"
|
||||
"k8s.io/kubernetes/pkg/util/netsh"
|
||||
)
|
||||
@ -322,7 +323,7 @@ func (proxier *Proxier) OnServiceUpdate(services []*api.Service) {
|
||||
activeServicePortPortals := make(map[ServicePortPortalName]bool) // use a map as a set
|
||||
for _, service := range services {
|
||||
// if ClusterIP is "None" or empty, skip proxying
|
||||
if !api.IsServiceIPSet(service) {
|
||||
if !helper.IsServiceIPSet(service) {
|
||||
glog.V(3).Infof("Skipping service %s due to clusterIP = %q", types.NamespacedName{Namespace: service.Namespace, Name: service.Name}, service.Spec.ClusterIP)
|
||||
continue
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/api/validation:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/externalversions"
|
||||
@ -104,7 +105,7 @@ func (p *pvcEvaluator) Constraints(required []api.ResourceName, item runtime.Obj
|
||||
|
||||
// these are the items that we will be handling based on the objects actual storage-class
|
||||
pvcRequiredSet := append([]api.ResourceName{}, pvcResources...)
|
||||
if storageClassRef := api.GetPersistentVolumeClaimClass(pvc); len(storageClassRef) > 0 {
|
||||
if storageClassRef := helper.GetPersistentVolumeClaimClass(pvc); len(storageClassRef) > 0 {
|
||||
pvcRequiredSet = append(pvcRequiredSet, ResourceByStorageClass(storageClassRef, api.ResourcePersistentVolumeClaims))
|
||||
pvcRequiredSet = append(pvcRequiredSet, ResourceByStorageClass(storageClassRef, api.ResourceRequestsStorage))
|
||||
}
|
||||
@ -175,7 +176,7 @@ func (p *pvcEvaluator) Usage(item runtime.Object) (api.ResourceList, error) {
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
storageClassRef := api.GetPersistentVolumeClaimClass(pvc)
|
||||
storageClassRef := helper.GetPersistentVolumeClaimClass(pvc)
|
||||
|
||||
// charge for claim
|
||||
result[api.ResourcePersistentVolumeClaims] = resource.MustParse("1")
|
||||
|
@ -18,6 +18,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/validation:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
apistorage "k8s.io/apiserver/pkg/storage"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
)
|
||||
|
||||
@ -110,7 +111,7 @@ func (rcStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime
|
||||
updateErrorList := validation.ValidateReplicationControllerUpdate(newRc, oldRc)
|
||||
errs := append(validationErrorList, updateErrorList...)
|
||||
|
||||
for key, value := range api.NonConvertibleFields(oldRc.Annotations) {
|
||||
for key, value := range helper.NonConvertibleFields(oldRc.Annotations) {
|
||||
parts := strings.Split(key, "/")
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
|
@ -20,6 +20,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/service:go_default_library",
|
||||
"//pkg/api/validation:go_default_library",
|
||||
"//pkg/capabilities:go_default_library",
|
||||
|
@ -14,6 +14,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||
"//pkg/client/retry:go_default_library",
|
||||
"//pkg/registry/core/rangeallocation:go_default_library",
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/client/retry"
|
||||
"k8s.io/kubernetes/pkg/registry/core/rangeallocation"
|
||||
@ -128,7 +129,7 @@ func (c *Repair) runOnce() error {
|
||||
rebuilt := ipallocator.NewCIDRRange(c.network)
|
||||
// Check every Service's ClusterIP, and rebuild the state as we think it should be.
|
||||
for _, svc := range list.Items {
|
||||
if !api.IsServiceIPSet(&svc) {
|
||||
if !helper.IsServiceIPSet(&svc) {
|
||||
// didn't need a cluster IP
|
||||
continue
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
apiservice "k8s.io/kubernetes/pkg/api/service"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
@ -87,13 +88,13 @@ func (rs *REST) Create(ctx genericapirequest.Context, obj runtime.Object) (runti
|
||||
releaseServiceIP := false
|
||||
defer func() {
|
||||
if releaseServiceIP {
|
||||
if api.IsServiceIPSet(service) {
|
||||
if helper.IsServiceIPSet(service) {
|
||||
rs.serviceIPs.Release(net.ParseIP(service.Spec.ClusterIP))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if api.IsServiceIPRequested(service) {
|
||||
if helper.IsServiceIPRequested(service) {
|
||||
// Allocate next available.
|
||||
ip, err := rs.serviceIPs.AllocateNext()
|
||||
if err != nil {
|
||||
@ -104,7 +105,7 @@ func (rs *REST) Create(ctx genericapirequest.Context, obj runtime.Object) (runti
|
||||
}
|
||||
service.Spec.ClusterIP = ip.String()
|
||||
releaseServiceIP = true
|
||||
} else if api.IsServiceIPSet(service) {
|
||||
} else if helper.IsServiceIPSet(service) {
|
||||
// Try to respect the requested IP.
|
||||
if err := rs.serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil {
|
||||
// TODO: when validation becomes versioned, this gets more complicated.
|
||||
@ -226,7 +227,7 @@ func (rs *REST) Delete(ctx genericapirequest.Context, id string) (runtime.Object
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if api.IsServiceIPSet(service) {
|
||||
if helper.IsServiceIPSet(service) {
|
||||
rs.serviceIPs.Release(net.ParseIP(service.Spec.ClusterIP))
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ go_test(
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
],
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
)
|
||||
|
||||
@ -268,7 +268,7 @@ func TestComputeReconciledRole(t *testing.T) {
|
||||
t.Errorf("%s: Expected\n\t%v\ngot\n\t%v", k, tc.expectedReconciliationNeeded, reconciliationNeeded)
|
||||
continue
|
||||
}
|
||||
if reconciliationNeeded && !api.Semantic.DeepEqual(result.Role.(ClusterRoleRuleOwner).ClusterRole, tc.expectedReconciledRole) {
|
||||
if reconciliationNeeded && !helper.Semantic.DeepEqual(result.Role.(ClusterRoleRuleOwner).ClusterRole, tc.expectedReconciledRole) {
|
||||
t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, tc.expectedReconciledRole, result.Role)
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ package reconciliation
|
||||
import (
|
||||
"testing"
|
||||
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
)
|
||||
|
||||
@ -81,10 +81,10 @@ func TestDiffObjectReferenceLists(t *testing.T) {
|
||||
|
||||
for k, tc := range tests {
|
||||
onlyA, onlyB := diffSubjectLists(tc.A, tc.B)
|
||||
if !api.Semantic.DeepEqual(onlyA, tc.ExpectedOnlyA) {
|
||||
if !helper.Semantic.DeepEqual(onlyA, tc.ExpectedOnlyA) {
|
||||
t.Errorf("%s: Expected %#v, got %#v", k, tc.ExpectedOnlyA, onlyA)
|
||||
}
|
||||
if !api.Semantic.DeepEqual(onlyB, tc.ExpectedOnlyB) {
|
||||
if !helper.Semantic.DeepEqual(onlyB, tc.ExpectedOnlyB) {
|
||||
t.Errorf("%s: Expected %#v, got %#v", k, tc.ExpectedOnlyB, onlyB)
|
||||
}
|
||||
}
|
||||
@ -174,7 +174,7 @@ func TestComputeUpdate(t *testing.T) {
|
||||
t.Errorf("%s: Expected\n\t%v\ngot\n\t%v (%v)", k, tc.ExpectedUpdateNeeded, updateNeeded, result.Operation)
|
||||
continue
|
||||
}
|
||||
if updateNeeded && !api.Semantic.DeepEqual(updatedBinding, tc.ExpectedUpdatedBinding) {
|
||||
if updateNeeded && !helper.Semantic.DeepEqual(updatedBinding, tc.ExpectedUpdatedBinding) {
|
||||
t.Errorf("%s: Expected\n\t%v %v\ngot\n\t%v %v", k, tc.ExpectedUpdatedBinding.RoleRef, tc.ExpectedUpdatedBinding.Subjects, updatedBinding.RoleRef, updatedBinding.Subjects)
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
],
|
||||
)
|
||||
@ -26,7 +27,10 @@ go_test(
|
||||
srcs = ["mustmatchpatterns_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = ["//pkg/api:go_default_library"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
)
|
||||
|
||||
// mustMatchPatterns implements the CapabilitiesStrategy interface
|
||||
@ -59,7 +60,7 @@ func (s *mustMatchPatterns) validateAnnotation(pod *api.Pod, key string) field.E
|
||||
|
||||
fieldPath := field.NewPath("pod", "metadata", "annotations").Key(key)
|
||||
|
||||
sysctls, err := api.SysctlsFromPodAnnotation(pod.Annotations[key])
|
||||
sysctls, err := helper.SysctlsFromPodAnnotation(pod.Annotations[key])
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fieldPath, pod.Annotations[key], err.Error()))
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
)
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
@ -75,7 +76,7 @@ func TestValidate(t *testing.T) {
|
||||
}
|
||||
testAllowed := func(key string, category string) {
|
||||
pod.Annotations = map[string]string{
|
||||
key: api.PodAnnotationsFromSysctls(sysctls),
|
||||
key: helper.PodAnnotationsFromSysctls(sysctls),
|
||||
}
|
||||
errs = strategy.Validate(pod)
|
||||
if len(errs) != 0 {
|
||||
@ -85,7 +86,7 @@ func TestValidate(t *testing.T) {
|
||||
testDisallowed := func(key string, category string) {
|
||||
for _, s := range v.disallowed {
|
||||
pod.Annotations = map[string]string{
|
||||
key: api.PodAnnotationsFromSysctls([]api.Sysctl{{Name: s, Value: "dummy"}}),
|
||||
key: helper.PodAnnotationsFromSysctls([]api.Sysctl{{Name: s, Value: "dummy"}}),
|
||||
}
|
||||
errs = strategy.Validate(pod)
|
||||
if len(errs) == 0 {
|
||||
|
@ -15,6 +15,7 @@ go_test(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apiserver/pkg/admission",
|
||||
],
|
||||
@ -26,6 +27,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apiserver/pkg/admission",
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -97,7 +98,7 @@ func (p *plugin) Admit(attributes admission.Attributes) (err error) {
|
||||
}
|
||||
|
||||
if !toleratesNodeNotReady {
|
||||
api.AddOrUpdateTolerationInPod(pod, &api.Toleration{
|
||||
helper.AddOrUpdateTolerationInPod(pod, &api.Toleration{
|
||||
Key: metav1.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
@ -106,7 +107,7 @@ func (p *plugin) Admit(attributes admission.Attributes) (err error) {
|
||||
}
|
||||
|
||||
if !toleratesNodeUnreachable {
|
||||
api.AddOrUpdateTolerationInPod(pod, &api.Toleration{
|
||||
helper.AddOrUpdateTolerationInPod(pod, &api.Toleration{
|
||||
Key: metav1.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
)
|
||||
|
||||
func TestForgivenessAdmission(t *testing.T) {
|
||||
@ -266,7 +267,7 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
t.Errorf("[%s]: unexpected error %v for pod %+v", test.description, err, test.requestedPod)
|
||||
}
|
||||
|
||||
if !api.Semantic.DeepEqual(test.expectedPod.Annotations, test.requestedPod.Annotations) {
|
||||
if !helper.Semantic.DeepEqual(test.expectedPod.Annotations, test.requestedPod.Annotations) {
|
||||
t.Errorf("[%s]: expected %#v got %#v", test.description, test.expectedPod.Annotations, test.requestedPod.Annotations)
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ go_test(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/extensions/internalversion:go_default_library",
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
kapi "k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
extensionslisters "k8s.io/kubernetes/pkg/client/listers/extensions/internalversion"
|
||||
@ -1172,8 +1173,8 @@ func TestAdmitSysctls(t *testing.T) {
|
||||
}
|
||||
return sysctls
|
||||
}
|
||||
pod.Annotations[kapi.SysctlsPodAnnotationKey] = kapi.PodAnnotationsFromSysctls(dummySysctls(safeSysctls))
|
||||
pod.Annotations[kapi.UnsafeSysctlsPodAnnotationKey] = kapi.PodAnnotationsFromSysctls(dummySysctls(unsafeSysctls))
|
||||
pod.Annotations[kapi.SysctlsPodAnnotationKey] = helper.PodAnnotationsFromSysctls(dummySysctls(safeSysctls))
|
||||
pod.Annotations[kapi.UnsafeSysctlsPodAnnotationKey] = helper.PodAnnotationsFromSysctls(dummySysctls(unsafeSysctls))
|
||||
return pod
|
||||
}
|
||||
|
||||
@ -1319,7 +1320,7 @@ func TestAdmitSysctls(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range tests {
|
||||
origSafeSysctls, origUnsafeSysctls, err := kapi.SysctlsFromPodAnnotations(v.pod.Annotations)
|
||||
origSafeSysctls, origUnsafeSysctls, err := helper.SysctlsFromPodAnnotations(v.pod.Annotations)
|
||||
if err != nil {
|
||||
t.Fatalf("invalid sysctl annotation: %v", err)
|
||||
}
|
||||
@ -1327,7 +1328,7 @@ func TestAdmitSysctls(t *testing.T) {
|
||||
testPSPAdmit(k, v.psps, v.pod, v.shouldPass, v.expectedPSP, t)
|
||||
|
||||
if v.shouldPass {
|
||||
safeSysctls, unsafeSysctls, _ := kapi.SysctlsFromPodAnnotations(v.pod.Annotations)
|
||||
safeSysctls, unsafeSysctls, _ := helper.SysctlsFromPodAnnotations(v.pod.Annotations)
|
||||
if !reflect.DeepEqual(safeSysctls, origSafeSysctls) {
|
||||
t.Errorf("%s: wrong safe sysctls: expected=%v, got=%v", k, origSafeSysctls, safeSysctls)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ go_library(
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//pkg/apis/storage/util:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
admission "k8s.io/apiserver/pkg/admission"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
@ -96,7 +97,7 @@ func (c *claimDefaulterPlugin) Admit(a admission.Attributes) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if api.PersistentVolumeClaimHasClass(pvc) {
|
||||
if helper.PersistentVolumeClaimHasClass(pvc) {
|
||||
// The user asked for a class.
|
||||
return nil
|
||||
}
|
||||
|
@ -64,4 +64,7 @@ const (
|
||||
// in the Annotations of a Pod.
|
||||
// TODO: remove when alpha support for affinity is removed
|
||||
AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity"
|
||||
|
||||
// annotation key prefix used to identify non-convertible json paths.
|
||||
NonConvertibleAnnotationPrefix = "non-convertible.kubernetes.io"
|
||||
)
|
||||
|
@ -14,18 +14,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package helper
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
@ -34,25 +31,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// Conversion error conveniently packages up errors in conversions.
|
||||
type ConversionError struct {
|
||||
In, Out interface{}
|
||||
Message string
|
||||
}
|
||||
|
||||
// Return a helpful string about the error
|
||||
func (c *ConversionError) Error() string {
|
||||
return spew.Sprintf(
|
||||
"Conversion error: %s. (in: %v(%+v) out: %v)",
|
||||
c.Message, reflect.TypeOf(c.In), c.In, reflect.TypeOf(c.Out),
|
||||
)
|
||||
}
|
||||
|
||||
const (
|
||||
// annotation key prefix used to identify non-convertible json paths.
|
||||
NonConvertibleAnnotationPrefix = "non-convertible.kubernetes.io"
|
||||
"k8s.io/client-go/pkg/api"
|
||||
)
|
||||
|
||||
// NonConvertibleFields iterates over the provided map and filters out all but
|
||||
@ -60,7 +39,7 @@ const (
|
||||
func NonConvertibleFields(annotations map[string]string) map[string]string {
|
||||
nonConvertibleKeys := map[string]string{}
|
||||
for key, value := range annotations {
|
||||
if strings.HasPrefix(key, NonConvertibleAnnotationPrefix) {
|
||||
if strings.HasPrefix(key, api.NonConvertibleAnnotationPrefix) {
|
||||
nonConvertibleKeys[key] = value
|
||||
}
|
||||
}
|
||||
@ -89,10 +68,10 @@ var Semantic = conversion.EqualitiesOrDie(
|
||||
)
|
||||
|
||||
var standardResourceQuotaScopes = sets.NewString(
|
||||
string(ResourceQuotaScopeTerminating),
|
||||
string(ResourceQuotaScopeNotTerminating),
|
||||
string(ResourceQuotaScopeBestEffort),
|
||||
string(ResourceQuotaScopeNotBestEffort),
|
||||
string(api.ResourceQuotaScopeTerminating),
|
||||
string(api.ResourceQuotaScopeNotTerminating),
|
||||
string(api.ResourceQuotaScopeBestEffort),
|
||||
string(api.ResourceQuotaScopeNotBestEffort),
|
||||
)
|
||||
|
||||
// IsStandardResourceQuotaScope returns true if the scope is a standard value
|
||||
@ -101,24 +80,24 @@ func IsStandardResourceQuotaScope(str string) bool {
|
||||
}
|
||||
|
||||
var podObjectCountQuotaResources = sets.NewString(
|
||||
string(ResourcePods),
|
||||
string(api.ResourcePods),
|
||||
)
|
||||
|
||||
var podComputeQuotaResources = sets.NewString(
|
||||
string(ResourceCPU),
|
||||
string(ResourceMemory),
|
||||
string(ResourceLimitsCPU),
|
||||
string(ResourceLimitsMemory),
|
||||
string(ResourceRequestsCPU),
|
||||
string(ResourceRequestsMemory),
|
||||
string(api.ResourceCPU),
|
||||
string(api.ResourceMemory),
|
||||
string(api.ResourceLimitsCPU),
|
||||
string(api.ResourceLimitsMemory),
|
||||
string(api.ResourceRequestsCPU),
|
||||
string(api.ResourceRequestsMemory),
|
||||
)
|
||||
|
||||
// IsResourceQuotaScopeValidForResource returns true if the resource applies to the specified scope
|
||||
func IsResourceQuotaScopeValidForResource(scope ResourceQuotaScope, resource string) bool {
|
||||
func IsResourceQuotaScopeValidForResource(scope api.ResourceQuotaScope, resource string) bool {
|
||||
switch scope {
|
||||
case ResourceQuotaScopeTerminating, ResourceQuotaScopeNotTerminating, ResourceQuotaScopeNotBestEffort:
|
||||
case api.ResourceQuotaScopeTerminating, api.ResourceQuotaScopeNotTerminating, api.ResourceQuotaScopeNotBestEffort:
|
||||
return podObjectCountQuotaResources.Has(resource) || podComputeQuotaResources.Has(resource)
|
||||
case ResourceQuotaScopeBestEffort:
|
||||
case api.ResourceQuotaScopeBestEffort:
|
||||
return podObjectCountQuotaResources.Has(resource)
|
||||
default:
|
||||
return true
|
||||
@ -126,8 +105,8 @@ func IsResourceQuotaScopeValidForResource(scope ResourceQuotaScope, resource str
|
||||
}
|
||||
|
||||
var standardContainerResources = sets.NewString(
|
||||
string(ResourceCPU),
|
||||
string(ResourceMemory),
|
||||
string(api.ResourceCPU),
|
||||
string(api.ResourceMemory),
|
||||
)
|
||||
|
||||
// IsStandardContainerResourceName returns true if the container can make a resource request
|
||||
@ -138,24 +117,24 @@ func IsStandardContainerResourceName(str string) bool {
|
||||
|
||||
// IsOpaqueIntResourceName returns true if the resource name has the opaque
|
||||
// integer resource prefix.
|
||||
func IsOpaqueIntResourceName(name ResourceName) bool {
|
||||
return strings.HasPrefix(string(name), ResourceOpaqueIntPrefix)
|
||||
func IsOpaqueIntResourceName(name api.ResourceName) bool {
|
||||
return strings.HasPrefix(string(name), api.ResourceOpaqueIntPrefix)
|
||||
}
|
||||
|
||||
// OpaqueIntResourceName returns a ResourceName with the canonical opaque
|
||||
// integer prefix prepended. If the argument already has the prefix, it is
|
||||
// returned unmodified.
|
||||
func OpaqueIntResourceName(name string) ResourceName {
|
||||
if IsOpaqueIntResourceName(ResourceName(name)) {
|
||||
return ResourceName(name)
|
||||
func OpaqueIntResourceName(name string) api.ResourceName {
|
||||
if IsOpaqueIntResourceName(api.ResourceName(name)) {
|
||||
return api.ResourceName(name)
|
||||
}
|
||||
return ResourceName(fmt.Sprintf("%s%s", ResourceOpaqueIntPrefix, name))
|
||||
return api.ResourceName(fmt.Sprintf("%s%s", api.ResourceOpaqueIntPrefix, name))
|
||||
}
|
||||
|
||||
var standardLimitRangeTypes = sets.NewString(
|
||||
string(LimitTypePod),
|
||||
string(LimitTypeContainer),
|
||||
string(LimitTypePersistentVolumeClaim),
|
||||
string(api.LimitTypePod),
|
||||
string(api.LimitTypeContainer),
|
||||
string(api.LimitTypePersistentVolumeClaim),
|
||||
)
|
||||
|
||||
// IsStandardLimitRangeType returns true if the type is Pod or Container
|
||||
@ -164,22 +143,22 @@ func IsStandardLimitRangeType(str string) bool {
|
||||
}
|
||||
|
||||
var standardQuotaResources = sets.NewString(
|
||||
string(ResourceCPU),
|
||||
string(ResourceMemory),
|
||||
string(ResourceRequestsCPU),
|
||||
string(ResourceRequestsMemory),
|
||||
string(ResourceRequestsStorage),
|
||||
string(ResourceLimitsCPU),
|
||||
string(ResourceLimitsMemory),
|
||||
string(ResourcePods),
|
||||
string(ResourceQuotas),
|
||||
string(ResourceServices),
|
||||
string(ResourceReplicationControllers),
|
||||
string(ResourceSecrets),
|
||||
string(ResourcePersistentVolumeClaims),
|
||||
string(ResourceConfigMaps),
|
||||
string(ResourceServicesNodePorts),
|
||||
string(ResourceServicesLoadBalancers),
|
||||
string(api.ResourceCPU),
|
||||
string(api.ResourceMemory),
|
||||
string(api.ResourceRequestsCPU),
|
||||
string(api.ResourceRequestsMemory),
|
||||
string(api.ResourceRequestsStorage),
|
||||
string(api.ResourceLimitsCPU),
|
||||
string(api.ResourceLimitsMemory),
|
||||
string(api.ResourcePods),
|
||||
string(api.ResourceQuotas),
|
||||
string(api.ResourceServices),
|
||||
string(api.ResourceReplicationControllers),
|
||||
string(api.ResourceSecrets),
|
||||
string(api.ResourcePersistentVolumeClaims),
|
||||
string(api.ResourceConfigMaps),
|
||||
string(api.ResourceServicesNodePorts),
|
||||
string(api.ResourceServicesLoadBalancers),
|
||||
)
|
||||
|
||||
// IsStandardQuotaResourceName returns true if the resource is known to
|
||||
@ -189,21 +168,21 @@ func IsStandardQuotaResourceName(str string) bool {
|
||||
}
|
||||
|
||||
var standardResources = sets.NewString(
|
||||
string(ResourceCPU),
|
||||
string(ResourceMemory),
|
||||
string(ResourceRequestsCPU),
|
||||
string(ResourceRequestsMemory),
|
||||
string(ResourceLimitsCPU),
|
||||
string(ResourceLimitsMemory),
|
||||
string(ResourcePods),
|
||||
string(ResourceQuotas),
|
||||
string(ResourceServices),
|
||||
string(ResourceReplicationControllers),
|
||||
string(ResourceSecrets),
|
||||
string(ResourceConfigMaps),
|
||||
string(ResourcePersistentVolumeClaims),
|
||||
string(ResourceStorage),
|
||||
string(ResourceRequestsStorage),
|
||||
string(api.ResourceCPU),
|
||||
string(api.ResourceMemory),
|
||||
string(api.ResourceRequestsCPU),
|
||||
string(api.ResourceRequestsMemory),
|
||||
string(api.ResourceLimitsCPU),
|
||||
string(api.ResourceLimitsMemory),
|
||||
string(api.ResourcePods),
|
||||
string(api.ResourceQuotas),
|
||||
string(api.ResourceServices),
|
||||
string(api.ResourceReplicationControllers),
|
||||
string(api.ResourceSecrets),
|
||||
string(api.ResourceConfigMaps),
|
||||
string(api.ResourcePersistentVolumeClaims),
|
||||
string(api.ResourceStorage),
|
||||
string(api.ResourceRequestsStorage),
|
||||
)
|
||||
|
||||
// IsStandardResourceName returns true if the resource is known to the system
|
||||
@ -212,50 +191,50 @@ func IsStandardResourceName(str string) bool {
|
||||
}
|
||||
|
||||
var integerResources = sets.NewString(
|
||||
string(ResourcePods),
|
||||
string(ResourceQuotas),
|
||||
string(ResourceServices),
|
||||
string(ResourceReplicationControllers),
|
||||
string(ResourceSecrets),
|
||||
string(ResourceConfigMaps),
|
||||
string(ResourcePersistentVolumeClaims),
|
||||
string(ResourceServicesNodePorts),
|
||||
string(ResourceServicesLoadBalancers),
|
||||
string(api.ResourcePods),
|
||||
string(api.ResourceQuotas),
|
||||
string(api.ResourceServices),
|
||||
string(api.ResourceReplicationControllers),
|
||||
string(api.ResourceSecrets),
|
||||
string(api.ResourceConfigMaps),
|
||||
string(api.ResourcePersistentVolumeClaims),
|
||||
string(api.ResourceServicesNodePorts),
|
||||
string(api.ResourceServicesLoadBalancers),
|
||||
)
|
||||
|
||||
// IsIntegerResourceName returns true if the resource is measured in integer values
|
||||
func IsIntegerResourceName(str string) bool {
|
||||
return integerResources.Has(str) || IsOpaqueIntResourceName(ResourceName(str))
|
||||
return integerResources.Has(str) || IsOpaqueIntResourceName(api.ResourceName(str))
|
||||
}
|
||||
|
||||
// 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 *Service) bool {
|
||||
return service.Spec.ClusterIP != ClusterIPNone && service.Spec.ClusterIP != ""
|
||||
func IsServiceIPSet(service *api.Service) bool {
|
||||
return service.Spec.ClusterIP != api.ClusterIPNone && service.Spec.ClusterIP != ""
|
||||
}
|
||||
|
||||
// this function aims to check if the service's cluster IP is requested or not
|
||||
func IsServiceIPRequested(service *Service) bool {
|
||||
func IsServiceIPRequested(service *api.Service) bool {
|
||||
// ExternalName services are CNAME aliases to external ones. Ignore the IP.
|
||||
if service.Spec.Type == ServiceTypeExternalName {
|
||||
if service.Spec.Type == api.ServiceTypeExternalName {
|
||||
return false
|
||||
}
|
||||
return service.Spec.ClusterIP == ""
|
||||
}
|
||||
|
||||
var standardFinalizers = sets.NewString(
|
||||
string(FinalizerKubernetes),
|
||||
string(api.FinalizerKubernetes),
|
||||
metav1.FinalizerOrphanDependents,
|
||||
)
|
||||
|
||||
// HasAnnotation returns a bool if passed in annotation exists
|
||||
func HasAnnotation(obj ObjectMeta, ann string) bool {
|
||||
func HasAnnotation(obj api.ObjectMeta, ann string) bool {
|
||||
_, found := obj.Annotations[ann]
|
||||
return found
|
||||
}
|
||||
|
||||
// SetMetaDataAnnotation sets the annotation and value
|
||||
func SetMetaDataAnnotation(obj *ObjectMeta, ann string, value string) {
|
||||
func SetMetaDataAnnotation(obj *api.ObjectMeta, ann string, value string) {
|
||||
if obj.Annotations == nil {
|
||||
obj.Annotations = make(map[string]string)
|
||||
}
|
||||
@ -268,7 +247,7 @@ func IsStandardFinalizerName(str string) bool {
|
||||
|
||||
// AddToNodeAddresses appends the NodeAddresses to the passed-by-pointer slice,
|
||||
// only if they do not already exist
|
||||
func AddToNodeAddresses(addresses *[]NodeAddress, addAddresses ...NodeAddress) {
|
||||
func AddToNodeAddresses(addresses *[]api.NodeAddress, addAddresses ...api.NodeAddress) {
|
||||
for _, add := range addAddresses {
|
||||
exists := false
|
||||
for _, existing := range *addresses {
|
||||
@ -292,11 +271,11 @@ func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) {
|
||||
}
|
||||
|
||||
// TODO: make method on LoadBalancerStatus?
|
||||
func LoadBalancerStatusEqual(l, r *LoadBalancerStatus) bool {
|
||||
func LoadBalancerStatusEqual(l, r *api.LoadBalancerStatus) bool {
|
||||
return ingressSliceEqual(l.Ingress, r.Ingress)
|
||||
}
|
||||
|
||||
func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool {
|
||||
func ingressSliceEqual(lhs, rhs []api.LoadBalancerIngress) bool {
|
||||
if len(lhs) != len(rhs) {
|
||||
return false
|
||||
}
|
||||
@ -308,7 +287,7 @@ func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func ingressEqual(lhs, rhs *LoadBalancerIngress) bool {
|
||||
func ingressEqual(lhs, rhs *api.LoadBalancerIngress) bool {
|
||||
if lhs.IP != rhs.IP {
|
||||
return false
|
||||
}
|
||||
@ -319,9 +298,9 @@ func ingressEqual(lhs, rhs *LoadBalancerIngress) bool {
|
||||
}
|
||||
|
||||
// TODO: make method on LoadBalancerStatus?
|
||||
func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus {
|
||||
c := &LoadBalancerStatus{}
|
||||
c.Ingress = make([]LoadBalancerIngress, len(lb.Ingress))
|
||||
func LoadBalancerStatusDeepCopy(lb *api.LoadBalancerStatus) *api.LoadBalancerStatus {
|
||||
c := &api.LoadBalancerStatus{}
|
||||
c.Ingress = make([]api.LoadBalancerIngress, len(lb.Ingress))
|
||||
for i := range lb.Ingress {
|
||||
c.Ingress[i] = lb.Ingress[i]
|
||||
}
|
||||
@ -330,42 +309,42 @@ func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus {
|
||||
|
||||
// GetAccessModesAsString returns a string representation of an array of access modes.
|
||||
// modes, when present, are always in the same order: RWO,ROX,RWX.
|
||||
func GetAccessModesAsString(modes []PersistentVolumeAccessMode) string {
|
||||
func GetAccessModesAsString(modes []api.PersistentVolumeAccessMode) string {
|
||||
modes = removeDuplicateAccessModes(modes)
|
||||
modesStr := []string{}
|
||||
if containsAccessMode(modes, ReadWriteOnce) {
|
||||
if containsAccessMode(modes, api.ReadWriteOnce) {
|
||||
modesStr = append(modesStr, "RWO")
|
||||
}
|
||||
if containsAccessMode(modes, ReadOnlyMany) {
|
||||
if containsAccessMode(modes, api.ReadOnlyMany) {
|
||||
modesStr = append(modesStr, "ROX")
|
||||
}
|
||||
if containsAccessMode(modes, ReadWriteMany) {
|
||||
if containsAccessMode(modes, api.ReadWriteMany) {
|
||||
modesStr = append(modesStr, "RWX")
|
||||
}
|
||||
return strings.Join(modesStr, ",")
|
||||
}
|
||||
|
||||
// GetAccessModesAsString returns an array of AccessModes from a string created by GetAccessModesAsString
|
||||
func GetAccessModesFromString(modes string) []PersistentVolumeAccessMode {
|
||||
func GetAccessModesFromString(modes string) []api.PersistentVolumeAccessMode {
|
||||
strmodes := strings.Split(modes, ",")
|
||||
accessModes := []PersistentVolumeAccessMode{}
|
||||
accessModes := []api.PersistentVolumeAccessMode{}
|
||||
for _, s := range strmodes {
|
||||
s = strings.Trim(s, " ")
|
||||
switch {
|
||||
case s == "RWO":
|
||||
accessModes = append(accessModes, ReadWriteOnce)
|
||||
accessModes = append(accessModes, api.ReadWriteOnce)
|
||||
case s == "ROX":
|
||||
accessModes = append(accessModes, ReadOnlyMany)
|
||||
accessModes = append(accessModes, api.ReadOnlyMany)
|
||||
case s == "RWX":
|
||||
accessModes = append(accessModes, ReadWriteMany)
|
||||
accessModes = append(accessModes, api.ReadWriteMany)
|
||||
}
|
||||
}
|
||||
return accessModes
|
||||
}
|
||||
|
||||
// removeDuplicateAccessModes returns an array of access modes without any duplicates
|
||||
func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []PersistentVolumeAccessMode {
|
||||
accessModes := []PersistentVolumeAccessMode{}
|
||||
func removeDuplicateAccessModes(modes []api.PersistentVolumeAccessMode) []api.PersistentVolumeAccessMode {
|
||||
accessModes := []api.PersistentVolumeAccessMode{}
|
||||
for _, m := range modes {
|
||||
if !containsAccessMode(accessModes, m) {
|
||||
accessModes = append(accessModes, m)
|
||||
@ -374,7 +353,7 @@ func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []Persistent
|
||||
return accessModes
|
||||
}
|
||||
|
||||
func containsAccessMode(modes []PersistentVolumeAccessMode, mode PersistentVolumeAccessMode) bool {
|
||||
func containsAccessMode(modes []api.PersistentVolumeAccessMode, mode api.PersistentVolumeAccessMode) bool {
|
||||
for _, m := range modes {
|
||||
if m == mode {
|
||||
return true
|
||||
@ -397,7 +376,7 @@ func ParseRFC3339(s string, nowFn func() metav1.Time) (metav1.Time, error) {
|
||||
|
||||
// NodeSelectorRequirementsAsSelector converts the []NodeSelectorRequirement api type into a struct that implements
|
||||
// labels.Selector.
|
||||
func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.Selector, error) {
|
||||
func NodeSelectorRequirementsAsSelector(nsm []api.NodeSelectorRequirement) (labels.Selector, error) {
|
||||
if len(nsm) == 0 {
|
||||
return labels.Nothing(), nil
|
||||
}
|
||||
@ -405,17 +384,17 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S
|
||||
for _, expr := range nsm {
|
||||
var op selection.Operator
|
||||
switch expr.Operator {
|
||||
case NodeSelectorOpIn:
|
||||
case api.NodeSelectorOpIn:
|
||||
op = selection.In
|
||||
case NodeSelectorOpNotIn:
|
||||
case api.NodeSelectorOpNotIn:
|
||||
op = selection.NotIn
|
||||
case NodeSelectorOpExists:
|
||||
case api.NodeSelectorOpExists:
|
||||
op = selection.Exists
|
||||
case NodeSelectorOpDoesNotExist:
|
||||
case api.NodeSelectorOpDoesNotExist:
|
||||
op = selection.DoesNotExist
|
||||
case NodeSelectorOpGt:
|
||||
case api.NodeSelectorOpGt:
|
||||
op = selection.GreaterThan
|
||||
case NodeSelectorOpLt:
|
||||
case api.NodeSelectorOpLt:
|
||||
op = selection.LessThan
|
||||
default:
|
||||
return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
|
||||
@ -431,10 +410,10 @@ func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.S
|
||||
|
||||
// GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations
|
||||
// and converts it to the []Toleration type in api.
|
||||
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Toleration, error) {
|
||||
var tolerations []Toleration
|
||||
if len(annotations) > 0 && annotations[TolerationsAnnotationKey] != "" {
|
||||
err := json.Unmarshal([]byte(annotations[TolerationsAnnotationKey]), &tolerations)
|
||||
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]api.Toleration, error) {
|
||||
var tolerations []api.Toleration
|
||||
if len(annotations) > 0 && annotations[api.TolerationsAnnotationKey] != "" {
|
||||
err := json.Unmarshal([]byte(annotations[api.TolerationsAnnotationKey]), &tolerations)
|
||||
if err != nil {
|
||||
return tolerations, err
|
||||
}
|
||||
@ -444,10 +423,10 @@ func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Tolerati
|
||||
|
||||
// AddOrUpdateTolerationInPod tries to add a toleration to the pod's toleration list.
|
||||
// Returns true if something was updated, false otherwise.
|
||||
func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool {
|
||||
func AddOrUpdateTolerationInPod(pod *api.Pod, toleration *api.Toleration) bool {
|
||||
podTolerations := pod.Spec.Tolerations
|
||||
|
||||
var newTolerations []Toleration
|
||||
var newTolerations []api.Toleration
|
||||
updated := false
|
||||
for i := range podTolerations {
|
||||
if toleration.MatchToleration(&podTolerations[i]) {
|
||||
@ -470,18 +449,8 @@ func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// MatchToleration checks if the toleration matches tolerationToMatch. Tolerations are unique by <key,effect,operator,value>,
|
||||
// if the two tolerations have same <key,effect,operator,value> combination, regard as they match.
|
||||
// TODO: uniqueness check for tolerations in api validations.
|
||||
func (t *Toleration) MatchToleration(tolerationToMatch *Toleration) bool {
|
||||
return t.Key == tolerationToMatch.Key &&
|
||||
t.Effect == tolerationToMatch.Effect &&
|
||||
t.Operator == tolerationToMatch.Operator &&
|
||||
t.Value == tolerationToMatch.Value
|
||||
}
|
||||
|
||||
// TolerationToleratesTaint checks if the toleration tolerates the taint.
|
||||
func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
|
||||
func TolerationToleratesTaint(toleration *api.Toleration, taint *api.Taint) bool {
|
||||
if len(toleration.Effect) != 0 && toleration.Effect != taint.Effect {
|
||||
return false
|
||||
}
|
||||
@ -490,17 +459,17 @@ func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
|
||||
return false
|
||||
}
|
||||
// TODO: Use proper defaulting when Toleration becomes a field of PodSpec
|
||||
if (len(toleration.Operator) == 0 || toleration.Operator == TolerationOpEqual) && toleration.Value == taint.Value {
|
||||
if (len(toleration.Operator) == 0 || toleration.Operator == api.TolerationOpEqual) && toleration.Value == taint.Value {
|
||||
return true
|
||||
}
|
||||
if toleration.Operator == TolerationOpExists {
|
||||
if toleration.Operator == api.TolerationOpExists {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TaintToleratedByTolerations checks if taint is tolerated by any of the tolerations.
|
||||
func TaintToleratedByTolerations(taint *Taint, tolerations []Toleration) bool {
|
||||
func TaintToleratedByTolerations(taint *api.Taint, tolerations []api.Toleration) bool {
|
||||
tolerated := false
|
||||
for i := range tolerations {
|
||||
if TolerationToleratesTaint(&tolerations[i], taint) {
|
||||
@ -511,28 +480,14 @@ func TaintToleratedByTolerations(taint *Taint, tolerations []Toleration) bool {
|
||||
return tolerated
|
||||
}
|
||||
|
||||
// MatchTaint checks if the taint matches taintToMatch. Taints are unique by key:effect,
|
||||
// if the two taints have same key:effect, regard as they match.
|
||||
func (t *Taint) MatchTaint(taintToMatch Taint) bool {
|
||||
return t.Key == taintToMatch.Key && t.Effect == taintToMatch.Effect
|
||||
}
|
||||
|
||||
// taint.ToString() converts taint struct to string in format key=value:effect or key:effect.
|
||||
func (t *Taint) ToString() string {
|
||||
if len(t.Value) == 0 {
|
||||
return fmt.Sprintf("%v:%v", t.Key, t.Effect)
|
||||
}
|
||||
return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect)
|
||||
}
|
||||
|
||||
// GetTaintsFromNodeAnnotations gets the json serialized taints data from Pod.Annotations
|
||||
// and converts it to the []Taint type in api.
|
||||
func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]Taint, error) {
|
||||
var taints []Taint
|
||||
if len(annotations) > 0 && annotations[TaintsAnnotationKey] != "" {
|
||||
err := json.Unmarshal([]byte(annotations[TaintsAnnotationKey]), &taints)
|
||||
func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]api.Taint, error) {
|
||||
var taints []api.Taint
|
||||
if len(annotations) > 0 && annotations[api.TaintsAnnotationKey] != "" {
|
||||
err := json.Unmarshal([]byte(annotations[api.TaintsAnnotationKey]), &taints)
|
||||
if err != nil {
|
||||
return []Taint{}, err
|
||||
return []api.Taint{}, err
|
||||
}
|
||||
}
|
||||
return taints, nil
|
||||
@ -541,12 +496,12 @@ func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]Taint, error
|
||||
// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls
|
||||
// and a slice of unsafe Sysctls. This is only a convenience wrapper around
|
||||
// SysctlsFromPodAnnotation.
|
||||
func SysctlsFromPodAnnotations(a map[string]string) ([]Sysctl, []Sysctl, error) {
|
||||
safe, err := SysctlsFromPodAnnotation(a[SysctlsPodAnnotationKey])
|
||||
func SysctlsFromPodAnnotations(a map[string]string) ([]api.Sysctl, []api.Sysctl, error) {
|
||||
safe, err := SysctlsFromPodAnnotation(a[api.SysctlsPodAnnotationKey])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
unsafe, err := SysctlsFromPodAnnotation(a[UnsafeSysctlsPodAnnotationKey])
|
||||
unsafe, err := SysctlsFromPodAnnotation(a[api.UnsafeSysctlsPodAnnotationKey])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -555,13 +510,13 @@ func SysctlsFromPodAnnotations(a map[string]string) ([]Sysctl, []Sysctl, error)
|
||||
}
|
||||
|
||||
// SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls.
|
||||
func SysctlsFromPodAnnotation(annotation string) ([]Sysctl, error) {
|
||||
func SysctlsFromPodAnnotation(annotation string) ([]api.Sysctl, error) {
|
||||
if len(annotation) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
kvs := strings.Split(annotation, ",")
|
||||
sysctls := make([]Sysctl, len(kvs))
|
||||
sysctls := make([]api.Sysctl, len(kvs))
|
||||
for i, kv := range kvs {
|
||||
cs := strings.Split(kv, "=")
|
||||
if len(cs) != 2 || len(cs[0]) == 0 {
|
||||
@ -574,7 +529,7 @@ func SysctlsFromPodAnnotation(annotation string) ([]Sysctl, error) {
|
||||
}
|
||||
|
||||
// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls.
|
||||
func PodAnnotationsFromSysctls(sysctls []Sysctl) string {
|
||||
func PodAnnotationsFromSysctls(sysctls []api.Sysctl) string {
|
||||
if len(sysctls) == 0 {
|
||||
return ""
|
||||
}
|
||||
@ -589,10 +544,10 @@ func PodAnnotationsFromSysctls(sysctls []Sysctl) string {
|
||||
// GetAffinityFromPodAnnotations gets the json serialized affinity data from Pod.Annotations
|
||||
// and converts it to the Affinity type in api.
|
||||
// TODO: remove when alpha support for affinity is removed
|
||||
func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, error) {
|
||||
if len(annotations) > 0 && annotations[AffinityAnnotationKey] != "" {
|
||||
var affinity Affinity
|
||||
err := json.Unmarshal([]byte(annotations[AffinityAnnotationKey]), &affinity)
|
||||
func GetAffinityFromPodAnnotations(annotations map[string]string) (*api.Affinity, error) {
|
||||
if len(annotations) > 0 && annotations[api.AffinityAnnotationKey] != "" {
|
||||
var affinity api.Affinity
|
||||
err := json.Unmarshal([]byte(annotations[api.AffinityAnnotationKey]), &affinity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -602,9 +557,9 @@ func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, er
|
||||
}
|
||||
|
||||
// GetPersistentVolumeClass returns StorageClassName.
|
||||
func GetPersistentVolumeClass(volume *PersistentVolume) string {
|
||||
func GetPersistentVolumeClass(volume *api.PersistentVolume) string {
|
||||
// Use beta annotation first
|
||||
if class, found := volume.Annotations[BetaStorageClassAnnotation]; found {
|
||||
if class, found := volume.Annotations[api.BetaStorageClassAnnotation]; found {
|
||||
return class
|
||||
}
|
||||
|
||||
@ -613,9 +568,9 @@ func GetPersistentVolumeClass(volume *PersistentVolume) string {
|
||||
|
||||
// GetPersistentVolumeClaimClass returns StorageClassName. If no storage class was
|
||||
// requested, it returns "".
|
||||
func GetPersistentVolumeClaimClass(claim *PersistentVolumeClaim) string {
|
||||
func GetPersistentVolumeClaimClass(claim *api.PersistentVolumeClaim) string {
|
||||
// Use beta annotation first
|
||||
if class, found := claim.Annotations[BetaStorageClassAnnotation]; found {
|
||||
if class, found := claim.Annotations[api.BetaStorageClassAnnotation]; found {
|
||||
return class
|
||||
}
|
||||
|
||||
@ -627,9 +582,9 @@ func GetPersistentVolumeClaimClass(claim *PersistentVolumeClaim) string {
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimHasClass returns true if given claim has set StorageClassName field.
|
||||
func PersistentVolumeClaimHasClass(claim *PersistentVolumeClaim) bool {
|
||||
func PersistentVolumeClaimHasClass(claim *api.PersistentVolumeClaim) bool {
|
||||
// Use beta annotation first
|
||||
if _, found := claim.Annotations[BetaStorageClassAnnotation]; found {
|
||||
if _, found := claim.Annotations[api.BetaStorageClassAnnotation]; found {
|
||||
return true
|
||||
}
|
||||
|
46
staging/src/k8s.io/client-go/pkg/api/methods.go
Normal file
46
staging/src/k8s.io/client-go/pkg/api/methods.go
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
//TODO: consider making these methods functions, because we don't want helper
|
||||
//functions in the k8s.io/api repo.
|
||||
|
||||
package api
|
||||
|
||||
import "fmt"
|
||||
|
||||
// MatchToleration checks if the toleration matches tolerationToMatch. Tolerations are unique by <key,effect,operator,value>,
|
||||
// if the two tolerations have same <key,effect,operator,value> combination, regard as they match.
|
||||
// TODO: uniqueness check for tolerations in api validations.
|
||||
func (t *Toleration) MatchToleration(tolerationToMatch *Toleration) bool {
|
||||
return t.Key == tolerationToMatch.Key &&
|
||||
t.Effect == tolerationToMatch.Effect &&
|
||||
t.Operator == tolerationToMatch.Operator &&
|
||||
t.Value == tolerationToMatch.Value
|
||||
}
|
||||
|
||||
// MatchTaint checks if the taint matches taintToMatch. Taints are unique by key:effect,
|
||||
// if the two taints have same key:effect, regard as they match.
|
||||
func (t *Taint) MatchTaint(taintToMatch Taint) bool {
|
||||
return t.Key == taintToMatch.Key && t.Effect == taintToMatch.Effect
|
||||
}
|
||||
|
||||
// taint.ToString() converts taint struct to string in format key=value:effect or key:effect.
|
||||
func (t *Taint) ToString() string {
|
||||
if len(t.Value) == 0 {
|
||||
return fmt.Sprintf("%v:%v", t.Key, t.Effect)
|
||||
}
|
||||
return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect)
|
||||
}
|
@ -28,6 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
"k8s.io/client-go/pkg/api"
|
||||
"k8s.io/client-go/pkg/api/helper"
|
||||
)
|
||||
|
||||
// IsOpaqueIntResourceName returns true if the resource name has the opaque
|
||||
@ -285,7 +286,7 @@ func AddOrUpdateTolerationInPod(pod *Pod, toleration *Toleration) bool {
|
||||
updated := false
|
||||
for i := range podTolerations {
|
||||
if toleration.MatchToleration(&podTolerations[i]) {
|
||||
if api.Semantic.DeepEqual(toleration, podTolerations[i]) {
|
||||
if helper.Semantic.DeepEqual(toleration, podTolerations[i]) {
|
||||
return false
|
||||
}
|
||||
newTolerations = append(newTolerations, *toleration)
|
||||
@ -527,7 +528,7 @@ func AddOrUpdateTaint(node *Node, taint *Taint) (*Node, bool, error) {
|
||||
updated := false
|
||||
for i := range nodeTaints {
|
||||
if taint.MatchTaint(&nodeTaints[i]) {
|
||||
if api.Semantic.DeepEqual(taint, nodeTaints[i]) {
|
||||
if helper.Semantic.DeepEqual(taint, nodeTaints[i]) {
|
||||
return newNode, false, nil
|
||||
}
|
||||
newTaints = append(newTaints, *taint)
|
||||
|
@ -65,7 +65,6 @@ func RegisterDeepCopies(scheme *runtime.Scheme) error {
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStateTerminated, InType: reflect.TypeOf(&ContainerStateTerminated{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStateWaiting, InType: reflect.TypeOf(&ContainerStateWaiting{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ContainerStatus, InType: reflect.TypeOf(&ContainerStatus{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_ConversionError, InType: reflect.TypeOf(&ConversionError{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DaemonEndpoint, InType: reflect.TypeOf(&DaemonEndpoint{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DeleteOptions, InType: reflect.TypeOf(&DeleteOptions{})},
|
||||
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_api_DownwardAPIProjection, InType: reflect.TypeOf(&DownwardAPIProjection{})},
|
||||
@ -707,31 +706,6 @@ func DeepCopy_api_ContainerStatus(in interface{}, out interface{}, c *conversion
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_api_ConversionError(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*ConversionError)
|
||||
out := out.(*ConversionError)
|
||||
*out = *in
|
||||
// in.In is kind 'Interface'
|
||||
if in.In != nil {
|
||||
if newVal, err := c.DeepCopy(&in.In); err != nil {
|
||||
return err
|
||||
} else {
|
||||
out.In = *newVal.(*interface{})
|
||||
}
|
||||
}
|
||||
// in.Out is kind 'Interface'
|
||||
if in.Out != nil {
|
||||
if newVal, err := c.DeepCopy(&in.Out); err != nil {
|
||||
return err
|
||||
} else {
|
||||
out.Out = *newVal.(*interface{})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_api_DaemonEndpoint(in interface{}, out interface{}, c *conversion.Cloner) error {
|
||||
{
|
||||
in := in.(*DaemonEndpoint)
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
"k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds"
|
||||
@ -85,13 +86,13 @@ func TestAdmission(t *testing.T) {
|
||||
break
|
||||
}
|
||||
if tolerations[i].MatchToleration(&nodeNotReady) {
|
||||
if api.Semantic.DeepEqual(tolerations[i], nodeNotReady) {
|
||||
if helper.Semantic.DeepEqual(tolerations[i], nodeNotReady) {
|
||||
found++
|
||||
continue
|
||||
}
|
||||
}
|
||||
if tolerations[i].MatchToleration(&nodeUnreachable) {
|
||||
if api.Semantic.DeepEqual(tolerations[i], nodeUnreachable) {
|
||||
if helper.Semantic.DeepEqual(tolerations[i], nodeUnreachable) {
|
||||
found++
|
||||
continue
|
||||
}
|
||||
|
23
vendor/BUILD
vendored
23
vendor/BUILD
vendored
@ -13903,8 +13903,8 @@ go_library(
|
||||
"k8s.io/client-go/pkg/api/defaults.go",
|
||||
"k8s.io/client-go/pkg/api/doc.go",
|
||||
"k8s.io/client-go/pkg/api/field_constants.go",
|
||||
"k8s.io/client-go/pkg/api/helpers.go",
|
||||
"k8s.io/client-go/pkg/api/json.go",
|
||||
"k8s.io/client-go/pkg/api/methods.go",
|
||||
"k8s.io/client-go/pkg/api/ref.go",
|
||||
"k8s.io/client-go/pkg/api/register.go",
|
||||
"k8s.io/client-go/pkg/api/resource_helpers.go",
|
||||
@ -13913,7 +13913,6 @@ go_library(
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:github.com/davecgh/go-spew/spew",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apimachinery/announced",
|
||||
@ -13925,10 +13924,8 @@ go_library(
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer",
|
||||
"//vendor:k8s.io/apimachinery/pkg/selection",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/intstr",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
],
|
||||
)
|
||||
|
||||
@ -13985,6 +13982,7 @@ go_library(
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"//vendor:k8s.io/client-go/pkg/api",
|
||||
"//vendor:k8s.io/client-go/pkg/api/helper",
|
||||
"//vendor:k8s.io/client-go/pkg/apis/extensions",
|
||||
"//vendor:k8s.io/client-go/pkg/util",
|
||||
"//vendor:k8s.io/client-go/pkg/util/parsers",
|
||||
@ -16761,3 +16759,20 @@ filegroup(
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "k8s.io/client-go/pkg/api/helper",
|
||||
srcs = ["k8s.io/client-go/pkg/api/helper/helpers.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/conversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/selection",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/client-go/pkg/api",
|
||||
],
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user