// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }