// 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
}
Exemple #2
0
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)
	}
}
Exemple #3
0
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)
	}
}
Exemple #4
0
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
}
Exemple #5
0
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
}
Exemple #6
0
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)
}
Exemple #7
0
// 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)
}
Exemple #8
0
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
}
Exemple #9
0
// 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)
}
Exemple #10
0
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}
}
Exemple #11
0
// 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
}
Exemple #12
0
// 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
}
Exemple #13
0
// 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
}
Exemple #14
0
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
}
Exemple #15
0
// 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
}
Exemple #16
0
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 = &copyGroupVersion

	config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}

	return nil
}
Exemple #17
0
// 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
}
Exemple #20
0
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
}
Exemple #22
0
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
}