// Sets the SelfLink field of the object. func (h *RESTHandler) setSelfLink(obj runtime.Object, req *http.Request) error { newURL := *req.URL newURL.Path = path.Join(h.canonicalPrefix, req.URL.Path) newURL.RawQuery = "" newURL.Fragment = "" err := h.selfLinker.SetSelfLink(obj, newURL.String()) if err != nil { return err } if !runtime.IsListType(obj) { return nil } // Set self-link of objects in the list. items, err := runtime.ExtractList(obj) if err != nil { return err } for i := range items { if err := h.setSelfLinkAddName(items[i], req); err != nil { return err } } return runtime.SetList(obj, items) }
// List returns a list object, with its resource version set. func (f *FakeControllerSource) List() (runtime.Object, error) { f.lock.RLock() defer f.lock.RUnlock() list := make([]runtime.Object, 0, len(f.items)) for _, obj := range f.items { // Must make a copy to allow clients to modify the object. // Otherwise, if they make a change and write it back, they // will inadvertently change the our canonical copy (in // addition to racing with other clients). objCopy, err := conversion.DeepCopy(obj) if err != nil { return nil, err } list = append(list, objCopy.(runtime.Object)) } listObj := &api.List{} if err := runtime.SetList(listObj, list); err != nil { return nil, err } objMeta, err := api.ListMetaFor(listObj) if err != nil { return nil, err } resourceVersion := len(f.changes) objMeta.ResourceVersion = strconv.Itoa(resourceVersion) return listObj, nil }
// FilterList filters any list object that conforms to the api conventions, // provided that 'm' works with the concrete type of list. d is an optional // decorator for the returned functions. Only matching items are decorated. func FilterList(list runtime.Object, m Matcher, d DecoratorFunc) (filtered runtime.Object, err error) { // TODO: push a matcher down into tools.EtcdHelper to avoid all this // nonsense. This is a lot of unnecessary copies. items, err := runtime.ExtractList(list) if err != nil { return nil, err } var filteredItems []runtime.Object for _, obj := range items { match, err := m.Matches(obj) if err != nil { return nil, err } if match { if d != nil { if err := d(obj); err != nil { return nil, err } } filteredItems = append(filteredItems, obj) } } err = runtime.SetList(list, filteredItems) if err != nil { return nil, err } return list, nil }
// setListSelfLink sets the self link of a list to the base URL, then sets the self links // on all child objects returned. func setListSelfLink(obj runtime.Object, req *restful.Request, namer ScopeNamer) error { if !runtime.IsListType(obj) { return nil } // TODO: List SelfLink generation should return a full URL? path, query, err := namer.GenerateListLink(req) if err != nil { return err } newURL := *req.Request.URL newURL.Path = path newURL.RawQuery = query // use the path that got us here newURL.Fragment = "" if err := namer.SetSelfLink(obj, newURL.String()); err != nil { glog.V(4).Infof("Unable to set self link on object: %v", err) } // Set self-link of objects in the list. items, err := runtime.ExtractList(obj) if err != nil { return err } for i := range items { if err := setSelfLink(items[i], req, namer); err != nil { return err } } return runtime.SetList(obj, items) }
func TestGetMultipleTypeObjectsAsList(t *testing.T) { pods, svc, _ := testData() f, tf, codec := NewAPIFactory() tf.Printer = &testPrinter{} tf.Client = &client.FakeRESTClient{ Codec: codec, Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { switch req.URL.Path { case "/namespaces/test/pods": return &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, nil case "/namespaces/test/services": return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } }), } tf.Namespace = "test" tf.ClientConfig = &client.Config{Version: testapi.Version()} buf := bytes.NewBuffer([]byte{}) cmd := NewCmdGet(f, buf) cmd.SetOutput(buf) cmd.Flags().Set("output", "json") cmd.Run(cmd, []string{"pods,services"}) if tf.Printer.(*testPrinter).Objects != nil { t.Errorf("unexpected print to default printer") } out, err := codec.Decode(buf.Bytes()) if err != nil { t.Fatalf("unexpected error: %v", err) } list, err := runtime.ExtractList(out) if err != nil { t.Fatalf("unexpected error: %v", err) } if errs := runtime.DecodeList(list, api.Scheme); len(errs) > 0 { t.Fatalf("unexpected error: %v", errs) } if err := runtime.SetList(out, list); err != nil { t.Fatalf("unexpected error: %v", err) } expected := &api.List{ Items: []runtime.Object{ &pods.Items[0], &pods.Items[1], &svc.Items[0], }, } if !reflect.DeepEqual(expected, out) { t.Errorf("unexpected output: %#v", out) } }
func (o objects) Kind(kind, name string) (runtime.Object, error) { empty, _ := o.creater.New("", kind) nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object) arr, ok := o.types[kind] if !ok { if strings.HasSuffix(kind, "List") { itemKind := kind[:len(kind)-4] arr, ok := o.types[itemKind] if !ok { return empty, nil } out, err := o.creater.New("", kind) if err != nil { return nilValue, err } if err := runtime.SetList(out, arr); err != nil { return nilValue, err } if out, err = o.copier.Copy(out); err != nil { return nilValue, err } return out, nil } return nilValue, errors.NewNotFound(kind, name) } index := o.last[kind] if index >= len(arr) { index = len(arr) - 1 } if index < 0 { return nilValue, errors.NewNotFound(kind, name) } out, err := o.copier.Copy(arr[index]) if err != nil { return nilValue, err } o.last[kind] = index + 1 if status, ok := out.(*api.Status); ok { if status.Details != nil { status.Details.Kind = kind } if status.Status != api.StatusSuccess { return nilValue, &errors.StatusError{*status} } } return out, nil }
func TestSetListToRuntimeObjectArray(t *testing.T) { pl := &api.List{} list := []runtime.Object{ &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}}, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "3"}}, } err := runtime.SetList(pl, list) if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := len(list), len(pl.Items); e != a { t.Fatalf("Expected %v, got %v", e, a) } for i := range list { if e, a := list[i], pl.Items[i]; e != a { t.Fatalf("%d: unmatched: %s", i, util.ObjectDiff(e, a)) } } }
func TestSetList(t *testing.T) { pl := &api.PodList{} list := []runtime.Object{ &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}}, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "3"}}, } err := runtime.SetList(pl, list) if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := len(list), len(pl.Items); e != a { t.Fatalf("Expected %v, got %v", e, a) } for i := range list { if e, a := list[i].(*api.Pod).Name, pl.Items[i].Name; e != a { t.Fatalf("Expected %v, got %v", e, a) } } }
// Sets the SelfLink field of the object. func (h *RESTHandler) setSelfLink(obj runtime.Object, req *http.Request) error { newURL := *req.URL newURL.Path = path.Join(h.canonicalPrefix, req.URL.Path) newURL.RawQuery = "" newURL.Fragment = "" namespace, err := h.selfLinker.Namespace(obj) if err != nil { return err } // we need to add namespace as a query param, if its not in the resource path if len(namespace) > 0 { parts := splitPath(req.URL.Path) if parts[0] != "ns" { query := newURL.Query() query.Set("namespace", namespace) newURL.RawQuery = query.Encode() } } err = h.selfLinker.SetSelfLink(obj, newURL.String()) if err != nil { return err } if !runtime.IsListType(obj) { return nil } // Set self-link of objects in the list. items, err := runtime.ExtractList(obj) if err != nil { return err } for i := range items { if err := h.setSelfLinkAddName(items[i], req); err != nil { return err } } return runtime.SetList(obj, items) }
func TestSetExtractListRoundTrip(t *testing.T) { fuzzer := fuzz.New().NilChance(0).NumElements(1, 5) for i := 0; i < 5; i++ { start := &api.PodList{} fuzzer.Fuzz(&start.Items) list, err := runtime.ExtractList(start) if err != nil { t.Errorf("Unexpected error %v", err) continue } got := &api.PodList{} err = runtime.SetList(got, list) if err != nil { t.Errorf("Unexpected error %v", err) continue } if e, a := start, got; !reflect.DeepEqual(e, a) { t.Fatalf("Expected %#v, got %#v", e, a) } } }
func TestArrayOfRuntimeObject(t *testing.T) { s := runtime.NewScheme() s.AddKnownTypes("", &EmbeddedTest{}) s.AddKnownTypeWithName("v1test", "EmbeddedTest", &EmbeddedTestExternal{}) s.AddKnownTypes("", &ObjectTest{}) s.AddKnownTypeWithName("v1test", "ObjectTest", &ObjectTestExternal{}) internal := &ObjectTest{ Items: []runtime.Object{ &EmbeddedTest{ID: "foo"}, &EmbeddedTest{ID: "bar"}, // TODO: until YAML is removed, this JSON must be in ascending key order to ensure consistent roundtrip serialization &runtime.Unknown{RawJSON: []byte(`{"apiVersion":"unknown","foo":"bar","kind":"OtherTest"}`)}, &ObjectTest{ Items: []runtime.Object{ &EmbeddedTest{ID: "baz"}, }, }, }, } wire, err := s.EncodeToVersion(internal, "v1test") if err != nil { t.Fatalf("unexpected error: %v", err) } t.Logf("Wire format is:\n%s\n", string(wire)) obj := &ObjectTestExternal{} if err := json.Unmarshal(wire, obj); err != nil { t.Fatalf("unexpected error: %v", err) } t.Logf("exact wire is: %s", string(obj.Items[0].RawJSON)) decoded, err := s.Decode(wire) if err != nil { t.Fatalf("unexpected error: %v", err) } list, err := runtime.ExtractList(decoded) if err != nil { t.Fatalf("unexpected error: %v", err) } if errs := runtime.DecodeList(list, s); len(errs) > 0 { t.Fatalf("unexpected error: %v", errs) } list2, err := runtime.ExtractList(list[3]) if err != nil { t.Fatalf("unexpected error: %v", err) } if errs := runtime.DecodeList(list2, s); len(errs) > 0 { t.Fatalf("unexpected error: %v", errs) } if err := runtime.SetList(list[3], list2); err != nil { t.Fatalf("unexpected error: %v", err) } internal.Items[2].(*runtime.Unknown).Kind = "OtherTest" internal.Items[2].(*runtime.Unknown).APIVersion = "unknown" if e, a := internal.Items, list; !reflect.DeepEqual(e, a) { t.Errorf("mismatched decoded: %s", util.ObjectDiff(e, a)) } }