func roundTrip(t *testing.T, codec runtime.Codec, item runtime.Object) { printer := spew.ConfigState{DisableMethods: true} name := reflect.TypeOf(item).Elem().Name() data, err := codec.Encode(item) if err != nil { t.Errorf("%v: %v (%s)", name, err, printer.Sprintf("%#v", item)) return } obj2, err := codec.Decode(data) if err != nil { t.Errorf("0: %v: %v\nCodec: %v\nData: %s\nSource: %#v", name, err, codec, string(data), printer.Sprintf("%#v", item)) return } if !api.Semantic.DeepEqual(item, obj2) { t.Errorf("1: %v: diff: %v\nCodec: %v\nData: %s\nSource: %#v\nFinal: %#v", name, util.ObjectGoPrintDiff(item, obj2), codec, string(data), printer.Sprintf("%#v", item), printer.Sprintf("%#v", obj2)) return } obj3 := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) err = codec.DecodeInto(data, obj3) if err != nil { t.Errorf("2: %v: %v", name, err) return } if !api.Semantic.DeepEqual(item, obj3) { t.Errorf("3: %v: diff: %v\nCodec: %v", name, util.ObjectDiff(item, obj3), codec) return } }
func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) { data, err := codec.Encode(obj) if err != nil { return "", err } return fmt.Sprintf("%x", md5.Sum(data)), nil }
func DoParseTest(t *testing.T, storage string, obj runtime.Object, codec runtime.Codec, p *Parser) { jsonData, _ := codec.Encode(obj) var tmp map[string]interface{} json.Unmarshal(jsonData, &tmp) yamlData, _ := yaml.Marshal(tmp) t.Logf("Intermediate yaml:\n%v\n", string(yamlData)) t.Logf("Intermediate json:\n%v\n", string(jsonData)) jsonGot, jsonErr := p.ToWireFormat(jsonData, storage, latest.Codec, codec) yamlGot, yamlErr := p.ToWireFormat(yamlData, storage, latest.Codec, codec) if jsonErr != nil { t.Errorf("json err: %#v", jsonErr) } if yamlErr != nil { t.Errorf("yaml err: %#v", yamlErr) } if string(jsonGot) != string(jsonData) { t.Errorf("json output didn't match:\nGot:\n%v\n\nWanted:\n%v\n", string(jsonGot), string(jsonData)) } if string(yamlGot) != string(jsonData) { t.Errorf("yaml parsed output didn't match:\nGot:\n%v\n\nWanted:\n%v\n", string(yamlGot), string(jsonData)) } }
// EncodeDeploymentConfig encodes config as a string using codec. func EncodeDeploymentConfig(config *deployapi.DeploymentConfig, codec runtime.Codec) (string, error) { if bytes, err := codec.Encode(config); err == nil { return string(bytes[:]), nil } else { return "", err } }
// writeJSON renders an object as JSON to the response. func writeJSON(statusCode int, codec runtime.Codec, object runtime.Object, w http.ResponseWriter) { output, err := codec.Encode(object) if err != nil { errorJSON(err, codec, w) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(statusCode) w.Write(output) }
// Object converts a watch.Event into an appropriately serializable JSON object func Object(codec runtime.Codec, event *watch.Event) (interface{}, error) { obj, ok := event.Object.(runtime.Object) if !ok { return nil, fmt.Errorf("The event object cannot be safely converted to JSON: %v", reflect.TypeOf(event.Object).Name()) } data, err := codec.Encode(obj) if err != nil { return nil, err } return &watchEvent{event.Type, runtime.RawExtension{json.RawMessage(data)}}, nil }
// errorJSONFatal renders an error to the response, and if codec fails will render plaintext func errorJSONFatal(err error, codec runtime.Codec, w http.ResponseWriter) { status := errToAPIStatus(err) output, err := codec.Encode(status) if err != nil { w.WriteHeader(status.Code) fmt.Fprintf(w, "%s: %s", status.Reason, status.Message) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(status.Code) w.Write(output) }
// ToWireFormat takes input 'data' as either json or yaml, checks that it parses as the // appropriate object type, and returns json for sending to the API or an error. func (p *Parser) ToWireFormat(data []byte, storage string, c runtime.Codec) ([]byte, error) { prototypeType, found := p.storageToType[storage] if !found { return nil, fmt.Errorf("unknown storage type: %v", storage) } obj := reflect.New(prototypeType).Interface().(runtime.Object) err := c.DecodeInto(data, obj) if err != nil { return nil, err } return c.Encode(obj) }
// errorJSONFatal renders an error to the response, and if codec fails will render plaintext. // Returns the HTTP status code of the error. func errorJSONFatal(err error, codec runtime.Codec, w http.ResponseWriter) int { util.HandleError(fmt.Errorf("apiserver was unable to write a JSON response: %v", err)) status := errToAPIStatus(err) output, err := codec.Encode(status) if err != nil { w.WriteHeader(status.Code) fmt.Fprintf(w, "%s: %s", status.Reason, status.Message) return status.Code } w.Header().Set("Content-Type", "application/json") w.WriteHeader(status.Code) w.Write(output) return status.Code }
func roundTrip(t *testing.T, codec runtime.Codec, originalItem runtime.Object) { // Make a copy of the originalItem to give to conversion functions // This lets us know if conversion messed with the input object deepCopy, err := api.Scheme.DeepCopy(originalItem) if err != nil { t.Errorf("Could not copy object: %v", err) return } item := deepCopy.(runtime.Object) name := reflect.TypeOf(item).Elem().Name() data, err := codec.Encode(item) if err != nil { if conversion.IsNotRegisteredError(err) { t.Logf("%v is not registered", name) return } t.Errorf("%v: %v (%#v)", name, err, item) return } obj2, err := codec.Decode(data) if err != nil { t.Errorf("0: %v: %v\nCodec: %v\nData: %s\nSource: %#v", name, err, codec, string(data), originalItem) return } if reflect.TypeOf(item) != reflect.TypeOf(obj2) { obj2conv := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) if err := api.Scheme.Convert(obj2, obj2conv); err != nil { t.Errorf("0X: no conversion from %v to %v: %v", reflect.TypeOf(item), reflect.TypeOf(obj2), err) return } obj2 = obj2conv } if !api.Semantic.DeepEqual(originalItem, obj2) { t.Errorf("1: %v: diff: %v\nCodec: %v\nData: %s\nSource: %s", name, util.ObjectDiff(originalItem, obj2), codec, string(data), util.ObjectGoPrintSideBySide(originalItem, obj2)) return } obj3 := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) err = codec.DecodeInto(data, obj3) if err != nil { t.Errorf("2: %v: %v", name, err) return } if !api.Semantic.DeepEqual(originalItem, obj3) { t.Errorf("3: %v: diff: %v\nCodec: %v", name, util.ObjectDiff(originalItem, obj3), codec) return } }
// writeJSON renders an object as JSON to the response. func writeJSON(statusCode int, codec runtime.Codec, object runtime.Object, w http.ResponseWriter) { output, err := codec.Encode(object) if err != nil { errorJSONFatal(err, codec, w) return } // PR #2243: Pretty-print JSON by default. formatted := &bytes.Buffer{} err = json.Indent(formatted, output, "", " ") if err != nil { errorJSONFatal(err, codec, w) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(statusCode) w.Write(formatted.Bytes()) }
func runTest(t *testing.T, codec runtime.Codec, source runtime.Object) { name := reflect.TypeOf(source).Elem().Name() apiObjectFuzzer.Fuzz(source) j, err := runtime.FindJSONBase(source) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, source) } j.SetKind("") j.SetAPIVersion("") data, err := codec.Encode(source) if err != nil { t.Errorf("%v: %v (%#v)", name, err, source) return } obj2, err := codec.Decode(data) if err != nil { t.Errorf("%v: %v", name, err) return } else { if !reflect.DeepEqual(source, obj2) { t.Errorf("1: %v: diff: %v", name, runtime.ObjectDiff(source, obj2)) return } } obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface().(runtime.Object) err = codec.DecodeInto(data, obj3) if err != nil { t.Errorf("2: %v: %v", name, err) return } else { if !reflect.DeepEqual(source, obj3) { t.Errorf("3: %v: diff: %v", name, runtime.ObjectDiff(source, obj3)) return } } }
// PatchResource returns a function that will handle a resource patch // TODO: Eventually PatchResource should just use AtomicUpdate and this routine should be a bit cleaner func PatchResource(r RESTPatcher, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, typer runtime.ObjectTyper, resource string, admit admission.Interface) 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 := namer.Name(req) if err != nil { errorJSON(err, codec, w) return } obj := r.New() // PATCH requires same permission as UPDATE err = admit.Admit(admission.NewAttributesRecord(obj, namespace, resource, "UPDATE")) if err != nil { errorJSON(err, codec, w) return } ctx := ctxFn(req) ctx = api.WithNamespace(ctx, namespace) original, err := r.Get(ctx, name) if err != nil { errorJSON(err, codec, w) return } originalObjJs, err := codec.Encode(original) if err != nil { errorJSON(err, codec, w) return } patchJs, err := readBody(req.Request) if err != nil { errorJSON(err, codec, w) return } patchedObjJs, err := jsonpatch.MergePatch(originalObjJs, patchJs) if err != nil { errorJSON(err, codec, w) return } if err := codec.DecodeInto(patchedObjJs, obj); err != nil { errorJSON(err, codec, w) return } if err := checkName(obj, name, namespace, namer); err != nil { errorJSON(err, codec, w) return } result, err := finishRequest(timeout, func() (runtime.Object, error) { // update should never create as previous get would fail obj, _, err := r.Update(ctx, obj) return obj, err }) if err != nil { errorJSON(err, codec, w) return } if err := setSelfLink(result, req, namer); err != nil { errorJSON(err, codec, w) return } writeJSON(http.StatusOK, codec, result, w) } }