Commit f4e2c738 authored by Kris's avatar Kris

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.
parent f3b4b1aa
...@@ -6,7 +6,7 @@ matrix: ...@@ -6,7 +6,7 @@ matrix:
include: include:
- go: 1.4 - go: 1.4
env: env:
- KUBE_TEST_API_VERSIONS="v1beta1" - KUBE_TEST_API_VERSIONS="v1beta3"
KUBE_TEST_ETCD_PREFIXES="registry" KUBE_TEST_ETCD_PREFIXES="registry"
- go: 1.3 - go: 1.3
env: env:
......
...@@ -23,5 +23,6 @@ ...@@ -23,5 +23,6 @@
} }
] ]
} }
] ],
"models": {}
} }
\ No newline at end of file
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
"swaggerVersion": "1.2", "swaggerVersion": "1.2",
"apis": [ "apis": [
{ {
"path": "/api",
"description": "get available API versions"
},
{
"path": "/api/v1beta3", "path": "/api/v1beta3",
"description": "API at /api/v1beta3 version v1beta3" "description": "API at /api/v1beta3 version v1beta3"
}, },
{ {
"path": "/api",
"description": "get available API versions"
},
{
"path": "/version", "path": "/version",
"description": "git code version from which this is built" "description": "git code version from which this is built"
} }
...@@ -19,4 +19,4 @@ ...@@ -19,4 +19,4 @@
"title": "", "title": "",
"description": "" "description": ""
} }
} }
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,5 +23,6 @@ ...@@ -23,5 +23,6 @@
} }
] ]
} }
] ],
"models": {}
} }
\ No newline at end of file
...@@ -16,7 +16,7 @@ spec: ...@@ -16,7 +16,7 @@ spec:
kubernetes.io/cluster-service: "true" kubernetes.io/cluster-service: "true"
spec: spec:
containers: containers:
- image: gcr.io/google_containers/heapster:v0.12.1 - image: gcr.io/google_containers/heapster:v0.13.0
name: heapster name: heapster
command: command:
- /heapster - /heapster
......
...@@ -16,7 +16,7 @@ spec: ...@@ -16,7 +16,7 @@ spec:
kubernetes.io/cluster-service: "true" kubernetes.io/cluster-service: "true"
spec: spec:
containers: containers:
- image: gcr.io/google_containers/heapster:v0.12.1 - image: gcr.io/google_containers/heapster:v0.13.0
name: heapster name: heapster
command: command:
- /heapster - /heapster
......
...@@ -23,8 +23,6 @@ import ( ...@@ -23,8 +23,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1" _ "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/api/v1beta3"
pkg_runtime "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" pkg_runtime "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
......
...@@ -24,8 +24,6 @@ import ( ...@@ -24,8 +24,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1" _ "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/api/v1beta3"
pkg_runtime "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" pkg_runtime "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
......
...@@ -605,23 +605,6 @@ func runPatchTest(c *client.Client) { ...@@ -605,23 +605,6 @@ func runPatchTest(c *client.Client) {
RemoveLabelBody []byte RemoveLabelBody []byte
RemoveAllLabelsBody []byte RemoveAllLabelsBody []byte
}{ }{
"v1beta1": {
api.JSONPatchType: {
[]byte(`[{"op":"add","path":"/labels","value":{"foo":"bar","baz":"qux"}}]`),
[]byte(`[{"op":"remove","path":"/labels/foo"}]`),
[]byte(`[{"op":"remove","path":"/labels"}]`),
},
api.MergePatchType: {
[]byte(`{"labels":{"foo":"bar","baz":"qux"}}`),
[]byte(`{"labels":{"foo":null}}`),
[]byte(`{"labels":null}`),
},
api.StrategicMergePatchType: {
[]byte(`{"labels":{"foo":"bar","baz":"qux"}}`),
[]byte(`{"labels":{"foo":null}}`),
[]byte(`{"labels":{"$patch":"replace"}}`),
},
},
"v1beta3": { "v1beta3": {
api.JSONPatchType: { api.JSONPatchType: {
[]byte(`[{"op":"add","path":"/metadata/labels","value":{"foo":"bar","baz":"qux"}}]`), []byte(`[{"op":"add","path":"/metadata/labels","value":{"foo":"bar","baz":"qux"}}]`),
...@@ -938,7 +921,7 @@ func main() { ...@@ -938,7 +921,7 @@ func main() {
glog.Infof("Running tests for APIVersion: %s", apiVersion) glog.Infof("Running tests for APIVersion: %s", apiVersion)
firstManifestURL := ServeCachedManifestFile(testPodSpecFile) firstManifestURL := ServeCachedManifestFile(testPodSpecFile)
secondManifestURL := ServeCachedManifestFile(testManifestFile) secondManifestURL := ServeCachedManifestFile(testPodSpecFile)
apiServerURL, _ := startComponents(firstManifestURL, secondManifestURL, apiVersion) apiServerURL, _ := startComponents(firstManifestURL, secondManifestURL, apiVersion)
// Ok. we're good to go. // Ok. we're good to go.
...@@ -1059,27 +1042,3 @@ const ( ...@@ -1059,27 +1042,3 @@ const (
} }
}` }`
) )
const (
// This is copied from, and should be kept in sync with:
// https://raw.githubusercontent.com/GoogleCloudPlatform/container-vm-guestbook-redis-python/master/manifest.yaml
// Note that kubelet complains about these containers not having a self link.
testManifestFile = `version: v1beta2
id: container-vm-guestbook-manifest
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-data
mountPath: /data
- name: guestbook
image: google/guestbook-python-redis
ports:
- name: www
hostPort: 80
containerPort: 80
volumes:
- name: redis-data`
)
{
"id": "nginx-controller",
"apiVersion": "v1beta1",
"kind": "ReplicationController",
"desiredState": {
"replicas": 2,
"replicaSelector": {"name": "nginx"},
"podTemplate": {
"desiredState": {
"manifest": {
"version": "v1beta1",
"id": "nginx-controller",
"containers": [{
"name": "nginx",
"image": "nginx",
"ports": [{"containerPort": 80}]
}]
}
},
"labels": {"name": "nginx"}
}},
"labels": {"name": "nginx"}
}
...@@ -264,16 +264,7 @@ func (s *APIServer) Run(_ []string) error { ...@@ -264,16 +264,7 @@ func (s *APIServer) Run(_ []string) error {
if ok && legacyAPIFlagValue == "false" { if ok && legacyAPIFlagValue == "false" {
disableLegacyAPIs = true disableLegacyAPIs = true
} }
_ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable.
// "api/v1beta1={true|false} allows users to enable/disable v1beta1 API.
// This takes preference over api/all and api/legacy, if specified.
disableV1beta1 := disableAllAPIs || disableLegacyAPIs
disableV1beta1 = !s.getRuntimeConfigValue("api/v1beta1", !disableV1beta1)
// "api/v1beta2={true|false} allows users to enable/disable v1beta2 API.
// This takes preference over api/all and api/legacy, if specified.
disableV1beta2 := disableAllAPIs || disableLegacyAPIs
disableV1beta2 = !s.getRuntimeConfigValue("api/v1beta2", !disableV1beta2)
// "api/v1beta3={true|false} allows users to enable/disable v1beta3 API. // "api/v1beta3={true|false} allows users to enable/disable v1beta3 API.
// This takes preference over api/all and api/legacy, if specified. // This takes preference over api/all and api/legacy, if specified.
...@@ -369,8 +360,6 @@ func (s *APIServer) Run(_ []string) error { ...@@ -369,8 +360,6 @@ func (s *APIServer) Run(_ []string) error {
SupportsBasicAuth: len(s.BasicAuthFile) > 0, SupportsBasicAuth: len(s.BasicAuthFile) > 0,
Authorizer: authorizer, Authorizer: authorizer,
AdmissionControl: admissionController, AdmissionControl: admissionController,
DisableV1Beta1: disableV1beta1,
DisableV1Beta2: disableV1beta2,
DisableV1Beta3: disableV1beta3, DisableV1Beta3: disableV1beta3,
EnableV1: enableV1, EnableV1: enableV1,
MasterServiceNamespace: s.MasterServiceNamespace, MasterServiceNamespace: s.MasterServiceNamespace,
......
...@@ -28,8 +28,6 @@ import ( ...@@ -28,8 +28,6 @@ import (
"runtime" "runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_ "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/api/v1beta3"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
......
...@@ -121,7 +121,6 @@ func walkJSONFiles(inDir string, fn func(name, path string, data []byte)) error ...@@ -121,7 +121,6 @@ func walkJSONFiles(inDir string, fn func(name, path string, data []byte)) error
func TestExampleObjectSchemas(t *testing.T) { func TestExampleObjectSchemas(t *testing.T) {
cases := map[string]map[string]runtime.Object{ cases := map[string]map[string]runtime.Object{
"../cmd/integration": { "../cmd/integration": {
"v1beta1-controller": &api.ReplicationController{},
"v1beta3-controller": &api.ReplicationController{}, "v1beta3-controller": &api.ReplicationController{},
}, },
"../examples/guestbook": { "../examples/guestbook": {
......
...@@ -114,8 +114,6 @@ PATH="${KUBE_OUTPUT_HOSTBIN}":$PATH ...@@ -114,8 +114,6 @@ PATH="${KUBE_OUTPUT_HOSTBIN}":$PATH
kube_api_versions=( kube_api_versions=(
"" ""
v1beta1
v1beta2
v1beta3 v1beta3
) )
for version in "${kube_api_versions[@]}"; do for version in "${kube_api_versions[@]}"; do
......
...@@ -52,7 +52,7 @@ KUBE_RACE=${KUBE_RACE:-} # use KUBE_RACE="-race" to enable race testing ...@@ -52,7 +52,7 @@ KUBE_RACE=${KUBE_RACE:-} # use KUBE_RACE="-race" to enable race testing
# Set to the goveralls binary path to report coverage results to Coveralls.io. # Set to the goveralls binary path to report coverage results to Coveralls.io.
KUBE_GOVERALLS_BIN=${KUBE_GOVERALLS_BIN:-} KUBE_GOVERALLS_BIN=${KUBE_GOVERALLS_BIN:-}
# Comma separated list of API Versions that should be tested. # Comma separated list of API Versions that should be tested.
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1beta1,v1beta3"} KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1beta3"}
# Run tests with the standard (registry) and a custom etcd prefix # Run tests with the standard (registry) and a custom etcd prefix
# (kubernetes.io/registry). # (kubernetes.io/registry).
KUBE_TEST_ETCD_PREFIXES=${KUBE_TEST_ETCD_PREFIXES:-"registry,kubernetes.io/registry"} KUBE_TEST_ETCD_PREFIXES=${KUBE_TEST_ETCD_PREFIXES:-"registry,kubernetes.io/registry"}
......
...@@ -25,7 +25,7 @@ set -o pipefail ...@@ -25,7 +25,7 @@ set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${KUBE_ROOT}/hack/lib/init.sh" source "${KUBE_ROOT}/hack/lib/init.sh"
# Comma separated list of API Versions that should be tested. # Comma separated list of API Versions that should be tested.
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1beta1,v1beta3"} KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1beta3"}
KUBE_INTEGRATION_TEST_MAX_CONCURRENCY=${KUBE_INTEGRATION_TEST_MAX_CONCURRENCY:-"-1"} KUBE_INTEGRATION_TEST_MAX_CONCURRENCY=${KUBE_INTEGRATION_TEST_MAX_CONCURRENCY:-"-1"}
LOG_LEVEL=${LOG_LEVEL:-2} LOG_LEVEL=${LOG_LEVEL:-2}
......
...@@ -24,9 +24,10 @@ KUBE_ROOT=$(dirname "${BASH_SOURCE}")/.. ...@@ -24,9 +24,10 @@ KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${KUBE_ROOT}/hack/lib/init.sh" source "${KUBE_ROOT}/hack/lib/init.sh"
# The api version in which objects are currently stored in etcd. # The api version in which objects are currently stored in etcd.
KUBE_OLD_API_VERSION=${KUBE_OLD_API_VERSION:-"v1beta1"} KUBE_OLD_API_VERSION=${KUBE_OLD_API_VERSION:-"v1beta3"}
# The api version in which our etcd objects should be converted to. # The api version in which our etcd objects should be converted to.
# The new api version # The new api version
# TODO change this to v1 when it's ready.
KUBE_NEW_API_VERSION=${KUBE_NEW_API_VERSION:-"v1beta3"} KUBE_NEW_API_VERSION=${KUBE_NEW_API_VERSION:-"v1beta3"}
ETCD_HOST=${ETCD_HOST:-127.0.0.1} ETCD_HOST=${ETCD_HOST:-127.0.0.1}
......
...@@ -22,8 +22,6 @@ import ( ...@@ -22,8 +22,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "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" _ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
) )
......
...@@ -24,8 +24,6 @@ import ( ...@@ -24,8 +24,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/registered" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/registered"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1" "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/api/v1beta3"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
...@@ -36,7 +34,7 @@ var Version string ...@@ -36,7 +34,7 @@ var Version string
// OldestVersion is the string that represents the oldest server version supported, // OldestVersion is the string that represents the oldest server version supported,
// for client code that wants to hardcode the lowest common denominator. // 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 // 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 // may be assumed to be least feature rich to most feature rich, and clients may
...@@ -88,20 +86,6 @@ func init() { ...@@ -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 // 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 // if a kind is not enumerated here, it is assumed to have a namespace scope
kindToRootScope := map[string]bool{ kindToRootScope := map[string]bool{
...@@ -130,16 +114,11 @@ func init() { ...@@ -130,16 +114,11 @@ func init() {
if ignoredKinds.Has(kind) { if ignoredKinds.Has(kind) {
continue continue
} }
mixedCase, found := versionMixedCase[version] scope := meta.RESTScopeNamespace
if !found { if kindToRootScope[kind] {
mixedCase = false
}
scope := versionToNamespaceScope[version]
_, found = kindToRootScope[kind]
if found {
scope = meta.RESTScopeRoot scope = meta.RESTScopeRoot
} }
mapper.Add(scope, kind, version, mixedCase) mapper.Add(scope, kind, version, false)
} }
} }
RESTMapper = mapper RESTMapper = mapper
...@@ -149,18 +128,6 @@ func init() { ...@@ -149,18 +128,6 @@ func init() {
// string, or an error if the version is not known. // string, or an error if the version is not known.
func InterfacesFor(version string) (*meta.VersionInterfaces, error) { func InterfacesFor(version string) (*meta.VersionInterfaces, error) {
switch version { 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": case "v1beta3":
return &meta.VersionInterfaces{ return &meta.VersionInterfaces{
Codec: v1beta3.Codec, Codec: v1beta3.Codec,
......
...@@ -21,8 +21,6 @@ import ( ...@@ -21,8 +21,6 @@ import (
"testing" "testing"
internal "github.com/GoogleCloudPlatform/kubernetes/pkg/api" 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) { func TestResourceVersioner(t *testing.T) {
......
...@@ -31,13 +31,11 @@ var RegisteredVersions []string ...@@ -31,13 +31,11 @@ var RegisteredVersions []string
func init() { func init() {
validAPIVersions := map[string]bool{ validAPIVersions := map[string]bool{
"v1": true, "v1": true,
"v1beta1": true,
"v1beta2": true,
"v1beta3": true, "v1beta3": true,
} }
// The default list of supported api versions, in order of most preferred to the least. // 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. // 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. // The versions should be in the order of most preferred to the least.
supportedVersions := os.Getenv("KUBE_API_VERSIONS") supportedVersions := os.Getenv("KUBE_API_VERSIONS")
......
...@@ -27,8 +27,6 @@ import ( ...@@ -27,8 +27,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
apitesting "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testing" 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/api/v1beta3"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
...@@ -89,12 +87,6 @@ func roundTripSame(t *testing.T, item runtime.Object, except ...string) { ...@@ -89,12 +87,6 @@ func roundTripSame(t *testing.T, item runtime.Object, except ...string) {
set := util.NewStringSet(except...) set := util.NewStringSet(except...)
seed := rand.Int63() seed := rand.Int63()
fuzzInternalObject(t, "", item, seed) 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") { if !set.Has("v1beta3") {
fuzzInternalObject(t, "v1beta3", item, seed) fuzzInternalObject(t, "v1beta3", item, seed)
roundTrip(t, v1beta3.Codec, item) roundTrip(t, v1beta3.Codec, item)
...@@ -103,8 +95,6 @@ func roundTripSame(t *testing.T, item runtime.Object, except ...string) { ...@@ -103,8 +95,6 @@ func roundTripSame(t *testing.T, item runtime.Object, except ...string) {
func roundTripAll(t *testing.T, item runtime.Object) { func roundTripAll(t *testing.T, item runtime.Object) {
seed := rand.Int63() 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)) roundTrip(t, v1beta3.Codec, fuzzInternalObject(t, "v1beta3", item, seed))
} }
...@@ -137,10 +127,7 @@ func TestList(t *testing.T) { ...@@ -137,10 +127,7 @@ func TestList(t *testing.T) {
var nonRoundTrippableTypes = util.NewStringSet("ContainerManifest", "ContainerManifestList") var nonRoundTrippableTypes = util.NewStringSet("ContainerManifest", "ContainerManifestList")
var nonInternalRoundTrippableTypes = util.NewStringSet("List", "ListOptions", "PodExecOptions") var nonInternalRoundTrippableTypes = util.NewStringSet("List", "ListOptions", "PodExecOptions")
var nonRoundTrippableTypesByVersion = map[string][]string{ var nonRoundTrippableTypesByVersion = map[string][]string{}
"PodTemplate": {"v1beta1", "v1beta2"},
"PodTemplateList": {"v1beta1", "v1beta2"},
}
func TestRoundTripTypes(t *testing.T) { func TestRoundTripTypes(t *testing.T) {
// api.Scheme.Log(t) // api.Scheme.Log(t)
......
/*
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
}
}
}
/*
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
/*
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() {}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
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
}
}
}
/*
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
/*
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() {}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -37,8 +37,6 @@ import ( ...@@ -37,8 +37,6 @@ import (
apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
...@@ -55,20 +53,13 @@ func convert(obj runtime.Object) (runtime.Object, error) { ...@@ -55,20 +53,13 @@ func convert(obj runtime.Object) (runtime.Object, error) {
return obj, nil return obj, nil
} }
// This creates a fake API version, similar to api/latest.go for a v1beta1 equivalent api. It is distinct // This creates fake API versions, similar to api/latest.go.
// from the Kubernetes API versions to allow clients to properly distinguish the two.
const testVersion = "version" const testVersion = "version"
const newVersion = "version2"
// The equivalent of the Kubernetes v1beta3 API. var versions = []string{testVersion, newVersion}
const testVersion2 = "version2" var codec = runtime.CodecFor(api.Scheme, testVersion)
var newCodec = runtime.CodecFor(api.Scheme, newVersion)
var versions = []string{testVersion, testVersion2}
var legacyCodec = runtime.CodecFor(api.Scheme, testVersion)
var codec = runtime.CodecFor(api.Scheme, testVersion2)
// these codecs reflect ListOptions/DeleteOptions coming from the serverAPIversion
var versionServerCodec = runtime.CodecFor(api.Scheme, "v1beta1")
var version2ServerCodec = runtime.CodecFor(api.Scheme, "v1beta3")
var accessor = meta.NewAccessor() var accessor = meta.NewAccessor()
var versioner runtime.ResourceVersioner = accessor var versioner runtime.ResourceVersioner = accessor
...@@ -81,13 +72,13 @@ func interfacesFor(version string) (*meta.VersionInterfaces, error) { ...@@ -81,13 +72,13 @@ func interfacesFor(version string) (*meta.VersionInterfaces, error) {
switch version { switch version {
case testVersion: case testVersion:
return &meta.VersionInterfaces{ return &meta.VersionInterfaces{
Codec: legacyCodec, Codec: codec,
ObjectConvertor: api.Scheme, ObjectConvertor: api.Scheme,
MetadataAccessor: accessor, MetadataAccessor: accessor,
}, nil }, nil
case testVersion2: case newVersion:
return &meta.VersionInterfaces{ return &meta.VersionInterfaces{
Codec: codec, Codec: newCodec,
ObjectConvertor: api.Scheme, ObjectConvertor: api.Scheme,
MetadataAccessor: accessor, MetadataAccessor: accessor,
}, nil }, nil
...@@ -109,26 +100,44 @@ func newMapper() *meta.DefaultRESTMapper { ...@@ -109,26 +100,44 @@ func newMapper() *meta.DefaultRESTMapper {
) )
} }
func addTestTypes() {
type ListOptions struct {
runtime.Object
api.TypeMeta `json:",inline"`
LabelSelector string `json:"labels,omitempty"`
FieldSelector string `json:"fields,omitempty"`
Watch bool `json:"watch,omitempty"`
ResourceVersion string `json:"resourceVersion,omitempty"`
}
api.Scheme.AddKnownTypes(testVersion, &Simple{}, &SimpleList{}, &api.Status{}, &ListOptions{}, &api.DeleteOptions{}, &SimpleGetOptions{}, &SimpleRoot{})
}
func addNewTestTypes() {
type ListOptions struct {
runtime.Object
api.TypeMeta `json:",inline"`
LabelSelector string `json:"labelSelector,omitempty"`
FieldSelector string `json:"fieldSelector,omitempty"`
Watch bool `json:"watch,omitempty"`
ResourceVersion string `json:"resourceVersion,omitempty"`
}
api.Scheme.AddKnownTypes(newVersion, &Simple{}, &SimpleList{}, &api.Status{}, &ListOptions{}, &api.DeleteOptions{}, &SimpleGetOptions{}, &SimpleRoot{})
}
func init() { func init() {
// Certain API objects are returned regardless of the contents of storage: // Certain API objects are returned regardless of the contents of storage:
// api.Status is returned in errors // api.Status is returned in errors
// "internal" version // "internal" version
api.Scheme.AddKnownTypes("", &Simple{}, &SimpleList{}, &api.Status{}, &api.ListOptions{}, &SimpleGetOptions{}, &SimpleRoot{}) api.Scheme.AddKnownTypes("", &Simple{}, &SimpleList{}, &api.Status{}, &api.ListOptions{}, &SimpleGetOptions{}, &SimpleRoot{})
// "version" version addTestTypes()
// TODO: Use versioned api objects? addNewTestTypes()
api.Scheme.AddKnownTypes(testVersion, &Simple{}, &SimpleList{}, &v1beta1.Status{}, &SimpleGetOptions{}, &SimpleRoot{})
// "version2" version
// TODO: Use versioned api objects?
api.Scheme.AddKnownTypes(testVersion2, &Simple{}, &SimpleList{}, &v1beta3.Status{}, &SimpleGetOptions{}, &SimpleRoot{})
// Register SimpleGetOptions with the server versions to convert query params to it
api.Scheme.AddKnownTypes("v1beta1", &SimpleGetOptions{})
api.Scheme.AddKnownTypes("v1beta3", &SimpleGetOptions{})
nsMapper := newMapper() nsMapper := newMapper()
legacyNsMapper := newMapper() legacyNsMapper := newMapper()
// enumerate all supported versions, get the kinds, and register with the mapper how to address our resources
// enumerate all supported versions, get the kinds, and register with
// the mapper how to address our resources
for _, version := range versions { for _, version := range versions {
for kind := range api.Scheme.KnownTypes(version) { for kind := range api.Scheme.KnownTypes(version) {
mixedCase := true mixedCase := true
...@@ -149,13 +158,12 @@ func init() { ...@@ -149,13 +158,12 @@ func init() {
admissionControl = admit.NewAlwaysAdmit() admissionControl = admit.NewAlwaysAdmit()
requestContextMapper = api.NewRequestContextMapper() requestContextMapper = api.NewRequestContextMapper()
//mapper.(*meta.DefaultRESTMapper).Add(meta.RESTScopeNamespaceLegacy, "Simple", testVersion, false)
api.Scheme.AddFieldLabelConversionFunc(testVersion, "Simple", api.Scheme.AddFieldLabelConversionFunc(testVersion, "Simple",
func(label, value string) (string, string, error) { func(label, value string) (string, string, error) {
return label, value, nil return label, value, nil
}, },
) )
api.Scheme.AddFieldLabelConversionFunc(testVersion2, "Simple", api.Scheme.AddFieldLabelConversionFunc(newVersion, "Simple",
func(label, value string) (string, string, error) { func(label, value string) (string, string, error) {
return label, value, nil return label, value, nil
}, },
...@@ -210,13 +218,13 @@ func handleInternal(legacy bool, storage map[string]rest.Storage, admissionContr ...@@ -210,13 +218,13 @@ func handleInternal(legacy bool, storage map[string]rest.Storage, admissionContr
} }
if legacy { if legacy {
group.Version = testVersion group.Version = testVersion
group.ServerVersion = "v1beta1" group.ServerVersion = testVersion
group.Codec = legacyCodec group.Codec = codec
group.Mapper = legacyNamespaceMapper group.Mapper = legacyNamespaceMapper
} else { } else {
group.Version = testVersion2 group.Version = newVersion
group.ServerVersion = "v1beta3" group.ServerVersion = newVersion
group.Codec = codec group.Codec = newCodec
group.Mapper = namespaceMapper group.Mapper = namespaceMapper
} }
...@@ -757,7 +765,7 @@ func TestList(t *testing.T) { ...@@ -757,7 +765,7 @@ func TestList(t *testing.T) {
selfLink: "/api/version/simple?namespace=", selfLink: "/api/version/simple?namespace=",
legacy: true, legacy: true,
}, },
// list items in a namespace, v1beta3+ // list items in a namespace in the path
{ {
url: "/api/version2/namespaces/default/simple", url: "/api/version2/namespaces/default/simple",
namespace: "default", namespace: "default",
...@@ -1378,7 +1386,7 @@ func TestDeleteWithOptions(t *testing.T) { ...@@ -1378,7 +1386,7 @@ func TestDeleteWithOptions(t *testing.T) {
item := &api.DeleteOptions{ item := &api.DeleteOptions{
GracePeriodSeconds: &grace, GracePeriodSeconds: &grace,
} }
body, err := versionServerCodec.Encode(item) body, err := codec.Encode(item)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -1439,7 +1447,7 @@ func TestLegacyDeleteIgnoresOptions(t *testing.T) { ...@@ -1439,7 +1447,7 @@ func TestLegacyDeleteIgnoresOptions(t *testing.T) {
defer server.Close() defer server.Close()
item := api.NewDeleteOptions(300) item := api.NewDeleteOptions(300)
body, err := versionServerCodec.Encode(item) body, err := codec.Encode(item)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -1888,9 +1896,9 @@ func TestParentResourceIsRequired(t *testing.T) { ...@@ -1888,9 +1896,9 @@ func TestParentResourceIsRequired(t *testing.T) {
Context: requestContextMapper, Context: requestContextMapper,
Mapper: namespaceMapper, Mapper: namespaceMapper,
Version: testVersion2, Version: newVersion,
ServerVersion: "v1beta3", ServerVersion: newVersion,
Codec: codec, Codec: newCodec,
} }
container := restful.NewContainer() container := restful.NewContainer()
if err := group.InstallREST(container); err == nil { if err := group.InstallREST(container); err == nil {
...@@ -1916,9 +1924,9 @@ func TestParentResourceIsRequired(t *testing.T) { ...@@ -1916,9 +1924,9 @@ func TestParentResourceIsRequired(t *testing.T) {
Context: requestContextMapper, Context: requestContextMapper,
Mapper: namespaceMapper, Mapper: namespaceMapper,
Version: testVersion2, Version: newVersion,
ServerVersion: "v1beta3", ServerVersion: newVersion,
Codec: codec, Codec: newCodec,
} }
container = restful.NewContainer() container = restful.NewContainer()
if err := group.InstallREST(container); err != nil { if err := group.InstallREST(container); err != nil {
......
...@@ -303,7 +303,7 @@ func TestWatchHTTPTimeout(t *testing.T) { ...@@ -303,7 +303,7 @@ func TestWatchHTTPTimeout(t *testing.T) {
// Setup a new watchserver // Setup a new watchserver
watchServer := &WatchServer{ watchServer := &WatchServer{
watcher, watcher,
version2ServerCodec, newCodec,
func(obj runtime.Object) {}, func(obj runtime.Object) {},
&fakeTimeoutFactory{timeoutCh, done}, &fakeTimeoutFactory{timeoutCh, done},
} }
...@@ -315,13 +315,13 @@ func TestWatchHTTPTimeout(t *testing.T) { ...@@ -315,13 +315,13 @@ func TestWatchHTTPTimeout(t *testing.T) {
// Setup a client // Setup a client
dest, _ := url.Parse(s.URL) dest, _ := url.Parse(s.URL)
dest.Path = "/api/version/watch/resource" dest.Path = "/api/" + newVersion + "/simple"
dest.RawQuery = "" dest.RawQuery = "watch=true"
req, _ := http.NewRequest("GET", dest.String(), nil) req, _ := http.NewRequest("GET", dest.String(), nil)
client := http.Client{} client := http.Client{}
resp, err := client.Do(req) resp, err := client.Do(req)
watcher.Add(&api.Pod{TypeMeta: api.TypeMeta{APIVersion: "v1beta3"}}) watcher.Add(&Simple{TypeMeta: api.TypeMeta{APIVersion: newVersion}})
// Make sure we can actually watch an endpoint // Make sure we can actually watch an endpoint
decoder := json.NewDecoder(resp.Body) decoder := json.NewDecoder(resp.Body)
......
...@@ -107,14 +107,6 @@ func TestExec(t *testing.T) { ...@@ -107,14 +107,6 @@ func TestExec(t *testing.T) {
execErr bool execErr bool
}{ }{
{ {
name: "v1beta1 - pod exec",
version: "v1beta1",
podPath: "/api/v1beta1/pods/foo",
execPath: "/api/v1beta1/pods/foo/exec",
nsInQuery: true,
pod: execPod(),
},
{
name: "v1beta3 - pod exec", name: "v1beta3 - pod exec",
version: "v1beta3", version: "v1beta3",
podPath: "/api/v1beta3/namespaces/test/pods/foo", podPath: "/api/v1beta3/namespaces/test/pods/foo",
......
...@@ -155,10 +155,10 @@ func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { ...@@ -155,10 +155,10 @@ func TestGetUnknownSchemaObjectListGeneric(t *testing.T) {
obj2 string obj2 string
}{ }{
"handles specific version": { "handles specific version": {
output: "v1beta3", output: "v1",
list: "v1beta3", list: "v1",
obj1: "unlikelyversion", obj1: "unlikelyversion",
obj2: "v1beta3", obj2: "v1",
}, },
"handles second specific version": { "handles second specific version": {
output: "unlikelyversion", output: "unlikelyversion",
...@@ -167,14 +167,14 @@ func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { ...@@ -167,14 +167,14 @@ func TestGetUnknownSchemaObjectListGeneric(t *testing.T) {
obj2: "v1beta3", // version of the API response obj2: "v1beta3", // version of the API response
}, },
"handles common version": { "handles common version": {
output: "v1beta1", output: "v1beta3",
list: "v1beta1", list: "v1beta3",
obj1: "unlikelyversion", // because test scheme defaults to unlikelyversion obj1: "unlikelyversion", // because test scheme defaults to unlikelyversion
obj2: "v1beta1", obj2: "v1beta3",
}, },
} }
for k, test := range testCases { for k, test := range testCases {
apiCodec := runtime.CodecFor(api.Scheme, "v1beta1") apiCodec := runtime.CodecFor(api.Scheme, "v1beta3")
regularClient := &client.FakeRESTClient{ regularClient := &client.FakeRESTClient{
Codec: apiCodec, Codec: apiCodec,
Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) {
......
...@@ -157,14 +157,6 @@ func TestLog(t *testing.T) { ...@@ -157,14 +157,6 @@ func TestLog(t *testing.T) {
pod *api.Pod pod *api.Pod
}{ }{
{ {
name: "v1beta1 - pod log",
version: "v1beta1",
podPath: "/api/v1beta1/pods/foo",
logPath: "/api/v1beta1/pods/foo/log",
nsInQuery: true,
pod: testPod(),
},
{
name: "v1beta3 - pod log", name: "v1beta3 - pod log",
version: "v1beta3", version: "v1beta3",
podPath: "/api/v1beta3/namespaces/test/pods/foo", podPath: "/api/v1beta3/namespaces/test/pods/foo",
......
...@@ -46,14 +46,6 @@ func TestPortForward(t *testing.T) { ...@@ -46,14 +46,6 @@ func TestPortForward(t *testing.T) {
pfErr bool pfErr bool
}{ }{
{ {
name: "v1beta1 - pod portforward",
version: "v1beta1",
podPath: "/api/v1beta1/pods/foo",
pfPath: "/api/v1beta1/pods/foo/portforward",
nsInQuery: true,
pod: execPod(),
},
{
name: "v1beta3 - pod portforward", name: "v1beta3 - pod portforward",
version: "v1beta3", version: "v1beta3",
podPath: "/api/v1beta3/namespaces/test/pods/foo", podPath: "/api/v1beta3/namespaces/test/pods/foo",
......
...@@ -43,7 +43,7 @@ func TestMerge(t *testing.T) { ...@@ -43,7 +43,7 @@ func TestMerge(t *testing.T) {
Name: "foo", Name: "foo",
}, },
}, },
fragment: `{ "apiVersion": "v1beta1" }`, fragment: `{ "apiVersion": "v1beta3" }`,
expected: &api.Pod{ expected: &api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "foo", Name: "foo",
...@@ -101,25 +101,6 @@ func TestMerge(t *testing.T) { ...@@ -101,25 +101,6 @@ func TestMerge(t *testing.T) {
Name: "foo", Name: "foo",
}, },
}, },
fragment: `{ "apiVersion": "v1beta1", "id": "baz", "desiredState": { "host": "bar" } }`,
expected: &api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "baz",
},
Spec: api.PodSpec{
NodeName: "bar",
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
},
},
},
{
kind: "Pod",
obj: &api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
},
fragment: `{ "apiVersion": "v1beta3", "spec": { "volumes": [ {"name": "v1"}, {"name": "v2"} ] } }`, fragment: `{ "apiVersion": "v1beta3", "spec": { "volumes": [ {"name": "v1"}, {"name": "v2"} ] } }`,
expected: &api.Pod{ expected: &api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
...@@ -149,24 +130,6 @@ func TestMerge(t *testing.T) { ...@@ -149,24 +130,6 @@ func TestMerge(t *testing.T) {
expectErr: true, expectErr: true,
}, },
{ {
kind: "Pod",
obj: &api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
},
fragment: `{ "apiVersion": "v1beta1", "id": null}`,
expected: &api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "",
},
Spec: api.PodSpec{
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
},
},
},
{
kind: "Service", kind: "Service",
obj: &api.Service{}, obj: &api.Service{},
fragment: `{ "apiVersion": "badVersion" }`, fragment: `{ "apiVersion": "badVersion" }`,
...@@ -177,11 +140,17 @@ func TestMerge(t *testing.T) { ...@@ -177,11 +140,17 @@ func TestMerge(t *testing.T) {
obj: &api.Service{ obj: &api.Service{
Spec: api.ServiceSpec{}, Spec: api.ServiceSpec{},
}, },
fragment: `{ "apiVersion": "v1beta1", "port": 0 }`, fragment: `{ "apiVersion": "v1beta3", "spec": { "ports": [ { "port": 0 } ] } }`,
expected: &api.Service{ expected: &api.Service{
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
SessionAffinity: "None", SessionAffinity: "None",
Type: api.ServiceTypeClusterIP, Type: api.ServiceTypeClusterIP,
Ports: []api.ServicePort{
{
Protocol: api.ProtocolTCP,
Port: 0,
},
},
}, },
}, },
}, },
...@@ -194,7 +163,7 @@ func TestMerge(t *testing.T) { ...@@ -194,7 +163,7 @@ func TestMerge(t *testing.T) {
}, },
}, },
}, },
fragment: `{ "apiVersion": "v1beta1", "selector": { "version": "v2" } }`, fragment: `{ "apiVersion": "v1beta3", "spec": { "selector": { "version": "v2" } } }`,
expected: &api.Service{ expected: &api.Service{
Spec: api.ServiceSpec{ Spec: api.ServiceSpec{
SessionAffinity: "None", SessionAffinity: "None",
......
...@@ -24,14 +24,12 @@ import ( ...@@ -24,14 +24,12 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
utilyaml "github.com/GoogleCloudPlatform/kubernetes/pkg/util/yaml" utilyaml "github.com/GoogleCloudPlatform/kubernetes/pkg/util/yaml"
"github.com/ghodss/yaml"
"github.com/golang/glog" "github.com/golang/glog"
) )
...@@ -144,68 +142,3 @@ func tryDecodePodList(data []byte, defaultFn defaultFunc) (parsed bool, pods api ...@@ -144,68 +142,3 @@ func tryDecodePodList(data []byte, defaultFn defaultFunc) (parsed bool, pods api
} }
return true, *newPods, err return true, *newPods, err
} }
func tryDecodeSingleManifest(data []byte, defaultFn defaultFunc) (parsed bool, manifest v1beta1.ContainerManifest, pod *api.Pod, err error) {
// TODO: should be api.Scheme.Decode
// This is awful. DecodeInto() expects to find an APIObject, which
// Manifest is not. We keep reading manifest for now for compat, but
// we will eventually change it to read Pod (at which point this all
// becomes nicer). Until then, we assert that the ContainerManifest
// structure on disk is always v1beta1. Read that, convert it to a
// "current" ContainerManifest (should be ~identical), then convert
// that to a Pod (which is a well-understood conversion). This
// avoids writing a v1beta1.ContainerManifest -> api.Pod
// conversion which would be identical to the api.ContainerManifest ->
// api.Pod conversion.
pod = new(api.Pod)
if err = yaml.Unmarshal(data, &manifest); err != nil {
return false, manifest, pod, err
}
newManifest := api.ContainerManifest{}
if err = api.Scheme.Convert(&manifest, &newManifest); err != nil {
return false, manifest, pod, err
}
if errs := validation.ValidateManifest(&newManifest); len(errs) > 0 {
err = fmt.Errorf("invalid manifest: %v", errs)
return false, manifest, pod, err
}
if err = api.Scheme.Convert(&newManifest, pod); err != nil {
return true, manifest, pod, err
}
if err := defaultFn(pod); err != nil {
return true, manifest, pod, err
}
// Success.
return true, manifest, pod, nil
}
func tryDecodeManifestList(data []byte, defaultFn defaultFunc) (parsed bool, manifests []v1beta1.ContainerManifest, pods api.PodList, err error) {
// TODO: should be api.Scheme.Decode
// See the comment in tryDecodeSingle().
if err = yaml.Unmarshal(data, &manifests); err != nil {
return false, manifests, pods, err
}
newManifests := []api.ContainerManifest{}
if err = api.Scheme.Convert(&manifests, &newManifests); err != nil {
return false, manifests, pods, err
}
for i := range newManifests {
manifest := &newManifests[i]
if errs := validation.ValidateManifest(manifest); len(errs) > 0 {
err = fmt.Errorf("invalid manifest: %v", errs)
return false, manifests, pods, err
}
}
list := api.ContainerManifestList{Items: newManifests}
if err = api.Scheme.Convert(&list, &pods); err != nil {
return true, manifests, pods, err
}
for i := range pods.Items {
pod := &pods.Items[i]
if err := defaultFn(pod); err != nil {
return true, manifests, pods, err
}
}
// Success.
return true, manifests, pods, nil
}
...@@ -148,15 +148,6 @@ func (s *sourceFile) extractFromFile(filename string) (pod *api.Pod, err error) ...@@ -148,15 +148,6 @@ func (s *sourceFile) extractFromFile(filename string) (pod *api.Pod, err error)
return s.applyDefaults(pod, filename) return s.applyDefaults(pod, filename)
} }
parsed, _, pod, manifestErr := tryDecodeSingleManifest(data, defaultFn)
if parsed {
if manifestErr != nil {
// It parsed but could not be used.
return pod, manifestErr
}
return pod, nil
}
parsed, pod, podErr := tryDecodeSinglePod(data, defaultFn) parsed, pod, podErr := tryDecodeSinglePod(data, defaultFn)
if parsed { if parsed {
if podErr != nil { if podErr != nil {
...@@ -165,7 +156,6 @@ func (s *sourceFile) extractFromFile(filename string) (pod *api.Pod, err error) ...@@ -165,7 +156,6 @@ func (s *sourceFile) extractFromFile(filename string) (pod *api.Pod, err error)
return pod, nil return pod, nil
} }
return pod, fmt.Errorf("%v: read '%v', but couldn't parse as neither "+ return pod, fmt.Errorf("%v: read '%v', but couldn't parse as pod(%v).\n",
"manifest (%v) nor pod (%v).\n", filename, string(data), podErr)
filename, string(data), manifestErr, podErr)
} }
...@@ -17,22 +17,18 @@ limitations under the License. ...@@ -17,22 +17,18 @@ limitations under the License.
package config package config
import ( import (
"encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"sort"
"testing" "testing"
"time" "time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/securitycontext" "github.com/GoogleCloudPlatform/kubernetes/pkg/securitycontext"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
) )
func TestExtractFromNonExistentFile(t *testing.T) { func TestExtractFromNonExistentFile(t *testing.T) {
...@@ -339,111 +335,3 @@ func TestExtractFromEmptyDir(t *testing.T) { ...@@ -339,111 +335,3 @@ func TestExtractFromEmptyDir(t *testing.T) {
t.Errorf("Expected %#v, Got %#v", expected, update) t.Errorf("Expected %#v, Got %#v", expected, update)
} }
} }
func exampleManifestAndPod(id string) (v1beta1.ContainerManifest, *api.Pod) {
hostname := "an-example-host"
manifest := v1beta1.ContainerManifest{
Version: "v1beta1",
ID: id,
UUID: types.UID(id),
Containers: []v1beta1.Container{
{
Name: "c" + id,
Image: "foo",
TerminationMessagePath: "/somepath",
},
},
Volumes: []v1beta1.Volume{
{
Name: "host-dir",
Source: v1beta1.VolumeSource{
HostDir: &v1beta1.HostPathVolumeSource{"/dir/path"},
},
},
},
}
expectedPod := &api.Pod{
ObjectMeta: api.ObjectMeta{
Name: id + "-" + hostname,
UID: types.UID(id),
Namespace: kubelet.NamespaceDefault,
SelfLink: getSelfLink(id+"-"+hostname, kubelet.NamespaceDefault),
},
Spec: api.PodSpec{
NodeName: hostname,
Containers: []api.Container{
{
Name: "c" + id,
Image: "foo",
},
},
Volumes: []api.Volume{
{
Name: "host-dir",
VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{"/dir/path"},
},
},
},
},
}
return manifest, expectedPod
}
func TestExtractFromDir(t *testing.T) {
if !api.PreV1Beta3(testapi.Version()) {
return
}
manifest, expectedPod := exampleManifestAndPod("1")
manifest2, expectedPod2 := exampleManifestAndPod("2")
manifests := []v1beta1.ContainerManifest{manifest, manifest2}
pods := []*api.Pod{expectedPod, expectedPod2}
files := make([]*os.File, len(manifests))
dirName, err := ioutil.TempDir("", "foo")
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
for i, manifest := range manifests {
data, err := json.Marshal(manifest)
if err != nil {
t.Errorf("Unexpected error: %v", err)
continue
}
file, err := ioutil.TempFile(dirName, manifest.ID)
if err != nil {
t.Errorf("Unexpected error: %v", err)
continue
}
name := file.Name()
if err := file.Close(); err != nil {
t.Errorf("Unexpected error: %v", err)
continue
}
ioutil.WriteFile(name, data, 0755)
files[i] = file
}
ch := make(chan interface{}, 1)
c := sourceFile{dirName, "an-example-host", ch}
err = c.extractFromPath()
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
update := (<-ch).(kubelet.PodUpdate)
expected := CreatePodUpdate(kubelet.SET, kubelet.FileSource, pods...)
sort.Sort(sortedPods(update.Pods))
sort.Sort(sortedPods(expected.Pods))
if !api.Semantic.DeepDerivative(expected, update) {
t.Fatalf("Expected %#v, Got %#v", expected, update)
}
for _, pod := range update.Pods {
if errs := validation.ValidatePod(pod); len(errs) != 0 {
t.Errorf("Expected no validation errors on %#v, Got %q", pod, errs)
}
}
}
...@@ -77,50 +77,12 @@ func (s *sourceURL) extractFromURL() error { ...@@ -77,50 +77,12 @@ func (s *sourceURL) extractFromURL() error {
s.updates <- kubelet.PodUpdate{[]*api.Pod{}, kubelet.SET, kubelet.HTTPSource} s.updates <- kubelet.PodUpdate{[]*api.Pod{}, kubelet.SET, kubelet.HTTPSource}
return fmt.Errorf("zero-length data received from %v", s.url) return fmt.Errorf("zero-length data received from %v", s.url)
} }
// Short circuit if the manifest has not changed since the last time it was read. // Short circuit if the data has not changed since the last time it was read.
if bytes.Compare(data, s.data) == 0 { if bytes.Compare(data, s.data) == 0 {
return nil return nil
} }
s.data = data s.data = data
// First try as if it's a single manifest
parsed, manifest, pod, singleErr := tryDecodeSingleManifest(data, s.applyDefaults)
if parsed {
if singleErr != nil {
// It parsed but could not be used.
return singleErr
}
// It parsed!
s.updates <- kubelet.PodUpdate{[]*api.Pod{pod}, kubelet.SET, kubelet.HTTPSource}
return nil
}
// That didn't work, so try an array of manifests.
parsed, manifests, podList, multiErr := tryDecodeManifestList(data, s.applyDefaults)
if parsed {
if multiErr != nil {
// It parsed but could not be used.
return multiErr
}
// A single manifest that did not pass semantic validation will yield an empty
// array of manifests (and no error) when unmarshaled as such. In that case,
// if the single manifest at least had a Version, we return the single-manifest
// error (if any).
if len(manifests) == 0 && len(manifest.Version) != 0 {
return singleErr
}
// It parsed!
pods := make([]*api.Pod, 0)
for i := range podList.Items {
pods = append(pods, &podList.Items[i])
}
s.updates <- kubelet.PodUpdate{pods, kubelet.SET, kubelet.HTTPSource}
return nil
}
// Parsing it as ContainerManifest(s) failed.
// Try to parse it as Pod(s).
// First try as it is a single pod. // First try as it is a single pod.
parsed, pod, singlePodErr := tryDecodeSinglePod(data, s.applyDefaults) parsed, pod, singlePodErr := tryDecodeSinglePod(data, s.applyDefaults)
if parsed { if parsed {
...@@ -147,9 +109,7 @@ func (s *sourceURL) extractFromURL() error { ...@@ -147,9 +109,7 @@ func (s *sourceURL) extractFromURL() error {
return nil return nil
} }
return fmt.Errorf("%v: received '%v', but couldn't parse as neither "+ return fmt.Errorf("%v: received '%v', but couldn't parse as "+
"single (%v: %+v) or multiple manifests (%v: %+v) nor "+
"single (%v) or multiple pods (%v).\n", "single (%v) or multiple pods (%v).\n",
s.url, string(data), singleErr, manifest, multiErr, manifests, s.url, string(data), singlePodErr, multiPodErr)
singlePodErr, multiPodErr)
} }
...@@ -24,7 +24,6 @@ import ( ...@@ -24,7 +24,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
...@@ -118,195 +117,6 @@ func TestExtractInvalidManifest(t *testing.T) { ...@@ -118,195 +117,6 @@ func TestExtractInvalidManifest(t *testing.T) {
} }
} }
func TestExtractManifestFromHTTP(t *testing.T) {
hostname := "random-hostname"
// ContainerManifests are not supported v1beta3 onwards.
if api.PreV1Beta3(testapi.Version()) {
return
}
var testCases = []struct {
desc string
manifests interface{}
expected kubelet.PodUpdate
}{
{
desc: "Single manifest",
manifests: v1beta1.ContainerManifest{Version: "v1beta1", ID: "foo", UUID: "111",
Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1beta1.PullAlways}}},
expected: CreatePodUpdate(kubelet.SET,
kubelet.HTTPSource,
&api.Pod{
ObjectMeta: api.ObjectMeta{
UID: "111",
Name: "foo" + "-" + hostname,
Namespace: "foobar",
SelfLink: getSelfLink("foo-"+hostname, kubelet.NamespaceDefault),
},
Spec: api.PodSpec{
NodeName: hostname,
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
Containers: []api.Container{{
Name: "1",
Image: "foo",
TerminationMessagePath: "/dev/termination-log",
ImagePullPolicy: "Always",
SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}},
},
}),
},
{
desc: "Single manifest without ID",
manifests: v1beta1.ContainerManifest{Version: "v1beta1", UUID: "111",
Containers: []v1beta1.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}},
expected: CreatePodUpdate(kubelet.SET,
kubelet.HTTPSource,
&api.Pod{
ObjectMeta: api.ObjectMeta{
UID: "111",
Name: "111" + "-" + hostname,
Namespace: "foobar",
SelfLink: getSelfLink("111-"+hostname, kubelet.NamespaceDefault),
},
Spec: api.PodSpec{
NodeName: hostname,
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
Containers: []api.Container{{
Name: "ctr",
Image: "image",
TerminationMessagePath: "/dev/termination-log",
ImagePullPolicy: "IfNotPresent",
SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}},
},
}),
},
{
desc: "Single manifest with v1beta2",
manifests: v1beta1.ContainerManifest{Version: "v1beta2", ID: "foo", UUID: "111",
Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1beta1.PullAlways}}},
expected: CreatePodUpdate(kubelet.SET,
kubelet.HTTPSource,
&api.Pod{
ObjectMeta: api.ObjectMeta{
UID: "111",
Name: "foo" + "-" + hostname,
Namespace: "foobar",
SelfLink: getSelfLink("foo-"+hostname, kubelet.NamespaceDefault),
},
Spec: api.PodSpec{
NodeName: hostname,
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
Containers: []api.Container{{
Name: "1",
Image: "foo",
TerminationMessagePath: "/dev/termination-log",
ImagePullPolicy: "Always",
SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}},
},
}),
},
{
desc: "Multiple manifests",
manifests: []v1beta1.ContainerManifest{
{Version: "v1beta1", ID: "foo", UUID: "111",
Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: v1beta1.PullAlways}}},
{Version: "v1beta1", ID: "bar", UUID: "222",
Containers: []v1beta1.Container{{Name: "1", Image: "foo", ImagePullPolicy: ""}}},
},
expected: CreatePodUpdate(kubelet.SET,
kubelet.HTTPSource,
&api.Pod{
ObjectMeta: api.ObjectMeta{
UID: "111",
Name: "foo" + "-" + hostname,
Namespace: "foobar",
SelfLink: getSelfLink("foo-"+hostname, kubelet.NamespaceDefault),
},
Spec: api.PodSpec{
NodeName: hostname,
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
Containers: []api.Container{{
Name: "1",
Image: "foo",
TerminationMessagePath: "/dev/termination-log",
ImagePullPolicy: "Always",
SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}},
},
},
&api.Pod{
ObjectMeta: api.ObjectMeta{
UID: "222",
Name: "bar" + "-" + hostname,
Namespace: "foobar",
SelfLink: getSelfLink("bar-"+hostname, kubelet.NamespaceDefault),
},
Spec: api.PodSpec{
NodeName: hostname,
RestartPolicy: api.RestartPolicyAlways,
DNSPolicy: api.DNSClusterFirst,
Containers: []api.Container{{
Name: "1",
Image: "foo",
TerminationMessagePath: "/dev/termination-log",
ImagePullPolicy: "IfNotPresent",
SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults()}},
},
}),
},
{
desc: "Empty Array",
manifests: []v1beta1.ContainerManifest{},
expected: CreatePodUpdate(kubelet.SET, kubelet.HTTPSource),
},
}
for _, testCase := range testCases {
data, err := json.Marshal(testCase.manifests)
if err != nil {
t.Fatalf("%s: Some weird json problem: %v", testCase.desc, err)
}
fakeHandler := util.FakeHandler{
StatusCode: 200,
ResponseBody: string(data),
}
testServer := httptest.NewServer(&fakeHandler)
defer testServer.Close()
ch := make(chan interface{}, 1)
c := sourceURL{testServer.URL, hostname, ch, nil}
if err := c.extractFromURL(); err != nil {
t.Errorf("%s: Unexpected error: %v", testCase.desc, err)
continue
}
update := (<-ch).(kubelet.PodUpdate)
for i := range update.Pods {
// There's no way to provide namespace in ContainerManifest, so
// it will be defaulted.
if update.Pods[i].Namespace != kubelet.NamespaceDefault {
t.Errorf("Unexpected namespace: %s", update.Pods[0].Namespace)
}
update.Pods[i].ObjectMeta.Namespace = "foobar"
}
if !api.Semantic.DeepEqual(testCase.expected, update) {
t.Errorf("%s: Expected: %#v, Got: %#v", testCase.desc, testCase.expected, update)
}
for _, pod := range update.Pods {
if errs := validation.ValidatePod(pod); len(errs) != 0 {
t.Errorf("%s: Expected no validation errors on %#v, Got %v", testCase.desc, pod, errors.NewAggregate(errs))
}
}
}
}
func TestExtractPodsFromHTTP(t *testing.T) { func TestExtractPodsFromHTTP(t *testing.T) {
hostname := "different-value" hostname := "different-value"
......
...@@ -33,8 +33,6 @@ import ( ...@@ -33,8 +33,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1" "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/api/v1beta3"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authenticator" "github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authenticator"
...@@ -91,10 +89,6 @@ type Config struct { ...@@ -91,10 +89,6 @@ type Config struct {
EnableUISupport bool EnableUISupport bool
// allow downstream consumers to disable swagger // allow downstream consumers to disable swagger
EnableSwaggerSupport bool EnableSwaggerSupport bool
// allow v1beta1 to be conditionally disabled
DisableV1Beta1 bool
// allow v1beta2 to be conditionally disabled
DisableV1Beta2 bool
// allow v1beta3 to be conditionally disabled // allow v1beta3 to be conditionally disabled
DisableV1Beta3 bool DisableV1Beta3 bool
// allow v1 to be conditionally enabled // allow v1 to be conditionally enabled
...@@ -170,8 +164,6 @@ type Master struct { ...@@ -170,8 +164,6 @@ type Master struct {
authorizer authorizer.Authorizer authorizer authorizer.Authorizer
admissionControl admission.Interface admissionControl admission.Interface
masterCount int masterCount int
v1beta1 bool
v1beta2 bool
v1beta3 bool v1beta3 bool
v1 bool v1 bool
requestContextMapper api.RequestContextMapper requestContextMapper api.RequestContextMapper
...@@ -328,8 +320,6 @@ func New(c *Config) *Master { ...@@ -328,8 +320,6 @@ func New(c *Config) *Master {
authenticator: c.Authenticator, authenticator: c.Authenticator,
authorizer: c.Authorizer, authorizer: c.Authorizer,
admissionControl: c.AdmissionControl, admissionControl: c.AdmissionControl,
v1beta1: !c.DisableV1Beta1,
v1beta2: !c.DisableV1Beta2,
v1beta3: !c.DisableV1Beta3, v1beta3: !c.DisableV1Beta3,
v1: c.EnableV1, v1: c.EnableV1,
requestContextMapper: c.RequestContextMapper, requestContextMapper: c.RequestContextMapper,
...@@ -501,18 +491,6 @@ func (m *Master) init(c *Config) { ...@@ -501,18 +491,6 @@ func (m *Master) init(c *Config) {
} }
apiVersions := []string{} apiVersions := []string{}
if m.v1beta1 {
if err := m.api_v1beta1().InstallREST(m.handlerContainer); err != nil {
glog.Fatalf("Unable to setup API v1beta1: %v", err)
}
apiVersions = append(apiVersions, "v1beta1")
}
if m.v1beta2 {
if err := m.api_v1beta2().InstallREST(m.handlerContainer); err != nil {
glog.Fatalf("Unable to setup API v1beta2: %v", err)
}
apiVersions = append(apiVersions, "v1beta2")
}
if m.v1beta3 { if m.v1beta3 {
if err := m.api_v1beta3().InstallREST(m.handlerContainer); err != nil { if err := m.api_v1beta3().InstallREST(m.handlerContainer); err != nil {
glog.Fatalf("Unable to setup API v1beta3: %v", err) glog.Fatalf("Unable to setup API v1beta3: %v", err)
...@@ -718,38 +696,6 @@ func (m *Master) defaultAPIGroupVersion() *apiserver.APIGroupVersion { ...@@ -718,38 +696,6 @@ func (m *Master) defaultAPIGroupVersion() *apiserver.APIGroupVersion {
} }
} }
// api_v1beta1 returns the resources and codec for API version v1beta1.
func (m *Master) api_v1beta1() *apiserver.APIGroupVersion {
storage := make(map[string]rest.Storage)
for k, v := range m.storage {
if k == "podTemplates" {
continue
}
storage[k] = v
}
version := m.defaultAPIGroupVersion()
version.Storage = storage
version.Version = "v1beta1"
version.Codec = v1beta1.Codec
return version
}
// api_v1beta2 returns the resources and codec for API version v1beta2.
func (m *Master) api_v1beta2() *apiserver.APIGroupVersion {
storage := make(map[string]rest.Storage)
for k, v := range m.storage {
if k == "podTemplates" {
continue
}
storage[k] = v
}
version := m.defaultAPIGroupVersion()
version.Storage = storage
version.Version = "v1beta2"
version.Codec = v1beta2.Codec
return version
}
// api_v1beta3 returns the resources and codec for API version v1beta3. // api_v1beta3 returns the resources and codec for API version v1beta3.
func (m *Master) api_v1beta3() *apiserver.APIGroupVersion { func (m *Master) api_v1beta3() *apiserver.APIGroupVersion {
storage := make(map[string]rest.Storage) storage := make(map[string]rest.Storage)
......
...@@ -24,8 +24,6 @@ import ( ...@@ -24,8 +24,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/endpoints" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/endpoints"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache" "github.com/GoogleCloudPlatform/kubernetes/pkg/client/cache"
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller/framework" "github.com/GoogleCloudPlatform/kubernetes/pkg/controller/framework"
...@@ -302,12 +300,6 @@ func (e *EndpointController) syncService(key string) { ...@@ -302,12 +300,6 @@ func (e *EndpointController) syncService(key string) {
for i := range service.Spec.Ports { for i := range service.Spec.Ports {
servicePort := &service.Spec.Ports[i] servicePort := &service.Spec.Ports[i]
// TODO: Once v1beta1 and v1beta2 are EOL'ed,
// this can safely assume that TargetPort is
// populated, and findPort() can be removed.
_ = v1beta1.Dependency
_ = v1beta2.Dependency
portName := servicePort.Name portName := servicePort.Name
portProto := servicePort.Protocol portProto := servicePort.Protocol
portNum, err := findPort(pod, servicePort) portNum, err := findPort(pod, servicePort)
...@@ -398,32 +390,14 @@ func (e *EndpointController) checkLeftoverEndpoints() { ...@@ -398,32 +390,14 @@ func (e *EndpointController) checkLeftoverEndpoints() {
} }
} }
func findDefaultPort(pod *api.Pod, servicePort int, proto api.Protocol) int { // findPort locates the container port for the given pod and portName. If the
for _, container := range pod.Spec.Containers { // targetPort is a number, use that. If the targetPort is a string, look that
for _, port := range container.Ports {
if port.Protocol == proto {
return port.ContainerPort
}
}
}
return servicePort
}
// findPort locates the container port for the given manifest and portName.
// If the targetPort is a non-zero number, use that. If the targetPort is 0 or
// not specified, use the first defined port with the same protocol. If no port
// is defined, use the service's port. If the targetPort is an empty string use
// the first defined port with the same protocol. If no port is defined, use
// the service's port. If the targetPort is a non-empty string, look that
// string up in all named ports in all containers in the target pod. If no // string up in all named ports in all containers in the target pod. If no
// match is found, fail. // match is found, fail.
func findPort(pod *api.Pod, svcPort *api.ServicePort) (int, error) { func findPort(pod *api.Pod, svcPort *api.ServicePort) (int, error) {
portName := svcPort.TargetPort portName := svcPort.TargetPort
switch portName.Kind { switch portName.Kind {
case util.IntstrString: case util.IntstrString:
if len(portName.StrVal) == 0 {
return findDefaultPort(pod, svcPort.Port, svcPort.Protocol), nil
}
name := portName.StrVal name := portName.StrVal
for _, container := range pod.Spec.Containers { for _, container := range pod.Spec.Containers {
for _, port := range container.Ports { for _, port := range container.Ports {
...@@ -433,9 +407,6 @@ func findPort(pod *api.Pod, svcPort *api.ServicePort) (int, error) { ...@@ -433,9 +407,6 @@ func findPort(pod *api.Pod, svcPort *api.ServicePort) (int, error) {
} }
} }
case util.IntstrInt: case util.IntstrInt:
if portName.IntVal == 0 {
return findDefaultPort(pod, svcPort.Port, svcPort.Protocol), nil
}
return portName.IntVal, nil return portName.IntVal, nil
} }
......
...@@ -63,7 +63,6 @@ func addPods(store cache.Store, namespace string, nPods int, nPorts int) { ...@@ -63,7 +63,6 @@ func addPods(store cache.Store, namespace string, nPods int, nPorts int) {
} }
func TestFindPort(t *testing.T) { func TestFindPort(t *testing.T) {
servicePort := 999
testCases := []struct { testCases := []struct {
name string name string
containers []api.Container containers []api.Container
...@@ -91,74 +90,6 @@ func TestFindPort(t *testing.T) { ...@@ -91,74 +90,6 @@ func TestFindPort(t *testing.T) {
expected: 93, expected: 93,
pass: true, pass: true,
}, { }, {
name: "zero int, no ports",
containers: []api.Container{{}},
port: util.NewIntOrStringFromInt(0),
expected: servicePort,
pass: true,
}, {
name: "zero int, one ctr with ports",
containers: []api.Container{{Ports: []api.ContainerPort{{
Name: "",
ContainerPort: 11,
Protocol: "UDP",
}, {
Name: "p",
ContainerPort: 22,
Protocol: "TCP",
}}}},
port: util.NewIntOrStringFromInt(0),
expected: 22,
pass: true,
}, {
name: "zero int, two ctr with ports",
containers: []api.Container{{}, {Ports: []api.ContainerPort{{
Name: "",
ContainerPort: 11,
Protocol: "UDP",
}, {
Name: "p",
ContainerPort: 22,
Protocol: "TCP",
}}}},
port: util.NewIntOrStringFromInt(0),
expected: 22,
pass: true,
}, {
name: "empty str, no ports",
containers: []api.Container{{}},
port: util.NewIntOrStringFromString(""),
expected: servicePort,
pass: true,
}, {
name: "empty str, one ctr with ports",
containers: []api.Container{{Ports: []api.ContainerPort{{
Name: "",
ContainerPort: 11,
Protocol: "UDP",
}, {
Name: "p",
ContainerPort: 22,
Protocol: "TCP",
}}}},
port: util.NewIntOrStringFromString(""),
expected: 22,
pass: true,
}, {
name: "empty str, two ctr with ports",
containers: []api.Container{{}, {Ports: []api.ContainerPort{{
Name: "",
ContainerPort: 11,
Protocol: "UDP",
}, {
Name: "p",
ContainerPort: 22,
Protocol: "TCP",
}}}},
port: util.NewIntOrStringFromString(""),
expected: 22,
pass: true,
}, {
name: "valid str, no ports", name: "valid str, no ports",
containers: []api.Container{{}}, containers: []api.Container{{}},
port: util.NewIntOrStringFromString("p"), port: util.NewIntOrStringFromString("p"),
...@@ -204,7 +135,7 @@ func TestFindPort(t *testing.T) { ...@@ -204,7 +135,7 @@ func TestFindPort(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
port, err := findPort(&api.Pod{Spec: api.PodSpec{Containers: tc.containers}}, port, err := findPort(&api.Pod{Spec: api.PodSpec{Containers: tc.containers}},
&api.ServicePort{Protocol: "TCP", Port: servicePort, TargetPort: tc.port}) &api.ServicePort{Protocol: "TCP", TargetPort: tc.port})
if err != nil && tc.pass { if err != nil && tc.pass {
t.Errorf("unexpected error for %s: %v", tc.name, err) t.Errorf("unexpected error for %s: %v", tc.name, err)
} }
......
...@@ -8,7 +8,7 @@ matrix: ...@@ -8,7 +8,7 @@ matrix:
include: include:
- go: 1.4 - go: 1.4
env: env:
- KUBE_TEST_API_VERSIONS=v1beta1 KUBE_TEST_ETCD_PREFIXES=registry - KUBE_TEST_API_VERSIONS=v1beta3 KUBE_TEST_ETCD_PREFIXES=registry
- go: 1.3 - go: 1.3
env: env:
- KUBE_TEST_API_VERSIONS=v1beta3 KUBE_TEST_ETCD_PREFIXES=kubernetes.io/registry - KUBE_TEST_API_VERSIONS=v1beta3 KUBE_TEST_ETCD_PREFIXES=kubernetes.io/registry
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment