move third party resource tests

pull/6/head
deads2k 2016-09-29 13:01:49 -04:00
parent 1c667e4fc5
commit 1123f6788b
2 changed files with 248 additions and 655 deletions

View File

@ -17,7 +17,6 @@ limitations under the License.
package master
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
@ -30,7 +29,6 @@ import (
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/api/unversioned"
apiv1 "k8s.io/kubernetes/pkg/api/v1"
@ -50,13 +48,8 @@ import (
"k8s.io/kubernetes/pkg/genericapiserver"
"k8s.io/kubernetes/pkg/kubelet/client"
ipallocator "k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
extensionsrest "k8s.io/kubernetes/pkg/registry/extensions/rest"
"k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/registry/registrytest"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage"
"k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/kubernetes/pkg/util/sets"
@ -67,7 +60,6 @@ import (
"github.com/go-openapi/strfmt"
"github.com/go-openapi/validate"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
// setUp is a convience function for setting up for (most) tests.
@ -289,6 +281,19 @@ func TestGetNodeAddresses(t *testing.T) {
assert.Equal([]string{"127.0.0.2", "127.0.0.2"}, addrs)
}
func decodeResponse(resp *http.Response, obj interface{}) error {
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
if err := json.Unmarshal(data, obj); err != nil {
return err
}
return nil
}
// Because we need to be backwards compatible with release 1.1, at endpoints
// that exist in release 1.1, the responses should have empty APIVersion.
func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) {
@ -477,613 +482,6 @@ func TestDiscoveryAtAPIS(t *testing.T) {
}
}
var versionsToTest = []string{"v1", "v3"}
type Foo struct {
unversioned.TypeMeta `json:",inline"`
api.ObjectMeta `json:"metadata,omitempty" description:"standard object metadata"`
SomeField string `json:"someField"`
OtherField int `json:"otherField"`
}
type FooList struct {
unversioned.TypeMeta `json:",inline"`
unversioned.ListMeta `json:"metadata,omitempty" description:"standard list metadata; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata"`
Items []Foo `json:"items"`
}
func initThirdParty(t *testing.T, version, name string) (*Master, *etcdtesting.EtcdTestServer, *httptest.Server, *assert.Assertions) {
return initThirdPartyMultiple(t, []string{version}, []string{name})
}
func initThirdPartyMultiple(t *testing.T, versions, names []string) (*Master, *etcdtesting.EtcdTestServer, *httptest.Server, *assert.Assertions) {
master, etcdserver, _, assert := newMaster(t)
_, master.ServiceClusterIPRange, _ = net.ParseCIDR("10.0.0.0/24")
for ix := range names {
api := &extensions.ThirdPartyResource{
ObjectMeta: api.ObjectMeta{
Name: names[ix],
},
Versions: []extensions.APIVersion{
{
Name: versions[ix],
},
},
}
hasRsrc, err := master.HasThirdPartyResource(api)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if !hasRsrc {
err := master.InstallThirdPartyResource(api)
if !assert.NoError(err) {
t.Errorf("Failed to install API: %v", err)
t.FailNow()
}
} else {
t.Errorf("Expected %s: %v not to be present!", names[ix], api)
}
}
server := httptest.NewServer(master.HandlerContainer.ServeMux)
return master, etcdserver, server, assert
}
func TestInstallMultipleAPIs(t *testing.T) {
names := []string{"foo.company.com", "bar.company.com"}
versions := []string{"v1", "v1"}
_, etcdserver, server, assert := initThirdPartyMultiple(t, versions, names)
defer server.Close()
defer etcdserver.Terminate(t)
for ix := range names {
kind, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(
&extensions.ThirdPartyResource{ObjectMeta: api.ObjectMeta{Name: names[ix]}})
assert.NoError(err, "Failed to extract group & kind")
plural, _ := meta.KindToResource(unversioned.GroupVersionKind{
Group: group,
Version: versions[ix],
Kind: kind,
})
resp, err := http.Get(
fmt.Sprintf("%s/apis/%s/%s/namespaces/default/%s", server.URL, group, versions[ix], plural.Resource))
if !assert.NoError(err, "Failed to do HTTP GET") {
return
}
defer resp.Body.Close()
assert.Equal(http.StatusOK, resp.StatusCode)
data, err := ioutil.ReadAll(resp.Body)
assert.NoError(err)
obj := map[string]interface{}{}
if err = json.Unmarshal(data, &obj); err != nil {
assert.NoError(err, fmt.Sprintf("unexpected error: %v", err))
}
kindOut, found := obj["kind"]
if !found {
t.Errorf("Missing 'kind' in %v", obj)
}
assert.Equal(kindOut, kind+"List")
}
}
func TestInstallThirdPartyAPIList(t *testing.T) {
for _, version := range versionsToTest {
testInstallThirdPartyAPIListVersion(t, version)
}
}
func testInstallThirdPartyAPIListVersion(t *testing.T, version string) {
tests := []struct {
items []Foo
name string
test string
}{
{
name: "foo.company.com",
test: "null",
},
{
items: []Foo{},
name: "foo.company.com",
test: "empty",
},
{
items: []Foo{},
name: "policy.company.com",
test: "plurals",
},
{
items: []Foo{
{
ObjectMeta: api.ObjectMeta{
Name: "test",
},
TypeMeta: unversioned.TypeMeta{
Kind: "Foo",
APIVersion: version,
},
SomeField: "test field",
OtherField: 10,
},
{
ObjectMeta: api.ObjectMeta{
Name: "bar",
},
TypeMeta: unversioned.TypeMeta{
Kind: "Foo",
APIVersion: version,
},
SomeField: "test field another",
OtherField: 20,
},
},
name: "foo.company.com",
test: "real list",
},
}
for _, test := range tests {
func() {
master, etcdserver, server, assert := initThirdParty(t, version, test.name)
defer server.Close()
defer etcdserver.Terminate(t)
kind, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(
&extensions.ThirdPartyResource{ObjectMeta: api.ObjectMeta{Name: test.name}})
assert.NoError(err, test.test)
plural, _ := meta.KindToResource(unversioned.GroupVersionKind{
Group: group,
Version: version,
Kind: kind,
})
if test.items != nil {
s, destroyFunc := generic.NewRawStorage(master.thirdPartyStorageConfig)
defer destroyFunc()
err := createThirdPartyList(
s,
fmt.Sprintf("/ThirdPartyResourceData/%s/%s/default", group, plural.Resource),
test.items)
if !assert.NoError(err, test.test) {
return
}
}
resp, err := http.Get(
fmt.Sprintf("%s/apis/%s/%s/namespaces/default/%s", server.URL, group, version, plural.Resource))
if !assert.NoError(err, test.test) {
return
}
defer resp.Body.Close()
assert.Equal(http.StatusOK, resp.StatusCode, test.test)
data, err := ioutil.ReadAll(resp.Body)
assert.NoError(err, test.test)
list := FooList{}
if err = json.Unmarshal(data, &list); err != nil {
assert.NoError(err, "unexpected error: %v %s", err, test.test)
}
if test.items == nil {
if len(list.Items) != 0 {
assert.NoError(err, "expected no items, saw: %v %s", err, list.Items, test.test)
}
return
}
if len(list.Items) != len(test.items) {
t.Fatalf("(%s) unexpected length: %d vs %d", test.name, len(list.Items), len(test.items))
}
// The order of elements in LIST is not guaranteed.
mapping := make(map[string]int)
for ix := range test.items {
mapping[test.items[ix].Name] = ix
}
for ix := range list.Items {
// Copy things that are set dynamically on the server
expectedObj := test.items[mapping[list.Items[ix].Name]]
expectedObj.SelfLink = list.Items[ix].SelfLink
expectedObj.ResourceVersion = list.Items[ix].ResourceVersion
expectedObj.Namespace = list.Items[ix].Namespace
expectedObj.UID = list.Items[ix].UID
expectedObj.CreationTimestamp = list.Items[ix].CreationTimestamp
// We endure the order of items by sorting them (using 'mapping')
// so that this function passes.
if !reflect.DeepEqual(list.Items[ix], expectedObj) {
t.Errorf("(%s) expected:\n%#v\nsaw:\n%#v\n", test.name, expectedObj, list.Items[ix])
}
}
}()
}
}
func encodeToThirdParty(name string, obj interface{}) (runtime.Object, error) {
serial, err := json.Marshal(obj)
if err != nil {
return nil, err
}
thirdPartyData := extensions.ThirdPartyResourceData{
ObjectMeta: api.ObjectMeta{Name: name},
Data: serial,
}
return &thirdPartyData, nil
}
func createThirdPartyObject(s storage.Interface, path, name string, obj interface{}) error {
data, err := encodeToThirdParty(name, obj)
if err != nil {
return err
}
return s.Create(context.TODO(), etcdtest.AddPrefix(path), data, nil, 0)
}
func createThirdPartyList(s storage.Interface, path string, list []Foo) error {
for _, obj := range list {
if err := createThirdPartyObject(s, path+"/"+obj.Name, obj.Name, obj); err != nil {
return err
}
}
return nil
}
func decodeResponse(resp *http.Response, obj interface{}) error {
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
if err := json.Unmarshal(data, obj); err != nil {
return err
}
return nil
}
func writeResponseToFile(resp *http.Response, filename string) error {
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
return ioutil.WriteFile(filename, data, 0755)
}
func TestInstallThirdPartyAPIGet(t *testing.T) {
for _, version := range versionsToTest {
testInstallThirdPartyAPIGetVersion(t, version)
}
}
func testInstallThirdPartyAPIGetVersion(t *testing.T, version string) {
master, etcdserver, server, assert := initThirdParty(t, version, "foo.company.com")
defer server.Close()
defer etcdserver.Terminate(t)
expectedObj := Foo{
ObjectMeta: api.ObjectMeta{
Name: "test",
},
TypeMeta: unversioned.TypeMeta{
Kind: "Foo",
APIVersion: version,
},
SomeField: "test field",
OtherField: 10,
}
s, destroyFunc := generic.NewRawStorage(master.thirdPartyStorageConfig)
defer destroyFunc()
if !assert.NoError(createThirdPartyObject(s, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj)) {
t.FailNow()
return
}
resp, err := http.Get(server.URL + "/apis/company.com/" + version + "/namespaces/default/foos/test")
if !assert.NoError(err) {
return
}
assert.Equal(http.StatusOK, resp.StatusCode)
item := Foo{}
assert.NoError(decodeResponse(resp, &item))
if !assert.False(reflect.DeepEqual(item, expectedObj)) {
t.Errorf("expected objects to not be equal:\n%v\nsaw:\n%v\n", expectedObj, item)
}
// Fill in data that the apiserver injects
expectedObj.SelfLink = item.SelfLink
expectedObj.ResourceVersion = item.ResourceVersion
if !assert.True(reflect.DeepEqual(item, expectedObj)) {
t.Errorf("expected:\n%#v\nsaw:\n%#v\n", expectedObj, item)
}
}
func TestInstallThirdPartyAPIPost(t *testing.T) {
registered.AddThirdPartyAPIGroupVersions(unversioned.GroupVersion{Group: "company.com", Version: "v1"}, unversioned.GroupVersion{Group: "company.com", Version: "v3"})
for _, version := range versionsToTest {
testInstallThirdPartyAPIPostForVersion(t, version)
}
}
func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) {
master, etcdserver, server, assert := initThirdParty(t, version, "foo.company.com")
defer server.Close()
defer etcdserver.Terminate(t)
inputObj := Foo{
ObjectMeta: api.ObjectMeta{
Name: "test",
},
TypeMeta: unversioned.TypeMeta{
Kind: "Foo",
APIVersion: "company.com/" + version,
},
SomeField: "test field",
OtherField: 10,
}
data, err := json.Marshal(inputObj)
if !assert.NoError(err) {
return
}
resp, err := http.Post(server.URL+"/apis/company.com/"+version+"/namespaces/default/foos", "application/json", bytes.NewBuffer(data))
if !assert.NoError(err) {
t.Fatalf("unexpected error: %v", err)
}
assert.Equal(http.StatusCreated, resp.StatusCode)
item := Foo{}
assert.NoError(decodeResponse(resp, &item))
// fill in fields set by the apiserver
expectedObj := inputObj
expectedObj.SelfLink = item.SelfLink
expectedObj.ResourceVersion = item.ResourceVersion
expectedObj.Namespace = item.Namespace
expectedObj.UID = item.UID
expectedObj.CreationTimestamp = item.CreationTimestamp
if !assert.True(reflect.DeepEqual(item, expectedObj)) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item)
}
thirdPartyObj := extensions.ThirdPartyResourceData{}
s, destroyFunc := generic.NewRawStorage(master.thirdPartyStorageConfig)
defer destroyFunc()
err = s.Get(context.TODO(), etcdtest.AddPrefix("/ThirdPartyResourceData/company.com/foos/default/test"), &thirdPartyObj, false)
if !assert.NoError(err) {
t.FailNow()
}
item = Foo{}
assert.NoError(json.Unmarshal(thirdPartyObj.Data, &item))
if !assert.True(reflect.DeepEqual(item, inputObj)) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", inputObj, item)
}
}
func TestInstallThirdPartyAPIDelete(t *testing.T) {
for _, version := range versionsToTest {
testInstallThirdPartyAPIDeleteVersion(t, version)
}
}
func testInstallThirdPartyAPIDeleteVersion(t *testing.T, version string) {
master, etcdserver, server, assert := initThirdParty(t, version, "foo.company.com")
defer server.Close()
defer etcdserver.Terminate(t)
expectedObj := Foo{
ObjectMeta: api.ObjectMeta{
Name: "test",
Namespace: "default",
},
TypeMeta: unversioned.TypeMeta{
Kind: "Foo",
},
SomeField: "test field",
OtherField: 10,
}
s, destroyFunc := generic.NewRawStorage(master.thirdPartyStorageConfig)
defer destroyFunc()
if !assert.NoError(createThirdPartyObject(s, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj)) {
t.FailNow()
return
}
resp, err := http.Get(server.URL + "/apis/company.com/" + version + "/namespaces/default/foos/test")
if !assert.NoError(err) {
return
}
assert.Equal(http.StatusOK, resp.StatusCode)
item := Foo{}
assert.NoError(decodeResponse(resp, &item))
// Fill in fields set by the apiserver
expectedObj.SelfLink = item.SelfLink
expectedObj.ResourceVersion = item.ResourceVersion
expectedObj.Namespace = item.Namespace
if !assert.True(reflect.DeepEqual(item, expectedObj)) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item)
}
resp, err = httpDelete(server.URL + "/apis/company.com/" + version + "/namespaces/default/foos/test")
if !assert.NoError(err) {
return
}
assert.Equal(http.StatusOK, resp.StatusCode)
resp, err = http.Get(server.URL + "/apis/company.com/" + version + "/namespaces/default/foos/test")
if !assert.NoError(err) {
return
}
assert.Equal(http.StatusNotFound, resp.StatusCode)
expectedDeletedKey := etcdtest.AddPrefix("ThirdPartyResourceData/company.com/foos/default/test")
thirdPartyObj := extensions.ThirdPartyResourceData{}
err = s.Get(context.TODO(), expectedDeletedKey, &thirdPartyObj, false)
if !storage.IsNotFound(err) {
t.Errorf("expected deletion didn't happen: %v", err)
}
}
func httpDelete(url string) (*http.Response, error) {
req, err := http.NewRequest("DELETE", url, nil)
if err != nil {
return nil, err
}
client := &http.Client{}
return client.Do(req)
}
func TestInstallThirdPartyAPIListOptions(t *testing.T) {
for _, version := range versionsToTest {
testInstallThirdPartyAPIListOptionsForVersion(t, version)
}
}
func testInstallThirdPartyAPIListOptionsForVersion(t *testing.T, version string) {
_, etcdserver, server, assert := initThirdParty(t, version, "foo.company.com")
defer server.Close()
defer etcdserver.Terminate(t)
// send a GET request with query parameter
resp, err := httpGetWithRV(server.URL + "/apis/company.com/" + version + "/namespaces/default/foos")
if !assert.NoError(err) {
t.Fatalf("unexpected error: %v", err)
}
assert.Equal(http.StatusOK, resp.StatusCode)
}
func httpGetWithRV(url string) (*http.Response, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
q := req.URL.Query()
// resourceversion is part of a ListOptions
q.Add("resourceversion", "0")
req.URL.RawQuery = q.Encode()
client := &http.Client{}
return client.Do(req)
}
func TestInstallThirdPartyResourceRemove(t *testing.T) {
for _, version := range versionsToTest {
testInstallThirdPartyResourceRemove(t, version)
}
}
func testInstallThirdPartyResourceRemove(t *testing.T, version string) {
master, etcdserver, server, assert := initThirdParty(t, version, "foo.company.com")
defer server.Close()
defer etcdserver.Terminate(t)
expectedObj := Foo{
ObjectMeta: api.ObjectMeta{
Name: "test",
},
TypeMeta: unversioned.TypeMeta{
Kind: "Foo",
},
SomeField: "test field",
OtherField: 10,
}
s, destroyFunc := generic.NewRawStorage(master.thirdPartyStorageConfig)
defer destroyFunc()
if !assert.NoError(createThirdPartyObject(s, "/ThirdPartyResourceData/company.com/foos/default/test", "test", expectedObj)) {
t.FailNow()
return
}
secondObj := expectedObj
secondObj.Name = "bar"
if !assert.NoError(createThirdPartyObject(s, "/ThirdPartyResourceData/company.com/foos/default/bar", "bar", secondObj)) {
t.FailNow()
return
}
resp, err := http.Get(server.URL + "/apis/company.com/" + version + "/namespaces/default/foos/test")
if !assert.NoError(err) {
t.FailNow()
return
}
if resp.StatusCode != http.StatusOK {
t.Errorf("unexpected status: %v", resp)
}
item := Foo{}
if err := decodeResponse(resp, &item); err != nil {
t.Errorf("unexpected error: %v", err)
}
// TODO: validate etcd set things here
item.ObjectMeta = expectedObj.ObjectMeta
if !assert.True(reflect.DeepEqual(item, expectedObj)) {
t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item)
}
path := extensionsrest.MakeThirdPartyPath("company.com")
master.RemoveThirdPartyResource(path + "/foos")
resp, err = http.Get(server.URL + "/apis/company.com/" + version + "/namespaces/default/foos/test")
if !assert.NoError(err) {
return
}
if resp.StatusCode != http.StatusNotFound {
t.Errorf("unexpected status: %v", resp)
}
expectedDeletedKeys := []string{
etcdtest.AddPrefix("/ThirdPartyResourceData/company.com/foos/default/test"),
etcdtest.AddPrefix("/ThirdPartyResourceData/company.com/foos/default/bar"),
}
for _, key := range expectedDeletedKeys {
thirdPartyObj := extensions.ThirdPartyResourceData{}
s, destroyFunc := generic.NewRawStorage(master.thirdPartyStorageConfig)
err := s.Get(context.TODO(), key, &thirdPartyObj, false)
if !storage.IsNotFound(err) {
t.Errorf("expected deletion didn't happen: %v", err)
}
destroyFunc()
}
installed := master.ListThirdPartyResources()
if len(installed) != 0 {
t.Errorf("Resource(s) still installed: %v", installed)
}
services := master.HandlerContainer.RegisteredWebServices()
for ix := range services {
if strings.HasPrefix(services[ix].RootPath(), "/apis/company.com") {
t.Errorf("Web service still installed at %s: %#v", services[ix].RootPath(), services[ix])
}
}
}
func TestThirdPartyDiscovery(t *testing.T) {
for _, version := range versionsToTest {
testThirdPartyDiscovery(t, version)
}
}
type FakeTunneler struct {
SecondsSinceSyncValue int64
SecondsSinceSSHKeySyncValue int64
@ -1116,48 +514,14 @@ func TestIsTunnelSyncHealthy(t *testing.T) {
assert.Error(err, "IsTunnelSyncHealthy() should have returned an error.")
}
func testThirdPartyDiscovery(t *testing.T, version string) {
_, etcdserver, server, assert := initThirdParty(t, version, "foo.company.com")
defer server.Close()
defer etcdserver.Terminate(t)
func writeResponseToFile(resp *http.Response, filename string) error {
defer resp.Body.Close()
resp, err := http.Get(server.URL + "/apis/company.com/")
if !assert.NoError(err) {
return
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
assert.Equal(http.StatusOK, resp.StatusCode)
group := unversioned.APIGroup{}
assert.NoError(decodeResponse(resp, &group))
assert.Equal(group.APIVersion, "v1")
assert.Equal(group.Kind, "APIGroup")
assert.Equal(group.Name, "company.com")
expectedVersion := unversioned.GroupVersionForDiscovery{
GroupVersion: "company.com/" + version,
Version: version,
}
assert.Equal(group.Versions, []unversioned.GroupVersionForDiscovery{expectedVersion})
assert.Equal(group.PreferredVersion, expectedVersion)
resp, err = http.Get(server.URL + "/apis/company.com/" + version)
if !assert.NoError(err) {
return
}
assert.Equal(http.StatusOK, resp.StatusCode)
resourceList := unversioned.APIResourceList{}
assert.NoError(decodeResponse(resp, &resourceList))
assert.Equal(resourceList.APIVersion, "v1")
assert.Equal(resourceList.Kind, "APIResourceList")
assert.Equal(resourceList.GroupVersion, "company.com/"+version)
assert.Equal(resourceList.APIResources, []unversioned.APIResource{
{
Name: "foos",
Namespaced: true,
Kind: "Foo",
},
})
return ioutil.WriteFile(filename, data, 0755)
}
// TestValidOpenAPISpec verifies that the open api is added

View File

@ -0,0 +1,229 @@
// +build integration,!no-etcd
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package thirdparty
// This file contains tests for the storage classes API resource.
import (
"encoding/json"
"reflect"
"testing"
"time"
"k8s.io/kubernetes/pkg/api"
apierrors "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/util/diff"
"k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/test/integration/framework"
)
// TODO these tests will eventually be runnable in a single test
func TestThirdPartyDelete(t *testing.T) {
_, s := framework.RunAMaster(framework.NewIntegrationTestMasterConfig())
defer s.Close()
clientConfig := &restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}}
client := internalclientset.NewForConfigOrDie(clientConfig)
DoTestInstallThirdPartyAPIDelete(t, client, clientConfig)
}
func TestThirdPartyMultiple(t *testing.T) {
_, s := framework.RunAMaster(framework.NewIntegrationTestMasterConfig())
defer s.Close()
clientConfig := &restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}}
client := internalclientset.NewForConfigOrDie(clientConfig)
DoTestInstallMultipleAPIs(t, client, clientConfig)
}
// TODO make multiple versions work. they've been broken
var versionsToTest = []string{"v1"}
type Foo struct {
unversioned.TypeMeta `json:",inline"`
api.ObjectMeta `json:"metadata,omitempty" description:"standard object metadata"`
SomeField string `json:"someField"`
OtherField int `json:"otherField"`
}
type FooList struct {
unversioned.TypeMeta `json:",inline"`
unversioned.ListMeta `json:"metadata,omitempty" description:"standard list metadata; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata"`
Items []Foo `json:"items"`
}
// installThirdParty installs a third party resoure and returns a defer func
func installThirdParty(t *testing.T, client internalclientset.Interface, clientConfig *restclient.Config, tpr *extensions.ThirdPartyResource, group, version, resource string) func() {
var err error
_, err = client.Extensions().ThirdPartyResources().Create(tpr)
if err != nil {
t.Fatal(err)
}
fooClientConfig := *clientConfig
fooClientConfig.APIPath = "apis"
fooClientConfig.GroupVersion = &unversioned.GroupVersion{Group: group, Version: version}
fooClient, err := restclient.RESTClientFor(&fooClientConfig)
if err != nil {
t.Fatal(err)
}
err = wait.Poll(100*time.Millisecond, 60*time.Second, func() (bool, error) {
_, err := fooClient.Get().Namespace("default").Resource(resource).DoRaw()
if err == nil {
return true, nil
}
if apierrors.IsNotFound(err) {
return false, nil
}
return false, err
})
if err != nil {
t.Fatal(err)
}
return func() {
client.Extensions().ThirdPartyResources().Delete(tpr.Name, nil)
err = wait.Poll(100*time.Millisecond, 60*time.Second, func() (bool, error) {
_, err := fooClient.Get().Namespace("default").Resource(resource).DoRaw()
if apierrors.IsNotFound(err) {
return true, nil
}
return false, err
})
if err != nil {
t.Fatal(err)
}
}
}
func DoTestInstallMultipleAPIs(t *testing.T, client internalclientset.Interface, clientConfig *restclient.Config) {
group := "company.com"
version := "v1"
defer installThirdParty(t, client, clientConfig,
&extensions.ThirdPartyResource{
ObjectMeta: api.ObjectMeta{Name: "foo.company.com"},
Versions: []extensions.APIVersion{{Name: version}},
}, group, version, "foos",
)()
// TODO make multiple resources in one version work
// defer installThirdParty(t, client, clientConfig,
// &extensions.ThirdPartyResource{
// ObjectMeta: api.ObjectMeta{Name: "bar.company.com"},
// Versions: []extensions.APIVersion{{Name: version}},
// }, group, version, "bars",
// )()
}
func DoTestInstallThirdPartyAPIDelete(t *testing.T, client internalclientset.Interface, clientConfig *restclient.Config) {
for _, version := range versionsToTest {
testInstallThirdPartyAPIDeleteVersion(t, client, clientConfig, version)
}
}
func testInstallThirdPartyAPIDeleteVersion(t *testing.T, client internalclientset.Interface, clientConfig *restclient.Config, version string) {
group := "company.com"
defer installThirdParty(t, client, clientConfig,
&extensions.ThirdPartyResource{
ObjectMeta: api.ObjectMeta{Name: "foo.company.com"},
Versions: []extensions.APIVersion{{Name: version}},
}, group, version, "foos",
)()
fooClientConfig := *clientConfig
fooClientConfig.APIPath = "apis"
fooClientConfig.GroupVersion = &unversioned.GroupVersion{Group: group, Version: version}
fooClient, err := restclient.RESTClientFor(&fooClientConfig)
if err != nil {
t.Fatal(err)
}
expectedObj := Foo{
ObjectMeta: api.ObjectMeta{
Name: "test",
Namespace: "default",
},
TypeMeta: unversioned.TypeMeta{
Kind: "Foo",
},
SomeField: "test field",
OtherField: 10,
}
objBytes, err := json.Marshal(&expectedObj)
if err != nil {
t.Fatal(err)
}
if _, err := fooClient.Post().Namespace("default").Resource("foos").Body(objBytes).DoRaw(); err != nil {
t.Fatal(err)
}
apiBytes, err := fooClient.Get().Namespace("default").Resource("foos").Name("test").DoRaw()
if err != nil {
t.Fatal(err)
}
item := Foo{}
err = json.Unmarshal(apiBytes, &item)
if err != nil {
t.Fatal(err)
}
// Fill in fields set by the apiserver
item.SelfLink = expectedObj.SelfLink
item.ResourceVersion = expectedObj.ResourceVersion
item.Namespace = expectedObj.Namespace
item.UID = expectedObj.UID
item.CreationTimestamp = expectedObj.CreationTimestamp
if !reflect.DeepEqual(item, expectedObj) {
t.Fatalf("expected:\n%v\n", diff.ObjectGoPrintSideBySide(expectedObj, item))
}
listBytes, err := fooClient.Get().Namespace("default").Resource("foos").DoRaw()
if err != nil {
t.Fatal(err)
}
list := FooList{}
err = json.Unmarshal(listBytes, &list)
if err != nil {
t.Fatal(err)
}
if len(list.Items) != 1 {
t.Fatalf("wrong item: %v", list)
}
if _, err := fooClient.Delete().Namespace("default").Resource("foos").Name("test").DoRaw(); err != nil {
t.Fatal(err)
}
if _, err := fooClient.Get().Namespace("default").Resource("foos").Name("test").DoRaw(); !apierrors.IsNotFound(err) {
t.Fatal(err)
}
}