// DecoderToVersion returns an decoder that does not do conversion. gv is ignored.
func (f DirectCodecFactory) DecoderToVersion(serializer runtime.Decoder, gv unversioned.GroupVersion) runtime.Decoder {
	return DirectCodec{
		runtime.NewCodec(nil, serializer),
		nil,
	}
}
Example #2
0
// PatchResource returns a function that will handle a resource patch
// TODO: Eventually PatchResource should just use GuaranteedUpdate and this routine should be a bit cleaner
func PatchResource(r rest.Patcher, scope RequestScope, typer runtime.ObjectTyper, admit admission.Interface, converter runtime.ObjectConvertor) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		// TODO: we either want to remove timeout or document it (if we
		// document, move timeout out of this function and declare it in
		// api_installer)
		timeout := parseTimeout(req.Request.URL.Query().Get("timeout"))

		namespace, name, err := scope.Namer.Name(req)
		if err != nil {
			scope.err(err, res.ResponseWriter, req.Request)
			return
		}

		ctx := scope.ContextFunc(req)
		ctx = api.WithNamespace(ctx, namespace)

		versionedObj, err := converter.ConvertToVersion(r.New(), scope.Kind.GroupVersion())
		if err != nil {
			scope.err(err, res.ResponseWriter, req.Request)
			return
		}

		// TODO: handle this in negotiation
		contentType := req.HeaderParameter("Content-Type")
		// Remove "; charset=" if included in header.
		if idx := strings.Index(contentType, ";"); idx > 0 {
			contentType = contentType[:idx]
		}
		patchType := api.PatchType(contentType)

		patchJS, err := readBody(req.Request)
		if err != nil {
			scope.err(err, res.ResponseWriter, req.Request)
			return
		}

		s, ok := scope.Serializer.SerializerForMediaType("application/json", nil)
		if !ok {
			scope.err(fmt.Errorf("no serializer defined for JSON"), res.ResponseWriter, req.Request)
			return
		}
		gv := scope.Kind.GroupVersion()
		codec := runtime.NewCodec(
			scope.Serializer.EncoderForVersion(s, gv),
			scope.Serializer.DecoderToVersion(s, unversioned.GroupVersion{Group: gv.Group, Version: runtime.APIVersionInternal}),
		)

		updateAdmit := func(updatedObject runtime.Object, currentObject runtime.Object) error {
			if admit != nil && admit.Handles(admission.Update) {
				userInfo, _ := api.UserFrom(ctx)
				return admit.Admit(admission.NewAttributesRecord(updatedObject, currentObject, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, userInfo))
			}

			return nil
		}

		result, err := patchResource(ctx, updateAdmit, timeout, versionedObj, r, name, patchType, patchJS, scope.Namer, scope.Copier, scope.Resource, codec)
		if err != nil {
			scope.err(err, res.ResponseWriter, req.Request)
			return
		}

		if err := setSelfLink(result, req, scope.Namer); err != nil {
			scope.err(err, res.ResponseWriter, req.Request)
			return
		}

		write(http.StatusOK, scope.Kind.GroupVersion(), scope.Serializer, result, w, req.Request)
	}

}
// EncoderForVersion returns an encoder that does not do conversion. gv is ignored.
func (f DirectCodecFactory) EncoderForVersion(serializer runtime.Encoder, gv unversioned.GroupVersion) runtime.Encoder {
	return DirectCodec{
		runtime.NewCodec(serializer, nil),
		f.CodecFactory.scheme,
	}
}
Example #4
0
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
	}

	// TODO: Validate flag usage against selected generator. More tricky since --expose was added.
	obj, err := generator.Generate(params)
	if err != nil {
		return nil, "", nil, nil, err
	}

	mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd))
	groupVersionKinds, _, err := typer.ObjectKinds(obj)
	if err != nil {
		return nil, "", nil, nil, err
	}
	groupVersionKind := groupVersionKinds[0]

	if len(overrides) > 0 {
		codec := runtime.NewCodec(f.JSONEncoder(), f.Decoder(true))
		obj, err = cmdutil.Merge(codec, obj, overrides, groupVersionKind.Kind)
		if err != nil {
			return nil, "", nil, nil, err
		}
	}

	mapping, err := mapper.RESTMapping(groupVersionKind.GroupKind(), groupVersionKind.Version)
	if err != nil {
		return nil, "", nil, nil, err
	}
	client, err := f.ClientForMapping(mapping)
	if err != nil {
		return nil, "", nil, nil, err
	}

	annotations, err := mapping.MetadataAccessor.Annotations(obj)
	if err != nil {
		return nil, "", nil, nil, err
	}
	if cmdutil.GetRecordFlag(cmd) || len(annotations[kubectl.ChangeCauseAnnotation]) > 0 {
		if err := cmdutil.RecordChangeCause(obj, f.Command()); err != nil {
			return nil, "", nil, nil, err
		}
	}
	if !cmdutil.GetDryRunFlag(cmd) {
		resourceMapper := &resource.Mapper{
			ObjectTyper:  typer,
			RESTMapper:   mapper,
			ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
			Decoder:      f.Decoder(true),
		}
		info, err := resourceMapper.InfoForObject(obj, nil)
		if err != nil {
			return nil, "", nil, nil, err
		}

		if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); 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, groupVersionKind.Kind, mapper, mapping, err
}