// roundTrip applies a single round-trip test to the given runtime object // using the given codec. The round-trip test ensures that an object can be // deep-copied and converted from internal -> versioned -> internal without // loss of data. func roundTrip(t *testing.T, codec runtime.Codec, item runtime.Object) { printer := spew.ConfigState{DisableMethods: true} original := item // deep copy the original object copied, err := api.Scheme.DeepCopy(item) if err != nil { panic(fmt.Sprintf("unable to copy: %v", err)) } item = copied.(runtime.Object) name := reflect.TypeOf(item).Elem().Name() // encode (serialize) the deep copy using the provided codec data, err := runtime.Encode(codec, item) if err != nil { if runtime.IsNotRegisteredError(err) { t.Logf("%v: not registered: %v (%s)", name, err, printer.Sprintf("%#v", item)) } else { t.Errorf("%v: %v (%s)", name, err, printer.Sprintf("%#v", item)) } return } // ensure that the deep copy is equal to the original; neither the deep // copy or conversion should alter the object if !api.Semantic.DeepEqual(original, item) { t.Errorf("0: %v: encode altered the object, diff: %v", name, diff.ObjectReflectDiff(original, item)) return } // decode (deserialize) the encoded data back into an object obj2, err := runtime.Decode(codec, data) if err != nil { t.Errorf("0: %v: %v\nCodec: %#v\nData: %s\nSource: %#v", name, err, codec, dataAsString(data), printer.Sprintf("%#v", item)) panic("failed") } // ensure that the object produced from decoding the encoded data is equal // to the original object if !api.Semantic.DeepEqual(original, obj2) { t.Errorf("\n1: %v: diff: %v\nCodec: %#v\nSource:\n\n%#v\n\nEncoded:\n\n%s\n\nFinal:\n\n%#v", name, diff.ObjectReflectDiff(item, obj2), codec, printer.Sprintf("%#v", item), dataAsString(data), printer.Sprintf("%#v", obj2)) return } // decode the encoded data into a new object (instead of letting the codec // create a new object) obj3 := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) if err := runtime.DecodeInto(codec, data, obj3); err != nil { t.Errorf("2: %v: %v", name, err) return } // ensure that the new runtime object is equal to the original after being // decoded into if !api.Semantic.DeepEqual(item, obj3) { t.Errorf("3: %v: diff: %v\nCodec: %#v", name, diff.ObjectReflectDiff(item, obj3), codec) return } }
// TestBadJSONRejection establishes that a JSON object without a kind or with // an unknown kind will not be decoded without error. func TestBadJSONRejection(t *testing.T) { badJSONMissingKind := []byte(`{ }`) if _, err := runtime.Decode(testapi.Default.Codec(), badJSONMissingKind); err == nil { t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind) } badJSONUnknownType := []byte(`{"kind": "bar"}`) if _, err1 := runtime.Decode(testapi.Default.Codec(), badJSONUnknownType); err1 == nil { t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType) } /*badJSONKindMismatch := []byte(`{"kind": "Pod"}`) if err2 := DecodeInto(badJSONKindMismatch, &Node{}); err2 == nil { t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch) }*/ }
func TestV1EncodeDecodeStatus(t *testing.T) { v1Codec := Default.Codec() encoded, err := runtime.Encode(v1Codec, status) if err != nil { t.Errorf("unexpected error: %v", err) } typeMeta := metav1.TypeMeta{} if err := json.Unmarshal(encoded, &typeMeta); err != nil { t.Errorf("unexpected error: %v", err) } if typeMeta.Kind != "Status" { t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded)) } if typeMeta.APIVersion != "v1" { t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded)) } decoded, err := runtime.Decode(v1Codec, encoded) if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(status, decoded) { t.Errorf("expected: %#v, got: %#v", status, decoded) } }
func (w *etcdWatcher) decodeObject(node *etcd.Node) (runtime.Object, error) { if obj, found := w.cache.getFromCache(node.ModifiedIndex, storage.SimpleFilter(storage.Everything)); found { return obj, nil } obj, err := runtime.Decode(w.encoding, []byte(node.Value)) if err != nil { return nil, err } // ensure resource version is set on the object we load from etcd if err := w.versioner.UpdateObject(obj, node.ModifiedIndex); err != nil { utilruntime.HandleError(fmt.Errorf("failure to version api object (%d) %#v: %v", node.ModifiedIndex, obj, err)) } // perform any necessary transformation if w.transform != nil { obj, err = w.transform(obj) if err != nil { utilruntime.HandleError(fmt.Errorf("failure to transform api object %#v: %v", obj, err)) return nil, err } } if node.ModifiedIndex != 0 { w.cache.addToCache(node.ModifiedIndex, obj) } return obj, nil }
func validate(testParam TestParam, t *testing.T, body []byte, fakeHandler *utiltesting.FakeHandler) { switch { case testParam.expectingError && testParam.actualError == nil: t.Errorf("Expected error") case !testParam.expectingError && testParam.actualError != nil: t.Error(testParam.actualError) } if !testParam.expCreated { if testParam.actualCreated { t.Errorf("Expected object not to be created") } } statusOut, err := runtime.Decode(testapi.Default.Codec(), body) if testParam.testBody { if testParam.testBodyErrorIsNotNil { if err == nil { t.Errorf("Expected Error") } } } if testParam.expStatus != nil { if !reflect.DeepEqual(testParam.expStatus, statusOut) { t.Errorf("Unexpected mis-match. Expected %#v. Saw %#v", testParam.expStatus, statusOut) } } fakeHandler.ValidateRequest(t, "/"+api.Registry.GroupOrDie(api.GroupName).GroupVersion.String()+"/test", "GET", nil) }
// TestUnversionedTypes establishes that the default codec can encode and // decode unversioned objects. func TestUnversionedTypes(t *testing.T) { testcases := []runtime.Object{ &metav1.Status{Status: "Failure", Message: "something went wrong"}, &metav1.APIVersions{Versions: []string{"A", "B", "C"}}, &metav1.APIGroupList{Groups: []metav1.APIGroup{{Name: "mygroup"}}}, &metav1.APIGroup{Name: "mygroup"}, &metav1.APIResourceList{GroupVersion: "mygroup/myversion"}, } for _, obj := range testcases { // Make sure the unversioned codec can encode unversionedJSON, err := runtime.Encode(testapi.Default.Codec(), obj) if err != nil { t.Errorf("%v: unexpected error: %v", obj, err) continue } // Make sure the versioned codec under test can decode versionDecodedObject, err := runtime.Decode(testapi.Default.Codec(), unversionedJSON) if err != nil { t.Errorf("%v: unexpected error: %v", obj, err) continue } // Make sure it decodes correctly if !reflect.DeepEqual(obj, versionDecodedObject) { t.Errorf("%v: expected %#v, got %#v", obj, obj, versionDecodedObject) continue } } }
// TestEncodePtr tests that a pointer to a golang type can be encoded and // decoded without information loss or mutation. func TestEncodePtr(t *testing.T) { grace := int64(30) pod := &api.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{"name": "foo"}, }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, SecurityContext: &api.PodSecurityContext{}, SchedulerName: api.DefaultSchedulerName, }, } obj := runtime.Object(pod) data, err := runtime.Encode(testapi.Default.Codec(), obj) obj2, err2 := runtime.Decode(testapi.Default.Codec(), data) if err != nil || err2 != nil { t.Fatalf("Failure: '%v' '%v'", err, err2) } if _, ok := obj2.(*api.Pod); !ok { t.Fatalf("Got wrong type") } if !api.Semantic.DeepEqual(obj2, pod) { t.Errorf("\nExpected:\n\n %#v,\n\nGot:\n\n %#vDiff: %v\n\n", pod, obj2, diff.ObjectDiff(obj2, pod)) } }
func verifyObjects(t *testing.T, expected, actual []runtime.Object) { var actualObj runtime.Object var err error if len(actual) != len(expected) { t.Fatal(actual) } for i, obj := range actual { switch obj.(type) { case runtime.Unstructured, *runtime.Unknown: actualObj, err = runtime.Decode( api.Codecs.UniversalDecoder(), []byte(runtime.EncodeOrDie(api.Codecs.LegacyCodec(), obj))) default: actualObj = obj err = nil } if err != nil { t.Fatal(err) } if !api.Semantic.DeepEqual(expected[i], actualObj) { t.Errorf("unexpected object: \n%#v\n%#v", expected[i], actualObj) } } }
func tryDecodePodList(data []byte, defaultFn defaultFunc) (parsed bool, pods v1.PodList, err error) { obj, err := runtime.Decode(api.Codecs.UniversalDecoder(), data) if err != nil { return false, pods, err } // Check whether the object could be converted to list of pods. if _, ok := obj.(*api.PodList); !ok { err = fmt.Errorf("invalid pods list: %#v", obj) return false, pods, err } newPods := obj.(*api.PodList) // Apply default values and validate pods. for i := range newPods.Items { newPod := &newPods.Items[i] if err = defaultFn(newPod); err != nil { return true, pods, err } if errs := validation.ValidatePod(newPod); len(errs) > 0 { err = fmt.Errorf("invalid pod: %v", errs) return true, pods, err } } v1Pods := &v1.PodList{} if err := v1.Convert_api_PodList_To_v1_PodList(newPods, v1Pods, nil); err != nil { return true, pods, err } return true, *v1Pods, err }
func tryDecodeSinglePod(data []byte, defaultFn defaultFunc) (parsed bool, pod *v1.Pod, err error) { // JSON is valid YAML, so this should work for everything. json, err := utilyaml.ToJSON(data) if err != nil { return false, nil, err } obj, err := runtime.Decode(api.Codecs.UniversalDecoder(), json) if err != nil { return false, pod, err } // Check whether the object could be converted to single pod. if _, ok := obj.(*api.Pod); !ok { err = fmt.Errorf("invalid pod: %#v", obj) return false, pod, err } newPod := obj.(*api.Pod) // Apply default values and validate the pod. if err = defaultFn(newPod); err != nil { return true, pod, err } if errs := validation.ValidatePod(newPod); len(errs) > 0 { err = fmt.Errorf("invalid pod: %v", errs) return true, pod, err } v1Pod := &v1.Pod{} if err := v1.Convert_api_Pod_To_v1_Pod(newPod, v1Pod, nil); err != nil { return true, nil, err } return true, v1Pod, nil }
func runTest(t *testing.T, source interface{}) { name := reflect.TypeOf(source).Elem().Name() TestObjectFuzzer.Fuzz(source) _, codec := GetTestScheme() data, err := runtime.Encode(codec, source.(runtime.Object)) if err != nil { t.Errorf("%v: %v (%#v)", name, err, source) return } obj2, err := runtime.Decode(codec, data) if err != nil { t.Errorf("%v: %v (%v)", name, err, string(data)) return } if !semantic.DeepEqual(source, obj2) { t.Errorf("1: %v: diff: %v", name, diff.ObjectGoPrintSideBySide(source, obj2)) return } obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface() if err := runtime.DecodeInto(codec, data, obj3.(runtime.Object)); err != nil { t.Errorf("2: %v: %v", name, err) return } if !semantic.DeepEqual(source, obj3) { t.Errorf("3: %v: diff: %v", name, diff.ObjectDiff(source, obj3)) return } }
func TestExperimentalEncodeDecodeStatus(t *testing.T) { status := &metav1.Status{ Status: metav1.StatusFailure, Code: 200, Reason: metav1.StatusReasonUnknown, Message: "", } // TODO: caesarxuchao: use the testapi.Extensions.Codec() once the PR that // moves experimental from v1 to v1beta1 got merged. expCodec := api.Codecs.LegacyCodec(extensions.SchemeGroupVersion) encoded, err := runtime.Encode(expCodec, status) if err != nil { t.Errorf("unexpected error: %v", err) } typeMeta := metav1.TypeMeta{} if err := json.Unmarshal(encoded, &typeMeta); err != nil { t.Errorf("unexpected error: %v", err) } if typeMeta.Kind != "Status" { t.Errorf("Kind is not set to \"Status\". Got %s", encoded) } if typeMeta.APIVersion != "v1" { t.Errorf("APIVersion is not set to \"\". Got %s", encoded) } decoded, err := runtime.Decode(expCodec, encoded) if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(status, decoded) { t.Errorf("expected: %v, got: %v", status, decoded) } }
func TestV1EncodeDecodeStatus(t *testing.T) { status := &metav1.Status{ Status: metav1.StatusFailure, Code: 200, Reason: metav1.StatusReasonUnknown, Message: "", } v1Codec := testapi.Default.Codec() encoded, err := runtime.Encode(v1Codec, status) if err != nil { t.Errorf("unexpected error: %v", err) } typeMeta := metav1.TypeMeta{} if err := json.Unmarshal(encoded, &typeMeta); err != nil { t.Errorf("unexpected error: %v", err) } if typeMeta.Kind != "Status" { t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded)) } if typeMeta.APIVersion != "v1" { t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded)) } decoded, err := runtime.Decode(v1Codec, encoded) if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(status, decoded) { t.Errorf("expected: %v, got: %v", status, decoded) } }
func TestExternalToInternalMapping(t *testing.T) { internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} externalGV := schema.GroupVersion{Group: "test.group", Version: "testExternal"} scheme := runtime.NewScheme() scheme.AddKnownTypeWithName(internalGV.WithKind("OptionalExtensionType"), &InternalOptionalExtensionType{}) scheme.AddKnownTypeWithName(externalGV.WithKind("OptionalExtensionType"), &ExternalOptionalExtensionType{}) codec := serializer.NewCodecFactory(scheme).LegacyCodec(externalGV) table := []struct { obj runtime.Object encoded string }{ { &InternalOptionalExtensionType{Extension: nil}, `{"kind":"OptionalExtensionType","apiVersion":"` + externalGV.String() + `"}`, }, } for i, item := range table { gotDecoded, err := runtime.Decode(codec, []byte(item.encoded)) if err != nil { t.Errorf("unexpected error '%v' (%v)", err, item.encoded) } else if e, a := item.obj, gotDecoded; !reflect.DeepEqual(e, a) { t.Errorf("%d: unexpected objects:\n%s", i, diff.ObjectGoPrintSideBySide(e, a)) } } }
func TestGetMultipleTypeObjectsAsList(t *testing.T) { pods, svc, _ := testData() f, tf, codec, _ := cmdtesting.NewAPIFactory() tf.Printer = &testPrinter{} tf.Client = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { switch req.URL.Path { case "/namespaces/test/pods": return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil case "/namespaces/test/services": return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } }), } tf.Namespace = "test" tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion}} buf := bytes.NewBuffer([]byte{}) errBuf := bytes.NewBuffer([]byte{}) cmd := NewCmdGet(f, buf, errBuf) cmd.SetOutput(buf) cmd.Flags().Set("output", "json") cmd.Run(cmd, []string{"pods,services"}) if tf.Printer.(*testPrinter).Objects != nil { t.Errorf("unexpected print to default printer") } out, err := runtime.Decode(codec, buf.Bytes()) if err != nil { t.Fatalf("unexpected error: %v", err) } list, err := meta.ExtractList(out) if err != nil { t.Fatalf("unexpected error: %v", err) } if errs := runtime.DecodeList(list, codec); len(errs) > 0 { t.Fatalf("unexpected error: %v", errs) } if err := meta.SetList(out, list); err != nil { t.Fatalf("unexpected error: %v", err) } expected := &api.List{ Items: []runtime.Object{ &pods.Items[0], &pods.Items[1], &svc.Items[0], }, } if !reflect.DeepEqual(expected, out) { t.Errorf("unexpected output: %#v", out) } }
// ReadAdmissionConfiguration reads the admission configuration at the specified path. // It returns the loaded admission configuration if the input file aligns with the required syntax. // If it does not align with the provided syntax, it returns a default configuration for the enumerated // set of pluginNames whose config location references the specified configFilePath. // It does this to preserve backward compatibility when admission control files were opaque. // It returns an error if the file did not exist. func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (admission.ConfigProvider, error) { if configFilePath == "" { return configProvider{config: &componentconfig.AdmissionConfiguration{}}, nil } // a file was provided, so we just read it. data, err := ioutil.ReadFile(configFilePath) if err != nil { return nil, fmt.Errorf("unable to read admission control configuration from %q [%v]", configFilePath, err) } decoder := api.Codecs.UniversalDecoder() decodedObj, err := runtime.Decode(decoder, data) // we were able to decode the file successfully if err == nil { decodedConfig, ok := decodedObj.(*componentconfig.AdmissionConfiguration) if !ok { return nil, fmt.Errorf("unexpected type: %T", decodedObj) } baseDir := path.Dir(configFilePath) for i := range decodedConfig.Plugins { if decodedConfig.Plugins[i].Path == "" { continue } // we update relative file paths to absolute paths absPath, err := makeAbs(decodedConfig.Plugins[i].Path, baseDir) if err != nil { return nil, err } decodedConfig.Plugins[i].Path = absPath } return configProvider{config: decodedConfig}, nil } // we got an error where the decode wasn't related to a missing type if !(runtime.IsMissingVersion(err) || runtime.IsMissingKind(err) || runtime.IsNotRegisteredError(err)) { return nil, err } // convert the legacy format to the new admission control format // in order to preserve backwards compatibility, we set plugins that // previously read input from a non-versioned file configuration to the // current input file. legacyPluginsWithUnversionedConfig := sets.NewString("ImagePolicyWebhook", "PodNodeSelector") externalConfig := &componentconfigv1alpha1.AdmissionConfiguration{} for _, pluginName := range pluginNames { if legacyPluginsWithUnversionedConfig.Has(pluginName) { externalConfig.Plugins = append(externalConfig.Plugins, componentconfigv1alpha1.AdmissionPluginConfiguration{ Name: pluginName, Path: configFilePath}) } } api.Scheme.Default(externalConfig) internalConfig := &componentconfig.AdmissionConfiguration{} if err := api.Scheme.Convert(externalConfig, internalConfig, nil); err != nil { return nil, err } return configProvider{config: internalConfig}, nil }
func TestBadJSONRejection(t *testing.T) { scheme := runtime.NewScheme() codecs := serializer.NewCodecFactory(scheme) info, _ := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) jsonserializer := info.Serializer badJSONMissingKind := []byte(`{ }`) if _, err := runtime.Decode(jsonserializer, badJSONMissingKind); err == nil { t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind) } badJSONUnknownType := []byte(`{"kind": "bar"}`) if _, err1 := runtime.Decode(jsonserializer, badJSONUnknownType); err1 == nil { t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType) } /*badJSONKindMismatch := []byte(`{"kind": "Pod"}`) if err2 := DecodeInto(badJSONKindMismatch, &Node{}); err2 == nil { t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch) }*/ }
func decodeObj(codec runtime.Codec, versioner storage.Versioner, data []byte, rev int64) (runtime.Object, error) { obj, err := runtime.Decode(codec, []byte(data)) if err != nil { return nil, err } // ensure resource version is set on the object we load from etcd if err := versioner.UpdateObject(obj, uint64(rev)); err != nil { return nil, fmt.Errorf("failure to version api object (%d) %#v: %v", rev, obj, err) } return obj, nil }
// roundTripOrDie round trips an object to get defaults set. func roundTripOrDie(codec runtime.Codec, object runtime.Object) runtime.Object { data, err := runtime.Encode(codec, object) if err != nil { panic(err) } obj, err := runtime.Decode(codec, data) if err != nil { panic(err) } return obj }
func TestWatchWebsocket(t *testing.T) { simpleStorage := &SimpleRESTStorage{} _ = rest.Watcher(simpleStorage) // Give compile error if this doesn't work. handler := handle(map[string]rest.Storage{"simples": simpleStorage}) server := httptest.NewServer(handler) defer server.Close() dest, _ := url.Parse(server.URL) dest.Scheme = "ws" // Required by websocket, though the server never sees it. dest.Path = "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/simples" dest.RawQuery = "" ws, err := websocket.Dial(dest.String(), "", "http://localhost") if err != nil { t.Fatalf("unexpected error: %v", err) } try := func(action watch.EventType, object runtime.Object) { // Send simpleStorage.fakeWatch.Action(action, object) // Test receive var got watchJSON err := websocket.JSON.Receive(ws, &got) if err != nil { t.Fatalf("Unexpected error: %v", err) } if got.Type != action { t.Errorf("Unexpected type: %v", got.Type) } gotObj, err := runtime.Decode(codec, got.Object) if err != nil { t.Fatalf("Decode error: %v\n%v", err, got) } if _, err := api.GetReference(gotObj); err != nil { t.Errorf("Unable to construct reference: %v", err) } if e, a := object, gotObj; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, got %#v", e, a) } } for _, item := range watchTestTable { try(item.t, item.obj) } simpleStorage.fakeWatch.Stop() var got watchJSON err = websocket.JSON.Receive(ws, &got) if err == nil { t.Errorf("Unexpected non-error") } }
// check if the object is unstructured. If so, let's attempt to convert it to a type we can understand. func DecodeUnknownObject(obj runtime.Object) (runtime.Object, error) { var err error switch obj.(type) { case runtime.Unstructured, *runtime.Unknown: if objBytes, err := runtime.Encode(api.Codecs.LegacyCodec(), obj); err == nil { if decodedObj, err := runtime.Decode(api.Codecs.UniversalDecoder(), objBytes); err == nil { obj = decodedObj } } } return obj, err }
func TestBadJSONRejection(t *testing.T) { log.SetOutput(os.Stderr) _, codec := GetTestScheme() badJSONs := [][]byte{ []byte(`{"myVersionKey":"v1"}`), // Missing kind []byte(`{"myVersionKey":"v1","myKindKey":"bar"}`), // Unknown kind []byte(`{"myVersionKey":"bar","myKindKey":"TestType1"}`), // Unknown version []byte(`{"myKindKey":"TestType1"}`), // Missing version } for _, b := range badJSONs { if _, err := runtime.Decode(codec, b); err == nil { t.Errorf("Did not reject bad json: %s", string(b)) } } badJSONKindMismatch := []byte(`{"myVersionKey":"v1","myKindKey":"ExternalInternalSame"}`) if err := runtime.DecodeInto(codec, badJSONKindMismatch, &TestType1{}); err == nil { t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch) } if err := runtime.DecodeInto(codec, []byte(``), &TestType1{}); err != nil { t.Errorf("Should allow empty decode: %v", err) } if _, _, err := codec.Decode([]byte(``), &schema.GroupVersionKind{Kind: "ExternalInternalSame"}, nil); err == nil { t.Errorf("Did not give error for empty data with only kind default") } if _, _, err := codec.Decode([]byte(`{"myVersionKey":"v1"}`), &schema.GroupVersionKind{Kind: "ExternalInternalSame"}, nil); err != nil { t.Errorf("Gave error for version and kind default") } if _, _, err := codec.Decode([]byte(`{"myKindKey":"ExternalInternalSame"}`), &schema.GroupVersionKind{Version: "v1"}, nil); err != nil { t.Errorf("Gave error for version and kind default") } if _, _, err := codec.Decode([]byte(``), &schema.GroupVersionKind{Kind: "ExternalInternalSame", Version: "v1"}, nil); err != nil { t.Errorf("Gave error for version and kind defaulted: %v", err) } if _, err := runtime.Decode(codec, []byte(``)); err == nil { t.Errorf("Did not give error for empty data") } }
func TestEncode_Ptr(t *testing.T) { _, codec := GetTestScheme() tt := &TestType1{A: "I am a pointer object"} data, err := runtime.Encode(codec, tt) obj2, err2 := runtime.Decode(codec, data) if err != nil || err2 != nil { t.Fatalf("Failure: '%v' '%v'\n%s", err, err2, data) } if _, ok := obj2.(*TestType1); !ok { t.Fatalf("Got wrong type") } if !semantic.DeepEqual(obj2, tt) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", tt, obj2) } }
// Merge requires JSON serialization // TODO: merge assumes JSON serialization, and does not properly abstract API retrieval func Merge(codec runtime.Codec, dst runtime.Object, fragment, kind string) (runtime.Object, error) { // encode dst into versioned json and apply fragment directly too it target, err := runtime.Encode(codec, dst) if err != nil { return nil, err } patched, err := jsonpatch.MergePatch(target, []byte(fragment)) if err != nil { return nil, err } out, err := runtime.Decode(codec, patched) if err != nil { return nil, err } return out, nil }
// TestSerializer makes sure that you're always able to decode an unversioned API object func TestSerializer(t *testing.T) { contentConfig := ContentConfig{ ContentType: "application/json", GroupVersion: &schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}, NegotiatedSerializer: api.Codecs, } serializer, err := createSerializers(contentConfig) if err != nil { t.Fatal(err) } // bytes based on actual return from API server when encoding an "unversioned" object obj, err := runtime.Decode(serializer.Decoder, []byte(`{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Success"}`)) t.Log(obj) if err != nil { t.Fatal(err) } }
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { data, err := runtime.Encode(api.Codecs.LegacyCodec(SchemeGroupVersion), obj) if err != nil { t.Errorf("%v\n %#v", err, obj) return nil } obj2, err := runtime.Decode(api.Codecs.UniversalDecoder(), data) if err != nil { t.Errorf("%v\nData: %s\nSource: %#v", err, string(data), obj) return nil } obj3 := reflect.New(reflect.TypeOf(obj).Elem()).Interface().(runtime.Object) err = api.Scheme.Convert(obj2, obj3, nil) if err != nil { t.Errorf("%v\nSource: %#v", err, obj2) return nil } return obj3 }
// Decode blocks until it can return the next object in the reader. Returns an error // if the reader is closed or an object can't be decoded. func (d *Decoder) Decode() (watch.EventType, runtime.Object, error) { var got metav1.WatchEvent res, _, err := d.decoder.Decode(nil, &got) if err != nil { return "", nil, err } if res != &got { return "", nil, fmt.Errorf("unable to decode to metav1.Event") } switch got.Type { case string(watch.Added), string(watch.Modified), string(watch.Deleted), string(watch.Error): default: return "", nil, fmt.Errorf("got invalid watch event type: %v", got.Type) } obj, err := runtime.Decode(d.embeddedDecoder, got.Object.Raw) if err != nil { return "", nil, fmt.Errorf("unable to decode watch event: %v", err) } return watch.EventType(got.Type), obj, nil }
func BenchmarkDecodeCodec(b *testing.B) { codec := testapi.Default.Codec() items := benchmarkItems() width := len(items) encoded := make([][]byte, width) for i := range items { data, err := runtime.Encode(codec, &items[i]) if err != nil { b.Fatal(err) } encoded[i] = data } b.ResetTimer() for i := 0; i < b.N; i++ { if _, err := runtime.Decode(codec, encoded[i%width]); err != nil { b.Fatal(err) } } b.StopTimer() }
func TestConvertTypesWhenDefaultNamesMatch(t *testing.T) { internalGV := schema.GroupVersion{Version: runtime.APIVersionInternal} externalGV := schema.GroupVersion{Version: "v1"} s := runtime.NewScheme() // create two names internally, with TestType1 being preferred s.AddKnownTypeWithName(internalGV.WithKind("TestType1"), &TestType1{}) s.AddKnownTypeWithName(internalGV.WithKind("OtherType1"), &TestType1{}) // create two names externally, with TestType1 being preferred s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &ExternalTestType1{}) s.AddKnownTypeWithName(externalGV.WithKind("OtherType1"), &ExternalTestType1{}) ext := &ExternalTestType1{} ext.APIVersion = "v1" ext.ObjectKind = "OtherType1" ext.A = "test" data, err := json.Marshal(ext) if err != nil { t.Fatalf("unexpected error: %v", err) } expect := &TestType1{A: "test"} codec := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})).LegacyCodec(schema.GroupVersion{Version: "v1"}) obj, err := runtime.Decode(codec, data) if err != nil { t.Fatalf("unexpected error: %v", err) } if !semantic.DeepEqual(expect, obj) { t.Errorf("unexpected object: %#v", obj) } into := &TestType1{} if err := runtime.DecodeInto(codec, data, into); err != nil { t.Fatalf("unexpected error: %v", err) } if !semantic.DeepEqual(expect, into) { t.Errorf("unexpected object: %#v", obj) } }
func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jsonpath.JSONPath, out io.Writer) error { columns := make([]string, len(parsers)) switch u := obj.(type) { case *runtime.Unknown: if len(u.Raw) > 0 { var err error if obj, err = runtime.Decode(s.Decoder, u.Raw); err != nil { return fmt.Errorf("can't decode object for printing: %v (%s)", err, u.Raw) } } } for ix := range parsers { parser := parsers[ix] var values [][]reflect.Value var err error if unstructured, ok := obj.(runtime.Unstructured); ok { values, err = parser.FindResults(unstructured.UnstructuredContent()) } else { values, err = parser.FindResults(reflect.ValueOf(obj).Elem().Interface()) } if err != nil { return err } if len(values) == 0 || len(values[0]) == 0 { fmt.Fprintf(out, "<none>\t") } valueStrings := []string{} for arrIx := range values { for valIx := range values[arrIx] { valueStrings = append(valueStrings, fmt.Sprintf("%v", values[arrIx][valIx].Interface())) } } columns[ix] = strings.Join(valueStrings, ",") } fmt.Fprintln(out, strings.Join(columns, "\t")) return nil }