Example #1
0
// 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
}
Example #2
0
// 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...)
}