// 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 var kind string if gvk != nil { kind = gvk.Kind } if len(kind) == 0 { // TODO: this is wrong gvk, err := Scheme.ObjectKind(obj) if err != nil { return nil, err } kind = gvk.Kind } // if the object referenced is actually persisted, we can also get version from meta var version string if gvk != nil { 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 }
// EncodeToStream ensures the provided object is output in the right scheme. If overrides are specified, when // encoding the object the first override that matches the object's group is used. Other overrides are ignored. func (c *codec) EncodeToStream(obj runtime.Object, w io.Writer, overrides ...unversioned.GroupVersion) error { if _, ok := obj.(*runtime.Unknown); ok { return c.serializer.EncodeToStream(obj, w, overrides...) } gvk, isUnversioned, err := c.typer.ObjectKind(obj) if err != nil { return err } if (c.encodeVersion == nil && len(overrides) == 0) || isUnversioned { old := obj.GetObjectKind().GroupVersionKind() obj.GetObjectKind().SetGroupVersionKind(gvk) defer obj.GetObjectKind().SetGroupVersionKind(old) return c.serializer.EncodeToStream(obj, w, overrides...) } targetGV, ok := c.encodeVersion[gvk.Group] // use override if provided for i, override := range overrides { if override.Group == gvk.Group { ok = true targetGV = override // swap the position of the override overrides[0], overrides[i] = targetGV, overrides[0] break } } // attempt a conversion to the sole encode version if !ok && len(c.encodeVersion) == 1 { ok = true for _, v := range c.encodeVersion { targetGV = v } // ensure the target override is first overrides = promoteOrPrependGroupVersion(targetGV, overrides) } // if no fallback is available, error if !ok { return fmt.Errorf("the codec does not recognize group %q for kind %q and cannot encode it", gvk.Group, gvk.Kind) } // Perform a conversion if necessary if gvk.GroupVersion() != targetGV { out, err := c.convertor.ConvertToVersion(obj, targetGV.String()) if err != nil { if ok { return err } } else { obj = out } } else { old := obj.GetObjectKind().GroupVersionKind() defer obj.GetObjectKind().SetGroupVersionKind(old) obj.GetObjectKind().SetGroupVersionKind(&unversioned.GroupVersionKind{Group: targetGV.Group, Version: targetGV.Version, Kind: gvk.Kind}) } return c.serializer.EncodeToStream(obj, w, overrides...) }