2014-12-27 21:48:27 +00:00
|
|
|
/*
|
2016-06-03 00:25:58 +00:00
|
|
|
Copyright 2014 The Kubernetes Authors.
|
2014-12-27 21:48:27 +00:00
|
|
|
|
|
|
|
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 resource
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
2017-11-02 20:06:07 +00:00
|
|
|
corev1 "k8s.io/api/core/v1"
|
2017-01-11 14:09:48 +00:00
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
2017-11-02 20:06:07 +00:00
|
|
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
|
|
|
"k8s.io/client-go/kubernetes/scheme"
|
2017-01-24 15:00:24 +00:00
|
|
|
"k8s.io/client-go/rest/fake"
|
2014-12-27 21:48:27 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func objBody(obj runtime.Object) io.ReadCloser {
|
2017-11-02 20:06:07 +00:00
|
|
|
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(corev1Codec, obj))))
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
|
2016-05-11 07:50:47 +00:00
|
|
|
func header() http.Header {
|
|
|
|
header := http.Header{}
|
|
|
|
header.Set("Content-Type", runtime.ContentTypeJSON)
|
|
|
|
return header
|
|
|
|
}
|
|
|
|
|
2014-12-27 21:48:27 +00:00
|
|
|
// splitPath returns the segments for a URL path.
|
|
|
|
func splitPath(path string) []string {
|
|
|
|
path = strings.Trim(path, "/")
|
|
|
|
if path == "" {
|
|
|
|
return []string{}
|
|
|
|
}
|
|
|
|
return strings.Split(path, "/")
|
|
|
|
}
|
|
|
|
|
2017-11-02 20:06:07 +00:00
|
|
|
// V1DeepEqualSafePodSpec returns a PodSpec which is ready to be used with apiequality.Semantic.DeepEqual
|
|
|
|
func V1DeepEqualSafePodSpec() corev1.PodSpec {
|
|
|
|
grace := int64(30)
|
|
|
|
return corev1.PodSpec{
|
|
|
|
RestartPolicy: corev1.RestartPolicyAlways,
|
|
|
|
DNSPolicy: corev1.DNSClusterFirst,
|
|
|
|
TerminationGracePeriodSeconds: &grace,
|
|
|
|
SecurityContext: &corev1.PodSecurityContext{},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-27 21:48:27 +00:00
|
|
|
func TestHelperDelete(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
Err bool
|
|
|
|
Req func(*http.Request) bool
|
|
|
|
Resp *http.Response
|
|
|
|
HttpErr error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
HttpErr: errors.New("failure"),
|
|
|
|
Err: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusNotFound,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2016-12-03 18:57:26 +00:00
|
|
|
Body: objBody(&metav1.Status{Status: metav1.StatusFailure}),
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
Err: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusOK,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2016-12-03 18:57:26 +00:00
|
|
|
Body: objBody(&metav1.Status{Status: metav1.StatusSuccess}),
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
Req: func(req *http.Request) bool {
|
|
|
|
if req.Method != "DELETE" {
|
|
|
|
t.Errorf("unexpected method: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
parts := splitPath(req.URL.Path)
|
2015-02-16 04:43:45 +00:00
|
|
|
if len(parts) < 3 {
|
|
|
|
t.Errorf("expected URL path to have 3 parts: %s", req.URL.Path)
|
|
|
|
return false
|
|
|
|
}
|
2014-12-27 21:48:27 +00:00
|
|
|
if parts[1] != "bar" {
|
|
|
|
t.Errorf("url doesn't contain namespace: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if parts[2] != "foo" {
|
|
|
|
t.Errorf("url doesn't contain name: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
2015-09-11 20:47:53 +00:00
|
|
|
client := &fake.RESTClient{
|
2017-11-02 20:06:07 +00:00
|
|
|
NegotiatedSerializer: scheme.Codecs,
|
2016-05-04 10:24:16 +00:00
|
|
|
Resp: test.Resp,
|
|
|
|
Err: test.HttpErr,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
modifier := &Helper{
|
2015-02-16 04:43:45 +00:00
|
|
|
RESTClient: client,
|
|
|
|
NamespaceScoped: true,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
err := modifier.Delete("bar", "foo")
|
|
|
|
if (err != nil) != test.Err {
|
|
|
|
t.Errorf("unexpected error: %t %v", test.Err, err)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if test.Req != nil && !test.Req(client.Req) {
|
|
|
|
t.Errorf("unexpected request: %#v", client.Req)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHelperCreate(t *testing.T) {
|
|
|
|
expectPost := func(req *http.Request) bool {
|
|
|
|
if req.Method != "POST" {
|
|
|
|
t.Errorf("unexpected method: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
parts := splitPath(req.URL.Path)
|
|
|
|
if parts[1] != "bar" {
|
|
|
|
t.Errorf("url doesn't contain namespace: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
2015-11-10 21:40:51 +00:00
|
|
|
Resp *http.Response
|
|
|
|
HttpErr error
|
|
|
|
Modify bool
|
|
|
|
Object runtime.Object
|
2014-12-27 21:48:27 +00:00
|
|
|
|
|
|
|
ExpectObject runtime.Object
|
|
|
|
Err bool
|
|
|
|
Req func(*http.Request) bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
HttpErr: errors.New("failure"),
|
|
|
|
Err: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusNotFound,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2016-12-03 18:57:26 +00:00
|
|
|
Body: objBody(&metav1.Status{Status: metav1.StatusFailure}),
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
Err: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusOK,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2016-12-03 18:57:26 +00:00
|
|
|
Body: objBody(&metav1.Status{Status: metav1.StatusSuccess}),
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
2017-11-02 20:06:07 +00:00
|
|
|
Object: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}},
|
|
|
|
ExpectObject: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}},
|
2014-12-27 21:48:27 +00:00
|
|
|
Req: expectPost,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Modify: false,
|
2017-11-02 20:06:07 +00:00
|
|
|
Object: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "10"}},
|
|
|
|
ExpectObject: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "10"}},
|
2016-12-03 18:57:26 +00:00
|
|
|
Resp: &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&metav1.Status{Status: metav1.StatusSuccess})},
|
2014-12-27 21:48:27 +00:00
|
|
|
Req: expectPost,
|
|
|
|
},
|
|
|
|
{
|
2015-01-26 17:52:50 +00:00
|
|
|
Modify: true,
|
2017-11-02 20:06:07 +00:00
|
|
|
Object: &corev1.Pod{
|
2017-01-17 03:38:19 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "10"},
|
2017-11-02 20:06:07 +00:00
|
|
|
Spec: V1DeepEqualSafePodSpec(),
|
2015-10-28 16:43:21 +00:00
|
|
|
},
|
2017-11-02 20:06:07 +00:00
|
|
|
ExpectObject: &corev1.Pod{
|
2017-01-17 03:38:19 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
2017-11-02 20:06:07 +00:00
|
|
|
Spec: V1DeepEqualSafePodSpec(),
|
2015-01-26 17:52:50 +00:00
|
|
|
},
|
2016-12-03 18:57:26 +00:00
|
|
|
Resp: &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&metav1.Status{Status: metav1.StatusSuccess})},
|
2015-01-26 17:52:50 +00:00
|
|
|
Req: expectPost,
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for i, test := range tests {
|
2015-09-11 20:47:53 +00:00
|
|
|
client := &fake.RESTClient{
|
2017-11-02 20:06:07 +00:00
|
|
|
GroupVersion: corev1GV,
|
|
|
|
NegotiatedSerializer: scheme.Codecs,
|
2016-05-04 10:24:16 +00:00
|
|
|
Resp: test.Resp,
|
|
|
|
Err: test.HttpErr,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
modifier := &Helper{
|
2015-02-16 04:43:45 +00:00
|
|
|
RESTClient: client,
|
|
|
|
NamespaceScoped: true,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
2015-10-28 16:43:21 +00:00
|
|
|
_, err := modifier.Create("bar", test.Modify, test.Object)
|
2014-12-27 21:48:27 +00:00
|
|
|
if (err != nil) != test.Err {
|
|
|
|
t.Errorf("%d: unexpected error: %t %v", i, test.Err, err)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if test.Req != nil && !test.Req(client.Req) {
|
|
|
|
t.Errorf("%d: unexpected request: %#v", i, client.Req)
|
|
|
|
}
|
|
|
|
body, err := ioutil.ReadAll(client.Req.Body)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("%d: unexpected error: %#v", i, err)
|
|
|
|
}
|
|
|
|
t.Logf("got body: %s", string(body))
|
|
|
|
expect := []byte{}
|
|
|
|
if test.ExpectObject != nil {
|
2017-11-02 20:06:07 +00:00
|
|
|
expect = []byte(runtime.EncodeOrDie(corev1Codec, test.ExpectObject))
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(expect, body) {
|
2015-10-28 16:43:21 +00:00
|
|
|
t.Errorf("%d: unexpected body: %s (expected %s)", i, string(body), string(expect))
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHelperGet(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
Err bool
|
|
|
|
Req func(*http.Request) bool
|
|
|
|
Resp *http.Response
|
|
|
|
HttpErr error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
HttpErr: errors.New("failure"),
|
|
|
|
Err: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusNotFound,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2016-12-03 18:57:26 +00:00
|
|
|
Body: objBody(&metav1.Status{Status: metav1.StatusFailure}),
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
Err: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusOK,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2017-11-02 20:06:07 +00:00
|
|
|
Body: objBody(&corev1.Pod{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"}, ObjectMeta: metav1.ObjectMeta{Name: "foo"}}),
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
Req: func(req *http.Request) bool {
|
|
|
|
if req.Method != "GET" {
|
|
|
|
t.Errorf("unexpected method: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
parts := splitPath(req.URL.Path)
|
|
|
|
if parts[1] != "bar" {
|
|
|
|
t.Errorf("url doesn't contain namespace: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if parts[2] != "foo" {
|
|
|
|
t.Errorf("url doesn't contain name: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2017-11-02 20:06:07 +00:00
|
|
|
for i, test := range tests {
|
2015-09-11 20:47:53 +00:00
|
|
|
client := &fake.RESTClient{
|
2017-11-02 20:06:07 +00:00
|
|
|
GroupVersion: corev1GV,
|
|
|
|
NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs},
|
2016-05-04 10:24:16 +00:00
|
|
|
Resp: test.Resp,
|
|
|
|
Err: test.HttpErr,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
modifier := &Helper{
|
2015-02-16 04:43:45 +00:00
|
|
|
RESTClient: client,
|
|
|
|
NamespaceScoped: true,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
2015-12-02 20:20:10 +00:00
|
|
|
obj, err := modifier.Get("bar", "foo", false)
|
2017-11-02 20:06:07 +00:00
|
|
|
|
2014-12-27 21:48:27 +00:00
|
|
|
if (err != nil) != test.Err {
|
2017-11-02 20:06:07 +00:00
|
|
|
t.Errorf("unexpected error: %d %t %v", i, test.Err, err)
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
2017-11-02 20:06:07 +00:00
|
|
|
if obj.(*corev1.Pod).Name != "foo" {
|
2014-12-27 21:48:27 +00:00
|
|
|
t.Errorf("unexpected object: %#v", obj)
|
|
|
|
}
|
|
|
|
if test.Req != nil && !test.Req(client.Req) {
|
|
|
|
t.Errorf("unexpected request: %#v", client.Req)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHelperList(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
Err bool
|
|
|
|
Req func(*http.Request) bool
|
|
|
|
Resp *http.Response
|
|
|
|
HttpErr error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
HttpErr: errors.New("failure"),
|
|
|
|
Err: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusNotFound,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2016-12-03 18:57:26 +00:00
|
|
|
Body: objBody(&metav1.Status{Status: metav1.StatusFailure}),
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
Err: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusOK,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2017-11-02 20:06:07 +00:00
|
|
|
Body: objBody(&corev1.PodList{
|
|
|
|
Items: []corev1.Pod{{
|
2017-01-17 03:38:19 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
Req: func(req *http.Request) bool {
|
|
|
|
if req.Method != "GET" {
|
|
|
|
t.Errorf("unexpected method: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
2015-01-19 21:50:00 +00:00
|
|
|
if req.URL.Path != "/namespaces/bar" {
|
2014-12-27 21:48:27 +00:00
|
|
|
t.Errorf("url doesn't contain name: %#v", req.URL)
|
|
|
|
return false
|
|
|
|
}
|
2017-11-02 20:06:07 +00:00
|
|
|
if req.URL.Query().Get(metav1.LabelSelectorQueryParam(corev1GV.String())) != labels.SelectorFromSet(labels.Set{"foo": "baz"}).String() {
|
2014-12-27 21:48:27 +00:00
|
|
|
t.Errorf("url doesn't contain query parameters: %#v", req.URL)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
2015-09-11 20:47:53 +00:00
|
|
|
client := &fake.RESTClient{
|
2017-11-02 20:06:07 +00:00
|
|
|
GroupVersion: corev1GV,
|
|
|
|
NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs},
|
2016-05-04 10:24:16 +00:00
|
|
|
Resp: test.Resp,
|
|
|
|
Err: test.HttpErr,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
modifier := &Helper{
|
2015-02-16 04:43:45 +00:00
|
|
|
RESTClient: client,
|
|
|
|
NamespaceScoped: true,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
2017-11-02 20:06:07 +00:00
|
|
|
obj, err := modifier.List("bar", corev1GV.String(), false, &metav1.ListOptions{LabelSelector: "foo=baz"})
|
2014-12-27 21:48:27 +00:00
|
|
|
if (err != nil) != test.Err {
|
|
|
|
t.Errorf("unexpected error: %t %v", test.Err, err)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
2017-11-02 20:06:07 +00:00
|
|
|
if obj.(*corev1.PodList).Items[0].Name != "foo" {
|
2014-12-27 21:48:27 +00:00
|
|
|
t.Errorf("unexpected object: %#v", obj)
|
|
|
|
}
|
|
|
|
if test.Req != nil && !test.Req(client.Req) {
|
|
|
|
t.Errorf("unexpected request: %#v", client.Req)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-05 05:25:53 +00:00
|
|
|
func TestHelperListSelectorCombination(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
Name string
|
|
|
|
Err bool
|
|
|
|
ErrMsg string
|
|
|
|
FieldSelector string
|
|
|
|
LabelSelector string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
Name: "No selector",
|
|
|
|
Err: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Only Label Selector",
|
|
|
|
Err: false,
|
|
|
|
LabelSelector: "foo=baz",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Only Field Selector",
|
|
|
|
Err: false,
|
|
|
|
FieldSelector: "xyz=zyx",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Both Label and Field Selector",
|
|
|
|
Err: false,
|
|
|
|
LabelSelector: "foo=baz",
|
|
|
|
FieldSelector: "xyz=zyx",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := &http.Response{
|
|
|
|
StatusCode: http.StatusOK,
|
|
|
|
Header: header(),
|
|
|
|
Body: objBody(&corev1.PodList{
|
|
|
|
Items: []corev1.Pod{{
|
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
client := &fake.RESTClient{
|
|
|
|
NegotiatedSerializer: scheme.Codecs,
|
|
|
|
Resp: resp,
|
|
|
|
Err: nil,
|
|
|
|
}
|
|
|
|
modifier := &Helper{
|
|
|
|
RESTClient: client,
|
|
|
|
NamespaceScoped: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
_, err := modifier.List("bar",
|
|
|
|
corev1GV.String(),
|
|
|
|
false,
|
|
|
|
&metav1.ListOptions{LabelSelector: test.LabelSelector, FieldSelector: test.FieldSelector})
|
|
|
|
if test.Err {
|
|
|
|
if err == nil {
|
|
|
|
t.Errorf("%q expected error: %q", test.Name, test.ErrMsg)
|
|
|
|
}
|
|
|
|
if err != nil && err.Error() != test.ErrMsg {
|
|
|
|
t.Errorf("%q expected error: %q", test.Name, test.ErrMsg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-27 04:25:08 +00:00
|
|
|
func TestHelperReplace(t *testing.T) {
|
2016-02-12 19:46:23 +00:00
|
|
|
expectPut := func(path string, req *http.Request) bool {
|
2014-12-27 21:48:27 +00:00
|
|
|
if req.Method != "PUT" {
|
|
|
|
t.Errorf("unexpected method: %#v", req)
|
|
|
|
return false
|
|
|
|
}
|
2016-02-12 19:46:23 +00:00
|
|
|
if req.URL.Path != path {
|
|
|
|
t.Errorf("unexpected url: %v", req.URL)
|
2014-12-27 21:48:27 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
2016-02-12 19:46:23 +00:00
|
|
|
Resp *http.Response
|
|
|
|
HTTPClient *http.Client
|
|
|
|
HttpErr error
|
|
|
|
Overwrite bool
|
|
|
|
Object runtime.Object
|
|
|
|
Namespace string
|
|
|
|
NamespaceScoped bool
|
2014-12-27 21:48:27 +00:00
|
|
|
|
2016-02-12 19:46:23 +00:00
|
|
|
ExpectPath string
|
2014-12-27 21:48:27 +00:00
|
|
|
ExpectObject runtime.Object
|
|
|
|
Err bool
|
2016-02-12 19:46:23 +00:00
|
|
|
Req func(string, *http.Request) bool
|
2014-12-27 21:48:27 +00:00
|
|
|
}{
|
|
|
|
{
|
2016-02-12 19:46:23 +00:00
|
|
|
Namespace: "bar",
|
|
|
|
NamespaceScoped: true,
|
|
|
|
HttpErr: errors.New("failure"),
|
|
|
|
Err: true,
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
{
|
2016-02-12 19:46:23 +00:00
|
|
|
Namespace: "bar",
|
|
|
|
NamespaceScoped: true,
|
2017-11-02 20:06:07 +00:00
|
|
|
Object: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}},
|
2014-12-27 21:48:27 +00:00
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusNotFound,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2016-12-03 18:57:26 +00:00
|
|
|
Body: objBody(&metav1.Status{Status: metav1.StatusFailure}),
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
Err: true,
|
|
|
|
},
|
|
|
|
{
|
2016-02-12 19:46:23 +00:00
|
|
|
Namespace: "bar",
|
|
|
|
NamespaceScoped: true,
|
2017-11-02 20:06:07 +00:00
|
|
|
Object: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}},
|
2016-02-12 19:46:23 +00:00
|
|
|
ExpectPath: "/namespaces/bar/foo",
|
2017-11-02 20:06:07 +00:00
|
|
|
ExpectObject: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}},
|
2014-12-27 21:48:27 +00:00
|
|
|
Resp: &http.Response{
|
|
|
|
StatusCode: http.StatusOK,
|
2016-05-11 07:50:47 +00:00
|
|
|
Header: header(),
|
2016-12-03 18:57:26 +00:00
|
|
|
Body: objBody(&metav1.Status{Status: metav1.StatusSuccess}),
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
Req: expectPut,
|
|
|
|
},
|
2016-02-12 19:46:23 +00:00
|
|
|
// namespace scoped resource
|
2014-12-27 21:48:27 +00:00
|
|
|
{
|
2016-02-12 19:46:23 +00:00
|
|
|
Namespace: "bar",
|
|
|
|
NamespaceScoped: true,
|
2017-11-02 20:06:07 +00:00
|
|
|
Object: &corev1.Pod{
|
2017-01-17 03:38:19 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
2017-11-02 20:06:07 +00:00
|
|
|
Spec: V1DeepEqualSafePodSpec(),
|
2015-10-28 16:43:21 +00:00
|
|
|
},
|
2016-02-12 19:46:23 +00:00
|
|
|
ExpectPath: "/namespaces/bar/foo",
|
2017-11-02 20:06:07 +00:00
|
|
|
ExpectObject: &corev1.Pod{
|
2017-01-17 03:38:19 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "10"},
|
2017-11-02 20:06:07 +00:00
|
|
|
Spec: V1DeepEqualSafePodSpec(),
|
2015-01-26 17:52:50 +00:00
|
|
|
},
|
2014-12-27 21:48:27 +00:00
|
|
|
Overwrite: true,
|
2015-11-11 19:54:58 +00:00
|
|
|
HTTPClient: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
2014-12-27 21:48:27 +00:00
|
|
|
if req.Method == "PUT" {
|
2016-12-03 18:57:26 +00:00
|
|
|
return &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&metav1.Status{Status: metav1.StatusSuccess})}, nil
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
2017-11-02 20:06:07 +00:00
|
|
|
return &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "10"}})}, nil
|
2015-11-10 21:40:51 +00:00
|
|
|
}),
|
2014-12-27 21:48:27 +00:00
|
|
|
Req: expectPut,
|
|
|
|
},
|
2016-02-12 19:46:23 +00:00
|
|
|
// cluster scoped resource
|
2014-12-27 21:48:27 +00:00
|
|
|
{
|
2017-11-02 20:06:07 +00:00
|
|
|
Object: &corev1.Node{
|
2017-01-17 03:38:19 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "foo"},
|
2016-02-12 19:46:23 +00:00
|
|
|
},
|
2017-11-02 20:06:07 +00:00
|
|
|
ExpectObject: &corev1.Node{
|
2017-01-17 03:38:19 +00:00
|
|
|
ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "10"},
|
2016-02-12 19:46:23 +00:00
|
|
|
},
|
|
|
|
Overwrite: true,
|
|
|
|
ExpectPath: "/foo",
|
|
|
|
HTTPClient: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
|
|
|
if req.Method == "PUT" {
|
2016-12-03 18:57:26 +00:00
|
|
|
return &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&metav1.Status{Status: metav1.StatusSuccess})}, nil
|
2016-02-12 19:46:23 +00:00
|
|
|
}
|
2017-11-02 20:06:07 +00:00
|
|
|
return &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "10"}})}, nil
|
2016-02-12 19:46:23 +00:00
|
|
|
}),
|
|
|
|
Req: expectPut,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Namespace: "bar",
|
|
|
|
NamespaceScoped: true,
|
2017-11-02 20:06:07 +00:00
|
|
|
Object: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "10"}},
|
2016-02-12 19:46:23 +00:00
|
|
|
ExpectPath: "/namespaces/bar/foo",
|
2017-11-02 20:06:07 +00:00
|
|
|
ExpectObject: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "10"}},
|
2016-12-03 18:57:26 +00:00
|
|
|
Resp: &http.Response{StatusCode: http.StatusOK, Header: header(), Body: objBody(&metav1.Status{Status: metav1.StatusSuccess})},
|
2016-02-12 19:46:23 +00:00
|
|
|
Req: expectPut,
|
2014-12-27 21:48:27 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for i, test := range tests {
|
2015-09-11 20:47:53 +00:00
|
|
|
client := &fake.RESTClient{
|
2017-11-02 20:06:07 +00:00
|
|
|
GroupVersion: corev1GV,
|
|
|
|
NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs},
|
2017-01-24 15:00:24 +00:00
|
|
|
Client: test.HTTPClient,
|
2016-05-04 10:24:16 +00:00
|
|
|
Resp: test.Resp,
|
|
|
|
Err: test.HttpErr,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
modifier := &Helper{
|
2015-02-16 04:43:45 +00:00
|
|
|
RESTClient: client,
|
2016-02-12 19:46:23 +00:00
|
|
|
NamespaceScoped: test.NamespaceScoped,
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
2016-02-12 19:46:23 +00:00
|
|
|
_, err := modifier.Replace(test.Namespace, "foo", test.Overwrite, test.Object)
|
2014-12-27 21:48:27 +00:00
|
|
|
if (err != nil) != test.Err {
|
|
|
|
t.Errorf("%d: unexpected error: %t %v", i, test.Err, err)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
2016-02-12 19:46:23 +00:00
|
|
|
if test.Req != nil && !test.Req(test.ExpectPath, client.Req) {
|
2014-12-27 21:48:27 +00:00
|
|
|
t.Errorf("%d: unexpected request: %#v", i, client.Req)
|
|
|
|
}
|
|
|
|
body, err := ioutil.ReadAll(client.Req.Body)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("%d: unexpected error: %#v", i, err)
|
|
|
|
}
|
|
|
|
expect := []byte{}
|
|
|
|
if test.ExpectObject != nil {
|
2017-11-02 20:06:07 +00:00
|
|
|
expect = []byte(runtime.EncodeOrDie(corev1Codec, test.ExpectObject))
|
2014-12-27 21:48:27 +00:00
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(expect, body) {
|
|
|
|
t.Errorf("%d: unexpected body: %s", i, string(body))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|