Ejemplo n.º 1
0
// 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
}
Ejemplo n.º 2
0
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]
}
Ejemplo n.º 3
0
// 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
}
Ejemplo n.º 4
0
// 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
}
Ejemplo n.º 5
0
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)
}
Ejemplo n.º 6
0
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{}{}
		}
	}
}
Ejemplo n.º 7
0
// 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
}
Ejemplo n.º 8
0
// 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
}
Ejemplo n.º 9
0
// 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
}
Ejemplo n.º 10
0
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
}
Ejemplo n.º 11
0
// 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
}
Ejemplo n.º 12
0
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
}