// MetaNamespaceKeyFunc is a convenient default KeyFunc which knows how to make // keys for API objects which implement meta.Interface. // The key uses the format <namespace>/<name> unless <namespace> is empty, then // it's just <name>. // // TODO: replace key-as-string with a key-as-struct so that this // packing/unpacking won't be necessary. func MetaNamespaceKeyFunc(obj interface{}) (string, error) { if key, ok := obj.(ExplicitKey); ok { return string(key), nil } meta, err := meta.Accessor(obj) if err != nil { return "", fmt.Errorf("object has no meta: %v", err) } if len(meta.GetNamespace()) > 0 { return meta.GetNamespace() + "/" + meta.GetName(), nil } return meta.GetName(), nil }
// nameIndexFunc is an index function that indexes based on an object's name func nameIndexFunc(obj interface{}) ([]string, error) { meta, err := meta.Accessor(obj) if err != nil { return []string{""}, fmt.Errorf("object has no meta: %v", err) } return []string{meta.GetName()}, nil }
// GetReference returns an ObjectReference which refers to the given // object, or an error if the object doesn't follow the conventions // that would allow this. // TODO: should take a meta.Interface see http://issue.k8s.io/7127 func GetReference(obj runtime.Object) (*ObjectReference, error) { if obj == nil { return nil, ErrNilObject } if ref, ok := obj.(*ObjectReference); ok { // Don't make a reference to a reference. return ref, nil } meta, err := meta.Accessor(obj) if err != nil { return nil, err } gvk := obj.GetObjectKind().GroupVersionKind() // if the object referenced is actually persisted, we can just get kind from meta // if we are building an object reference to something not yet persisted, we should fallback to scheme kind := gvk.Kind if len(kind) == 0 { // TODO: this is wrong gvks, _, err := Scheme.ObjectKinds(obj) if err != nil { return nil, err } kind = gvks[0].Kind } // if the object referenced is actually persisted, we can also get version from meta version := gvk.GroupVersion().String() if len(version) == 0 { selfLink := meta.GetSelfLink() if len(selfLink) == 0 { return nil, ErrNoSelfLink } selfLinkUrl, err := url.Parse(selfLink) if err != nil { return nil, err } // example paths: /<prefix>/<version>/* parts := strings.Split(selfLinkUrl.Path, "/") if len(parts) < 3 { return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version) } version = parts[2] } return &ObjectReference{ Kind: kind, APIVersion: version, Name: meta.GetName(), Namespace: meta.GetNamespace(), UID: meta.GetUID(), ResourceVersion: meta.GetResourceVersion(), }, nil }
func NoNamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { meta, err := meta.Accessor(obj) if err != nil { return "", err } name := meta.GetName() if msgs := validation.IsValidPathSegmentName(name); len(msgs) != 0 { return "", fmt.Errorf("invalid name: %v", msgs) } return prefix + "/" + name, nil }
// ObjectPath returns the full path of an object. // This uses the format "<apiVersion>/namespaces/<namespace>/<kind>/<name>" func ObjectPath(obj KubeObject) (string, error) { // attempt to determine ObjectKind gkv, err := objectKind(obj) if err != nil { return "", fmt.Errorf("could not get object path: %v", err) } meta := obj.GetObjectMeta() path := fmt.Sprintf("namespaces/%s/%s/%s", meta.GetNamespace(), gkv.Kind, meta.GetName()) return strings.ToLower(path), nil }
// update replaces the currently deployed version with a new one. If the objects already match then nothing is done. func (c *KubeCluster) update(obj KubeObject, create bool, mapping *meta.RESTMapping) (KubeObject, error) { meta := obj.GetObjectMeta() deployed, err := c.get(meta.GetNamespace(), meta.GetName(), true, mapping) if doesNotExist(err) && create { return c.create(obj, mapping) } else if err != nil { return nil, err } // TODO: need a better way to handle resource versioning // set resource version on local to same as remote deployedVersion := deployed.GetObjectMeta().GetResourceVersion() meta.SetResourceVersion(deployedVersion) copyImmutables(deployed, obj) // if local matches deployed, do nothing if kube.Semantic.DeepEqual(obj, deployed) { return deployed, nil } patch, err := diff(deployed, obj) if err != nil { return nil, fmt.Errorf("could not create diff: %v", err) } req := c.Client.RESTClient.Patch(kube.StrategicMergePatchType). Name(meta.GetName()). Body(patch) setRequestObjectInfo(req, meta.GetNamespace(), mapping) runtimeObj, err := req.Do().Get() if err != nil { return nil, resourceError("update", meta.GetNamespace(), meta.GetName(), mapping, err) } return AsKubeObject(runtimeObj) }
// create adds the object to the cluster. func (c *KubeCluster) create(obj KubeObject, mapping *meta.RESTMapping) (KubeObject, error) { meta := obj.GetObjectMeta() req := c.Client.RESTClient.Post().Body(obj) setRequestObjectInfo(req, meta.GetNamespace(), mapping) runtimeObj, err := req.Do().Get() if err != nil { return nil, resourceError("create", meta.GetName(), meta.GetNamespace(), mapping, err) } return AsKubeObject(runtimeObj) }
//CreateObjList will create a list from the array of objects func CreateObjList(prefix string, helper storage.Interface, items []runtime.Object) error { for i := range items { obj := items[i] meta, err := meta.Accessor(obj) if err != nil { return err } err = CreateObj(helper, path.Join(prefix, meta.GetName()), obj, obj, 0) if err != nil { return err } items[i] = obj } return nil }