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:
Kris
2015-05-22 08:20:27 -07:00
parent f3b4b1aa31
commit f4e2c738f6
55 changed files with 3449 additions and 37462 deletions

View File

@@ -24,14 +24,12 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"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/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
utilyaml "github.com/GoogleCloudPlatform/kubernetes/pkg/util/yaml"
"github.com/ghodss/yaml"
"github.com/golang/glog"
)
@@ -144,68 +142,3 @@ func tryDecodePodList(data []byte, defaultFn defaultFunc) (parsed bool, pods api
}
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
}

View File

@@ -148,15 +148,6 @@ func (s *sourceFile) extractFromFile(filename string) (pod *api.Pod, err error)
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)
if parsed {
if podErr != nil {
@@ -165,7 +156,6 @@ func (s *sourceFile) extractFromFile(filename string) (pod *api.Pod, err error)
return pod, nil
}
return pod, fmt.Errorf("%v: read '%v', but couldn't parse as neither "+
"manifest (%v) nor pod (%v).\n",
filename, string(data), manifestErr, podErr)
return pod, fmt.Errorf("%v: read '%v', but couldn't parse as pod(%v).\n",
filename, string(data), podErr)
}

View File

@@ -17,22 +17,18 @@ limitations under the License.
package config
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"sort"
"testing"
"time"
"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/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/securitycontext"
"github.com/GoogleCloudPlatform/kubernetes/pkg/types"
)
func TestExtractFromNonExistentFile(t *testing.T) {
@@ -339,111 +335,3 @@ func TestExtractFromEmptyDir(t *testing.T) {
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)
}
}
}

View File

@@ -77,50 +77,12 @@ func (s *sourceURL) extractFromURL() error {
s.updates <- kubelet.PodUpdate{[]*api.Pod{}, kubelet.SET, kubelet.HTTPSource}
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 {
return nil
}
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.
parsed, pod, singlePodErr := tryDecodeSinglePod(data, s.applyDefaults)
if parsed {
@@ -147,9 +109,7 @@ func (s *sourceURL) extractFromURL() error {
return nil
}
return fmt.Errorf("%v: received '%v', but couldn't parse as neither "+
"single (%v: %+v) or multiple manifests (%v: %+v) nor "+
return fmt.Errorf("%v: received '%v', but couldn't parse as "+
"single (%v) or multiple pods (%v).\n",
s.url, string(data), singleErr, manifest, multiErr, manifests,
singlePodErr, multiPodErr)
s.url, string(data), singlePodErr, multiPodErr)
}

View File

@@ -24,7 +24,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/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@@ -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) {
hostname := "different-value"