// 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>
func MetaNamespaceKeyFunc(obj interface{}) (string, error) {
	meta, err := meta.Accessor(obj)
	if err != nil {
		return "", fmt.Errorf("object has no meta: %v", err)
	}
	if len(meta.Namespace()) > 0 {
		return meta.Namespace() + "/" + meta.Name(), nil
	}
	return meta.Name(), nil
}
// 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.Namespace()) > 0 {
		return meta.Namespace() + "/" + meta.Name(), nil
	}
	return meta.Name(), nil
}
Exemple #3
0
// MetaNamespaceIndexFunc is a default index function that indexes based on an object's namespace
func MetaNamespaceIndexFunc(obj interface{}) (string, error) {
	meta, err := meta.Accessor(obj)
	if err != nil {
		return "", fmt.Errorf("object has no meta: %v", err)
	}
	return meta.Namespace(), nil
}
Exemple #4
0
// ResourceFromFile retrieves the name and namespace from a valid file. If the file does not
// resolve to a known type an error is returned. The returned mapping can be used to determine
// the correct REST endpoint to modify this resource with.
func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper) (mapping *meta.RESTMapping, namespace, name string, data []byte) {
	configData, err := ReadConfigData(filename)
	checkErr(err)
	data = configData

	version, kind, err := typer.DataVersionAndKind(data)
	checkErr(err)

	// TODO: allow unversioned objects?
	if len(version) == 0 {
		checkErr(fmt.Errorf("The resource in the provided file has no apiVersion defined"))
	}

	mapping, err = mapper.RESTMapping(version, kind)
	checkErr(err)

	obj, err := mapping.Codec.Decode(data)
	checkErr(err)

	meta := mapping.MetadataAccessor
	namespace, err = meta.Namespace(obj)
	checkErr(err)
	name, err = meta.Name(obj)
	checkErr(err)

	return
}
Exemple #5
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.
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
	}
	_, kind, err := Scheme.ObjectVersionAndKind(obj)
	if err != nil {
		return nil, err
	}
	version := versionFromSelfLink.FindStringSubmatch(meta.SelfLink())
	if len(version) < 2 {
		return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", meta.SelfLink(), version)
	}
	return &ObjectReference{
		Kind:            kind,
		APIVersion:      version[1],
		Name:            meta.Name(),
		Namespace:       meta.Namespace(),
		UID:             meta.UID(),
		ResourceVersion: meta.ResourceVersion(),
	}, nil
}
Exemple #6
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 https://github.com/GoogleCloudPlatform/kubernetes/issues/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
	}

	// 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 := meta.Kind()
	if kind == "" {
		_, kind, err = Scheme.ObjectVersionAndKind(obj)
		if err != nil {
			return nil, err
		}
	}

	// if the object referenced is actually persisted, we can also get version from meta
	version := meta.APIVersion()
	if version == "" {
		selfLink := meta.SelfLink()
		if selfLink == "" {
			if ForTesting_ReferencesAllowBlankSelfLinks {
				version = "testing"
			} else {
				return nil, ErrNoSelfLink
			}
		} else {
			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.Name(),
		Namespace:       meta.Namespace(),
		UID:             meta.UID(),
		ResourceVersion: meta.ResourceVersion(),
	}, nil
}
Exemple #7
0
// ResourceFromFile retrieves the name and namespace from a valid file. If the file does not
// resolve to a known type an error is returned. The returned mapping can be used to determine
// the correct REST endpoint to modify this resource with.
// DEPRECATED: Use resource.Builder
func ResourceFromFile(filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper, schema validation.Schema, cmdVersion string) (mapping *meta.RESTMapping, namespace, name string, data []byte, err error) {
	data, err = ReadConfigData(filename)
	if err != nil {
		return
	}

	objVersion, kind, err := typer.DataVersionAndKind(data)
	if err != nil {
		return
	}

	// TODO: allow unversioned objects?
	if len(objVersion) == 0 {
		err = fmt.Errorf("the resource in the provided file has no apiVersion defined")
	}

	err = schema.ValidateBytes(data)
	if err != nil {
		return
	}

	// decode using the version stored with the object (allows codec to vary across versions)
	mapping, err = mapper.RESTMapping(kind, objVersion)
	if err != nil {
		return
	}

	obj, err := mapping.Codec.Decode(data)
	if err != nil {
		return
	}

	meta := mapping.MetadataAccessor
	namespace, err = meta.Namespace(obj)
	if err != nil {
		return
	}
	name, err = meta.Name(obj)
	if err != nil {
		return
	}

	// if the preferred API version differs, get a different mapper
	if cmdVersion != objVersion {
		mapping, err = mapper.RESTMapping(kind, cmdVersion)
	}
	return
}
Exemple #8
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.
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
	}
	_, kind, err := Scheme.ObjectVersionAndKind(obj)
	if err != nil {
		return nil, err
	}
	version := ""
	parsedSelfLink := versionFromSelfLink.FindStringSubmatch(meta.SelfLink())
	if len(parsedSelfLink) < 2 {
		if ForTesting_ReferencesAllowBlankSelfLinks {
			version = "testing"
		} else if meta.SelfLink() == "" {
			return nil, ErrNoSelfLink
		} else {
			return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", meta.SelfLink(), version)
		}
	} else {
		version = parsedSelfLink[1]
	}
	return &ObjectReference{
		Kind:            kind,
		APIVersion:      version,
		Name:            meta.Name(),
		Namespace:       meta.Namespace(),
		UID:             meta.UID(),
		ResourceVersion: meta.ResourceVersion(),
	}, nil
}
Exemple #9
0
// ResourceFromFile retrieves the name and namespace from a valid file. If the file does not
// resolve to a known type an error is returned. The returned mapping can be used to determine
// the correct REST endpoint to modify this resource with.
func ResourceFromFile(cmd *cobra.Command, filename string, typer runtime.ObjectTyper, mapper meta.RESTMapper, schema validation.Schema) (mapping *meta.RESTMapping, namespace, name string, data []byte) {
	configData, err := ReadConfigData(filename)
	checkErr(err)
	data = configData

	objVersion, kind, err := typer.DataVersionAndKind(data)
	checkErr(err)

	// TODO: allow unversioned objects?
	if len(objVersion) == 0 {
		checkErr(fmt.Errorf("the resource in the provided file has no apiVersion defined"))
	}

	err = schema.ValidateBytes(data)
	checkErr(err)

	// decode using the version stored with the object (allows codec to vary across versions)
	mapping, err = mapper.RESTMapping(kind, objVersion)
	checkErr(err)

	obj, err := mapping.Codec.Decode(data)
	checkErr(err)

	meta := mapping.MetadataAccessor
	namespace, err = meta.Namespace(obj)
	checkErr(err)
	name, err = meta.Name(obj)
	checkErr(err)

	// if the preferred API version differs, get a different mapper
	version := GetFlagString(cmd, "api-version")
	if version != objVersion {
		mapping, err = mapper.RESTMapping(kind, version)
		checkErr(err)
	}

	return
}