// fuzzInternalObject fuzzes an arbitrary runtime object using the appropriate // fuzzer registered with the apitesting package. func fuzzInternalObject(t *testing.T, forVersion schema.GroupVersion, item runtime.Object, seed int64) runtime.Object { apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)).Fuzz(item) j, err := meta.TypeAccessor(item) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, item) } j.SetKind("") j.SetAPIVersion("") return item }
func TestGenericTypeMeta(t *testing.T) { type TypeMeta struct { Kind string `json:"kind,omitempty"` Namespace string `json:"namespace,omitempty"` Name string `json:"name,omitempty"` GenerateName string `json:"generateName,omitempty"` UID string `json:"uid,omitempty"` CreationTimestamp metav1.Time `json:"creationTimestamp,omitempty"` SelfLink string `json:"selfLink,omitempty"` ResourceVersion string `json:"resourceVersion,omitempty"` APIVersion string `json:"apiVersion,omitempty"` Labels map[string]string `json:"labels,omitempty"` Annotations map[string]string `json:"annotations,omitempty"` OwnerReferences []metav1.OwnerReference `json:"ownerReferences,omitempty"` Finalizers []string `json:"finalizers,omitempty"` } j := struct{ TypeMeta }{TypeMeta{APIVersion: "a", Kind: "b"}} typeAccessor, err := meta.TypeAccessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } typeAccessor.SetAPIVersion("d") typeAccessor.SetKind("e") if e, a := "d", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "e", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } }
func doRoundTripTest(group testapi.TestGroup, kind string, t *testing.T) { object, err := api.Scheme.New(group.InternalGroupVersion().WithKind(kind)) if err != nil { t.Fatalf("Couldn't make a %v? %v", kind, err) } if _, err := meta.TypeAccessor(object); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } if api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) { roundTripSame(t, group, object, nonRoundTrippableTypesByVersion[kind]...) } if !nonInternalRoundTrippableTypes.Has(kind) && api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) { roundTrip(t, group.Codec(), fuzzInternalObject(t, group.InternalGroupVersion(), object, rand.Int63())) } }
func TestAPIObjectMeta(t *testing.T) { j := &api.Pod{ TypeMeta: metav1.TypeMeta{APIVersion: "/a", Kind: "b"}, ObjectMeta: metav1.ObjectMeta{ Namespace: "bar", Name: "foo", GenerateName: "prefix", UID: "uid", ResourceVersion: "1", SelfLink: "some/place/only/we/know", Labels: map[string]string{"foo": "bar"}, Annotations: map[string]string{"x": "y"}, Finalizers: []string{ "finalizer.1", "finalizer.2", }, }, } var _ metav1.Object = &j.ObjectMeta var _ metav1.ObjectMetaAccessor = j accessor, err := meta.Accessor(j) if err != nil { t.Fatalf("unexpected error: %v", err) } if accessor != metav1.Object(j) { t.Fatalf("should have returned the same pointer: %#v\n\n%#v", accessor, j) } if e, a := "bar", accessor.GetNamespace(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "foo", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "prefix", accessor.GetGenerateName(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "uid", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := []string{"finalizer.1", "finalizer.2"}, accessor.GetFinalizers(); !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } typeAccessor, err := meta.TypeAccessor(j) if err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } accessor.SetNamespace("baz") accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") typeAccessor.SetAPIVersion("c") typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") accessor.SetFinalizers([]string{"finalizer.3"}) // Prove that accessor changes the original object. if e, a := "baz", j.Namespace; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "bar", j.Name; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "generate", j.GenerateName; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := types.UID("other"), j.UID; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "c", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "2", j.ResourceVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "google.com", j.SelfLink; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := []string{"finalizer.3"}, j.Finalizers; !reflect.DeepEqual(e, a) { t.Errorf("expected %v, got %v", e, a) } typeAccessor.SetAPIVersion("d") typeAccessor.SetKind("e") if e, a := "d", j.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "e", j.Kind; e != a { t.Errorf("expected %v, got %v", e, a) } }
// Dequeueing an event from eventQueue, updating graph, populating dirty_queue. func (p *Propagator) processEvent() { timedItem, quit := p.eventQueue.Get() if quit { return } defer p.eventQueue.Done(timedItem) event, ok := timedItem.Object.(*event) if !ok { utilruntime.HandleError(fmt.Errorf("expect a *event, got %v", timedItem.Object)) return } obj := event.obj accessor, err := meta.Accessor(obj) if err != nil { utilruntime.HandleError(fmt.Errorf("cannot access obj: %v", err)) return } typeAccessor, err := meta.TypeAccessor(obj) if err != nil { utilruntime.HandleError(fmt.Errorf("cannot access obj: %v", err)) return } glog.V(6).Infof("Propagator process object: %s/%s, namespace %s, name %s, event type %s", typeAccessor.GetAPIVersion(), typeAccessor.GetKind(), accessor.GetNamespace(), accessor.GetName(), event.eventType) // Check if the node already exsits existingNode, found := p.uidToNode.Read(accessor.GetUID()) switch { case (event.eventType == addEvent || event.eventType == updateEvent) && !found: newNode := &node{ identity: objectReference{ OwnerReference: metav1.OwnerReference{ APIVersion: typeAccessor.GetAPIVersion(), Kind: typeAccessor.GetKind(), UID: accessor.GetUID(), Name: accessor.GetName(), }, Namespace: accessor.GetNamespace(), }, dependents: make(map[*node]struct{}), owners: accessor.GetOwnerReferences(), } p.insertNode(newNode) // the underlying delta_fifo may combine a creation and deletion into one event if shouldOrphanDependents(event, accessor) { glog.V(6).Infof("add %s to the orphanQueue", newNode.identity) p.gc.orphanQueue.Add(&workqueue.TimedWorkQueueItem{StartTime: p.gc.clock.Now(), Object: newNode}) } case (event.eventType == addEvent || event.eventType == updateEvent) && found: // caveat: if GC observes the creation of the dependents later than the // deletion of the owner, then the orphaning finalizer won't be effective. if shouldOrphanDependents(event, accessor) { glog.V(6).Infof("add %s to the orphanQueue", existingNode.identity) p.gc.orphanQueue.Add(&workqueue.TimedWorkQueueItem{StartTime: p.gc.clock.Now(), Object: existingNode}) } // add/remove owner refs added, removed := referencesDiffs(existingNode.owners, accessor.GetOwnerReferences()) if len(added) == 0 && len(removed) == 0 { glog.V(6).Infof("The updateEvent %#v doesn't change node references, ignore", event) return } // update the node itself existingNode.owners = accessor.GetOwnerReferences() // Add the node to its new owners' dependent lists. p.addDependentToOwners(existingNode, added) // remove the node from the dependent list of node that are no long in // the node's owners list. p.removeDependentFromOwners(existingNode, removed) case event.eventType == deleteEvent: if !found { glog.V(6).Infof("%v doesn't exist in the graph, this shouldn't happen", accessor.GetUID()) return } p.removeNode(existingNode) existingNode.dependentsLock.RLock() defer existingNode.dependentsLock.RUnlock() if len(existingNode.dependents) > 0 { p.gc.absentOwnerCache.Add(accessor.GetUID()) } for dep := range existingNode.dependents { p.gc.dirtyQueue.Add(&workqueue.TimedWorkQueueItem{StartTime: p.gc.clock.Now(), Object: dep}) } } EventProcessingLatency.Observe(sinceInMicroseconds(p.gc.clock, timedItem.StartTime)) }