func (gc *GarbageCollector) patchObject(item objectReference, patch []byte) (*runtime.Unstructured, error) { fqKind := schema.FromAPIVersionAndKind(item.APIVersion, item.Kind) client, err := gc.clientPool.ClientForGroupVersionKind(fqKind) gc.registeredRateLimiter.registerIfNotPresent(fqKind.GroupVersion(), client, "garbage_collector_operation") resource, err := gc.apiResource(item.APIVersion, item.Kind, len(item.Namespace) != 0) if err != nil { return nil, err } return client.Resource(resource, item.Namespace).Patch(item.Name, api.StrategicMergePatchType, patch) }
func (gc *GarbageCollector) deleteObject(item objectReference) error { fqKind := schema.FromAPIVersionAndKind(item.APIVersion, item.Kind) client, err := gc.clientPool.ClientForGroupVersionKind(fqKind) gc.registeredRateLimiter.registerIfNotPresent(fqKind.GroupVersion(), client, "garbage_collector_operation") resource, err := gc.apiResource(item.APIVersion, item.Kind, len(item.Namespace) != 0) if err != nil { return err } uid := item.UID preconditions := v1.Preconditions{UID: &uid} deleteOptions := v1.DeleteOptions{Preconditions: &preconditions} return client.Resource(resource, item.Namespace).Delete(item.Name, &deleteOptions) }
// apiResource consults the REST mapper to translate an <apiVersion, kind, // namespace> tuple to a metav1.APIResource struct. func (gc *GarbageCollector) apiResource(apiVersion, kind string, namespaced bool) (*metav1.APIResource, error) { fqKind := schema.FromAPIVersionAndKind(apiVersion, kind) mapping, err := gc.restMapper.RESTMapping(fqKind.GroupKind(), apiVersion) if err != nil { return nil, fmt.Errorf("unable to get REST mapping for kind: %s, version: %s", kind, apiVersion) } glog.V(6).Infof("map kind %s, version %s to resource %s", kind, apiVersion, mapping.Resource) resource := metav1.APIResource{ Name: mapping.Resource, Namespaced: namespaced, Kind: kind, } return &resource, nil }
func (obj *MyWeirdCustomEmbeddedVersionKindField) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.ObjectKind) }
// GroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta func (obj *TypeMeta) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) }
func (obj *ExternalType2) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) }
func (obj *ObjectReference) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) }
func (obj *MyAPIObject) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.TypeMeta.APIVersion, obj.TypeMeta.Kind) }
func (gc *GarbageCollector) processItem(item *node) error { // Get the latest item from the API server latest, err := gc.getObject(item.identity) if err != nil { if errors.IsNotFound(err) { // the Propagator can add "virtual" node for an owner that doesn't // exist yet, so we need to enqueue a virtual Delete event to remove // the virtual node from Propagator.uidToNode. glog.V(6).Infof("item %v not found, generating a virtual delete event", item.identity) event := &event{ eventType: deleteEvent, obj: objectReferenceToMetadataOnlyObject(item.identity), } glog.V(6).Infof("generating virtual delete event for %s\n\n", event.obj) gc.propagator.eventQueue.Add(&workqueue.TimedWorkQueueItem{StartTime: gc.clock.Now(), Object: event}) return nil } return err } if latest.GetUID() != item.identity.UID { glog.V(6).Infof("UID doesn't match, item %v not found, generating a virtual delete event", item.identity) event := &event{ eventType: deleteEvent, obj: objectReferenceToMetadataOnlyObject(item.identity), } glog.V(6).Infof("generating virtual delete event for %s\n\n", event.obj) gc.propagator.eventQueue.Add(&workqueue.TimedWorkQueueItem{StartTime: gc.clock.Now(), Object: event}) return nil } ownerReferences := latest.GetOwnerReferences() if len(ownerReferences) == 0 { glog.V(6).Infof("object %s's doesn't have an owner, continue on next item", item.identity) return nil } // TODO: we need to remove dangling references if the object is not to be // deleted. for _, reference := range ownerReferences { if gc.absentOwnerCache.Has(reference.UID) { glog.V(6).Infof("according to the absentOwnerCache, object %s's owner %s/%s, %s does not exist", item.identity.UID, reference.APIVersion, reference.Kind, reference.Name) continue } // TODO: we need to verify the reference resource is supported by the // system. If it's not a valid resource, the garbage collector should i) // ignore the reference when decide if the object should be deleted, and // ii) should update the object to remove such references. This is to // prevent objects having references to an old resource from being // deleted during a cluster upgrade. fqKind := schema.FromAPIVersionAndKind(reference.APIVersion, reference.Kind) client, err := gc.clientPool.ClientForGroupVersionKind(fqKind) if err != nil { return err } resource, err := gc.apiResource(reference.APIVersion, reference.Kind, len(item.identity.Namespace) != 0) if err != nil { return err } owner, err := client.Resource(resource, item.identity.Namespace).Get(reference.Name) if err == nil { if owner.GetUID() != reference.UID { glog.V(6).Infof("object %s's owner %s/%s, %s is not found, UID mismatch", item.identity.UID, reference.APIVersion, reference.Kind, reference.Name) gc.absentOwnerCache.Add(reference.UID) continue } glog.V(6).Infof("object %s has at least an existing owner, will not garbage collect", item.identity.UID) return nil } else if errors.IsNotFound(err) { gc.absentOwnerCache.Add(reference.UID) glog.V(6).Infof("object %s's owner %s/%s, %s is not found", item.identity.UID, reference.APIVersion, reference.Kind, reference.Name) } else { return err } } glog.V(2).Infof("none of object %s's owners exist any more, will garbage collect it", item.identity) return gc.deleteObject(item.identity) }
func (obj *Config) GroupVersionKind() schema.GroupVersionKind { return schema.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) }