Bumping k8s dependencies to 1.13

This commit is contained in:
Cheng Xing
2018-11-16 14:08:25 -08:00
parent 305407125c
commit b4c0b68ec7
8002 changed files with 884099 additions and 276228 deletions

View File

@@ -1,4 +1,15 @@
approvers:
- api-approvers
reviewers:
- api-reviewers
# See the OWNERS docs at https://go.k8s.io/owners
filters:
".*":
approvers:
- api-approvers
reviewers:
- api-reviewers
# examples:
# pkg/api/types.go
# pkg/api/*/register.go
"([^/]+/)?(register|types)\\.go$":
labels:
- kind/api-change

View File

@@ -13,7 +13,7 @@ go_library(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/util/hash:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
],
)
@@ -23,8 +23,8 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
],
)

View File

@@ -38,12 +38,12 @@ func RepackSubsets(subsets []api.EndpointSubset) []api.EndpointSubset {
allAddrs := map[addressKey]*api.EndpointAddress{}
portToAddrReadyMap := map[api.EndpointPort]addressSet{}
for i := range subsets {
for _, port := range subsets[i].Ports {
for k := range subsets[i].Addresses {
mapAddressByPort(&subsets[i].Addresses[k], port, true, allAddrs, portToAddrReadyMap)
}
for k := range subsets[i].NotReadyAddresses {
mapAddressByPort(&subsets[i].NotReadyAddresses[k], port, false, allAddrs, portToAddrReadyMap)
if len(subsets[i].Ports) == 0 {
// Don't discard endpoints with no ports defined, use a sentinel.
mapAddressesByPort(&subsets[i], api.EndpointPort{Port: -1}, allAddrs, portToAddrReadyMap)
} else {
for _, port := range subsets[i].Ports {
mapAddressesByPort(&subsets[i], port, allAddrs, portToAddrReadyMap)
}
}
}
@@ -58,7 +58,14 @@ func RepackSubsets(subsets []api.EndpointSubset) []api.EndpointSubset {
for port, addrs := range portToAddrReadyMap {
key := keyString(hashAddresses(addrs))
keyToAddrReadyMap[key] = addrs
addrReadyMapKeyToPorts[key] = append(addrReadyMapKeyToPorts[key], port)
if port.Port > 0 { // avoid sentinels
addrReadyMapKeyToPorts[key] = append(addrReadyMapKeyToPorts[key], port)
} else {
if _, found := addrReadyMapKeyToPorts[key]; !found {
// Force it to be present in the map
addrReadyMapKeyToPorts[key] = nil
}
}
}
// Next, build the N-to-M association the API wants.
@@ -85,7 +92,17 @@ type addressKey struct {
uid types.UID
}
// mapAddressByPort adds an address into a map by its ports, registering the address with a unique pointer, and preserving
// mapAddressesByPort adds all ready and not-ready addresses into a map by a single port.
func mapAddressesByPort(subset *api.EndpointSubset, port api.EndpointPort, allAddrs map[addressKey]*api.EndpointAddress, portToAddrReadyMap map[api.EndpointPort]addressSet) {
for k := range subset.Addresses {
mapAddressByPort(&subset.Addresses[k], port, true, allAddrs, portToAddrReadyMap)
}
for k := range subset.NotReadyAddresses {
mapAddressByPort(&subset.NotReadyAddresses[k], port, false, allAddrs, portToAddrReadyMap)
}
}
// mapAddressByPort adds one address into a map by port, registering the address with a unique pointer, and preserving
// any existing ready state.
func mapAddressByPort(addr *api.EndpointAddress, port api.EndpointPort, ready bool, allAddrs map[addressKey]*api.EndpointAddress, portToAddrReadyMap map[api.EndpointPort]addressSet) *api.EndpointAddress {
// use addressKey to distinguish between two endpoints that are identical addresses

View File

@@ -51,11 +51,11 @@ func TestPackSubsets(t *testing.T) {
}, {
name: "empty ports",
given: []api.EndpointSubset{{Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []api.EndpointPort{}}},
expect: []api.EndpointSubset{},
expect: []api.EndpointSubset{{Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, Ports: nil}},
}, {
name: "empty ports",
given: []api.EndpointSubset{{NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []api.EndpointPort{}}},
expect: []api.EndpointSubset{},
expect: []api.EndpointSubset{{NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, Ports: nil}},
}, {
name: "one set, one ip, one port",
given: []api.EndpointSubset{{

View File

@@ -19,7 +19,7 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
],
)

View File

@@ -6,8 +6,8 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/api/legacyscheme",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
],
)

View File

@@ -3,7 +3,6 @@ package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
@@ -13,7 +12,7 @@ go_library(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)
@@ -29,16 +28,3 @@ filegroup(
srcs = [":package-srcs"],
tags = ["automanaged"],
)
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)

View File

@@ -22,119 +22,6 @@ import (
"k8s.io/kubernetes/pkg/features"
)
func getClaimRefNamespace(pv *api.PersistentVolume) string {
if pv.Spec.ClaimRef != nil {
return pv.Spec.ClaimRef.Namespace
}
return ""
}
// Visitor is called with each object's namespace and name, and returns true if visiting should continue
type Visitor func(namespace, name string, kubeletVisible bool) (shouldContinue bool)
// VisitPVSecretNames invokes the visitor function with the name of every secret
// referenced by the PV spec. If visitor returns false, visiting is short-circuited.
// Returns true if visiting completed, false if visiting was short-circuited.
func VisitPVSecretNames(pv *api.PersistentVolume, visitor Visitor) bool {
source := &pv.Spec.PersistentVolumeSource
switch {
case source.AzureFile != nil:
if source.AzureFile.SecretNamespace != nil && len(*source.AzureFile.SecretNamespace) > 0 {
if len(source.AzureFile.SecretName) > 0 && !visitor(*source.AzureFile.SecretNamespace, source.AzureFile.SecretName, true /* kubeletVisible */) {
return false
}
} else {
if len(source.AzureFile.SecretName) > 0 && !visitor(getClaimRefNamespace(pv), source.AzureFile.SecretName, true /* kubeletVisible */) {
return false
}
}
return true
case source.CephFS != nil:
if source.CephFS.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.CephFS.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.CephFS.SecretRef.Namespace
}
if !visitor(ns, source.CephFS.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.Cinder != nil:
if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Namespace, source.Cinder.SecretRef.Name, true /* kubeletVisible */) {
return false
}
case source.FlexVolume != nil:
if source.FlexVolume.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.FlexVolume.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.FlexVolume.SecretRef.Namespace
}
if !visitor(ns, source.FlexVolume.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.RBD != nil:
if source.RBD.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.RBD.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.RBD.SecretRef.Namespace
}
if !visitor(ns, source.RBD.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.ScaleIO != nil:
if source.ScaleIO.SecretRef != nil {
ns := getClaimRefNamespace(pv)
if source.ScaleIO.SecretRef != nil && len(source.ScaleIO.SecretRef.Namespace) > 0 {
ns = source.ScaleIO.SecretRef.Namespace
}
if !visitor(ns, source.ScaleIO.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.ISCSI != nil:
if source.ISCSI.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.ISCSI.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.ISCSI.SecretRef.Namespace
}
if !visitor(ns, source.ISCSI.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.StorageOS != nil:
if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Namespace, source.StorageOS.SecretRef.Name, true /* kubeletVisible */) {
return false
}
case source.CSI != nil:
if source.CSI.ControllerPublishSecretRef != nil {
if !visitor(source.CSI.ControllerPublishSecretRef.Namespace, source.CSI.ControllerPublishSecretRef.Name, false /* kubeletVisible */) {
return false
}
}
if source.CSI.NodePublishSecretRef != nil {
if !visitor(source.CSI.NodePublishSecretRef.Namespace, source.CSI.NodePublishSecretRef.Name, true /* kubeletVisible */) {
return false
}
}
if source.CSI.NodeStageSecretRef != nil {
if !visitor(source.CSI.NodeStageSecretRef.Namespace, source.CSI.NodeStageSecretRef.Name, true /* kubeletVisible */) {
return false
}
}
}
return true
}
// DropDisabledAlphaFields removes disabled fields from the pv spec.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pv spec.
func DropDisabledAlphaFields(pvSpec *api.PersistentVolumeSpec) {

View File

@@ -13,7 +13,7 @@ go_library(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)
@@ -37,6 +37,6 @@ go_test(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)

View File

@@ -13,8 +13,8 @@ go_library(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)
@@ -38,8 +38,8 @@ go_test(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)

View File

@@ -248,10 +248,6 @@ func DropDisabledAlphaFields(podSpec *api.PodSpec) {
}
}
if !utilfeature.DefaultFeatureGate.Enabled(features.PodShareProcessNamespace) && podSpec.SecurityContext != nil {
podSpec.SecurityContext.ShareProcessNamespace = nil
}
for i := range podSpec.Containers {
DropDisabledVolumeMountsAlphaFields(podSpec.Containers[i].VolumeMounts)
}
@@ -262,6 +258,12 @@ func DropDisabledAlphaFields(podSpec *api.PodSpec) {
DropDisabledVolumeDevicesAlphaFields(podSpec)
DropDisabledRunAsGroupField(podSpec)
if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && podSpec.RuntimeClassName != nil {
podSpec.RuntimeClassName = nil
}
DropDisabledProcMountField(podSpec)
}
// DropDisabledRunAsGroupField removes disabled fields from PodSpec related
@@ -284,6 +286,24 @@ func DropDisabledRunAsGroupField(podSpec *api.PodSpec) {
}
}
// DropDisabledProcMountField removes disabled fields from PodSpec related
// to ProcMount
func DropDisabledProcMountField(podSpec *api.PodSpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) {
defProcMount := api.DefaultProcMount
for i := range podSpec.Containers {
if podSpec.Containers[i].SecurityContext != nil {
podSpec.Containers[i].SecurityContext.ProcMount = &defProcMount
}
}
for i := range podSpec.InitContainers {
if podSpec.InitContainers[i].SecurityContext != nil {
podSpec.InitContainers[i].SecurityContext.ProcMount = &defProcMount
}
}
}
}
// DropDisabledVolumeMountsAlphaFields removes disabled fields from []VolumeMount.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeMount
func DropDisabledVolumeMountsAlphaFields(volumeMounts []api.VolumeMount) {

View File

@@ -18,9 +18,8 @@ package pod
import (
"reflect"
"testing"
"strings"
"testing"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"

View File

@@ -0,0 +1,43 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = ["util.go"],
importpath = "k8s.io/kubernetes/pkg/api/podsecuritypolicy",
deps = [
"//pkg/apis/policy:go_default_library",
"//pkg/features:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/features:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)

3
vendor/k8s.io/kubernetes/pkg/api/podsecuritypolicy/OWNERS generated vendored Executable file
View File

@@ -0,0 +1,3 @@
reviewers:
- smarterclayton
- jessfraz

View File

@@ -0,0 +1,31 @@
/*
Copyright 2018 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 podsecuritypolicy
import (
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/features"
)
// DropDisabledAlphaFields removes disabled fields from the pod security policy spec.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a od security policy spec.
func DropDisabledAlphaFields(pspSpec *policy.PodSecurityPolicySpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) {
pspSpec.AllowedProcMountTypes = nil
}
}

View File

@@ -0,0 +1,69 @@
/*
Copyright 2018 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 podsecuritypolicy
import (
"testing"
utilfeature "k8s.io/apiserver/pkg/util/feature"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/features"
)
func TestDropAlphaProcMountType(t *testing.T) {
// PodSecurityPolicy with AllowedProcMountTypes set
psp := policy.PodSecurityPolicy{
Spec: policy.PodSecurityPolicySpec{
AllowedProcMountTypes: []api.ProcMountType{api.UnmaskedProcMount},
},
}
// Enable alpha feature ProcMountType
err1 := utilfeature.DefaultFeatureGate.Set("ProcMountType=true")
if err1 != nil {
t.Fatalf("Failed to enable feature gate for ProcMountType: %v", err1)
}
// now test dropping the fields - should not be dropped
DropDisabledAlphaFields(&psp.Spec)
// check to make sure AllowedProcMountTypes is still present
// if featureset is set to true
if utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) {
if psp.Spec.AllowedProcMountTypes == nil {
t.Error("AllowedProcMountTypes in pvc.Spec should not have been dropped based on feature-gate")
}
}
// Disable alpha feature ProcMountType
err := utilfeature.DefaultFeatureGate.Set("ProcMountType=false")
if err != nil {
t.Fatalf("Failed to disable feature gate for ProcMountType: %v", err)
}
// now test dropping the fields
DropDisabledAlphaFields(&psp.Spec)
// check to make sure AllowedProcMountTypes is nil
// if featureset is set to false
if utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) {
if psp.Spec.AllowedProcMountTypes != nil {
t.Error("DropDisabledAlphaFields AllowedProcMountTypes for psp.Spec failed")
}
}
}

View File

@@ -13,9 +13,10 @@ go_test(
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
],
)
@@ -25,9 +26,9 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/api/ref",
deps = [
"//pkg/apis/core:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)

View File

@@ -20,6 +20,8 @@ import (
"reflect"
"testing"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -53,7 +55,7 @@ func TestGetReference(t *testing.T) {
// then you run into trouble because the types aren't registered in the scheme by anything. This does the
// register manually to allow unit test execution
if _, _, err := legacyscheme.Scheme.ObjectKinds(&api.Pod{}); err != nil {
api.AddToScheme(legacyscheme.Scheme)
require.NoError(t, api.AddToScheme(legacyscheme.Scheme))
}
table := map[string]struct {

View File

@@ -12,7 +12,7 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/api/resource",
deps = [
"//pkg/apis/core:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
],
)
@@ -35,6 +35,8 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
],
)

View File

@@ -25,50 +25,45 @@ import (
api "k8s.io/kubernetes/pkg/apis/core"
)
// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
// containers of the pod.
func PodRequestsAndLimits(pod *api.Pod) (reqs map[api.ResourceName]resource.Quantity, limits map[api.ResourceName]resource.Quantity) {
reqs, limits = map[api.ResourceName]resource.Quantity{}, map[api.ResourceName]resource.Quantity{}
for _, container := range pod.Spec.Containers {
for name, quantity := range container.Resources.Requests {
if value, ok := reqs[name]; !ok {
reqs[name] = *quantity.Copy()
} else {
value.Add(quantity)
reqs[name] = value
}
// addResourceList adds the resources in newList to list
func addResourceList(list, new api.ResourceList) {
for name, quantity := range new {
if value, ok := list[name]; !ok {
list[name] = *quantity.Copy()
} else {
value.Add(quantity)
list[name] = value
}
for name, quantity := range container.Resources.Limits {
if value, ok := limits[name]; !ok {
limits[name] = *quantity.Copy()
} else {
value.Add(quantity)
limits[name] = value
}
}
// maxResourceList sets list to the greater of list/newList for every resource
// either list
func maxResourceList(list, new api.ResourceList) {
for name, quantity := range new {
if value, ok := list[name]; !ok {
list[name] = *quantity.Copy()
continue
} else {
if quantity.Cmp(value) > 0 {
list[name] = *quantity.Copy()
}
}
}
}
// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
// containers of the pod.
func PodRequestsAndLimits(pod *api.Pod) (reqs api.ResourceList, limits api.ResourceList) {
reqs, limits = api.ResourceList{}, api.ResourceList{}
for _, container := range pod.Spec.Containers {
addResourceList(reqs, container.Resources.Requests)
addResourceList(limits, container.Resources.Limits)
}
// init containers define the minimum of any resource
for _, container := range pod.Spec.InitContainers {
for name, quantity := range container.Resources.Requests {
value, ok := reqs[name]
if !ok {
reqs[name] = *quantity.Copy()
continue
}
if quantity.Cmp(value) > 0 {
reqs[name] = *quantity.Copy()
}
}
for name, quantity := range container.Resources.Limits {
value, ok := limits[name]
if !ok {
limits[name] = *quantity.Copy()
continue
}
if quantity.Cmp(value) > 0 {
limits[name] = *quantity.Copy()
}
}
maxResourceList(reqs, container.Resources.Requests)
maxResourceList(limits, container.Resources.Limits)
}
return
}

View File

@@ -17,9 +17,12 @@ limitations under the License.
package resource
import (
"strings"
"testing"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/uuid"
api "k8s.io/kubernetes/pkg/apis/core"
)
@@ -60,3 +63,184 @@ func TestDefaultResourceHelpers(t *testing.T) {
t.Errorf("expected %v, actual %v", resource.BinarySI, resourceList.Memory().Format)
}
}
func TestPodRequestsAndLimits(t *testing.T) {
tests := []struct {
name string
pod *api.Pod
expectreqs map[api.ResourceName]resource.Quantity
expectlimits map[api.ResourceName]resource.Quantity
}{
{
name: "InitContainers resource < Containers resource",
pod: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
UID: uuid.NewUUID(),
},
Spec: api.PodSpec{
InitContainers: []api.Container{
makeContainer("100m", "200m", "100Mi", "200Mi"),
},
Containers: []api.Container{
makeContainer("100m", "400m", "100Mi", "400Mi"),
makeContainer("100m", "200m", "100Mi", "200Mi"),
},
},
},
expectreqs: map[api.ResourceName]resource.Quantity{
api.ResourceCPU: resource.MustParse("200m"),
api.ResourceMemory: resource.MustParse("200Mi"),
},
expectlimits: map[api.ResourceName]resource.Quantity{
api.ResourceCPU: resource.MustParse("600m"),
api.ResourceMemory: resource.MustParse("600Mi"),
},
},
{
name: "InitContainers resource > Containers resource",
pod: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
UID: uuid.NewUUID(),
},
Spec: api.PodSpec{
InitContainers: []api.Container{
makeContainer("500m", "500m", "500Mi", "500Mi"),
makeContainer("100m", "200m", "100Mi", "200Mi"),
},
Containers: []api.Container{
makeContainer("100m", "200m", "100Mi", "200Mi"),
makeContainer("100m", "200m", "100Mi", "200Mi"),
},
},
},
expectreqs: map[api.ResourceName]resource.Quantity{
api.ResourceCPU: resource.MustParse("500m"),
api.ResourceMemory: resource.MustParse("500Mi"),
},
expectlimits: map[api.ResourceName]resource.Quantity{
api.ResourceCPU: resource.MustParse("500m"),
api.ResourceMemory: resource.MustParse("500Mi"),
},
},
}
for i, test := range tests {
t.Run(test.name, func(t *testing.T) {
requests, limits := PodRequestsAndLimits(test.pod)
for name, quantity := range test.expectreqs {
if value, ok := requests[name]; !ok {
t.Errorf("case[%d]: Error to get value of key=%s from requests result", i, name)
} else if quantity.Cmp(value) != 0 {
t.Errorf("case[%d]: Expected value of key=%s from requests result:%v, Got:%v", i, name, quantity, value)
}
}
for name, quantity := range test.expectlimits {
if value, ok := limits[name]; !ok {
t.Errorf("case[%d]: Error to get value of key=%s from limits result", i, name)
} else if quantity.Cmp(value) != 0 {
t.Errorf("case[%d]: Expected value of key=%s from limits result:%v, Got:%v", i, name, quantity, value)
}
}
})
}
}
func TestExtractContainerResourceValue(t *testing.T) {
testcontainer := &api.Container{
Name: string(uuid.NewUUID()),
Resources: api.ResourceRequirements{
Limits: api.ResourceList{
api.ResourceCPU: resource.MustParse("200m"),
api.ResourceMemory: resource.MustParse("200Mi"),
api.ResourceStorage: resource.MustParse("2G"),
api.ResourceEphemeralStorage: resource.MustParse("2G"),
},
Requests: api.ResourceList{
api.ResourceCPU: resource.MustParse("100m"),
api.ResourceMemory: resource.MustParse("100Mi"),
api.ResourceStorage: resource.MustParse("1G"),
api.ResourceEphemeralStorage: resource.MustParse("300Mi"),
},
},
}
tests := []struct {
name string
filed *api.ResourceFieldSelector
expectresult string
expecterr string
}{
{
name: "get limits cpu",
filed: &api.ResourceFieldSelector{Resource: "limits.cpu", Divisor: resource.MustParse("1m")},
expectresult: "200",
expecterr: "",
},
{
name: "get limits memory",
filed: &api.ResourceFieldSelector{Resource: "limits.memory"},
expectresult: "209715200",
expecterr: "",
},
{
name: "get limits ephemeral-storage",
filed: &api.ResourceFieldSelector{Resource: "limits.ephemeral-storage", Divisor: resource.MustParse("1G")},
expectresult: "2",
expecterr: "",
},
{
name: "get requests cpu",
filed: &api.ResourceFieldSelector{Resource: "requests.cpu", Divisor: resource.MustParse("1m")},
expectresult: "100",
expecterr: "",
},
{
name: "get requests memory",
filed: &api.ResourceFieldSelector{Resource: "requests.memory", Divisor: resource.MustParse("1G")},
expectresult: "1",
expecterr: "",
},
{
name: "get requests ephemeral-storage",
filed: &api.ResourceFieldSelector{Resource: "requests.ephemeral-storage"},
expectresult: "314572800",
expecterr: "",
},
{
name: "get limits storage",
filed: &api.ResourceFieldSelector{Resource: "limits.storage", Divisor: resource.MustParse("1G")},
expectresult: "",
expecterr: "unsupported container resource",
},
}
for i, test := range tests {
t.Run(test.name, func(t *testing.T) {
result, err := ExtractContainerResourceValue(test.filed, testcontainer)
if test.expecterr != "" {
if !strings.Contains(err.Error(), test.expecterr) {
t.Errorf("case[%d]:%s Expected err:%s, Got err:%s", i, test.name, test.expecterr, err.Error())
}
} else if err != nil {
t.Errorf("case[%d]:%s Expected no err, Got err:%s", i, test.name, err.Error())
}
if result != test.expectresult {
t.Errorf("case[%d]:%s Expected result:%s, Got result:%s", i, test.name, test.expectresult, result)
}
})
}
}
func makeContainer(cpuReq, cpuLim, memReq, memLim string) api.Container {
return api.Container{
Name: string(uuid.NewUUID()),
Resources: api.ResourceRequirements{
Limits: api.ResourceList{
api.ResourceCPU: resource.MustParse(cpuLim),
api.ResourceMemory: resource.MustParse(memLim),
},
Requests: api.ResourceList{
api.ResourceCPU: resource.MustParse(cpuReq),
api.ResourceMemory: resource.MustParse(memReq),
},
},
}
}

View File

@@ -27,7 +27,8 @@ go_library(
"//pkg/apis/batch/install:go_default_library",
"//pkg/apis/certificates:go_default_library",
"//pkg/apis/certificates/install:go_default_library",
"//pkg/apis/componentconfig/install:go_default_library",
"//pkg/apis/coordination:go_default_library",
"//pkg/apis/coordination/install:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/install:go_default_library",
"//pkg/apis/events:go_default_library",
@@ -48,9 +49,9 @@ go_library(
"//pkg/apis/settings/install:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/apis/storage/install:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
],
)
@@ -59,8 +60,8 @@ go_test(
srcs = ["testapi_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)

View File

@@ -41,6 +41,7 @@ import (
"k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/certificates"
"k8s.io/kubernetes/pkg/apis/coordination"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/events"
"k8s.io/kubernetes/pkg/apis/extensions"
@@ -60,7 +61,7 @@ import (
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
_ "k8s.io/kubernetes/pkg/apis/batch/install"
_ "k8s.io/kubernetes/pkg/apis/certificates/install"
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
_ "k8s.io/kubernetes/pkg/apis/coordination/install"
_ "k8s.io/kubernetes/pkg/apis/core/install"
_ "k8s.io/kubernetes/pkg/apis/events/install"
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
@@ -257,6 +258,12 @@ func init() {
externalGroupVersion: externalGroupVersion,
}
}
if _, ok := Groups[coordination.GroupName]; !ok {
externalGroupVersion := schema.GroupVersion{Group: coordination.GroupName, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(coordination.GroupName)[0].Version}
Groups[coordination.GroupName] = TestGroup{
externalGroupVersion: externalGroupVersion,
}
}
Default = Groups[api.GroupName]
Autoscaling = Groups[autoscaling.GroupName]

View File

@@ -31,14 +31,15 @@ go_library(
"//pkg/apis/policy/fuzzer:go_default_library",
"//pkg/apis/rbac/fuzzer:go_default_library",
"//pkg/apis/storage/fuzzer:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/apitesting:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/apitesting/fuzzer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
],
)
@@ -82,28 +83,28 @@ go_test(
"//pkg/apis/core/validation:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/extensions/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/apitesting/fuzzer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/apitesting/roundtrip:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/json-iterator/go:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
],
)

View File

@@ -11,9 +11,9 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/api/testing/compat",
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)

View File

@@ -20,6 +20,7 @@ import (
"testing"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/api/legacyscheme"
)
@@ -38,6 +39,13 @@ func TestSelectableFieldLabelConversionsOfKind(t *testing.T, apiVersion string,
value := "value"
gv, err := schema.ParseGroupVersion(apiVersion)
if err != nil {
t.Errorf("kind=%s: got unexpected error: %v", kind, err)
return
}
gvk := gv.WithKind(kind)
if len(fields) == 0 {
t.Logf("no selectable fields for kind %q, skipping", kind)
}
@@ -46,7 +54,7 @@ func TestSelectableFieldLabelConversionsOfKind(t *testing.T, apiVersion string,
t.Logf("FIXME: \"name\" is deprecated by \"metadata.name\", it should be removed from selectable fields of kind=%s", kind)
continue
}
newLabel, newValue, err := legacyscheme.Scheme.ConvertFieldLabel(apiVersion, kind, label, value)
newLabel, newValue, err := legacyscheme.Scheme.ConvertFieldLabel(gvk, label, value)
if err != nil {
t.Errorf("kind=%s label=%s: got unexpected error: %v", kind, label, err)
} else {
@@ -64,7 +72,7 @@ func TestSelectableFieldLabelConversionsOfKind(t *testing.T, apiVersion string,
}
for _, label := range badFieldLabels {
_, _, err := legacyscheme.Scheme.ConvertFieldLabel(apiVersion, kind, label, "value")
_, _, err := legacyscheme.Scheme.ConvertFieldLabel(gvk, label, "value")
if err == nil {
t.Errorf("kind=%s label=%s: got unexpected non-error", kind, label)
}

View File

@@ -21,8 +21,8 @@ import (
"math/rand"
"testing"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"

View File

@@ -24,8 +24,8 @@ import (
"github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
"k8s.io/apimachinery/pkg/api/apitesting/roundtrip"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"

View File

@@ -26,7 +26,7 @@ import (
apiv1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
roundtrip "k8s.io/apimachinery/pkg/api/testing/roundtrip"
roundtrip "k8s.io/apimachinery/pkg/api/apitesting/roundtrip"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -88,9 +88,6 @@ func TestDefaulting(t *testing.T) {
{Group: "batch", Version: "v2alpha1", Kind: "JobTemplate"}: {},
{Group: "certificates.k8s.io", Version: "v1beta1", Kind: "CertificateSigningRequest"}: {},
{Group: "certificates.k8s.io", Version: "v1beta1", Kind: "CertificateSigningRequestList"}: {},
{Group: "componentconfig", Version: "v1alpha1", Kind: "KubeProxyConfiguration"}: {},
{Group: "componentconfig", Version: "v1alpha1", Kind: "KubeSchedulerConfiguration"}: {},
{Group: "componentconfig", Version: "v1alpha1", Kind: "KubeletConfiguration"}: {},
{Group: "kubeadm.k8s.io", Version: "v1alpha1", Kind: "MasterConfiguration"}: {},
// This object contains only int fields which currently breaks the defaulting test because
// it's pretty stupid. Once we add non integer fields, we should uncomment this.

View File

@@ -22,8 +22,8 @@ import (
fuzz "github.com/google/gofuzz"
"k8s.io/api/core/v1"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
apitesting "k8s.io/apimachinery/pkg/api/apitesting"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
genericfuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer"
"k8s.io/apimachinery/pkg/runtime"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"

View File

@@ -26,8 +26,8 @@ import (
"github.com/gogo/protobuf/proto"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"

View File

@@ -19,7 +19,7 @@ package testing
import (
"bytes"
"encoding/hex"
"encoding/json"
gojson "encoding/json"
"io/ioutil"
"math/rand"
"reflect"
@@ -29,15 +29,15 @@ import (
"k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
"k8s.io/apimachinery/pkg/api/apitesting/roundtrip"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
k8s_json "k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/sets"
@@ -72,7 +72,7 @@ func Convert_v1beta1_ReplicaSet_to_api_ReplicationController(in *v1beta1.Replica
}
intermediate2 := &v1.ReplicationController{}
if err := k8s_api_v1.Convert_extensions_ReplicaSet_to_v1_ReplicationController(intermediate1, intermediate2, s); err != nil {
if err := k8s_api_v1.Convert_extensions_ReplicaSet_To_v1_ReplicationController(intermediate1, intermediate2, s); err != nil {
return err
}
@@ -156,11 +156,13 @@ var nonRoundTrippableTypes = sets.NewString(
"WatchEvent",
// ListOptions is now part of the meta group
"ListOptions",
// Delete options is only read in metav1
// DeleteOptions, CreateOptions and UpdateOptions are only read in metav1
"DeleteOptions",
"CreateOptions",
"UpdateOptions",
)
var commonKinds = []string{"Status", "ListOptions", "DeleteOptions", "ExportOptions"}
var commonKinds = []string{"Status", "ListOptions", "DeleteOptions", "ExportOptions", "GetOptions", "CreateOptions", "UpdateOptions"}
// TestCommonKindsRegistered verifies that all group/versions registered with
// the testapi package have the common kinds.
@@ -203,11 +205,7 @@ func TestCommonKindsRegistered(t *testing.T) {
func TestRoundTripTypes(t *testing.T) {
seed := rand.Int63()
fuzzer := fuzzer.FuzzerFor(FuzzerFuncs, rand.NewSource(seed), legacyscheme.Codecs)
nonRoundTrippableTypes := map[schema.GroupVersionKind]bool{
{Group: "componentconfig", Version: runtime.APIVersionInternal, Kind: "KubeProxyConfiguration"}: true,
{Group: "componentconfig", Version: runtime.APIVersionInternal, Kind: "KubeSchedulerConfiguration"}: true,
}
nonRoundTrippableTypes := map[schema.GroupVersionKind]bool{}
roundtrip.RoundTripTypes(t, legacyscheme.Scheme, legacyscheme.Codecs, fuzzer, nonRoundTrippableTypes)
}
@@ -437,7 +435,7 @@ func BenchmarkEncodeJSONMarshal(b *testing.B) {
width := len(items)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := json.Marshal(&items[i%width]); err != nil {
if _, err := gojson.Marshal(&items[i%width]); err != nil {
b.Fatal(err)
}
}
@@ -529,7 +527,7 @@ func BenchmarkDecodeIntoJSON(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
obj := v1.Pod{}
if err := json.Unmarshal(encoded[i%width], &obj); err != nil {
if err := gojson.Unmarshal(encoded[i%width], &obj); err != nil {
b.Fatal(err)
}
}
@@ -579,7 +577,7 @@ func BenchmarkDecodeIntoJSONCodecGenConfigCompatibleWithStandardLibrary(b *testi
}
b.ResetTimer()
iter := k8s_json.CaseSensitiveJsonIterator()
iter := json.CaseSensitiveJsonIterator()
for i := 0; i < b.N; i++ {
obj := v1.Pod{}
if err := iter.Unmarshal(encoded[i%width], &obj); err != nil {

View File

@@ -24,9 +24,9 @@ import (
"github.com/google/gofuzz"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metaunstruct "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"

View File

@@ -12,8 +12,8 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/api/v1/endpoints",
deps = [
"//pkg/util/hash:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
],
)
@@ -22,9 +22,9 @@ go_test(
srcs = ["util_test.go"],
embed = [":go_default_library"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
],
)

View File

@@ -38,12 +38,12 @@ func RepackSubsets(subsets []v1.EndpointSubset) []v1.EndpointSubset {
allAddrs := map[addressKey]*v1.EndpointAddress{}
portToAddrReadyMap := map[v1.EndpointPort]addressSet{}
for i := range subsets {
for _, port := range subsets[i].Ports {
for k := range subsets[i].Addresses {
mapAddressByPort(&subsets[i].Addresses[k], port, true, allAddrs, portToAddrReadyMap)
}
for k := range subsets[i].NotReadyAddresses {
mapAddressByPort(&subsets[i].NotReadyAddresses[k], port, false, allAddrs, portToAddrReadyMap)
if len(subsets[i].Ports) == 0 {
// Don't discard endpoints with no ports defined, use a sentinel.
mapAddressesByPort(&subsets[i], v1.EndpointPort{Port: -1}, allAddrs, portToAddrReadyMap)
} else {
for _, port := range subsets[i].Ports {
mapAddressesByPort(&subsets[i], port, allAddrs, portToAddrReadyMap)
}
}
}
@@ -58,7 +58,14 @@ func RepackSubsets(subsets []v1.EndpointSubset) []v1.EndpointSubset {
for port, addrs := range portToAddrReadyMap {
key := keyString(hashAddresses(addrs))
keyToAddrReadyMap[key] = addrs
addrReadyMapKeyToPorts[key] = append(addrReadyMapKeyToPorts[key], port)
if port.Port > 0 { // avoid sentinels
addrReadyMapKeyToPorts[key] = append(addrReadyMapKeyToPorts[key], port)
} else {
if _, found := addrReadyMapKeyToPorts[key]; !found {
// Force it to be present in the map
addrReadyMapKeyToPorts[key] = nil
}
}
}
// Next, build the N-to-M association the API wants.
@@ -85,7 +92,17 @@ type addressKey struct {
uid types.UID
}
// mapAddressByPort adds an address into a map by its ports, registering the address with a unique pointer, and preserving
// mapAddressesByPort adds all ready and not-ready addresses into a map by a single port.
func mapAddressesByPort(subset *v1.EndpointSubset, port v1.EndpointPort, allAddrs map[addressKey]*v1.EndpointAddress, portToAddrReadyMap map[v1.EndpointPort]addressSet) {
for k := range subset.Addresses {
mapAddressByPort(&subset.Addresses[k], port, true, allAddrs, portToAddrReadyMap)
}
for k := range subset.NotReadyAddresses {
mapAddressByPort(&subset.NotReadyAddresses[k], port, false, allAddrs, portToAddrReadyMap)
}
}
// mapAddressByPort adds one address into a map by port, registering the address with a unique pointer, and preserving
// any existing ready state.
func mapAddressByPort(addr *v1.EndpointAddress, port v1.EndpointPort, ready bool, allAddrs map[addressKey]*v1.EndpointAddress, portToAddrReadyMap map[v1.EndpointPort]addressSet) *v1.EndpointAddress {
// use addressKey to distinguish between two endpoints that are identical addresses

View File

@@ -51,11 +51,11 @@ func TestPackSubsets(t *testing.T) {
}, {
name: "empty ports",
given: []v1.EndpointSubset{{Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []v1.EndpointPort{}}},
expect: []v1.EndpointSubset{},
expect: []v1.EndpointSubset{{Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}, Ports: nil}},
}, {
name: "empty ports",
given: []v1.EndpointSubset{{NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []v1.EndpointPort{}}},
expect: []v1.EndpointSubset{},
expect: []v1.EndpointSubset{{NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}, Ports: nil}},
}, {
name: "one set, one ip, one port",
given: []v1.EndpointSubset{{

View File

@@ -9,7 +9,7 @@ go_library(
name = "go_default_library",
srcs = ["util.go"],
importpath = "k8s.io/kubernetes/pkg/api/v1/node",
deps = ["//vendor/k8s.io/api/core/v1:go_default_library"],
deps = ["//staging/src/k8s.io/api/core/v1:go_default_library"],
)
filegroup(

View File

@@ -0,0 +1,41 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["util.go"],
importpath = "k8s.io/kubernetes/pkg/api/v1/persistentvolume",
visibility = ["//visibility:public"],
deps = [
"//pkg/features:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,144 @@
/*
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 persistentvolume
import (
corev1 "k8s.io/api/core/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/features"
)
func getClaimRefNamespace(pv *corev1.PersistentVolume) string {
if pv.Spec.ClaimRef != nil {
return pv.Spec.ClaimRef.Namespace
}
return ""
}
// Visitor is called with each object's namespace and name, and returns true if visiting should continue
type Visitor func(namespace, name string, kubeletVisible bool) (shouldContinue bool)
// VisitPVSecretNames invokes the visitor function with the name of every secret
// referenced by the PV spec. If visitor returns false, visiting is short-circuited.
// Returns true if visiting completed, false if visiting was short-circuited.
func VisitPVSecretNames(pv *corev1.PersistentVolume, visitor Visitor) bool {
source := &pv.Spec.PersistentVolumeSource
switch {
case source.AzureFile != nil:
if source.AzureFile.SecretNamespace != nil && len(*source.AzureFile.SecretNamespace) > 0 {
if len(source.AzureFile.SecretName) > 0 && !visitor(*source.AzureFile.SecretNamespace, source.AzureFile.SecretName, true /* kubeletVisible */) {
return false
}
} else {
if len(source.AzureFile.SecretName) > 0 && !visitor(getClaimRefNamespace(pv), source.AzureFile.SecretName, true /* kubeletVisible */) {
return false
}
}
return true
case source.CephFS != nil:
if source.CephFS.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.CephFS.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.CephFS.SecretRef.Namespace
}
if !visitor(ns, source.CephFS.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.Cinder != nil:
if source.Cinder.SecretRef != nil && !visitor(source.Cinder.SecretRef.Namespace, source.Cinder.SecretRef.Name, true /* kubeletVisible */) {
return false
}
case source.FlexVolume != nil:
if source.FlexVolume.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.FlexVolume.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.FlexVolume.SecretRef.Namespace
}
if !visitor(ns, source.FlexVolume.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.RBD != nil:
if source.RBD.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.RBD.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.RBD.SecretRef.Namespace
}
if !visitor(ns, source.RBD.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.ScaleIO != nil:
if source.ScaleIO.SecretRef != nil {
ns := getClaimRefNamespace(pv)
if source.ScaleIO.SecretRef != nil && len(source.ScaleIO.SecretRef.Namespace) > 0 {
ns = source.ScaleIO.SecretRef.Namespace
}
if !visitor(ns, source.ScaleIO.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.ISCSI != nil:
if source.ISCSI.SecretRef != nil {
// previously persisted PV objects use claimRef namespace
ns := getClaimRefNamespace(pv)
if len(source.ISCSI.SecretRef.Namespace) > 0 {
// use the secret namespace if namespace is set
ns = source.ISCSI.SecretRef.Namespace
}
if !visitor(ns, source.ISCSI.SecretRef.Name, true /* kubeletVisible */) {
return false
}
}
case source.StorageOS != nil:
if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Namespace, source.StorageOS.SecretRef.Name, true /* kubeletVisible */) {
return false
}
case source.CSI != nil:
if source.CSI.ControllerPublishSecretRef != nil {
if !visitor(source.CSI.ControllerPublishSecretRef.Namespace, source.CSI.ControllerPublishSecretRef.Name, false /* kubeletVisible */) {
return false
}
}
if source.CSI.NodePublishSecretRef != nil {
if !visitor(source.CSI.NodePublishSecretRef.Namespace, source.CSI.NodePublishSecretRef.Name, true /* kubeletVisible */) {
return false
}
}
if source.CSI.NodeStageSecretRef != nil {
if !visitor(source.CSI.NodeStageSecretRef.Namespace, source.CSI.NodeStageSecretRef.Name, true /* kubeletVisible */) {
return false
}
}
}
return true
}
// DropDisabledAlphaFields removes disabled fields from the pv spec.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pv spec.
func DropDisabledAlphaFields(pvSpec *corev1.PersistentVolumeSpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
pvSpec.VolumeMode = nil
}
}

View File

@@ -22,6 +22,7 @@ import (
"strings"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
utilfeature "k8s.io/apiserver/pkg/util/feature"
@@ -33,115 +34,115 @@ func TestPVSecrets(t *testing.T) {
// Stub containing all possible secret references in a PV.
// The names of the referenced secrets match struct paths detected by reflection.
secretNamespace := "Spec.PersistentVolumeSource.AzureFile.SecretNamespace"
pvs := []*api.PersistentVolume{
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
AzureFile: &api.AzureFilePersistentVolumeSource{
pvs := []*corev1.PersistentVolume{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
AzureFile: &corev1.AzureFilePersistentVolumeSource{
SecretName: "Spec.PersistentVolumeSource.AzureFile.SecretName"}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
AzureFile: &api.AzureFilePersistentVolumeSource{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
AzureFile: &corev1.AzureFilePersistentVolumeSource{
SecretName: "Spec.PersistentVolumeSource.AzureFile.SecretName",
SecretNamespace: &secretNamespace}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
CephFS: &api.CephFSPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
CephFS: &corev1.CephFSPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.CephFS.SecretRef",
Namespace: "cephfs"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
CephFS: &api.CephFSPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
CephFS: &corev1.CephFSPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.CephFS.SecretRef"}}}}},
{Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
Cinder: &api.CinderPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
PersistentVolumeSource: corev1.PersistentVolumeSource{
Cinder: &corev1.CinderPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.Cinder.SecretRef",
Namespace: "cinder"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
FlexVolume: &api.FlexPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
FlexVolume: &corev1.FlexPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.FlexVolume.SecretRef",
Namespace: "flexns"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
FlexVolume: &api.FlexPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
FlexVolume: &corev1.FlexPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.FlexVolume.SecretRef"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
RBD: &api.RBDPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
RBD: &corev1.RBDPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.RBD.SecretRef"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
RBD: &api.RBDPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
RBD: &corev1.RBDPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.RBD.SecretRef",
Namespace: "rbdns"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
ScaleIO: &api.ScaleIOPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
ScaleIO: &corev1.ScaleIOPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.ScaleIO.SecretRef"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
ScaleIO: &api.ScaleIOPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
ScaleIO: &corev1.ScaleIOPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.ScaleIO.SecretRef",
Namespace: "scaleions"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
ISCSI: &api.ISCSIPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
ISCSI: &corev1.ISCSIPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.ISCSI.SecretRef",
Namespace: "iscsi"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
ISCSI: &api.ISCSIPersistentVolumeSource{
SecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
ISCSI: &corev1.ISCSIPersistentVolumeSource{
SecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.ISCSI.SecretRef"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
StorageOS: &api.StorageOSPersistentVolumeSource{
SecretRef: &api.ObjectReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
StorageOS: &corev1.StorageOSPersistentVolumeSource{
SecretRef: &corev1.ObjectReference{
Name: "Spec.PersistentVolumeSource.StorageOS.SecretRef",
Namespace: "storageosns"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
CSI: &api.CSIPersistentVolumeSource{
ControllerPublishSecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
CSI: &corev1.CSIPersistentVolumeSource{
ControllerPublishSecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.CSI.ControllerPublishSecretRef",
Namespace: "csi"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
CSI: &api.CSIPersistentVolumeSource{
NodePublishSecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
CSI: &corev1.CSIPersistentVolumeSource{
NodePublishSecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.CSI.NodePublishSecretRef",
Namespace: "csi"}}}}},
{Spec: api.PersistentVolumeSpec{
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: api.PersistentVolumeSource{
CSI: &api.CSIPersistentVolumeSource{
NodeStageSecretRef: &api.SecretReference{
{Spec: corev1.PersistentVolumeSpec{
ClaimRef: &corev1.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
PersistentVolumeSource: corev1.PersistentVolumeSource{
CSI: &corev1.CSIPersistentVolumeSource{
NodeStageSecretRef: &corev1.SecretReference{
Name: "Spec.PersistentVolumeSource.CSI.NodeStageSecretRef",
Namespace: "csi"}}}}},
}
@@ -266,23 +267,23 @@ func collectSecretPaths(t *testing.T, path *field.Path, name string, tp reflect.
return secretPaths
}
func newHostPathType(pathType string) *api.HostPathType {
hostPathType := new(api.HostPathType)
*hostPathType = api.HostPathType(pathType)
func newHostPathType(pathType string) *corev1.HostPathType {
hostPathType := new(corev1.HostPathType)
*hostPathType = corev1.HostPathType(pathType)
return hostPathType
}
func TestDropAlphaPVVolumeMode(t *testing.T) {
vmode := api.PersistentVolumeFilesystem
vmode := corev1.PersistentVolumeFilesystem
// PersistentVolume with VolumeMode set
pv := api.PersistentVolume{
Spec: api.PersistentVolumeSpec{
AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
PersistentVolumeSource: api.PersistentVolumeSource{
HostPath: &api.HostPathVolumeSource{
pv := corev1.PersistentVolume{
Spec: corev1.PersistentVolumeSpec{
AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce},
PersistentVolumeSource: corev1.PersistentVolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(api.HostPathDirectory)),
Type: newHostPathType(string(corev1.HostPathDirectory)),
},
},
StorageClassName: "test-storage-class",

View File

@@ -11,9 +11,9 @@ go_library(
srcs = ["util.go"],
importpath = "k8s.io/kubernetes/pkg/api/v1/pod",
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
],
)
@@ -22,12 +22,12 @@ go_test(
srcs = ["util_test.go"],
embed = [":go_default_library"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
],
)

View File

@@ -209,14 +209,10 @@ func GetContainerStatus(statuses []v1.ContainerStatus, name string) (v1.Containe
}
// GetExistingContainerStatus extracts the status of container "name" from "statuses",
// and returns empty status if "name" does not exist.
// It also returns if "name" exists.
func GetExistingContainerStatus(statuses []v1.ContainerStatus, name string) v1.ContainerStatus {
for i := range statuses {
if statuses[i].Name == name {
return statuses[i]
}
}
return v1.ContainerStatus{}
status, _ := GetContainerStatus(statuses, name)
return status
}
// IsPodAvailable returns true if a pod is available; false otherwise.

View File

@@ -301,7 +301,7 @@ func TestPodSecrets(t *testing.T) {
"Spec.Volumes[*].VolumeSource.ISCSI.SecretRef",
"Spec.Volumes[*].VolumeSource.StorageOS.SecretRef",
)
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&v1.Pod{}))
secretPaths := collectResourcePaths(t, "secret", nil, "", reflect.TypeOf(&v1.Pod{}))
secretPaths = secretPaths.Difference(excludedSecretPaths)
if missingPaths := expectedSecretPaths.Difference(secretPaths); len(missingPaths) > 0 {
t.Logf("Missing expected secret paths:\n%s", strings.Join(missingPaths.List(), "\n"))
@@ -322,38 +322,113 @@ func TestPodSecrets(t *testing.T) {
}
}
// collectSecretPaths traverses the object, computing all the struct paths that lead to fields with "secret" in the name.
func collectSecretPaths(t *testing.T, path *field.Path, name string, tp reflect.Type) sets.String {
secretPaths := sets.NewString()
// collectResourcePaths traverses the object, computing all the struct paths that lead to fields with resourcename in the name.
func collectResourcePaths(t *testing.T, resourcename string, path *field.Path, name string, tp reflect.Type) sets.String {
resourcename = strings.ToLower(resourcename)
resourcePaths := sets.NewString()
if tp.Kind() == reflect.Ptr {
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...)
return secretPaths
resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...)
return resourcePaths
}
if strings.Contains(strings.ToLower(name), "secret") {
secretPaths.Insert(path.String())
if strings.Contains(strings.ToLower(name), resourcename) {
resourcePaths.Insert(path.String())
}
switch tp.Kind() {
case reflect.Ptr:
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...)
resourcePaths.Insert(collectResourcePaths(t, resourcename, path, name, tp.Elem()).List()...)
case reflect.Struct:
for i := 0; i < tp.NumField(); i++ {
field := tp.Field(i)
secretPaths.Insert(collectSecretPaths(t, path.Child(field.Name), field.Name, field.Type).List()...)
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Child(field.Name), field.Name, field.Type).List()...)
}
case reflect.Interface:
t.Errorf("cannot find secret fields in interface{} field %s", path.String())
t.Errorf("cannot find %s fields in interface{} field %s", resourcename, path.String())
case reflect.Map:
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...)
case reflect.Slice:
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
resourcePaths.Insert(collectResourcePaths(t, resourcename, path.Key("*"), "", tp.Elem()).List()...)
default:
// all primitive types
}
return secretPaths
return resourcePaths
}
func TestPodConfigmaps(t *testing.T) {
// Stub containing all possible ConfigMap references in a pod.
// The names of the referenced ConfigMaps match struct paths detected by reflection.
pod := &v1.Pod{
Spec: v1.PodSpec{
Containers: []v1.Container{{
EnvFrom: []v1.EnvFromSource{{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.Containers[*].EnvFrom[*].ConfigMapRef"}}}},
Env: []v1.EnvVar{{
ValueFrom: &v1.EnvVarSource{
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef"}}}}}}},
InitContainers: []v1.Container{{
EnvFrom: []v1.EnvFromSource{{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.InitContainers[*].EnvFrom[*].ConfigMapRef"}}}},
Env: []v1.EnvVar{{
ValueFrom: &v1.EnvVarSource{
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.InitContainers[*].Env[*].ValueFrom.ConfigMapKeyRef"}}}}}}},
Volumes: []v1.Volume{{
VolumeSource: v1.VolumeSource{
Projected: &v1.ProjectedVolumeSource{
Sources: []v1.VolumeProjection{{
ConfigMap: &v1.ConfigMapProjection{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.Projected.Sources[*].ConfigMap"}}}}}}}, {
VolumeSource: v1.VolumeSource{
ConfigMap: &v1.ConfigMapVolumeSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "Spec.Volumes[*].VolumeSource.ConfigMap"}}}}},
},
}
extractedNames := sets.NewString()
VisitPodConfigmapNames(pod, func(name string) bool {
extractedNames.Insert(name)
return true
})
// expectedPaths holds struct paths to fields with "ConfigMap" in the name that are references to ConfigMap API objects.
// every path here should be represented as an example in the Pod stub above, with the ConfigMap name set to the path.
expectedPaths := sets.NewString(
"Spec.Containers[*].EnvFrom[*].ConfigMapRef",
"Spec.Containers[*].Env[*].ValueFrom.ConfigMapKeyRef",
"Spec.InitContainers[*].EnvFrom[*].ConfigMapRef",
"Spec.InitContainers[*].Env[*].ValueFrom.ConfigMapKeyRef",
"Spec.Volumes[*].VolumeSource.Projected.Sources[*].ConfigMap",
"Spec.Volumes[*].VolumeSource.ConfigMap",
)
collectPaths := collectResourcePaths(t, "ConfigMap", nil, "", reflect.TypeOf(&v1.Pod{}))
if missingPaths := expectedPaths.Difference(collectPaths); len(missingPaths) > 0 {
t.Logf("Missing expected paths:\n%s", strings.Join(missingPaths.List(), "\n"))
t.Error("Missing expected paths. Verify VisitPodConfigmapNames() is correctly finding the missing paths, then correct expectedPaths")
}
if extraPaths := collectPaths.Difference(expectedPaths); len(extraPaths) > 0 {
t.Logf("Extra paths:\n%s", strings.Join(extraPaths.List(), "\n"))
t.Error("Extra fields with resource in the name found. Verify VisitPodConfigmapNames() is including these fields if appropriate, then correct expectedPaths")
}
if missingNames := expectedPaths.Difference(extractedNames); len(missingNames) > 0 {
t.Logf("Missing expected names:\n%s", strings.Join(missingNames.List(), "\n"))
t.Error("Missing expected names. Verify the pod stub above includes these references, then verify VisitPodConfigmapNames() is correctly finding the missing names")
}
if extraNames := extractedNames.Difference(expectedPaths); len(extraNames) > 0 {
t.Logf("Extra names:\n%s", strings.Join(extraNames.List(), "\n"))
t.Error("Extra names extracted. Verify VisitPodConfigmapNames() is correctly extracting resource names")
}
}
func newPod(now metav1.Time, ready bool, beforeSec int) *v1.Pod {

View File

@@ -11,9 +11,9 @@ go_test(
srcs = ["helpers_test.go"],
embed = [":go_default_library"],
deps = [
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
],
)
@@ -22,8 +22,8 @@ go_library(
srcs = ["helpers.go"],
importpath = "k8s.io/kubernetes/pkg/api/v1/resource",
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
],
)

View File

@@ -25,50 +25,45 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
)
// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
// containers of the pod.
func PodRequestsAndLimits(pod *v1.Pod) (reqs map[v1.ResourceName]resource.Quantity, limits map[v1.ResourceName]resource.Quantity) {
reqs, limits = map[v1.ResourceName]resource.Quantity{}, map[v1.ResourceName]resource.Quantity{}
for _, container := range pod.Spec.Containers {
for name, quantity := range container.Resources.Requests {
if value, ok := reqs[name]; !ok {
reqs[name] = *quantity.Copy()
} else {
value.Add(quantity)
reqs[name] = value
}
// addResourceList adds the resources in newList to list
func addResourceList(list, new v1.ResourceList) {
for name, quantity := range new {
if value, ok := list[name]; !ok {
list[name] = *quantity.Copy()
} else {
value.Add(quantity)
list[name] = value
}
for name, quantity := range container.Resources.Limits {
if value, ok := limits[name]; !ok {
limits[name] = *quantity.Copy()
} else {
value.Add(quantity)
limits[name] = value
}
}
// maxResourceList sets list to the greater of list/newList for every resource
// either list
func maxResourceList(list, new v1.ResourceList) {
for name, quantity := range new {
if value, ok := list[name]; !ok {
list[name] = *quantity.Copy()
continue
} else {
if quantity.Cmp(value) > 0 {
list[name] = *quantity.Copy()
}
}
}
}
// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
// containers of the pod.
func PodRequestsAndLimits(pod *v1.Pod) (reqs, limits v1.ResourceList) {
reqs, limits = v1.ResourceList{}, v1.ResourceList{}
for _, container := range pod.Spec.Containers {
addResourceList(reqs, container.Resources.Requests)
addResourceList(limits, container.Resources.Limits)
}
// init containers define the minimum of any resource
for _, container := range pod.Spec.InitContainers {
for name, quantity := range container.Resources.Requests {
value, ok := reqs[name]
if !ok {
reqs[name] = *quantity.Copy()
continue
}
if quantity.Cmp(value) > 0 {
reqs[name] = *quantity.Copy()
}
}
for name, quantity := range container.Resources.Limits {
value, ok := limits[name]
if !ok {
limits[name] = *quantity.Copy()
continue
}
if quantity.Cmp(value) > 0 {
limits[name] = *quantity.Copy()
}
}
maxResourceList(reqs, container.Resources.Requests)
maxResourceList(limits, container.Resources.Limits)
}
return
}

View File

@@ -12,7 +12,7 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/api/v1/service",
deps = [
"//pkg/util/net/sets:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
],
)
@@ -22,7 +22,7 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/util/net/sets:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
],
)