// checkNamespace makes sure that the scope of gvk matches ns. It // returns an error if namespace is empty but gvk is a namespaced // kind, or if ns is non-empty and gvk is a namespaced kind. func checkNamespace(gvk unversioned.GroupVersionKind, ns string) error { group, err := registered.Group(gvk.Group) if err != nil { return err } mapping, err := group.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version) if err != nil { return err } switch mapping.Scope.Name() { case meta.RESTScopeNameRoot: if ns != "" { return fmt.Errorf("namespace specified for a non-namespaced kind %s", gvk) } case meta.RESTScopeNameNamespace: if ns == "" { // Skipping this check for Events, since // controllers emit events that have no namespace, // even though Event is a namespaced resource. if gvk.Kind != "Event" { return fmt.Errorf("no namespace specified for a namespaced kind %s", gvk) } } } return nil }
// copyKindDefaults defaults dst to the value in src if dst does not have a value set. func copyKindDefaults(dst, src *unversioned.GroupVersionKind) { if src == nil { return } // apply kind and version defaulting from provided default if len(dst.Kind) == 0 { dst.Kind = src.Kind } if len(dst.Version) == 0 && len(src.Version) > 0 { dst.Group = src.Group dst.Version = src.Version } }
// KindToResource converts Kind to a resource name. // Broken. This method only "sort of" works when used outside of this package. It assumes that Kinds and Resources match // and they aren't guaranteed to do so. func KindToResource(kind unversioned.GroupVersionKind) ( /*plural*/ unversioned.GroupVersionResource /*singular*/, unversioned.GroupVersionResource) { kindName := kind.Kind if len(kindName) == 0 { return unversioned.GroupVersionResource{}, unversioned.GroupVersionResource{} } singularName := strings.ToLower(kindName) singular := kind.GroupVersion().WithResource(singularName) for _, skip := range unpluralizedSuffixes { if strings.HasSuffix(singularName, skip) { return singular, singular } } switch string(singularName[len(singularName)-1]) { case "s": return kind.GroupVersion().WithResource(singularName + "es"), singular case "y": return kind.GroupVersion().WithResource(strings.TrimSuffix(singularName, "y") + "ies"), singular } return kind.GroupVersion().WithResource(singularName + "s"), singular }
// SetGroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta func (obj *TypeMeta) SetGroupVersionKind(gvk unversioned.GroupVersionKind) { obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() }
// IsAnAPIObject allows clients to preemptively get a reference to an API object and pass it to places that // intend only to get a reference to that object. This simplifies the event recording interface. func (obj *ObjectReference) SetGroupVersionKind(gvk unversioned.GroupVersionKind) { obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() }
func (obj *Config) SetGroupVersionKind(gvk unversioned.GroupVersionKind) { obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() }
func (u *UnstructuredList) SetGroupVersionKind(gvk unversioned.GroupVersionKind) { u.SetAPIVersion(gvk.GroupVersion().String()) u.SetKind(gvk.Kind) }
// RESTMapping returns a struct representing the resource path and conversion interfaces a // RESTClient should use to operate on the provided group/kind in order of versions. If a version search // order is not provided, the search order provided to DefaultRESTMapper will be used to resolve which // version should be used to access the named group/kind. // TODO: consider refactoring to use RESTMappings in a way that preserves version ordering and preference func (m *DefaultRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (*RESTMapping, error) { // Pick an appropriate version var gvk *unversioned.GroupVersionKind hadVersion := false for _, version := range versions { if len(version) == 0 || version == runtime.APIVersionInternal { continue } currGVK := gk.WithVersion(version) hadVersion = true if _, ok := m.kindToPluralResource[currGVK]; ok { gvk = &currGVK break } } // Use the default preferred versions if !hadVersion && (gvk == nil) { for _, gv := range m.defaultGroupVersions { if gv.Group != gk.Group { continue } currGVK := gk.WithVersion(gv.Version) if _, ok := m.kindToPluralResource[currGVK]; ok { gvk = &currGVK break } } } if gvk == nil { return nil, &NoKindMatchError{PartialKind: gk.WithVersion("")} } // Ensure we have a REST mapping resource, ok := m.kindToPluralResource[*gvk] if !ok { found := []unversioned.GroupVersion{} for _, gv := range m.defaultGroupVersions { if _, ok := m.kindToPluralResource[*gvk]; ok { found = append(found, gv) } } if len(found) > 0 { return nil, fmt.Errorf("object with kind %q exists in versions %v, not %v", gvk.Kind, found, gvk.GroupVersion().String()) } return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported object", gvk.GroupVersion().String(), gvk.Kind) } // Ensure we have a REST scope scope, ok := m.kindToScope[*gvk] if !ok { return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported scope", gvk.GroupVersion().String(), gvk.Kind) } interfaces, err := m.interfacesFunc(gvk.GroupVersion()) if err != nil { return nil, fmt.Errorf("the provided version %q has no relevant versions", gvk.GroupVersion().String()) } retVal := &RESTMapping{ Resource: resource.Resource, GroupVersionKind: *gvk, Scope: scope, ObjectConvertor: interfaces.ObjectConvertor, MetadataAccessor: interfaces.MetadataAccessor, } return retVal, nil }