// 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 (v FlattenListVisitor) Visit(fn VisitorFunc) error { return v.Visitor.Visit(func(info *Info) error { if info.Object == nil { return fn(info) } items, err := runtime.ExtractList(info.Object) if err != nil { return fn(info) } if errs := runtime.DecodeList(items, struct { runtime.ObjectTyper runtime.Decoder }{v.Mapper, info.Mapping.Codec}); len(errs) > 0 { return errors.NewAggregate(errs) } for i := range items { item, err := v.InfoForObject(items[i]) if err != nil { return err } if len(info.ResourceVersion) != 0 { item.ResourceVersion = info.ResourceVersion } if err := fn(item); err != nil { return err } } return nil }) }
func (o objects) Add(obj runtime.Object) error { _, kind, err := o.scheme.ObjectVersionAndKind(obj) if err != nil { return err } switch { case runtime.IsListType(obj): if kind != "List" { o.types[kind] = append(o.types[kind], obj) } list, err := runtime.ExtractList(obj) if err != nil { return err } if errs := runtime.DecodeList(list, o.decoder); len(errs) > 0 { return errs[0] } for _, obj := range list { if err := o.Add(obj); err != nil { return err } } default: if status, ok := obj.(*api.Status); ok && status.Details != nil { kind = status.Details.Kind } o.types[kind] = append(o.types[kind], obj) } return 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 }
func (r *Reflector) listAndWatch(stopCh <-chan struct{}) { var resourceVersion string resyncCh, cleanup := r.resyncChan() defer cleanup() list, err := r.listerWatcher.List() if err != nil { glog.Errorf("Failed to list %v: %v", r.expectedType, err) return } meta, err := meta.Accessor(list) if err != nil { glog.Errorf("Unable to understand list result %#v", list) return } resourceVersion = meta.ResourceVersion() items, err := runtime.ExtractList(list) if err != nil { glog.Errorf("Unable to understand list result %#v (%v)", list, err) return } if err := r.syncWith(items); err != nil { glog.Errorf("Unable to sync list result: %v", err) return } r.setLastSyncResourceVersion(resourceVersion) for { w, err := r.listerWatcher.Watch(resourceVersion) if err != nil { switch err { case io.EOF: // watch closed normally case io.ErrUnexpectedEOF: glog.V(1).Infof("Watch for %v closed with unexpected EOF: %v", r.expectedType, err) default: glog.Errorf("Failed to watch %v: %v", r.expectedType, err) } // If this is "connection refused" error, it means that most likely apiserver is not responsive. // It doesn't make sense to re-list all objects because most likely we will be able to restart // watch where we ended. // If that's the case wait and resend watch request. if urlError, ok := err.(*url.Error); ok { if opError, ok := urlError.Err.(*net.OpError); ok { if errno, ok := opError.Err.(syscall.Errno); ok && errno == syscall.ECONNREFUSED { time.Sleep(time.Second) continue } } } return } if err := r.watchHandler(w, &resourceVersion, resyncCh, stopCh); err != nil { if err != errorResyncRequested && err != errorStopRequested { glog.Errorf("watch of %v ended with: %v", r.expectedType, err) } return } } }
func TestExtractListOfInterfacePtrs(t *testing.T) { pl := &fakePtrInterfaceList{ Items: &[]runtime.Object{}, } list, err := runtime.ExtractList(pl) if err != nil { t.Fatalf("Unexpected error %v", err) } if len(list) > 0 { t.Fatalf("Expected empty list, got %#v", list) } }
func TestExtractListOfValuePtrs(t *testing.T) { pl := &fakePtrValueList{ Items: []*api.Pod{ {ObjectMeta: api.ObjectMeta{Name: "1"}}, {ObjectMeta: api.ObjectMeta{Name: "2"}}, }, } list, err := runtime.ExtractList(pl) 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 obj, ok := list[i].(*api.Pod); !ok { t.Fatalf("Expected list[%d] to be *api.Pod, it is %#v", i, obj) } } }
func TestExtractListGeneric(t *testing.T) { pl := &api.List{ Items: []runtime.Object{ &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}}, &api.Service{ObjectMeta: api.ObjectMeta{Name: "2"}}, }, } list, err := runtime.ExtractList(pl) 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) } if obj, ok := list[0].(*api.Pod); !ok { t.Fatalf("Expected list[0] to be *api.Pod, it is %#v", obj) } if obj, ok := list[1].(*api.Service); !ok { t.Fatalf("Expected list[1] to be *api.Service, it is %#v", obj) } }
func TestExtractList(t *testing.T) { pl := &api.PodList{ Items: []api.Pod{ {ObjectMeta: api.ObjectMeta{Name: "1"}}, {ObjectMeta: api.ObjectMeta{Name: "2"}}, {ObjectMeta: api.ObjectMeta{Name: "3"}}, }, } list, err := runtime.ExtractList(pl) 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) } } }
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)) } }