Delete deprecated API versions
pkg/service: There were a couple of references here just as a reminder to change the behavior of findPort. As of v1beta3, TargetPort was always defaulted, so we could remove findDefaultPort and related tests. pkg/apiserver: The tests were using versioned API codecs for some of their encoding tests. Necessary API types had to be written and registered with the fake versioned codecs. pkg/kubectl: Some tests were converted to current versions where it made sense.
This commit is contained in:
@@ -22,8 +22,6 @@ import (
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
|
||||
)
|
||||
|
||||
|
@@ -24,8 +24,6 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/registered"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
@@ -36,7 +34,7 @@ var Version string
|
||||
|
||||
// OldestVersion is the string that represents the oldest server version supported,
|
||||
// for client code that wants to hardcode the lowest common denominator.
|
||||
const OldestVersion = "v1beta1"
|
||||
const OldestVersion = "v1beta3"
|
||||
|
||||
// Versions is the list of versions that are recognized in code. The order provided
|
||||
// may be assumed to be least feature rich to most feature rich, and clients may
|
||||
@@ -88,20 +86,6 @@ func init() {
|
||||
},
|
||||
)
|
||||
|
||||
// versions that used mixed case URL formats
|
||||
versionMixedCase := map[string]bool{
|
||||
"v1beta1": true,
|
||||
"v1beta2": true,
|
||||
}
|
||||
|
||||
// backwards compatibility, prior to v1beta3, we identified the namespace as a query parameter
|
||||
versionToNamespaceScope := map[string]meta.RESTScope{
|
||||
"v1beta1": meta.RESTScopeNamespaceLegacy,
|
||||
"v1beta2": meta.RESTScopeNamespaceLegacy,
|
||||
"v1beta3": meta.RESTScopeNamespace,
|
||||
"v1": meta.RESTScopeNamespace,
|
||||
}
|
||||
|
||||
// the list of kinds that are scoped at the root of the api hierarchy
|
||||
// if a kind is not enumerated here, it is assumed to have a namespace scope
|
||||
kindToRootScope := map[string]bool{
|
||||
@@ -130,16 +114,11 @@ func init() {
|
||||
if ignoredKinds.Has(kind) {
|
||||
continue
|
||||
}
|
||||
mixedCase, found := versionMixedCase[version]
|
||||
if !found {
|
||||
mixedCase = false
|
||||
}
|
||||
scope := versionToNamespaceScope[version]
|
||||
_, found = kindToRootScope[kind]
|
||||
if found {
|
||||
scope := meta.RESTScopeNamespace
|
||||
if kindToRootScope[kind] {
|
||||
scope = meta.RESTScopeRoot
|
||||
}
|
||||
mapper.Add(scope, kind, version, mixedCase)
|
||||
mapper.Add(scope, kind, version, false)
|
||||
}
|
||||
}
|
||||
RESTMapper = mapper
|
||||
@@ -149,18 +128,6 @@ func init() {
|
||||
// string, or an error if the version is not known.
|
||||
func InterfacesFor(version string) (*meta.VersionInterfaces, error) {
|
||||
switch version {
|
||||
case "v1beta1":
|
||||
return &meta.VersionInterfaces{
|
||||
Codec: v1beta1.Codec,
|
||||
ObjectConvertor: api.Scheme,
|
||||
MetadataAccessor: accessor,
|
||||
}, nil
|
||||
case "v1beta2":
|
||||
return &meta.VersionInterfaces{
|
||||
Codec: v1beta2.Codec,
|
||||
ObjectConvertor: api.Scheme,
|
||||
MetadataAccessor: accessor,
|
||||
}, nil
|
||||
case "v1beta3":
|
||||
return &meta.VersionInterfaces{
|
||||
Codec: v1beta3.Codec,
|
||||
|
@@ -21,8 +21,6 @@ import (
|
||||
"testing"
|
||||
|
||||
internal "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
|
||||
)
|
||||
|
||||
func TestResourceVersioner(t *testing.T) {
|
||||
|
@@ -31,13 +31,11 @@ var RegisteredVersions []string
|
||||
func init() {
|
||||
validAPIVersions := map[string]bool{
|
||||
"v1": true,
|
||||
"v1beta1": true,
|
||||
"v1beta2": true,
|
||||
"v1beta3": true,
|
||||
}
|
||||
|
||||
// The default list of supported api versions, in order of most preferred to the least.
|
||||
defaultSupportedVersions := "v1beta3,v1beta1,v1beta2,v1"
|
||||
defaultSupportedVersions := "v1beta3,v1"
|
||||
// Env var KUBE_API_VERSIONS is a comma separated list of API versions that should be registered in the scheme.
|
||||
// The versions should be in the order of most preferred to the least.
|
||||
supportedVersions := os.Getenv("KUBE_API_VERSIONS")
|
||||
|
@@ -27,8 +27,6 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
|
||||
apitesting "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testing"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
@@ -89,12 +87,6 @@ func roundTripSame(t *testing.T, item runtime.Object, except ...string) {
|
||||
set := util.NewStringSet(except...)
|
||||
seed := rand.Int63()
|
||||
fuzzInternalObject(t, "", item, seed)
|
||||
if !set.Has("v1beta1") {
|
||||
roundTrip(t, v1beta1.Codec, item)
|
||||
}
|
||||
if !set.Has("v1beta2") {
|
||||
roundTrip(t, v1beta2.Codec, item)
|
||||
}
|
||||
if !set.Has("v1beta3") {
|
||||
fuzzInternalObject(t, "v1beta3", item, seed)
|
||||
roundTrip(t, v1beta3.Codec, item)
|
||||
@@ -103,8 +95,6 @@ func roundTripSame(t *testing.T, item runtime.Object, except ...string) {
|
||||
|
||||
func roundTripAll(t *testing.T, item runtime.Object) {
|
||||
seed := rand.Int63()
|
||||
roundTrip(t, v1beta1.Codec, fuzzInternalObject(t, "v1beta1", item, seed))
|
||||
roundTrip(t, v1beta2.Codec, fuzzInternalObject(t, "v1beta2", item, seed))
|
||||
roundTrip(t, v1beta3.Codec, fuzzInternalObject(t, "v1beta3", item, seed))
|
||||
}
|
||||
|
||||
@@ -137,10 +127,7 @@ func TestList(t *testing.T) {
|
||||
|
||||
var nonRoundTrippableTypes = util.NewStringSet("ContainerManifest", "ContainerManifestList")
|
||||
var nonInternalRoundTrippableTypes = util.NewStringSet("List", "ListOptions", "PodExecOptions")
|
||||
var nonRoundTrippableTypesByVersion = map[string][]string{
|
||||
"PodTemplate": {"v1beta1", "v1beta2"},
|
||||
"PodTemplateList": {"v1beta1", "v1beta2"},
|
||||
}
|
||||
var nonRoundTrippableTypesByVersion = map[string][]string{}
|
||||
|
||||
func TestRoundTripTypes(t *testing.T) {
|
||||
// api.Scheme.Log(t)
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,811 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta1_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||
versioned "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
var Convert = api.Scheme.Convert
|
||||
|
||||
func TestEmptyObjectConversion(t *testing.T) {
|
||||
s, err := versioned.Codec.Encode(&versioned.LimitRange{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
// DeletionTimestamp is not included, while CreationTimestamp is (would always be set)
|
||||
if string(s) != `{"kind":"LimitRange","creationTimestamp":null,"apiVersion":"v1beta1","spec":{"limits":null}}` {
|
||||
t.Errorf("unexpected empty object: %s", string(s))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeConversion(t *testing.T) {
|
||||
version, kind, err := api.Scheme.ObjectVersionAndKind(&versioned.Minion{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if version != "v1beta1" || kind != "Minion" {
|
||||
t.Errorf("unexpected version and kind: %s %s", version, kind)
|
||||
}
|
||||
|
||||
api.Scheme.Log(t)
|
||||
obj, err := versioned.Codec.Decode([]byte(`{"kind":"Node","apiVersion":"v1beta1"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if _, ok := obj.(*api.Node); !ok {
|
||||
t.Errorf("unexpected type: %#v", obj)
|
||||
}
|
||||
|
||||
obj, err = versioned.Codec.Decode([]byte(`{"kind":"NodeList","apiVersion":"v1beta1"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if _, ok := obj.(*api.NodeList); !ok {
|
||||
t.Errorf("unexpected type: %#v", obj)
|
||||
}
|
||||
|
||||
obj = &api.Node{}
|
||||
if err := versioned.Codec.DecodeInto([]byte(`{"kind":"Node","apiVersion":"v1beta1"}`), obj); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
obj = &api.Node{}
|
||||
data, err := versioned.Codec.Encode(obj)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
m := map[string]interface{}{}
|
||||
if err := json.Unmarshal(data, &m); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if m["kind"] != "Minion" {
|
||||
t.Errorf("unexpected encoding: %s - %#v", m["kind"], string(data))
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvConversion(t *testing.T) {
|
||||
nonCanonical := []versioned.EnvVar{
|
||||
{Key: "EV"},
|
||||
{Key: "EV", Name: "EX"},
|
||||
}
|
||||
canonical := []api.EnvVar{
|
||||
{Name: "EV"},
|
||||
{Name: "EX"},
|
||||
}
|
||||
for i := range nonCanonical {
|
||||
var got api.EnvVar
|
||||
err := Convert(&nonCanonical[i], &got)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if e, a := canonical[i], got; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
// Test conversion the other way, too.
|
||||
for i := range canonical {
|
||||
var got versioned.EnvVar
|
||||
err := Convert(&canonical[i], &got)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if e, a := canonical[i].Name, got.Key; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := canonical[i].Name, got.Name; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVolumeMountConversionToOld(t *testing.T) {
|
||||
table := []struct {
|
||||
in api.VolumeMount
|
||||
out versioned.VolumeMount
|
||||
}{
|
||||
{
|
||||
in: api.VolumeMount{Name: "foo", MountPath: "/dev/foo", ReadOnly: true},
|
||||
out: versioned.VolumeMount{Name: "foo", MountPath: "/dev/foo", Path: "/dev/foo", ReadOnly: true},
|
||||
},
|
||||
}
|
||||
for _, item := range table {
|
||||
got := versioned.VolumeMount{}
|
||||
err := Convert(&item.in, &got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
continue
|
||||
}
|
||||
if e, a := item.out, got; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("Expected: %#v, got %#v", e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVolumeMountConversionToNew(t *testing.T) {
|
||||
table := []struct {
|
||||
in versioned.VolumeMount
|
||||
out api.VolumeMount
|
||||
}{
|
||||
{
|
||||
in: versioned.VolumeMount{Name: "foo", MountPath: "/dev/foo", ReadOnly: true},
|
||||
out: api.VolumeMount{Name: "foo", MountPath: "/dev/foo", ReadOnly: true},
|
||||
}, {
|
||||
in: versioned.VolumeMount{Name: "foo", MountPath: "/dev/foo", Path: "/dev/bar", ReadOnly: true},
|
||||
out: api.VolumeMount{Name: "foo", MountPath: "/dev/foo", ReadOnly: true},
|
||||
}, {
|
||||
in: versioned.VolumeMount{Name: "foo", Path: "/dev/bar", ReadOnly: true},
|
||||
out: api.VolumeMount{Name: "foo", MountPath: "/dev/bar", ReadOnly: true},
|
||||
},
|
||||
}
|
||||
for _, item := range table {
|
||||
got := api.VolumeMount{}
|
||||
err := Convert(&item.in, &got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
continue
|
||||
}
|
||||
if e, a := item.out, got; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("Expected: %#v, got %#v", e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinionListConversionToNew(t *testing.T) {
|
||||
oldMinion := func(id string) versioned.Minion {
|
||||
return versioned.Minion{
|
||||
TypeMeta: versioned.TypeMeta{ID: id},
|
||||
ExternalID: id}
|
||||
}
|
||||
newNode := func(id string) api.Node {
|
||||
return api.Node{
|
||||
ObjectMeta: api.ObjectMeta{Name: id},
|
||||
Spec: api.NodeSpec{ExternalID: id},
|
||||
}
|
||||
}
|
||||
oldMinions := []versioned.Minion{
|
||||
oldMinion("foo"),
|
||||
oldMinion("bar"),
|
||||
}
|
||||
newMinions := []api.Node{
|
||||
newNode("foo"),
|
||||
newNode("bar"),
|
||||
}
|
||||
|
||||
table := []struct {
|
||||
oldML *versioned.MinionList
|
||||
newML *api.NodeList
|
||||
}{
|
||||
{
|
||||
oldML: &versioned.MinionList{Items: oldMinions},
|
||||
newML: &api.NodeList{Items: newMinions},
|
||||
}, {
|
||||
oldML: &versioned.MinionList{Minions: oldMinions},
|
||||
newML: &api.NodeList{Items: newMinions},
|
||||
}, {
|
||||
oldML: &versioned.MinionList{
|
||||
Items: oldMinions,
|
||||
Minions: []versioned.Minion{oldMinion("baz")},
|
||||
},
|
||||
newML: &api.NodeList{Items: newMinions},
|
||||
},
|
||||
}
|
||||
|
||||
for _, item := range table {
|
||||
got := &api.NodeList{}
|
||||
err := Convert(item.oldML, got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if e, a := item.newML, got; !api.Semantic.DeepEqual(e, a) {
|
||||
t.Errorf("Expected: %#v, got %#v", e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMinionListConversionToOld(t *testing.T) {
|
||||
oldMinion := func(id string) versioned.Minion {
|
||||
return versioned.Minion{TypeMeta: versioned.TypeMeta{ID: id}}
|
||||
}
|
||||
newNode := func(id string) api.Node {
|
||||
return api.Node{ObjectMeta: api.ObjectMeta{Name: id}}
|
||||
}
|
||||
oldMinions := []versioned.Minion{
|
||||
oldMinion("foo"),
|
||||
oldMinion("bar"),
|
||||
}
|
||||
newMinions := []api.Node{
|
||||
newNode("foo"),
|
||||
newNode("bar"),
|
||||
}
|
||||
|
||||
newML := &api.NodeList{Items: newMinions}
|
||||
oldML := &versioned.MinionList{
|
||||
Items: oldMinions,
|
||||
Minions: oldMinions,
|
||||
}
|
||||
|
||||
got := &versioned.MinionList{}
|
||||
err := Convert(newML, got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if e, a := oldML, got; !api.Semantic.DeepEqual(e, a) {
|
||||
t.Errorf("Expected: %#v, got %#v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceEmptySelector(t *testing.T) {
|
||||
// Nil map should be preserved
|
||||
svc := &versioned.Service{Selector: nil}
|
||||
data, err := api.Scheme.EncodeToVersion(svc, "v1beta1")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
obj, err := api.Scheme.Decode(data)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
selector := obj.(*api.Service).Spec.Selector
|
||||
if selector != nil {
|
||||
t.Errorf("unexpected selector: %#v", obj)
|
||||
}
|
||||
|
||||
// Empty map should be preserved
|
||||
svc2 := &versioned.Service{Selector: map[string]string{}}
|
||||
data, err = api.Scheme.EncodeToVersion(svc2, "v1beta1")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
obj, err = api.Scheme.Decode(data)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
selector = obj.(*api.Service).Spec.Selector
|
||||
if selector == nil || len(selector) != 0 {
|
||||
t.Errorf("unexpected selector: %#v", obj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServicePorts(t *testing.T) {
|
||||
testCases := []struct {
|
||||
given versioned.Service
|
||||
expected api.Service
|
||||
roundtrip versioned.Service
|
||||
}{
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "legacy-with-defaults",
|
||||
},
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Port: 111,
|
||||
Protocol: api.ProtocolTCP,
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "legacy-full",
|
||||
},
|
||||
PortName: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromString("p"),
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: api.ProtocolTCP,
|
||||
TargetPort: util.NewIntOrStringFromString("p"),
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromString("p"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "both",
|
||||
},
|
||||
PortName: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromString("p"),
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}},
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: api.ProtocolUDP,
|
||||
TargetPort: util.NewIntOrStringFromInt(93),
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "one",
|
||||
},
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}},
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: api.ProtocolUDP,
|
||||
TargetPort: util.NewIntOrStringFromInt(93),
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "two",
|
||||
},
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}, {
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(76),
|
||||
}},
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: api.ProtocolUDP,
|
||||
TargetPort: util.NewIntOrStringFromInt(93),
|
||||
}, {
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: api.ProtocolTCP,
|
||||
TargetPort: util.NewIntOrStringFromInt(76),
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}, {
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(76),
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
// Convert versioned -> internal.
|
||||
got := api.Service{}
|
||||
if err := Convert(&tc.given, &got); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(got.Spec.Ports, tc.expected.Spec.Ports) {
|
||||
t.Errorf("[Case: %d] Expected %v, got %v", i, tc.expected.Spec.Ports, got.Spec.Ports)
|
||||
}
|
||||
|
||||
// Convert internal -> versioned.
|
||||
got2 := versioned.Service{}
|
||||
if err := Convert(&got, &got2); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(got2.Ports, tc.roundtrip.Ports) {
|
||||
t.Errorf("[Case: %d] Expected %v, got %v", i, tc.roundtrip.Ports, got2.Ports)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPullPolicyConversion(t *testing.T) {
|
||||
table := []struct {
|
||||
versioned versioned.PullPolicy
|
||||
internal api.PullPolicy
|
||||
}{
|
||||
{
|
||||
versioned: versioned.PullAlways,
|
||||
internal: api.PullAlways,
|
||||
}, {
|
||||
versioned: versioned.PullNever,
|
||||
internal: api.PullNever,
|
||||
}, {
|
||||
versioned: versioned.PullIfNotPresent,
|
||||
internal: api.PullIfNotPresent,
|
||||
}, {
|
||||
versioned: "",
|
||||
internal: "",
|
||||
}, {
|
||||
versioned: "invalid value",
|
||||
internal: "invalid value",
|
||||
},
|
||||
}
|
||||
for _, item := range table {
|
||||
var got api.PullPolicy
|
||||
err := Convert(&item.versioned, &got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
continue
|
||||
}
|
||||
if e, a := item.internal, got; e != a {
|
||||
t.Errorf("Expected: %q, got %q", e, a)
|
||||
}
|
||||
}
|
||||
for _, item := range table {
|
||||
var got versioned.PullPolicy
|
||||
err := Convert(&item.internal, &got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
continue
|
||||
}
|
||||
if e, a := item.versioned, got; e != a {
|
||||
t.Errorf("Expected: %q, got %q", e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getResourceRequirements(cpu, memory resource.Quantity) versioned.ResourceRequirements {
|
||||
res := versioned.ResourceRequirements{}
|
||||
res.Limits = versioned.ResourceList{}
|
||||
if cpu.Value() > 0 {
|
||||
res.Limits[versioned.ResourceCPU] = util.NewIntOrStringFromInt(int(cpu.Value()))
|
||||
}
|
||||
if memory.Value() > 0 {
|
||||
res.Limits[versioned.ResourceMemory] = util.NewIntOrStringFromInt(int(memory.Value()))
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func TestContainerConversion(t *testing.T) {
|
||||
cpuLimit := resource.MustParse("10")
|
||||
memoryLimit := resource.MustParse("10M")
|
||||
null := resource.Quantity{}
|
||||
testCases := []versioned.Container{
|
||||
{
|
||||
Name: "container",
|
||||
Resources: getResourceRequirements(cpuLimit, memoryLimit),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
CPU: int(cpuLimit.MilliValue()),
|
||||
Resources: getResourceRequirements(null, memoryLimit),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
Memory: memoryLimit.Value(),
|
||||
Resources: getResourceRequirements(cpuLimit, null),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
CPU: int(cpuLimit.MilliValue()),
|
||||
Memory: memoryLimit.Value(),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
Memory: memoryLimit.Value(),
|
||||
Resources: getResourceRequirements(cpuLimit, resource.MustParse("100M")),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
CPU: int(cpuLimit.MilliValue()),
|
||||
Resources: getResourceRequirements(resource.MustParse("500"), memoryLimit),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
got := api.Container{}
|
||||
if err := Convert(&tc, &got); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if cpu := got.Resources.Limits.Cpu(); cpu.Value() != cpuLimit.Value() {
|
||||
t.Errorf("[Case: %d] Expected cpu: %v, got: %v", i, cpuLimit, *cpu)
|
||||
}
|
||||
if memory := got.Resources.Limits.Memory(); memory.Value() != memoryLimit.Value() {
|
||||
t.Errorf("[Case: %d] Expected memory: %v, got: %v", i, memoryLimit, *memory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEndpointsConversion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
given versioned.Endpoints
|
||||
expected api.Endpoints
|
||||
}{
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "empty",
|
||||
},
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
Endpoints: []string{},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "one legacy",
|
||||
},
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
Endpoints: []string{"1.2.3.4:88"},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 88, Protocol: api.ProtocolTCP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "several legacy",
|
||||
},
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
Endpoints: []string{"1.2.3.4:88", "1.2.3.4:89", "1.2.3.4:90"},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 88, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
},
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 89, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
},
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 90, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "one subset",
|
||||
},
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
Endpoints: []string{"1.2.3.4:88"},
|
||||
Subsets: []versioned.EndpointSubset{{
|
||||
Ports: []versioned.EndpointPort{{Name: "", Port: 88, Protocol: versioned.ProtocolTCP}},
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
}},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 88, Protocol: api.ProtocolTCP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "several subset",
|
||||
},
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
Endpoints: []string{"1.2.3.4:88", "5.6.7.8:88", "1.2.3.4:89", "5.6.7.8:89"},
|
||||
Subsets: []versioned.EndpointSubset{
|
||||
{
|
||||
Ports: []versioned.EndpointPort{{Name: "", Port: 88, Protocol: versioned.ProtocolUDP}},
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
{
|
||||
Ports: []versioned.EndpointPort{{Name: "", Port: 89, Protocol: versioned.ProtocolUDP}},
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
{
|
||||
Ports: []versioned.EndpointPort{{Name: "named", Port: 90, Protocol: versioned.ProtocolUDP}},
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 88, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 89, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "named", Port: 90, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
// Convert versioned -> internal.
|
||||
got := api.Endpoints{}
|
||||
if err := Convert(&tc.given, &got); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !api.Semantic.DeepEqual(got.Subsets, tc.expected.Subsets) {
|
||||
t.Errorf("[Case: %d] Expected %#v, got %#v", i, tc.expected.Subsets, got.Subsets)
|
||||
}
|
||||
|
||||
// Convert internal -> versioned.
|
||||
got2 := versioned.Endpoints{}
|
||||
if err := Convert(&got, &got2); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if got2.Protocol != tc.given.Protocol || !api.Semantic.DeepEqual(got2.Endpoints, tc.given.Endpoints) {
|
||||
t.Errorf("[Case: %d] Expected %s %#v, got %s %#v", i, tc.given.Protocol, tc.given.Endpoints, got2.Protocol, got2.Endpoints)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecretVolumeSourceConversion(t *testing.T) {
|
||||
given := versioned.SecretVolumeSource{
|
||||
Target: versioned.ObjectReference{
|
||||
ID: "foo",
|
||||
},
|
||||
}
|
||||
|
||||
expected := api.SecretVolumeSource{
|
||||
SecretName: "foo",
|
||||
}
|
||||
|
||||
got := api.SecretVolumeSource{}
|
||||
if err := Convert(&given, &got); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if got.SecretName != expected.SecretName {
|
||||
t.Errorf("Expected %v; got %v", expected, got)
|
||||
}
|
||||
|
||||
got2 := versioned.SecretVolumeSource{}
|
||||
if err := Convert(&got, &got2); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if got2.Target.ID != given.Target.ID {
|
||||
t.Errorf("Expected %v; got %v", given, got2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadSecurityContextConversion(t *testing.T) {
|
||||
priv := false
|
||||
testCases := map[string]struct {
|
||||
c *versioned.Container
|
||||
err string
|
||||
}{
|
||||
// this use case must use true for the container and false for the sc. Otherwise the defaulter
|
||||
// will assume privileged was left undefined (since it is the default value) and copy the
|
||||
// sc setting upwards
|
||||
"mismatched privileged": {
|
||||
c: &versioned.Container{
|
||||
Privileged: true,
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Privileged: &priv,
|
||||
},
|
||||
},
|
||||
err: "container privileged settings do not match security context settings, cannot convert",
|
||||
},
|
||||
"mismatched caps add": {
|
||||
c: &versioned.Container{
|
||||
Capabilities: versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Add: []versioned.Capability{"bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
err: "container capability settings do not match security context settings, cannot convert",
|
||||
},
|
||||
"mismatched caps drop": {
|
||||
c: &versioned.Container{
|
||||
Capabilities: versioned.Capabilities{
|
||||
Drop: []versioned.Capability{"foo"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
err: "container capability settings do not match security context settings, cannot convert",
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range testCases {
|
||||
got := api.Container{}
|
||||
err := Convert(v.c, &got)
|
||||
if err == nil {
|
||||
t.Errorf("expected error for case %s but got none", k)
|
||||
} else {
|
||||
if err.Error() != v.err {
|
||||
t.Errorf("unexpected error for case %s. Expected: %s but got: %s", k, v.err, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,242 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs() {
|
||||
api.Scheme.AddDefaultingFuncs(
|
||||
func(obj *ReplicationController) {
|
||||
if len(obj.DesiredState.ReplicaSelector) == 0 {
|
||||
obj.DesiredState.ReplicaSelector = obj.DesiredState.PodTemplate.Labels
|
||||
}
|
||||
if len(obj.Labels) == 0 {
|
||||
obj.Labels = obj.DesiredState.PodTemplate.Labels
|
||||
}
|
||||
},
|
||||
func(obj *Volume) {
|
||||
if util.AllPtrFieldsNil(&obj.Source) {
|
||||
obj.Source = VolumeSource{
|
||||
EmptyDir: &EmptyDirVolumeSource{},
|
||||
}
|
||||
}
|
||||
},
|
||||
func(obj *ContainerPort) {
|
||||
if obj.Protocol == "" {
|
||||
obj.Protocol = ProtocolTCP
|
||||
}
|
||||
},
|
||||
func(obj *Container) {
|
||||
if obj.ImagePullPolicy == "" {
|
||||
// TODO(dchen1107): Move ParseImageName code to pkg/util
|
||||
parts := strings.Split(obj.Image, ":")
|
||||
// Check image tag
|
||||
if parts[len(parts)-1] == "latest" {
|
||||
obj.ImagePullPolicy = PullAlways
|
||||
} else {
|
||||
obj.ImagePullPolicy = PullIfNotPresent
|
||||
}
|
||||
}
|
||||
if obj.TerminationMessagePath == "" {
|
||||
obj.TerminationMessagePath = TerminationMessagePathDefault
|
||||
}
|
||||
defaultSecurityContext(obj)
|
||||
},
|
||||
func(obj *RestartPolicy) {
|
||||
if util.AllPtrFieldsNil(obj) {
|
||||
obj.Always = &RestartPolicyAlways{}
|
||||
}
|
||||
},
|
||||
func(obj *Service) {
|
||||
if obj.Protocol == "" {
|
||||
obj.Protocol = ProtocolTCP
|
||||
}
|
||||
if obj.SessionAffinity == "" {
|
||||
obj.SessionAffinity = ServiceAffinityNone
|
||||
}
|
||||
if obj.Type == "" {
|
||||
if obj.CreateExternalLoadBalancer {
|
||||
obj.Type = ServiceTypeLoadBalancer
|
||||
} else {
|
||||
obj.Type = ServiceTypeClusterIP
|
||||
}
|
||||
} else if obj.Type == ServiceTypeLoadBalancer {
|
||||
obj.CreateExternalLoadBalancer = true
|
||||
}
|
||||
for i := range obj.Ports {
|
||||
sp := &obj.Ports[i]
|
||||
if sp.Protocol == "" {
|
||||
sp.Protocol = ProtocolTCP
|
||||
}
|
||||
if sp.ContainerPort == util.NewIntOrStringFromInt(0) || sp.ContainerPort == util.NewIntOrStringFromString("") {
|
||||
sp.ContainerPort = util.NewIntOrStringFromInt(sp.Port)
|
||||
}
|
||||
}
|
||||
},
|
||||
func(obj *PodSpec) {
|
||||
if obj.DNSPolicy == "" {
|
||||
obj.DNSPolicy = DNSClusterFirst
|
||||
}
|
||||
if obj.HostNetwork {
|
||||
defaultHostNetworkPorts(&obj.Containers)
|
||||
}
|
||||
},
|
||||
func(obj *ContainerManifest) {
|
||||
if obj.DNSPolicy == "" {
|
||||
obj.DNSPolicy = DNSClusterFirst
|
||||
}
|
||||
if obj.HostNetwork {
|
||||
defaultHostNetworkPorts(&obj.Containers)
|
||||
}
|
||||
},
|
||||
func(obj *LivenessProbe) {
|
||||
if obj.TimeoutSeconds == 0 {
|
||||
obj.TimeoutSeconds = 1
|
||||
}
|
||||
},
|
||||
func(obj *Secret) {
|
||||
if obj.Type == "" {
|
||||
obj.Type = SecretTypeOpaque
|
||||
}
|
||||
},
|
||||
func(obj *PersistentVolume) {
|
||||
if obj.Status.Phase == "" {
|
||||
obj.Status.Phase = VolumePending
|
||||
}
|
||||
},
|
||||
func(obj *PersistentVolumeClaim) {
|
||||
if obj.Status.Phase == "" {
|
||||
obj.Status.Phase = ClaimPending
|
||||
}
|
||||
},
|
||||
func(obj *Endpoints) {
|
||||
if obj.Protocol == "" {
|
||||
obj.Protocol = ProtocolTCP
|
||||
}
|
||||
if len(obj.Subsets) == 0 && len(obj.Endpoints) > 0 {
|
||||
// Must be a legacy-style object - populate
|
||||
// Subsets from the older fields. Do this the
|
||||
// simplest way, which is dumb (but valid).
|
||||
for i := range obj.Endpoints {
|
||||
host, portStr, err := net.SplitHostPort(obj.Endpoints[i])
|
||||
if err != nil {
|
||||
glog.Errorf("failed to SplitHostPort(%q)", obj.Endpoints[i])
|
||||
}
|
||||
var tgtRef *ObjectReference
|
||||
for j := range obj.TargetRefs {
|
||||
if obj.TargetRefs[j].Endpoint == obj.Endpoints[i] {
|
||||
tgtRef = &ObjectReference{}
|
||||
*tgtRef = obj.TargetRefs[j].ObjectReference
|
||||
}
|
||||
}
|
||||
port, err := strconv.Atoi(portStr)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to Atoi(%q)", portStr)
|
||||
}
|
||||
obj.Subsets = append(obj.Subsets, EndpointSubset{
|
||||
Addresses: []EndpointAddress{{IP: host, TargetRef: tgtRef}},
|
||||
Ports: []EndpointPort{{Protocol: obj.Protocol, Port: port}},
|
||||
})
|
||||
}
|
||||
}
|
||||
for i := range obj.Subsets {
|
||||
ss := &obj.Subsets[i]
|
||||
for i := range ss.Ports {
|
||||
ep := &ss.Ports[i]
|
||||
if ep.Protocol == "" {
|
||||
ep.Protocol = ProtocolTCP
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
func(obj *HTTPGetAction) {
|
||||
if obj.Path == "" {
|
||||
obj.Path = "/"
|
||||
}
|
||||
},
|
||||
func(obj *NamespaceStatus) {
|
||||
if obj.Phase == "" {
|
||||
obj.Phase = NamespaceActive
|
||||
}
|
||||
},
|
||||
func(obj *Minion) {
|
||||
if obj.ExternalID == "" {
|
||||
obj.ExternalID = obj.ID
|
||||
}
|
||||
},
|
||||
func(obj *ObjectFieldSelector) {
|
||||
if obj.APIVersion == "" {
|
||||
obj.APIVersion = "v1beta1"
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// With host networking default all host ports to container ports.
|
||||
func defaultHostNetworkPorts(containers *[]Container) {
|
||||
for i := range *containers {
|
||||
for j := range (*containers)[i].Ports {
|
||||
if (*containers)[i].Ports[j].HostPort == 0 {
|
||||
(*containers)[i].Ports[j].HostPort = (*containers)[i].Ports[j].ContainerPort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// defaultSecurityContext performs the downward and upward merges of a pod definition
|
||||
func defaultSecurityContext(container *Container) {
|
||||
if container.SecurityContext == nil {
|
||||
glog.V(5).Infof("creating security context for container %s", container.Name)
|
||||
container.SecurityContext = &SecurityContext{}
|
||||
}
|
||||
// if there are no capabilities defined on the SecurityContext then copy the container settings
|
||||
if container.SecurityContext.Capabilities == nil {
|
||||
container.SecurityContext.Capabilities = &container.Capabilities
|
||||
} else {
|
||||
// if there are capabilities defined on the security context and the container setting is
|
||||
// empty then assume that it was left off the pod definition and ensure that the container
|
||||
// settings match the security context settings (checked by the convert functions). If
|
||||
// there are settings in both then don't touch it, the converter will error if they don't
|
||||
// match
|
||||
if len(container.Capabilities.Add) == 0 {
|
||||
container.Capabilities.Add = container.SecurityContext.Capabilities.Add
|
||||
}
|
||||
if len(container.Capabilities.Drop) == 0 {
|
||||
container.Capabilities.Drop = container.SecurityContext.Capabilities.Drop
|
||||
}
|
||||
}
|
||||
// if there are no privileged settings on the security context then copy the container settings
|
||||
if container.SecurityContext.Privileged == nil {
|
||||
container.SecurityContext.Privileged = &container.Privileged
|
||||
} else {
|
||||
// we don't have a good way to know if container.Privileged was set or just defaulted to false
|
||||
// so the best we can do here is check if the securityContext is set to true and the
|
||||
// container is set to false and assume that the Privileged field was left off the container
|
||||
// definition and not an intentional mismatch
|
||||
if *container.SecurityContext.Privileged && !container.Privileged {
|
||||
container.Privileged = *container.SecurityContext.Privileged
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,461 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta1_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
versioned "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
||||
data, err := versioned.Codec.Encode(obj)
|
||||
if err != nil {
|
||||
t.Errorf("%v\n %#v", err, obj)
|
||||
return nil
|
||||
}
|
||||
obj2, err := api.Codec.Decode(data)
|
||||
if err != nil {
|
||||
t.Errorf("%v\nData: %s\nSource: %#v", err, string(data), obj)
|
||||
return nil
|
||||
}
|
||||
obj3 := reflect.New(reflect.TypeOf(obj).Elem()).Interface().(runtime.Object)
|
||||
err = api.Scheme.Convert(obj2, obj3)
|
||||
if err != nil {
|
||||
t.Errorf("%v\nSource: %#v", err, obj2)
|
||||
return nil
|
||||
}
|
||||
return obj3
|
||||
}
|
||||
|
||||
func TestSetDefaultReplicationController(t *testing.T) {
|
||||
tests := []struct {
|
||||
rc *versioned.ReplicationController
|
||||
expectLabels bool
|
||||
expectSelector bool
|
||||
}{
|
||||
{
|
||||
rc: &versioned.ReplicationController{
|
||||
DesiredState: versioned.ReplicationControllerState{
|
||||
PodTemplate: versioned.PodTemplate{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectLabels: true,
|
||||
expectSelector: true,
|
||||
},
|
||||
{
|
||||
rc: &versioned.ReplicationController{
|
||||
Labels: map[string]string{
|
||||
"bar": "foo",
|
||||
},
|
||||
DesiredState: versioned.ReplicationControllerState{
|
||||
PodTemplate: versioned.PodTemplate{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectLabels: false,
|
||||
expectSelector: true,
|
||||
},
|
||||
{
|
||||
rc: &versioned.ReplicationController{
|
||||
Labels: map[string]string{
|
||||
"bar": "foo",
|
||||
},
|
||||
DesiredState: versioned.ReplicationControllerState{
|
||||
ReplicaSelector: map[string]string{
|
||||
"some": "other",
|
||||
},
|
||||
PodTemplate: versioned.PodTemplate{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectLabels: false,
|
||||
expectSelector: false,
|
||||
},
|
||||
{
|
||||
rc: &versioned.ReplicationController{
|
||||
DesiredState: versioned.ReplicationControllerState{
|
||||
ReplicaSelector: map[string]string{
|
||||
"some": "other",
|
||||
},
|
||||
PodTemplate: versioned.PodTemplate{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectLabels: true,
|
||||
expectSelector: false,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
rc := test.rc
|
||||
obj2 := roundTrip(t, runtime.Object(rc))
|
||||
rc2, ok := obj2.(*versioned.ReplicationController)
|
||||
if !ok {
|
||||
t.Errorf("unexpected object: %v", rc2)
|
||||
t.FailNow()
|
||||
}
|
||||
if test.expectSelector != reflect.DeepEqual(rc2.DesiredState.ReplicaSelector, rc2.DesiredState.PodTemplate.Labels) {
|
||||
if test.expectSelector {
|
||||
t.Errorf("expected: %v, got: %v", rc2.DesiredState.PodTemplate.Labels, rc2.DesiredState.ReplicaSelector)
|
||||
} else {
|
||||
t.Errorf("unexpected equality: %v", rc2.DesiredState.PodTemplate.Labels)
|
||||
}
|
||||
}
|
||||
if test.expectLabels != reflect.DeepEqual(rc2.Labels, rc2.DesiredState.PodTemplate.Labels) {
|
||||
if test.expectLabels {
|
||||
t.Errorf("expected: %v, got: %v", rc2.DesiredState.PodTemplate.Labels, rc2.Labels)
|
||||
} else {
|
||||
t.Errorf("unexpected equality: %v", rc2.DesiredState.PodTemplate.Labels)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultService(t *testing.T) {
|
||||
svc := &versioned.Service{}
|
||||
obj2 := roundTrip(t, runtime.Object(svc))
|
||||
svc2 := obj2.(*versioned.Service)
|
||||
if svc2.Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected default protocol :%s, got: %s", versioned.ProtocolTCP, svc2.Protocol)
|
||||
}
|
||||
if svc2.SessionAffinity != versioned.ServiceAffinityNone {
|
||||
t.Errorf("Expected default session affinity type:%s, got: %s", versioned.ServiceAffinityNone, svc2.SessionAffinity)
|
||||
}
|
||||
if svc2.Type != versioned.ServiceTypeClusterIP {
|
||||
t.Errorf("Expected default type:%s, got: %s", versioned.ServiceTypeClusterIP, svc2.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultServiceWithLoadbalancer(t *testing.T) {
|
||||
svc := &versioned.Service{}
|
||||
svc.CreateExternalLoadBalancer = true
|
||||
obj2 := roundTrip(t, runtime.Object(svc))
|
||||
svc2 := obj2.(*versioned.Service)
|
||||
if svc2.Type != versioned.ServiceTypeLoadBalancer {
|
||||
t.Errorf("Expected default type:%s, got: %s", versioned.ServiceTypeLoadBalancer, svc2.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultSecret(t *testing.T) {
|
||||
s := &versioned.Secret{}
|
||||
obj2 := roundTrip(t, runtime.Object(s))
|
||||
s2 := obj2.(*versioned.Secret)
|
||||
|
||||
if s2.Type != versioned.SecretTypeOpaque {
|
||||
t.Errorf("Expected secret type %v, got %v", versioned.SecretTypeOpaque, s2.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultPersistentVolume(t *testing.T) {
|
||||
pv := &versioned.PersistentVolume{}
|
||||
obj2 := roundTrip(t, runtime.Object(pv))
|
||||
pv2 := obj2.(*versioned.PersistentVolume)
|
||||
|
||||
if pv2.Status.Phase != versioned.VolumePending {
|
||||
t.Errorf("Expected volume phase %v, got %v", versioned.VolumePending, pv2.Status.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultPersistentVolumeClaim(t *testing.T) {
|
||||
pvc := &versioned.PersistentVolumeClaim{}
|
||||
obj2 := roundTrip(t, runtime.Object(pvc))
|
||||
pvc2 := obj2.(*versioned.PersistentVolumeClaim)
|
||||
|
||||
if pvc2.Status.Phase != versioned.ClaimPending {
|
||||
t.Errorf("Expected claim phase %v, got %v", versioned.ClaimPending, pvc2.Status.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
// Test that we use "legacy" fields if "modern" fields are not provided.
|
||||
func TestSetDefaulEndpointsLegacy(t *testing.T) {
|
||||
in := &versioned.Endpoints{
|
||||
Protocol: "UDP",
|
||||
Endpoints: []string{"1.2.3.4:93", "5.6.7.8:76"},
|
||||
TargetRefs: []versioned.EndpointObjectReference{{Endpoint: "1.2.3.4:93", ObjectReference: versioned.ObjectReference{ID: "foo"}}},
|
||||
}
|
||||
obj := roundTrip(t, runtime.Object(in))
|
||||
out := obj.(*versioned.Endpoints)
|
||||
|
||||
if len(out.Subsets) != 2 {
|
||||
t.Errorf("Expected 2 EndpointSubsets, got %d (%#v)", len(out.Subsets), out.Subsets)
|
||||
}
|
||||
expected := []versioned.EndpointSubset{
|
||||
{
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4", TargetRef: &versioned.ObjectReference{ID: "foo"}}},
|
||||
Ports: []versioned.EndpointPort{{Protocol: versioned.ProtocolUDP, Port: 93}},
|
||||
},
|
||||
{
|
||||
Addresses: []versioned.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []versioned.EndpointPort{{Protocol: versioned.ProtocolUDP, Port: 76}},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(out.Subsets, expected) {
|
||||
t.Errorf("Expected %#v, got %#v", expected, out.Subsets)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaulEndpointsProtocol(t *testing.T) {
|
||||
in := &versioned.Endpoints{Subsets: []versioned.EndpointSubset{
|
||||
{Ports: []versioned.EndpointPort{{}, {Protocol: "UDP"}, {}}},
|
||||
}}
|
||||
obj := roundTrip(t, runtime.Object(in))
|
||||
out := obj.(*versioned.Endpoints)
|
||||
|
||||
if out.Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Protocol)
|
||||
}
|
||||
for i := range out.Subsets {
|
||||
for j := range out.Subsets[i].Ports {
|
||||
if in.Subsets[i].Ports[j].Protocol == "" {
|
||||
if out.Subsets[i].Ports[j].Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Subsets[i].Ports[j].Protocol)
|
||||
}
|
||||
} else {
|
||||
if out.Subsets[i].Ports[j].Protocol != in.Subsets[i].Ports[j].Protocol {
|
||||
t.Errorf("Expected protocol %s, got %s", in.Subsets[i].Ports[j].Protocol, out.Subsets[i].Ports[j].Protocol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultNamespace(t *testing.T) {
|
||||
s := &versioned.Namespace{}
|
||||
obj2 := roundTrip(t, runtime.Object(s))
|
||||
s2 := obj2.(*versioned.Namespace)
|
||||
|
||||
if s2.Status.Phase != versioned.NamespaceActive {
|
||||
t.Errorf("Expected phase %v, got %v", versioned.NamespaceActive, s2.Status.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultContainerManifestHostNetwork(t *testing.T) {
|
||||
portNum := 8080
|
||||
s := versioned.ContainerManifest{}
|
||||
s.HostNetwork = true
|
||||
s.Containers = []versioned.Container{
|
||||
{
|
||||
Ports: []versioned.ContainerPort{
|
||||
{
|
||||
ContainerPort: portNum,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
obj2 := roundTrip(t, runtime.Object(&versioned.ContainerManifestList{
|
||||
Items: []versioned.ContainerManifest{s},
|
||||
}))
|
||||
sList2 := obj2.(*versioned.ContainerManifestList)
|
||||
s2 := sList2.Items[0]
|
||||
|
||||
hostPortNum := s2.Containers[0].Ports[0].HostPort
|
||||
if hostPortNum != portNum {
|
||||
t.Errorf("Expected container port to be defaulted, was made %d instead of %d", hostPortNum, portNum)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultServicePort(t *testing.T) {
|
||||
// Unchanged if set.
|
||||
in := &versioned.Service{Ports: []versioned.ServicePort{{Protocol: "UDP", Port: 9376, ContainerPort: util.NewIntOrStringFromInt(118)}}}
|
||||
out := roundTrip(t, runtime.Object(in)).(*versioned.Service)
|
||||
if out.Ports[0].Protocol != versioned.ProtocolUDP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Ports[0].Protocol)
|
||||
}
|
||||
if out.Ports[0].ContainerPort != in.Ports[0].ContainerPort {
|
||||
t.Errorf("Expected port %d, got %d", in.Ports[0].ContainerPort, out.Ports[0].ContainerPort)
|
||||
}
|
||||
|
||||
// Defaulted.
|
||||
in = &versioned.Service{Ports: []versioned.ServicePort{{Protocol: "", Port: 9376, ContainerPort: util.NewIntOrStringFromInt(0)}}}
|
||||
out = roundTrip(t, runtime.Object(in)).(*versioned.Service)
|
||||
if out.Ports[0].Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Ports[0].Protocol)
|
||||
}
|
||||
if out.Ports[0].ContainerPort != util.NewIntOrStringFromInt(in.Ports[0].Port) {
|
||||
t.Errorf("Expected port %d, got %v", in.Ports[0].Port, out.Ports[0].ContainerPort)
|
||||
}
|
||||
|
||||
// Defaulted.
|
||||
in = &versioned.Service{Ports: []versioned.ServicePort{{Protocol: "", Port: 9376, ContainerPort: util.NewIntOrStringFromString("")}}}
|
||||
out = roundTrip(t, runtime.Object(in)).(*versioned.Service)
|
||||
if out.Ports[0].Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Ports[0].Protocol)
|
||||
}
|
||||
if out.Ports[0].ContainerPort != util.NewIntOrStringFromInt(in.Ports[0].Port) {
|
||||
t.Errorf("Expected port %d, got %v", in.Ports[0].Port, out.Ports[0].ContainerPort)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultMinionExternalID(t *testing.T) {
|
||||
name := "node0"
|
||||
m := &versioned.Minion{}
|
||||
m.ID = name
|
||||
obj2 := roundTrip(t, runtime.Object(m))
|
||||
m2 := obj2.(*versioned.Minion)
|
||||
if m2.ExternalID != name {
|
||||
t.Errorf("Expected default External ID: %s, got: %s", name, m2.ExternalID)
|
||||
}
|
||||
if m2.ProviderID != "" {
|
||||
t.Errorf("Expected empty default Cloud Provider ID, got: %s", m2.ProviderID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
|
||||
s := versioned.ContainerManifest{
|
||||
Containers: []versioned.Container{
|
||||
{
|
||||
Env: []versioned.EnvVar{
|
||||
{
|
||||
ValueFrom: &versioned.EnvVarSource{
|
||||
FieldRef: &versioned.ObjectFieldSelector{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
obj2 := roundTrip(t, runtime.Object(&versioned.ContainerManifestList{
|
||||
Items: []versioned.ContainerManifest{s},
|
||||
}))
|
||||
sList2 := obj2.(*versioned.ContainerManifestList)
|
||||
s2 := sList2.Items[0]
|
||||
|
||||
apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldRef.APIVersion
|
||||
if apiVersion != "v1beta1" {
|
||||
t.Errorf("Expected default APIVersion v1beta1, got: %v", apiVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultSecurityContext(t *testing.T) {
|
||||
priv := false
|
||||
privTrue := true
|
||||
testCases := map[string]struct {
|
||||
c versioned.Container
|
||||
}{
|
||||
"downward defaulting caps": {
|
||||
c: versioned.Container{
|
||||
Privileged: false,
|
||||
Capabilities: versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Privileged: &priv,
|
||||
},
|
||||
},
|
||||
},
|
||||
"downward defaulting priv": {
|
||||
c: versioned.Container{
|
||||
Privileged: false,
|
||||
Capabilities: versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"upward defaulting caps": {
|
||||
c: versioned.Container{
|
||||
Privileged: false,
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Privileged: &priv,
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Add: []versioned.Capability{"biz"},
|
||||
Drop: []versioned.Capability{"baz"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"upward defaulting priv": {
|
||||
c: versioned.Container{
|
||||
Capabilities: versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Privileged: &privTrue,
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pod := &versioned.Pod{
|
||||
DesiredState: versioned.PodState{
|
||||
Manifest: versioned.ContainerManifest{},
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range testCases {
|
||||
pod.DesiredState.Manifest.Containers = []versioned.Container{v.c}
|
||||
obj := roundTrip(t, runtime.Object(pod))
|
||||
defaultedPod := obj.(*versioned.Pod)
|
||||
c := defaultedPod.DesiredState.Manifest.Containers[0]
|
||||
if isEqual, issues := areSecurityContextAndContainerEqual(&c); !isEqual {
|
||||
t.Errorf("test case %s expected the security context to have the same values as the container but found %#v", k, issues)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func areSecurityContextAndContainerEqual(c *versioned.Container) (bool, []string) {
|
||||
issues := make([]string, 0)
|
||||
equal := true
|
||||
|
||||
if c.SecurityContext == nil || c.SecurityContext.Privileged == nil || c.SecurityContext.Capabilities == nil {
|
||||
equal = false
|
||||
issues = append(issues, "Expected non nil settings for SecurityContext")
|
||||
return equal, issues
|
||||
}
|
||||
if *c.SecurityContext.Privileged != c.Privileged {
|
||||
equal = false
|
||||
issues = append(issues, "The defaulted SecurityContext.Privileged value did not match the container value")
|
||||
}
|
||||
if !reflect.DeepEqual(c.Capabilities.Add, c.Capabilities.Add) {
|
||||
equal = false
|
||||
issues = append(issues, "The defaulted SecurityContext.Capabilities.Add did not match the container settings")
|
||||
}
|
||||
if !reflect.DeepEqual(c.Capabilities.Drop, c.Capabilities.Drop) {
|
||||
equal = false
|
||||
issues = append(issues, "The defaulted SecurityContext.Capabilities.Drop did not match the container settings")
|
||||
}
|
||||
return equal, issues
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta1 is the v1beta1 version of the API.
|
||||
package v1beta1
|
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/registered"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// Codec encodes internal objects to the v1beta1 scheme
|
||||
var Codec = runtime.CodecFor(api.Scheme, "v1beta1")
|
||||
|
||||
// Dependency does nothing but give a hook for other packages to force a
|
||||
// compile-time error when this API version is eventually removed. This is
|
||||
// useful, for example, to clean up things that are implicitly tied to
|
||||
// semantics of older APIs.
|
||||
const Dependency = true
|
||||
|
||||
func init() {
|
||||
// Check if v1beta1 is in the list of supported API versions.
|
||||
if !registered.IsRegisteredAPIVersion("v1beta1") {
|
||||
return
|
||||
}
|
||||
|
||||
// Register the API.
|
||||
addKnownTypes()
|
||||
addConversionFuncs()
|
||||
addDefaultingFuncs()
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes() {
|
||||
api.Scheme.AddKnownTypes("v1beta1",
|
||||
&Pod{},
|
||||
&PodStatusResult{},
|
||||
&PodList{},
|
||||
&ReplicationController{},
|
||||
&ReplicationControllerList{},
|
||||
&Service{},
|
||||
&ServiceList{},
|
||||
&Endpoints{},
|
||||
&EndpointsList{},
|
||||
&Minion{},
|
||||
&MinionList{},
|
||||
&NodeInfo{},
|
||||
&Binding{},
|
||||
&Status{},
|
||||
&Event{},
|
||||
&EventList{},
|
||||
&ContainerManifest{},
|
||||
&ContainerManifestList{},
|
||||
&List{},
|
||||
&LimitRange{},
|
||||
&LimitRangeList{},
|
||||
&ResourceQuota{},
|
||||
&ResourceQuotaList{},
|
||||
&Namespace{},
|
||||
&NamespaceList{},
|
||||
&Secret{},
|
||||
&SecretList{},
|
||||
&ServiceAccount{},
|
||||
&ServiceAccountList{},
|
||||
&PersistentVolume{},
|
||||
&PersistentVolumeList{},
|
||||
&PersistentVolumeClaim{},
|
||||
&PersistentVolumeClaimList{},
|
||||
&DeleteOptions{},
|
||||
&ListOptions{},
|
||||
&PodLogOptions{},
|
||||
&PodExecOptions{},
|
||||
&PodProxyOptions{},
|
||||
&ComponentStatus{},
|
||||
&ComponentStatusList{},
|
||||
&SerializedReference{},
|
||||
&RangeAllocation{},
|
||||
)
|
||||
// Future names are supported
|
||||
api.Scheme.AddKnownTypeWithName("v1beta1", "Node", &Minion{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta1", "NodeList", &MinionList{})
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
func (*PodStatusResult) IsAnAPIObject() {}
|
||||
func (*PodList) IsAnAPIObject() {}
|
||||
func (*ReplicationController) IsAnAPIObject() {}
|
||||
func (*ReplicationControllerList) IsAnAPIObject() {}
|
||||
func (*Service) IsAnAPIObject() {}
|
||||
func (*ServiceList) IsAnAPIObject() {}
|
||||
func (*Endpoints) IsAnAPIObject() {}
|
||||
func (*EndpointsList) IsAnAPIObject() {}
|
||||
func (*Minion) IsAnAPIObject() {}
|
||||
func (*NodeInfo) IsAnAPIObject() {}
|
||||
func (*MinionList) IsAnAPIObject() {}
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
func (*Event) IsAnAPIObject() {}
|
||||
func (*EventList) IsAnAPIObject() {}
|
||||
func (*ContainerManifest) IsAnAPIObject() {}
|
||||
func (*ContainerManifestList) IsAnAPIObject() {}
|
||||
func (*List) IsAnAPIObject() {}
|
||||
func (*LimitRange) IsAnAPIObject() {}
|
||||
func (*LimitRangeList) IsAnAPIObject() {}
|
||||
func (*ResourceQuota) IsAnAPIObject() {}
|
||||
func (*ResourceQuotaList) IsAnAPIObject() {}
|
||||
func (*Namespace) IsAnAPIObject() {}
|
||||
func (*NamespaceList) IsAnAPIObject() {}
|
||||
func (*Secret) IsAnAPIObject() {}
|
||||
func (*SecretList) IsAnAPIObject() {}
|
||||
func (*ServiceAccount) IsAnAPIObject() {}
|
||||
func (*ServiceAccountList) IsAnAPIObject() {}
|
||||
func (*PersistentVolume) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeList) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeClaim) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeClaimList) IsAnAPIObject() {}
|
||||
func (*DeleteOptions) IsAnAPIObject() {}
|
||||
func (*ListOptions) IsAnAPIObject() {}
|
||||
func (*PodLogOptions) IsAnAPIObject() {}
|
||||
func (*PodExecOptions) IsAnAPIObject() {}
|
||||
func (*PodProxyOptions) IsAnAPIObject() {}
|
||||
func (*ComponentStatus) IsAnAPIObject() {}
|
||||
func (*ComponentStatusList) IsAnAPIObject() {}
|
||||
func (*SerializedReference) IsAnAPIObject() {}
|
||||
func (*RangeAllocation) IsAnAPIObject() {}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,626 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta2_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||
versioned "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
func TestServiceEmptySelector(t *testing.T) {
|
||||
// Nil map should be preserved
|
||||
svc := &versioned.Service{Selector: nil}
|
||||
data, err := api.Scheme.EncodeToVersion(svc, "v1beta2")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
obj, err := api.Scheme.Decode(data)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
selector := obj.(*api.Service).Spec.Selector
|
||||
if selector != nil {
|
||||
t.Errorf("unexpected selector: %#v", obj)
|
||||
}
|
||||
|
||||
// Empty map should be preserved
|
||||
svc2 := &versioned.Service{Selector: map[string]string{}}
|
||||
data, err = api.Scheme.EncodeToVersion(svc2, "v1beta2")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
obj, err = api.Scheme.Decode(data)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
selector = obj.(*api.Service).Spec.Selector
|
||||
if selector == nil || len(selector) != 0 {
|
||||
t.Errorf("unexpected selector: %#v", obj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServicePorts(t *testing.T) {
|
||||
testCases := []struct {
|
||||
given versioned.Service
|
||||
expected api.Service
|
||||
roundtrip versioned.Service
|
||||
}{
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "legacy-with-defaults",
|
||||
},
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Port: 111,
|
||||
Protocol: api.ProtocolTCP,
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "legacy-full",
|
||||
},
|
||||
PortName: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromString("p"),
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: api.ProtocolTCP,
|
||||
TargetPort: util.NewIntOrStringFromString("p"),
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromString("p"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "both",
|
||||
},
|
||||
PortName: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromString("p"),
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}},
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: api.ProtocolUDP,
|
||||
TargetPort: util.NewIntOrStringFromInt(93),
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "one",
|
||||
},
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}},
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: api.ProtocolUDP,
|
||||
TargetPort: util.NewIntOrStringFromInt(93),
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Service{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "two",
|
||||
},
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}, {
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(76),
|
||||
}},
|
||||
},
|
||||
expected: api.Service{
|
||||
Spec: api.ServiceSpec{Ports: []api.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: api.ProtocolUDP,
|
||||
TargetPort: util.NewIntOrStringFromInt(93),
|
||||
}, {
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: api.ProtocolTCP,
|
||||
TargetPort: util.NewIntOrStringFromInt(76),
|
||||
}}},
|
||||
},
|
||||
roundtrip: versioned.Service{
|
||||
Ports: []versioned.ServicePort{{
|
||||
Name: "p",
|
||||
Port: 111,
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(93),
|
||||
}, {
|
||||
Name: "q",
|
||||
Port: 222,
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
ContainerPort: util.NewIntOrStringFromInt(76),
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
// Convert versioned -> internal.
|
||||
got := api.Service{}
|
||||
if err := api.Scheme.Convert(&tc.given, &got); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(got.Spec.Ports, tc.expected.Spec.Ports) {
|
||||
t.Errorf("[Case: %d] Expected %v, got %v", i, tc.expected.Spec.Ports, got.Spec.Ports)
|
||||
}
|
||||
|
||||
// Convert internal -> versioned.
|
||||
got2 := versioned.Service{}
|
||||
if err := api.Scheme.Convert(&got, &got2); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(got2.Ports, tc.roundtrip.Ports) {
|
||||
t.Errorf("[Case: %d] Expected %v, got %v", i, tc.roundtrip.Ports, got2.Ports)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeConversion(t *testing.T) {
|
||||
version, kind, err := api.Scheme.ObjectVersionAndKind(&versioned.Minion{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if version != "v1beta2" || kind != "Minion" {
|
||||
t.Errorf("unexpected version and kind: %s %s", version, kind)
|
||||
}
|
||||
|
||||
api.Scheme.Log(t)
|
||||
obj, err := versioned.Codec.Decode([]byte(`{"kind":"Node","apiVersion":"v1beta2"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if _, ok := obj.(*api.Node); !ok {
|
||||
t.Errorf("unexpected type: %#v", obj)
|
||||
}
|
||||
|
||||
obj, err = versioned.Codec.Decode([]byte(`{"kind":"NodeList","apiVersion":"v1beta2"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if _, ok := obj.(*api.NodeList); !ok {
|
||||
t.Errorf("unexpected type: %#v", obj)
|
||||
}
|
||||
|
||||
obj = &api.Node{}
|
||||
if err := versioned.Codec.DecodeInto([]byte(`{"kind":"Node","apiVersion":"v1beta2"}`), obj); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
obj = &api.Node{}
|
||||
data, err := versioned.Codec.Encode(obj)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
m := map[string]interface{}{}
|
||||
if err := json.Unmarshal(data, &m); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if m["kind"] != "Minion" {
|
||||
t.Errorf("unexpected encoding: %s - %#v", m["kind"], string(data))
|
||||
}
|
||||
}
|
||||
|
||||
func TestPullPolicyConversion(t *testing.T) {
|
||||
table := []struct {
|
||||
versioned versioned.PullPolicy
|
||||
internal api.PullPolicy
|
||||
}{
|
||||
{
|
||||
versioned: versioned.PullAlways,
|
||||
internal: api.PullAlways,
|
||||
}, {
|
||||
versioned: versioned.PullNever,
|
||||
internal: api.PullNever,
|
||||
}, {
|
||||
versioned: versioned.PullIfNotPresent,
|
||||
internal: api.PullIfNotPresent,
|
||||
}, {
|
||||
versioned: "",
|
||||
internal: "",
|
||||
}, {
|
||||
versioned: "invalid value",
|
||||
internal: "invalid value",
|
||||
},
|
||||
}
|
||||
for _, item := range table {
|
||||
var got api.PullPolicy
|
||||
err := api.Scheme.Convert(&item.versioned, &got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
continue
|
||||
}
|
||||
if e, a := item.internal, got; e != a {
|
||||
t.Errorf("Expected: %q, got %q", e, a)
|
||||
}
|
||||
}
|
||||
for _, item := range table {
|
||||
var got versioned.PullPolicy
|
||||
err := api.Scheme.Convert(&item.internal, &got)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
continue
|
||||
}
|
||||
if e, a := item.versioned, got; e != a {
|
||||
t.Errorf("Expected: %q, got %q", e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getResourceRequirements(cpu, memory resource.Quantity) versioned.ResourceRequirements {
|
||||
res := versioned.ResourceRequirements{}
|
||||
res.Limits = versioned.ResourceList{}
|
||||
if cpu.Value() > 0 {
|
||||
res.Limits[versioned.ResourceCPU] = util.NewIntOrStringFromInt(int(cpu.Value()))
|
||||
}
|
||||
if memory.Value() > 0 {
|
||||
res.Limits[versioned.ResourceMemory] = util.NewIntOrStringFromInt(int(memory.Value()))
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func TestContainerConversion(t *testing.T) {
|
||||
cpuLimit := resource.MustParse("10")
|
||||
memoryLimit := resource.MustParse("10M")
|
||||
null := resource.Quantity{}
|
||||
testCases := []versioned.Container{
|
||||
{
|
||||
Name: "container",
|
||||
Resources: getResourceRequirements(cpuLimit, memoryLimit),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
CPU: int(cpuLimit.MilliValue()),
|
||||
Resources: getResourceRequirements(null, memoryLimit),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
Memory: memoryLimit.Value(),
|
||||
Resources: getResourceRequirements(cpuLimit, null),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
CPU: int(cpuLimit.MilliValue()),
|
||||
Memory: memoryLimit.Value(),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
Memory: memoryLimit.Value(),
|
||||
Resources: getResourceRequirements(cpuLimit, resource.MustParse("100M")),
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
CPU: int(cpuLimit.MilliValue()),
|
||||
Resources: getResourceRequirements(resource.MustParse("500"), memoryLimit),
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
got := api.Container{}
|
||||
if err := api.Scheme.Convert(&tc, &got); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if cpu := got.Resources.Limits.Cpu(); cpu.Value() != cpuLimit.Value() {
|
||||
t.Errorf("[Case: %d] Expected cpu: %v, got: %v", i, cpuLimit, *cpu)
|
||||
}
|
||||
if memory := got.Resources.Limits.Memory(); memory.Value() != memoryLimit.Value() {
|
||||
t.Errorf("[Case: %d] Expected memory: %v, got: %v", i, memoryLimit, *memory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEndpointsConversion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
given versioned.Endpoints
|
||||
expected api.Endpoints
|
||||
}{
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "empty",
|
||||
},
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
Endpoints: []string{},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "one legacy",
|
||||
},
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
Endpoints: []string{"1.2.3.4:88"},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 88, Protocol: api.ProtocolTCP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "several legacy",
|
||||
},
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
Endpoints: []string{"1.2.3.4:88", "1.2.3.4:89", "1.2.3.4:90"},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 88, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
},
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 89, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
},
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 90, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "one subset",
|
||||
},
|
||||
Protocol: versioned.ProtocolTCP,
|
||||
Endpoints: []string{"1.2.3.4:88"},
|
||||
Subsets: []versioned.EndpointSubset{{
|
||||
Ports: []versioned.EndpointPort{{Name: "", Port: 88, Protocol: versioned.ProtocolTCP}},
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
}},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 88, Protocol: api.ProtocolTCP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
given: versioned.Endpoints{
|
||||
TypeMeta: versioned.TypeMeta{
|
||||
ID: "several subset",
|
||||
},
|
||||
Protocol: versioned.ProtocolUDP,
|
||||
Endpoints: []string{"1.2.3.4:88", "5.6.7.8:88", "1.2.3.4:89", "5.6.7.8:89"},
|
||||
Subsets: []versioned.EndpointSubset{
|
||||
{
|
||||
Ports: []versioned.EndpointPort{{Name: "", Port: 88, Protocol: versioned.ProtocolUDP}},
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
{
|
||||
Ports: []versioned.EndpointPort{{Name: "", Port: 89, Protocol: versioned.ProtocolUDP}},
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
{
|
||||
Ports: []versioned.EndpointPort{{Name: "named", Port: 90, Protocol: versioned.ProtocolUDP}},
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: api.Endpoints{
|
||||
Subsets: []api.EndpointSubset{
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 88, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "", Port: 89, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
{
|
||||
Ports: []api.EndpointPort{{Name: "named", Port: 90, Protocol: api.ProtocolUDP}},
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
// Convert versioned -> internal.
|
||||
got := api.Endpoints{}
|
||||
if err := api.Scheme.Convert(&tc.given, &got); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !api.Semantic.DeepEqual(got.Subsets, tc.expected.Subsets) {
|
||||
t.Errorf("[Case: %d] Expected %#v, got %#v", i, tc.expected.Subsets, got.Subsets)
|
||||
}
|
||||
|
||||
// Convert internal -> versioned.
|
||||
got2 := versioned.Endpoints{}
|
||||
if err := api.Scheme.Convert(&got, &got2); err != nil {
|
||||
t.Errorf("[Case: %d] Unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if got2.Protocol != tc.given.Protocol || !api.Semantic.DeepEqual(got2.Endpoints, tc.given.Endpoints) {
|
||||
t.Errorf("[Case: %d] Expected %#v, got %#v", i, tc.given.Endpoints, got2.Endpoints)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecretVolumeSourceConversion(t *testing.T) {
|
||||
given := versioned.SecretVolumeSource{
|
||||
Target: versioned.ObjectReference{
|
||||
ID: "foo",
|
||||
},
|
||||
}
|
||||
|
||||
expected := api.SecretVolumeSource{
|
||||
SecretName: "foo",
|
||||
}
|
||||
|
||||
got := api.SecretVolumeSource{}
|
||||
if err := api.Scheme.Convert(&given, &got); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if got.SecretName != expected.SecretName {
|
||||
t.Errorf("Expected %v; got %v", expected, got)
|
||||
}
|
||||
|
||||
got2 := versioned.SecretVolumeSource{}
|
||||
if err := api.Scheme.Convert(&got, &got2); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if got2.Target.ID != given.Target.ID {
|
||||
t.Errorf("Expected %v; got %v", given, got2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadSecurityContextConversion(t *testing.T) {
|
||||
priv := false
|
||||
testCases := map[string]struct {
|
||||
c *versioned.Container
|
||||
err string
|
||||
}{
|
||||
// this use case must use true for the container and false for the sc. Otherwise the defaulter
|
||||
// will assume privileged was left undefined (since it is the default value) and copy the
|
||||
// sc setting upwards
|
||||
"mismatched privileged": {
|
||||
c: &versioned.Container{
|
||||
Privileged: true,
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Privileged: &priv,
|
||||
},
|
||||
},
|
||||
err: "container privileged settings do not match security context settings, cannot convert",
|
||||
},
|
||||
"mismatched caps add": {
|
||||
c: &versioned.Container{
|
||||
Capabilities: versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Add: []versioned.Capability{"bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
err: "container capability settings do not match security context settings, cannot convert",
|
||||
},
|
||||
"mismatched caps drop": {
|
||||
c: &versioned.Container{
|
||||
Capabilities: versioned.Capabilities{
|
||||
Drop: []versioned.Capability{"foo"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
err: "container capability settings do not match security context settings, cannot convert",
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range testCases {
|
||||
got := api.Container{}
|
||||
err := api.Scheme.Convert(v.c, &got)
|
||||
if err == nil {
|
||||
t.Errorf("expected error for case %s but got none", k)
|
||||
} else {
|
||||
if err.Error() != v.err {
|
||||
t.Errorf("unexpected error for case %s. Expected: %s but got: %s", k, v.err, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta2
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs() {
|
||||
api.Scheme.AddDefaultingFuncs(
|
||||
func(obj *ReplicationController) {
|
||||
if len(obj.DesiredState.ReplicaSelector) == 0 {
|
||||
obj.DesiredState.ReplicaSelector = obj.DesiredState.PodTemplate.Labels
|
||||
}
|
||||
if len(obj.Labels) == 0 {
|
||||
obj.Labels = obj.DesiredState.PodTemplate.Labels
|
||||
}
|
||||
},
|
||||
func(obj *Volume) {
|
||||
if util.AllPtrFieldsNil(&obj.Source) {
|
||||
glog.Errorf("Defaulting volume source for %v", obj)
|
||||
obj.Source = VolumeSource{
|
||||
EmptyDir: &EmptyDirVolumeSource{},
|
||||
}
|
||||
}
|
||||
},
|
||||
func(obj *ContainerPort) {
|
||||
if obj.Protocol == "" {
|
||||
obj.Protocol = ProtocolTCP
|
||||
}
|
||||
},
|
||||
func(obj *Container) {
|
||||
if obj.ImagePullPolicy == "" {
|
||||
// TODO(dchen1107): Move ParseImageName code to pkg/util
|
||||
parts := strings.Split(obj.Image, ":")
|
||||
// Check image tag
|
||||
if parts[len(parts)-1] == "latest" {
|
||||
obj.ImagePullPolicy = PullAlways
|
||||
} else {
|
||||
obj.ImagePullPolicy = PullIfNotPresent
|
||||
}
|
||||
}
|
||||
if obj.TerminationMessagePath == "" {
|
||||
obj.TerminationMessagePath = TerminationMessagePathDefault
|
||||
}
|
||||
defaultSecurityContext(obj)
|
||||
},
|
||||
func(obj *RestartPolicy) {
|
||||
if util.AllPtrFieldsNil(obj) {
|
||||
obj.Always = &RestartPolicyAlways{}
|
||||
}
|
||||
},
|
||||
func(obj *Service) {
|
||||
if obj.Protocol == "" {
|
||||
obj.Protocol = ProtocolTCP
|
||||
}
|
||||
if obj.SessionAffinity == "" {
|
||||
obj.SessionAffinity = ServiceAffinityNone
|
||||
}
|
||||
if obj.Type == "" {
|
||||
if obj.CreateExternalLoadBalancer {
|
||||
obj.Type = ServiceTypeLoadBalancer
|
||||
} else {
|
||||
obj.Type = ServiceTypeClusterIP
|
||||
}
|
||||
} else if obj.Type == ServiceTypeLoadBalancer {
|
||||
obj.CreateExternalLoadBalancer = true
|
||||
}
|
||||
for i := range obj.Ports {
|
||||
sp := &obj.Ports[i]
|
||||
if sp.Protocol == "" {
|
||||
sp.Protocol = ProtocolTCP
|
||||
}
|
||||
if sp.ContainerPort == util.NewIntOrStringFromInt(0) || sp.ContainerPort == util.NewIntOrStringFromString("") {
|
||||
sp.ContainerPort = util.NewIntOrStringFromInt(sp.Port)
|
||||
}
|
||||
}
|
||||
},
|
||||
func(obj *PodSpec) {
|
||||
if obj.DNSPolicy == "" {
|
||||
obj.DNSPolicy = DNSClusterFirst
|
||||
}
|
||||
if obj.HostNetwork {
|
||||
defaultHostNetworkPorts(&obj.Containers)
|
||||
}
|
||||
},
|
||||
func(obj *ContainerManifest) {
|
||||
if obj.DNSPolicy == "" {
|
||||
obj.DNSPolicy = DNSClusterFirst
|
||||
}
|
||||
if obj.HostNetwork {
|
||||
defaultHostNetworkPorts(&obj.Containers)
|
||||
}
|
||||
},
|
||||
func(obj *LivenessProbe) {
|
||||
if obj.TimeoutSeconds == 0 {
|
||||
obj.TimeoutSeconds = 1
|
||||
}
|
||||
},
|
||||
func(obj *Secret) {
|
||||
if obj.Type == "" {
|
||||
obj.Type = SecretTypeOpaque
|
||||
}
|
||||
},
|
||||
func(obj *PersistentVolume) {
|
||||
if obj.Status.Phase == "" {
|
||||
obj.Status.Phase = VolumePending
|
||||
}
|
||||
},
|
||||
func(obj *PersistentVolumeClaim) {
|
||||
if obj.Status.Phase == "" {
|
||||
obj.Status.Phase = ClaimPending
|
||||
}
|
||||
},
|
||||
func(obj *Endpoints) {
|
||||
if obj.Protocol == "" {
|
||||
obj.Protocol = ProtocolTCP
|
||||
}
|
||||
if len(obj.Subsets) == 0 && len(obj.Endpoints) > 0 {
|
||||
// Must be a legacy-style object - populate
|
||||
// Subsets from the older fields. Do this the
|
||||
// simplest way, which is dumb (but valid).
|
||||
for i := range obj.Endpoints {
|
||||
host, portStr, err := net.SplitHostPort(obj.Endpoints[i])
|
||||
if err != nil {
|
||||
glog.Errorf("failed to SplitHostPort(%q)", obj.Endpoints[i])
|
||||
}
|
||||
var tgtRef *ObjectReference
|
||||
for j := range obj.TargetRefs {
|
||||
if obj.TargetRefs[j].Endpoint == obj.Endpoints[i] {
|
||||
tgtRef = &ObjectReference{}
|
||||
*tgtRef = obj.TargetRefs[j].ObjectReference
|
||||
}
|
||||
}
|
||||
port, err := strconv.Atoi(portStr)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to Atoi(%q)", portStr)
|
||||
}
|
||||
obj.Subsets = append(obj.Subsets, EndpointSubset{
|
||||
Addresses: []EndpointAddress{{IP: host, TargetRef: tgtRef}},
|
||||
Ports: []EndpointPort{{Protocol: obj.Protocol, Port: port}},
|
||||
})
|
||||
}
|
||||
}
|
||||
for i := range obj.Subsets {
|
||||
ss := &obj.Subsets[i]
|
||||
for i := range ss.Ports {
|
||||
ep := &ss.Ports[i]
|
||||
if ep.Protocol == "" {
|
||||
ep.Protocol = ProtocolTCP
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
func(obj *HTTPGetAction) {
|
||||
if obj.Path == "" {
|
||||
obj.Path = "/"
|
||||
}
|
||||
},
|
||||
func(obj *NamespaceStatus) {
|
||||
if obj.Phase == "" {
|
||||
obj.Phase = NamespaceActive
|
||||
}
|
||||
},
|
||||
func(obj *Minion) {
|
||||
if obj.ExternalID == "" {
|
||||
obj.ExternalID = obj.ID
|
||||
}
|
||||
},
|
||||
func(obj *ObjectFieldSelector) {
|
||||
if obj.APIVersion == "" {
|
||||
obj.APIVersion = "v1beta2"
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// With host networking default all container ports to host ports.
|
||||
func defaultHostNetworkPorts(containers *[]Container) {
|
||||
for i := range *containers {
|
||||
for j := range (*containers)[i].Ports {
|
||||
if (*containers)[i].Ports[j].HostPort == 0 {
|
||||
(*containers)[i].Ports[j].HostPort = (*containers)[i].Ports[j].ContainerPort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// defaultSecurityContext performs the downward and upward merges of a pod definition
|
||||
func defaultSecurityContext(container *Container) {
|
||||
if container.SecurityContext == nil {
|
||||
glog.V(5).Infof("creating security context for container %s", container.Name)
|
||||
container.SecurityContext = &SecurityContext{}
|
||||
}
|
||||
// if there are no capabilities defined on the SecurityContext then copy the container settings
|
||||
if container.SecurityContext.Capabilities == nil {
|
||||
container.SecurityContext.Capabilities = &container.Capabilities
|
||||
} else {
|
||||
// if there are capabilities defined on the security context and the container setting is
|
||||
// empty then assume that it was left off the pod definition and ensure that the container
|
||||
// settings match the security context settings (checked by the convert functions). If
|
||||
// there are settings in both then don't touch it, the converter will error if they don't
|
||||
// match
|
||||
if len(container.Capabilities.Add) == 0 {
|
||||
container.Capabilities.Add = container.SecurityContext.Capabilities.Add
|
||||
}
|
||||
if len(container.Capabilities.Drop) == 0 {
|
||||
container.Capabilities.Drop = container.SecurityContext.Capabilities.Drop
|
||||
}
|
||||
}
|
||||
// if there are no privileged settings on the security context then copy the container settings
|
||||
if container.SecurityContext.Privileged == nil {
|
||||
container.SecurityContext.Privileged = &container.Privileged
|
||||
} else {
|
||||
// we don't have a good way to know if container.Privileged was set or just defaulted to false
|
||||
// so the best we can do here is check if the securityContext is set to true and the
|
||||
// container is set to false and assume that the Privileged field was left off the container
|
||||
// definition and not an intentional mismatch
|
||||
if *container.SecurityContext.Privileged && !container.Privileged {
|
||||
container.Privileged = *container.SecurityContext.Privileged
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,460 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta2_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
versioned "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
||||
data, err := versioned.Codec.Encode(obj)
|
||||
if err != nil {
|
||||
t.Errorf("%v\n %#v", err, obj)
|
||||
return nil
|
||||
}
|
||||
obj2, err := api.Codec.Decode(data)
|
||||
if err != nil {
|
||||
t.Errorf("%v\nData: %s\nSource: %#v", err, string(data), obj)
|
||||
return nil
|
||||
}
|
||||
obj3 := reflect.New(reflect.TypeOf(obj).Elem()).Interface().(runtime.Object)
|
||||
err = api.Scheme.Convert(obj2, obj3)
|
||||
if err != nil {
|
||||
t.Errorf("%v\nSource: %#v", err, obj2)
|
||||
return nil
|
||||
}
|
||||
return obj3
|
||||
}
|
||||
|
||||
func TestSetDefaultReplicationController(t *testing.T) {
|
||||
tests := []struct {
|
||||
rc *versioned.ReplicationController
|
||||
expectLabels bool
|
||||
expectSelector bool
|
||||
}{
|
||||
{
|
||||
rc: &versioned.ReplicationController{
|
||||
DesiredState: versioned.ReplicationControllerState{
|
||||
PodTemplate: versioned.PodTemplate{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectLabels: true,
|
||||
expectSelector: true,
|
||||
},
|
||||
{
|
||||
rc: &versioned.ReplicationController{
|
||||
Labels: map[string]string{
|
||||
"bar": "foo",
|
||||
},
|
||||
DesiredState: versioned.ReplicationControllerState{
|
||||
PodTemplate: versioned.PodTemplate{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectLabels: false,
|
||||
expectSelector: true,
|
||||
},
|
||||
{
|
||||
rc: &versioned.ReplicationController{
|
||||
Labels: map[string]string{
|
||||
"bar": "foo",
|
||||
},
|
||||
DesiredState: versioned.ReplicationControllerState{
|
||||
ReplicaSelector: map[string]string{
|
||||
"some": "other",
|
||||
},
|
||||
PodTemplate: versioned.PodTemplate{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectLabels: false,
|
||||
expectSelector: false,
|
||||
},
|
||||
{
|
||||
rc: &versioned.ReplicationController{
|
||||
DesiredState: versioned.ReplicationControllerState{
|
||||
ReplicaSelector: map[string]string{
|
||||
"some": "other",
|
||||
},
|
||||
PodTemplate: versioned.PodTemplate{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectLabels: true,
|
||||
expectSelector: false,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
rc := test.rc
|
||||
obj2 := roundTrip(t, runtime.Object(rc))
|
||||
rc2, ok := obj2.(*versioned.ReplicationController)
|
||||
if !ok {
|
||||
t.Errorf("unexpected object: %v", rc2)
|
||||
t.FailNow()
|
||||
}
|
||||
if test.expectSelector != reflect.DeepEqual(rc2.DesiredState.ReplicaSelector, rc2.DesiredState.PodTemplate.Labels) {
|
||||
if test.expectSelector {
|
||||
t.Errorf("expected: %v, got: %v", rc2.DesiredState.PodTemplate.Labels, rc2.DesiredState.ReplicaSelector)
|
||||
} else {
|
||||
t.Errorf("unexpected equality: %v", rc2.DesiredState.PodTemplate.Labels)
|
||||
}
|
||||
}
|
||||
if test.expectLabels != reflect.DeepEqual(rc2.Labels, rc2.DesiredState.PodTemplate.Labels) {
|
||||
if test.expectLabels {
|
||||
t.Errorf("expected: %v, got: %v", rc2.DesiredState.PodTemplate.Labels, rc2.Labels)
|
||||
} else {
|
||||
t.Errorf("unexpected equality: %v", rc2.DesiredState.PodTemplate.Labels)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultService(t *testing.T) {
|
||||
svc := &versioned.Service{}
|
||||
obj2 := roundTrip(t, runtime.Object(svc))
|
||||
svc2 := obj2.(*versioned.Service)
|
||||
if svc2.Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected default protocol :%s, got: %s", versioned.ProtocolTCP, svc2.Protocol)
|
||||
}
|
||||
if svc2.SessionAffinity != versioned.ServiceAffinityNone {
|
||||
t.Errorf("Expected default session affinity type:%s, got: %s", versioned.ServiceAffinityNone, svc2.SessionAffinity)
|
||||
}
|
||||
if svc2.Type != versioned.ServiceTypeClusterIP {
|
||||
t.Errorf("Expected default type:%s, got: %s", versioned.ServiceTypeClusterIP, svc2.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultServiceWithLoadbalancer(t *testing.T) {
|
||||
svc := &versioned.Service{}
|
||||
svc.CreateExternalLoadBalancer = true
|
||||
obj2 := roundTrip(t, runtime.Object(svc))
|
||||
svc2 := obj2.(*versioned.Service)
|
||||
if svc2.Type != versioned.ServiceTypeLoadBalancer {
|
||||
t.Errorf("Expected default type:%s, got: %s", versioned.ServiceTypeLoadBalancer, svc2.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultPersistentVolume(t *testing.T) {
|
||||
pv := &versioned.PersistentVolume{}
|
||||
obj2 := roundTrip(t, runtime.Object(pv))
|
||||
pv2 := obj2.(*versioned.PersistentVolume)
|
||||
|
||||
if pv2.Status.Phase != versioned.VolumePending {
|
||||
t.Errorf("Expected volume phase %v, got %v", versioned.VolumePending, pv2.Status.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultPersistentVolumeClaim(t *testing.T) {
|
||||
pvc := &versioned.PersistentVolumeClaim{}
|
||||
obj2 := roundTrip(t, runtime.Object(pvc))
|
||||
pvc2 := obj2.(*versioned.PersistentVolumeClaim)
|
||||
|
||||
if pvc2.Status.Phase != versioned.ClaimPending {
|
||||
t.Errorf("Expected claim phase %v, got %v", versioned.ClaimPending, pvc2.Status.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultSecret(t *testing.T) {
|
||||
s := &versioned.Secret{}
|
||||
obj2 := roundTrip(t, runtime.Object(s))
|
||||
s2 := obj2.(*versioned.Secret)
|
||||
|
||||
if s2.Type != versioned.SecretTypeOpaque {
|
||||
t.Errorf("Expected secret type %v, got %v", versioned.SecretTypeOpaque, s2.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaulEndpointsLegacy(t *testing.T) {
|
||||
in := &versioned.Endpoints{
|
||||
Protocol: "UDP",
|
||||
Endpoints: []string{"1.2.3.4:93", "5.6.7.8:76"},
|
||||
TargetRefs: []versioned.EndpointObjectReference{{Endpoint: "1.2.3.4:93", ObjectReference: versioned.ObjectReference{ID: "foo"}}},
|
||||
}
|
||||
obj := roundTrip(t, runtime.Object(in))
|
||||
out := obj.(*versioned.Endpoints)
|
||||
|
||||
if len(out.Subsets) != 2 {
|
||||
t.Errorf("Expected 2 EndpointSubsets, got %d (%#v)", len(out.Subsets), out.Subsets)
|
||||
}
|
||||
expected := []versioned.EndpointSubset{
|
||||
{
|
||||
Addresses: []versioned.EndpointAddress{{IP: "1.2.3.4", TargetRef: &versioned.ObjectReference{ID: "foo"}}},
|
||||
Ports: []versioned.EndpointPort{{Protocol: versioned.ProtocolUDP, Port: 93}},
|
||||
},
|
||||
{
|
||||
Addresses: []versioned.EndpointAddress{{IP: "5.6.7.8"}},
|
||||
Ports: []versioned.EndpointPort{{Protocol: versioned.ProtocolUDP, Port: 76}},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(out.Subsets, expected) {
|
||||
t.Errorf("Expected %#v, got %#v", expected, out.Subsets)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaulEndpointsProtocol(t *testing.T) {
|
||||
in := &versioned.Endpoints{Subsets: []versioned.EndpointSubset{
|
||||
{Ports: []versioned.EndpointPort{{}, {Protocol: "UDP"}, {}}},
|
||||
}}
|
||||
obj := roundTrip(t, runtime.Object(in))
|
||||
out := obj.(*versioned.Endpoints)
|
||||
|
||||
if out.Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Protocol)
|
||||
}
|
||||
for i := range out.Subsets {
|
||||
for j := range out.Subsets[i].Ports {
|
||||
if in.Subsets[i].Ports[j].Protocol == "" {
|
||||
if out.Subsets[i].Ports[j].Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Subsets[i].Ports[j].Protocol)
|
||||
}
|
||||
} else {
|
||||
if out.Subsets[i].Ports[j].Protocol != in.Subsets[i].Ports[j].Protocol {
|
||||
t.Errorf("Expected protocol %s, got %s", in.Subsets[i].Ports[j].Protocol, out.Subsets[i].Ports[j].Protocol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultNamespace(t *testing.T) {
|
||||
s := &versioned.Namespace{}
|
||||
obj2 := roundTrip(t, runtime.Object(s))
|
||||
s2 := obj2.(*versioned.Namespace)
|
||||
|
||||
if s2.Status.Phase != versioned.NamespaceActive {
|
||||
t.Errorf("Expected phase %v, got %v", versioned.NamespaceActive, s2.Status.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultContainerManifestHostNetwork(t *testing.T) {
|
||||
portNum := 8080
|
||||
s := versioned.ContainerManifest{}
|
||||
s.HostNetwork = true
|
||||
s.Containers = []versioned.Container{
|
||||
{
|
||||
Ports: []versioned.ContainerPort{
|
||||
{
|
||||
ContainerPort: portNum,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
obj2 := roundTrip(t, runtime.Object(&versioned.ContainerManifestList{
|
||||
Items: []versioned.ContainerManifest{s},
|
||||
}))
|
||||
sList2 := obj2.(*versioned.ContainerManifestList)
|
||||
s2 := sList2.Items[0]
|
||||
|
||||
hostPortNum := s2.Containers[0].Ports[0].HostPort
|
||||
if hostPortNum != portNum {
|
||||
t.Errorf("Expected container port to be defaulted, was made %d instead of %d", hostPortNum, portNum)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultServicePort(t *testing.T) {
|
||||
// Unchanged if set.
|
||||
in := &versioned.Service{Ports: []versioned.ServicePort{{Protocol: "UDP", Port: 9376, ContainerPort: util.NewIntOrStringFromInt(118)}}}
|
||||
out := roundTrip(t, runtime.Object(in)).(*versioned.Service)
|
||||
if out.Ports[0].Protocol != versioned.ProtocolUDP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Ports[0].Protocol)
|
||||
}
|
||||
if out.Ports[0].ContainerPort != in.Ports[0].ContainerPort {
|
||||
t.Errorf("Expected port %d, got %d", in.Ports[0].ContainerPort, out.Ports[0].ContainerPort)
|
||||
}
|
||||
|
||||
// Defaulted.
|
||||
in = &versioned.Service{Ports: []versioned.ServicePort{{Protocol: "", Port: 9376, ContainerPort: util.NewIntOrStringFromInt(0)}}}
|
||||
out = roundTrip(t, runtime.Object(in)).(*versioned.Service)
|
||||
if out.Ports[0].Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Ports[0].Protocol)
|
||||
}
|
||||
if out.Ports[0].ContainerPort != util.NewIntOrStringFromInt(in.Ports[0].Port) {
|
||||
t.Errorf("Expected port %d, got %v", in.Ports[0].Port, out.Ports[0].ContainerPort)
|
||||
}
|
||||
|
||||
// Defaulted.
|
||||
in = &versioned.Service{Ports: []versioned.ServicePort{{Protocol: "", Port: 9376, ContainerPort: util.NewIntOrStringFromString("")}}}
|
||||
out = roundTrip(t, runtime.Object(in)).(*versioned.Service)
|
||||
if out.Ports[0].Protocol != versioned.ProtocolTCP {
|
||||
t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Ports[0].Protocol)
|
||||
}
|
||||
if out.Ports[0].ContainerPort != util.NewIntOrStringFromInt(in.Ports[0].Port) {
|
||||
t.Errorf("Expected port %d, got %v", in.Ports[0].Port, out.Ports[0].ContainerPort)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultMinionExternalID(t *testing.T) {
|
||||
name := "node0"
|
||||
m := &versioned.Minion{}
|
||||
m.ID = name
|
||||
obj2 := roundTrip(t, runtime.Object(m))
|
||||
m2 := obj2.(*versioned.Minion)
|
||||
if m2.ExternalID != name {
|
||||
t.Errorf("Expected default External ID: %s, got: %s", name, m2.ExternalID)
|
||||
}
|
||||
if m2.ProviderID != "" {
|
||||
t.Errorf("Expected empty default Cloud Provider ID, got: %s", m2.ProviderID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) {
|
||||
s := versioned.ContainerManifest{
|
||||
Containers: []versioned.Container{
|
||||
{
|
||||
Env: []versioned.EnvVar{
|
||||
{
|
||||
ValueFrom: &versioned.EnvVarSource{
|
||||
FieldRef: &versioned.ObjectFieldSelector{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
obj2 := roundTrip(t, runtime.Object(&versioned.ContainerManifestList{
|
||||
Items: []versioned.ContainerManifest{s},
|
||||
}))
|
||||
sList2 := obj2.(*versioned.ContainerManifestList)
|
||||
s2 := sList2.Items[0]
|
||||
|
||||
apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldRef.APIVersion
|
||||
if apiVersion != "v1beta2" {
|
||||
t.Errorf("Expected default APIVersion v1beta2, got: %v", apiVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultSecurityContext(t *testing.T) {
|
||||
priv := false
|
||||
privTrue := true
|
||||
testCases := map[string]struct {
|
||||
c versioned.Container
|
||||
}{
|
||||
"downward defaulting caps": {
|
||||
c: versioned.Container{
|
||||
Privileged: false,
|
||||
Capabilities: versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Privileged: &priv,
|
||||
},
|
||||
},
|
||||
},
|
||||
"downward defaulting priv": {
|
||||
c: versioned.Container{
|
||||
Privileged: false,
|
||||
Capabilities: versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"upward defaulting caps": {
|
||||
c: versioned.Container{
|
||||
Privileged: false,
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Privileged: &priv,
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Add: []versioned.Capability{"biz"},
|
||||
Drop: []versioned.Capability{"baz"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"upward defaulting priv": {
|
||||
c: versioned.Container{
|
||||
Capabilities: versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
SecurityContext: &versioned.SecurityContext{
|
||||
Privileged: &privTrue,
|
||||
Capabilities: &versioned.Capabilities{
|
||||
Add: []versioned.Capability{"foo"},
|
||||
Drop: []versioned.Capability{"bar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pod := &versioned.Pod{
|
||||
DesiredState: versioned.PodState{
|
||||
Manifest: versioned.ContainerManifest{},
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range testCases {
|
||||
pod.DesiredState.Manifest.Containers = []versioned.Container{v.c}
|
||||
obj := roundTrip(t, runtime.Object(pod))
|
||||
defaultedPod := obj.(*versioned.Pod)
|
||||
c := defaultedPod.DesiredState.Manifest.Containers[0]
|
||||
if isEqual, issues := areSecurityContextAndContainerEqual(&c); !isEqual {
|
||||
t.Errorf("test case %s expected the security context to have the same values as the container but found %#v", k, issues)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func areSecurityContextAndContainerEqual(c *versioned.Container) (bool, []string) {
|
||||
issues := make([]string, 0)
|
||||
equal := true
|
||||
|
||||
if c.SecurityContext == nil || c.SecurityContext.Privileged == nil || c.SecurityContext.Capabilities == nil {
|
||||
equal = false
|
||||
issues = append(issues, "Expected non nil settings for SecurityContext")
|
||||
return equal, issues
|
||||
}
|
||||
if *c.SecurityContext.Privileged != c.Privileged {
|
||||
equal = false
|
||||
issues = append(issues, "The defaulted SecurityContext.Privileged value did not match the container value")
|
||||
}
|
||||
if !reflect.DeepEqual(c.Capabilities.Add, c.Capabilities.Add) {
|
||||
equal = false
|
||||
issues = append(issues, "The defaulted SecurityContext.Capabilities.Add did not match the container settings")
|
||||
}
|
||||
if !reflect.DeepEqual(c.Capabilities.Drop, c.Capabilities.Drop) {
|
||||
equal = false
|
||||
issues = append(issues, "The defaulted SecurityContext.Capabilities.Drop did not match the container settings")
|
||||
}
|
||||
return equal, issues
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta2 is the v1beta2 version of the API.
|
||||
package v1beta2
|
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 v1beta2
|
||||
|
||||
import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/registered"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// Codec encodes internal objects to the v1beta2 scheme
|
||||
var Codec = runtime.CodecFor(api.Scheme, "v1beta2")
|
||||
|
||||
// Dependency does nothing but give a hook for other packages to force a
|
||||
// compile-time error when this API version is eventually removed. This is
|
||||
// useful, for example, to clean up things that are implicitly tied to
|
||||
// semantics of older APIs.
|
||||
const Dependency = true
|
||||
|
||||
func init() {
|
||||
// Check if v1beta2 is in the list of supported API versions.
|
||||
if !registered.IsRegisteredAPIVersion("v1beta2") {
|
||||
return
|
||||
}
|
||||
|
||||
// Register the API.
|
||||
addKnownTypes()
|
||||
addConversionFuncs()
|
||||
addDefaultingFuncs()
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes() {
|
||||
api.Scheme.AddKnownTypes("v1beta2",
|
||||
&Pod{},
|
||||
&PodStatusResult{},
|
||||
&PodList{},
|
||||
&ReplicationController{},
|
||||
&ReplicationControllerList{},
|
||||
&Service{},
|
||||
&ServiceList{},
|
||||
&Endpoints{},
|
||||
&EndpointsList{},
|
||||
&Minion{},
|
||||
&NodeInfo{},
|
||||
&MinionList{},
|
||||
&Binding{},
|
||||
&Status{},
|
||||
&Event{},
|
||||
&EventList{},
|
||||
&ContainerManifest{},
|
||||
&ContainerManifestList{},
|
||||
&List{},
|
||||
&LimitRange{},
|
||||
&LimitRangeList{},
|
||||
&ResourceQuota{},
|
||||
&ResourceQuotaList{},
|
||||
&Namespace{},
|
||||
&NamespaceList{},
|
||||
&Secret{},
|
||||
&SecretList{},
|
||||
&ServiceAccount{},
|
||||
&ServiceAccountList{},
|
||||
&PersistentVolume{},
|
||||
&PersistentVolumeList{},
|
||||
&PersistentVolumeClaim{},
|
||||
&PersistentVolumeClaimList{},
|
||||
&DeleteOptions{},
|
||||
&ListOptions{},
|
||||
&PodLogOptions{},
|
||||
&PodExecOptions{},
|
||||
&PodProxyOptions{},
|
||||
&ComponentStatus{},
|
||||
&ComponentStatusList{},
|
||||
&SerializedReference{},
|
||||
&RangeAllocation{},
|
||||
)
|
||||
// Future names are supported
|
||||
api.Scheme.AddKnownTypeWithName("v1beta2", "Node", &Minion{})
|
||||
api.Scheme.AddKnownTypeWithName("v1beta2", "NodeList", &MinionList{})
|
||||
}
|
||||
|
||||
func (*Pod) IsAnAPIObject() {}
|
||||
func (*PodStatusResult) IsAnAPIObject() {}
|
||||
func (*PodList) IsAnAPIObject() {}
|
||||
func (*ReplicationController) IsAnAPIObject() {}
|
||||
func (*ReplicationControllerList) IsAnAPIObject() {}
|
||||
func (*Service) IsAnAPIObject() {}
|
||||
func (*ServiceList) IsAnAPIObject() {}
|
||||
func (*Endpoints) IsAnAPIObject() {}
|
||||
func (*EndpointsList) IsAnAPIObject() {}
|
||||
func (*Minion) IsAnAPIObject() {}
|
||||
func (*NodeInfo) IsAnAPIObject() {}
|
||||
func (*MinionList) IsAnAPIObject() {}
|
||||
func (*Binding) IsAnAPIObject() {}
|
||||
func (*Status) IsAnAPIObject() {}
|
||||
func (*Event) IsAnAPIObject() {}
|
||||
func (*EventList) IsAnAPIObject() {}
|
||||
func (*ContainerManifest) IsAnAPIObject() {}
|
||||
func (*ContainerManifestList) IsAnAPIObject() {}
|
||||
func (*List) IsAnAPIObject() {}
|
||||
func (*LimitRange) IsAnAPIObject() {}
|
||||
func (*LimitRangeList) IsAnAPIObject() {}
|
||||
func (*ResourceQuota) IsAnAPIObject() {}
|
||||
func (*ResourceQuotaList) IsAnAPIObject() {}
|
||||
func (*Namespace) IsAnAPIObject() {}
|
||||
func (*NamespaceList) IsAnAPIObject() {}
|
||||
func (*Secret) IsAnAPIObject() {}
|
||||
func (*SecretList) IsAnAPIObject() {}
|
||||
func (*ServiceAccount) IsAnAPIObject() {}
|
||||
func (*ServiceAccountList) IsAnAPIObject() {}
|
||||
func (*PersistentVolume) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeList) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeClaim) IsAnAPIObject() {}
|
||||
func (*PersistentVolumeClaimList) IsAnAPIObject() {}
|
||||
func (*DeleteOptions) IsAnAPIObject() {}
|
||||
func (*ListOptions) IsAnAPIObject() {}
|
||||
func (*PodLogOptions) IsAnAPIObject() {}
|
||||
func (*PodExecOptions) IsAnAPIObject() {}
|
||||
func (*PodProxyOptions) IsAnAPIObject() {}
|
||||
func (*ComponentStatus) IsAnAPIObject() {}
|
||||
func (*ComponentStatusList) IsAnAPIObject() {}
|
||||
func (*SerializedReference) IsAnAPIObject() {}
|
||||
func (*RangeAllocation) IsAnAPIObject() {}
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user