// 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 }
func init() { kubeTestAPI := os.Getenv("KUBE_TEST_API") if kubeTestAPI != "" { 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}, } } } if _, ok := Groups[api.GroupName]; !ok { Groups[api.GroupName] = TestGroup{ externalGroupVersion: unversioned.GroupVersion{Group: api.GroupName, Version: latest.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: latest.GroupOrDie(extensions.GroupName).GroupVersion.Version}, internalGroupVersion: extensions.SchemeGroupVersion, } } Default = Groups[api.GroupName] Extensions = Groups[extensions.GroupName] }
// 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 }
// UpdateVersionAndKind uses reflection to find and set the versionField and kindField fields // on a pointer to a struct to version and kind. Provided as a convenience for others // implementing MetaFactory. Pass an array to baseFields to check one or more nested structs // for the named fields. The version field is treated as optional if it is not present in the struct. // TODO: this method is on its way out func UpdateVersionAndKind(baseFields []string, versionField, version, kindField, kind string, obj interface{}) error { if typed, ok := obj.(unversioned.ObjectKind); ok { if len(version) == 0 && len(kind) == 0 { typed.SetGroupVersionKind(nil) } else { gv, err := unversioned.ParseGroupVersion(version) if err != nil { return err } typed.SetGroupVersionKind(&unversioned.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}) } return nil } v, err := EnforcePtr(obj) if err != nil { return err } pkg := path.Base(v.Type().PkgPath()) t := v.Type() name := t.Name() if v.Kind() != reflect.Struct { return fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), name, v.Interface()) } for i := range baseFields { base := v.FieldByName(baseFields[i]) if !base.IsValid() { continue } v = base } field := v.FieldByName(kindField) if !field.IsValid() { // Types defined in the unversioned package are allowed to not have a // kindField. Clients will have to know what they are based on the // context. // TODO: add some type trait here, or some way of indicating whether // this feature is allowed on a per-type basis. Using package name is // overly broad and a bit hacky. if pkg == "unversioned" { return nil } return fmt.Errorf("couldn't find %v field in %#v", kindField, v.Interface()) } field.SetString(kind) if field := v.FieldByName(versionField); field.IsValid() { field.SetString(version) } return nil }
func (obj objectAccessor) SetAPIVersion(version string) { gvk := obj.GetObjectKind().GroupVersionKind() if gvk == nil { gvk = &unversioned.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) }
func init() { // Env var KUBE_API_VERSIONS is a comma separated list of API versions that // should be registered in the scheme. kubeAPIVersions := os.Getenv("KUBE_API_VERSIONS") if len(kubeAPIVersions) != 0 { for _, version := range strings.Split(kubeAPIVersions, ",") { gv, err := unversioned.ParseGroupVersion(version) if err != nil { glog.Fatalf("invalid api version: %s in KUBE_API_VERSIONS: %s.", version, os.Getenv("KUBE_API_VERSIONS")) } envRequestedVersions[gv] = struct{}{} } } }
// embeddedObjectToRawExtension does the conversion you would expect from the name, using the information // given in conversion.Scope. It's placed in the DefaultScheme as a ConversionFunc to enable plugins; // see the comment for RawExtension. func (self *Scheme) embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExtension, s conversion.Scope) error { if in.Object == nil { out.RawJSON = []byte("null") return nil } // Figure out the type and kind of the output object. _, outGroupVersionString, scheme := self.fromScope(s) objKind, err := scheme.raw.ObjectKind(in.Object) if err != nil { return err } outVersion, err := unversioned.ParseGroupVersion(outGroupVersionString) if err != nil { return err } // Manufacture an object of this type and kind. outObj, err := scheme.New(outVersion.WithKind(objKind.Kind)) if err != nil { return err } // Manually do the conversion. err = s.Convert(in.Object, outObj, 0) if err != nil { return err } // Copy the kind field into the output object. err = s.Convert( &emptyPlugin{PluginBase: PluginBase{Kind: objKind.Kind}}, outObj, conversion.SourceToDest|conversion.IgnoreMissingFields|conversion.AllowDifferentFieldTypeNames, ) if err != nil { return err } // Because we provide the correct version, EncodeToVersion will not attempt a conversion. raw, err := scheme.EncodeToVersion(outObj, outVersion.String()) if err != nil { // TODO: if this fails, create an Unknown-- maybe some other // component will understand it. return err } out.RawJSON = raw return nil }
// Interpret will return the group,version,kind of the JSON wire-format // encoding of an object, or an error. func (SimpleMetaFactory) Interpret(data []byte) (unversioned.GroupVersionKind, error) { findKind := struct { APIVersion string `json:"apiVersion,omitempty"` Kind string `json:"kind,omitempty"` }{} err := json.Unmarshal(data, &findKind) if err != nil { return unversioned.GroupVersionKind{}, fmt.Errorf("couldn't get version/kind; json parse error: %v", err) } gv, err := unversioned.ParseGroupVersion(findKind.APIVersion) if err != nil { return unversioned.GroupVersionKind{}, fmt.Errorf("couldn't parse apiVersion: %v", err) } return gv.WithKind(findKind.Kind), nil }
// ClientConfig implements ClientConfig func (config DirectClientConfig) ClientConfig() (*client.Config, error) { if err := config.ConfirmUsable(); err != nil { return nil, err } configAuthInfo := config.getAuthInfo() configClusterInfo := config.getCluster() clientConfig := &client.Config{} clientConfig.Host = configClusterInfo.Server if u, err := url.ParseRequestURI(clientConfig.Host); err == nil && u.Opaque == "" && len(u.Path) > 1 { clientConfig.Prefix = u.Path u.Path = "" u.RawQuery = "" u.Fragment = "" clientConfig.Host = u.String() } if len(configClusterInfo.APIVersion) != 0 { gv, err := unversioned.ParseGroupVersion(configClusterInfo.APIVersion) if err != nil { return nil, err } clientConfig.GroupVersion = &gv } // only try to read the auth information if we are secure if client.IsConfigTransportTLS(*clientConfig) { var err error // mergo is a first write wins for map value and a last writing wins for interface values userAuthPartialConfig, err := getUserIdentificationPartialConfig(configAuthInfo, config.fallbackReader) if err != nil { return nil, err } mergo.Merge(clientConfig, userAuthPartialConfig) serverAuthPartialConfig, err := getServerIdentificationPartialConfig(configAuthInfo, configClusterInfo) if err != nil { return nil, err } mergo.Merge(clientConfig, serverAuthPartialConfig) } return clientConfig, nil }
func (unstructuredJSONScheme) DataKind(data []byte) (unversioned.GroupVersionKind, error) { obj := TypeMeta{} if err := json.Unmarshal(data, &obj); err != nil { return unversioned.GroupVersionKind{}, err } if len(obj.APIVersion) == 0 { return unversioned.GroupVersionKind{}, conversion.NewMissingVersionErr(string(data)) } if len(obj.Kind) == 0 { return unversioned.GroupVersionKind{}, conversion.NewMissingKindErr(string(data)) } gv, err := unversioned.ParseGroupVersion(obj.APIVersion) if err != nil { return unversioned.GroupVersionKind{}, err } return gv.WithKind(obj.Kind), 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). func (s *Scheme) ConvertToVersion(in interface{}, outGroupVersionString string) (interface{}, error) { 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) } gvks, ok := s.typeToGVK[t] if !ok { return nil, fmt.Errorf("%v cannot be converted into version %q", t, outGroupVersionString) } outVersion, err := unversioned.ParseGroupVersion(outGroupVersionString) if err != nil { return nil, err } outKind := outVersion.WithKind(gvks[0].Kind) inKind, err := s.ObjectKind(in) if err != nil { return nil, err } out, err := s.NewObject(outKind) if err != nil { return nil, err } flags, meta := s.generateConvertMeta(inKind.GroupVersion(), outVersion, in) if err := s.converter.Convert(in, out, flags, meta); err != nil { return nil, err } if err := s.SetVersionAndKind(outVersion.String(), outKind.Kind, out); err != nil { return nil, err } return out, nil }
func (s *Scheme) EncodeToVersionStream(obj interface{}, destGroupVersionString string, stream io.Writer) error { obj = maybeCopy(obj) v, _ := EnforcePtr(obj) // maybeCopy guarantees a pointer // Don't encode an object defined in the unversioned package, unless if the // destGroupVersionString is v1, encode it to v1 for backward compatibility. pkg := path.Base(v.Type().PkgPath()) if pkg == "unversioned" && destGroupVersionString != "v1" { // TODO: convert this to streaming too data, err := s.encodeUnversionedObject(obj) if err != nil { return err } _, err = stream.Write(data) return err } if _, registered := s.typeToGVK[v.Type()]; !registered { return fmt.Errorf("type %v is not registered for %q and it will be impossible to Decode it, therefore Encode will refuse to encode it.", v.Type(), destGroupVersionString) } objKind, err := s.ObjectKind(obj) if err != nil { return err } destVersion, err := unversioned.ParseGroupVersion(destGroupVersionString) if err != nil { return err } // Perform a conversion if necessary. if objKind.GroupVersion() != destVersion { objOut, err := s.NewObject(destVersion.WithKind(objKind.Kind)) if err != nil { return err } flags, meta := s.generateConvertMeta(objKind.GroupVersion(), destVersion, obj) err = s.converter.Convert(obj, objOut, flags, meta) if err != nil { return err } obj = objOut // ensure the output object name comes from the destination type newGroupVersionKind, err := s.ObjectKind(obj) if err != nil { return err } objKind.Kind = newGroupVersionKind.Kind } // Version and Kind should be set on the wire. err = s.SetVersionAndKind(destVersion.String(), objKind.Kind, obj) if err != nil { return err } // To add metadata, do some simple surgery on the JSON. encoder := json.NewEncoder(stream) if err := encoder.Encode(obj); err != nil { return err } // Version and Kind should be blank in memory. Reset them, since it's // possible that we modified a user object and not a copy above. err = s.SetVersionAndKind("", "", obj) if err != nil { return err } return nil }