Update dependencies
This commit is contained in:
parent
bf5616c65b
commit
d6d374b28d
13962 changed files with 48226 additions and 3618880 deletions
41
vendor/k8s.io/kubernetes/pkg/api/endpoints/BUILD
generated
vendored
41
vendor/k8s.io/kubernetes/pkg/api/endpoints/BUILD
generated
vendored
|
|
@ -1,41 +0,0 @@
|
|||
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"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/util/hash:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
8
vendor/k8s.io/kubernetes/pkg/api/endpoints/OWNERS
generated
vendored
8
vendor/k8s.io/kubernetes/pkg/api/endpoints/OWNERS
generated
vendored
|
|
@ -1,8 +0,0 @@
|
|||
reviewers:
|
||||
- thockin
|
||||
- smarterclayton
|
||||
- mikedanese
|
||||
- sttts
|
||||
- eparis
|
||||
- resouer
|
||||
- david-mcmahon
|
||||
226
vendor/k8s.io/kubernetes/pkg/api/endpoints/util.go
generated
vendored
226
vendor/k8s.io/kubernetes/pkg/api/endpoints/util.go
generated
vendored
|
|
@ -1,226 +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 endpoints
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"hash"
|
||||
"sort"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
hashutil "k8s.io/kubernetes/pkg/util/hash"
|
||||
)
|
||||
|
||||
// RepackSubsets takes a slice of EndpointSubset objects, expands it to the full
|
||||
// representation, and then repacks that into the canonical layout. This
|
||||
// ensures that code which operates on these objects can rely on the common
|
||||
// form for things like comparison. The result is a newly allocated slice.
|
||||
func RepackSubsets(subsets []api.EndpointSubset) []api.EndpointSubset {
|
||||
// First map each unique port definition to the sets of hosts that
|
||||
// offer it.
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next, map the sets of hosts to the sets of ports they offer.
|
||||
// Go does not allow maps or slices as keys to maps, so we have
|
||||
// to synthesize an artificial key and do a sort of 2-part
|
||||
// associative entity.
|
||||
type keyString string
|
||||
keyToAddrReadyMap := map[keyString]addressSet{}
|
||||
addrReadyMapKeyToPorts := map[keyString][]api.EndpointPort{}
|
||||
for port, addrs := range portToAddrReadyMap {
|
||||
key := keyString(hashAddresses(addrs))
|
||||
keyToAddrReadyMap[key] = addrs
|
||||
addrReadyMapKeyToPorts[key] = append(addrReadyMapKeyToPorts[key], port)
|
||||
}
|
||||
|
||||
// Next, build the N-to-M association the API wants.
|
||||
final := []api.EndpointSubset{}
|
||||
for key, ports := range addrReadyMapKeyToPorts {
|
||||
var readyAddrs, notReadyAddrs []api.EndpointAddress
|
||||
for addr, ready := range keyToAddrReadyMap[key] {
|
||||
if ready {
|
||||
readyAddrs = append(readyAddrs, *addr)
|
||||
} else {
|
||||
notReadyAddrs = append(notReadyAddrs, *addr)
|
||||
}
|
||||
}
|
||||
final = append(final, api.EndpointSubset{Addresses: readyAddrs, NotReadyAddresses: notReadyAddrs, Ports: ports})
|
||||
}
|
||||
|
||||
// Finally, sort it.
|
||||
return SortSubsets(final)
|
||||
}
|
||||
|
||||
// The sets of hosts must be de-duped, using IP+UID as the key.
|
||||
type addressKey struct {
|
||||
ip string
|
||||
uid types.UID
|
||||
}
|
||||
|
||||
// mapAddressByPort adds an address into a map by its ports, 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
|
||||
// but may have come from different hosts, for attribution. For instance, Mesos
|
||||
// assigns pods the node IP, but the pods are distinct.
|
||||
key := addressKey{ip: addr.IP}
|
||||
if addr.TargetRef != nil {
|
||||
key.uid = addr.TargetRef.UID
|
||||
}
|
||||
|
||||
// Accumulate the address. The full EndpointAddress structure is preserved for use when
|
||||
// we rebuild the subsets so that the final TargetRef has all of the necessary data.
|
||||
existingAddress := allAddrs[key]
|
||||
if existingAddress == nil {
|
||||
// Make a copy so we don't write to the
|
||||
// input args of this function.
|
||||
existingAddress = &api.EndpointAddress{}
|
||||
*existingAddress = *addr
|
||||
allAddrs[key] = existingAddress
|
||||
}
|
||||
|
||||
// Remember that this port maps to this address.
|
||||
if _, found := portToAddrReadyMap[port]; !found {
|
||||
portToAddrReadyMap[port] = addressSet{}
|
||||
}
|
||||
// if we have not yet recorded this port for this address, or if the previous
|
||||
// state was ready, write the current ready state. not ready always trumps
|
||||
// ready.
|
||||
if wasReady, found := portToAddrReadyMap[port][existingAddress]; !found || wasReady {
|
||||
portToAddrReadyMap[port][existingAddress] = ready
|
||||
}
|
||||
return existingAddress
|
||||
}
|
||||
|
||||
type addressSet map[*api.EndpointAddress]bool
|
||||
|
||||
type addrReady struct {
|
||||
addr *api.EndpointAddress
|
||||
ready bool
|
||||
}
|
||||
|
||||
func hashAddresses(addrs addressSet) string {
|
||||
// Flatten the list of addresses into a string so it can be used as a
|
||||
// map key. Unfortunately, DeepHashObject is implemented in terms of
|
||||
// spew, and spew does not handle non-primitive map keys well. So
|
||||
// first we collapse it into a slice, sort the slice, then hash that.
|
||||
slice := make([]addrReady, 0, len(addrs))
|
||||
for k, ready := range addrs {
|
||||
slice = append(slice, addrReady{k, ready})
|
||||
}
|
||||
sort.Sort(addrsReady(slice))
|
||||
hasher := md5.New()
|
||||
hashutil.DeepHashObject(hasher, slice)
|
||||
return hex.EncodeToString(hasher.Sum(nil)[0:])
|
||||
}
|
||||
|
||||
func lessAddrReady(a, b addrReady) bool {
|
||||
// ready is not significant to hashing since we can't have duplicate addresses
|
||||
return LessEndpointAddress(a.addr, b.addr)
|
||||
}
|
||||
|
||||
type addrsReady []addrReady
|
||||
|
||||
func (sl addrsReady) Len() int { return len(sl) }
|
||||
func (sl addrsReady) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl addrsReady) Less(i, j int) bool {
|
||||
return lessAddrReady(sl[i], sl[j])
|
||||
}
|
||||
|
||||
func LessEndpointAddress(a, b *api.EndpointAddress) bool {
|
||||
ipComparison := bytes.Compare([]byte(a.IP), []byte(b.IP))
|
||||
if ipComparison != 0 {
|
||||
return ipComparison < 0
|
||||
}
|
||||
if b.TargetRef == nil {
|
||||
return false
|
||||
}
|
||||
if a.TargetRef == nil {
|
||||
return true
|
||||
}
|
||||
return a.TargetRef.UID < b.TargetRef.UID
|
||||
}
|
||||
|
||||
type addrPtrsByIpAndUID []*api.EndpointAddress
|
||||
|
||||
func (sl addrPtrsByIpAndUID) Len() int { return len(sl) }
|
||||
func (sl addrPtrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl addrPtrsByIpAndUID) Less(i, j int) bool {
|
||||
return LessEndpointAddress(sl[i], sl[j])
|
||||
}
|
||||
|
||||
// SortSubsets sorts an array of EndpointSubset objects in place. For ease of
|
||||
// use it returns the input slice.
|
||||
func SortSubsets(subsets []api.EndpointSubset) []api.EndpointSubset {
|
||||
for i := range subsets {
|
||||
ss := &subsets[i]
|
||||
sort.Sort(addrsByIpAndUID(ss.Addresses))
|
||||
sort.Sort(addrsByIpAndUID(ss.NotReadyAddresses))
|
||||
sort.Sort(portsByHash(ss.Ports))
|
||||
}
|
||||
sort.Sort(subsetsByHash(subsets))
|
||||
return subsets
|
||||
}
|
||||
|
||||
func hashObject(hasher hash.Hash, obj interface{}) []byte {
|
||||
hashutil.DeepHashObject(hasher, obj)
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
type subsetsByHash []api.EndpointSubset
|
||||
|
||||
func (sl subsetsByHash) Len() int { return len(sl) }
|
||||
func (sl subsetsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl subsetsByHash) Less(i, j int) bool {
|
||||
hasher := md5.New()
|
||||
h1 := hashObject(hasher, sl[i])
|
||||
h2 := hashObject(hasher, sl[j])
|
||||
return bytes.Compare(h1, h2) < 0
|
||||
}
|
||||
|
||||
type addrsByIpAndUID []api.EndpointAddress
|
||||
|
||||
func (sl addrsByIpAndUID) Len() int { return len(sl) }
|
||||
func (sl addrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl addrsByIpAndUID) Less(i, j int) bool {
|
||||
return LessEndpointAddress(&sl[i], &sl[j])
|
||||
}
|
||||
|
||||
type portsByHash []api.EndpointPort
|
||||
|
||||
func (sl portsByHash) Len() int { return len(sl) }
|
||||
func (sl portsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl portsByHash) Less(i, j int) bool {
|
||||
hasher := md5.New()
|
||||
h1 := hashObject(hasher, sl[i])
|
||||
h2 := hashObject(hasher, sl[j])
|
||||
return bytes.Compare(h1, h2) < 0
|
||||
}
|
||||
464
vendor/k8s.io/kubernetes/pkg/api/endpoints/util_test.go
generated
vendored
464
vendor/k8s.io/kubernetes/pkg/api/endpoints/util_test.go
generated
vendored
|
|
@ -1,464 +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 endpoints
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func podRef(uid string) *api.ObjectReference {
|
||||
ref := api.ObjectReference{UID: types.UID(uid)}
|
||||
return &ref
|
||||
}
|
||||
|
||||
func TestPackSubsets(t *testing.T) {
|
||||
// The downside of table-driven tests is that some things have to live outside the table.
|
||||
fooObjRef := api.ObjectReference{Name: "foo"}
|
||||
barObjRef := api.ObjectReference{Name: "bar"}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
given []api.EndpointSubset
|
||||
expect []api.EndpointSubset
|
||||
}{
|
||||
{
|
||||
name: "empty everything",
|
||||
given: []api.EndpointSubset{{Addresses: []api.EndpointAddress{}, Ports: []api.EndpointPort{}}},
|
||||
expect: []api.EndpointSubset{},
|
||||
}, {
|
||||
name: "empty addresses",
|
||||
given: []api.EndpointSubset{{Addresses: []api.EndpointAddress{}, Ports: []api.EndpointPort{{Port: 111}}}},
|
||||
expect: []api.EndpointSubset{},
|
||||
}, {
|
||||
name: "empty ports",
|
||||
given: []api.EndpointSubset{{Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []api.EndpointPort{}}},
|
||||
expect: []api.EndpointSubset{},
|
||||
}, {
|
||||
name: "empty ports",
|
||||
given: []api.EndpointSubset{{NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []api.EndpointPort{}}},
|
||||
expect: []api.EndpointSubset{},
|
||||
}, {
|
||||
name: "one set, one ip, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, one port (IPv6)",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "beef::1:2:3:4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "beef::1:2:3:4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one notReady ip, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, one UID, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one notReady ip, one UID, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, empty UID, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one notReady ip, empty UID, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, two ips, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, two mixed ips, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, two duplicate ips, one port, notReady is covered by ready",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, two ports",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup ips, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup ips, one port (IPv6)",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "beef::1"}, {IP: "beef::1"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "beef::1"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup ips with target-refs, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: &fooObjRef},
|
||||
{IP: "1.2.3.4", TargetRef: &barObjRef},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &fooObjRef}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup mixed ips with target-refs, one port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: &fooObjRef},
|
||||
},
|
||||
NotReadyAddresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: &barObjRef},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
// finding the same address twice is considered an error on input, only the first address+port
|
||||
// reference is preserved
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &fooObjRef}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, dup ports",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}, {Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup ip, dup port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup mixed ip, dup port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup ip, two ports",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup ip, dup uids, two ports",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup mixed ip, dup uids, two ports",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two ips, dup port",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two set, dup ip, two uids, dup ports",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-2")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-1")},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-2")},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two set, dup ip, with and without uid, dup ports",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-2")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-2")},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two ips, two dup ip with uid, dup port, wrong order",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "5.6.7.8", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-1")},
|
||||
{IP: "5.6.7.8"},
|
||||
{IP: "5.6.7.8", TargetRef: podRef("uid-1")},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two mixed ips, two dup ip with uid, dup port, wrong order, ends up with split addresses",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "5.6.7.8", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "5.6.7.8"},
|
||||
},
|
||||
NotReadyAddresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-1")},
|
||||
{IP: "5.6.7.8", TargetRef: podRef("uid-1")},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two ips, two ports",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []api.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "four sets, three ips, three ports, jumbled",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []api.EndpointPort{{Port: 222}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.6"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []api.EndpointPort{{Port: 333}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.6"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []api.EndpointPort{{Port: 222}, {Port: 333}},
|
||||
}},
|
||||
}, {
|
||||
name: "four sets, three mixed ips, three ports, jumbled",
|
||||
given: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []api.EndpointPort{{Port: 222}},
|
||||
}, {
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.6"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []api.EndpointPort{{Port: 333}},
|
||||
}},
|
||||
expect: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.6"}},
|
||||
Ports: []api.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []api.EndpointPort{{Port: 222}, {Port: 333}},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
result := RepackSubsets(tc.given)
|
||||
if !reflect.DeepEqual(result, SortSubsets(tc.expect)) {
|
||||
t.Errorf("case %q: expected %s, got %s", tc.name, spew.Sprintf("%#v", SortSubsets(tc.expect)), spew.Sprintf("%#v", result))
|
||||
}
|
||||
}
|
||||
}
|
||||
36
vendor/k8s.io/kubernetes/pkg/api/events/BUILD
generated
vendored
36
vendor/k8s.io/kubernetes/pkg/api/events/BUILD
generated
vendored
|
|
@ -1,36 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["sorted_event_list.go"],
|
||||
deps = ["//pkg/api:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["sorted_event_list_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
2
vendor/k8s.io/kubernetes/pkg/api/events/OWNERS
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/api/events/OWNERS
generated
vendored
|
|
@ -1,2 +0,0 @@
|
|||
reviewers:
|
||||
- gmarek
|
||||
36
vendor/k8s.io/kubernetes/pkg/api/events/sorted_event_list.go
generated
vendored
36
vendor/k8s.io/kubernetes/pkg/api/events/sorted_event_list.go
generated
vendored
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// SortableEvents implements sort.Interface for []api.Event based on the Timestamp field
|
||||
type SortableEvents []api.Event
|
||||
|
||||
func (list SortableEvents) Len() int {
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (list SortableEvents) Swap(i, j int) {
|
||||
list[i], list[j] = list[j], list[i]
|
||||
}
|
||||
|
||||
func (list SortableEvents) Less(i, j int) bool {
|
||||
return list[i].LastTimestamp.Time.Before(list[j].LastTimestamp.Time)
|
||||
}
|
||||
66
vendor/k8s.io/kubernetes/pkg/api/events/sorted_event_list_test.go
generated
vendored
66
vendor/k8s.io/kubernetes/pkg/api/events/sorted_event_list_test.go
generated
vendored
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func TestSortableEvents(t *testing.T) {
|
||||
// Arrange
|
||||
list := SortableEvents([]api.Event{
|
||||
{
|
||||
Source: api.EventSource{Component: "kubelet"},
|
||||
Message: "Item 1",
|
||||
FirstTimestamp: metav1.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
|
||||
LastTimestamp: metav1.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)),
|
||||
Count: 1,
|
||||
Type: api.EventTypeNormal,
|
||||
},
|
||||
{
|
||||
Source: api.EventSource{Component: "scheduler"},
|
||||
Message: "Item 2",
|
||||
FirstTimestamp: metav1.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)),
|
||||
LastTimestamp: metav1.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)),
|
||||
Count: 1,
|
||||
Type: api.EventTypeNormal,
|
||||
},
|
||||
{
|
||||
Source: api.EventSource{Component: "kubelet"},
|
||||
Message: "Item 3",
|
||||
FirstTimestamp: metav1.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)),
|
||||
LastTimestamp: metav1.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)),
|
||||
Count: 1,
|
||||
Type: api.EventTypeNormal,
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
sort.Sort(list)
|
||||
|
||||
// Assert
|
||||
if list[0].Message != "Item 2" ||
|
||||
list[1].Message != "Item 3" ||
|
||||
list[2].Message != "Item 1" {
|
||||
t.Fatal("List is not sorted by time. List: ", list)
|
||||
}
|
||||
}
|
||||
35
vendor/k8s.io/kubernetes/pkg/api/fuzzer/BUILD
generated
vendored
35
vendor/k8s.io/kubernetes/pkg/api/fuzzer/BUILD
generated
vendored
|
|
@ -1,35 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["fuzzer.go"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels: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:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
465
vendor/k8s.io/kubernetes/pkg/api/fuzzer/fuzzer.go
generated
vendored
465
vendor/k8s.io/kubernetes/pkg/api/fuzzer/fuzzer.go
generated
vendored
|
|
@ -1,465 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fuzzer
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// Funcs returns the fuzzer functions for the core api group.
|
||||
var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
return []interface{}{
|
||||
func(q *resource.Quantity, c fuzz.Continue) {
|
||||
*q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
|
||||
},
|
||||
func(j *api.ObjectReference, c fuzz.Continue) {
|
||||
// We have to customize the randomization of TypeMetas because their
|
||||
// APIVersion and Kind must remain blank in memory.
|
||||
j.APIVersion = c.RandString()
|
||||
j.Kind = c.RandString()
|
||||
j.Namespace = c.RandString()
|
||||
j.Name = c.RandString()
|
||||
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
|
||||
j.FieldPath = c.RandString()
|
||||
},
|
||||
func(j *api.ListOptions, c fuzz.Continue) {
|
||||
label, _ := labels.Parse("a=b")
|
||||
j.LabelSelector = label
|
||||
field, _ := fields.ParseSelector("a=b")
|
||||
j.FieldSelector = field
|
||||
},
|
||||
func(j *api.PodExecOptions, c fuzz.Continue) {
|
||||
j.Stdout = true
|
||||
j.Stderr = true
|
||||
},
|
||||
func(j *api.PodAttachOptions, c fuzz.Continue) {
|
||||
j.Stdout = true
|
||||
j.Stderr = true
|
||||
},
|
||||
func(j *api.PodPortForwardOptions, c fuzz.Continue) {
|
||||
if c.RandBool() {
|
||||
j.Ports = make([]int32, c.Intn(10))
|
||||
for i := range j.Ports {
|
||||
j.Ports[i] = c.Int31n(65535)
|
||||
}
|
||||
}
|
||||
},
|
||||
func(s *api.PodSpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s)
|
||||
// has a default value
|
||||
ttl := int64(30)
|
||||
if c.RandBool() {
|
||||
ttl = int64(c.Uint32())
|
||||
}
|
||||
s.TerminationGracePeriodSeconds = &ttl
|
||||
|
||||
c.Fuzz(s.SecurityContext)
|
||||
|
||||
if s.SecurityContext == nil {
|
||||
s.SecurityContext = new(api.PodSecurityContext)
|
||||
}
|
||||
if s.Affinity == nil {
|
||||
s.Affinity = new(api.Affinity)
|
||||
}
|
||||
if s.SchedulerName == "" {
|
||||
s.SchedulerName = api.DefaultSchedulerName
|
||||
}
|
||||
},
|
||||
func(j *api.PodPhase, c fuzz.Continue) {
|
||||
statuses := []api.PodPhase{api.PodPending, api.PodRunning, api.PodFailed, api.PodUnknown}
|
||||
*j = statuses[c.Rand.Intn(len(statuses))]
|
||||
},
|
||||
func(j *api.Binding, c fuzz.Continue) {
|
||||
c.Fuzz(&j.ObjectMeta)
|
||||
j.Target.Name = c.RandString()
|
||||
},
|
||||
func(j *api.ReplicationControllerSpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||
//j.TemplateRef = nil // this is required for round trip
|
||||
},
|
||||
func(j *api.List, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||
// TODO: uncomment when round trip starts from a versioned object
|
||||
if false { //j.Items == nil {
|
||||
j.Items = []runtime.Object{}
|
||||
}
|
||||
},
|
||||
func(q *api.ResourceRequirements, c fuzz.Continue) {
|
||||
randomQuantity := func() resource.Quantity {
|
||||
var q resource.Quantity
|
||||
c.Fuzz(&q)
|
||||
// precalc the string for benchmarking purposes
|
||||
_ = q.String()
|
||||
return q
|
||||
}
|
||||
q.Limits = make(api.ResourceList)
|
||||
q.Requests = make(api.ResourceList)
|
||||
cpuLimit := randomQuantity()
|
||||
q.Limits[api.ResourceCPU] = *cpuLimit.Copy()
|
||||
q.Requests[api.ResourceCPU] = *cpuLimit.Copy()
|
||||
memoryLimit := randomQuantity()
|
||||
q.Limits[api.ResourceMemory] = *memoryLimit.Copy()
|
||||
q.Requests[api.ResourceMemory] = *memoryLimit.Copy()
|
||||
storageLimit := randomQuantity()
|
||||
q.Limits[api.ResourceStorage] = *storageLimit.Copy()
|
||||
q.Requests[api.ResourceStorage] = *storageLimit.Copy()
|
||||
},
|
||||
func(q *api.LimitRangeItem, c fuzz.Continue) {
|
||||
var cpuLimit resource.Quantity
|
||||
c.Fuzz(&cpuLimit)
|
||||
|
||||
q.Type = api.LimitTypeContainer
|
||||
q.Default = make(api.ResourceList)
|
||||
q.Default[api.ResourceCPU] = *(cpuLimit.Copy())
|
||||
|
||||
q.DefaultRequest = make(api.ResourceList)
|
||||
q.DefaultRequest[api.ResourceCPU] = *(cpuLimit.Copy())
|
||||
|
||||
q.Max = make(api.ResourceList)
|
||||
q.Max[api.ResourceCPU] = *(cpuLimit.Copy())
|
||||
|
||||
q.Min = make(api.ResourceList)
|
||||
q.Min[api.ResourceCPU] = *(cpuLimit.Copy())
|
||||
|
||||
q.MaxLimitRequestRatio = make(api.ResourceList)
|
||||
q.MaxLimitRequestRatio[api.ResourceCPU] = resource.MustParse("10")
|
||||
},
|
||||
func(p *api.PullPolicy, c fuzz.Continue) {
|
||||
policies := []api.PullPolicy{api.PullAlways, api.PullNever, api.PullIfNotPresent}
|
||||
*p = policies[c.Rand.Intn(len(policies))]
|
||||
},
|
||||
func(rp *api.RestartPolicy, c fuzz.Continue) {
|
||||
policies := []api.RestartPolicy{api.RestartPolicyAlways, api.RestartPolicyNever, api.RestartPolicyOnFailure}
|
||||
*rp = policies[c.Rand.Intn(len(policies))]
|
||||
},
|
||||
// api.DownwardAPIVolumeFile needs to have a specific func since FieldRef has to be
|
||||
// defaulted to a version otherwise roundtrip will fail
|
||||
func(m *api.DownwardAPIVolumeFile, c fuzz.Continue) {
|
||||
m.Path = c.RandString()
|
||||
versions := []string{"v1"}
|
||||
m.FieldRef = &api.ObjectFieldSelector{}
|
||||
m.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))]
|
||||
m.FieldRef.FieldPath = c.RandString()
|
||||
c.Fuzz(m.Mode)
|
||||
if m.Mode != nil {
|
||||
*m.Mode &= 0777
|
||||
}
|
||||
},
|
||||
func(s *api.SecretVolumeSource, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
||||
|
||||
if c.RandBool() {
|
||||
opt := c.RandBool()
|
||||
s.Optional = &opt
|
||||
}
|
||||
// DefaultMode should always be set, it has a default
|
||||
// value and it is expected to be between 0 and 0777
|
||||
var mode int32
|
||||
c.Fuzz(&mode)
|
||||
mode &= 0777
|
||||
s.DefaultMode = &mode
|
||||
},
|
||||
func(cm *api.ConfigMapVolumeSource, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(cm) // fuzz self without calling this function again
|
||||
|
||||
if c.RandBool() {
|
||||
opt := c.RandBool()
|
||||
cm.Optional = &opt
|
||||
}
|
||||
// DefaultMode should always be set, it has a default
|
||||
// value and it is expected to be between 0 and 0777
|
||||
var mode int32
|
||||
c.Fuzz(&mode)
|
||||
mode &= 0777
|
||||
cm.DefaultMode = &mode
|
||||
},
|
||||
func(d *api.DownwardAPIVolumeSource, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(d) // fuzz self without calling this function again
|
||||
|
||||
// DefaultMode should always be set, it has a default
|
||||
// value and it is expected to be between 0 and 0777
|
||||
var mode int32
|
||||
c.Fuzz(&mode)
|
||||
mode &= 0777
|
||||
d.DefaultMode = &mode
|
||||
},
|
||||
func(s *api.ProjectedVolumeSource, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
||||
|
||||
// DefaultMode should always be set, it has a default
|
||||
// value and it is expected to be between 0 and 0777
|
||||
var mode int32
|
||||
c.Fuzz(&mode)
|
||||
mode &= 0777
|
||||
s.DefaultMode = &mode
|
||||
},
|
||||
func(k *api.KeyToPath, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(k) // fuzz self without calling this function again
|
||||
k.Key = c.RandString()
|
||||
k.Path = c.RandString()
|
||||
|
||||
// Mode is not mandatory, but if it is set, it should be
|
||||
// a value between 0 and 0777
|
||||
if k.Mode != nil {
|
||||
*k.Mode &= 0777
|
||||
}
|
||||
},
|
||||
func(vs *api.VolumeSource, c fuzz.Continue) {
|
||||
// Exactly one of the fields must be set.
|
||||
v := reflect.ValueOf(vs).Elem()
|
||||
i := int(c.RandUint64() % uint64(v.NumField()))
|
||||
t := v.Field(i).Addr()
|
||||
for v.Field(i).IsNil() {
|
||||
c.Fuzz(t.Interface())
|
||||
}
|
||||
},
|
||||
func(i *api.ISCSIVolumeSource, c fuzz.Continue) {
|
||||
i.ISCSIInterface = c.RandString()
|
||||
if i.ISCSIInterface == "" {
|
||||
i.ISCSIInterface = "default"
|
||||
}
|
||||
},
|
||||
func(d *api.DNSPolicy, c fuzz.Continue) {
|
||||
policies := []api.DNSPolicy{api.DNSClusterFirst, api.DNSDefault}
|
||||
*d = policies[c.Rand.Intn(len(policies))]
|
||||
},
|
||||
func(p *api.Protocol, c fuzz.Continue) {
|
||||
protocols := []api.Protocol{api.ProtocolTCP, api.ProtocolUDP}
|
||||
*p = protocols[c.Rand.Intn(len(protocols))]
|
||||
},
|
||||
func(p *api.ServiceAffinity, c fuzz.Continue) {
|
||||
types := []api.ServiceAffinity{api.ServiceAffinityClientIP, api.ServiceAffinityNone}
|
||||
*p = types[c.Rand.Intn(len(types))]
|
||||
},
|
||||
func(p *api.ServiceType, c fuzz.Continue) {
|
||||
types := []api.ServiceType{api.ServiceTypeClusterIP, api.ServiceTypeNodePort, api.ServiceTypeLoadBalancer}
|
||||
*p = types[c.Rand.Intn(len(types))]
|
||||
},
|
||||
func(p *api.ServiceExternalTrafficPolicyType, c fuzz.Continue) {
|
||||
types := []api.ServiceExternalTrafficPolicyType{api.ServiceExternalTrafficPolicyTypeCluster, api.ServiceExternalTrafficPolicyTypeLocal}
|
||||
*p = types[c.Rand.Intn(len(types))]
|
||||
},
|
||||
func(ct *api.Container, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(ct) // fuzz self without calling this function again
|
||||
ct.TerminationMessagePath = "/" + ct.TerminationMessagePath // Must be non-empty
|
||||
ct.TerminationMessagePolicy = "File"
|
||||
},
|
||||
func(p *api.Probe, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(p)
|
||||
// These fields have default values.
|
||||
intFieldsWithDefaults := [...]string{"TimeoutSeconds", "PeriodSeconds", "SuccessThreshold", "FailureThreshold"}
|
||||
v := reflect.ValueOf(p).Elem()
|
||||
for _, field := range intFieldsWithDefaults {
|
||||
f := v.FieldByName(field)
|
||||
if f.Int() == 0 {
|
||||
f.SetInt(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
func(ev *api.EnvVar, c fuzz.Continue) {
|
||||
ev.Name = c.RandString()
|
||||
if c.RandBool() {
|
||||
ev.Value = c.RandString()
|
||||
} else {
|
||||
ev.ValueFrom = &api.EnvVarSource{}
|
||||
ev.ValueFrom.FieldRef = &api.ObjectFieldSelector{}
|
||||
|
||||
versions := []schema.GroupVersion{
|
||||
{Group: "admission.k8s.io", Version: "v1alpha1"},
|
||||
{Group: "apps", Version: "v1beta1"},
|
||||
{Group: "apps", Version: "v1beta2"},
|
||||
{Group: "foo", Version: "v42"},
|
||||
}
|
||||
|
||||
ev.ValueFrom.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))].String()
|
||||
ev.ValueFrom.FieldRef.FieldPath = c.RandString()
|
||||
}
|
||||
},
|
||||
func(ev *api.EnvFromSource, c fuzz.Continue) {
|
||||
if c.RandBool() {
|
||||
ev.Prefix = "p_"
|
||||
}
|
||||
if c.RandBool() {
|
||||
c.Fuzz(&ev.ConfigMapRef)
|
||||
} else {
|
||||
c.Fuzz(&ev.SecretRef)
|
||||
}
|
||||
},
|
||||
func(cm *api.ConfigMapEnvSource, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(cm) // fuzz self without calling this function again
|
||||
if c.RandBool() {
|
||||
opt := c.RandBool()
|
||||
cm.Optional = &opt
|
||||
}
|
||||
},
|
||||
func(s *api.SecretEnvSource, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
||||
},
|
||||
func(sc *api.SecurityContext, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(sc) // fuzz self without calling this function again
|
||||
if c.RandBool() {
|
||||
priv := c.RandBool()
|
||||
sc.Privileged = &priv
|
||||
}
|
||||
|
||||
if c.RandBool() {
|
||||
sc.Capabilities = &api.Capabilities{
|
||||
Add: make([]api.Capability, 0),
|
||||
Drop: make([]api.Capability, 0),
|
||||
}
|
||||
c.Fuzz(&sc.Capabilities.Add)
|
||||
c.Fuzz(&sc.Capabilities.Drop)
|
||||
}
|
||||
},
|
||||
func(s *api.Secret, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
||||
s.Type = api.SecretTypeOpaque
|
||||
},
|
||||
func(r *api.RBDVolumeSource, c fuzz.Continue) {
|
||||
r.RBDPool = c.RandString()
|
||||
if r.RBDPool == "" {
|
||||
r.RBDPool = "rbd"
|
||||
}
|
||||
r.RadosUser = c.RandString()
|
||||
if r.RadosUser == "" {
|
||||
r.RadosUser = "admin"
|
||||
}
|
||||
r.Keyring = c.RandString()
|
||||
if r.Keyring == "" {
|
||||
r.Keyring = "/etc/ceph/keyring"
|
||||
}
|
||||
},
|
||||
func(obj *api.HostPathVolumeSource, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
types := []api.HostPathType{api.HostPathUnset, api.HostPathDirectoryOrCreate, api.HostPathDirectory,
|
||||
api.HostPathFileOrCreate, api.HostPathFile, api.HostPathSocket, api.HostPathCharDev, api.HostPathBlockDev}
|
||||
typeVol := types[c.Rand.Intn(len(types))]
|
||||
if obj.Type == nil {
|
||||
obj.Type = &typeVol
|
||||
}
|
||||
},
|
||||
func(pv *api.PersistentVolume, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(pv) // fuzz self without calling this function again
|
||||
types := []api.PersistentVolumePhase{api.VolumeAvailable, api.VolumePending, api.VolumeBound, api.VolumeReleased, api.VolumeFailed}
|
||||
pv.Status.Phase = types[c.Rand.Intn(len(types))]
|
||||
pv.Status.Message = c.RandString()
|
||||
reclamationPolicies := []api.PersistentVolumeReclaimPolicy{api.PersistentVolumeReclaimRecycle, api.PersistentVolumeReclaimRetain}
|
||||
pv.Spec.PersistentVolumeReclaimPolicy = reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))]
|
||||
},
|
||||
func(pvc *api.PersistentVolumeClaim, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(pvc) // fuzz self without calling this function again
|
||||
types := []api.PersistentVolumeClaimPhase{api.ClaimBound, api.ClaimPending, api.ClaimLost}
|
||||
pvc.Status.Phase = types[c.Rand.Intn(len(types))]
|
||||
},
|
||||
func(obj *api.AzureDiskVolumeSource, c fuzz.Continue) {
|
||||
if obj.CachingMode == nil {
|
||||
obj.CachingMode = new(api.AzureDataDiskCachingMode)
|
||||
*obj.CachingMode = api.AzureDataDiskCachingReadWrite
|
||||
}
|
||||
if obj.Kind == nil {
|
||||
obj.Kind = new(api.AzureDataDiskKind)
|
||||
*obj.Kind = api.AzureSharedBlobDisk
|
||||
}
|
||||
if obj.FSType == nil {
|
||||
obj.FSType = new(string)
|
||||
*obj.FSType = "ext4"
|
||||
}
|
||||
if obj.ReadOnly == nil {
|
||||
obj.ReadOnly = new(bool)
|
||||
*obj.ReadOnly = false
|
||||
}
|
||||
},
|
||||
func(sio *api.ScaleIOVolumeSource, c fuzz.Continue) {
|
||||
sio.ProtectionDomain = c.RandString()
|
||||
if sio.ProtectionDomain == "" {
|
||||
sio.ProtectionDomain = "default"
|
||||
}
|
||||
sio.StoragePool = c.RandString()
|
||||
if sio.StoragePool == "" {
|
||||
sio.StoragePool = "default"
|
||||
}
|
||||
sio.StorageMode = c.RandString()
|
||||
if sio.StorageMode == "" {
|
||||
sio.StorageMode = "ThinProvisioned"
|
||||
}
|
||||
sio.FSType = c.RandString()
|
||||
if sio.FSType == "" {
|
||||
sio.FSType = "xfs"
|
||||
}
|
||||
},
|
||||
func(s *api.NamespaceSpec, c fuzz.Continue) {
|
||||
s.Finalizers = []api.FinalizerName{api.FinalizerKubernetes}
|
||||
},
|
||||
func(s *api.NamespaceStatus, c fuzz.Continue) {
|
||||
s.Phase = api.NamespaceActive
|
||||
},
|
||||
func(http *api.HTTPGetAction, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(http) // fuzz self without calling this function again
|
||||
http.Path = "/" + http.Path // can't be blank
|
||||
http.Scheme = "x" + http.Scheme // can't be blank
|
||||
},
|
||||
func(ss *api.ServiceSpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(ss) // fuzz self without calling this function again
|
||||
if len(ss.Ports) == 0 {
|
||||
// There must be at least 1 port.
|
||||
ss.Ports = append(ss.Ports, api.ServicePort{})
|
||||
c.Fuzz(&ss.Ports[0])
|
||||
}
|
||||
for i := range ss.Ports {
|
||||
switch ss.Ports[i].TargetPort.Type {
|
||||
case intstr.Int:
|
||||
ss.Ports[i].TargetPort.IntVal = 1 + ss.Ports[i].TargetPort.IntVal%65535 // non-zero
|
||||
case intstr.String:
|
||||
ss.Ports[i].TargetPort.StrVal = "x" + ss.Ports[i].TargetPort.StrVal // non-empty
|
||||
}
|
||||
}
|
||||
types := []api.ServiceAffinity{api.ServiceAffinityNone, api.ServiceAffinityClientIP}
|
||||
ss.SessionAffinity = types[c.Rand.Intn(len(types))]
|
||||
switch ss.SessionAffinity {
|
||||
case api.ServiceAffinityClientIP:
|
||||
timeoutSeconds := int32(c.Rand.Intn(int(api.MaxClientIPServiceAffinitySeconds)))
|
||||
ss.SessionAffinityConfig = &api.SessionAffinityConfig{
|
||||
ClientIP: &api.ClientIPConfig{
|
||||
TimeoutSeconds: &timeoutSeconds,
|
||||
},
|
||||
}
|
||||
case api.ServiceAffinityNone:
|
||||
ss.SessionAffinityConfig = nil
|
||||
}
|
||||
},
|
||||
func(n *api.Node, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(n)
|
||||
n.Spec.ExternalID = "external"
|
||||
},
|
||||
func(s *api.NodeStatus, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s)
|
||||
s.Allocatable = s.Capacity
|
||||
},
|
||||
}
|
||||
}
|
||||
30
vendor/k8s.io/kubernetes/pkg/api/helper/qos/BUILD
generated
vendored
30
vendor/k8s.io/kubernetes/pkg/api/helper/qos/BUILD
generated
vendored
|
|
@ -1,30 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["qos.go"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
97
vendor/k8s.io/kubernetes/pkg/api/helper/qos/qos.go
generated
vendored
97
vendor/k8s.io/kubernetes/pkg/api/helper/qos/qos.go
generated
vendored
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// NOTE: DO NOT use those helper functions through client-go, the
|
||||
// package path will be changed in the future.
|
||||
package qos
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
)
|
||||
|
||||
func isSupportedQoSComputeResource(name api.ResourceName) bool {
|
||||
supportedQoSComputeResources := sets.NewString(string(api.ResourceCPU), string(api.ResourceMemory))
|
||||
return supportedQoSComputeResources.Has(string(name)) || helper.IsHugePageResourceName(name)
|
||||
}
|
||||
|
||||
// GetPodQOS returns the QoS class of a pod.
|
||||
// A pod is besteffort if none of its containers have specified any requests or limits.
|
||||
// A pod is guaranteed only when requests and limits are specified for all the containers and they are equal.
|
||||
// A pod is burstable if limits and requests do not match across all containers.
|
||||
func GetPodQOS(pod *api.Pod) api.PodQOSClass {
|
||||
requests := api.ResourceList{}
|
||||
limits := api.ResourceList{}
|
||||
zeroQuantity := resource.MustParse("0")
|
||||
isGuaranteed := true
|
||||
for _, container := range pod.Spec.Containers {
|
||||
// process requests
|
||||
for name, quantity := range container.Resources.Requests {
|
||||
if !isSupportedQoSComputeResource(name) {
|
||||
continue
|
||||
}
|
||||
if quantity.Cmp(zeroQuantity) == 1 {
|
||||
delta := quantity.Copy()
|
||||
if _, exists := requests[name]; !exists {
|
||||
requests[name] = *delta
|
||||
} else {
|
||||
delta.Add(requests[name])
|
||||
requests[name] = *delta
|
||||
}
|
||||
}
|
||||
}
|
||||
// process limits
|
||||
qosLimitsFound := sets.NewString()
|
||||
for name, quantity := range container.Resources.Limits {
|
||||
if !isSupportedQoSComputeResource(name) {
|
||||
continue
|
||||
}
|
||||
if quantity.Cmp(zeroQuantity) == 1 {
|
||||
qosLimitsFound.Insert(string(name))
|
||||
delta := quantity.Copy()
|
||||
if _, exists := limits[name]; !exists {
|
||||
limits[name] = *delta
|
||||
} else {
|
||||
delta.Add(limits[name])
|
||||
limits[name] = *delta
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !qosLimitsFound.HasAll(string(api.ResourceMemory), string(api.ResourceCPU)) {
|
||||
isGuaranteed = false
|
||||
}
|
||||
}
|
||||
if len(requests) == 0 && len(limits) == 0 {
|
||||
return api.PodQOSBestEffort
|
||||
}
|
||||
// Check is requests match limits for all resources.
|
||||
if isGuaranteed {
|
||||
for name, req := range requests {
|
||||
if lim, exists := limits[name]; !exists || lim.Cmp(req) != 0 {
|
||||
isGuaranteed = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if isGuaranteed &&
|
||||
len(requests) == len(limits) {
|
||||
return api.PodQOSGuaranteed
|
||||
}
|
||||
return api.PodQOSBurstable
|
||||
}
|
||||
37
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/BUILD
generated
vendored
37
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/BUILD
generated
vendored
|
|
@ -1,37 +0,0 @@
|
|||
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"],
|
||||
deps = ["//pkg/api: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"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
||||
4
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/OWNERS
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/OWNERS
generated
vendored
|
|
@ -1,4 +0,0 @@
|
|||
reviewers:
|
||||
- smarterclayton
|
||||
- jsafrane
|
||||
- david-mcmahon
|
||||
84
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util.go
generated
vendored
84
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util.go
generated
vendored
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package persistentvolume
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
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) (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) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if len(source.AzureFile.SecretName) > 0 && !visitor(getClaimRefNamespace(pv), source.AzureFile.SecretName) {
|
||||
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) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case source.FlexVolume != nil:
|
||||
if source.FlexVolume.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.FlexVolume.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
case source.RBD != nil:
|
||||
if source.RBD.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.RBD.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
case source.ScaleIO != nil:
|
||||
if source.ScaleIO.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.ScaleIO.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
case source.ISCSI != nil:
|
||||
if source.ISCSI.SecretRef != nil && !visitor(getClaimRefNamespace(pv), source.ISCSI.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
case source.StorageOS != nil:
|
||||
if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Namespace, source.StorageOS.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
190
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util_test.go
generated
vendored
190
vendor/k8s.io/kubernetes/pkg/api/persistentvolume/util_test.go
generated
vendored
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package persistentvolume
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
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{
|
||||
SecretName: "Spec.PersistentVolumeSource.AzureFile.SecretName"}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
AzureFile: &api.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{
|
||||
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{
|
||||
Name: "Spec.PersistentVolumeSource.CephFS.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
FlexVolume: &api.FlexVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.PersistentVolumeSource.FlexVolume.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
RBD: &api.RBDVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.PersistentVolumeSource.RBD.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
ScaleIO: &api.ScaleIOVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.PersistentVolumeSource.ScaleIO.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.PersistentVolumeSource.ISCSI.SecretRef"}}}}},
|
||||
{Spec: api.PersistentVolumeSpec{
|
||||
ClaimRef: &api.ObjectReference{Namespace: "claimrefns", Name: "claimrefname"},
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
StorageOS: &api.StorageOSPersistentVolumeSource{
|
||||
SecretRef: &api.ObjectReference{
|
||||
Name: "Spec.PersistentVolumeSource.StorageOS.SecretRef",
|
||||
Namespace: "storageosns"}}}}},
|
||||
}
|
||||
extractedNames := sets.NewString()
|
||||
extractedNamesWithNamespace := sets.NewString()
|
||||
for _, pv := range pvs {
|
||||
VisitPVSecretNames(pv, func(namespace, name string) bool {
|
||||
extractedNames.Insert(name)
|
||||
extractedNamesWithNamespace.Insert(namespace + "/" + name)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects
|
||||
excludedSecretPaths := sets.NewString(
|
||||
"Spec.PersistentVolumeSource.CephFS.SecretFile",
|
||||
"Spec.PersistentVolumeSource.AzureFile.SecretNamespace",
|
||||
)
|
||||
// expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects.
|
||||
// every path here should be represented as an example in the PV stub above, with the secret name set to the path.
|
||||
expectedSecretPaths := sets.NewString(
|
||||
"Spec.PersistentVolumeSource.AzureFile.SecretName",
|
||||
"Spec.PersistentVolumeSource.CephFS.SecretRef",
|
||||
"Spec.PersistentVolumeSource.FlexVolume.SecretRef",
|
||||
"Spec.PersistentVolumeSource.RBD.SecretRef",
|
||||
"Spec.PersistentVolumeSource.ScaleIO.SecretRef",
|
||||
"Spec.PersistentVolumeSource.ISCSI.SecretRef",
|
||||
"Spec.PersistentVolumeSource.StorageOS.SecretRef",
|
||||
)
|
||||
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.PersistentVolume{}))
|
||||
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"))
|
||||
t.Error("Missing expected secret paths. Verify VisitPVSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths")
|
||||
}
|
||||
if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 {
|
||||
t.Logf("Extra secret paths:\n%s", strings.Join(extraPaths.List(), "\n"))
|
||||
t.Error("Extra fields with 'secret' in the name found. Verify VisitPVSecretNames() is including these fields if appropriate, then correct expectedSecretPaths")
|
||||
}
|
||||
|
||||
if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 {
|
||||
t.Logf("Missing expected secret names:\n%s", strings.Join(missingNames.List(), "\n"))
|
||||
t.Error("Missing expected secret names. Verify the PV stub above includes these references, then verify VisitPVSecretNames() is correctly finding the missing names")
|
||||
}
|
||||
if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 {
|
||||
t.Logf("Extra secret names:\n%s", strings.Join(extraNames.List(), "\n"))
|
||||
t.Error("Extra secret names extracted. Verify VisitPVSecretNames() is correctly extracting secret names")
|
||||
}
|
||||
|
||||
expectedNamespacedNames := sets.NewString(
|
||||
"claimrefns/Spec.PersistentVolumeSource.AzureFile.SecretName",
|
||||
"Spec.PersistentVolumeSource.AzureFile.SecretNamespace/Spec.PersistentVolumeSource.AzureFile.SecretName",
|
||||
"claimrefns/Spec.PersistentVolumeSource.CephFS.SecretRef",
|
||||
"cephfs/Spec.PersistentVolumeSource.CephFS.SecretRef",
|
||||
"claimrefns/Spec.PersistentVolumeSource.FlexVolume.SecretRef",
|
||||
"claimrefns/Spec.PersistentVolumeSource.RBD.SecretRef",
|
||||
"claimrefns/Spec.PersistentVolumeSource.ScaleIO.SecretRef",
|
||||
"claimrefns/Spec.PersistentVolumeSource.ISCSI.SecretRef",
|
||||
"storageosns/Spec.PersistentVolumeSource.StorageOS.SecretRef",
|
||||
)
|
||||
if missingNames := expectedNamespacedNames.Difference(extractedNamesWithNamespace); len(missingNames) > 0 {
|
||||
t.Logf("Missing expected namespaced names:\n%s", strings.Join(missingNames.List(), "\n"))
|
||||
t.Error("Missing expected namespaced names. Verify the PV stub above includes these references, then verify VisitPVSecretNames() is correctly finding the missing names")
|
||||
}
|
||||
if extraNames := extractedNamesWithNamespace.Difference(expectedNamespacedNames); len(extraNames) > 0 {
|
||||
t.Logf("Extra namespaced names:\n%s", strings.Join(extraNames.List(), "\n"))
|
||||
t.Error("Extra namespaced names extracted. Verify VisitPVSecretNames() is correctly extracting secret names")
|
||||
}
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
||||
if tp.Kind() == reflect.Ptr {
|
||||
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...)
|
||||
return secretPaths
|
||||
}
|
||||
|
||||
if strings.Contains(strings.ToLower(name), "secret") {
|
||||
secretPaths.Insert(path.String())
|
||||
}
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Ptr:
|
||||
secretPaths.Insert(collectSecretPaths(t, 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()...)
|
||||
}
|
||||
case reflect.Interface:
|
||||
t.Errorf("cannot find secret fields in interface{} field %s", path.String())
|
||||
case reflect.Map:
|
||||
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
|
||||
case reflect.Slice:
|
||||
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
|
||||
default:
|
||||
// all primitive types
|
||||
}
|
||||
|
||||
return secretPaths
|
||||
}
|
||||
42
vendor/k8s.io/kubernetes/pkg/api/pod/BUILD
generated
vendored
42
vendor/k8s.io/kubernetes/pkg/api/pod/BUILD
generated
vendored
|
|
@ -1,42 +0,0 @@
|
|||
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"],
|
||||
deps = [
|
||||
"//pkg/api: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",
|
||||
],
|
||||
)
|
||||
|
||||
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"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
||||
4
vendor/k8s.io/kubernetes/pkg/api/pod/OWNERS
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/api/pod/OWNERS
generated
vendored
|
|
@ -1,4 +0,0 @@
|
|||
reviewers:
|
||||
- smarterclayton
|
||||
- thockin
|
||||
- david-mcmahon
|
||||
262
vendor/k8s.io/kubernetes/pkg/api/pod/util.go
generated
vendored
262
vendor/k8s.io/kubernetes/pkg/api/pod/util.go
generated
vendored
|
|
@ -1,262 +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 pod
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
// Visitor is called with each object name, and returns true if visiting should continue
|
||||
type Visitor func(name string) (shouldContinue bool)
|
||||
|
||||
// VisitPodSecretNames invokes the visitor function with the name of every secret
|
||||
// referenced by the pod spec. If visitor returns false, visiting is short-circuited.
|
||||
// Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
|
||||
// Returns true if visiting completed, false if visiting was short-circuited.
|
||||
func VisitPodSecretNames(pod *api.Pod, visitor Visitor) bool {
|
||||
for _, reference := range pod.Spec.ImagePullSecrets {
|
||||
if !visitor(reference.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i := range pod.Spec.InitContainers {
|
||||
if !visitContainerSecretNames(&pod.Spec.InitContainers[i], visitor) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i := range pod.Spec.Containers {
|
||||
if !visitContainerSecretNames(&pod.Spec.Containers[i], visitor) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
var source *api.VolumeSource
|
||||
for i := range pod.Spec.Volumes {
|
||||
source = &pod.Spec.Volumes[i].VolumeSource
|
||||
switch {
|
||||
case source.AzureFile != nil:
|
||||
if len(source.AzureFile.SecretName) > 0 && !visitor(source.AzureFile.SecretName) {
|
||||
return false
|
||||
}
|
||||
case source.CephFS != nil:
|
||||
if source.CephFS.SecretRef != nil && !visitor(source.CephFS.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
case source.FlexVolume != nil:
|
||||
if source.FlexVolume.SecretRef != nil && !visitor(source.FlexVolume.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
case source.Projected != nil:
|
||||
for j := range source.Projected.Sources {
|
||||
if source.Projected.Sources[j].Secret != nil {
|
||||
if !visitor(source.Projected.Sources[j].Secret.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
case source.RBD != nil:
|
||||
if source.RBD.SecretRef != nil && !visitor(source.RBD.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
case source.Secret != nil:
|
||||
if !visitor(source.Secret.SecretName) {
|
||||
return false
|
||||
}
|
||||
case source.ScaleIO != nil:
|
||||
if source.ScaleIO.SecretRef != nil && !visitor(source.ScaleIO.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
case source.ISCSI != nil:
|
||||
if source.ISCSI.SecretRef != nil && !visitor(source.ISCSI.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
case source.StorageOS != nil:
|
||||
if source.StorageOS.SecretRef != nil && !visitor(source.StorageOS.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func visitContainerSecretNames(container *api.Container, visitor Visitor) bool {
|
||||
for _, env := range container.EnvFrom {
|
||||
if env.SecretRef != nil {
|
||||
if !visitor(env.SecretRef.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, envVar := range container.Env {
|
||||
if envVar.ValueFrom != nil && envVar.ValueFrom.SecretKeyRef != nil {
|
||||
if !visitor(envVar.ValueFrom.SecretKeyRef.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// VisitPodConfigmapNames invokes the visitor function with the name of every configmap
|
||||
// referenced by the pod spec. If visitor returns false, visiting is short-circuited.
|
||||
// Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
|
||||
// Returns true if visiting completed, false if visiting was short-circuited.
|
||||
func VisitPodConfigmapNames(pod *api.Pod, visitor Visitor) bool {
|
||||
for i := range pod.Spec.InitContainers {
|
||||
if !visitContainerConfigmapNames(&pod.Spec.InitContainers[i], visitor) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i := range pod.Spec.Containers {
|
||||
if !visitContainerConfigmapNames(&pod.Spec.Containers[i], visitor) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
var source *api.VolumeSource
|
||||
for i := range pod.Spec.Volumes {
|
||||
source = &pod.Spec.Volumes[i].VolumeSource
|
||||
switch {
|
||||
case source.Projected != nil:
|
||||
for j := range source.Projected.Sources {
|
||||
if source.Projected.Sources[j].ConfigMap != nil {
|
||||
if !visitor(source.Projected.Sources[j].ConfigMap.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
case source.ConfigMap != nil:
|
||||
if !visitor(source.ConfigMap.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func visitContainerConfigmapNames(container *api.Container, visitor Visitor) bool {
|
||||
for _, env := range container.EnvFrom {
|
||||
if env.ConfigMapRef != nil {
|
||||
if !visitor(env.ConfigMapRef.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, envVar := range container.Env {
|
||||
if envVar.ValueFrom != nil && envVar.ValueFrom.ConfigMapKeyRef != nil {
|
||||
if !visitor(envVar.ValueFrom.ConfigMapKeyRef.Name) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsPodReady returns true if a pod is ready; false otherwise.
|
||||
func IsPodReady(pod *api.Pod) bool {
|
||||
return IsPodReadyConditionTrue(pod.Status)
|
||||
}
|
||||
|
||||
// IsPodReadyConditionTrue retruns true if a pod is ready; false otherwise.
|
||||
func IsPodReadyConditionTrue(status api.PodStatus) bool {
|
||||
condition := GetPodReadyCondition(status)
|
||||
return condition != nil && condition.Status == api.ConditionTrue
|
||||
}
|
||||
|
||||
// GetPodReadyCondition extracts the pod ready condition from the given status and returns that.
|
||||
// Returns nil if the condition is not present.
|
||||
func GetPodReadyCondition(status api.PodStatus) *api.PodCondition {
|
||||
_, condition := GetPodCondition(&status, api.PodReady)
|
||||
return condition
|
||||
}
|
||||
|
||||
// GetPodCondition extracts the provided condition from the given status and returns that.
|
||||
// Returns nil and -1 if the condition is not present, and the index of the located condition.
|
||||
func GetPodCondition(status *api.PodStatus, conditionType api.PodConditionType) (int, *api.PodCondition) {
|
||||
if status == nil {
|
||||
return -1, nil
|
||||
}
|
||||
for i := range status.Conditions {
|
||||
if status.Conditions[i].Type == conditionType {
|
||||
return i, &status.Conditions[i]
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// UpdatePodCondition updates existing pod condition or creates a new one. Sets LastTransitionTime to now if the
|
||||
// status has changed.
|
||||
// Returns true if pod condition has changed or has been added.
|
||||
func UpdatePodCondition(status *api.PodStatus, condition *api.PodCondition) bool {
|
||||
condition.LastTransitionTime = metav1.Now()
|
||||
// Try to find this pod condition.
|
||||
conditionIndex, oldCondition := GetPodCondition(status, condition.Type)
|
||||
|
||||
if oldCondition == nil {
|
||||
// We are adding new pod condition.
|
||||
status.Conditions = append(status.Conditions, *condition)
|
||||
return true
|
||||
}
|
||||
// We are updating an existing condition, so we need to check if it has changed.
|
||||
if condition.Status == oldCondition.Status {
|
||||
condition.LastTransitionTime = oldCondition.LastTransitionTime
|
||||
}
|
||||
|
||||
isEqual := condition.Status == oldCondition.Status &&
|
||||
condition.Reason == oldCondition.Reason &&
|
||||
condition.Message == oldCondition.Message &&
|
||||
condition.LastProbeTime.Equal(&oldCondition.LastProbeTime) &&
|
||||
condition.LastTransitionTime.Equal(&oldCondition.LastTransitionTime)
|
||||
|
||||
status.Conditions[conditionIndex] = *condition
|
||||
// Return true if one of the fields have changed.
|
||||
return !isEqual
|
||||
}
|
||||
|
||||
// DropDisabledAlphaFields removes disabled fields from the pod spec.
|
||||
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pod spec.
|
||||
func DropDisabledAlphaFields(podSpec *api.PodSpec) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) {
|
||||
podSpec.Priority = nil
|
||||
podSpec.PriorityClassName = ""
|
||||
}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) {
|
||||
for i := range podSpec.Volumes {
|
||||
if podSpec.Volumes[i].EmptyDir != nil {
|
||||
podSpec.Volumes[i].EmptyDir.SizeLimit = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := range podSpec.Containers {
|
||||
DropDisabledVolumeMountsAlphaFields(podSpec.Containers[i].VolumeMounts)
|
||||
}
|
||||
for i := range podSpec.InitContainers {
|
||||
DropDisabledVolumeMountsAlphaFields(podSpec.InitContainers[i].VolumeMounts)
|
||||
}
|
||||
}
|
||||
|
||||
// DropDisabledVolumeMountsAlphaFields removes disabled fields from []VolumeMount.
|
||||
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeMount
|
||||
func DropDisabledVolumeMountsAlphaFields(volumeMounts []api.VolumeMount) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.MountPropagation) {
|
||||
for i := range volumeMounts {
|
||||
volumeMounts[i].MountPropagation = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
181
vendor/k8s.io/kubernetes/pkg/api/pod/util_test.go
generated
vendored
181
vendor/k8s.io/kubernetes/pkg/api/pod/util_test.go
generated
vendored
|
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pod
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func TestPodSecrets(t *testing.T) {
|
||||
// Stub containing all possible secret references in a pod.
|
||||
// The names of the referenced secrets match struct paths detected by reflection.
|
||||
pod := &api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{{
|
||||
EnvFrom: []api.EnvFromSource{{
|
||||
SecretRef: &api.SecretEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{
|
||||
Name: "Spec.Containers[*].EnvFrom[*].SecretRef"}}}},
|
||||
Env: []api.EnvVar{{
|
||||
ValueFrom: &api.EnvVarSource{
|
||||
SecretKeyRef: &api.SecretKeySelector{
|
||||
LocalObjectReference: api.LocalObjectReference{
|
||||
Name: "Spec.Containers[*].Env[*].ValueFrom.SecretKeyRef"}}}}}}},
|
||||
ImagePullSecrets: []api.LocalObjectReference{{
|
||||
Name: "Spec.ImagePullSecrets"}},
|
||||
InitContainers: []api.Container{{
|
||||
EnvFrom: []api.EnvFromSource{{
|
||||
SecretRef: &api.SecretEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{
|
||||
Name: "Spec.InitContainers[*].EnvFrom[*].SecretRef"}}}},
|
||||
Env: []api.EnvVar{{
|
||||
ValueFrom: &api.EnvVarSource{
|
||||
SecretKeyRef: &api.SecretKeySelector{
|
||||
LocalObjectReference: api.LocalObjectReference{
|
||||
Name: "Spec.InitContainers[*].Env[*].ValueFrom.SecretKeyRef"}}}}}}},
|
||||
Volumes: []api.Volume{{
|
||||
VolumeSource: api.VolumeSource{
|
||||
AzureFile: &api.AzureFileVolumeSource{
|
||||
SecretName: "Spec.Volumes[*].VolumeSource.AzureFile.SecretName"}}}, {
|
||||
VolumeSource: api.VolumeSource{
|
||||
CephFS: &api.CephFSVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.CephFS.SecretRef"}}}}, {
|
||||
VolumeSource: api.VolumeSource{
|
||||
FlexVolume: &api.FlexVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.FlexVolume.SecretRef"}}}}, {
|
||||
VolumeSource: api.VolumeSource{
|
||||
Projected: &api.ProjectedVolumeSource{
|
||||
Sources: []api.VolumeProjection{{
|
||||
Secret: &api.SecretProjection{
|
||||
LocalObjectReference: api.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.Projected.Sources[*].Secret"}}}}}}}, {
|
||||
VolumeSource: api.VolumeSource{
|
||||
RBD: &api.RBDVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.RBD.SecretRef"}}}}, {
|
||||
VolumeSource: api.VolumeSource{
|
||||
Secret: &api.SecretVolumeSource{
|
||||
SecretName: "Spec.Volumes[*].VolumeSource.Secret.SecretName"}}}, {
|
||||
VolumeSource: api.VolumeSource{
|
||||
Secret: &api.SecretVolumeSource{
|
||||
SecretName: "Spec.Volumes[*].VolumeSource.Secret"}}}, {
|
||||
VolumeSource: api.VolumeSource{
|
||||
ScaleIO: &api.ScaleIOVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.ScaleIO.SecretRef"}}}}, {
|
||||
VolumeSource: api.VolumeSource{
|
||||
ISCSI: &api.ISCSIVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.ISCSI.SecretRef"}}}}, {
|
||||
VolumeSource: api.VolumeSource{
|
||||
StorageOS: &api.StorageOSVolumeSource{
|
||||
SecretRef: &api.LocalObjectReference{
|
||||
Name: "Spec.Volumes[*].VolumeSource.StorageOS.SecretRef"}}}}},
|
||||
},
|
||||
}
|
||||
extractedNames := sets.NewString()
|
||||
VisitPodSecretNames(pod, func(name string) bool {
|
||||
extractedNames.Insert(name)
|
||||
return true
|
||||
})
|
||||
|
||||
// excludedSecretPaths holds struct paths to fields with "secret" in the name that are not actually references to secret API objects
|
||||
excludedSecretPaths := sets.NewString(
|
||||
"Spec.Volumes[*].VolumeSource.CephFS.SecretFile",
|
||||
)
|
||||
// expectedSecretPaths holds struct paths to fields with "secret" in the name that are references to secret API objects.
|
||||
// every path here should be represented as an example in the Pod stub above, with the secret name set to the path.
|
||||
expectedSecretPaths := sets.NewString(
|
||||
"Spec.Containers[*].EnvFrom[*].SecretRef",
|
||||
"Spec.Containers[*].Env[*].ValueFrom.SecretKeyRef",
|
||||
"Spec.ImagePullSecrets",
|
||||
"Spec.InitContainers[*].EnvFrom[*].SecretRef",
|
||||
"Spec.InitContainers[*].Env[*].ValueFrom.SecretKeyRef",
|
||||
"Spec.Volumes[*].VolumeSource.AzureFile.SecretName",
|
||||
"Spec.Volumes[*].VolumeSource.CephFS.SecretRef",
|
||||
"Spec.Volumes[*].VolumeSource.FlexVolume.SecretRef",
|
||||
"Spec.Volumes[*].VolumeSource.Projected.Sources[*].Secret",
|
||||
"Spec.Volumes[*].VolumeSource.RBD.SecretRef",
|
||||
"Spec.Volumes[*].VolumeSource.Secret",
|
||||
"Spec.Volumes[*].VolumeSource.Secret.SecretName",
|
||||
"Spec.Volumes[*].VolumeSource.ScaleIO.SecretRef",
|
||||
"Spec.Volumes[*].VolumeSource.ISCSI.SecretRef",
|
||||
"Spec.Volumes[*].VolumeSource.StorageOS.SecretRef",
|
||||
)
|
||||
secretPaths := collectSecretPaths(t, nil, "", reflect.TypeOf(&api.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"))
|
||||
t.Error("Missing expected secret paths. Verify VisitPodSecretNames() is correctly finding the missing paths, then correct expectedSecretPaths")
|
||||
}
|
||||
if extraPaths := secretPaths.Difference(expectedSecretPaths); len(extraPaths) > 0 {
|
||||
t.Logf("Extra secret paths:\n%s", strings.Join(extraPaths.List(), "\n"))
|
||||
t.Error("Extra fields with 'secret' in the name found. Verify VisitPodSecretNames() is including these fields if appropriate, then correct expectedSecretPaths")
|
||||
}
|
||||
|
||||
if missingNames := expectedSecretPaths.Difference(extractedNames); len(missingNames) > 0 {
|
||||
t.Logf("Missing expected secret names:\n%s", strings.Join(missingNames.List(), "\n"))
|
||||
t.Error("Missing expected secret names. Verify the pod stub above includes these references, then verify VisitPodSecretNames() is correctly finding the missing names")
|
||||
}
|
||||
if extraNames := extractedNames.Difference(expectedSecretPaths); len(extraNames) > 0 {
|
||||
t.Logf("Extra secret names:\n%s", strings.Join(extraNames.List(), "\n"))
|
||||
t.Error("Extra secret names extracted. Verify VisitPodSecretNames() is correctly extracting secret names")
|
||||
}
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
||||
if tp.Kind() == reflect.Ptr {
|
||||
secretPaths.Insert(collectSecretPaths(t, path, name, tp.Elem()).List()...)
|
||||
return secretPaths
|
||||
}
|
||||
|
||||
if strings.Contains(strings.ToLower(name), "secret") {
|
||||
secretPaths.Insert(path.String())
|
||||
}
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Ptr:
|
||||
secretPaths.Insert(collectSecretPaths(t, 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()...)
|
||||
}
|
||||
case reflect.Interface:
|
||||
t.Errorf("cannot find secret fields in interface{} field %s", path.String())
|
||||
case reflect.Map:
|
||||
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
|
||||
case reflect.Slice:
|
||||
secretPaths.Insert(collectSecretPaths(t, path.Key("*"), "", tp.Elem()).List()...)
|
||||
default:
|
||||
// all primitive types
|
||||
}
|
||||
|
||||
return secretPaths
|
||||
}
|
||||
43
vendor/k8s.io/kubernetes/pkg/api/ref/BUILD
generated
vendored
43
vendor/k8s.io/kubernetes/pkg/api/ref/BUILD
generated
vendored
|
|
@ -1,43 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["ref_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api: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",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["ref.go"],
|
||||
deps = [
|
||||
"//pkg/api: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",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
122
vendor/k8s.io/kubernetes/pkg/api/ref/ref.go
generated
vendored
122
vendor/k8s.io/kubernetes/pkg/api/ref/ref.go
generated
vendored
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ref
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
var (
|
||||
// Errors that could be returned by GetReference.
|
||||
ErrNilObject = errors.New("can't reference a nil object")
|
||||
ErrNoSelfLink = errors.New("selfLink was empty, can't make reference")
|
||||
)
|
||||
|
||||
// GetReference returns an ObjectReference which refers to the given
|
||||
// object, or an error if the object doesn't follow the conventions
|
||||
// that would allow this.
|
||||
// TODO: should take a meta.Interface see http://issue.k8s.io/7127
|
||||
func GetReference(scheme *runtime.Scheme, obj runtime.Object) (*api.ObjectReference, error) {
|
||||
if obj == nil {
|
||||
return nil, ErrNilObject
|
||||
}
|
||||
if ref, ok := obj.(*api.ObjectReference); ok {
|
||||
// Don't make a reference to a reference.
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
gvk := obj.GetObjectKind().GroupVersionKind()
|
||||
|
||||
// if the object referenced is actually persisted, we can just get kind from meta
|
||||
// if we are building an object reference to something not yet persisted, we should fallback to scheme
|
||||
kind := gvk.Kind
|
||||
if len(kind) == 0 {
|
||||
// TODO: this is wrong
|
||||
gvks, _, err := scheme.ObjectKinds(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kind = gvks[0].Kind
|
||||
}
|
||||
|
||||
// An object that implements only List has enough metadata to build a reference
|
||||
var listMeta metav1.Common
|
||||
objectMeta, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
listMeta, err = meta.CommonAccessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
listMeta = objectMeta
|
||||
}
|
||||
|
||||
// if the object referenced is actually persisted, we can also get version from meta
|
||||
version := gvk.GroupVersion().String()
|
||||
if len(version) == 0 {
|
||||
selfLink := listMeta.GetSelfLink()
|
||||
if len(selfLink) == 0 {
|
||||
return nil, ErrNoSelfLink
|
||||
}
|
||||
selfLinkUrl, err := url.Parse(selfLink)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// example paths: /<prefix>/<version>/*
|
||||
parts := strings.Split(selfLinkUrl.Path, "/")
|
||||
if len(parts) < 3 {
|
||||
return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version)
|
||||
}
|
||||
version = parts[2]
|
||||
}
|
||||
|
||||
// only has list metadata
|
||||
if objectMeta == nil {
|
||||
return &api.ObjectReference{
|
||||
Kind: kind,
|
||||
APIVersion: version,
|
||||
ResourceVersion: listMeta.GetResourceVersion(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &api.ObjectReference{
|
||||
Kind: kind,
|
||||
APIVersion: version,
|
||||
Name: objectMeta.GetName(),
|
||||
Namespace: objectMeta.GetNamespace(),
|
||||
UID: objectMeta.GetUID(),
|
||||
ResourceVersion: objectMeta.GetResourceVersion(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetPartialReference is exactly like GetReference, but allows you to set the FieldPath.
|
||||
func GetPartialReference(scheme *runtime.Scheme, obj runtime.Object, fieldPath string) (*api.ObjectReference, error) {
|
||||
ref, err := GetReference(scheme, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ref.FieldPath = fieldPath
|
||||
return ref, nil
|
||||
}
|
||||
147
vendor/k8s.io/kubernetes/pkg/api/ref/ref_test.go
generated
vendored
147
vendor/k8s.io/kubernetes/pkg/api/ref/ref_test.go
generated
vendored
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ref
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
type FakeAPIObject struct{}
|
||||
|
||||
func (obj *FakeAPIObject) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
|
||||
func (obj *FakeAPIObject) DeepCopyObject() runtime.Object {
|
||||
if obj == nil {
|
||||
return nil
|
||||
}
|
||||
clone := *obj
|
||||
return &clone
|
||||
}
|
||||
|
||||
type ExtensionAPIObject struct {
|
||||
metav1.TypeMeta
|
||||
metav1.ObjectMeta
|
||||
}
|
||||
|
||||
func (obj *ExtensionAPIObject) DeepCopyObject() runtime.Object {
|
||||
panic("ExtensionAPIObject does not support DeepCopy")
|
||||
}
|
||||
|
||||
func TestGetReference(t *testing.T) {
|
||||
|
||||
// when vendoring kube, if you don't force the set of registered versions (like make test does)
|
||||
// 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 := api.Scheme.ObjectKinds(&api.Pod{}); err != nil {
|
||||
api.AddToScheme(api.Scheme)
|
||||
}
|
||||
|
||||
table := map[string]struct {
|
||||
obj runtime.Object
|
||||
ref *api.ObjectReference
|
||||
fieldPath string
|
||||
shouldErr bool
|
||||
}{
|
||||
"pod": {
|
||||
obj: &api.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
SelfLink: "/api/version1/pods/foo",
|
||||
},
|
||||
},
|
||||
fieldPath: ".desiredState.containers[0]",
|
||||
ref: &api.ObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: "version1",
|
||||
Name: "foo",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
FieldPath: ".desiredState.containers[0]",
|
||||
},
|
||||
},
|
||||
"serviceList": {
|
||||
obj: &api.ServiceList{
|
||||
ListMeta: metav1.ListMeta{
|
||||
ResourceVersion: "42",
|
||||
SelfLink: "/api/version2/services",
|
||||
},
|
||||
},
|
||||
ref: &api.ObjectReference{
|
||||
Kind: "ServiceList",
|
||||
APIVersion: "version2",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
},
|
||||
"extensionAPIObject": {
|
||||
obj: &ExtensionAPIObject{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "ExtensionAPIObject",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
SelfLink: "/custom_prefix/version1/extensions/foo",
|
||||
},
|
||||
},
|
||||
ref: &api.ObjectReference{
|
||||
Kind: "ExtensionAPIObject",
|
||||
APIVersion: "version1",
|
||||
Name: "foo",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
},
|
||||
"badSelfLink": {
|
||||
obj: &api.ServiceList{
|
||||
ListMeta: metav1.ListMeta{
|
||||
ResourceVersion: "42",
|
||||
SelfLink: "version2/services",
|
||||
},
|
||||
},
|
||||
shouldErr: true,
|
||||
},
|
||||
"error": {
|
||||
obj: &FakeAPIObject{},
|
||||
ref: nil,
|
||||
shouldErr: true,
|
||||
},
|
||||
"errorNil": {
|
||||
obj: nil,
|
||||
ref: nil,
|
||||
shouldErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, item := range table {
|
||||
ref, err := GetPartialReference(api.Scheme, item.obj, item.fieldPath)
|
||||
if e, a := item.shouldErr, (err != nil); e != a {
|
||||
t.Errorf("%v: expected %v, got %v, err %v", name, e, a, err)
|
||||
continue
|
||||
}
|
||||
if e, a := item.ref, ref; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%v: expected %#v, got %#v", name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
40
vendor/k8s.io/kubernetes/pkg/api/resource/BUILD
generated
vendored
40
vendor/k8s.io/kubernetes/pkg/api/resource/BUILD
generated
vendored
|
|
@ -1,40 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["helpers.go"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource: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 = ["helpers_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
123
vendor/k8s.io/kubernetes/pkg/api/resource/helpers.go
generated
vendored
123
vendor/k8s.io/kubernetes/pkg/api/resource/helpers.go
generated
vendored
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resource
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// 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, err error) {
|
||||
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
|
||||
}
|
||||
}
|
||||
for name, quantity := range container.Resources.Limits {
|
||||
if value, ok := limits[name]; !ok {
|
||||
limits[name] = *quantity.Copy()
|
||||
} else {
|
||||
value.Add(quantity)
|
||||
limits[name] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ExtractContainerResourceValue extracts the value of a resource
|
||||
// in an already known container
|
||||
func ExtractContainerResourceValue(fs *api.ResourceFieldSelector, container *api.Container) (string, error) {
|
||||
divisor := resource.Quantity{}
|
||||
if divisor.Cmp(fs.Divisor) == 0 {
|
||||
divisor = resource.MustParse("1")
|
||||
} else {
|
||||
divisor = fs.Divisor
|
||||
}
|
||||
|
||||
switch fs.Resource {
|
||||
case "limits.cpu":
|
||||
return convertResourceCPUToString(container.Resources.Limits.Cpu(), divisor)
|
||||
case "limits.memory":
|
||||
return convertResourceMemoryToString(container.Resources.Limits.Memory(), divisor)
|
||||
case "limits.ephemeral-storage":
|
||||
return convertResourceEphemeralStorageToString(container.Resources.Limits.StorageEphemeral(), divisor)
|
||||
case "requests.cpu":
|
||||
return convertResourceCPUToString(container.Resources.Requests.Cpu(), divisor)
|
||||
case "requests.memory":
|
||||
return convertResourceMemoryToString(container.Resources.Requests.Memory(), divisor)
|
||||
case "requests.ephemeral-storage":
|
||||
return convertResourceEphemeralStorageToString(container.Resources.Requests.StorageEphemeral(), divisor)
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("unsupported container resource : %v", fs.Resource)
|
||||
}
|
||||
|
||||
// convertResourceCPUToString converts cpu value to the format of divisor and returns
|
||||
// ceiling of the value.
|
||||
func convertResourceCPUToString(cpu *resource.Quantity, divisor resource.Quantity) (string, error) {
|
||||
c := int64(math.Ceil(float64(cpu.MilliValue()) / float64(divisor.MilliValue())))
|
||||
return strconv.FormatInt(c, 10), nil
|
||||
}
|
||||
|
||||
// convertResourceMemoryToString converts memory value to the format of divisor and returns
|
||||
// ceiling of the value.
|
||||
func convertResourceMemoryToString(memory *resource.Quantity, divisor resource.Quantity) (string, error) {
|
||||
m := int64(math.Ceil(float64(memory.Value()) / float64(divisor.Value())))
|
||||
return strconv.FormatInt(m, 10), nil
|
||||
}
|
||||
|
||||
// convertResourceEphemeralStorageToString converts ephemeral storage value to the format of divisor and returns
|
||||
// ceiling of the value.
|
||||
func convertResourceEphemeralStorageToString(ephemeralStorage *resource.Quantity, divisor resource.Quantity) (string, error) {
|
||||
m := int64(math.Ceil(float64(ephemeralStorage.Value()) / float64(divisor.Value())))
|
||||
return strconv.FormatInt(m, 10), nil
|
||||
}
|
||||
82
vendor/k8s.io/kubernetes/pkg/api/resource/helpers_test.go
generated
vendored
82
vendor/k8s.io/kubernetes/pkg/api/resource/helpers_test.go
generated
vendored
|
|
@ -1,82 +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 resource
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func TestResourceHelpers(t *testing.T) {
|
||||
cpuLimit := resource.MustParse("10")
|
||||
memoryLimit := resource.MustParse("10G")
|
||||
resourceSpec := api.ResourceRequirements{
|
||||
Limits: api.ResourceList{
|
||||
api.ResourceCPU: cpuLimit,
|
||||
api.ResourceMemory: memoryLimit,
|
||||
},
|
||||
}
|
||||
if res := resourceSpec.Limits.Cpu(); res.Cmp(cpuLimit) != 0 {
|
||||
t.Errorf("expected cpulimit %v, got %v", cpuLimit, res)
|
||||
}
|
||||
if res := resourceSpec.Limits.Memory(); res.Cmp(memoryLimit) != 0 {
|
||||
t.Errorf("expected memorylimit %v, got %v", memoryLimit, res)
|
||||
}
|
||||
resourceSpec = api.ResourceRequirements{
|
||||
Limits: api.ResourceList{
|
||||
api.ResourceMemory: memoryLimit,
|
||||
},
|
||||
}
|
||||
if res := resourceSpec.Limits.Cpu(); res.Value() != 0 {
|
||||
t.Errorf("expected cpulimit %v, got %v", 0, res)
|
||||
}
|
||||
if res := resourceSpec.Limits.Memory(); res.Cmp(memoryLimit) != 0 {
|
||||
t.Errorf("expected memorylimit %v, got %v", memoryLimit, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultResourceHelpers(t *testing.T) {
|
||||
resourceList := api.ResourceList{}
|
||||
if resourceList.Cpu().Format != resource.DecimalSI {
|
||||
t.Errorf("expected %v, actual %v", resource.DecimalSI, resourceList.Cpu().Format)
|
||||
}
|
||||
if resourceList.Memory().Format != resource.BinarySI {
|
||||
t.Errorf("expected %v, actual %v", resource.BinarySI, resourceList.Memory().Format)
|
||||
}
|
||||
}
|
||||
|
||||
func newPod(now metav1.Time, ready bool, beforeSec int) *api.Pod {
|
||||
conditionStatus := api.ConditionFalse
|
||||
if ready {
|
||||
conditionStatus = api.ConditionTrue
|
||||
}
|
||||
return &api.Pod{
|
||||
Status: api.PodStatus{
|
||||
Conditions: []api.PodCondition{
|
||||
{
|
||||
Type: api.PodReady,
|
||||
LastTransitionTime: metav1.NewTime(now.Time.Add(-1 * time.Duration(beforeSec) * time.Second)),
|
||||
Status: conditionStatus,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
77
vendor/k8s.io/kubernetes/pkg/api/testapi/BUILD
generated
vendored
77
vendor/k8s.io/kubernetes/pkg/api/testapi/BUILD
generated
vendored
|
|
@ -1,77 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["testapi.go"],
|
||||
deps = [
|
||||
"//federation/apis/federation:go_default_library",
|
||||
"//federation/apis/federation/install:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/install:go_default_library",
|
||||
"//pkg/apis/admission:go_default_library",
|
||||
"//pkg/apis/admission/install:go_default_library",
|
||||
"//pkg/apis/admissionregistration:go_default_library",
|
||||
"//pkg/apis/admissionregistration/install:go_default_library",
|
||||
"//pkg/apis/apps:go_default_library",
|
||||
"//pkg/apis/apps/install:go_default_library",
|
||||
"//pkg/apis/authentication/install:go_default_library",
|
||||
"//pkg/apis/authorization:go_default_library",
|
||||
"//pkg/apis/authorization/install:go_default_library",
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/autoscaling/install:go_default_library",
|
||||
"//pkg/apis/batch:go_default_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/extensions:go_default_library",
|
||||
"//pkg/apis/extensions/install:go_default_library",
|
||||
"//pkg/apis/imagepolicy:go_default_library",
|
||||
"//pkg/apis/imagepolicy/install:go_default_library",
|
||||
"//pkg/apis/networking:go_default_library",
|
||||
"//pkg/apis/networking/install:go_default_library",
|
||||
"//pkg/apis/policy:go_default_library",
|
||||
"//pkg/apis/policy/install:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/apis/rbac/install:go_default_library",
|
||||
"//pkg/apis/scheduling:go_default_library",
|
||||
"//pkg/apis/scheduling/install:go_default_library",
|
||||
"//pkg/apis/settings:go_default_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/api/meta: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",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["testapi_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
20
vendor/k8s.io/kubernetes/pkg/api/testapi/OWNERS
generated
vendored
20
vendor/k8s.io/kubernetes/pkg/api/testapi/OWNERS
generated
vendored
|
|
@ -1,20 +0,0 @@
|
|||
reviewers:
|
||||
- thockin
|
||||
- lavalamp
|
||||
- smarterclayton
|
||||
- wojtek-t
|
||||
- deads2k
|
||||
- caesarxuchao
|
||||
- mikedanese
|
||||
- liggitt
|
||||
- nikhiljindal
|
||||
- erictune
|
||||
- tallclair
|
||||
- eparis
|
||||
- soltysh
|
||||
- madhusudancs
|
||||
- markturansky
|
||||
- mml
|
||||
- david-mcmahon
|
||||
- ericchiang
|
||||
- jianhuiz
|
||||
542
vendor/k8s.io/kubernetes/pkg/api/testapi/testapi.go
generated
vendored
542
vendor/k8s.io/kubernetes/pkg/api/testapi/testapi.go
generated
vendored
|
|
@ -1,542 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package testapi provides a helper for retrieving the KUBE_TEST_API environment variable.
|
||||
//
|
||||
// TODO(lavalamp): this package is a huge disaster at the moment. I intend to
|
||||
// refactor. All code currently using this package should change:
|
||||
// 1. Declare your own api.Registry.APIGroupRegistrationManager in your own test code.
|
||||
// 2. Import the relevant install packages.
|
||||
// 3. Register the types you need, from the announced.APIGroupAnnouncementManager.
|
||||
package testapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mime"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/admission"
|
||||
"k8s.io/kubernetes/pkg/apis/admissionregistration"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/authorization"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/imagepolicy"
|
||||
"k8s.io/kubernetes/pkg/apis/networking"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/scheduling"
|
||||
"k8s.io/kubernetes/pkg/apis/settings"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
|
||||
_ "k8s.io/kubernetes/federation/apis/federation/install"
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/admission/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/admissionregistration/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/apps/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/authentication/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/authorization/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/certificates/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/networking/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/policy/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/scheduling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/settings/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/storage/install"
|
||||
)
|
||||
|
||||
var (
|
||||
Groups = make(map[string]TestGroup)
|
||||
Default TestGroup
|
||||
Authorization TestGroup
|
||||
Autoscaling TestGroup
|
||||
Batch TestGroup
|
||||
Extensions TestGroup
|
||||
Apps TestGroup
|
||||
Policy TestGroup
|
||||
Federation TestGroup
|
||||
Rbac TestGroup
|
||||
Certificates TestGroup
|
||||
Scheduling TestGroup
|
||||
Settings TestGroup
|
||||
Storage TestGroup
|
||||
ImagePolicy TestGroup
|
||||
Admission TestGroup
|
||||
Networking TestGroup
|
||||
|
||||
serializer runtime.SerializerInfo
|
||||
storageSerializer runtime.SerializerInfo
|
||||
)
|
||||
|
||||
type TestGroup struct {
|
||||
externalGroupVersion schema.GroupVersion
|
||||
internalGroupVersion schema.GroupVersion
|
||||
internalTypes map[string]reflect.Type
|
||||
externalTypes map[string]reflect.Type
|
||||
}
|
||||
|
||||
func init() {
|
||||
if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 {
|
||||
var ok bool
|
||||
mediaType, _, err := mime.ParseMediaType(apiMediaType)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
serializer, ok = runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("no serializer for %s", apiMediaType))
|
||||
}
|
||||
}
|
||||
|
||||
if storageMediaType := StorageMediaType(); len(storageMediaType) > 0 {
|
||||
var ok bool
|
||||
mediaType, _, err := mime.ParseMediaType(storageMediaType)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
storageSerializer, ok = runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("no serializer for %s", storageMediaType))
|
||||
}
|
||||
}
|
||||
|
||||
kubeTestAPI := os.Getenv("KUBE_TEST_API")
|
||||
if len(kubeTestAPI) != 0 {
|
||||
// priority is "first in list preferred", so this has to run in reverse order
|
||||
testGroupVersions := strings.Split(kubeTestAPI, ",")
|
||||
for i := len(testGroupVersions) - 1; i >= 0; i-- {
|
||||
gvString := testGroupVersions[i]
|
||||
groupVersion, err := schema.ParseGroupVersion(gvString)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Error parsing groupversion %v: %v", gvString, err))
|
||||
}
|
||||
|
||||
internalGroupVersion := schema.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal}
|
||||
Groups[groupVersion.Group] = TestGroup{
|
||||
externalGroupVersion: groupVersion,
|
||||
internalGroupVersion: internalGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(internalGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(groupVersion),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := Groups[api.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: api.GroupName, Version: api.Registry.GroupOrDie(api.GroupName).GroupVersion.Version}
|
||||
Groups[api.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: api.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(api.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[extensions.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: extensions.GroupName, Version: api.Registry.GroupOrDie(extensions.GroupName).GroupVersion.Version}
|
||||
Groups[extensions.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: extensions.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[autoscaling.GroupName]; !ok {
|
||||
internalTypes := make(map[string]reflect.Type)
|
||||
for k, t := range api.Scheme.KnownTypes(extensions.SchemeGroupVersion) {
|
||||
if k == "Scale" {
|
||||
continue
|
||||
}
|
||||
internalTypes[k] = t
|
||||
}
|
||||
externalGroupVersion := schema.GroupVersion{Group: autoscaling.GroupName, Version: api.Registry.GroupOrDie(autoscaling.GroupName).GroupVersion.Version}
|
||||
Groups[autoscaling.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: extensions.SchemeGroupVersion,
|
||||
internalTypes: internalTypes,
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[autoscaling.GroupName+"IntraGroup"]; !ok {
|
||||
internalTypes := make(map[string]reflect.Type)
|
||||
for k, t := range api.Scheme.KnownTypes(extensions.SchemeGroupVersion) {
|
||||
if k == "Scale" {
|
||||
internalTypes[k] = t
|
||||
break
|
||||
}
|
||||
}
|
||||
externalGroupVersion := schema.GroupVersion{Group: autoscaling.GroupName, Version: api.Registry.GroupOrDie(autoscaling.GroupName).GroupVersion.Version}
|
||||
Groups[autoscaling.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: autoscaling.SchemeGroupVersion,
|
||||
internalTypes: internalTypes,
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[batch.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: batch.GroupName, Version: api.Registry.GroupOrDie(batch.GroupName).GroupVersion.Version}
|
||||
Groups[batch.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: batch.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(batch.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[apps.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: apps.GroupName, Version: api.Registry.GroupOrDie(apps.GroupName).GroupVersion.Version}
|
||||
Groups[apps.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: apps.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(apps.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[policy.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: policy.GroupName, Version: api.Registry.GroupOrDie(policy.GroupName).GroupVersion.Version}
|
||||
Groups[policy.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: policy.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(policy.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[federation.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: federation.GroupName, Version: api.Registry.GroupOrDie(federation.GroupName).GroupVersion.Version}
|
||||
Groups[federation.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: federation.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(federation.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[rbac.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: rbac.GroupName, Version: api.Registry.GroupOrDie(rbac.GroupName).GroupVersion.Version}
|
||||
Groups[rbac.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: rbac.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(rbac.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[scheduling.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: scheduling.GroupName, Version: api.Registry.GroupOrDie(scheduling.GroupName).GroupVersion.Version}
|
||||
Groups[scheduling.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: scheduling.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(scheduling.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[settings.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: settings.GroupName, Version: api.Registry.GroupOrDie(settings.GroupName).GroupVersion.Version}
|
||||
Groups[settings.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: settings.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(settings.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[storage.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: storage.GroupName, Version: api.Registry.GroupOrDie(storage.GroupName).GroupVersion.Version}
|
||||
Groups[storage.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: storage.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(storage.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[certificates.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: certificates.GroupName, Version: api.Registry.GroupOrDie(certificates.GroupName).GroupVersion.Version}
|
||||
Groups[certificates.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: certificates.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(certificates.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[imagepolicy.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: imagepolicy.GroupName, Version: api.Registry.GroupOrDie(imagepolicy.GroupName).GroupVersion.Version}
|
||||
Groups[imagepolicy.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: imagepolicy.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(imagepolicy.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[authorization.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: authorization.GroupName, Version: api.Registry.GroupOrDie(authorization.GroupName).GroupVersion.Version}
|
||||
Groups[authorization.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: authorization.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(authorization.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[admissionregistration.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: admissionregistration.GroupName, Version: api.Registry.GroupOrDie(admissionregistration.GroupName).GroupVersion.Version}
|
||||
Groups[admissionregistration.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: admissionregistration.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(admissionregistration.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[admission.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: admission.GroupName, Version: api.Registry.GroupOrDie(admission.GroupName).GroupVersion.Version}
|
||||
Groups[admission.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: admission.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(admission.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[networking.GroupName]; !ok {
|
||||
externalGroupVersion := schema.GroupVersion{Group: networking.GroupName, Version: api.Registry.GroupOrDie(networking.GroupName).GroupVersion.Version}
|
||||
Groups[networking.GroupName] = TestGroup{
|
||||
externalGroupVersion: externalGroupVersion,
|
||||
internalGroupVersion: networking.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(networking.SchemeGroupVersion),
|
||||
externalTypes: api.Scheme.KnownTypes(externalGroupVersion),
|
||||
}
|
||||
}
|
||||
|
||||
Default = Groups[api.GroupName]
|
||||
Autoscaling = Groups[autoscaling.GroupName]
|
||||
Batch = Groups[batch.GroupName]
|
||||
Apps = Groups[apps.GroupName]
|
||||
Policy = Groups[policy.GroupName]
|
||||
Certificates = Groups[certificates.GroupName]
|
||||
Extensions = Groups[extensions.GroupName]
|
||||
Federation = Groups[federation.GroupName]
|
||||
Rbac = Groups[rbac.GroupName]
|
||||
Scheduling = Groups[scheduling.GroupName]
|
||||
Settings = Groups[settings.GroupName]
|
||||
Storage = Groups[storage.GroupName]
|
||||
ImagePolicy = Groups[imagepolicy.GroupName]
|
||||
Authorization = Groups[authorization.GroupName]
|
||||
Admission = Groups[admission.GroupName]
|
||||
Networking = Groups[networking.GroupName]
|
||||
}
|
||||
|
||||
func (g TestGroup) ContentConfig() (string, *schema.GroupVersion, runtime.Codec) {
|
||||
return "application/json", g.GroupVersion(), g.Codec()
|
||||
}
|
||||
|
||||
func (g TestGroup) GroupVersion() *schema.GroupVersion {
|
||||
copyOfGroupVersion := g.externalGroupVersion
|
||||
return ©OfGroupVersion
|
||||
}
|
||||
|
||||
// InternalGroupVersion returns the group,version used to identify the internal
|
||||
// types for this API
|
||||
func (g TestGroup) InternalGroupVersion() schema.GroupVersion {
|
||||
return g.internalGroupVersion
|
||||
}
|
||||
|
||||
// InternalTypes returns a map of internal API types' kind names to their Go types.
|
||||
func (g TestGroup) InternalTypes() map[string]reflect.Type {
|
||||
return g.internalTypes
|
||||
}
|
||||
|
||||
// ExternalTypes returns a map of external API types' kind names to their Go types.
|
||||
func (g TestGroup) ExternalTypes() map[string]reflect.Type {
|
||||
return g.externalTypes
|
||||
}
|
||||
|
||||
// Codec returns the codec for the API version to test against, as set by the
|
||||
// KUBE_TEST_API_TYPE env var.
|
||||
func (g TestGroup) Codec() runtime.Codec {
|
||||
if serializer.Serializer == nil {
|
||||
return api.Codecs.LegacyCodec(g.externalGroupVersion)
|
||||
}
|
||||
return api.Codecs.CodecForVersions(serializer.Serializer, api.Codecs.UniversalDeserializer(), schema.GroupVersions{g.externalGroupVersion}, nil)
|
||||
}
|
||||
|
||||
// NegotiatedSerializer returns the negotiated serializer for the server.
|
||||
func (g TestGroup) NegotiatedSerializer() runtime.NegotiatedSerializer {
|
||||
return api.Codecs
|
||||
}
|
||||
|
||||
func StorageMediaType() string {
|
||||
return os.Getenv("KUBE_TEST_API_STORAGE_TYPE")
|
||||
}
|
||||
|
||||
// StorageCodec returns the codec for the API version to store in etcd, as set by the
|
||||
// KUBE_TEST_API_STORAGE_TYPE env var.
|
||||
func (g TestGroup) StorageCodec() runtime.Codec {
|
||||
s := storageSerializer.Serializer
|
||||
|
||||
if s == nil {
|
||||
return api.Codecs.LegacyCodec(g.externalGroupVersion)
|
||||
}
|
||||
|
||||
// etcd2 only supports string data - we must wrap any result before returning
|
||||
// TODO: remove for etcd3 / make parameterizable
|
||||
if !storageSerializer.EncodesAsText {
|
||||
s = runtime.NewBase64Serializer(s, s)
|
||||
}
|
||||
ds := recognizer.NewDecoder(s, api.Codecs.UniversalDeserializer())
|
||||
|
||||
return api.Codecs.CodecForVersions(s, ds, schema.GroupVersions{g.externalGroupVersion}, nil)
|
||||
}
|
||||
|
||||
// Converter returns the api.Scheme for the API version to test against, as set by the
|
||||
// KUBE_TEST_API env var.
|
||||
func (g TestGroup) Converter() runtime.ObjectConvertor {
|
||||
interfaces, err := api.Registry.GroupOrDie(g.externalGroupVersion.Group).InterfacesFor(g.externalGroupVersion)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return interfaces.ObjectConvertor
|
||||
}
|
||||
|
||||
// MetadataAccessor returns the MetadataAccessor for the API version to test against,
|
||||
// as set by the KUBE_TEST_API env var.
|
||||
func (g TestGroup) MetadataAccessor() meta.MetadataAccessor {
|
||||
interfaces, err := api.Registry.GroupOrDie(g.externalGroupVersion.Group).InterfacesFor(g.externalGroupVersion)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return interfaces.MetadataAccessor
|
||||
}
|
||||
|
||||
// SelfLink returns a self link that will appear to be for the version Version().
|
||||
// 'resource' should be the resource path, e.g. "pods" for the Pod type. 'name' should be
|
||||
// empty for lists.
|
||||
func (g TestGroup) SelfLink(resource, name string) string {
|
||||
if g.externalGroupVersion.Group == api.GroupName {
|
||||
if name == "" {
|
||||
return fmt.Sprintf("/api/%s/%s", g.externalGroupVersion.Version, resource)
|
||||
}
|
||||
return fmt.Sprintf("/api/%s/%s/%s", g.externalGroupVersion.Version, resource, name)
|
||||
} else {
|
||||
// TODO: will need a /apis prefix once we have proper multi-group
|
||||
// support
|
||||
if name == "" {
|
||||
return fmt.Sprintf("/apis/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource)
|
||||
}
|
||||
return fmt.Sprintf("/apis/%s/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource, name)
|
||||
}
|
||||
}
|
||||
|
||||
// ResourcePathWithPrefix returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name.
|
||||
// For ex, this is of the form:
|
||||
// /api/v1/watch/namespaces/foo/pods/pod0 for v1.
|
||||
func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name string) string {
|
||||
var path string
|
||||
if g.externalGroupVersion.Group == api.GroupName {
|
||||
path = "/api/" + g.externalGroupVersion.Version
|
||||
} else {
|
||||
// TODO: switch back once we have proper multiple group support
|
||||
// path = "/apis/" + g.Group + "/" + Version(group...)
|
||||
path = "/apis/" + g.externalGroupVersion.Group + "/" + g.externalGroupVersion.Version
|
||||
}
|
||||
|
||||
if prefix != "" {
|
||||
path = path + "/" + prefix
|
||||
}
|
||||
if namespace != "" {
|
||||
path = path + "/namespaces/" + namespace
|
||||
}
|
||||
// Resource names are lower case.
|
||||
resource = strings.ToLower(resource)
|
||||
if resource != "" {
|
||||
path = path + "/" + resource
|
||||
}
|
||||
if name != "" {
|
||||
path = path + "/" + name
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// ResourcePath returns the appropriate path for the given resource, namespace and name.
|
||||
// For example, this is of the form:
|
||||
// /api/v1/namespaces/foo/pods/pod0 for v1.
|
||||
func (g TestGroup) ResourcePath(resource, namespace, name string) string {
|
||||
return g.ResourcePathWithPrefix("", resource, namespace, name)
|
||||
}
|
||||
|
||||
// SubResourcePath returns the appropriate path for the given resource, namespace,
|
||||
// name and subresource.
|
||||
func (g TestGroup) SubResourcePath(resource, namespace, name, sub string) string {
|
||||
path := g.ResourcePathWithPrefix("", resource, namespace, name)
|
||||
if sub != "" {
|
||||
path = path + "/" + sub
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
// RESTMapper returns RESTMapper in api.Registry.
|
||||
func (g TestGroup) RESTMapper() meta.RESTMapper {
|
||||
return api.Registry.RESTMapper()
|
||||
}
|
||||
|
||||
// ExternalGroupVersions returns all external group versions allowed for the server.
|
||||
func ExternalGroupVersions() schema.GroupVersions {
|
||||
versions := []schema.GroupVersion{}
|
||||
for _, g := range Groups {
|
||||
gv := g.GroupVersion()
|
||||
versions = append(versions, *gv)
|
||||
}
|
||||
return versions
|
||||
}
|
||||
|
||||
// GetCodecForObject gets codec based on runtime.Object
|
||||
func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) {
|
||||
kinds, _, err := api.Scheme.ObjectKinds(obj)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unexpected encoding error: %v", err)
|
||||
}
|
||||
kind := kinds[0]
|
||||
|
||||
for _, group := range Groups {
|
||||
if group.GroupVersion().Group != kind.Group {
|
||||
continue
|
||||
}
|
||||
|
||||
if api.Scheme.Recognizes(kind) {
|
||||
return group.Codec(), nil
|
||||
}
|
||||
}
|
||||
// Codec used for unversioned types
|
||||
if api.Scheme.Recognizes(kind) {
|
||||
serializer, ok := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no serializer registered for json")
|
||||
}
|
||||
return serializer.Serializer, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected kind: %v", kind)
|
||||
}
|
||||
|
||||
// NewTestGroup creates a new TestGroup.
|
||||
func NewTestGroup(external, internal schema.GroupVersion, internalTypes map[string]reflect.Type, externalTypes map[string]reflect.Type) TestGroup {
|
||||
return TestGroup{external, internal, internalTypes, externalTypes}
|
||||
}
|
||||
137
vendor/k8s.io/kubernetes/pkg/api/testapi/testapi_test.go
generated
vendored
137
vendor/k8s.io/kubernetes/pkg/api/testapi/testapi_test.go
generated
vendored
|
|
@ -1,137 +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 testapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// TODO these tests don't add much value for testing things that have groups
|
||||
|
||||
func TestResourcePathWithPrefix(t *testing.T) {
|
||||
testCases := []struct {
|
||||
prefix string
|
||||
resource string
|
||||
namespace string
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"prefix", "resource", "mynamespace", "myresource", "/api/" + Default.GroupVersion().Version + "/prefix/namespaces/mynamespace/resource/myresource"},
|
||||
{"prefix", "resource", "", "myresource", "/api/" + Default.GroupVersion().Version + "/prefix/resource/myresource"},
|
||||
{"prefix", "resource", "mynamespace", "", "/api/" + Default.GroupVersion().Version + "/prefix/namespaces/mynamespace/resource"},
|
||||
{"prefix", "resource", "", "", "/api/" + Default.GroupVersion().Version + "/prefix/resource"},
|
||||
{"", "resource", "mynamespace", "myresource", "/api/" + Default.GroupVersion().Version + "/namespaces/mynamespace/resource/myresource"},
|
||||
}
|
||||
for _, item := range testCases {
|
||||
if actual := Default.ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected {
|
||||
t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourcePath(t *testing.T) {
|
||||
testCases := []struct {
|
||||
resource string
|
||||
namespace string
|
||||
name string
|
||||
expected string
|
||||
}{
|
||||
{"resource", "mynamespace", "myresource", "/api/" + Default.GroupVersion().Version + "/namespaces/mynamespace/resource/myresource"},
|
||||
{"resource", "", "myresource", "/api/" + Default.GroupVersion().Version + "/resource/myresource"},
|
||||
{"resource", "mynamespace", "", "/api/" + Default.GroupVersion().Version + "/namespaces/mynamespace/resource"},
|
||||
{"resource", "", "", "/api/" + Default.GroupVersion().Version + "/resource"},
|
||||
}
|
||||
for _, item := range testCases {
|
||||
if actual := Default.ResourcePath(item.resource, item.namespace, item.name); actual != item.expected {
|
||||
t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var status = &metav1.Status{
|
||||
Status: metav1.StatusFailure,
|
||||
Code: 200,
|
||||
Reason: metav1.StatusReasonUnknown,
|
||||
Message: "",
|
||||
}
|
||||
|
||||
func TestV1EncodeDecodeStatus(t *testing.T) {
|
||||
v1Codec := Default.Codec()
|
||||
|
||||
encoded, err := runtime.Encode(v1Codec, status)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
typeMeta := metav1.TypeMeta{}
|
||||
if err := json.Unmarshal(encoded, &typeMeta); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if typeMeta.Kind != "Status" {
|
||||
t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded))
|
||||
}
|
||||
if typeMeta.APIVersion != "v1" {
|
||||
t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded))
|
||||
}
|
||||
decoded, err := runtime.Decode(v1Codec, encoded)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(status, decoded) {
|
||||
t.Errorf("expected: %#v, got: %#v", status, decoded)
|
||||
}
|
||||
}
|
||||
|
||||
func testEncodeDecodeStatus(t *testing.T, codec runtime.Codec) {
|
||||
encoded, err := runtime.Encode(codec, status)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
typeMeta := metav1.TypeMeta{}
|
||||
if err := json.Unmarshal(encoded, &typeMeta); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if typeMeta.Kind != "Status" {
|
||||
t.Errorf("Kind is not set to \"Status\". Got %s", encoded)
|
||||
}
|
||||
if typeMeta.APIVersion != "v1" {
|
||||
t.Errorf("APIVersion is not set to \"\". Got %s", encoded)
|
||||
}
|
||||
decoded, err := runtime.Decode(codec, encoded)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(status, decoded) {
|
||||
t.Errorf("expected: %v, got: %v", status, decoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoscalingEncodeDecodeStatus(t *testing.T) {
|
||||
testEncodeDecodeStatus(t, Autoscaling.Codec())
|
||||
}
|
||||
|
||||
func TestBatchEncodeDecodeStatus(t *testing.T) {
|
||||
testEncodeDecodeStatus(t, Batch.Codec())
|
||||
}
|
||||
|
||||
func TestExperimentalEncodeDecodeStatus(t *testing.T) {
|
||||
testEncodeDecodeStatus(t, Extensions.Codec())
|
||||
}
|
||||
56
vendor/k8s.io/kubernetes/pkg/api/testing/BUILD
generated
vendored
56
vendor/k8s.io/kubernetes/pkg/api/testing/BUILD
generated
vendored
|
|
@ -1,56 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"conversion.go",
|
||||
"fuzzer.go",
|
||||
"pod_specs.go",
|
||||
],
|
||||
deps = [
|
||||
"//cmd/kubeadm/app/apis/kubeadm/fuzzer:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/fuzzer:go_default_library",
|
||||
"//pkg/apis/admissionregistration/fuzzer:go_default_library",
|
||||
"//pkg/apis/apps/fuzzer:go_default_library",
|
||||
"//pkg/apis/autoscaling/fuzzer:go_default_library",
|
||||
"//pkg/apis/batch/fuzzer:go_default_library",
|
||||
"//pkg/apis/certificates/fuzzer:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/apis/extensions/fuzzer:go_default_library",
|
||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
"//pkg/apis/networking/fuzzer:go_default_library",
|
||||
"//pkg/apis/policy/fuzzer:go_default_library",
|
||||
"//pkg/apis/rbac/fuzzer:go_default_library",
|
||||
"//pkg/apis/storage/fuzzer: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",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/api/testing/compat:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
39
vendor/k8s.io/kubernetes/pkg/api/testing/OWNERS
generated
vendored
39
vendor/k8s.io/kubernetes/pkg/api/testing/OWNERS
generated
vendored
|
|
@ -1,39 +0,0 @@
|
|||
reviewers:
|
||||
- thockin
|
||||
- lavalamp
|
||||
- smarterclayton
|
||||
- wojtek-t
|
||||
- deads2k
|
||||
- yujuhong
|
||||
- brendandburns
|
||||
- derekwaynecarr
|
||||
- caesarxuchao
|
||||
- vishh
|
||||
- mikedanese
|
||||
- nikhiljindal
|
||||
- erictune
|
||||
- pmorie
|
||||
- dchen1107
|
||||
- saad-ali
|
||||
- zmerlynn
|
||||
- justinsb
|
||||
- pwittrock
|
||||
- roberthbailey
|
||||
- tallclair
|
||||
- yifan-gu
|
||||
- eparis
|
||||
- soltysh
|
||||
- jsafrane
|
||||
- madhusudancs
|
||||
- hongchaodeng
|
||||
- rootfs
|
||||
- jszczepkowski
|
||||
- markturansky
|
||||
- fgrzadkowski
|
||||
- aveshagarwal
|
||||
- david-mcmahon
|
||||
- pweil-
|
||||
- rata
|
||||
- feihujiang
|
||||
- sdminonne
|
||||
- ghodss
|
||||
31
vendor/k8s.io/kubernetes/pkg/api/testing/compat/BUILD
generated
vendored
31
vendor/k8s.io/kubernetes/pkg/api/testing/compat/BUILD
generated
vendored
|
|
@ -1,31 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["compatibility_tester.go"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/printers: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",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
144
vendor/k8s.io/kubernetes/pkg/api/testing/compat/compatibility_tester.go
generated
vendored
144
vendor/k8s.io/kubernetes/pkg/api/testing/compat/compatibility_tester.go
generated
vendored
|
|
@ -1,144 +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 compat
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
|
||||
// Based on: https://github.com/openshift/origin/blob/master/pkg/api/compatibility_test.go
|
||||
//
|
||||
// TestCompatibility reencodes the input using the codec for the given
|
||||
// version and checks for the presence of the expected keys and absent
|
||||
// keys in the resulting JSON.
|
||||
func TestCompatibility(
|
||||
t *testing.T,
|
||||
version schema.GroupVersion,
|
||||
input []byte,
|
||||
validator func(obj runtime.Object) field.ErrorList,
|
||||
expectedKeys map[string]string,
|
||||
absentKeys []string,
|
||||
) {
|
||||
|
||||
// Decode
|
||||
codec := api.Codecs.LegacyCodec(version)
|
||||
obj, err := runtime.Decode(codec, input)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Validate
|
||||
errs := validator(obj)
|
||||
if len(errs) != 0 {
|
||||
t.Fatalf("Unexpected validation errors: %v", errs)
|
||||
}
|
||||
|
||||
// Encode
|
||||
output, err := runtime.Encode(codec, obj)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Validate old and new fields are encoded
|
||||
generic := map[string]interface{}{}
|
||||
if err := json.Unmarshal(output, &generic); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
hasError := false
|
||||
for k, expectedValue := range expectedKeys {
|
||||
keys := strings.Split(k, ".")
|
||||
if actualValue, ok, err := getJSONValue(generic, keys...); err != nil || !ok {
|
||||
t.Errorf("Unexpected error for %s: %v", k, err)
|
||||
hasError = true
|
||||
} else if !reflect.DeepEqual(expectedValue, fmt.Sprintf("%v", actualValue)) {
|
||||
hasError = true
|
||||
t.Errorf("Unexpected value for %v: expected %v, got %v", k, expectedValue, actualValue)
|
||||
}
|
||||
}
|
||||
|
||||
for _, absentKey := range absentKeys {
|
||||
keys := strings.Split(absentKey, ".")
|
||||
actualValue, ok, err := getJSONValue(generic, keys...)
|
||||
if err == nil || ok {
|
||||
t.Errorf("Unexpected value found for key %s: %v", absentKey, actualValue)
|
||||
hasError = true
|
||||
}
|
||||
}
|
||||
|
||||
if hasError {
|
||||
printer := &printers.JSONPrinter{}
|
||||
printer.PrintObj(obj, os.Stdout)
|
||||
t.Logf("2: Encoded value: %#v", string(output))
|
||||
}
|
||||
}
|
||||
|
||||
func getJSONValue(data map[string]interface{}, keys ...string) (interface{}, bool, error) {
|
||||
// No keys, current value is it
|
||||
if len(keys) == 0 {
|
||||
return data, true, nil
|
||||
}
|
||||
|
||||
// Get the key (and optional index)
|
||||
key := keys[0]
|
||||
index := -1
|
||||
if matches := regexp.MustCompile(`^(.*)\[(\d+)\]$`).FindStringSubmatch(key); len(matches) > 0 {
|
||||
key = matches[1]
|
||||
index, _ = strconv.Atoi(matches[2])
|
||||
}
|
||||
|
||||
// Look up the value
|
||||
value, ok := data[key]
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("No key %s found", key)
|
||||
}
|
||||
|
||||
// Get the indexed value if an index is specified
|
||||
if index >= 0 {
|
||||
valueSlice, ok := value.([]interface{})
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("Key %s did not hold a slice", key)
|
||||
}
|
||||
if index >= len(valueSlice) {
|
||||
return nil, false, fmt.Errorf("Index %d out of bounds for slice at key: %v", index, key)
|
||||
}
|
||||
value = valueSlice[index]
|
||||
}
|
||||
|
||||
if len(keys) == 1 {
|
||||
return value, true, nil
|
||||
}
|
||||
|
||||
childData, ok := value.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("Key %s did not hold a map", keys[0])
|
||||
}
|
||||
return getJSONValue(childData, keys[1:]...)
|
||||
}
|
||||
72
vendor/k8s.io/kubernetes/pkg/api/testing/conversion.go
generated
vendored
72
vendor/k8s.io/kubernetes/pkg/api/testing/conversion.go
generated
vendored
|
|
@ -1,72 +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 testing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// TestSelectableFieldLabelConversions verifies that given resource have field
|
||||
// label conversion defined for each its selectable field.
|
||||
// fields contains selectable fields of the resource.
|
||||
// labelMap maps deprecated labels to their canonical names.
|
||||
func TestSelectableFieldLabelConversionsOfKind(t *testing.T, apiVersion string, kind string, fields fields.Set, labelMap map[string]string) {
|
||||
badFieldLabels := []string{
|
||||
"name",
|
||||
".name",
|
||||
"bad",
|
||||
"metadata",
|
||||
"foo.bar",
|
||||
}
|
||||
|
||||
value := "value"
|
||||
|
||||
if len(fields) == 0 {
|
||||
t.Logf("no selectable fields for kind %q, skipping", kind)
|
||||
}
|
||||
for label := range fields {
|
||||
if label == "name" {
|
||||
t.Logf("FIXME: \"name\" is deprecated by \"metadata.name\", it should be removed from selectable fields of kind=%s", kind)
|
||||
continue
|
||||
}
|
||||
newLabel, newValue, err := api.Scheme.ConvertFieldLabel(apiVersion, kind, label, value)
|
||||
if err != nil {
|
||||
t.Errorf("kind=%s label=%s: got unexpected error: %v", kind, label, err)
|
||||
} else {
|
||||
expectedLabel := label
|
||||
if l, exists := labelMap[label]; exists {
|
||||
expectedLabel = l
|
||||
}
|
||||
if newLabel != expectedLabel {
|
||||
t.Errorf("kind=%s label=%s: got unexpected label name (%q != %q)", kind, label, newLabel, expectedLabel)
|
||||
}
|
||||
if newValue != value {
|
||||
t.Errorf("kind=%s label=%s: got unexpected new value (%q != %q)", kind, label, newValue, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, label := range badFieldLabels {
|
||||
_, _, err := api.Scheme.ConvertFieldLabel(apiVersion, kind, label, "value")
|
||||
if err == nil {
|
||||
t.Errorf("kind=%s label=%s: got unexpected non-error", kind, label)
|
||||
}
|
||||
}
|
||||
}
|
||||
107
vendor/k8s.io/kubernetes/pkg/api/testing/fuzzer.go
generated
vendored
107
vendor/k8s.io/kubernetes/pkg/api/testing/fuzzer.go
generated
vendored
|
|
@ -1,107 +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 testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
|
||||
genericfuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
kubeadmfuzzer "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/fuzzer"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
corefuzzer "k8s.io/kubernetes/pkg/api/fuzzer"
|
||||
admissionregistrationfuzzer "k8s.io/kubernetes/pkg/apis/admissionregistration/fuzzer"
|
||||
appsfuzzer "k8s.io/kubernetes/pkg/apis/apps/fuzzer"
|
||||
autoscalingfuzzer "k8s.io/kubernetes/pkg/apis/autoscaling/fuzzer"
|
||||
batchfuzzer "k8s.io/kubernetes/pkg/apis/batch/fuzzer"
|
||||
certificatesfuzzer "k8s.io/kubernetes/pkg/apis/certificates/fuzzer"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
extensionsfuzzer "k8s.io/kubernetes/pkg/apis/extensions/fuzzer"
|
||||
extensionsv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||
networkingfuzzer "k8s.io/kubernetes/pkg/apis/networking/fuzzer"
|
||||
policyfuzzer "k8s.io/kubernetes/pkg/apis/policy/fuzzer"
|
||||
rbacfuzzer "k8s.io/kubernetes/pkg/apis/rbac/fuzzer"
|
||||
storagefuzzer "k8s.io/kubernetes/pkg/apis/storage/fuzzer"
|
||||
)
|
||||
|
||||
// overrideGenericFuncs override some generic fuzzer funcs from k8s.io/apiserver in order to have more realistic
|
||||
// values in a Kubernetes context.
|
||||
func overrideGenericFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
return []interface{}{
|
||||
func(j *runtime.Object, c fuzz.Continue) {
|
||||
// TODO: uncomment when round trip starts from a versioned object
|
||||
if true { //c.RandBool() {
|
||||
*j = &runtime.Unknown{
|
||||
// We do not set TypeMeta here because it is not carried through a round trip
|
||||
Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
|
||||
ContentType: runtime.ContentTypeJSON,
|
||||
}
|
||||
} else {
|
||||
types := []runtime.Object{&api.Pod{}, &api.ReplicationController{}}
|
||||
t := types[c.Rand.Intn(len(types))]
|
||||
c.Fuzz(t)
|
||||
*j = t
|
||||
}
|
||||
},
|
||||
func(r *runtime.RawExtension, c fuzz.Continue) {
|
||||
// Pick an arbitrary type and fuzz it
|
||||
types := []runtime.Object{&api.Pod{}, &extensions.Deployment{}, &api.Service{}}
|
||||
obj := types[c.Rand.Intn(len(types))]
|
||||
c.Fuzz(obj)
|
||||
|
||||
var codec runtime.Codec
|
||||
switch obj.(type) {
|
||||
case *extensions.Deployment:
|
||||
codec = apitesting.TestCodec(codecs, extensionsv1beta1.SchemeGroupVersion)
|
||||
default:
|
||||
codec = apitesting.TestCodec(codecs, v1.SchemeGroupVersion)
|
||||
}
|
||||
|
||||
// Convert the object to raw bytes
|
||||
bytes, err := runtime.Encode(codec, obj)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to encode object: %v", err))
|
||||
}
|
||||
|
||||
// Set the bytes field on the RawExtension
|
||||
r.Raw = bytes
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var FuzzerFuncs = fuzzer.MergeFuzzerFuncs(
|
||||
genericfuzzer.Funcs,
|
||||
overrideGenericFuncs,
|
||||
corefuzzer.Funcs,
|
||||
extensionsfuzzer.Funcs,
|
||||
appsfuzzer.Funcs,
|
||||
batchfuzzer.Funcs,
|
||||
autoscalingfuzzer.Funcs,
|
||||
rbacfuzzer.Funcs,
|
||||
kubeadmfuzzer.Funcs,
|
||||
policyfuzzer.Funcs,
|
||||
certificatesfuzzer.Funcs,
|
||||
admissionregistrationfuzzer.Funcs,
|
||||
storagefuzzer.Funcs,
|
||||
networkingfuzzer.Funcs,
|
||||
)
|
||||
45
vendor/k8s.io/kubernetes/pkg/api/testing/pod_specs.go
generated
vendored
45
vendor/k8s.io/kubernetes/pkg/api/testing/pod_specs.go
generated
vendored
|
|
@ -1,45 +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 testing
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// DeepEqualSafePodSpec returns a PodSpec which is ready to be used with apiequality.Semantic.DeepEqual
|
||||
func DeepEqualSafePodSpec() api.PodSpec {
|
||||
grace := int64(30)
|
||||
return api.PodSpec{
|
||||
RestartPolicy: api.RestartPolicyAlways,
|
||||
DNSPolicy: api.DNSClusterFirst,
|
||||
TerminationGracePeriodSeconds: &grace,
|
||||
SecurityContext: &api.PodSecurityContext{},
|
||||
SchedulerName: api.DefaultSchedulerName,
|
||||
}
|
||||
}
|
||||
|
||||
// V1DeepEqualSafePodSpec returns a PodSpec which is ready to be used with apiequality.Semantic.DeepEqual
|
||||
func V1DeepEqualSafePodSpec() v1.PodSpec {
|
||||
grace := int64(30)
|
||||
return v1.PodSpec{
|
||||
RestartPolicy: v1.RestartPolicyAlways,
|
||||
DNSPolicy: v1.DNSClusterFirst,
|
||||
TerminationGracePeriodSeconds: &grace,
|
||||
SecurityContext: &v1.PodSecurityContext{},
|
||||
}
|
||||
}
|
||||
33
vendor/k8s.io/kubernetes/pkg/api/unversioned/BUILD
generated
vendored
33
vendor/k8s.io/kubernetes/pkg/api/unversioned/BUILD
generated
vendored
|
|
@ -1,33 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"duration.go",
|
||||
"time.go",
|
||||
"types.go",
|
||||
],
|
||||
deps = [
|
||||
"//vendor/github.com/go-openapi/spec:go_default_library",
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
"//vendor/k8s.io/kube-openapi/pkg/common:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
47
vendor/k8s.io/kubernetes/pkg/api/unversioned/duration.go
generated
vendored
47
vendor/k8s.io/kubernetes/pkg/api/unversioned/duration.go
generated
vendored
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package unversioned
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Duration is a wrapper around time.Duration which supports correct
|
||||
// marshaling to YAML and JSON. In particular, it marshals into strings, which
|
||||
// can be used as map keys in json.
|
||||
type Duration struct {
|
||||
time.Duration `protobuf:"-"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||
var str string
|
||||
json.Unmarshal(b, &str)
|
||||
|
||||
pd, err := time.ParseDuration(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Duration = pd
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (d Duration) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(d.Duration.String())
|
||||
}
|
||||
176
vendor/k8s.io/kubernetes/pkg/api/unversioned/time.go
generated
vendored
176
vendor/k8s.io/kubernetes/pkg/api/unversioned/time.go
generated
vendored
|
|
@ -1,176 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package unversioned
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
openapi "k8s.io/kube-openapi/pkg/common"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/google/gofuzz"
|
||||
)
|
||||
|
||||
// Time is a wrapper around time.Time which supports correct
|
||||
// marshaling to YAML and JSON. Wrappers are provided for many
|
||||
// of the factory methods that the time package offers.
|
||||
type Time struct {
|
||||
time.Time `protobuf:"-"`
|
||||
}
|
||||
|
||||
// DeepCopyInto creates a deep-copy of the Time value. The underlying time.Time
|
||||
// type is effectively immutable in the time API, so it is safe to
|
||||
// copy-by-assign, despite the presence of (unexported) Pointer fields.
|
||||
func (t *Time) DeepCopyInto(out *Time) {
|
||||
*out = *t
|
||||
}
|
||||
|
||||
// String returns the representation of the time.
|
||||
func (t Time) String() string {
|
||||
return t.Time.String()
|
||||
}
|
||||
|
||||
// NewTime returns a wrapped instance of the provided time
|
||||
func NewTime(time time.Time) Time {
|
||||
return Time{time}
|
||||
}
|
||||
|
||||
// Date returns the Time corresponding to the supplied parameters
|
||||
// by wrapping time.Date.
|
||||
func Date(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) Time {
|
||||
return Time{time.Date(year, month, day, hour, min, sec, nsec, loc)}
|
||||
}
|
||||
|
||||
// Now returns the current local time.
|
||||
func Now() Time {
|
||||
return Time{time.Now()}
|
||||
}
|
||||
|
||||
// IsZero returns true if the value is nil or time is zero.
|
||||
func (t *Time) IsZero() bool {
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
return t.Time.IsZero()
|
||||
}
|
||||
|
||||
// Before reports whether the time instant t is before u.
|
||||
func (t Time) Before(u Time) bool {
|
||||
return t.Time.Before(u.Time)
|
||||
}
|
||||
|
||||
// Equal reports whether the time instant t is equal to u.
|
||||
func (t Time) Equal(u Time) bool {
|
||||
return t.Time.Equal(u.Time)
|
||||
}
|
||||
|
||||
// Unix returns the local time corresponding to the given Unix time
|
||||
// by wrapping time.Unix.
|
||||
func Unix(sec int64, nsec int64) Time {
|
||||
return Time{time.Unix(sec, nsec)}
|
||||
}
|
||||
|
||||
// Rfc3339Copy returns a copy of the Time at second-level precision.
|
||||
func (t Time) Rfc3339Copy() Time {
|
||||
copied, _ := time.Parse(time.RFC3339, t.Format(time.RFC3339))
|
||||
return Time{copied}
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaller interface.
|
||||
func (t *Time) UnmarshalJSON(b []byte) error {
|
||||
if len(b) == 4 && string(b) == "null" {
|
||||
t.Time = time.Time{}
|
||||
return nil
|
||||
}
|
||||
|
||||
var str string
|
||||
json.Unmarshal(b, &str)
|
||||
|
||||
pt, err := time.Parse(time.RFC3339, str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Time = pt.Local()
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalQueryParameter converts from a URL query parameter value to an object
|
||||
func (t *Time) UnmarshalQueryParameter(str string) error {
|
||||
if len(str) == 0 {
|
||||
t.Time = time.Time{}
|
||||
return nil
|
||||
}
|
||||
// Tolerate requests from older clients that used JSON serialization to build query params
|
||||
if len(str) == 4 && str == "null" {
|
||||
t.Time = time.Time{}
|
||||
return nil
|
||||
}
|
||||
|
||||
pt, err := time.Parse(time.RFC3339, str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Time = pt.Local()
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (t Time) MarshalJSON() ([]byte, error) {
|
||||
if t.IsZero() {
|
||||
// Encode unset/nil objects as JSON's "null".
|
||||
return []byte("null"), nil
|
||||
}
|
||||
|
||||
return json.Marshal(t.UTC().Format(time.RFC3339))
|
||||
}
|
||||
|
||||
func (_ Time) OpenAPIDefinition() openapi.OpenAPIDefinition {
|
||||
return openapi.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "date-time",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalQueryParameter converts to a URL query parameter value
|
||||
func (t Time) MarshalQueryParameter() (string, error) {
|
||||
if t.IsZero() {
|
||||
// Encode unset/nil objects as an empty string
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return t.UTC().Format(time.RFC3339), nil
|
||||
}
|
||||
|
||||
// Fuzz satisfies fuzz.Interface.
|
||||
func (t *Time) Fuzz(c fuzz.Continue) {
|
||||
if t == nil {
|
||||
return
|
||||
}
|
||||
// Allow for about 1000 years of randomness. Leave off nanoseconds
|
||||
// because JSON doesn't represent them so they can't round-trip
|
||||
// properly.
|
||||
t.Time = time.Unix(c.Rand.Int63n(1000*365*24*60*60), 0)
|
||||
}
|
||||
|
||||
var _ fuzz.Interface = &Time{}
|
||||
60
vendor/k8s.io/kubernetes/pkg/api/unversioned/types.go
generated
vendored
60
vendor/k8s.io/kubernetes/pkg/api/unversioned/types.go
generated
vendored
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package unversioned is deprecated and has been replaced with pkg/apis/meta/v1
|
||||
//
|
||||
// DEPRECATED - Do not reference or add types to this package, it will be removed
|
||||
// once Heapster is updated to use pkg/apis/meta/v1.
|
||||
package unversioned
|
||||
|
||||
// TypeMeta describes an individual object in an API response or request
|
||||
// with strings representing the type of the object and its API schema version.
|
||||
// Structures that are versioned or persisted should inline TypeMeta.
|
||||
type TypeMeta struct {
|
||||
// Kind is a string value representing the REST resource this object represents.
|
||||
// Servers may infer this from the endpoint the client submits requests to.
|
||||
// Cannot be updated.
|
||||
// In CamelCase.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
|
||||
// +optional
|
||||
Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"`
|
||||
|
||||
// APIVersion defines the versioned schema of this representation of an object.
|
||||
// Servers should convert recognized schemas to the latest internal value, and
|
||||
// may reject unrecognized values.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources
|
||||
// +optional
|
||||
APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"`
|
||||
}
|
||||
|
||||
// ListMeta describes metadata that synthetic resources must have, including lists and
|
||||
// various status objects. A resource may have only one of {ObjectMeta, ListMeta}.
|
||||
type ListMeta struct {
|
||||
// SelfLink is a URL representing this object.
|
||||
// Populated by the system.
|
||||
// Read-only.
|
||||
// +optional
|
||||
SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,1,opt,name=selfLink"`
|
||||
|
||||
// String that identifies the server's internal version of this object that
|
||||
// can be used by clients to determine when objects have changed.
|
||||
// Value must be treated as opaque by clients and passed unmodified back to the server.
|
||||
// Populated by the system.
|
||||
// Read-only.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency
|
||||
// +optional
|
||||
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,2,opt,name=resourceVersion"`
|
||||
}
|
||||
41
vendor/k8s.io/kubernetes/pkg/api/v1/endpoints/BUILD
generated
vendored
41
vendor/k8s.io/kubernetes/pkg/api/v1/endpoints/BUILD
generated
vendored
|
|
@ -1,41 +0,0 @@
|
|||
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"],
|
||||
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",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//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",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
226
vendor/k8s.io/kubernetes/pkg/api/v1/endpoints/util.go
generated
vendored
226
vendor/k8s.io/kubernetes/pkg/api/v1/endpoints/util.go
generated
vendored
|
|
@ -1,226 +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 endpoints
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"hash"
|
||||
"sort"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
hashutil "k8s.io/kubernetes/pkg/util/hash"
|
||||
)
|
||||
|
||||
// RepackSubsets takes a slice of EndpointSubset objects, expands it to the full
|
||||
// representation, and then repacks that into the canonical layout. This
|
||||
// ensures that code which operates on these objects can rely on the common
|
||||
// form for things like comparison. The result is a newly allocated slice.
|
||||
func RepackSubsets(subsets []v1.EndpointSubset) []v1.EndpointSubset {
|
||||
// First map each unique port definition to the sets of hosts that
|
||||
// offer it.
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Next, map the sets of hosts to the sets of ports they offer.
|
||||
// Go does not allow maps or slices as keys to maps, so we have
|
||||
// to synthesize an artificial key and do a sort of 2-part
|
||||
// associative entity.
|
||||
type keyString string
|
||||
keyToAddrReadyMap := map[keyString]addressSet{}
|
||||
addrReadyMapKeyToPorts := map[keyString][]v1.EndpointPort{}
|
||||
for port, addrs := range portToAddrReadyMap {
|
||||
key := keyString(hashAddresses(addrs))
|
||||
keyToAddrReadyMap[key] = addrs
|
||||
addrReadyMapKeyToPorts[key] = append(addrReadyMapKeyToPorts[key], port)
|
||||
}
|
||||
|
||||
// Next, build the N-to-M association the API wants.
|
||||
final := []v1.EndpointSubset{}
|
||||
for key, ports := range addrReadyMapKeyToPorts {
|
||||
var readyAddrs, notReadyAddrs []v1.EndpointAddress
|
||||
for addr, ready := range keyToAddrReadyMap[key] {
|
||||
if ready {
|
||||
readyAddrs = append(readyAddrs, *addr)
|
||||
} else {
|
||||
notReadyAddrs = append(notReadyAddrs, *addr)
|
||||
}
|
||||
}
|
||||
final = append(final, v1.EndpointSubset{Addresses: readyAddrs, NotReadyAddresses: notReadyAddrs, Ports: ports})
|
||||
}
|
||||
|
||||
// Finally, sort it.
|
||||
return SortSubsets(final)
|
||||
}
|
||||
|
||||
// The sets of hosts must be de-duped, using IP+UID as the key.
|
||||
type addressKey struct {
|
||||
ip string
|
||||
uid types.UID
|
||||
}
|
||||
|
||||
// mapAddressByPort adds an address into a map by its ports, 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
|
||||
// but may have come from different hosts, for attribution. For instance, Mesos
|
||||
// assigns pods the node IP, but the pods are distinct.
|
||||
key := addressKey{ip: addr.IP}
|
||||
if addr.TargetRef != nil {
|
||||
key.uid = addr.TargetRef.UID
|
||||
}
|
||||
|
||||
// Accumulate the address. The full EndpointAddress structure is preserved for use when
|
||||
// we rebuild the subsets so that the final TargetRef has all of the necessary data.
|
||||
existingAddress := allAddrs[key]
|
||||
if existingAddress == nil {
|
||||
// Make a copy so we don't write to the
|
||||
// input args of this function.
|
||||
existingAddress = &v1.EndpointAddress{}
|
||||
*existingAddress = *addr
|
||||
allAddrs[key] = existingAddress
|
||||
}
|
||||
|
||||
// Remember that this port maps to this address.
|
||||
if _, found := portToAddrReadyMap[port]; !found {
|
||||
portToAddrReadyMap[port] = addressSet{}
|
||||
}
|
||||
// if we have not yet recorded this port for this address, or if the previous
|
||||
// state was ready, write the current ready state. not ready always trumps
|
||||
// ready.
|
||||
if wasReady, found := portToAddrReadyMap[port][existingAddress]; !found || wasReady {
|
||||
portToAddrReadyMap[port][existingAddress] = ready
|
||||
}
|
||||
return existingAddress
|
||||
}
|
||||
|
||||
type addressSet map[*v1.EndpointAddress]bool
|
||||
|
||||
type addrReady struct {
|
||||
addr *v1.EndpointAddress
|
||||
ready bool
|
||||
}
|
||||
|
||||
func hashAddresses(addrs addressSet) string {
|
||||
// Flatten the list of addresses into a string so it can be used as a
|
||||
// map key. Unfortunately, DeepHashObject is implemented in terms of
|
||||
// spew, and spew does not handle non-primitive map keys well. So
|
||||
// first we collapse it into a slice, sort the slice, then hash that.
|
||||
slice := make([]addrReady, 0, len(addrs))
|
||||
for k, ready := range addrs {
|
||||
slice = append(slice, addrReady{k, ready})
|
||||
}
|
||||
sort.Sort(addrsReady(slice))
|
||||
hasher := md5.New()
|
||||
hashutil.DeepHashObject(hasher, slice)
|
||||
return hex.EncodeToString(hasher.Sum(nil)[0:])
|
||||
}
|
||||
|
||||
func lessAddrReady(a, b addrReady) bool {
|
||||
// ready is not significant to hashing since we can't have duplicate addresses
|
||||
return LessEndpointAddress(a.addr, b.addr)
|
||||
}
|
||||
|
||||
type addrsReady []addrReady
|
||||
|
||||
func (sl addrsReady) Len() int { return len(sl) }
|
||||
func (sl addrsReady) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl addrsReady) Less(i, j int) bool {
|
||||
return lessAddrReady(sl[i], sl[j])
|
||||
}
|
||||
|
||||
func LessEndpointAddress(a, b *v1.EndpointAddress) bool {
|
||||
ipComparison := bytes.Compare([]byte(a.IP), []byte(b.IP))
|
||||
if ipComparison != 0 {
|
||||
return ipComparison < 0
|
||||
}
|
||||
if b.TargetRef == nil {
|
||||
return false
|
||||
}
|
||||
if a.TargetRef == nil {
|
||||
return true
|
||||
}
|
||||
return a.TargetRef.UID < b.TargetRef.UID
|
||||
}
|
||||
|
||||
type addrPtrsByIpAndUID []*v1.EndpointAddress
|
||||
|
||||
func (sl addrPtrsByIpAndUID) Len() int { return len(sl) }
|
||||
func (sl addrPtrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl addrPtrsByIpAndUID) Less(i, j int) bool {
|
||||
return LessEndpointAddress(sl[i], sl[j])
|
||||
}
|
||||
|
||||
// SortSubsets sorts an array of EndpointSubset objects in place. For ease of
|
||||
// use it returns the input slice.
|
||||
func SortSubsets(subsets []v1.EndpointSubset) []v1.EndpointSubset {
|
||||
for i := range subsets {
|
||||
ss := &subsets[i]
|
||||
sort.Sort(addrsByIpAndUID(ss.Addresses))
|
||||
sort.Sort(addrsByIpAndUID(ss.NotReadyAddresses))
|
||||
sort.Sort(portsByHash(ss.Ports))
|
||||
}
|
||||
sort.Sort(subsetsByHash(subsets))
|
||||
return subsets
|
||||
}
|
||||
|
||||
func hashObject(hasher hash.Hash, obj interface{}) []byte {
|
||||
hashutil.DeepHashObject(hasher, obj)
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
type subsetsByHash []v1.EndpointSubset
|
||||
|
||||
func (sl subsetsByHash) Len() int { return len(sl) }
|
||||
func (sl subsetsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl subsetsByHash) Less(i, j int) bool {
|
||||
hasher := md5.New()
|
||||
h1 := hashObject(hasher, sl[i])
|
||||
h2 := hashObject(hasher, sl[j])
|
||||
return bytes.Compare(h1, h2) < 0
|
||||
}
|
||||
|
||||
type addrsByIpAndUID []v1.EndpointAddress
|
||||
|
||||
func (sl addrsByIpAndUID) Len() int { return len(sl) }
|
||||
func (sl addrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl addrsByIpAndUID) Less(i, j int) bool {
|
||||
return LessEndpointAddress(&sl[i], &sl[j])
|
||||
}
|
||||
|
||||
type portsByHash []v1.EndpointPort
|
||||
|
||||
func (sl portsByHash) Len() int { return len(sl) }
|
||||
func (sl portsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||
func (sl portsByHash) Less(i, j int) bool {
|
||||
hasher := md5.New()
|
||||
h1 := hashObject(hasher, sl[i])
|
||||
h2 := hashObject(hasher, sl[j])
|
||||
return bytes.Compare(h1, h2) < 0
|
||||
}
|
||||
464
vendor/k8s.io/kubernetes/pkg/api/v1/endpoints/util_test.go
generated
vendored
464
vendor/k8s.io/kubernetes/pkg/api/v1/endpoints/util_test.go
generated
vendored
|
|
@ -1,464 +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 endpoints
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
func podRef(uid string) *v1.ObjectReference {
|
||||
ref := v1.ObjectReference{UID: types.UID(uid)}
|
||||
return &ref
|
||||
}
|
||||
|
||||
func TestPackSubsets(t *testing.T) {
|
||||
// The downside of table-driven tests is that some things have to live outside the table.
|
||||
fooObjRef := v1.ObjectReference{Name: "foo"}
|
||||
barObjRef := v1.ObjectReference{Name: "bar"}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
given []v1.EndpointSubset
|
||||
expect []v1.EndpointSubset
|
||||
}{
|
||||
{
|
||||
name: "empty everything",
|
||||
given: []v1.EndpointSubset{{Addresses: []v1.EndpointAddress{}, Ports: []v1.EndpointPort{}}},
|
||||
expect: []v1.EndpointSubset{},
|
||||
}, {
|
||||
name: "empty addresses",
|
||||
given: []v1.EndpointSubset{{Addresses: []v1.EndpointAddress{}, Ports: []v1.EndpointPort{{Port: 111}}}},
|
||||
expect: []v1.EndpointSubset{},
|
||||
}, {
|
||||
name: "empty ports",
|
||||
given: []v1.EndpointSubset{{Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []v1.EndpointPort{}}},
|
||||
expect: []v1.EndpointSubset{},
|
||||
}, {
|
||||
name: "empty ports",
|
||||
given: []v1.EndpointSubset{{NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []v1.EndpointPort{}}},
|
||||
expect: []v1.EndpointSubset{},
|
||||
}, {
|
||||
name: "one set, one ip, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, one port (IPv6)",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "beef::1:2:3:4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "beef::1:2:3:4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one notReady ip, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, one UID, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one notReady ip, one UID, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, empty UID, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one notReady ip, empty UID, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, two ips, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, two mixed ips, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, two duplicate ips, one port, notReady is covered by ready",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup ips, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup ips, one port (IPv6)",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "beef::1"}, {IP: "beef::1"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "beef::1"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup ips with target-refs, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: &fooObjRef},
|
||||
{IP: "1.2.3.4", TargetRef: &barObjRef},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: &fooObjRef}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, dup mixed ips with target-refs, one port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: &fooObjRef},
|
||||
},
|
||||
NotReadyAddresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: &barObjRef},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
// finding the same address twice is considered an error on input, only the first address+port
|
||||
// reference is preserved
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: &fooObjRef}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "one set, one ip, dup ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup ip, dup port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup mixed ip, dup port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup ip, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup ip, dup uids, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}, {Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, dup mixed ip, dup uids, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two ips, dup port",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two set, dup ip, two uids, dup ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-2")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-1")},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-2")},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two set, dup ip, with and without uid, dup ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-2")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-2")},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two ips, two dup ip with uid, dup port, wrong order",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-1")},
|
||||
{IP: "5.6.7.8"},
|
||||
{IP: "5.6.7.8", TargetRef: podRef("uid-1")},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two mixed ips, two dup ip with uid, dup port, wrong order, ends up with split addresses",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "5.6.7.8", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{
|
||||
{IP: "5.6.7.8"},
|
||||
},
|
||||
NotReadyAddresses: []v1.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "1.2.3.4", TargetRef: podRef("uid-1")},
|
||||
{IP: "5.6.7.8", TargetRef: podRef("uid-1")},
|
||||
},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}},
|
||||
}, {
|
||||
name: "two sets, two ips, two ports",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}},
|
||||
}, {
|
||||
name: "four sets, three ips, three ports, jumbled",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.6"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 333}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.6"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}, {Port: 333}},
|
||||
}},
|
||||
}, {
|
||||
name: "four sets, three mixed ips, three ports, jumbled",
|
||||
given: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}},
|
||||
}, {
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.6"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 333}},
|
||||
}},
|
||||
expect: []v1.EndpointSubset{{
|
||||
Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.6"}},
|
||||
Ports: []v1.EndpointPort{{Port: 111}},
|
||||
}, {
|
||||
NotReadyAddresses: []v1.EndpointAddress{{IP: "1.2.3.5"}},
|
||||
Ports: []v1.EndpointPort{{Port: 222}, {Port: 333}},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
result := RepackSubsets(tc.given)
|
||||
if !reflect.DeepEqual(result, SortSubsets(tc.expect)) {
|
||||
t.Errorf("case %q: expected %s, got %s", tc.name, spew.Sprintf("%#v", SortSubsets(tc.expect)), spew.Sprintf("%#v", result))
|
||||
}
|
||||
}
|
||||
}
|
||||
45
vendor/k8s.io/kubernetes/pkg/api/v1/helper/qos/BUILD
generated
vendored
45
vendor/k8s.io/kubernetes/pkg/api/v1/helper/qos/BUILD
generated
vendored
|
|
@ -1,45 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["qos_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/helper/qos:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["qos.go"],
|
||||
deps = [
|
||||
"//pkg/api/v1/helper:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
98
vendor/k8s.io/kubernetes/pkg/api/v1/helper/qos/qos.go
generated
vendored
98
vendor/k8s.io/kubernetes/pkg/api/v1/helper/qos/qos.go
generated
vendored
|
|
@ -1,98 +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 qos
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
v1helper "k8s.io/kubernetes/pkg/api/v1/helper"
|
||||
)
|
||||
|
||||
// QOSList is a set of (resource name, QoS class) pairs.
|
||||
type QOSList map[v1.ResourceName]v1.PodQOSClass
|
||||
|
||||
func isSupportedQoSComputeResource(name v1.ResourceName) bool {
|
||||
supportedQoSComputeResources := sets.NewString(string(v1.ResourceCPU), string(v1.ResourceMemory))
|
||||
return supportedQoSComputeResources.Has(string(name)) || v1helper.IsHugePageResourceName(name)
|
||||
}
|
||||
|
||||
// GetPodQOS returns the QoS class of a pod.
|
||||
// A pod is besteffort if none of its containers have specified any requests or limits.
|
||||
// A pod is guaranteed only when requests and limits are specified for all the containers and they are equal.
|
||||
// A pod is burstable if limits and requests do not match across all containers.
|
||||
func GetPodQOS(pod *v1.Pod) v1.PodQOSClass {
|
||||
requests := v1.ResourceList{}
|
||||
limits := v1.ResourceList{}
|
||||
zeroQuantity := resource.MustParse("0")
|
||||
isGuaranteed := true
|
||||
for _, container := range pod.Spec.Containers {
|
||||
// process requests
|
||||
for name, quantity := range container.Resources.Requests {
|
||||
if !isSupportedQoSComputeResource(name) {
|
||||
continue
|
||||
}
|
||||
if quantity.Cmp(zeroQuantity) == 1 {
|
||||
delta := quantity.Copy()
|
||||
if _, exists := requests[name]; !exists {
|
||||
requests[name] = *delta
|
||||
} else {
|
||||
delta.Add(requests[name])
|
||||
requests[name] = *delta
|
||||
}
|
||||
}
|
||||
}
|
||||
// process limits
|
||||
qosLimitsFound := sets.NewString()
|
||||
for name, quantity := range container.Resources.Limits {
|
||||
if !isSupportedQoSComputeResource(name) {
|
||||
continue
|
||||
}
|
||||
if quantity.Cmp(zeroQuantity) == 1 {
|
||||
qosLimitsFound.Insert(string(name))
|
||||
delta := quantity.Copy()
|
||||
if _, exists := limits[name]; !exists {
|
||||
limits[name] = *delta
|
||||
} else {
|
||||
delta.Add(limits[name])
|
||||
limits[name] = *delta
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !qosLimitsFound.HasAll(string(v1.ResourceMemory), string(v1.ResourceCPU)) {
|
||||
isGuaranteed = false
|
||||
}
|
||||
}
|
||||
if len(requests) == 0 && len(limits) == 0 {
|
||||
return v1.PodQOSBestEffort
|
||||
}
|
||||
// Check is requests match limits for all resources.
|
||||
if isGuaranteed {
|
||||
for name, req := range requests {
|
||||
if lim, exists := limits[name]; !exists || lim.Cmp(req) != 0 {
|
||||
isGuaranteed = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if isGuaranteed &&
|
||||
len(requests) == len(limits) {
|
||||
return v1.PodQOSGuaranteed
|
||||
}
|
||||
return v1.PodQOSBurstable
|
||||
}
|
||||
194
vendor/k8s.io/kubernetes/pkg/api/v1/helper/qos/qos_test.go
generated
vendored
194
vendor/k8s.io/kubernetes/pkg/api/v1/helper/qos/qos_test.go
generated
vendored
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package qos
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/helper/qos"
|
||||
k8sv1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
func TestGetPodQOS(t *testing.T) {
|
||||
testCases := []struct {
|
||||
pod *v1.Pod
|
||||
expected v1.PodQOSClass
|
||||
}{
|
||||
{
|
||||
pod: newPod("guaranteed", []v1.Container{
|
||||
newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
|
||||
}),
|
||||
expected: v1.PodQOSGuaranteed,
|
||||
},
|
||||
{
|
||||
pod: newPod("guaranteed-with-gpu", []v1.Container{
|
||||
newContainer("guaranteed", getResourceList("100m", "100Mi"), addResource("nvidia-gpu", "2", getResourceList("100m", "100Mi"))),
|
||||
}),
|
||||
expected: v1.PodQOSGuaranteed,
|
||||
},
|
||||
{
|
||||
pod: newPod("guaranteed-guaranteed", []v1.Container{
|
||||
newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
|
||||
newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
|
||||
}),
|
||||
expected: v1.PodQOSGuaranteed,
|
||||
},
|
||||
{
|
||||
pod: newPod("guaranteed-guaranteed-with-gpu", []v1.Container{
|
||||
newContainer("guaranteed", getResourceList("100m", "100Mi"), addResource("nvidia-gpu", "2", getResourceList("100m", "100Mi"))),
|
||||
newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
|
||||
}),
|
||||
expected: v1.PodQOSGuaranteed,
|
||||
},
|
||||
{
|
||||
pod: newPod("best-effort-best-effort", []v1.Container{
|
||||
newContainer("best-effort", getResourceList("", ""), getResourceList("", "")),
|
||||
newContainer("best-effort", getResourceList("", ""), getResourceList("", "")),
|
||||
}),
|
||||
expected: v1.PodQOSBestEffort,
|
||||
},
|
||||
{
|
||||
pod: newPod("best-effort-best-effort-with-gpu", []v1.Container{
|
||||
newContainer("best-effort", getResourceList("", ""), addResource("nvidia-gpu", "2", getResourceList("", ""))),
|
||||
newContainer("best-effort", getResourceList("", ""), getResourceList("", "")),
|
||||
}),
|
||||
expected: v1.PodQOSBestEffort,
|
||||
},
|
||||
{
|
||||
pod: newPod("best-effort-with-gpu", []v1.Container{
|
||||
newContainer("best-effort", getResourceList("", ""), addResource("nvidia-gpu", "2", getResourceList("", ""))),
|
||||
}),
|
||||
expected: v1.PodQOSBestEffort,
|
||||
},
|
||||
{
|
||||
pod: newPod("best-effort-burstable", []v1.Container{
|
||||
newContainer("best-effort", getResourceList("", ""), addResource("nvidia-gpu", "2", getResourceList("", ""))),
|
||||
newContainer("burstable", getResourceList("1", ""), getResourceList("2", "")),
|
||||
}),
|
||||
expected: v1.PodQOSBurstable,
|
||||
},
|
||||
{
|
||||
pod: newPod("best-effort-guaranteed", []v1.Container{
|
||||
newContainer("best-effort", getResourceList("", ""), addResource("nvidia-gpu", "2", getResourceList("", ""))),
|
||||
newContainer("guaranteed", getResourceList("10m", "100Mi"), getResourceList("10m", "100Mi")),
|
||||
}),
|
||||
expected: v1.PodQOSBurstable,
|
||||
},
|
||||
{
|
||||
pod: newPod("burstable-cpu-guaranteed-memory", []v1.Container{
|
||||
newContainer("burstable", getResourceList("", "100Mi"), getResourceList("", "100Mi")),
|
||||
}),
|
||||
expected: v1.PodQOSBurstable,
|
||||
},
|
||||
{
|
||||
pod: newPod("burstable-no-limits", []v1.Container{
|
||||
newContainer("burstable", getResourceList("100m", "100Mi"), getResourceList("", "")),
|
||||
}),
|
||||
expected: v1.PodQOSBurstable,
|
||||
},
|
||||
{
|
||||
pod: newPod("burstable-guaranteed", []v1.Container{
|
||||
newContainer("burstable", getResourceList("1", "100Mi"), getResourceList("2", "100Mi")),
|
||||
newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
|
||||
}),
|
||||
expected: v1.PodQOSBurstable,
|
||||
},
|
||||
{
|
||||
pod: newPod("burstable-unbounded-but-requests-match-limits", []v1.Container{
|
||||
newContainer("burstable", getResourceList("100m", "100Mi"), getResourceList("200m", "200Mi")),
|
||||
newContainer("burstable-unbounded", getResourceList("100m", "100Mi"), getResourceList("", "")),
|
||||
}),
|
||||
expected: v1.PodQOSBurstable,
|
||||
},
|
||||
{
|
||||
pod: newPod("burstable-1", []v1.Container{
|
||||
newContainer("burstable", getResourceList("10m", "100Mi"), getResourceList("100m", "200Mi")),
|
||||
}),
|
||||
expected: v1.PodQOSBurstable,
|
||||
},
|
||||
{
|
||||
pod: newPod("burstable-2", []v1.Container{
|
||||
newContainer("burstable", getResourceList("0", "0"), addResource("nvidia-gpu", "2", getResourceList("100m", "200Mi"))),
|
||||
}),
|
||||
expected: v1.PodQOSBurstable,
|
||||
},
|
||||
{
|
||||
pod: newPod("burstable-hugepages", []v1.Container{
|
||||
newContainer("burstable", addResource("hugepages-2Mi", "1Gi", getResourceList("0", "0")), addResource("hugepages-2Mi", "1Gi", getResourceList("0", "0"))),
|
||||
}),
|
||||
expected: v1.PodQOSBurstable,
|
||||
},
|
||||
}
|
||||
for id, testCase := range testCases {
|
||||
if actual := GetPodQOS(testCase.pod); testCase.expected != actual {
|
||||
t.Errorf("[%d]: invalid qos pod %s, expected: %s, actual: %s", id, testCase.pod.Name, testCase.expected, actual)
|
||||
}
|
||||
|
||||
// Convert v1.Pod to api.Pod, and then check against `api.helper.GetPodQOS`.
|
||||
pod := api.Pod{}
|
||||
k8sv1.Convert_v1_Pod_To_api_Pod(testCase.pod, &pod, nil)
|
||||
|
||||
if actual := qos.GetPodQOS(&pod); api.PodQOSClass(testCase.expected) != actual {
|
||||
t.Errorf("[%d]: conversion invalid qos pod %s, expected: %s, actual: %s", id, testCase.pod.Name, testCase.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getResourceList(cpu, memory string) v1.ResourceList {
|
||||
res := v1.ResourceList{}
|
||||
if cpu != "" {
|
||||
res[v1.ResourceCPU] = resource.MustParse(cpu)
|
||||
}
|
||||
if memory != "" {
|
||||
res[v1.ResourceMemory] = resource.MustParse(memory)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func addResource(rName, value string, rl v1.ResourceList) v1.ResourceList {
|
||||
rl[v1.ResourceName(rName)] = resource.MustParse(value)
|
||||
return rl
|
||||
}
|
||||
|
||||
func getResourceRequirements(requests, limits v1.ResourceList) v1.ResourceRequirements {
|
||||
res := v1.ResourceRequirements{}
|
||||
res.Requests = requests
|
||||
res.Limits = limits
|
||||
return res
|
||||
}
|
||||
|
||||
func newContainer(name string, requests v1.ResourceList, limits v1.ResourceList) v1.Container {
|
||||
return v1.Container{
|
||||
Name: name,
|
||||
Resources: getResourceRequirements(requests, limits),
|
||||
}
|
||||
}
|
||||
|
||||
func newPod(name string, containers []v1.Container) *v1.Pod {
|
||||
return &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: containers,
|
||||
},
|
||||
}
|
||||
}
|
||||
25
vendor/k8s.io/kubernetes/pkg/api/v1/node/BUILD
generated
vendored
25
vendor/k8s.io/kubernetes/pkg/api/v1/node/BUILD
generated
vendored
|
|
@ -1,25 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["util.go"],
|
||||
deps = ["//vendor/k8s.io/api/core/v1:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
47
vendor/k8s.io/kubernetes/pkg/api/v1/node/util.go
generated
vendored
47
vendor/k8s.io/kubernetes/pkg/api/v1/node/util.go
generated
vendored
|
|
@ -1,47 +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.
|
||||
*/
|
||||
|
||||
// TODO: merge with pkg/util/node
|
||||
|
||||
package node
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// GetNodeCondition extracts the provided condition from the given status and returns that.
|
||||
// Returns nil and -1 if the condition is not present, and the index of the located condition.
|
||||
func GetNodeCondition(status *v1.NodeStatus, conditionType v1.NodeConditionType) (int, *v1.NodeCondition) {
|
||||
if status == nil {
|
||||
return -1, nil
|
||||
}
|
||||
for i := range status.Conditions {
|
||||
if status.Conditions[i].Type == conditionType {
|
||||
return i, &status.Conditions[i]
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// IsNodeReady returns true if a node is ready; false otherwise.
|
||||
func IsNodeReady(node *v1.Node) bool {
|
||||
for _, c := range node.Status.Conditions {
|
||||
if c.Type == v1.NodeReady {
|
||||
return c.Status == v1.ConditionTrue
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
40
vendor/k8s.io/kubernetes/pkg/api/v1/resource/BUILD
generated
vendored
40
vendor/k8s.io/kubernetes/pkg/api/v1/resource/BUILD
generated
vendored
|
|
@ -1,40 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
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",
|
||||
deps = [
|
||||
"//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",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["helpers.go"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
206
vendor/k8s.io/kubernetes/pkg/api/v1/resource/helpers.go
generated
vendored
206
vendor/k8s.io/kubernetes/pkg/api/v1/resource/helpers.go
generated
vendored
|
|
@ -1,206 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resource
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"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
|
||||
}
|
||||
}
|
||||
for name, quantity := range container.Resources.Limits {
|
||||
if value, ok := limits[name]; !ok {
|
||||
limits[name] = *quantity.Copy()
|
||||
} else {
|
||||
value.Add(quantity)
|
||||
limits[name] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// finds and returns the request for a specific resource.
|
||||
func GetResourceRequest(pod *v1.Pod, resource v1.ResourceName) int64 {
|
||||
if resource == v1.ResourcePods {
|
||||
return 1
|
||||
}
|
||||
totalResources := int64(0)
|
||||
for _, container := range pod.Spec.Containers {
|
||||
if rQuantity, ok := container.Resources.Requests[resource]; ok {
|
||||
if resource == v1.ResourceCPU {
|
||||
totalResources += rQuantity.MilliValue()
|
||||
} else {
|
||||
totalResources += rQuantity.Value()
|
||||
}
|
||||
}
|
||||
}
|
||||
// take max_resource(sum_pod, any_init_container)
|
||||
for _, container := range pod.Spec.InitContainers {
|
||||
if rQuantity, ok := container.Resources.Requests[resource]; ok {
|
||||
if resource == v1.ResourceCPU && rQuantity.MilliValue() > totalResources {
|
||||
totalResources = rQuantity.MilliValue()
|
||||
} else if rQuantity.Value() > totalResources {
|
||||
totalResources = rQuantity.Value()
|
||||
}
|
||||
}
|
||||
}
|
||||
return totalResources
|
||||
}
|
||||
|
||||
// ExtractResourceValueByContainerName extracts the value of a resource
|
||||
// by providing container name
|
||||
func ExtractResourceValueByContainerName(fs *v1.ResourceFieldSelector, pod *v1.Pod, containerName string) (string, error) {
|
||||
container, err := findContainerInPod(pod, containerName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ExtractContainerResourceValue(fs, container)
|
||||
}
|
||||
|
||||
type deepCopier interface {
|
||||
DeepCopy(interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
// ExtractResourceValueByContainerNameAndNodeAllocatable extracts the value of a resource
|
||||
// by providing container name and node allocatable
|
||||
func ExtractResourceValueByContainerNameAndNodeAllocatable(copier deepCopier, fs *v1.ResourceFieldSelector, pod *v1.Pod, containerName string, nodeAllocatable v1.ResourceList) (string, error) {
|
||||
realContainer, err := findContainerInPod(pod, containerName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
container := realContainer.DeepCopy()
|
||||
|
||||
MergeContainerResourceLimits(container, nodeAllocatable)
|
||||
|
||||
return ExtractContainerResourceValue(fs, container)
|
||||
}
|
||||
|
||||
// ExtractContainerResourceValue extracts the value of a resource
|
||||
// in an already known container
|
||||
func ExtractContainerResourceValue(fs *v1.ResourceFieldSelector, container *v1.Container) (string, error) {
|
||||
divisor := resource.Quantity{}
|
||||
if divisor.Cmp(fs.Divisor) == 0 {
|
||||
divisor = resource.MustParse("1")
|
||||
} else {
|
||||
divisor = fs.Divisor
|
||||
}
|
||||
|
||||
switch fs.Resource {
|
||||
case "limits.cpu":
|
||||
return convertResourceCPUToString(container.Resources.Limits.Cpu(), divisor)
|
||||
case "limits.memory":
|
||||
return convertResourceMemoryToString(container.Resources.Limits.Memory(), divisor)
|
||||
case "limits.ephemeral-storage":
|
||||
return convertResourceEphemeralStorageToString(container.Resources.Limits.StorageEphemeral(), divisor)
|
||||
case "requests.cpu":
|
||||
return convertResourceCPUToString(container.Resources.Requests.Cpu(), divisor)
|
||||
case "requests.memory":
|
||||
return convertResourceMemoryToString(container.Resources.Requests.Memory(), divisor)
|
||||
case "requests.ephemeral-storage":
|
||||
return convertResourceEphemeralStorageToString(container.Resources.Requests.StorageEphemeral(), divisor)
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Unsupported container resource : %v", fs.Resource)
|
||||
}
|
||||
|
||||
// convertResourceCPUToString converts cpu value to the format of divisor and returns
|
||||
// ceiling of the value.
|
||||
func convertResourceCPUToString(cpu *resource.Quantity, divisor resource.Quantity) (string, error) {
|
||||
c := int64(math.Ceil(float64(cpu.MilliValue()) / float64(divisor.MilliValue())))
|
||||
return strconv.FormatInt(c, 10), nil
|
||||
}
|
||||
|
||||
// convertResourceMemoryToString converts memory value to the format of divisor and returns
|
||||
// ceiling of the value.
|
||||
func convertResourceMemoryToString(memory *resource.Quantity, divisor resource.Quantity) (string, error) {
|
||||
m := int64(math.Ceil(float64(memory.Value()) / float64(divisor.Value())))
|
||||
return strconv.FormatInt(m, 10), nil
|
||||
}
|
||||
|
||||
// convertResourceEphemeralStorageToString converts ephemeral storage value to the format of divisor and returns
|
||||
// ceiling of the value.
|
||||
func convertResourceEphemeralStorageToString(ephemeralStorage *resource.Quantity, divisor resource.Quantity) (string, error) {
|
||||
m := int64(math.Ceil(float64(ephemeralStorage.Value()) / float64(divisor.Value())))
|
||||
return strconv.FormatInt(m, 10), nil
|
||||
}
|
||||
|
||||
// findContainerInPod finds a container by its name in the provided pod
|
||||
func findContainerInPod(pod *v1.Pod, containerName string) (*v1.Container, error) {
|
||||
for _, container := range pod.Spec.Containers {
|
||||
if container.Name == containerName {
|
||||
return &container, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("container %s not found", containerName)
|
||||
}
|
||||
|
||||
// MergeContainerResourceLimits checks if a limit is applied for
|
||||
// the container, and if not, it sets the limit to the passed resource list.
|
||||
func MergeContainerResourceLimits(container *v1.Container,
|
||||
allocatable v1.ResourceList) {
|
||||
if container.Resources.Limits == nil {
|
||||
container.Resources.Limits = make(v1.ResourceList)
|
||||
}
|
||||
for _, resource := range []v1.ResourceName{v1.ResourceCPU, v1.ResourceMemory} {
|
||||
if quantity, exists := container.Resources.Limits[resource]; !exists || quantity.IsZero() {
|
||||
if cap, exists := allocatable[resource]; exists {
|
||||
container.Resources.Limits[resource] = *cap.Copy()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
180
vendor/k8s.io/kubernetes/pkg/api/v1/resource/helpers_test.go
generated
vendored
180
vendor/k8s.io/kubernetes/pkg/api/v1/resource/helpers_test.go
generated
vendored
|
|
@ -1,180 +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 resource
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
)
|
||||
|
||||
func TestResourceHelpers(t *testing.T) {
|
||||
cpuLimit := resource.MustParse("10")
|
||||
memoryLimit := resource.MustParse("10G")
|
||||
resourceSpec := v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceCPU: cpuLimit,
|
||||
v1.ResourceMemory: memoryLimit,
|
||||
},
|
||||
}
|
||||
if res := resourceSpec.Limits.Cpu(); res.Cmp(cpuLimit) != 0 {
|
||||
t.Errorf("expected cpulimit %v, got %v", cpuLimit, res)
|
||||
}
|
||||
if res := resourceSpec.Limits.Memory(); res.Cmp(memoryLimit) != 0 {
|
||||
t.Errorf("expected memorylimit %v, got %v", memoryLimit, res)
|
||||
}
|
||||
resourceSpec = v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceMemory: memoryLimit,
|
||||
},
|
||||
}
|
||||
if res := resourceSpec.Limits.Cpu(); res.Value() != 0 {
|
||||
t.Errorf("expected cpulimit %v, got %v", 0, res)
|
||||
}
|
||||
if res := resourceSpec.Limits.Memory(); res.Cmp(memoryLimit) != 0 {
|
||||
t.Errorf("expected memorylimit %v, got %v", memoryLimit, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultResourceHelpers(t *testing.T) {
|
||||
resourceList := v1.ResourceList{}
|
||||
if resourceList.Cpu().Format != resource.DecimalSI {
|
||||
t.Errorf("expected %v, actual %v", resource.DecimalSI, resourceList.Cpu().Format)
|
||||
}
|
||||
if resourceList.Memory().Format != resource.BinarySI {
|
||||
t.Errorf("expected %v, actual %v", resource.BinarySI, resourceList.Memory().Format)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractResourceValue(t *testing.T) {
|
||||
cases := []struct {
|
||||
fs *v1.ResourceFieldSelector
|
||||
pod *v1.Pod
|
||||
cName string
|
||||
expectedValue string
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
fs: &v1.ResourceFieldSelector{
|
||||
Resource: "limits.cpu",
|
||||
},
|
||||
cName: "foo",
|
||||
pod: getPod("foo", "", "9", "", ""),
|
||||
expectedValue: "9",
|
||||
},
|
||||
{
|
||||
fs: &v1.ResourceFieldSelector{
|
||||
Resource: "requests.cpu",
|
||||
},
|
||||
cName: "foo",
|
||||
pod: getPod("foo", "", "", "", ""),
|
||||
expectedValue: "0",
|
||||
},
|
||||
{
|
||||
fs: &v1.ResourceFieldSelector{
|
||||
Resource: "requests.cpu",
|
||||
},
|
||||
cName: "foo",
|
||||
pod: getPod("foo", "8", "", "", ""),
|
||||
expectedValue: "8",
|
||||
},
|
||||
{
|
||||
fs: &v1.ResourceFieldSelector{
|
||||
Resource: "requests.cpu",
|
||||
},
|
||||
cName: "foo",
|
||||
pod: getPod("foo", "100m", "", "", ""),
|
||||
expectedValue: "1",
|
||||
},
|
||||
{
|
||||
fs: &v1.ResourceFieldSelector{
|
||||
Resource: "requests.cpu",
|
||||
Divisor: resource.MustParse("100m"),
|
||||
},
|
||||
cName: "foo",
|
||||
pod: getPod("foo", "1200m", "", "", ""),
|
||||
expectedValue: "12",
|
||||
},
|
||||
{
|
||||
fs: &v1.ResourceFieldSelector{
|
||||
Resource: "requests.memory",
|
||||
},
|
||||
cName: "foo",
|
||||
pod: getPod("foo", "", "", "100Mi", ""),
|
||||
expectedValue: "104857600",
|
||||
},
|
||||
{
|
||||
fs: &v1.ResourceFieldSelector{
|
||||
Resource: "requests.memory",
|
||||
Divisor: resource.MustParse("1Mi"),
|
||||
},
|
||||
cName: "foo",
|
||||
pod: getPod("foo", "", "", "100Mi", "1Gi"),
|
||||
expectedValue: "100",
|
||||
},
|
||||
{
|
||||
fs: &v1.ResourceFieldSelector{
|
||||
Resource: "limits.memory",
|
||||
},
|
||||
cName: "foo",
|
||||
pod: getPod("foo", "", "", "10Mi", "100Mi"),
|
||||
expectedValue: "104857600",
|
||||
},
|
||||
}
|
||||
as := assert.New(t)
|
||||
for idx, tc := range cases {
|
||||
actual, err := ExtractResourceValueByContainerName(tc.fs, tc.pod, tc.cName)
|
||||
if tc.expectedError != nil {
|
||||
as.Equal(tc.expectedError, err, "expected test case [%d] to fail with error %v; got %v", idx, tc.expectedError, err)
|
||||
} else {
|
||||
as.Nil(err, "expected test case [%d] to not return an error; got %v", idx, err)
|
||||
as.Equal(tc.expectedValue, actual, "expected test case [%d] to return %q; got %q instead", idx, tc.expectedValue, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getPod(cname, cpuRequest, cpuLimit, memoryRequest, memoryLimit string) *v1.Pod {
|
||||
resources := v1.ResourceRequirements{
|
||||
Limits: make(v1.ResourceList),
|
||||
Requests: make(v1.ResourceList),
|
||||
}
|
||||
if cpuLimit != "" {
|
||||
resources.Limits[v1.ResourceCPU] = resource.MustParse(cpuLimit)
|
||||
}
|
||||
if memoryLimit != "" {
|
||||
resources.Limits[v1.ResourceMemory] = resource.MustParse(memoryLimit)
|
||||
}
|
||||
if cpuRequest != "" {
|
||||
resources.Requests[v1.ResourceCPU] = resource.MustParse(cpuRequest)
|
||||
}
|
||||
if memoryRequest != "" {
|
||||
resources.Requests[v1.ResourceMemory] = resource.MustParse(memoryRequest)
|
||||
}
|
||||
return &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: cname,
|
||||
Resources: resources,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
39
vendor/k8s.io/kubernetes/pkg/api/v1/service/BUILD
generated
vendored
39
vendor/k8s.io/kubernetes/pkg/api/v1/service/BUILD
generated
vendored
|
|
@ -1,39 +0,0 @@
|
|||
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"],
|
||||
deps = [
|
||||
"//pkg/util/net/sets:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/util/net/sets:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
97
vendor/k8s.io/kubernetes/pkg/api/v1/service/util.go
generated
vendored
97
vendor/k8s.io/kubernetes/pkg/api/v1/service/util.go
generated
vendored
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
netsets "k8s.io/kubernetes/pkg/util/net/sets"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultLoadBalancerSourceRanges = "0.0.0.0/0"
|
||||
)
|
||||
|
||||
// IsAllowAll checks whether the netsets.IPNet allows traffic from 0.0.0.0/0
|
||||
func IsAllowAll(ipnets netsets.IPNet) bool {
|
||||
for _, s := range ipnets.StringSlice() {
|
||||
if s == "0.0.0.0/0" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetLoadBalancerSourceRanges first try to parse and verify LoadBalancerSourceRanges field from a service.
|
||||
// If the field is not specified, turn to parse and verify the AnnotationLoadBalancerSourceRangesKey annotation from a service,
|
||||
// extracting the source ranges to allow, and if not present returns a default (allow-all) value.
|
||||
func GetLoadBalancerSourceRanges(service *v1.Service) (netsets.IPNet, error) {
|
||||
var ipnets netsets.IPNet
|
||||
var err error
|
||||
// if SourceRange field is specified, ignore sourceRange annotation
|
||||
if len(service.Spec.LoadBalancerSourceRanges) > 0 {
|
||||
specs := service.Spec.LoadBalancerSourceRanges
|
||||
ipnets, err = netsets.ParseIPNets(specs...)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("service.Spec.LoadBalancerSourceRanges: %v is not valid. Expecting a list of IP ranges. For example, 10.0.0.0/24. Error msg: %v", specs, err)
|
||||
}
|
||||
} else {
|
||||
val := service.Annotations[v1.AnnotationLoadBalancerSourceRangesKey]
|
||||
val = strings.TrimSpace(val)
|
||||
if val == "" {
|
||||
val = defaultLoadBalancerSourceRanges
|
||||
}
|
||||
specs := strings.Split(val, ",")
|
||||
ipnets, err = netsets.ParseIPNets(specs...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %s is not valid. Expecting a comma-separated list of source IP ranges. For example, 10.0.0.0/24,192.168.2.0/24", v1.AnnotationLoadBalancerSourceRangesKey, val)
|
||||
}
|
||||
}
|
||||
return ipnets, nil
|
||||
}
|
||||
|
||||
// RequestsOnlyLocalTraffic checks if service requests OnlyLocal traffic.
|
||||
func RequestsOnlyLocalTraffic(service *v1.Service) bool {
|
||||
if service.Spec.Type != v1.ServiceTypeLoadBalancer &&
|
||||
service.Spec.Type != v1.ServiceTypeNodePort {
|
||||
return false
|
||||
}
|
||||
return service.Spec.ExternalTrafficPolicy == v1.ServiceExternalTrafficPolicyTypeLocal
|
||||
}
|
||||
|
||||
// NeedsHealthCheck checks if service needs health check.
|
||||
func NeedsHealthCheck(service *v1.Service) bool {
|
||||
if service.Spec.Type != v1.ServiceTypeLoadBalancer {
|
||||
return false
|
||||
}
|
||||
return RequestsOnlyLocalTraffic(service)
|
||||
}
|
||||
|
||||
// GetServiceHealthCheckPathPort returns the path and nodePort programmed into the Cloud LB Health Check
|
||||
func GetServiceHealthCheckPathPort(service *v1.Service) (string, int32) {
|
||||
if !NeedsHealthCheck(service) {
|
||||
return "", 0
|
||||
}
|
||||
port := service.Spec.HealthCheckNodePort
|
||||
if port == 0 {
|
||||
return "", 0
|
||||
}
|
||||
return "/healthz", port
|
||||
}
|
||||
216
vendor/k8s.io/kubernetes/pkg/api/v1/service/util_test.go
generated
vendored
216
vendor/k8s.io/kubernetes/pkg/api/v1/service/util_test.go
generated
vendored
|
|
@ -1,216 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
netsets "k8s.io/kubernetes/pkg/util/net/sets"
|
||||
)
|
||||
|
||||
func TestGetLoadBalancerSourceRanges(t *testing.T) {
|
||||
checkError := func(v string) {
|
||||
annotations := make(map[string]string)
|
||||
annotations[v1.AnnotationLoadBalancerSourceRangesKey] = v
|
||||
svc := v1.Service{}
|
||||
svc.Annotations = annotations
|
||||
_, err := GetLoadBalancerSourceRanges(&svc)
|
||||
if err == nil {
|
||||
t.Errorf("Expected error parsing: %q", v)
|
||||
}
|
||||
svc = v1.Service{}
|
||||
svc.Spec.LoadBalancerSourceRanges = strings.Split(v, ",")
|
||||
_, err = GetLoadBalancerSourceRanges(&svc)
|
||||
if err == nil {
|
||||
t.Errorf("Expected error parsing: %q", v)
|
||||
}
|
||||
}
|
||||
checkError("10.0.0.1/33")
|
||||
checkError("foo.bar")
|
||||
checkError("10.0.0.1/32,*")
|
||||
checkError("10.0.0.1/32,")
|
||||
checkError("10.0.0.1/32, ")
|
||||
checkError("10.0.0.1")
|
||||
|
||||
checkOK := func(v string) netsets.IPNet {
|
||||
annotations := make(map[string]string)
|
||||
annotations[v1.AnnotationLoadBalancerSourceRangesKey] = v
|
||||
svc := v1.Service{}
|
||||
svc.Annotations = annotations
|
||||
cidrs, err := GetLoadBalancerSourceRanges(&svc)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error parsing: %q", v)
|
||||
}
|
||||
svc = v1.Service{}
|
||||
svc.Spec.LoadBalancerSourceRanges = strings.Split(v, ",")
|
||||
cidrs, err = GetLoadBalancerSourceRanges(&svc)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error parsing: %q", v)
|
||||
}
|
||||
return cidrs
|
||||
}
|
||||
cidrs := checkOK("192.168.0.1/32")
|
||||
if len(cidrs) != 1 {
|
||||
t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice())
|
||||
}
|
||||
cidrs = checkOK("192.168.0.1/32,192.168.0.1/32")
|
||||
if len(cidrs) != 1 {
|
||||
t.Errorf("Expected exactly one CIDR (after de-dup): %v", cidrs.StringSlice())
|
||||
}
|
||||
cidrs = checkOK("192.168.0.1/32,192.168.0.2/32")
|
||||
if len(cidrs) != 2 {
|
||||
t.Errorf("Expected two CIDRs: %v", cidrs.StringSlice())
|
||||
}
|
||||
cidrs = checkOK(" 192.168.0.1/32 , 192.168.0.2/32 ")
|
||||
if len(cidrs) != 2 {
|
||||
t.Errorf("Expected two CIDRs: %v", cidrs.StringSlice())
|
||||
}
|
||||
// check LoadBalancerSourceRanges not specified
|
||||
svc := v1.Service{}
|
||||
cidrs, err := GetLoadBalancerSourceRanges(&svc)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if len(cidrs) != 1 {
|
||||
t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice())
|
||||
}
|
||||
if !IsAllowAll(cidrs) {
|
||||
t.Errorf("Expected default to be allow-all: %v", cidrs.StringSlice())
|
||||
}
|
||||
// check SourceRanges annotation is empty
|
||||
annotations := make(map[string]string)
|
||||
annotations[v1.AnnotationLoadBalancerSourceRangesKey] = ""
|
||||
svc = v1.Service{}
|
||||
svc.Annotations = annotations
|
||||
cidrs, err = GetLoadBalancerSourceRanges(&svc)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if len(cidrs) != 1 {
|
||||
t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice())
|
||||
}
|
||||
if !IsAllowAll(cidrs) {
|
||||
t.Errorf("Expected default to be allow-all: %v", cidrs.StringSlice())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllowAll(t *testing.T) {
|
||||
checkAllowAll := func(allowAll bool, cidrs ...string) {
|
||||
ipnets, err := netsets.ParseIPNets(cidrs...)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error parsing cidrs: %v", cidrs)
|
||||
}
|
||||
if allowAll != IsAllowAll(ipnets) {
|
||||
t.Errorf("IsAllowAll did not return expected value for %v", cidrs)
|
||||
}
|
||||
}
|
||||
checkAllowAll(false, "10.0.0.1/32")
|
||||
checkAllowAll(false, "10.0.0.1/32", "10.0.0.2/32")
|
||||
checkAllowAll(false, "10.0.0.1/32", "10.0.0.1/32")
|
||||
|
||||
checkAllowAll(true, "0.0.0.0/0")
|
||||
checkAllowAll(true, "192.168.0.0/0")
|
||||
checkAllowAll(true, "192.168.0.1/32", "0.0.0.0/0")
|
||||
}
|
||||
|
||||
func TestRequestsOnlyLocalTraffic(t *testing.T) {
|
||||
checkRequestsOnlyLocalTraffic := func(requestsOnlyLocalTraffic bool, service *v1.Service) {
|
||||
res := RequestsOnlyLocalTraffic(service)
|
||||
if res != requestsOnlyLocalTraffic {
|
||||
t.Errorf("Expected requests OnlyLocal traffic = %v, got %v",
|
||||
requestsOnlyLocalTraffic, res)
|
||||
}
|
||||
}
|
||||
|
||||
checkRequestsOnlyLocalTraffic(false, &v1.Service{})
|
||||
checkRequestsOnlyLocalTraffic(false, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeClusterIP,
|
||||
},
|
||||
})
|
||||
checkRequestsOnlyLocalTraffic(false, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeNodePort,
|
||||
},
|
||||
})
|
||||
checkRequestsOnlyLocalTraffic(false, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeNodePort,
|
||||
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeCluster,
|
||||
},
|
||||
})
|
||||
checkRequestsOnlyLocalTraffic(true, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeNodePort,
|
||||
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeLocal,
|
||||
},
|
||||
})
|
||||
checkRequestsOnlyLocalTraffic(false, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeLoadBalancer,
|
||||
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeCluster,
|
||||
},
|
||||
})
|
||||
checkRequestsOnlyLocalTraffic(true, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeLoadBalancer,
|
||||
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeLocal,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestNeedsHealthCheck(t *testing.T) {
|
||||
checkNeedsHealthCheck := func(needsHealthCheck bool, service *v1.Service) {
|
||||
res := NeedsHealthCheck(service)
|
||||
if res != needsHealthCheck {
|
||||
t.Errorf("Expected needs health check = %v, got %v",
|
||||
needsHealthCheck, res)
|
||||
}
|
||||
}
|
||||
|
||||
checkNeedsHealthCheck(false, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeClusterIP,
|
||||
},
|
||||
})
|
||||
checkNeedsHealthCheck(false, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeNodePort,
|
||||
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeCluster,
|
||||
},
|
||||
})
|
||||
checkNeedsHealthCheck(false, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeNodePort,
|
||||
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeLocal,
|
||||
},
|
||||
})
|
||||
checkNeedsHealthCheck(false, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeLoadBalancer,
|
||||
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeCluster,
|
||||
},
|
||||
})
|
||||
checkNeedsHealthCheck(true, &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
Type: v1.ServiceTypeLoadBalancer,
|
||||
ExternalTrafficPolicy: v1.ServiceExternalTrafficPolicyTypeLocal,
|
||||
},
|
||||
})
|
||||
}
|
||||
47
vendor/k8s.io/kubernetes/pkg/api/v1/validation/BUILD
generated
vendored
47
vendor/k8s.io/kubernetes/pkg/api/v1/validation/BUILD
generated
vendored
|
|
@ -1,47 +0,0 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["validation.go"],
|
||||
deps = [
|
||||
"//pkg/api/helper:go_default_library",
|
||||
"//pkg/api/v1/helper:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
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 = ["validation_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
||||
171
vendor/k8s.io/kubernetes/pkg/api/v1/validation/validation.go
generated
vendored
171
vendor/k8s.io/kubernetes/pkg/api/v1/validation/validation.go
generated
vendored
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api/helper"
|
||||
v1helper "k8s.io/kubernetes/pkg/api/v1/helper"
|
||||
)
|
||||
|
||||
const isNegativeErrorMsg string = `must be greater than or equal to 0`
|
||||
const isNotIntegerErrorMsg string = `must be an integer`
|
||||
|
||||
func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
limPath := fldPath.Child("limits")
|
||||
reqPath := fldPath.Child("requests")
|
||||
for resourceName, quantity := range requirements.Limits {
|
||||
fldPath := limPath.Key(string(resourceName))
|
||||
// Validate resource name.
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...)
|
||||
|
||||
// Validate resource quantity.
|
||||
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
|
||||
|
||||
}
|
||||
for resourceName, quantity := range requirements.Requests {
|
||||
fldPath := reqPath.Key(string(resourceName))
|
||||
// Validate resource name.
|
||||
allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...)
|
||||
// Validate resource quantity.
|
||||
allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...)
|
||||
|
||||
// Check that request <= limit.
|
||||
limitQuantity, exists := requirements.Limits[resourceName]
|
||||
if exists {
|
||||
// For GPUs, not only requests can't exceed limits, they also can't be lower, i.e. must be equal.
|
||||
if quantity.Cmp(limitQuantity) != 0 && !v1helper.IsOvercommitAllowed(resourceName) {
|
||||
allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s limit", resourceName)))
|
||||
} else if quantity.Cmp(limitQuantity) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be less than or equal to %s limit", resourceName)))
|
||||
}
|
||||
} else if resourceName == v1.ResourceNvidiaGPU {
|
||||
allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s request", v1.ResourceNvidiaGPU)))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateContainerResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := validateResourceName(value, fldPath)
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !helper.IsStandardContainerResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource for containers"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateResourceQuantityValue enforces that specified quantity is valid for specified resource
|
||||
func ValidateResourceQuantityValue(resource string, value resource.Quantity, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateNonnegativeQuantity(value, fldPath)...)
|
||||
if helper.IsIntegerResourceName(resource) {
|
||||
if value.MilliValue()%int64(1000) != int64(0) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value, isNotIntegerErrorMsg))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// Validates that a Quantity is not negative
|
||||
func ValidateNonnegativeQuantity(value resource.Quantity, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if value.Cmp(resource.Quantity{}) < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value.String(), isNegativeErrorMsg))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// Validate compute resource typename.
|
||||
// Refer to docs/design/resources.md for more details.
|
||||
func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||
// Opaque integer resources (OIR) deprecation began in v1.8
|
||||
// TODO: Remove warning after OIR deprecation cycle.
|
||||
if v1helper.IsOpaqueIntResourceName(v1.ResourceName(value)) {
|
||||
glog.Errorf("DEPRECATION WARNING! Opaque integer resources are deprecated starting with v1.8: %s", value)
|
||||
}
|
||||
|
||||
allErrs := field.ErrorList{}
|
||||
for _, msg := range validation.IsQualifiedName(value) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value, msg))
|
||||
}
|
||||
if len(allErrs) != 0 {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if len(strings.Split(value, "/")) == 1 {
|
||||
if !helper.IsStandardResourceName(value) {
|
||||
return append(allErrs, field.Invalid(fldPath, value, "must be a standard resource type or fully qualified"))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidatePodLogOptions(opts *v1.PodLogOptions) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if opts.TailLines != nil && *opts.TailLines < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("tailLines"), *opts.TailLines, isNegativeErrorMsg))
|
||||
}
|
||||
if opts.LimitBytes != nil && *opts.LimitBytes < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("limitBytes"), *opts.LimitBytes, "must be greater than 0"))
|
||||
}
|
||||
switch {
|
||||
case opts.SinceSeconds != nil && opts.SinceTime != nil:
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath(""), "at most one of `sinceTime` or `sinceSeconds` may be specified"))
|
||||
case opts.SinceSeconds != nil:
|
||||
if *opts.SinceSeconds < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("sinceSeconds"), *opts.SinceSeconds, "must be greater than 0"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func AccumulateUniqueHostPorts(containers []v1.Container, accumulator *sets.String, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
for ci, ctr := range containers {
|
||||
idxPath := fldPath.Index(ci)
|
||||
portsPath := idxPath.Child("ports")
|
||||
for pi := range ctr.Ports {
|
||||
idxPath := portsPath.Index(pi)
|
||||
port := ctr.Ports[pi].HostPort
|
||||
if port == 0 {
|
||||
continue
|
||||
}
|
||||
str := fmt.Sprintf("%d/%s", port, ctr.Ports[pi].Protocol)
|
||||
if accumulator.Has(str) {
|
||||
allErrs = append(allErrs, field.Duplicate(idxPath.Child("hostPort"), str))
|
||||
} else {
|
||||
accumulator.Insert(str)
|
||||
}
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
179
vendor/k8s.io/kubernetes/pkg/api/v1/validation/validation_test.go
generated
vendored
179
vendor/k8s.io/kubernetes/pkg/api/v1/validation/validation_test.go
generated
vendored
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
func TestValidateResourceRequirements(t *testing.T) {
|
||||
successCase := []struct {
|
||||
Name string
|
||||
requirements v1.ResourceRequirements
|
||||
}{
|
||||
{
|
||||
Name: "GPU only setting Limits",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GPU setting Limits equals Requests",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"),
|
||||
},
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Resources with GPU with Requests",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"),
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("1"),
|
||||
},
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"),
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Resources with only Limits",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"),
|
||||
v1.ResourceName("my.org/resource"): resource.MustParse("10"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Resources with only Requests",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"),
|
||||
v1.ResourceName("my.org/resource"): resource.MustParse("10"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Resources with Requests Less Than Limits",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("9"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("9G"),
|
||||
v1.ResourceName("my.org/resource"): resource.MustParse("9"),
|
||||
},
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"),
|
||||
v1.ResourceName("my.org/resource"): resource.MustParse("9"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range successCase {
|
||||
if errs := ValidateResourceRequirements(&tc.requirements, field.NewPath("resources")); len(errs) != 0 {
|
||||
t.Errorf("%q unexpected error: %v", tc.Name, errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCase := []struct {
|
||||
Name string
|
||||
requirements v1.ResourceRequirements
|
||||
}{
|
||||
{
|
||||
Name: "GPU only setting Requests",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GPU setting Limits less than Requests",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"),
|
||||
},
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("11"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GPU setting Limits larger than Requests",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("10"),
|
||||
},
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceNvidiaGPU): resource.MustParse("9"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Resources with Requests Larger Than Limits",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("10"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"),
|
||||
v1.ResourceName("my.org/resource"): resource.MustParse("10m"),
|
||||
},
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceCPU): resource.MustParse("9"),
|
||||
v1.ResourceName(v1.ResourceMemory): resource.MustParse("9G"),
|
||||
v1.ResourceName("my.org/resource"): resource.MustParse("9m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Invalid Resources with Requests",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceName("my.org"): resource.MustParse("10m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Invalid Resources with Limits",
|
||||
requirements: v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{
|
||||
v1.ResourceName("my.org"): resource.MustParse("9m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range errorCase {
|
||||
if errs := ValidateResourceRequirements(&tc.requirements, field.NewPath("resources")); len(errs) == 0 {
|
||||
t.Errorf("%q expected error", tc.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue