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 }
// 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 }
// NewObject returns a new object of the given version and name, // or an error if it hasn't been registered. func (s *Scheme) NewObject(gvString, kind string) (interface{}, error) { gv, err := unversioned.ParseGroupVersion(gvString) if err != nil { return nil, err } gvk := gv.WithKind(kind) if t, exists := s.gvkToType[gvk]; exists { return reflect.New(t).Interface(), nil } return nil, ¬RegisteredErr{gvk: gvk} }
// 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 }
// runtimeObjectToRawExtensionArray takes a list of objects and encodes them as RawExtension in the output version // defined by the conversion.Scope. If objects must be encoded to different schema versions than the default, you // should encode them yourself with runtime.Unknown, or convert the object prior to invoking conversion. Objects // outside of the current scheme must be added as runtime.Unknown. func (self *Scheme) runtimeObjectToRawExtensionArray(in *[]Object, out *[]RawExtension, s conversion.Scope) error { src := *in dest := make([]RawExtension, len(src)) _, outVersion, scheme := self.fromScope(s) for i := range src { switch t := src[i].(type) { case *Unknown: // TODO: this should be decoupled from the scheme (since it is JSON specific) dest[i].RawJSON = t.RawJSON case *Unstructured: // TODO: this should be decoupled from the scheme (since it is JSON specific) data, err := json.Marshal(t.Object) if err != nil { return err } dest[i].RawJSON = data default: version := outVersion // if the object exists // this code is try to set the outputVersion, but only if the object has a non-internal group version if inGVString, _, err := scheme.ObjectVersionAndKind(src[i]); err == nil && len(inGVString) != 0 { inGV, err := unversioned.ParseGroupVersion(inGVString) if err != nil { return err } if self.raw.InternalVersions[inGV.Group] != inGV { version = inGV.String() } } data, err := scheme.EncodeToVersion(src[i], version) if err != nil { return err } dest[i].RawJSON = data } } *out = dest return nil }
func init() { validGroupVersions := map[unversioned.GroupVersion]bool{ unversioned.GroupVersion{Group: "", Version: "v1"}: true, unversioned.GroupVersion{Group: "extensions", Version: "v1beta1"}: true, unversioned.GroupVersion{Group: "componentconfig", Version: "v1alpha1"}: true, unversioned.GroupVersion{Group: "metrics", Version: "v1alpha1"}: true, } // The default list of supported api versions, in order of most preferred to the least. supportedVersions := []unversioned.GroupVersion{ {Group: "", Version: "v1"}, {Group: "extensions", Version: "v1beta1"}, {Group: "componentconfig", Version: "v1alpha1"}, } // Env var KUBE_API_VERSIONS is a comma separated list of API versions that should be registered in the scheme. // The versions should be in the order of most preferred to the least. userRequestedVersions := os.Getenv("KUBE_API_VERSIONS") if len(userRequestedVersions) != 0 { // reset the supported versions supportedVersions = []unversioned.GroupVersion{} for _, version := range strings.Split(userRequestedVersions, ",") { gv, err := unversioned.ParseGroupVersion(version) if err != nil { glog.Fatalf("invalid api version: %s in KUBE_API_VERSIONS: %s. List of valid API versions: %v", version, os.Getenv("KUBE_API_VERSIONS"), validGroupVersions) } // Verify that the version is valid. valid, ok := validGroupVersions[gv] if !ok || !valid { // Not a valid API version. glog.Fatalf("invalid api version: %s in KUBE_API_VERSIONS: %s. List of valid API versions: %v", version, os.Getenv("KUBE_API_VERSIONS"), validGroupVersions) } supportedVersions = append(supportedVersions, gv) } } RegisteredGroupVersions = supportedVersions }
// DecodeToVersion converts a JSON string back into a pointer to an api object. // Deduces the type based upon the fields added by the MetaInsertionFactory // technique. The object will be converted, if necessary, into the versioned // type before being returned. Decode will not decode objects without version // set unless version is also "". // a GroupVersion with .IsEmpty() == true is means "use the internal version for // the object's group" func (s *Scheme) DecodeToVersion(data []byte, gv unversioned.GroupVersion) (interface{}, error) { obj, sourceVersion, kind, err := s.DecodeToVersionedObject(data) if err != nil { return nil, err } // Version and Kind should be blank in memory. if err := s.SetVersionAndKind("", "", obj); err != nil { return nil, err } sourceGV, err := unversioned.ParseGroupVersion(sourceVersion) if err != nil { return nil, err } // if the gv is empty, then we want the internal version, but the internal version varies by // group. We can lookup the group now because we have knowledge of the group if gv.IsEmpty() { exists := false gv, exists = s.InternalVersions[sourceGV.Group] if !exists { return nil, fmt.Errorf("no internalVersion specified for %v", gv) } } // Convert if needed. if gv != sourceGV { objOut, err := s.NewObject(gv.String(), kind) if err != nil { return nil, err } flags, meta := s.generateConvertMeta(sourceVersion, gv.String(), obj) if err := s.converter.Convert(obj, objOut, flags, meta); err != nil { return nil, err } obj = objOut } return obj, nil }