// dest must be a map of group to groupVersion. func mergeGroupVersionIntoMap(gvList string, dest map[string]schema.GroupVersion) error { for _, gvString := range strings.Split(gvList, ",") { if gvString == "" { continue } // We accept two formats. "group/version" OR // "group=group/version". The latter is used when types // move between groups. if !strings.Contains(gvString, "=") { gv, err := schema.ParseGroupVersion(gvString) if err != nil { return err } dest[gv.Group] = gv } else { parts := strings.SplitN(gvString, "=", 2) gv, err := schema.ParseGroupVersion(parts[1]) if err != nil { return err } dest[parts[0]] = gv } } return nil }
func (t *thirdPartyResourceDataDecoder) populateFromObject(mapObj map[string]interface{}, data []byte) (runtime.Object, *schema.GroupVersionKind, error) { typeMeta := metav1.TypeMeta{} if err := json.Unmarshal(data, &typeMeta); err != nil { return nil, nil, err } gv, err := schema.ParseGroupVersion(typeMeta.APIVersion) if err != nil { return nil, nil, err } gvk := gv.WithKind(typeMeta.Kind) isList := strings.HasSuffix(typeMeta.Kind, "List") switch { case !isList && (len(t.kind) == 0 || typeMeta.Kind == t.kind): result := &extensions.ThirdPartyResourceData{} if err := t.populateResource(result, mapObj, data); err != nil { return nil, nil, err } return result, &gvk, nil case isList && (len(t.kind) == 0 || typeMeta.Kind == t.kind+"List"): list := &extensions.ThirdPartyResourceDataList{} if err := t.populateListResource(list, mapObj); err != nil { return nil, nil, err } return list, &gvk, nil default: return nil, nil, fmt.Errorf("unexpected kind: %s, expected %s", typeMeta.Kind, t.kind) } }
func TestDirectCodec(t *testing.T) { s := GetDirectCodecTestScheme() cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})) info, _ := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON) serializer := info.Serializer df := DirectCodecFactory{cf} ignoredGV, err := schema.ParseGroupVersion("ignored group/ignored version") if err != nil { t.Fatal(err) } directEncoder := df.EncoderForVersion(serializer, ignoredGV) directDecoder := df.DecoderToVersion(serializer, ignoredGV) out, err := runtime.Encode(directEncoder, &ExternalTestType1{}) if err != nil { t.Fatal(err) } if string(out) != `{"myVersionKey":"v1","myKindKey":"ExternalTestType1"}`+"\n" { t.Fatal(string(out)) } a, _, err := directDecoder.Decode(out, nil, nil) e := &ExternalTestType1{ MyWeirdCustomEmbeddedVersionKindField: MyWeirdCustomEmbeddedVersionKindField{ APIVersion: "v1", ObjectKind: "ExternalTestType1", }, } if !semantic.DeepEqual(e, a) { t.Fatalf("expect %v, got %v", e, a) } }
func IsThirdPartyObject(rawData []byte, gvk *schema.GroupVersionKind) (isThirdParty bool, gvkOut *schema.GroupVersionKind, err error) { var gv schema.GroupVersion if gvk == nil { data, err := yaml.ToJSON(rawData) if err != nil { return false, nil, err } metadata := metav1.TypeMeta{} if err = json.Unmarshal(data, &metadata); err != nil { return false, nil, err } gv, err = schema.ParseGroupVersion(metadata.APIVersion) if err != nil { return false, nil, err } gvkOut = &schema.GroupVersionKind{ Group: gv.Group, Version: gv.Version, Kind: metadata.Kind, } } else { gv = gvk.GroupVersion() gvkOut = gvk } return registered.IsThirdPartyAPIGroupVersion(gv), gvkOut, nil }
func (u *UnstructuredList) GroupVersionKind() schema.GroupVersionKind { gv, err := schema.ParseGroupVersion(u.GetAPIVersion()) if err != nil { return schema.GroupVersionKind{} } gvk := gv.WithKind(u.GetKind()) return gvk }
func (obj objectAccessor) SetAPIVersion(version string) { gvk := obj.GetObjectKind().GroupVersionKind() gv, err := schema.ParseGroupVersion(version) if err != nil { gv = schema.GroupVersion{Version: version} } gvk.Group, gvk.Version = gv.Group, gv.Version obj.GetObjectKind().SetGroupVersionKind(gvk) }
// RunExplain executes the appropriate steps to print a model's documentation func RunExplain(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string) error { if len(args) == 0 { fmt.Fprint(cmdErr, "You must specify the type of resource to explain. ", valid_resources) return cmdutil.UsageError(cmd, "Required resource not specified.") } if len(args) > 1 { return cmdutil.UsageError(cmd, "We accept only this format: explain RESOURCE") } recursive := cmdutil.GetFlagBool(cmd, "recursive") apiVersionString := cmdutil.GetFlagString(cmd, "api-version") apiVersion := schema.GroupVersion{} mapper, _ := f.Object() // TODO: After we figured out the new syntax to separate group and resource, allow // the users to use it in explain (kubectl explain <group><syntax><resource>). // Refer to issue #16039 for why we do this. Refer to PR #15808 that used "/" syntax. inModel, fieldsPath, err := kubectl.SplitAndParseResourceRequest(args[0], mapper) if err != nil { return err } // TODO: We should deduce the group for a resource by discovering the supported resources at server. fullySpecifiedGVR, groupResource := schema.ParseResourceArg(inModel) gvk := schema.GroupVersionKind{} if fullySpecifiedGVR != nil { gvk, _ = mapper.KindFor(*fullySpecifiedGVR) } if gvk.Empty() { gvk, err = mapper.KindFor(groupResource.WithVersion("")) if err != nil { return err } } if len(apiVersionString) == 0 { groupMeta, err := registered.Group(gvk.Group) if err != nil { return err } apiVersion = groupMeta.GroupVersion } else { apiVersion, err = schema.ParseGroupVersion(apiVersionString) if err != nil { return nil } } schema, err := f.SwaggerSchema(apiVersion.WithKind(gvk.Kind)) if err != nil { return err } return kubectl.PrintModelDescription(inModel, fieldsPath, out, schema, recursive) }
func (gv *GroupVersion) unmarshal(value []byte) error { var s string if err := json.Unmarshal(value, &s); err != nil { return err } parsed, err := schema.ParseGroupVersion(s) if err != nil { return err } gv.Group, gv.Version = parsed.Group, parsed.Version return nil }
// OutputVersion returns the preferred output version for generic content (JSON, YAML, or templates) // defaultVersion is never mutated. Nil simply allows clean passing in common usage from client.Config func OutputVersion(cmd *cobra.Command, defaultVersion *schema.GroupVersion) (schema.GroupVersion, error) { outputVersionString := GetFlagString(cmd, "output-version") if len(outputVersionString) == 0 { if defaultVersion == nil { return schema.GroupVersion{}, nil } return *defaultVersion, nil } return schema.ParseGroupVersion(outputVersionString) }
func (m PriorityRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (mapping *RESTMapping, err error) { mappings, err := m.Delegate.RESTMappings(gk) if err != nil { return nil, err } // any versions the user provides take priority priorities := m.KindPriority if len(versions) > 0 { priorities = make([]schema.GroupVersionKind, 0, len(m.KindPriority)+len(versions)) for _, version := range versions { gv, err := schema.ParseGroupVersion(version) if err != nil { return nil, err } priorities = append(priorities, gv.WithKind(AnyKind)) } priorities = append(priorities, m.KindPriority...) } remaining := append([]*RESTMapping{}, mappings...) for _, pattern := range priorities { var matching []*RESTMapping for _, m := range remaining { if kindMatches(pattern, m.GroupVersionKind) { matching = append(matching, m) } } switch len(matching) { case 0: // if you have no matches, then nothing matched this pattern just move to the next continue case 1: // one match, return return matching[0], nil default: // more than one match, use the matched hits as the list moving to the next pattern. // this way you can have a series of selection criteria remaining = matching } } if len(remaining) == 1 { return remaining[0], nil } var kinds []schema.GroupVersionKind for _, m := range mappings { kinds = append(kinds, m.GroupVersionKind) } return nil, &AmbiguousKindError{PartialKind: gk.WithVersion(""), MatchingKinds: kinds} }
// GroupVersionResources converts APIResourceLists to the GroupVersionResources. func GroupVersionResources(rls []*metav1.APIResourceList) (map[schema.GroupVersionResource]struct{}, error) { gvrs := map[schema.GroupVersionResource]struct{}{} for _, rl := range rls { gv, err := schema.ParseGroupVersion(rl.GroupVersion) if err != nil { return nil, err } for i := range rl.APIResources { gvrs[schema.GroupVersionResource{Group: gv.Group, Version: gv.Version, Resource: rl.APIResources[i].Name}] = struct{}{} } } return gvrs, nil }
// NewObjectTyper constructs an ObjectTyper from discovery information. func NewObjectTyper(resources []*unversioned.APIResourceList) (runtime.ObjectTyper, error) { ot := &ObjectTyper{registered: make(map[schema.GroupVersionKind]bool)} for _, resourceList := range resources { gv, err := schema.ParseGroupVersion(resourceList.GroupVersion) if err != nil { return nil, err } for _, resource := range resourceList.APIResources { ot.registered[gv.WithKind(resource.Kind)] = true } } return ot, nil }
// Interpret will return the APIVersion and Kind of the JSON wire-format // encoding of an object, or an error. func (SimpleMetaFactory) Interpret(data []byte) (*schema.GroupVersionKind, error) { findKind := struct { // +optional APIVersion string `json:"apiVersion,omitempty"` // +optional Kind string `json:"kind,omitempty"` }{} if err := json.Unmarshal(data, &findKind); err != nil { return nil, fmt.Errorf("couldn't get version/kind; json parse error: %v", err) } gv, err := schema.ParseGroupVersion(findKind.APIVersion) if err != nil { return nil, err } return &schema.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: findKind.Kind}, nil }
func (testMetaFactory) Interpret(data []byte) (*schema.GroupVersionKind, error) { findKind := struct { APIVersion string `json:"myVersionKey,omitempty"` ObjectKind string `json:"myKindKey,omitempty"` }{} // yaml is a superset of json, so we use it to decode here. That way, // we understand both. if err := yaml.Unmarshal(data, &findKind); err != nil { return nil, fmt.Errorf("couldn't get version/kind: %v", err) } gv, err := schema.ParseGroupVersion(findKind.APIVersion) if err != nil { return nil, err } return &schema.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: findKind.ObjectKind}, nil }
// NewDiscoveryRESTMapper returns a RESTMapper based on discovery information. func NewDiscoveryRESTMapper(resources []*unversioned.APIResourceList, versionFunc meta.VersionInterfacesFunc) (*meta.DefaultRESTMapper, error) { rm := meta.NewDefaultRESTMapper(nil, versionFunc) for _, resourceList := range resources { gv, err := schema.ParseGroupVersion(resourceList.GroupVersion) if err != nil { return nil, err } for _, resource := range resourceList.APIResources { gvk := gv.WithKind(resource.Kind) scope := meta.RESTScopeRoot if resource.Namespaced { scope = meta.RESTScopeNamespace } rm.Add(gvk, scope) } } return rm, nil }
func setConfigDefaults(config *restclient.Config) error { gv, err := schema.ParseGroupVersion("policy/v1beta1") if err != nil { return err } // if policy/v1beta1 is not enabled, return an error if !registered.IsEnabledVersion(gv) { return fmt.Errorf("policy/v1beta1 is not enabled") } config.APIPath = "/apis" if config.UserAgent == "" { config.UserAgent = restclient.DefaultKubernetesUserAgent() } copyGroupVersion := gv config.GroupVersion = ©GroupVersion config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs} return nil }
// NewAPIRegistrationManager constructs a new manager. The argument ought to be // the value of the KUBE_API_VERSIONS env var, or a value of this which you // wish to test. func NewAPIRegistrationManager(kubeAPIVersions string) (*APIRegistrationManager, error) { m := &APIRegistrationManager{ registeredVersions: map[schema.GroupVersion]struct{}{}, thirdPartyGroupVersions: []schema.GroupVersion{}, enabledVersions: map[schema.GroupVersion]struct{}{}, groupMetaMap: map[string]*apimachinery.GroupMeta{}, envRequestedVersions: []schema.GroupVersion{}, } if len(kubeAPIVersions) != 0 { for _, version := range strings.Split(kubeAPIVersions, ",") { gv, err := schema.ParseGroupVersion(version) if err != nil { return nil, fmt.Errorf("invalid api version: %s in KUBE_API_VERSIONS: %s.", version, kubeAPIVersions) } m.envRequestedVersions = append(m.envRequestedVersions, gv) } } return m, nil }
// TODO: In general, any controller checking this needs to be dynamic so // users don't have to restart their controller manager if they change the apiserver. func getAvailableResources(clientBuilder controller.ControllerClientBuilder) (map[schema.GroupVersionResource]bool, error) { var discoveryClient discovery.DiscoveryInterface // If apiserver is not running we should wait for some time and fail only then. This is particularly // important when we start apiserver and controller manager at the same time. err := wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) { client, err := clientBuilder.Client("controller-discovery") if err != nil { glog.Errorf("Failed to get api versions from server: %v", err) return false, nil } discoveryClient = client.Discovery() return true, nil }) if err != nil { return nil, fmt.Errorf("failed to get api versions from server: %v", err) } resourceMap, err := discoveryClient.ServerResources() if err != nil { return nil, fmt.Errorf("failed to get supported resources from server: %v", err) } allResources := map[schema.GroupVersionResource]bool{} for _, apiResourceList := range resourceMap { version, err := schema.ParseGroupVersion(apiResourceList.GroupVersion) if err != nil { return nil, err } for _, apiResource := range apiResourceList.APIResources { allResources[version.WithResource(apiResource.Name)] = true } } return allResources, nil }
func (e ShortcutExpander) getAll() []schema.GroupResource { if e.discoveryClient == nil { return e.All } // Check if we have access to server resources apiResources, err := e.discoveryClient.ServerResources() if err != nil { return e.All } availableResources := []schema.GroupVersionResource{} for groupVersionString, resourceList := range apiResources { currVersion, err := schema.ParseGroupVersion(groupVersionString) if err != nil { return e.All } for _, resource := range resourceList.APIResources { availableResources = append(availableResources, currVersion.WithResource(resource.Name)) } } availableAll := []schema.GroupResource{} for _, requestedResource := range e.All { for _, availableResource := range availableResources { if requestedResource.Group == availableResource.Group && requestedResource.Resource == availableResource.Resource { availableAll = append(availableAll, requestedResource) break } } } return availableAll }
func init() { if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 { var ok bool mediaType, _, err := mime.ParseMediaType(apiMediaType) if err != nil { panic(err) } serializer, ok = runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType) if !ok { panic(fmt.Sprintf("no serializer for %s", apiMediaType)) } } if storageMediaType := StorageMediaType(); len(storageMediaType) > 0 { var ok bool mediaType, _, err := mime.ParseMediaType(storageMediaType) if err != nil { panic(err) } storageSerializer, ok = runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType) if !ok { panic(fmt.Sprintf("no serializer for %s", storageMediaType)) } } kubeTestAPI := os.Getenv("KUBE_TEST_API") if len(kubeTestAPI) != 0 { // priority is "first in list preferred", so this has to run in reverse order testGroupVersions := strings.Split(kubeTestAPI, ",") for i := len(testGroupVersions) - 1; i >= 0; i-- { gvString := testGroupVersions[i] groupVersion, err := schema.ParseGroupVersion(gvString) if err != nil { panic(fmt.Sprintf("Error parsing groupversion %v: %v", gvString, err)) } internalGroupVersion := schema.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal} Groups[groupVersion.Group] = TestGroup{ externalGroupVersion: groupVersion, internalGroupVersion: internalGroupVersion, internalTypes: api.Scheme.KnownTypes(internalGroupVersion), externalTypes: api.Scheme.KnownTypes(groupVersion), } } } if _, ok := Groups[api.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: api.GroupName, Version: registered.GroupOrDie(api.GroupName).GroupVersion.Version} Groups[api.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: api.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(api.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[extensions.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: extensions.GroupName, Version: registered.GroupOrDie(extensions.GroupName).GroupVersion.Version} Groups[extensions.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: extensions.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[autoscaling.GroupName]; !ok { internalTypes := make(map[string]reflect.Type) for k, t := range api.Scheme.KnownTypes(extensions.SchemeGroupVersion) { if k == "Scale" { continue } internalTypes[k] = t } externalGroupVersion := schema.GroupVersion{Group: autoscaling.GroupName, Version: registered.GroupOrDie(autoscaling.GroupName).GroupVersion.Version} Groups[autoscaling.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: extensions.SchemeGroupVersion, internalTypes: internalTypes, externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[autoscaling.GroupName+"IntraGroup"]; !ok { internalTypes := make(map[string]reflect.Type) for k, t := range api.Scheme.KnownTypes(extensions.SchemeGroupVersion) { if k == "Scale" { internalTypes[k] = t break } } externalGroupVersion := schema.GroupVersion{Group: autoscaling.GroupName, Version: registered.GroupOrDie(autoscaling.GroupName).GroupVersion.Version} Groups[autoscaling.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: autoscaling.SchemeGroupVersion, internalTypes: internalTypes, externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[batch.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: batch.GroupName, Version: registered.GroupOrDie(batch.GroupName).GroupVersion.Version} Groups[batch.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: batch.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(batch.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[apps.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: apps.GroupName, Version: registered.GroupOrDie(apps.GroupName).GroupVersion.Version} Groups[apps.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: extensions.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[policy.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: policy.GroupName, Version: registered.GroupOrDie(policy.GroupName).GroupVersion.Version} Groups[policy.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: policy.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(policy.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[federation.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: federation.GroupName, Version: registered.GroupOrDie(federation.GroupName).GroupVersion.Version} Groups[federation.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: federation.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(federation.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[rbac.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: rbac.GroupName, Version: registered.GroupOrDie(rbac.GroupName).GroupVersion.Version} Groups[rbac.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: rbac.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(rbac.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[storage.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: storage.GroupName, Version: registered.GroupOrDie(storage.GroupName).GroupVersion.Version} Groups[storage.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: storage.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(storage.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[certificates.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: certificates.GroupName, Version: registered.GroupOrDie(certificates.GroupName).GroupVersion.Version} Groups[certificates.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: certificates.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(certificates.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[imagepolicy.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: imagepolicy.GroupName, Version: registered.GroupOrDie(imagepolicy.GroupName).GroupVersion.Version} Groups[imagepolicy.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: imagepolicy.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(imagepolicy.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[authorization.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: authorization.GroupName, Version: registered.GroupOrDie(authorization.GroupName).GroupVersion.Version} Groups[authorization.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: authorization.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(authorization.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[kubeadm.GroupName]; !ok { externalGroupVersion := schema.GroupVersion{Group: kubeadm.GroupName, Version: registered.GroupOrDie(kubeadm.GroupName).GroupVersion.Version} Groups[kubeadm.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: kubeadm.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(kubeadm.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } Default = Groups[api.GroupName] Autoscaling = Groups[autoscaling.GroupName] Batch = Groups[batch.GroupName] Apps = Groups[apps.GroupName] Policy = Groups[policy.GroupName] Certificates = Groups[certificates.GroupName] Extensions = Groups[extensions.GroupName] Federation = Groups[federation.GroupName] Rbac = Groups[rbac.GroupName] Storage = Groups[storage.GroupName] ImagePolicy = Groups[imagepolicy.GroupName] Authorization = Groups[authorization.GroupName] }
// NewNamespaceController creates a new NamespaceController func NewNamespaceController( kubeClient clientset.Interface, clientPool dynamic.ClientPool, discoverResourcesFn func() ([]*metav1.APIResourceList, error), resyncPeriod time.Duration, finalizerToken v1.FinalizerName) *NamespaceController { opCache := &operationNotSupportedCache{ m: make(map[operationKey]bool), } // pre-fill opCache with the discovery info // // TODO(sttts): get rid of opCache and http 405 logic around it and trust discovery info resources, err := discoverResourcesFn() if err != nil { glog.Fatalf("Failed to get supported resources: %v", err) } deletableGroupVersionResources := []schema.GroupVersionResource{} for _, rl := range resources { gv, err := schema.ParseGroupVersion(rl.GroupVersion) if err != nil { glog.Errorf("Failed to parse GroupVersion %q, skipping: %v", rl.GroupVersion, err) continue } for _, r := range rl.APIResources { gvr := schema.GroupVersionResource{Group: gv.Group, Version: gv.Version, Resource: r.Name} verbs := sets.NewString([]string(r.Verbs)...) if !verbs.Has("delete") { glog.V(6).Infof("Skipping resource %v because it cannot be deleted.", gvr) } for _, op := range []operation{operationList, operationDeleteCollection} { if !verbs.Has(string(op)) { opCache.setNotSupported(operationKey{op: op, gvr: gvr}) } } deletableGroupVersionResources = append(deletableGroupVersionResources, gvr) } } // create the controller so we can inject the enqueue function namespaceController := &NamespaceController{ kubeClient: kubeClient, clientPool: clientPool, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespace"), discoverResourcesFn: discoverResourcesFn, opCache: opCache, finalizerToken: finalizerToken, } if kubeClient != nil && kubeClient.Core().RESTClient().GetRateLimiter() != nil { metrics.RegisterMetricAndTrackRateLimiterUsage("namespace_controller", kubeClient.Core().RESTClient().GetRateLimiter()) } // configure the backing store/controller store, controller := cache.NewInformer( &cache.ListWatch{ ListFunc: func(options v1.ListOptions) (runtime.Object, error) { return kubeClient.Core().Namespaces().List(options) }, WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { return kubeClient.Core().Namespaces().Watch(options) }, }, &v1.Namespace{}, resyncPeriod, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { namespace := obj.(*v1.Namespace) namespaceController.enqueueNamespace(namespace) }, UpdateFunc: func(oldObj, newObj interface{}) { namespace := newObj.(*v1.Namespace) namespaceController.enqueueNamespace(namespace) }, }, ) namespaceController.store = store namespaceController.controller = controller return namespaceController }
func (t *thirdPartyResourceDataDecoder) Decode(data []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { if into == nil { if gvk == nil || gvk.Kind != t.kind { if isThirdParty, _, err := IsThirdPartyObject(data, gvk); err != nil { return nil, nil, err } else if !isThirdParty { return t.delegate.Decode(data, gvk, into) } } return t.populate(data) } switch o := into.(type) { case *extensions.ThirdPartyResourceData: break case *runtime.VersionedObjects: // We're not sure that it's third party, we need to test if gvk == nil || gvk.Kind != t.kind { if isThirdParty, _, err := IsThirdPartyObject(data, gvk); err != nil { return nil, nil, err } else if !isThirdParty { return t.delegate.Decode(data, gvk, into) } } obj, outGVK, err := t.populate(data) if err != nil { return nil, nil, err } o.Objects = []runtime.Object{ obj, } return o, outGVK, nil default: if gvk != nil && registered.IsThirdPartyAPIGroupVersion(gvk.GroupVersion()) { // delegate won't recognize a thirdparty group version gvk = nil } return t.delegate.Decode(data, gvk, into) } thirdParty := into.(*extensions.ThirdPartyResourceData) var dataObj interface{} if err := json.Unmarshal(data, &dataObj); err != nil { return nil, nil, err } mapObj, ok := dataObj.(map[string]interface{}) if !ok { return nil, nil, fmt.Errorf("unexpected object: %#v", dataObj) } /*if gvk.Kind != "ThirdPartyResourceData" { return nil, nil, fmt.Errorf("unexpected kind: %s", gvk.Kind) }*/ actual := &schema.GroupVersionKind{} if kindObj, found := mapObj["kind"]; !found { if gvk == nil { return nil, nil, runtime.NewMissingKindErr(string(data)) } mapObj["kind"] = gvk.Kind actual.Kind = gvk.Kind } else { kindStr, ok := kindObj.(string) if !ok { return nil, nil, fmt.Errorf("unexpected object for 'kind': %v", kindObj) } if len(t.kind) > 0 && kindStr != t.kind { return nil, nil, fmt.Errorf("kind doesn't match, expecting: %s, got %s", t.kind, kindStr) } actual.Kind = kindStr } if versionObj, found := mapObj["apiVersion"]; !found { if gvk == nil { return nil, nil, runtime.NewMissingVersionErr(string(data)) } mapObj["apiVersion"] = gvk.GroupVersion().String() actual.Group, actual.Version = gvk.Group, gvk.Version } else { versionStr, ok := versionObj.(string) if !ok { return nil, nil, fmt.Errorf("unexpected object for 'apiVersion': %v", versionObj) } if gvk != nil && versionStr != gvk.GroupVersion().String() { return nil, nil, fmt.Errorf("version doesn't match, expecting: %v, got %s", gvk.GroupVersion(), versionStr) } gv, err := schema.ParseGroupVersion(versionStr) if err != nil { return nil, nil, err } actual.Group, actual.Version = gv.Group, gv.Version } mapObj, err := parseObject(data) if err != nil { return nil, actual, err } if err := t.populateResource(thirdParty, mapObj, data); err != nil { return nil, actual, err } return thirdParty, actual, nil }
// Merges the given defaultAPIResourceConfig with the given resourceConfigOverrides. func mergeAPIResourceConfigs(defaultAPIResourceConfig *ResourceConfig, resourceConfigOverrides config.ConfigurationMap) (*ResourceConfig, error) { resourceConfig := defaultAPIResourceConfig overrides := resourceConfigOverrides // "api/all=false" allows users to selectively enable specific api versions. allAPIFlagValue, ok := overrides["api/all"] if ok { if allAPIFlagValue == "false" { // Disable all group versions. resourceConfig.DisableVersions(registered.RegisteredGroupVersions()...) } else if allAPIFlagValue == "true" { resourceConfig.EnableVersions(registered.RegisteredGroupVersions()...) } } // "api/legacy=false" allows users to disable legacy api versions. disableLegacyAPIs := false legacyAPIFlagValue, ok := overrides["api/legacy"] if ok && legacyAPIFlagValue == "false" { disableLegacyAPIs = true } _ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable. // "<resourceSpecifier>={true|false} allows users to enable/disable API. // This takes preference over api/all and api/legacy, if specified. // Iterate through all group/version overrides specified in runtimeConfig. for key := range overrides { if key == "api/all" || key == "api/legacy" { // Have already handled them above. Can skip them here. continue } tokens := strings.Split(key, "/") if len(tokens) != 2 { continue } groupVersionString := tokens[0] + "/" + tokens[1] // HACK: Hack for "v1" legacy group version. // Remove when we stop supporting the legacy group version. if groupVersionString == "api/v1" { groupVersionString = "v1" } groupVersion, err := schema.ParseGroupVersion(groupVersionString) if err != nil { return nil, fmt.Errorf("invalid key %s", key) } // Verify that the groupVersion is registered. if !registered.IsRegisteredVersion(groupVersion) { return nil, fmt.Errorf("group version %s that has not been registered", groupVersion.String()) } enabled, err := getRuntimeConfigValue(overrides, key, false) if err != nil { return nil, err } if enabled { resourceConfig.EnableVersions(groupVersion) } else { resourceConfig.DisableVersions(groupVersion) } } // Iterate through all group/version/resource overrides specified in runtimeConfig. for key := range overrides { tokens := strings.Split(key, "/") if len(tokens) != 3 { continue } groupVersionString := tokens[0] + "/" + tokens[1] // HACK: Hack for "v1" legacy group version. // Remove when we stop supporting the legacy group version. if groupVersionString == "api/v1" { groupVersionString = "v1" } groupVersion, err := schema.ParseGroupVersion(groupVersionString) if err != nil { return nil, fmt.Errorf("invalid key %s", key) } resource := tokens[2] // Verify that the groupVersion is registered. if !registered.IsRegisteredVersion(groupVersion) { return nil, fmt.Errorf("group version %s that has not been registered", groupVersion.String()) } if !resourceConfig.AnyResourcesForVersionEnabled(groupVersion) { return nil, fmt.Errorf("%v is disabled, you cannot configure its resources individually", groupVersion) } enabled, err := getRuntimeConfigValue(overrides, key, false) if err != nil { return nil, err } if enabled { resourceConfig.EnableResources(groupVersion.WithResource(resource)) } else { resourceConfig.DisableResources(groupVersion.WithResource(resource)) } } return resourceConfig, nil }