func init() { kubeTestAPI := os.Getenv("KUBE_TEST_API") if kubeTestAPI != "" { testGroupVersions := strings.Split(kubeTestAPI, ",") for _, groupVersion := range testGroupVersions { // TODO: caesarxuchao: the apiutil package is hacky, it will be replaced // by a following PR. Groups[apiutil.GetGroup(groupVersion)] = TestGroup{apiutil.GetGroup(groupVersion), apiutil.GetVersion(groupVersion), groupVersion} } } // TODO: caesarxuchao: we need a central place to store all available API // groups and their metadata. if _, ok := Groups[""]; !ok { // TODO: The second latest.GroupOrDie("").Version will be latest.GroupVersion after we // have multiple group support Groups[""] = TestGroup{"", latest.GroupOrDie("").Version, latest.GroupOrDie("").GroupVersion} } if _, ok := Groups["extensions"]; !ok { Groups["extensions"] = TestGroup{"extensions", latest.GroupOrDie("extensions").Version, latest.GroupOrDie("extensions").GroupVersion} } Default = Groups[""] Extensions = Groups["extensions"] }
func init() { groupMeta, err := latest.RegisterGroup("experimental") if err != nil { glog.V(4).Infof("%v", err) return } registeredGroupVersions := registered.GroupVersionsForGroup("experimental") groupVersion := registeredGroupVersions[0] *groupMeta = latest.GroupMeta{ GroupVersion: groupVersion, Group: apiutil.GetGroup(groupVersion), Version: apiutil.GetVersion(groupVersion), Codec: runtime.CodecFor(api.Scheme, groupVersion), } var versions []string var groupVersions []string for i := len(registeredGroupVersions) - 1; i >= 0; i-- { versions = append(versions, apiutil.GetVersion(registeredGroupVersions[i])) groupVersions = append(groupVersions, registeredGroupVersions[i]) } groupMeta.Versions = versions groupMeta.GroupVersions = groupVersions groupMeta.SelfLinker = runtime.SelfLinker(accessor) // the list of kinds that are scoped at the root of the api hierarchy // if a kind is not enumerated here, it is assumed to have a namespace scope rootScoped := sets.NewString() ignoredKinds := sets.NewString() groupMeta.RESTMapper = api.NewDefaultRESTMapper("experimental", groupVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped) api.RegisterRESTMapper(groupMeta.RESTMapper) groupMeta.InterfacesFor = interfacesFor }
func init() { groupMeta, err := latest.RegisterGroup("") if err != nil { glog.V(4).Infof("%v", err) return } // Use the first API version in the list of registered versions as the latest. registeredGroupVersions := registered.GroupVersionsForGroup("") groupVersion := registeredGroupVersions[0] *groupMeta = latest.GroupMeta{ GroupVersion: groupVersion, Group: apiutil.GetGroup(groupVersion), Version: apiutil.GetVersion(groupVersion), Codec: runtime.CodecFor(api.Scheme, groupVersion), } var versions []string var groupVersions []string for i := len(registeredGroupVersions) - 1; i >= 0; i-- { versions = append(versions, apiutil.GetVersion(registeredGroupVersions[i])) groupVersions = append(groupVersions, registeredGroupVersions[i]) } groupMeta.Versions = versions groupMeta.GroupVersions = groupVersions groupMeta.SelfLinker = runtime.SelfLinker(accessor) // the list of kinds that are scoped at the root of the api hierarchy // if a kind is not enumerated here, it is assumed to have a namespace scope // the list of kinds that are scoped at the root of the api hierarchy // if a kind is not enumerated here, it is assumed to have a namespace scope rootScoped := sets.NewString( "Node", "Minion", "Namespace", "PersistentVolume", "ComponentStatus", ) // these kinds should be excluded from the list of resources ignoredKinds := sets.NewString( "ListOptions", "DeleteOptions", "Status", "PodLogOptions", "PodExecOptions", "PodAttachOptions", "PodProxyOptions", "ThirdPartyResource", "ThirdPartyResourceData", "ThirdPartyResourceList") mapper := api.NewDefaultRESTMapper("", versions, interfacesFor, importPrefix, ignoredKinds, rootScoped) // setup aliases for groups of resources mapper.AddResourceAlias("all", userResources...) groupMeta.RESTMapper = mapper api.RegisterRESTMapper(groupMeta.RESTMapper) groupMeta.InterfacesFor = interfacesFor }
// GroupVersionsForGroup returns the registered versions of a group in the form // of "group/version". func GroupVersionsForGroup(group string) []string { ret := []string{} for _, v := range RegisteredVersions { if apiutil.GetGroup(v) == group { ret = append(ret, v) } } return ret }
// convert to a map between group and groupVersions. func generateStorageVersionMap(legacyVersion string, storageVersions string) map[string]string { storageVersionMap := map[string]string{} if legacyVersion != "" { storageVersionMap[""] = legacyVersion } if storageVersions != "" { groupVersions := strings.Split(storageVersions, ",") for _, gv := range groupVersions { storageVersionMap[apiutil.GetGroup(gv)] = gv } } return storageVersionMap }
// Check whether the kind in groupVersion is scoped at the root of the api hierarchy func isNamespacedKind(kind, groupVersion string) (bool, error) { group := apiutil.GetGroup(groupVersion) g, err := latest.Group(group) if err != nil { return false, err } restMapping, err := g.RESTMapper.RESTMapping(unversioned.GroupKind{Group: group, Kind: kind}, apiutil.GetVersion(groupVersion)) if err != nil { return false, err } scopeName := restMapping.Scope.Name() if scopeName == meta.RESTScopeNameNamespace { return true, nil } return false, nil }
// StorageGroupsToEncodingVersion returns a map from group name to group version, // computed from the s.DeprecatedStorageVersion and s.StorageVersions flags. // TODO: can we move the whole storage version concept to the generic apiserver? func (s *APIServer) StorageGroupsToEncodingVersion() (map[string]unversioned.GroupVersion, error) { storageVersionMap := map[string]unversioned.GroupVersion{} if s.DeprecatedStorageVersion != "" { storageVersionMap[""] = unversioned.GroupVersion{Group: apiutil.GetGroup(s.DeprecatedStorageVersion), Version: apiutil.GetVersion(s.DeprecatedStorageVersion)} } // First, get the defaults. if err := mergeGroupVersionIntoMap(s.DefaultStorageVersions, storageVersionMap); err != nil { return nil, err } // Override any defaults with the user settings. if err := mergeGroupVersionIntoMap(s.StorageVersions, storageVersionMap); err != nil { return nil, err } return storageVersionMap, nil }
// dest must be a map of group to groupVersion. func gvToMap(gvList string, dest map[string]string) { for _, gv := range strings.Split(gvList, ",") { if gv == "" { continue } // We accept two formats. "group/version" OR // "group=group/version". The latter is used when types // move between groups. if !strings.Contains(gv, "=") { dest[apiutil.GetGroup(gv)] = gv } else { parts := strings.SplitN(gv, "=", 2) // TODO: error checking. dest[parts[0]] = parts[1] } } }
// ValidateEvent makes sure that the event makes sense. func ValidateEvent(event *api.Event) field.ErrorList { allErrs := field.ErrorList{} // There is no namespace required for root-scoped kind, for example, node. // However, older client code accidentally sets event.Namespace // to api.NamespaceDefault, so we accept that too, but "" is preferred. // Todo: Events may reference 3rd party object, and we can't check whether the object is namespaced. // Suppose them are namespaced. Do check if we can get the piece of information. // This should apply to all groups served by this apiserver. group := apiutil.GetGroup(event.InvolvedObject.APIVersion) version := apiutil.GetVersion(event.InvolvedObject.APIVersion) if (group == "" || group == "extensions") && (version != "extensions" && version != "") { namespacedKindFlag, err := isNamespacedKind(event.InvolvedObject.Kind, event.InvolvedObject.APIVersion) if err != nil { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "kind"), event.InvolvedObject.Kind, fmt.Sprintf("couldn't check whether namespace is allowed: %s", err))) } else { if !namespacedKindFlag && event.Namespace != api.NamespaceDefault && event.Namespace != "" { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, fmt.Sprintf("not allowed for %s", event.InvolvedObject.Kind))) } if namespacedKindFlag && event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match involvedObject")) } } } else { if event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match involvedObject")) } } if !validation.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, "")) } return allErrs }