func newEtcd(ns runtime.NegotiatedSerializer, storageGroupVersionString, memoryGroupVersionString string, etcdConfig etcdstorage.EtcdConfig) (etcdStorage storage.Interface, err error) { if storageGroupVersionString == "" { return etcdStorage, fmt.Errorf("storageVersion is required to create a etcd storage") } storageVersion, err := unversioned.ParseGroupVersion(storageGroupVersionString) if err != nil { return nil, fmt.Errorf("couldn't understand storage version %v: %v", storageGroupVersionString, err) } memoryVersion, err := unversioned.ParseGroupVersion(memoryGroupVersionString) if err != nil { return nil, fmt.Errorf("couldn't understand memory version %v: %v", memoryGroupVersionString, err) } var storageConfig etcdstorage.EtcdStorageConfig storageConfig.Config = etcdConfig s, ok := ns.SerializerForMediaType("application/json", nil) if !ok { return nil, fmt.Errorf("unable to find serializer for JSON") } glog.Infof("constructing etcd storage interface.\n sv: %v\n mv: %v\n", storageVersion, memoryVersion) encoder := ns.EncoderForVersion(s, storageVersion) decoder := ns.DecoderToVersion(s, memoryVersion) if memoryVersion.Group != storageVersion.Group { // Allow this codec to translate between groups. if err = versioning.EnableCrossGroupEncoding(encoder, memoryVersion.Group, storageVersion.Group); err != nil { return nil, fmt.Errorf("error setting up encoder for %v: %v", storageGroupVersionString, err) } if err = versioning.EnableCrossGroupDecoding(decoder, storageVersion.Group, memoryVersion.Group); err != nil { return nil, fmt.Errorf("error setting up decoder for %v: %v", storageGroupVersionString, err) } } storageConfig.Codec = runtime.NewCodec(encoder, decoder) return storageConfig.NewStorage() }
// dest must be a map of group to groupVersion. func mergeGroupVersionIntoMap(gvList string, dest map[string]unversioned.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 := unversioned.ParseGroupVersion(gvString) if err != nil { return err } dest[gv.Group] = gv } else { parts := strings.SplitN(gvString, "=", 2) gv, err := unversioned.ParseGroupVersion(parts[1]) if err != nil { return err } dest[parts[0]] = gv } } return nil }
// rawExtensionToEmbeddedObject does the conversion you would expect from the name, using the information // given in conversion.Scope. It's placed in all schemes as a ConversionFunc to enable plugins; // see the comment for RawExtension. func (self *Scheme) rawExtensionToEmbeddedObject(in *RawExtension, out *EmbeddedObject, s conversion.Scope) error { if len(in.RawJSON) == 0 || (len(in.RawJSON) == 4 && string(in.RawJSON) == "null") { out.Object = nil return nil } // Figure out the type and kind of the output object. inGroupVersionString, outGroupVersionString, scheme := self.fromScope(s) dataKind, err := scheme.raw.DataKind(in.RawJSON) if err != nil { return err } inVersion, err := unversioned.ParseGroupVersion(inGroupVersionString) if err != nil { return err } outVersion, err := unversioned.ParseGroupVersion(outGroupVersionString) if err != nil { return err } // We have to make this object ourselves because we don't store the version field for // plugin objects. inObj, err := scheme.New(inVersion.WithKind(dataKind.Kind)) if err != nil { return err } err = DecodeInto(scheme, in.RawJSON, inObj) if err != nil { return err } // Make the desired internal version, and do the conversion. outObj, err := scheme.New(outVersion.WithKind(dataKind.Kind)) if err != nil { return err } err = scheme.Convert(inObj, outObj) if err != nil { return err } // Last step, clear the Kind field; that should always be blank in memory. err = s.Convert( &emptyPlugin{PluginBase: PluginBase{Kind: ""}}, outObj, conversion.SourceToDest|conversion.IgnoreMissingFields|conversion.AllowDifferentFieldTypeNames, ) if err != nil { return err } out.Object = outObj return nil }
// ClientConfigForVersion returns the correct config for a server func (c *ClientCache) ClientConfigForVersion(version string) (*client.Config, error) { if c.defaultConfig == nil { config, err := c.loader.ClientConfig() if err != nil { return nil, err } c.defaultConfig = config if c.matchVersion { if err := client.MatchesServerVersion(c.defaultClient, config); err != nil { return nil, err } } } if config, ok := c.configs[version]; ok { return config, nil } // TODO: have a better config copy method config := *c.defaultConfig // TODO these fall out when we finish the refactor var preferredGV *unversioned.GroupVersion if len(version) > 0 { gv, err := unversioned.ParseGroupVersion(version) if err != nil { return nil, err } preferredGV = &gv } registeredGVs := []unversioned.GroupVersion{} for _, gvString := range registered.RegisteredVersions { gv, err := unversioned.ParseGroupVersion(gvString) if err != nil { return nil, err } registeredGVs = append(registeredGVs, gv) } negotiatedVersion, err := client.NegotiateVersion(c.defaultClient, &config, preferredGV, registeredGVs) if err != nil { return nil, err } config.GroupVersion = negotiatedVersion client.SetKubernetesDefaults(&config) c.configs[version] = &config // `version` does not necessarily equal `config.Version`. However, we know that we call this method again with // `config.Version`, we should get the the config we've just built. configCopy := config c.configs[config.GroupVersion.String()] = &configCopy return &config, nil }
func AddHPAScaleRefEdges(g osgraph.Graph) { for _, node := range g.NodesByKind(kubegraph.HorizontalPodAutoscalerNodeKind) { hpaNode := node.(*kubegraph.HorizontalPodAutoscalerNode) syntheticMeta := kapi.ObjectMeta{ Name: hpaNode.HorizontalPodAutoscaler.Spec.ScaleRef.Name, Namespace: hpaNode.HorizontalPodAutoscaler.Namespace, } var groupVersionResource unversioned.GroupVersionResource resource := strings.ToLower(hpaNode.HorizontalPodAutoscaler.Spec.ScaleRef.Kind) if groupVersion, err := unversioned.ParseGroupVersion(hpaNode.HorizontalPodAutoscaler.Spec.ScaleRef.APIVersion); err == nil { groupVersionResource = groupVersion.WithResource(resource) } else { groupVersionResource = unversioned.GroupVersionResource{Resource: resource} } groupVersionResource, err := registered.RESTMapper().ResourceFor(groupVersionResource) if err != nil { continue } var syntheticNode graph.Node switch groupVersionResource.GroupResource() { case kapi.Resource("replicationcontrollers"): syntheticNode = kubegraph.FindOrCreateSyntheticReplicationControllerNode(g, &kapi.ReplicationController{ObjectMeta: syntheticMeta}) case deployapi.Resource("deploymentconfigs"): syntheticNode = deploygraph.FindOrCreateSyntheticDeploymentConfigNode(g, &deployapi.DeploymentConfig{ObjectMeta: syntheticMeta}) default: continue } g.AddEdge(hpaNode, syntheticNode, ScalingEdgeKind) } }
// DecodeList alters the list in place, attempting to decode any objects found in // the list that have the runtime.Unknown type. Any errors that occur are returned // after the entire list is processed. Decoders are tried in order. func DecodeList(objects []Object, decoders ...ObjectDecoder) []error { errs := []error(nil) for i, obj := range objects { switch t := obj.(type) { case *Unknown: for _, decoder := range decoders { gv, err := unversioned.ParseGroupVersion(t.APIVersion) if err != nil { errs = append(errs, err) break } if !decoder.Recognizes(gv.WithKind(t.Kind)) { continue } obj, err := Decode(decoder, t.RawJSON) if err != nil { errs = append(errs, err) break } objects[i] = obj break } } } return errs }
func (g TestGroup) GroupVersion() *unversioned.GroupVersion { gv, err := unversioned.ParseGroupVersion(g.GroupVersionUnderTest) if err != nil { panic(err) } return &gv }
// Convert_runtime_RawExtension_To_runtime_Object well, this is the reason why there was runtime.Embedded. The `out` here is hopeless. // The caller doesn't know the type ahead of time and that means this method can't communicate the return value. This sucks really badly. // I'm going to set the `in.Object` field can have callers to this function do magic to pull it back out. I'm also going to bitch about it. func Convert_runtime_RawExtension_To_runtime_Object(in *runtime.RawExtension, out runtime.Object, s conversion.Scope) error { if in == nil || len(in.Raw) == 0 || in.Object != nil { return nil } // the scheme knows all available group versions, so its possible to build the decoder properly, but it would require some refactoring srcVersion, err := unversioned.ParseGroupVersion(s.Meta().SrcVersion) if err != nil { return err } decodedObject, err := runtime.Decode(kapi.Codecs.UniversalDecoder(srcVersion), in.Raw) if err != nil { return err } internalObject, err := kapi.Scheme.ConvertToVersion(decodedObject, s.Meta().DestVersion) if err != nil { return err } in.Object = internalObject return nil }
// The docker metadata must be cast to a version func Convert_api_Image_To_v1beta3_Image(in *newer.Image, out *Image, s conversion.Scope) error { if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil { return err } out.DockerImageReference = in.DockerImageReference out.DockerImageManifest = in.DockerImageManifest out.DockerImageManifestMediaType = in.DockerImageManifestMediaType out.DockerImageConfig = in.DockerImageConfig gvString := in.DockerImageMetadataVersion if len(gvString) == 0 { gvString = "1.0" } if !strings.Contains(gvString, "/") { gvString = "/" + gvString } version, err := unversioned.ParseGroupVersion(gvString) if err != nil { return err } data, err := runtime.Encode(api.Codecs.LegacyCodec(version), &in.DockerImageMetadata, version) if err != nil { return err } out.DockerImageMetadata.Raw = data out.DockerImageMetadataVersion = version.Version return nil }
// serverAPIVersions fetches the server versions available from the groupless API at the given prefix func serverAPIVersions(c *kclient.Client, grouplessPrefix string) ([]unversioned.GroupVersion, error) { // Get versions doc body, err := c.Get().AbsPath(grouplessPrefix).Do().Raw() if err != nil { return []unversioned.GroupVersion{}, err } // Unmarshal var v unversioned.APIVersions err = json.Unmarshal(body, &v) if err != nil { return []unversioned.GroupVersion{}, fmt.Errorf("got '%s': %v", string(body), err) } // Convert to GroupVersion structs serverAPIVersions := []unversioned.GroupVersion{} for _, version := range v.Versions { gv, err := unversioned.ParseGroupVersion(version) if err != nil { return []unversioned.GroupVersion{}, err } serverAPIVersions = append(serverAPIVersions, gv) } return serverAPIVersions, nil }
// ConvertToVersion attempts to convert an input object to its matching Kind in another // version within this scheme. Will return an error if the provided version does not // contain the inKind (or a mapping by name defined with AddKnownTypeWithName). Will also // return an error if the conversion does not result in a valid Object being // returned. The serializer handles loading/serializing nested objects. func (s *Scheme) ConvertToVersion(in Object, outVersion string) (Object, error) { gv, err := unversioned.ParseGroupVersion(outVersion) if err != nil { return nil, err } switch in.(type) { case *Unknown, *Unstructured, *UnstructuredList: old := in.GetObjectKind().GroupVersionKind() defer in.GetObjectKind().SetGroupVersionKind(old) setTargetVersion(in, s, gv) return in, nil } t := reflect.TypeOf(in) if t.Kind() != reflect.Ptr { return nil, fmt.Errorf("only pointer types may be converted: %v", t) } t = t.Elem() if t.Kind() != reflect.Struct { return nil, fmt.Errorf("only pointers to struct types may be converted: %v", t) } var kind unversioned.GroupVersionKind if unversionedKind, ok := s.unversionedTypes[t]; ok { kind = unversionedKind } else { kinds, ok := s.typeToGVK[t] if !ok || len(kinds) == 0 { return nil, fmt.Errorf("%v is not a registered type and cannot be converted into version %q", t, outVersion) } for _, kind := range kinds { if gv.Version == kind.Version && gv.Group == kind.Group { setTargetKind(in, kind) return in, nil } } kind = kinds[0] } outKind := gv.WithKind(kind.Kind) inKind, err := s.ObjectKind(in) if err != nil { return nil, err } out, err := s.New(outKind) if err != nil { return nil, err } flags, meta := s.generateConvertMeta(inKind.GroupVersion(), gv, in) if err := s.converter.Convert(in, out, flags, meta); err != nil { return nil, err } setTargetVersion(out, s, gv) return out, nil }
func setExtensionsDefaults(config *Config) error { // if experimental group is not registered, return an error g, err := latest.Group("extensions") if err != nil { return err } config.Prefix = "apis/" if config.UserAgent == "" { config.UserAgent = DefaultKubernetesUserAgent() } // TODO: Unconditionally set the config.Version, until we fix the config. //if config.Version == "" { gv, err := unversioned.ParseGroupVersion(g.GroupVersion) if err != nil { return err } config.GroupVersion = &gv //} versionInterfaces, err := g.InterfacesFor(config.GroupVersion.String()) if err != nil { return fmt.Errorf("Extensions API group/version '%v' is not recognized (valid values: %s)", config.GroupVersion, strings.Join(latest.GroupOrDie("extensions").Versions, ", ")) } config.Codec = versionInterfaces.Codec if config.QPS == 0 { config.QPS = 5 } if config.Burst == 0 { config.Burst = 10 } return nil }
// InfoForObject creates an Info object for the given Object. An error is returned // if the object cannot be introspected. Name and namespace will be set into Info // if the mapping's MetadataAccessor can retrieve them. func (m *Mapper) InfoForObject(obj runtime.Object) (*Info, error) { gvString, kind, err := m.ObjectVersionAndKind(obj) if err != nil { return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err) } gv, err := unversioned.ParseGroupVersion(gvString) if err != nil { return nil, fmt.Errorf("unable to parse group/version from %q: %v", gvString, err) } mapping, err := m.RESTMapping(unversioned.GroupKind{Group: gv.Group, Kind: kind}, gv.Version) if err != nil { return nil, fmt.Errorf("unable to recognize %q: %v", kind, err) } client, err := m.ClientForMapping(mapping) if err != nil { return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err) } name, _ := mapping.MetadataAccessor.Name(obj) namespace, _ := mapping.MetadataAccessor.Namespace(obj) resourceVersion, _ := mapping.MetadataAccessor.ResourceVersion(obj) return &Info{ Mapping: mapping, Client: client, Namespace: namespace, Name: name, Object: obj, ResourceVersion: resourceVersion, }, nil }
func TestDirectCodec(t *testing.T) { s := GetDirectCodecTestScheme() cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})) serializer, _ := cf.SerializerForFileExtension("json") df := DirectCodecFactory{cf} ignoredGV, err := unversioned.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 (c *clientSwaggerSchema) ValidateBytes(data []byte) error { version, kind, err := runtime.UnstructuredJSONScheme.DataVersionAndKind(data) if err != nil { return err } gv, err := unversioned.ParseGroupVersion(version) if err != nil { return fmt.Errorf("unable to parse group/version from %q: %v", version, err) } if ok := registered.IsRegisteredAPIGroupVersion(gv); !ok { return fmt.Errorf("API version %q isn't supported, only supports API versions %q", version, registered.RegisteredGroupVersions) } resource, _ := meta.KindToResource(kind, false) gvk, err := c.mapper.KindFor(resource) if err != nil { return fmt.Errorf("could not find api group for %s: %v", kind, err) } if gvk.Group == "extensions" { if c.c.ExtensionsClient == nil { return errors.New("unable to validate: no experimental client") } return getSchemaAndValidate(c.c.ExtensionsClient.RESTClient, data, "apis/", version, c.cacheDir) } return getSchemaAndValidate(c.c.RESTClient, data, "api", version, c.cacheDir) }
// FindAllCanonicalResources returns all resource names that map directly to their kind (Kind -> Resource -> Kind) // and are not subresources. This is the closest mapping possible from the client side to resources that can be // listed and updated. Note that this may return some virtual resources (like imagestreamtags) that can be otherwise // represented. // TODO: add a field to APIResources for "virtual" (or that points to the canonical resource). // TODO: fallback to the scheme when discovery is not possible. func FindAllCanonicalResources(d discovery.DiscoveryInterface, m meta.RESTMapper) ([]unversioned.GroupResource, error) { set := make(map[unversioned.GroupResource]struct{}) all, err := d.ServerResources() if err != nil { return nil, err } for apiVersion, v := range all { gv, err := unversioned.ParseGroupVersion(apiVersion) if err != nil { continue } for _, r := range v.APIResources { // ignore subresources if strings.Contains(r.Name, "/") { continue } // because discovery info doesn't tell us whether the object is virtual or not, perform a lookup // by the kind for resource (which should be the canonical resource) and then verify that the reverse // lookup (KindsFor) does not error. if mapping, err := m.RESTMapping(unversioned.GroupKind{Group: gv.Group, Kind: r.Kind}, gv.Version); err == nil { if _, err := m.KindsFor(mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource)); err == nil { set[unversioned.GroupResource{Group: mapping.GroupVersionKind.Group, Resource: mapping.Resource}] = struct{}{} } } } } var groupResources []unversioned.GroupResource for k := range set { groupResources = append(groupResources, k) } sort.Sort(groupResourcesByName(groupResources)) return groupResources, nil }
func (o *AppJSONOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error { version, _ := cmd.Flags().GetString("output-version") for _, v := range strings.Split(version, ",") { gv, err := unversioned.ParseGroupVersion(v) if err != nil { return fmt.Errorf("provided output-version %q is not valid: %v", v, err) } o.OutputVersions = append(o.OutputVersions, gv) } o.OutputVersions = append(o.OutputVersions, registered.EnabledVersions()...) o.Action.Bulk.Mapper = clientcmd.ResourceMapper(f) o.Action.Bulk.Op = configcmd.Create mapper, _ := f.Object(false) o.PrintObject = cmdutil.VersionedPrintObject(f.PrintObject, cmd, mapper, o.Action.Out) o.Generator, _ = cmd.Flags().GetString("generator") ns, _, err := f.DefaultNamespace() if err != nil { return err } o.Namespace = ns o.Client, _, err = f.Clients() return err }
func NewDefaultRESTMapper(group string, groupVersionStrings []string, interfacesFunc meta.VersionInterfacesFunc, importPathPrefix string, ignoredKinds, rootScoped sets.String) *meta.DefaultRESTMapper { mapper := meta.NewDefaultRESTMapper(group, groupVersionStrings, interfacesFunc) // enumerate all supported versions, get the kinds, and register with the mapper how to address // our resources. for _, gvString := range groupVersionStrings { gv, err := unversioned.ParseGroupVersion(gvString) // TODO stop panicing when the types are fixed if err != nil { panic(err) } if gv.Group != group { panic(fmt.Sprintf("%q does not match the expect %q", gv.Group, group)) } for kind, oType := range Scheme.KnownTypes(gv.String()) { // TODO: Remove import path prefix check. // We check the import path prefix because we currently stuff both "api" and "extensions" objects // into the same group within Scheme since Scheme has no notion of groups yet. if !strings.HasPrefix(oType.PkgPath(), importPathPrefix) || ignoredKinds.Has(kind) { continue } scope := meta.RESTScopeNamespace if rootScoped.Has(kind) { scope = meta.RESTScopeRoot } mapper.Add(scope, kind, gv.String(), false) } } return mapper }
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 init() { kubeTestAPI := os.Getenv("KUBE_TEST_API") if len(kubeTestAPI) != 0 { testGroupVersions := strings.Split(kubeTestAPI, ",") for _, gvString := range testGroupVersions { groupVersion, err := unversioned.ParseGroupVersion(gvString) if err != nil { panic(fmt.Sprintf("Error parsing groupversion %v: %v", gvString, err)) } Groups[groupVersion.Group] = TestGroup{ externalGroupVersion: groupVersion, internalGroupVersion: unversioned.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal}, } } } if _, ok := Groups[api.GroupName]; !ok { Groups[api.GroupName] = TestGroup{ externalGroupVersion: unversioned.GroupVersion{Group: api.GroupName, Version: registered.GroupOrDie(api.GroupName).GroupVersion.Version}, internalGroupVersion: api.SchemeGroupVersion, } } if _, ok := Groups[extensions.GroupName]; !ok { Groups[extensions.GroupName] = TestGroup{ externalGroupVersion: unversioned.GroupVersion{Group: extensions.GroupName, Version: registered.GroupOrDie(extensions.GroupName).GroupVersion.Version}, internalGroupVersion: extensions.SchemeGroupVersion, } } Default = Groups[api.GroupName] Extensions = Groups[extensions.GroupName] }
func (s *Scheme) DecodeToVersionedObject(data []byte) (interface{}, string, string, error) { version, kind, err := s.DataVersionAndKind(data) if err != nil { return nil, "", "", err } gv, err := unversioned.ParseGroupVersion(version) if err != nil { return nil, "", "", err } internalGV, exists := s.InternalVersions[gv.Group] if !exists { return nil, "", "", fmt.Errorf("no internalVersion specified for %v", gv) } if len(gv.Version) == 0 && len(internalGV.Version) != 0 { return nil, "", "", fmt.Errorf("version not set in '%s'", string(data)) } if kind == "" { return nil, "", "", fmt.Errorf("kind not set in '%s'", string(data)) } obj, err := s.NewObject(version, kind) if err != nil { return nil, "", "", err } if err := codec.NewDecoderBytes(data, new(codec.JsonHandle)).Decode(obj); err != nil { return nil, "", "", err } return obj, version, kind, nil }
func NewShortcutExpander(discoveryClient discovery.DiscoveryInterface, delegate meta.RESTMapper) ShortcutExpander { defaultMapper := ShortcutExpander{RESTMapper: delegate} // this assumes that legacy kube versions and legacy origin versions are the same, probably fair apiResources, err := discoveryClient.ServerResources() if err != nil { return defaultMapper } availableResources := []unversioned.GroupVersionResource{} for groupVersionString, resourceList := range apiResources { currVersion, err := unversioned.ParseGroupVersion(groupVersionString) if err != nil { return defaultMapper } for _, resource := range resourceList.APIResources { availableResources = append(availableResources, currVersion.WithResource(resource.Name)) } } availableAll := []string{} for _, requestedResource := range userResources { for _, availableResource := range availableResources { if requestedResource == availableResource.Resource { availableAll = append(availableAll, requestedResource) break } } } return ShortcutExpander{All: availableAll, RESTMapper: delegate} }
func (t *thirdPartyResourceDataDecoder) populateFromObject(mapObj map[string]interface{}, data []byte) (runtime.Object, *unversioned.GroupVersionKind, error) { typeMeta := unversioned.TypeMeta{} if err := json.Unmarshal(data, &typeMeta); err != nil { return nil, nil, err } gv, err := unversioned.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 (u *Unstructured) GroupVersionKind() *unversioned.GroupVersionKind { gv, err := unversioned.ParseGroupVersion(u.GetAPIVersion()) if err != nil { return nil } gvk := gv.WithKind(u.GetKind()) return &gvk }
func (u *UnstructuredList) GroupVersionKind() unversioned.GroupVersionKind { gv, err := unversioned.ParseGroupVersion(u.GetAPIVersion()) if err != nil { return unversioned.GroupVersionKind{} } gvk := gv.WithKind(u.GetKind()) return gvk }
// convertItemsForDisplayFromDefaultCommand returns a new list that contains parallel elements that have been converted to the most preferred external version // TODO: move this function into the core factory PrintObjects method // TODO: print-objects should have preferred output versions func convertItemsForDisplayFromDefaultCommand(cmd *cobra.Command, objs []runtime.Object) ([]runtime.Object, error) { requested := kcmdutil.GetFlagString(cmd, "output-version") version, err := unversioned.ParseGroupVersion(requested) if err != nil { return nil, err } return convertItemsForDisplay(objs, version) }
func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kubectl.Generator, names []kubectl.GeneratorParam, params map[string]interface{}, overrides, namespace string) (runtime.Object, string, meta.RESTMapper, *meta.RESTMapping, error) { err := kubectl.ValidateParams(names, params) if err != nil { return nil, "", nil, nil, err } obj, err := generator.Generate(params) if err != nil { return nil, "", nil, nil, err } mapper, typer := f.Object() gvString, kind, err := typer.ObjectVersionAndKind(obj) if err != nil { return nil, "", nil, nil, err } gv, err := unversioned.ParseGroupVersion(gvString) if err != nil { return nil, "", nil, nil, err } gvk := gv.WithKind(kind) if len(overrides) > 0 { obj, err = cmdutil.Merge(obj, overrides, kind) if err != nil { return nil, "", nil, nil, err } } mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version) if err != nil { return nil, "", nil, nil, err } client, err := f.RESTClient(mapping) if err != nil { return nil, "", nil, nil, err } // TODO: extract this flag to a central location, when such a location exists. if !cmdutil.GetFlagBool(cmd, "dry-run") { resourceMapper := &resource.Mapper{ObjectTyper: typer, RESTMapper: mapper, ClientMapper: f.ClientMapperForCommand()} info, err := resourceMapper.InfoForObject(obj) if err != nil { return nil, "", nil, nil, err } if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info); err != nil { return nil, "", nil, nil, err } obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) if err != nil { return nil, "", nil, nil, err } } return obj, kind, mapper, mapping, err }
func (obj objectAccessor) SetAPIVersion(version string) { gvk := obj.GetObjectKind().GroupVersionKind() gv, err := unversioned.ParseGroupVersion(version) if err != nil { gv = unversioned.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 := unversioned.GroupVersion{} mapper, _ := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) // 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 := unversioned.ParseResourceArg(inModel) gvk := unversioned.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 = unversioned.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) }
// Recognizes returns true if the scheme is able to handle the provided version and kind // of an object. func (s *Scheme) Recognizes(gvString, kind string) bool { gv, err := unversioned.ParseGroupVersion(gvString) if err != nil { return false } gvk := gv.WithKind(kind) _, exists := s.gvkToType[gvk] return exists }