mirror of https://github.com/k3s-io/k3s
move third party resource tests
parent
1c667e4fc5
commit
1123f6788b
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue