func (w *etcdWatcher) sendResult(res *etcd.Response) { var action watch.EventType var data []byte var nodes etcd.Nodes switch res.Action { case "set": if res.Node == nil { glog.Errorf("unexpected nil node: %#v", res) return } data = []byte(res.Node.Value) nodes = res.Node.Nodes // TODO: Is this conditional correct? if res.EtcdIndex > 0 { action = watch.Modified } else { action = watch.Added } case "delete": if res.PrevNode == nil { glog.Errorf("unexpected nil prev node: %#v", res) return } data = []byte(res.PrevNode.Value) nodes = res.PrevNode.Nodes action = watch.Deleted } // If listing, we're interested in sub-nodes. if w.list { for _, n := range nodes { obj, err := api.Decode([]byte(n.Value)) if err != nil { glog.Errorf("failure to decode api object: %#v", res) continue } if w.filter != nil && !w.filter(obj) { continue } w.outgoing <- watch.Event{ Type: action, Object: obj, } } return } obj, err := api.Decode(data) if err != nil { glog.Errorf("failure to decode api object: %#v", res) return } w.outgoing <- watch.Event{ Type: action, Object: obj, } }
func TestBadJSONRejection(t *testing.T) { badJSONMissingKind := []byte(`{ }`) if _, err := api.Decode(badJSONMissingKind); err == nil { t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind) } badJSONUnknownType := []byte(`{"kind": "bar"}`) if _, err1 := api.Decode(badJSONUnknownType); err1 == nil { t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType) } /*badJSONKindMismatch := []byte(`{"kind": "Pod"}`) if err2 := DecodeInto(badJSONKindMismatch, &Minion{}); err2 == nil { t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch) }*/ }
func TestDoRequestAcceptedSuccess(t *testing.T) { status := api.Status{Status: api.StatusSuccess} expectedBody, _ := api.Encode(status) fakeHandler := util.FakeHandler{ StatusCode: 202, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewTLSServer(&fakeHandler) request, _ := http.NewRequest("GET", testServer.URL+"/foo/bar", nil) auth := AuthInfo{User: "******", Password: "******"} c := New(testServer.URL, &auth) body, err := c.doRequest(request) if request.Header["Authorization"] == nil { t.Errorf("Request is missing authorization header: %#v", *request) } if err != nil { t.Errorf("Unexpected error %#v", err) } statusOut, err := api.Decode(body) if err != nil { t.Errorf("Unexpected error %#v", err) } if !reflect.DeepEqual(&status, statusOut) { t.Errorf("Unexpected mis-match. Expected %#v. Saw %#v", status, statusOut) } fakeHandler.ValidateRequest(t, "/foo/bar", "GET", nil) }
// Print parses the data as JSON, and re-formats it with the Go Template. func (t *TemplatePrinter) Print(data []byte, w io.Writer) error { obj, err := api.Decode(data) if err != nil { return err } return t.PrintObj(obj, w) }
// Print parses the data as JSON, then prints the parsed data in a human-friendly format according to the type of the data. func (h *HumanReadablePrinter) Print(data []byte, output io.Writer) error { var mapObj map[string]interface{} if err := json.Unmarshal([]byte(data), &mapObj); err != nil { return err } if _, contains := mapObj["kind"]; !contains { return fmt.Errorf("unexpected object with no 'kind' field: %s", data) } obj, err := api.Decode(data) if err != nil { return err } return h.PrintObj(obj, output) }
func TestOperationsList(t *testing.T) { simpleStorage := &SimpleRESTStorage{} handler := New(map[string]RESTStorage{ "foo": simpleStorage, }, "/prefix/version") handler.asyncOpWait = 0 server := httptest.NewServer(handler) client := http.Client{} simple := Simple{ Name: "foo", } data, err := api.Encode(simple) if err != nil { t.Errorf("unexpected error: %v", err) } response, err := client.Post(server.URL+"/prefix/version/foo", "application/json", bytes.NewBuffer(data)) if err != nil { t.Errorf("unexpected error: %v", err) } if response.StatusCode != http.StatusAccepted { t.Errorf("Unexpected response %#v", response) } response, err = client.Get(server.URL + "/prefix/version/operations") if err != nil { t.Errorf("unexpected error: %v", err) } if response.StatusCode != http.StatusOK { t.Fatalf("unexpected status code %#v", response) } body, err := ioutil.ReadAll(response.Body) if err != nil { t.Errorf("unexpected error: %v", err) } obj, err := api.Decode(body) if err != nil { t.Errorf("unexpected error: %v", err) } oplist, ok := obj.(*api.ServerOpList) if !ok { t.Fatalf("expected ServerOpList, got %#v", obj) } if len(oplist.Items) != 1 { t.Errorf("expected 1 operation, got %#v", obj) } }
func TestEncode_Ptr(t *testing.T) { pod := &api.Pod{ Labels: map[string]string{"name": "foo"}, } obj := interface{}(pod) data, err := api.Encode(obj) obj2, err2 := api.Decode(data) if err != nil || err2 != nil { t.Fatalf("Failure: '%v' '%v'", err, err2) } if _, ok := obj2.(*api.Pod); !ok { t.Fatalf("Got wrong type") } if !reflect.DeepEqual(obj2, pod) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", &pod, obj2) } }
func (w *etcdWatcher) sendResult(res *etcd.Response) { var action watch.EventType var data []byte switch res.Action { case "set": if res.Node == nil { glog.Errorf("unexpected nil node: %#v", res) return } data = []byte(res.Node.Value) // TODO: Is this conditional correct? if res.EtcdIndex > 0 { action = watch.Modified } else { action = watch.Added } case "delete": if res.PrevNode == nil { glog.Errorf("unexpected nil prev node: %#v", res) return } data = []byte(res.PrevNode.Value) action = watch.Deleted default: glog.Errorf("unknown action: %v", res.Action) return } obj, err := api.Decode(data) if err != nil { glog.Errorf("failure to decode api object: '%v' from %#v", string(data), res) // TODO: expose an error through watch.Interface? w.Stop() return } w.emit(watch.Event{ Type: action, Object: obj, }) }
func TestIdentityPrinter(t *testing.T) { printer := &IdentityPrinter{} buff := bytes.NewBuffer([]byte{}) str := "this is a test string" printer.Print([]byte(str), buff) if buff.String() != str { t.Errorf("Bytes are not equal: %s vs %s", str, buff.String()) } obj := api.Pod{ JSONBase: api.JSONBase{ID: "foo"}, } buff.Reset() printer.PrintObj(obj, buff) objOut, err := api.Decode([]byte(buff.String())) if err != nil { t.Errorf("Unexpeted error: %#v", err) } if !reflect.DeepEqual(&obj, objOut) { t.Errorf("Unexpected inequality: %#v vs %#v", obj, objOut) } }
func runTest(t *testing.T, source interface{}) { name := reflect.TypeOf(source).Elem().Name() apiObjectFuzzer.Fuzz(source) j, err := api.FindJSONBase(source) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, source) } j.SetKind("") j.SetAPIVersion("") data, err := api.Encode(source) if err != nil { t.Errorf("%v: %v (%#v)", name, err, source) return } obj2, err := api.Decode(data) if err != nil { t.Errorf("%v: %v", name, err) return } else { if !reflect.DeepEqual(source, obj2) { t.Errorf("1: %v: diff: %v", name, objDiff(source, obj2)) return } } obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface() err = api.DecodeInto(data, obj3) if err != nil { t.Errorf("2: %v: %v", name, err) return } else { if !reflect.DeepEqual(source, obj3) { t.Errorf("3: %v: diff: %v", name, objDiff(source, obj3)) return } } }
func executeAPIRequest(method string, s *kube_client.Client) bool { storage, path, hasSuffix := storagePathFromArg(flag.Arg(1)) validStorage := checkStorage(storage) verb := "" setBody := false var version uint64 switch method { case "get": verb = "GET" if !validStorage || !hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>[/<id>]", method, prettyWireStorage()) } case "list": verb = "GET" if !validStorage || hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage()) } case "delete": verb = "DELETE" if !validStorage || !hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage()) } case "create": verb = "POST" setBody = true if !validStorage || hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>", method, prettyWireStorage()) } case "update": obj, err := s.Verb("GET").Path(path).Do().Get() if err != nil { glog.Fatalf("error obtaining resource version for update: %v", err) } jsonBase, err := api.FindJSONBase(obj) if err != nil { glog.Fatalf("error finding json base for update: %v", err) } version = jsonBase.ResourceVersion() verb = "PUT" setBody = true if !validStorage || !hasSuffix { glog.Fatalf("usage: kubecfg [OPTIONS] %s <%s>/<id>", method, prettyWireStorage()) } default: return false } r := s.Verb(verb). Path(path). ParseSelectorParam("labels", *selector) if setBody { if version != 0 { data := readConfig(storage) obj, err := api.Decode(data) if err != nil { glog.Fatalf("error setting resource version: %v", err) } jsonBase, err := api.FindJSONBase(obj) if err != nil { glog.Fatalf("error setting resource version: %v", err) } jsonBase.SetResourceVersion(version) data, err = api.Encode(obj) if err != nil { glog.Fatalf("error setting resource version: %v", err) } r.Body(data) } else { r.Body(readConfig(storage)) } } result := r.Do() obj, err := result.Get() if err != nil { glog.Fatalf("Got request error: %v\n", err) return false } var printer kubecfg.ResourcePrinter switch { case *json: printer = &kubecfg.IdentityPrinter{} case *yaml: printer = &kubecfg.YAMLPrinter{} case len(*templateFile) > 0 || len(*templateStr) > 0: var data []byte if len(*templateFile) > 0 { var err error data, err = ioutil.ReadFile(*templateFile) if err != nil { glog.Fatalf("Error reading template %s, %v\n", *templateFile, err) return false } } else { data = []byte(*templateStr) } tmpl, err := template.New("output").Parse(string(data)) if err != nil { glog.Fatalf("Error parsing template %s, %v\n", string(data), err) return false } printer = &kubecfg.TemplatePrinter{ Template: tmpl, } default: printer = &kubecfg.HumanReadablePrinter{} } if err = printer.PrintObj(obj, os.Stdout); err != nil { body, _ := result.Raw() glog.Fatalf("Failed to print: %v\nRaw received object:\n%#v\n\nBody received: %v", err, obj, string(body)) } fmt.Print("\n") return true }
// Get returns the result as an object. func (r Result) Get() (interface{}, error) { if r.err != nil { return nil, r.err } return api.Decode(r.body) }