ref(*): kubernetes v1.10 support

parent 19c73207
This diff is collapsed.
......@@ -43,28 +43,20 @@ import:
- package: github.com/evanphx/json-patch
- package: github.com/BurntSushi/toml
version: ~0.3.0
- package: github.com/naoina/go-stringutil
version: ~0.1.0
- package: github.com/chai2010/gettext-go
- package: github.com/prometheus/client_golang
version: 0.8.0
- package: vbom.ml/util
repo: https://github.com/fvbommel/util.git
vcs: git
- package: github.com/grpc-ecosystem/go-grpc-prometheus
- package: k8s.io/kubernetes
version: 1.9.2
version: release-1.10
- package: k8s.io/client-go
version: ~6.0.0
version: kubernetes-1.10.0
- package: k8s.io/api
version: kubernetes-1.9.2
version: release-1.10
- package: k8s.io/apimachinery
version: kubernetes-1.9.2
version: release-1.10
- package: k8s.io/apiserver
version: kubernetes-1.9.2
- package: cloud.google.com/go/compute
repo: https://github.com/GoogleCloudPlatform/google-cloud-go.git
version: release-1.10
testImports:
- package: github.com/stretchr/testify
......
......@@ -47,7 +47,7 @@ import (
"k8s.io/client-go/tools/clientcmd"
batchinternal "k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/core"
conditions "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/conditions"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
......@@ -77,10 +77,12 @@ func New(config clientcmd.ClientConfig) *Client {
return &Client{
Factory: cmdutil.NewFactory(config),
SchemaCacheDir: clientcmd.RecommendedSchemaFile,
Log: func(_ string, _ ...interface{}) {},
Log: nopLogger,
}
}
var nopLogger = func(_ string, _ ...interface{}) {}
// ResourceActorFunc performs an action on a single resource.
type ResourceActorFunc func(*resource.Info) error
......@@ -205,7 +207,10 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) {
// an object type changes, so we can just rely on that. Problem is it doesn't seem to keep
// track of tab widths.
buf := new(bytes.Buffer)
p, _ := c.Printer(nil, printers.PrintOptions{})
p, err := cmdutil.PrinterForOptions(&printers.PrintOptions{})
if err != nil {
return "", err
}
for t, ot := range objs {
if _, err = buf.WriteString("==> " + t + "\n"); err != nil {
return "", err
......@@ -608,7 +613,8 @@ func (c *Client) AsVersionedObject(obj runtime.Object) (runtime.Object, error) {
return nil, err
}
versions := &runtime.VersionedObjects{}
err = runtime.DecodeInto(c.Decoder(true), json, versions)
decoder := unstructured.UnstructuredJSONScheme
err = runtime.DecodeInto(decoder, json, versions)
return versions.First(), err
}
......
......@@ -18,8 +18,6 @@ package kube
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
......@@ -31,19 +29,20 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/printers"
watchjson "k8s.io/kubernetes/pkg/watch/json"
"k8s.io/kubernetes/pkg/kubectl/scheme"
)
var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer
func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj))))
}
......@@ -117,31 +116,21 @@ func (f *fakeReaperFactory) Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, e
return f.reaper, nil
}
func newEventResponse(code int, e *watch.Event) (*http.Response, error) {
dispatchedEvent, err := encodeAndMarshalEvent(e)
if err != nil {
return nil, err
}
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
body := ioutil.NopCloser(bytes.NewReader(dispatchedEvent))
return &http.Response{StatusCode: code, Header: header, Body: body}, nil
type testClient struct {
*Client
*cmdtesting.TestFactory
}
func encodeAndMarshalEvent(e *watch.Event) ([]byte, error) {
encodedEvent, err := watchjson.Object(testapi.Default.Codec(), e)
if err != nil {
return nil, err
func newTestClient() *testClient {
tf := cmdtesting.NewTestFactory()
c := &Client{
Factory: tf,
Log: nopLogger,
}
return &testClient{
Client: c,
TestFactory: tf,
}
return json.Marshal(encodedEvent)
}
func newTestClient(f cmdutil.Factory) *Client {
c := New(nil)
c.Factory = f
return c
}
func TestUpdate(t *testing.T) {
......@@ -153,10 +142,11 @@ func TestUpdate(t *testing.T) {
var actions []string
f, tf, codec, _ := cmdtesting.NewAPIFactory()
tf := cmdtesting.NewTestFactory()
defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: dynamic.ContentConfig().NegotiatedSerializer,
NegotiatedSerializer: unstructuredSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
p, m := req.URL.Path, req.Method
actions = append(actions, p+":"+m)
......@@ -190,9 +180,11 @@ func TestUpdate(t *testing.T) {
}),
}
c := newTestClient()
reaper := &fakeReaper{}
rf := &fakeReaperFactory{Factory: f, reaper: reaper}
c := newTestClient(rf)
rf := &fakeReaperFactory{Factory: tf, reaper: reaper}
c.Client.Factory = rf
codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...)
if err := c.Update(core.NamespaceDefault, objBody(codec, &listA), objBody(codec, &listB), false, false, 0, false); err != nil {
t.Fatal(err)
}
......@@ -251,54 +243,35 @@ func TestBuild(t *testing.T) {
},
}
c := newTestClient()
for _, tt := range tests {
f, _, _, _ := cmdtesting.NewAPIFactory()
c := newTestClient(f)
// Test for an invalid manifest
infos, err := c.Build(tt.namespace, tt.reader)
if err != nil && !tt.err {
t.Errorf("%q. Got error message when no error should have occurred: %v", tt.name, err)
} else if err != nil && strings.Contains(err.Error(), "--validate=false") {
t.Errorf("%q. error message was not scrubbed", tt.name)
}
t.Run(tt.name, func(t *testing.T) {
c.Cleanup()
// Test for an invalid manifest
infos, err := c.Build(tt.namespace, tt.reader)
if err != nil && !tt.err {
t.Errorf("Got error message when no error should have occurred: %v", err)
} else if err != nil && strings.Contains(err.Error(), "--validate=false") {
t.Error("error message was not scrubbed")
}
if len(infos) != tt.count {
t.Errorf("%q. expected %d result objects, got %d", tt.name, tt.count, len(infos))
}
if len(infos) != tt.count {
t.Errorf("expected %d result objects, got %d", tt.count, len(infos))
}
})
}
}
type testPrinter struct {
Objects []runtime.Object
Err error
printers.ResourcePrinter
}
func (t *testPrinter) PrintObj(obj runtime.Object, out io.Writer) error {
t.Objects = append(t.Objects, obj)
fmt.Fprintf(out, "%#v", obj)
return t.Err
}
func (t *testPrinter) HandledResources() []string {
return []string{}
}
func (t *testPrinter) AfterPrint(io.Writer, string) error {
return t.Err
}
func TestGet(t *testing.T) {
list := newPodList("starfish", "otter")
f, tf, _, _ := cmdtesting.NewAPIFactory()
tf.Printer = &testPrinter{}
tf.UnstructuredClient = &fake.RESTClient{
c := newTestClient()
defer c.Cleanup()
c.TestFactory.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: dynamic.ContentConfig().NegotiatedSerializer,
NegotiatedSerializer: unstructuredSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
p, m := req.URL.Path, req.Method
//actions = append(actions, p+":"+m)
t.Logf("got request %s %s", p, m)
switch {
case p == "/namespaces/default/pods/starfish" && m == "GET":
......@@ -311,7 +284,6 @@ func TestGet(t *testing.T) {
}
}),
}
c := newTestClient(f)
// Test Success
data := strings.NewReader("kind: Pod\napiVersion: v1\nmetadata:\n name: otter")
......@@ -358,101 +330,37 @@ func TestPerform(t *testing.T) {
}
for _, tt := range tests {
results := []*resource.Info{}
t.Run(tt.name, func(t *testing.T) {
results := []*resource.Info{}
fn := func(info *resource.Info) error {
results = append(results, info)
fn := func(info *resource.Info) error {
results = append(results, info)
if info.Namespace != tt.namespace {
t.Errorf("%q. expected namespace to be '%s', got %s", tt.name, tt.namespace, info.Namespace)
if info.Namespace != tt.namespace {
t.Errorf("expected namespace to be '%s', got %s", tt.namespace, info.Namespace)
}
return nil
}
return nil
}
f, _, _, _ := cmdtesting.NewAPIFactory()
c := newTestClient(f)
infos, err := c.Build(tt.namespace, tt.reader)
if err != nil && err.Error() != tt.errMessage {
t.Errorf("%q. Error while building manifests: %v", tt.name, err)
}
err = perform(infos, fn)
if (err != nil) != tt.err {
t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err)
}
if err != nil && err.Error() != tt.errMessage {
t.Errorf("%q. expected error message: %v, got %v", tt.name, tt.errMessage, err)
}
if len(results) != tt.count {
t.Errorf("%q. expected %d result objects, got %d", tt.name, tt.count, len(results))
}
}
}
func TestWaitAndGetCompletedPodPhase(t *testing.T) {
tests := []struct {
podPhase core.PodPhase
expectedPhase core.PodPhase
err bool
errMessage string
}{
{
podPhase: core.PodPending,
expectedPhase: core.PodUnknown,
err: true,
errMessage: "watch closed before Until timeout",
}, {
podPhase: core.PodRunning,
expectedPhase: core.PodUnknown,
err: true,
errMessage: "watch closed before Until timeout",
}, {
podPhase: core.PodSucceeded,
expectedPhase: core.PodSucceeded,
}, {
podPhase: core.PodFailed,
expectedPhase: core.PodFailed,
},
}
for _, tt := range tests {
f, tf, codec, ns := cmdtesting.NewAPIFactory()
actions := make(map[string]string)
var testPodList core.PodList
testPodList.Items = append(testPodList.Items, newPodWithStatus("bestpod", core.PodStatus{Phase: tt.podPhase}, "test"))
tf.Client = &fake.RESTClient{
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
p, m := req.URL.Path, req.Method
actions[p] = m
switch {
case p == "/namespaces/test/pods/bestpod" && m == "GET":
return newResponse(200, &testPodList.Items[0])
case p == "/namespaces/test/pods" && m == "GET":
event := watch.Event{Type: watch.Added, Object: &testPodList.Items[0]}
return newEventResponse(200, &event)
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
c := newTestClient()
defer c.Cleanup()
infos, err := c.Build(tt.namespace, tt.reader)
if err != nil && err.Error() != tt.errMessage {
t.Errorf("Error while building manifests: %v", err)
}
c := newTestClient(f)
err = perform(infos, fn)
if (err != nil) != tt.err {
t.Errorf("expected error: %v, got %v", tt.err, err)
}
if err != nil && err.Error() != tt.errMessage {
t.Errorf("expected error message: %v, got %v", tt.errMessage, err)
}
phase, err := c.WaitAndGetCompletedPodPhase("test", objBody(codec, &testPodList), 1*time.Second)
if (err != nil) != tt.err {
t.Fatalf("Expected error but there was none.")
}
if err != nil && err.Error() != tt.errMessage {
t.Fatalf("Expected error %s, got %s", tt.errMessage, err.Error())
}
if phase != tt.expectedPhase {
t.Fatalf("Expected pod phase %s, got %s", tt.expectedPhase, phase)
}
if len(results) != tt.count {
t.Errorf("expected %d result objects, got %d", tt.count, len(results))
}
})
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment