// ClientForGroupVersion returns a client for the specified groupVersion, creates one if none exists. Kind // in the GroupVersionKind may be empty. func (c *clientPoolImpl) ClientForGroupVersionKind(kind unversioned.GroupVersionKind) (*Client, error) { c.lock.Lock() defer c.lock.Unlock() gv := kind.GroupVersion() // do we have a client already configured? if existingClient, found := c.clients[gv]; found { return existingClient, nil } // avoid changing the original config confCopy := *c.config conf := &confCopy // we need to set the api path based on group version, if no group, default to legacy path conf.APIPath = c.apiPathResolverFunc(kind) // we need to make a client conf.GroupVersion = &gv dynamicClient, err := NewClient(conf) if err != nil { return nil, err } c.clients[gv] = dynamicClient return dynamicClient, nil }
// ClientForGroupVersion returns a client for the specified groupVersion, creates one if none exists. Kind // in the GroupVersionKind may be empty. func (c *clientPoolImpl) ClientForGroupVersionKind(kind unversioned.GroupVersionKind) (*Client, error) { c.lock.Lock() defer c.lock.Unlock() gv := kind.GroupVersion() // do we have a client already configured? if existingClient, found := c.clients[gv]; found { return existingClient, nil } // avoid changing the original config confCopy := *c.config conf := &confCopy // we need to set the api path based on group version, if no group, default to legacy path conf.APIPath = c.apiPathResolverFunc(kind) // we need to make a client conf.GroupVersion = &gv if conf.NegotiatedSerializer == nil { streamingInfo, _ := api.Codecs.StreamingSerializerForMediaType("application/json;stream=watch", nil) conf.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: dynamicCodec{}}, streamingInfo) } dynamicClient, err := NewClient(conf) if err != nil { return nil, err } c.clients[gv] = dynamicClient return dynamicClient, nil }
// KindToResource converts Kind to a resource name. func KindToResource(kind unversioned.GroupVersionKind, mixedCase bool) (plural, singular unversioned.GroupVersionResource) { kindName := kind.Kind if len(kindName) == 0 { return } if mixedCase { // Legacy support for mixed case names singular = kind.GroupVersion().WithResource(strings.ToLower(kindName[:1]) + kindName[1:]) } else { singular = kind.GroupVersion().WithResource(strings.ToLower(kindName)) } singularName := singular.Resource if strings.HasSuffix(singularName, "endpoints") || strings.HasSuffix(singularName, "securitycontextconstraints") { plural = singular } else { switch string(singularName[len(singularName)-1]) { case "s": plural = kind.GroupVersion().WithResource(singularName + "es") case "y": plural = kind.GroupVersion().WithResource(strings.TrimSuffix(singularName, "y") + "ies") default: plural = kind.GroupVersion().WithResource(singularName + "s") } } return }
func getRequestOptions(req *restful.Request, scope RequestScope, internalKind, externalKind unversioned.GroupVersionKind, subpath bool, subpathKey string) (runtime.Object, error) { if internalKind.IsEmpty() { return nil, nil } query := req.Request.URL.Query() if subpath { newQuery := make(url.Values) for k, v := range query { newQuery[k] = v } newQuery[subpathKey] = []string{req.PathParameter("path")} query = newQuery } versioned, err := scope.Creater.New(externalKind) if err != nil { return nil, err } if err := scope.Codec.DecodeParametersInto(query, versioned); err != nil { return nil, errors.NewBadRequest(err.Error()) } out, err := scope.Convertor.ConvertToVersion(versioned, internalKind.GroupVersion().String()) if err != nil { // programmer error return nil, err } return out, nil }
func IsThirdPartyObject(rawData []byte, gvk *unversioned.GroupVersionKind) (isThirdParty bool, gvkOut *unversioned.GroupVersionKind, err error) { var gv unversioned.GroupVersion if gvk == nil { data, err := yaml.ToJSON(rawData) if err != nil { return false, nil, err } metadata := unversioned.TypeMeta{} if err = json.Unmarshal(data, &metadata); err != nil { return false, nil, err } gv, err = unversioned.ParseGroupVersion(metadata.APIVersion) if err != nil { return false, nil, err } gvkOut = &unversioned.GroupVersionKind{ Group: gv.Group, Version: gv.Version, Kind: metadata.Kind, } } else { gv = gvk.GroupVersion() gvkOut = gvk } return registered.IsThirdPartyAPIGroupVersion(gv), gvkOut, nil }
func (f *factory) SwaggerSchema(gvk unversioned.GroupVersionKind) (*swagger.ApiDeclaration, error) { version := gvk.GroupVersion() clientset, err := f.clients.ClientSetForVersion(&version) if err != nil { return nil, err } return clientset.Discovery().SwaggerSchema(version) }
func (o objects) Kind(gvk unversioned.GroupVersionKind, name string) (runtime.Object, error) { // TODO our test clients deal in internal versions. We need to plumb that knowledge down here // we might do this via an extra function to the scheme to allow getting internal group versions // I'm punting for now gvk.Version = "" empty, _ := o.scheme.New(gvk.GroupVersion().String(), gvk.Kind) nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object) arr, ok := o.types[gvk.Kind] if !ok { if strings.HasSuffix(gvk.Kind, "List") { itemKind := gvk.Kind[:len(gvk.Kind)-4] arr, ok := o.types[itemKind] if !ok { return empty, nil } out, err := o.scheme.New(gvk.GroupVersion().String(), gvk.Kind) if err != nil { return nilValue, err } if err := meta.SetList(out, arr); err != nil { return nilValue, err } if out, err = o.scheme.Copy(out); err != nil { return nilValue, err } return out, nil } return nilValue, errors.NewNotFound(gvk.Kind, name) } index := o.last[gvk.Kind] if index >= len(arr) { index = len(arr) - 1 } if index < 0 { return nilValue, errors.NewNotFound(gvk.Kind, name) } out, err := o.scheme.Copy(arr[index]) if err != nil { return nilValue, err } o.last[gvk.Kind] = index + 1 if status, ok := out.(*unversioned.Status); ok { if status.Details != nil { status.Details.Kind = gvk.Kind } if status.Status != unversioned.StatusSuccess { return nilValue, &errors.StatusError{ErrStatus: *status} } } return out, nil }
// DecodeIntoWithSpecifiedVersionKind compares the passed in requestGroupVersionKind // with data.Version and data.Kind, defaulting data.Version and // data.Kind to the specified value if they are empty, or generating an error if // data.Version and data.Kind are not empty and differ from the specified value. // The function then implements the functionality of DecodeInto. // If specifiedVersion and specifiedKind are empty, the function degenerates to // DecodeInto. func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{}, requestedGVK unversioned.GroupVersionKind) error { if len(data) == 0 { return errors.New("empty input") } dataVersion, dataKind, err := s.DataVersionAndKind(data) if err != nil { return err } if dataVersion == "" { dataVersion = requestedGVK.GroupVersion().String() } if dataKind == "" { dataKind = requestedGVK.Kind } if (len(requestedGVK.Group) > 0 || len(requestedGVK.Version) > 0) && (dataVersion != requestedGVK.GroupVersion().String()) { return errors.New(fmt.Sprintf("The apiVersion in the data (%s) does not match the specified apiVersion(%v)", dataVersion, requestedGVK.GroupVersion())) } if len(requestedGVK.Kind) > 0 && (dataKind != requestedGVK.Kind) { return errors.New(fmt.Sprintf("The kind in the data (%s) does not match the specified kind(%v)", dataKind, requestedGVK)) } objVersion, objKind, err := s.ObjectVersionAndKind(obj) if err != nil { return err } if dataKind == "" { // Assume objects with unset Kind fields are being unmarshalled into the // correct type. dataKind = objKind } if dataVersion == "" { // Assume objects with unset Version fields are being unmarshalled into the // correct type. dataVersion = objVersion } external, err := s.NewObject(dataVersion, dataKind) if err != nil { return err } if err := codec.NewDecoderBytes(data, new(codec.JsonHandle)).Decode(external); err != nil { return err } flags, meta := s.generateConvertMeta(dataVersion, objVersion, external) if err := s.converter.Convert(external, obj, flags, meta); err != nil { return err } // Version and Kind should be blank in memory. return s.SetVersionAndKind("", "", obj) }
func (t *thirdPartyResourceDataCreator) New(kind unversioned.GroupVersionKind) (out runtime.Object, err error) { switch kind.Kind { case "ThirdPartyResourceData": if apiutil.GetGroupVersion(t.group, t.version) != kind.GroupVersion().String() { return nil, fmt.Errorf("unknown kind %v", kind) } return &extensions.ThirdPartyResourceData{}, nil case "ThirdPartyResourceDataList": if apiutil.GetGroupVersion(t.group, t.version) != kind.GroupVersion().String() { return nil, fmt.Errorf("unknown kind %v", kind) } return &extensions.ThirdPartyResourceDataList{}, nil default: return t.delegate.New(kind) } }
func doDeepCopyTest(t *testing.T, kind unversioned.GroupVersionKind, f *fuzz.Fuzzer) { item, err := api.Scheme.New(kind) if err != nil { t.Fatalf("Could not create a %v: %s", kind, err) } f.Fuzz(item) itemCopy, err := api.Scheme.DeepCopy(item) if err != nil { t.Errorf("Could not deep copy a %v: %s", kind, err) return } if !reflect.DeepEqual(item, itemCopy) { t.Errorf("\nexpected: %#v\n\ngot: %#v\n\ndiff: %v", item, itemCopy, diff.ObjectReflectDiff(item, itemCopy)) } prefuzzData := &bytes.Buffer{} if err := api.Codecs.LegacyCodec(kind.GroupVersion()).Encode(item, prefuzzData); err != nil { t.Errorf("Could not encode a %v: %s", kind, err) return } // Refuzz the copy, which should have no effect on the original f.Fuzz(itemCopy) postfuzzData := &bytes.Buffer{} if err := api.Codecs.LegacyCodec(kind.GroupVersion()).Encode(item, postfuzzData); err != nil { t.Errorf("Could not encode a %v: %s", kind, err) return } if bytes.Compare(prefuzzData.Bytes(), postfuzzData.Bytes()) != 0 { t.Log(diff.StringDiff(prefuzzData.String(), postfuzzData.String())) t.Errorf("Fuzzing copy modified original of %#v", kind) return } }
// 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 }
func (t *thirdPartyResourceDataCodec) DecodeIntoWithSpecifiedVersionKind(data []byte, obj runtime.Object, gvk unversioned.GroupVersionKind) error { thirdParty, ok := obj.(*extensions.ThirdPartyResourceData) if !ok { return fmt.Errorf("unexpected object: %#v", obj) } if gvk.Kind != "ThirdPartyResourceData" { return fmt.Errorf("unexpeceted kind: %s", gvk.Kind) } var dataObj interface{} if err := json.Unmarshal(data, &dataObj); err != nil { return err } mapObj, ok := dataObj.(map[string]interface{}) if !ok { return fmt.Errorf("unexpcted object: %#v", dataObj) } if kindObj, found := mapObj["kind"]; !found { mapObj["kind"] = gvk.Kind } else { kindStr, ok := kindObj.(string) if !ok { return fmt.Errorf("unexpected object for 'kind': %v", kindObj) } if kindStr != t.kind { return fmt.Errorf("kind doesn't match, expecting: %s, got %s", gvk.Kind, kindStr) } } if versionObj, found := mapObj["apiVersion"]; !found { mapObj["apiVersion"] = gvk.GroupVersion().String() } else { versionStr, ok := versionObj.(string) if !ok { return fmt.Errorf("unexpected object for 'apiVersion': %v", versionObj) } if versionStr != gvk.GroupVersion().String() { return fmt.Errorf("version doesn't match, expecting: %v, got %s", gvk.GroupVersion(), versionStr) } } if err := t.populate(thirdParty, data); err != nil { return err } return nil }
func (t *thirdPartyResourceDataCreator) New(kind unversioned.GroupVersionKind) (out runtime.Object, err error) { switch kind.Kind { case "ThirdPartyResourceData": if apiutil.GetGroupVersion(t.group, t.version) != kind.GroupVersion().String() { return nil, fmt.Errorf("unknown kind %v", kind) } return &extensions.ThirdPartyResourceData{}, nil case "ThirdPartyResourceDataList": if apiutil.GetGroupVersion(t.group, t.version) != kind.GroupVersion().String() { return nil, fmt.Errorf("unknown kind %v", kind) } return &extensions.ThirdPartyResourceDataList{}, nil case "ListOptions": if apiutil.GetGroupVersion(t.group, t.version) == kind.GroupVersion().String() { // Translate third party group to external group. gvk := registered.EnabledVersionsForGroup(api.GroupName)[0].WithKind(kind.Kind) return t.delegate.New(gvk) } return t.delegate.New(kind) default: return t.delegate.New(kind) } }
func (t *thirdPartyResourceDataCodec) Decode(data []byte, gvk *unversioned.GroupVersionKind, into runtime.Object) (runtime.Object, *unversioned.GroupVersionKind, error) { if into == nil { obj, err := t.populate(data) if err != nil { return nil, nil, err } return obj, gvk, nil } thirdParty, ok := into.(*extensions.ThirdPartyResourceData) if !ok { return nil, nil, fmt.Errorf("unexpected object: %#v", into) } 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 := &unversioned.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 kindStr != t.kind { return nil, nil, fmt.Errorf("kind doesn't match, expecting: %s, got %s", gvk.Kind, kindStr) } actual.Kind = t.kind } 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 := unversioned.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 }
// Recognizes returns true for any version or kind that is specified (internal // versions are specifically excluded). func (unstructuredJSONScheme) Recognizes(gvk unversioned.GroupVersionKind) bool { return !gvk.GroupVersion().IsEmpty() && len(gvk.Kind) > 0 }
func (t *thirdPartyResourceDataDecoder) Decode(data []byte, gvk *unversioned.GroupVersionKind, into runtime.Object) (runtime.Object, *unversioned.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) } } obj, err := t.populate(data) if err != nil { return nil, nil, err } return obj, gvk, nil } 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, err := t.populate(data) if err != nil { return nil, nil, err } o.Objects = []runtime.Object{ obj, } return o, gvk, nil default: 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 := &unversioned.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", gvk.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 := unversioned.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 }
func (c *mockCreater) New(kind unversioned.GroupVersionKind) (runtime.Object, error) { c.apiVersion, c.kind = kind.GroupVersion().String(), kind.Kind return c.obj, c.err }
// 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. 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, fmt.Errorf("no kind named %q is registered in versions %q", gk, versions) } // 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 }
func (u *UnstructuredList) SetGroupVersionKind(gvk unversioned.GroupVersionKind) { u.SetAPIVersion(gvk.GroupVersion().String()) u.SetKind(gvk.Kind) }