// ObjectReaction returns a ReactionFunc that applies core.Action to // the given tracker. func ObjectReaction(tracker ObjectTracker, mapper meta.RESTMapper) ReactionFunc { return func(action Action) (bool, runtime.Object, error) { ns := action.GetNamespace() gvr := action.GetResource() gvk, err := mapper.KindFor(gvr) if err != nil { return false, nil, fmt.Errorf("error getting kind for resource %q: %s", gvr, err) } // This is a temporary fix. Because there is no internal resource, so // the caller has no way to express that it expects to get an internal // kind back. A more proper fix will be directly specify the Kind when // build the action. gvk.Version = gvr.Version if len(gvk.Version) == 0 { gvk.Version = runtime.APIVersionInternal } // Here and below we need to switch on implementation types, // not on interfaces, as some interfaces are identical // (e.g. UpdateAction and CreateAction), so if we use them, // updates and creates end up matching the same case branch. switch action := action.(type) { case ListActionImpl: obj, err := tracker.List(gvk, ns) return true, obj, err case GetActionImpl: obj, err := tracker.Get(gvk, ns, action.GetName()) return true, obj, err case CreateActionImpl: objMeta, err := meta.Accessor(action.GetObject()) if err != nil { return true, nil, err } if action.GetSubresource() == "" { err = tracker.Create(action.GetObject(), ns) } else { // TODO: Currently we're handling subresource creation as an update // on the enclosing resource. This works for some subresources but // might not be generic enough. err = tracker.Update(action.GetObject(), ns) } if err != nil { return true, nil, err } obj, err := tracker.Get(gvk, ns, objMeta.GetName()) return true, obj, err case UpdateActionImpl: objMeta, err := meta.Accessor(action.GetObject()) if err != nil { return true, nil, err } err = tracker.Update(action.GetObject(), ns) if err != nil { return true, nil, err } obj, err := tracker.Get(gvk, ns, objMeta.GetName()) return true, obj, err case DeleteActionImpl: err := tracker.Delete(gvk, ns, action.GetName()) if err != nil { return true, nil, err } return true, nil, nil default: return false, nil, fmt.Errorf("no reaction implemented for %s", action) } } }