func TestDecodeToMetadataOnlyObject(t *testing.T) { data := getPodJson(t) cf := serializer.DirectCodecFactory{CodecFactory: NewMetadataCodecFactory()} info, ok := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON) if !ok { t.Fatalf("expected to get a JSON serializer") } codec := cf.DecoderToVersion(info.Serializer, unversioned.GroupVersion{Group: "SOMEGROUP", Version: "SOMEVERSION"}) // decode with into into := &MetadataOnlyObject{} ret, _, err := codec.Decode(data, nil, into) if err != nil { t.Fatal(err) } metaOnly, ok := ret.(*MetadataOnlyObject) if !ok { t.Fatalf("expected ret to be *runtime.MetadataOnlyObject") } verfiyMetadata("check returned metaonly with into", t, metaOnly) verfiyMetadata("check into", t, into) // decode without into ret, _, err = codec.Decode(data, nil, nil) if err != nil { t.Fatal(err) } metaOnly, ok = ret.(*MetadataOnlyObject) if !ok { t.Fatalf("expected ret to be *runtime.MetadataOnlyObject") } verfiyMetadata("check returned metaonly without into", t, metaOnly) }
func (c *RESTClient) request(verb string) *restclient.Request { config := restclient.ContentConfig{ ContentType: runtime.ContentTypeJSON, GroupVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion, NegotiatedSerializer: c.NegotiatedSerializer, } groupName := api.GroupName if c.GroupName != "" { groupName = c.GroupName } ns := c.NegotiatedSerializer info, _ := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), runtime.ContentTypeJSON) internalVersion := unversioned.GroupVersion{ Group: registered.GroupOrDie(groupName).GroupVersion.Group, Version: runtime.APIVersionInternal, } internalVersion.Version = runtime.APIVersionInternal serializers := restclient.Serializers{ Encoder: ns.EncoderForVersion(info.Serializer, registered.GroupOrDie(api.GroupName).GroupVersion), Decoder: ns.DecoderToVersion(info.Serializer, internalVersion), } if info.StreamSerializer != nil { serializers.StreamingSerializer = info.StreamSerializer.Serializer serializers.Framer = info.StreamSerializer.Framer } return restclient.NewRequest(c, verb, &url.URL{Host: "localhost"}, "", config, serializers, nil, nil) }
// Get codec based on runtime.Object func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) { kinds, _, err := api.Scheme.ObjectKinds(obj) if err != nil { return nil, fmt.Errorf("unexpected encoding error: %v", err) } kind := kinds[0] for _, group := range Groups { if group.GroupVersion().Group != kind.Group { continue } if api.Scheme.Recognizes(kind) { return group.Codec(), nil } } // Codec used for unversioned types if api.Scheme.Recognizes(kind) { serializer, ok := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) if !ok { return nil, fmt.Errorf("no serializer registered for json") } return serializer.Serializer, nil } return nil, fmt.Errorf("unexpected kind: %v", kind) }
func TestDirectCodec(t *testing.T) { s := GetDirectCodecTestScheme() cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})) info, _ := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON) serializer := info.Serializer df := DirectCodecFactory{cf} ignoredGV, err := schema.ParseGroupVersion("ignored group/ignored version") if err != nil { t.Fatal(err) } directEncoder := df.EncoderForVersion(serializer, ignoredGV) directDecoder := df.DecoderToVersion(serializer, ignoredGV) out, err := runtime.Encode(directEncoder, &ExternalTestType1{}) if err != nil { t.Fatal(err) } if string(out) != `{"myVersionKey":"v1","myKindKey":"ExternalTestType1"}`+"\n" { t.Fatal(string(out)) } a, _, err := directDecoder.Decode(out, nil, nil) e := &ExternalTestType1{ MyWeirdCustomEmbeddedVersionKindField: MyWeirdCustomEmbeddedVersionKindField{ APIVersion: "v1", ObjectKind: "ExternalTestType1", }, } if !semantic.DeepEqual(e, a) { t.Fatalf("expect %v, got %v", e, a) } }
func TestVersionedEncoding(t *testing.T) { s, _ := GetTestScheme() cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})) info, _ := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON) encoder := info.Serializer codec := cf.CodecForVersions(encoder, nil, schema.GroupVersion{Version: "v2"}, nil) out, err := runtime.Encode(codec, &TestType1{}) if err != nil { t.Fatal(err) } if string(out) != `{"myVersionKey":"v2","myKindKey":"TestType1"}`+"\n" { t.Fatal(string(out)) } codec = cf.CodecForVersions(encoder, nil, schema.GroupVersion{Version: "v3"}, nil) _, err = runtime.Encode(codec, &TestType1{}) if err == nil { t.Fatal(err) } // unversioned encode with no versions is written directly to wire codec = cf.CodecForVersions(encoder, nil, runtime.InternalGroupVersioner, nil) out, err = runtime.Encode(codec, &TestType1{}) if err != nil { t.Fatal(err) } if string(out) != `{}`+"\n" { t.Fatal(string(out)) } }
func TestDecodeToMetadataOnlyObjectList(t *testing.T) { data := getPodListJson(t) cf := serializer.DirectCodecFactory{CodecFactory: NewMetadataCodecFactory()} info, ok := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON) if !ok { t.Fatalf("expected to get a JSON serializer") } codec := cf.DecoderToVersion(info.Serializer, schema.GroupVersion{Group: "SOMEGROUP", Version: "SOMEVERSION"}) // decode with into into := &MetadataOnlyObjectList{} ret, _, err := codec.Decode(data, nil, into) if err != nil { t.Fatal(err) } metaOnlyList, ok := ret.(*MetadataOnlyObjectList) if !ok { t.Fatalf("expected ret to be *runtime.UnstructuredList") } verifyListMetadata(t, metaOnlyList) verifyListMetadata(t, into) // decode without into ret, _, err = codec.Decode(data, nil, nil) if err != nil { t.Fatal(err) } metaOnlyList, ok = ret.(*MetadataOnlyObjectList) if !ok { t.Fatalf("expected ret to be *runtime.UnstructuredList") } verifyListMetadata(t, metaOnlyList) }
func TestDecodeSinglePod(t *testing.T) { grace := int64(30) pod := &api.Pod{ TypeMeta: unversioned.TypeMeta{ APIVersion: "", }, ObjectMeta: api.ObjectMeta{ Name: "test", UID: "12345", Namespace: "mynamespace", }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, Containers: []api.Container{{ Name: "image", Image: "test/image", ImagePullPolicy: "IfNotPresent", TerminationMessagePath: "/dev/termination-log", SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), }}, SecurityContext: &api.PodSecurityContext{}, }, } json, err := runtime.Encode(testapi.Default.Codec(), pod) if err != nil { t.Errorf("unexpected error: %v", err) } parsed, podOut, err := tryDecodeSinglePod(json, noDefault) if !parsed { t.Errorf("expected to have parsed file: (%s)", string(json)) } if err != nil { t.Errorf("unexpected error: %v (%s)", err, string(json)) } if !reflect.DeepEqual(pod, podOut) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, podOut, string(json)) } for _, gv := range registered.EnabledVersionsForGroup(api.GroupName) { info, _ := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), "application/yaml") encoder := api.Codecs.EncoderForVersion(info.Serializer, gv) yaml, err := runtime.Encode(encoder, pod) if err != nil { t.Errorf("unexpected error: %v", err) } parsed, podOut, err = tryDecodeSinglePod(yaml, noDefault) if !parsed { t.Errorf("expected to have parsed file: (%s)", string(yaml)) } if err != nil { t.Errorf("unexpected error: %v (%s)", err, string(yaml)) } if !reflect.DeepEqual(pod, podOut) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, podOut, string(yaml)) } } }
// createSerializers creates all necessary serializers for given contentType. // TODO: the negotiated serializer passed to this method should probably return // serializers that control decoding and versioning without this package // being aware of the types. Depends on whether RESTClient must deal with // generic infrastructure. func createSerializers(config ContentConfig) (*Serializers, error) { mediaTypes := config.NegotiatedSerializer.SupportedMediaTypes() contentType := config.ContentType mediaType, _, err := mime.ParseMediaType(contentType) if err != nil { return nil, fmt.Errorf("the content type specified in the client configuration is not recognized: %v", err) } info, ok := runtime.SerializerInfoForMediaType(mediaTypes, mediaType) if !ok { if len(contentType) != 0 || len(mediaTypes) == 0 { return nil, fmt.Errorf("no serializers registered for %s", contentType) } info = mediaTypes[0] } internalGV := unversioned.GroupVersions{ { Group: config.GroupVersion.Group, Version: runtime.APIVersionInternal, }, // always include the legacy group as a decoding target to handle non-error `Status` return types { Group: "", Version: runtime.APIVersionInternal, }, } s := &Serializers{ Encoder: config.NegotiatedSerializer.EncoderForVersion(info.Serializer, *config.GroupVersion), Decoder: config.NegotiatedSerializer.DecoderToVersion(info.Serializer, internalGV), RenegotiatedDecoder: func(contentType string, params map[string]string) (runtime.Decoder, error) { info, ok := runtime.SerializerInfoForMediaType(mediaTypes, contentType) if !ok { return nil, fmt.Errorf("serializer for %s not registered", contentType) } return config.NegotiatedSerializer.DecoderToVersion(info.Serializer, internalGV), nil }, } if info.StreamSerializer != nil { s.StreamingSerializer = info.StreamSerializer.Serializer s.Framer = info.StreamSerializer.Framer } return s, 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 TestUniversalDeserializer(t *testing.T) { expected := &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "test"}} d := api.Codecs.UniversalDeserializer() for _, mediaType := range []string{"application/json", "application/yaml", "application/vnd.kubernetes.protobuf"} { info, ok := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType) if !ok { t.Fatal(mediaType) } buf := &bytes.Buffer{} if err := info.Serializer.Encode(expected, buf); err != nil { t.Fatalf("%s: %v", mediaType, err) } obj, _, err := d.Decode(buf.Bytes(), &schema.GroupVersionKind{Kind: "Pod", Version: "v1"}, nil) if err != nil { t.Fatalf("%s: %v", mediaType, err) } if !api.Semantic.DeepEqual(expected, obj) { t.Fatalf("%s: %#v", mediaType, obj) } } }
// NewStorageCodec assembles a storage codec for the provided storage media type, the provided serializer, and the requested // storage and memory versions. func NewStorageCodec(storageMediaType string, ns runtime.StorageSerializer, storageVersion, memoryVersion unversioned.GroupVersion, config storagebackend.Config) (runtime.Codec, error) { mediaType, _, err := mime.ParseMediaType(storageMediaType) if err != nil { return nil, fmt.Errorf("%q is not a valid mime-type", storageMediaType) } serializer, ok := runtime.SerializerInfoForMediaType(ns.SupportedMediaTypes(), mediaType) if !ok { return nil, fmt.Errorf("unable to find serializer for %q", storageMediaType) } s := serializer.Serializer // etcd2 only supports string data - we must wrap any result before returning // TODO: storagebackend should return a boolean indicating whether it supports binary data if !serializer.EncodesAsText && (config.Type == storagebackend.StorageTypeUnset || config.Type == storagebackend.StorageTypeETCD2) { glog.V(4).Infof("Wrapping the underlying binary storage serializer with a base64 encoding for etcd2") s = runtime.NewBase64Serializer(s) } encoder := ns.EncoderForVersion( s, runtime.NewMultiGroupVersioner( storageVersion, unversioned.GroupKind{Group: storageVersion.Group}, unversioned.GroupKind{Group: memoryVersion.Group}, ), ) ds := recognizer.NewDecoder(s, ns.UniversalDeserializer()) decoder := ns.DecoderToVersion( ds, runtime.NewMultiGroupVersioner( memoryVersion, unversioned.GroupKind{Group: memoryVersion.Group}, unversioned.GroupKind{Group: storageVersion.Group}, ), ) return runtime.NewCodec(encoder, decoder), nil }
func TestWatchHTTPTimeout(t *testing.T) { watcher := watch.NewFake() timeoutCh := make(chan time.Time) done := make(chan struct{}) info, ok := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) if !ok || info.StreamSerializer == nil { t.Fatal(info) } serializer := info.StreamSerializer // Setup a new watchserver watchServer := &WatchServer{ watching: watcher, mediaType: "testcase/json", framer: serializer.Framer, encoder: newCodec, embeddedEncoder: newCodec, fixup: func(obj runtime.Object) {}, t: &fakeTimeoutFactory{timeoutCh, done}, } s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { watchServer.ServeHTTP(w, req) })) defer s.Close() // Setup a client dest, _ := url.Parse(s.URL) dest.Path = "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/simple" dest.RawQuery = "watch=true" req, _ := http.NewRequest("GET", dest.String(), nil) client := http.Client{} resp, err := client.Do(req) watcher.Add(&apiservertesting.Simple{TypeMeta: metav1.TypeMeta{APIVersion: newGroupVersion.String()}}) // Make sure we can actually watch an endpoint decoder := json.NewDecoder(resp.Body) var got watchJSON err = decoder.Decode(&got) if err != nil { t.Fatalf("Unexpected error: %v", err) } // Timeout and check for leaks close(timeoutCh) select { case <-done: if !watcher.Stopped { t.Errorf("Leaked watch on timeout") } case <-time.After(wait.ForeverTestTimeout): t.Errorf("Failed to stop watcher after %s of timeout signal", wait.ForeverTestTimeout.String()) } // Make sure we can't receive any more events through the timeout watch err = decoder.Decode(&got) if err != io.EOF { t.Errorf("Unexpected non-error") } }
func TestWatchRead(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.Path = "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simples" dest.RawQuery = "watch=1" connectHTTP := func(accept string) (io.ReadCloser, string) { client := http.Client{} request, err := http.NewRequest("GET", dest.String(), nil) if err != nil { t.Fatalf("unexpected error: %v", err) } request.Header.Add("Accept", accept) response, err := client.Do(request) if err != nil { t.Fatalf("unexpected error: %v", err) } if response.StatusCode != http.StatusOK { b, _ := ioutil.ReadAll(response.Body) t.Fatalf("Unexpected response for accept: %q: %#v\n%s", accept, response, string(b)) } return response.Body, response.Header.Get("Content-Type") } connectWebSocket := func(accept string) (io.ReadCloser, string) { dest := *dest dest.Scheme = "ws" // Required by websocket, though the server never sees it. config, err := websocket.NewConfig(dest.String(), "http://localhost") if err != nil { t.Fatalf("unexpected error: %v", err) } config.Header.Add("Accept", accept) ws, err := websocket.DialConfig(config) if err != nil { t.Fatalf("unexpected error: %v", err) } return ws, "__default__" } testCases := []struct { Accept string ExpectedContentType string MediaType string }{ { Accept: "application/json", ExpectedContentType: "application/json", MediaType: "application/json", }, { Accept: "application/json;stream=watch", ExpectedContentType: "application/json", // legacy behavior MediaType: "application/json", }, // TODO: yaml stream serialization requires that RawExtension.MarshalJSON // be able to understand nested encoding (since yaml calls json.Marshal // rather than yaml.Marshal, which results in the raw bytes being in yaml). // Same problem as thirdparty object. /*{ Accept: "application/yaml", ExpectedContentType: "application/yaml;stream=watch", MediaType: "application/yaml", },*/ { Accept: "application/vnd.kubernetes.protobuf", ExpectedContentType: "application/vnd.kubernetes.protobuf;stream=watch", MediaType: "application/vnd.kubernetes.protobuf", }, { Accept: "application/vnd.kubernetes.protobuf;stream=watch", ExpectedContentType: "application/vnd.kubernetes.protobuf;stream=watch", MediaType: "application/vnd.kubernetes.protobuf", }, } protocols := []struct { name string selfFraming bool fn func(string) (io.ReadCloser, string) }{ {name: "http", fn: connectHTTP}, {name: "websocket", selfFraming: true, fn: connectWebSocket}, } for _, protocol := range protocols { for _, test := range testCases { info, ok := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), test.MediaType) if !ok || info.StreamSerializer == nil { t.Fatal(info) } streamSerializer := info.StreamSerializer r, contentType := protocol.fn(test.Accept) defer r.Close() if contentType != "__default__" && contentType != test.ExpectedContentType { t.Errorf("Unexpected content type: %#v", contentType) } objectCodec := api.Codecs.DecoderToVersion(info.Serializer, testInternalGroupVersion) var fr io.ReadCloser = r if !protocol.selfFraming { fr = streamSerializer.Framer.NewFrameReader(r) } d := streaming.NewDecoder(fr, streamSerializer.Serializer) var w *watch.FakeWatcher for w == nil { w = simpleStorage.Watcher() time.Sleep(time.Millisecond) } for i, item := range podWatchTestTable { action, object := item.t, item.obj name := fmt.Sprintf("%s-%s-%d", protocol.name, test.MediaType, i) // Send w.Action(action, object) // Test receive var got versioned.Event _, _, err := d.Decode(nil, &got) if err != nil { t.Fatalf("%s: Unexpected error: %v", name, err) } if got.Type != string(action) { t.Errorf("%s: Unexpected type: %v", name, got.Type) } gotObj, err := runtime.Decode(objectCodec, got.Object.Raw) if err != nil { t.Fatalf("%s: Decode error: %v", name, err) } if _, err := api.GetReference(gotObj); err != nil { t.Errorf("%s: Unable to construct reference: %v", name, err) } if e, a := object, gotObj; !api.Semantic.DeepEqual(e, a) { t.Errorf("%s: different: %s", name, diff.ObjectDiff(e, a)) } } w.Stop() var got versioned.Event _, _, err := d.Decode(nil, &got) if err == nil { t.Errorf("Unexpected non-error") } r.Close() } } }
// 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 := runtime.SerializerInfoForMediaType(scope.Serializer.SupportedMediaTypes(), runtime.ContentTypeJSON) 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.Serializer, gv), scope.Serializer.DecoderToVersion(s.Serializer, 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) } }
func init() { if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 { var ok bool mediaType, _, err := mime.ParseMediaType(apiMediaType) if err != nil { panic(err) } serializer, ok = runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType) if !ok { panic(fmt.Sprintf("no serializer for %s", apiMediaType)) } } if storageMediaType := StorageMediaType(); len(storageMediaType) > 0 { var ok bool mediaType, _, err := mime.ParseMediaType(storageMediaType) if err != nil { panic(err) } storageSerializer, ok = runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), mediaType) if !ok { panic(fmt.Sprintf("no serializer for %s", storageMediaType)) } } kubeTestAPI := os.Getenv("KUBE_TEST_API") if len(kubeTestAPI) != 0 { // priority is "first in list preferred", so this has to run in reverse order testGroupVersions := strings.Split(kubeTestAPI, ",") for i := len(testGroupVersions) - 1; i >= 0; i-- { gvString := testGroupVersions[i] groupVersion, err := unversioned.ParseGroupVersion(gvString) if err != nil { panic(fmt.Sprintf("Error parsing groupversion %v: %v", gvString, err)) } internalGroupVersion := unversioned.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal} Groups[groupVersion.Group] = TestGroup{ externalGroupVersion: groupVersion, internalGroupVersion: internalGroupVersion, internalTypes: api.Scheme.KnownTypes(internalGroupVersion), externalTypes: api.Scheme.KnownTypes(groupVersion), } } } if _, ok := Groups[api.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: api.GroupName, Version: registered.GroupOrDie(api.GroupName).GroupVersion.Version} Groups[api.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: api.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(api.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[extensions.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: extensions.GroupName, Version: registered.GroupOrDie(extensions.GroupName).GroupVersion.Version} Groups[extensions.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: extensions.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[autoscaling.GroupName]; !ok { internalTypes := make(map[string]reflect.Type) for k, t := range api.Scheme.KnownTypes(extensions.SchemeGroupVersion) { if k == "Scale" { continue } internalTypes[k] = t } externalGroupVersion := unversioned.GroupVersion{Group: autoscaling.GroupName, Version: registered.GroupOrDie(autoscaling.GroupName).GroupVersion.Version} Groups[autoscaling.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: extensions.SchemeGroupVersion, internalTypes: internalTypes, externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[autoscaling.GroupName+"IntraGroup"]; !ok { internalTypes := make(map[string]reflect.Type) for k, t := range api.Scheme.KnownTypes(extensions.SchemeGroupVersion) { if k == "Scale" { internalTypes[k] = t break } } externalGroupVersion := unversioned.GroupVersion{Group: autoscaling.GroupName, Version: registered.GroupOrDie(autoscaling.GroupName).GroupVersion.Version} Groups[autoscaling.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: autoscaling.SchemeGroupVersion, internalTypes: internalTypes, externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[batch.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: batch.GroupName, Version: registered.GroupOrDie(batch.GroupName).GroupVersion.Version} Groups[batch.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: batch.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(batch.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[apps.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: apps.GroupName, Version: registered.GroupOrDie(apps.GroupName).GroupVersion.Version} Groups[apps.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: extensions.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[policy.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: policy.GroupName, Version: registered.GroupOrDie(policy.GroupName).GroupVersion.Version} Groups[policy.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: policy.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(policy.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[federation.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: federation.GroupName, Version: registered.GroupOrDie(federation.GroupName).GroupVersion.Version} Groups[federation.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: federation.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(federation.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[rbac.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: rbac.GroupName, Version: registered.GroupOrDie(rbac.GroupName).GroupVersion.Version} Groups[rbac.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: rbac.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(rbac.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[storage.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: storage.GroupName, Version: registered.GroupOrDie(storage.GroupName).GroupVersion.Version} Groups[storage.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: storage.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(storage.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[certificates.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: certificates.GroupName, Version: registered.GroupOrDie(certificates.GroupName).GroupVersion.Version} Groups[certificates.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: certificates.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(certificates.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[imagepolicy.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: imagepolicy.GroupName, Version: registered.GroupOrDie(imagepolicy.GroupName).GroupVersion.Version} Groups[imagepolicy.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: imagepolicy.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(imagepolicy.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } if _, ok := Groups[kubeadm.GroupName]; !ok { externalGroupVersion := unversioned.GroupVersion{Group: kubeadm.GroupName, Version: registered.GroupOrDie(kubeadm.GroupName).GroupVersion.Version} Groups[kubeadm.GroupName] = TestGroup{ externalGroupVersion: externalGroupVersion, internalGroupVersion: kubeadm.SchemeGroupVersion, internalTypes: api.Scheme.KnownTypes(kubeadm.SchemeGroupVersion), externalTypes: api.Scheme.KnownTypes(externalGroupVersion), } } Default = Groups[api.GroupName] Autoscaling = Groups[autoscaling.GroupName] Batch = Groups[batch.GroupName] Apps = Groups[apps.GroupName] Policy = Groups[policy.GroupName] Certificates = Groups[certificates.GroupName] Extensions = Groups[extensions.GroupName] Federation = Groups[federation.GroupName] Rbac = Groups[rbac.GroupName] Storage = Groups[storage.GroupName] ImagePolicy = Groups[imagepolicy.GroupName] }
func TestSpecificRoundTrips(t *testing.T) { boolFalse := false testCases := []struct { mediaType string in, out runtime.Object to, from unversioned.GroupVersion }{ { in: &configapi.MasterConfig{ AdmissionConfig: configapi.AdmissionConfig{ PluginConfig: map[string]configapi.AdmissionPluginConfig{ "test1": {Configuration: &configapi.LDAPSyncConfig{BindDN: "first"}}, "test2": {Configuration: &runtime.Unknown{Raw: []byte(`{"kind":"LDAPSyncConfig","apiVersion":"v1","bindDN":"second"}`)}}, "test3": {Configuration: &runtime.Unknown{Raw: []byte(`{"kind":"Unknown","apiVersion":"some/version"}`)}}, "test4": {Configuration: nil}, }, }, }, to: configapiv1.SchemeGroupVersion, out: &configapiv1.MasterConfig{ TypeMeta: unversioned.TypeMeta{Kind: "MasterConfig", APIVersion: "v1"}, AdmissionConfig: configapiv1.AdmissionConfig{ PluginConfig: map[string]configapiv1.AdmissionPluginConfig{ "test1": {Configuration: runtime.RawExtension{ Object: &configapiv1.LDAPSyncConfig{BindDN: "first"}, Raw: []byte(`{"kind":"LDAPSyncConfig","apiVersion":"v1","url":"","bindDN":"first","bindPassword":"","insecure":false,"ca":"","groupUIDNameMapping":null}`), }}, "test2": {Configuration: runtime.RawExtension{ Object: &configapiv1.LDAPSyncConfig{BindDN: "second"}, Raw: []byte(`{"kind":"LDAPSyncConfig","apiVersion":"v1","bindDN":"second"}`), }}, "test3": {Configuration: runtime.RawExtension{ Object: &runtime.Unknown{TypeMeta: runtime.TypeMeta{Kind: "Unknown", APIVersion: "some/version"}, ContentType: "application/json", Raw: []byte(`{"kind":"Unknown","apiVersion":"some/version"}`)}, Raw: []byte(`{"kind":"Unknown","apiVersion":"some/version"}`), }}, "test4": {}, }, }, VolumeConfig: configapiv1.MasterVolumeConfig{DynamicProvisioningEnabled: &boolFalse}, }, from: configapiv1.SchemeGroupVersion, }, } f := serializer.NewCodecFactory(configapi.Scheme) for i, test := range testCases { var s runtime.Serializer if len(test.mediaType) != 0 { info, _ := runtime.SerializerInfoForMediaType(f.SupportedMediaTypes(), test.mediaType) s = info.Serializer } else { info, _ := runtime.SerializerInfoForMediaType(f.SupportedMediaTypes(), f.SupportedMediaTypes()[0].MediaType) s = info.Serializer } data, err := runtime.Encode(f.LegacyCodec(test.to), test.in) if err != nil { t.Errorf("%d: unable to encode: %v", i, err) continue } result, err := runtime.Decode(f.DecoderToVersion(s, test.from), data) if err != nil { t.Errorf("%d: unable to decode: %v", i, err) continue } if !reflect.DeepEqual(test.out, result) { t.Errorf("%d: result did not match: %s", i, diff.ObjectReflectDiff(test.out, result)) continue } } }
func TestScheme(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("Simple"), &InternalSimple{}) scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) // If set, would clear TypeMeta during conversion. //scheme.AddIgnoredConversionType(&TypeMeta{}, &TypeMeta{}) // test that scheme is an ObjectTyper var _ runtime.ObjectTyper = scheme internalToExternalCalls := 0 externalToInternalCalls := 0 // Register functions to verify that scope.Meta() gets set correctly. err := scheme.AddConversionFuncs( func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error { scope.Convert(&in.TypeMeta, &out.TypeMeta, 0) scope.Convert(&in.TestString, &out.TestString, 0) internalToExternalCalls++ return nil }, func(in *ExternalSimple, out *InternalSimple, scope conversion.Scope) error { scope.Convert(&in.TypeMeta, &out.TypeMeta, 0) scope.Convert(&in.TestString, &out.TestString, 0) externalToInternalCalls++ return nil }, ) if err != nil { t.Fatalf("unexpected error: %v", err) } codecs := serializer.NewCodecFactory(scheme) codec := codecs.LegacyCodec(externalGV) info, _ := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) jsonserializer := info.Serializer simple := &InternalSimple{ TestString: "foo", } // Test Encode, Decode, DecodeInto, and DecodeToVersion obj := runtime.Object(simple) data, err := runtime.Encode(codec, obj) if err != nil { t.Fatal(err) } obj2, err := runtime.Decode(codec, data) if err != nil { t.Fatal(err) } if _, ok := obj2.(*InternalSimple); !ok { t.Fatalf("Got wrong type") } if e, a := simple, obj2; !reflect.DeepEqual(e, a) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", e, a) } obj3 := &InternalSimple{} if err := runtime.DecodeInto(codec, data, obj3); err != nil { t.Fatal(err) } // clearing TypeMeta is a function of the scheme, which we do not test here (ConvertToVersion // does not automatically clear TypeMeta anymore). simple.TypeMeta = runtime.TypeMeta{Kind: "Simple", APIVersion: externalGV.String()} if e, a := simple, obj3; !reflect.DeepEqual(e, a) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", e, a) } obj4, err := runtime.Decode(jsonserializer, data) if err != nil { t.Fatal(err) } if _, ok := obj4.(*ExternalSimple); !ok { t.Fatalf("Got wrong type") } // Test Convert external := &ExternalSimple{} err = scheme.Convert(simple, external, nil) if err != nil { t.Fatalf("Unexpected error: %v", err) } if e, a := simple.TestString, external.TestString; e != a { t.Errorf("Expected %v, got %v", e, a) } // Encode and Convert should each have caused an increment. if e, a := 2, internalToExternalCalls; e != a { t.Errorf("Expected %v, got %v", e, a) } // DecodeInto and Decode should each have caused an increment because of a conversion if e, a := 2, externalToInternalCalls; e != a { t.Errorf("Expected %v, got %v", e, a) } }
// Returns a basic master config. func NewMasterConfig() *master.Config { config := storagebackend.Config{ ServerList: []string{GetEtcdURLFromEnv()}, // This causes the integration tests to exercise the etcd // prefix code, so please don't change without ensuring // sufficient coverage in other ways. Prefix: uuid.New(), } info, _ := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) ns := NewSingleContentTypeSerializer(api.Scheme, info) storageFactory := genericapiserver.NewDefaultStorageFactory(config, runtime.ContentTypeJSON, ns, genericapiserver.NewDefaultResourceEncodingConfig(), master.DefaultAPIResourceConfigSource()) storageFactory.SetSerializer( unversioned.GroupResource{Group: api.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: autoscaling.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: batch.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: apps.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: extensions.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: policy.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: rbac.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: certificates.GroupName, Resource: genericapiserver.AllResources}, "", ns) storageFactory.SetSerializer( unversioned.GroupResource{Group: storage.GroupName, Resource: genericapiserver.AllResources}, "", ns) genericConfig := genericapiserver.NewConfig() kubeVersion := version.Get() genericConfig.Version = &kubeVersion genericConfig.APIResourceConfigSource = master.DefaultAPIResourceConfigSource() genericConfig.Authorizer = authorizer.NewAlwaysAllowAuthorizer() genericConfig.AdmissionControl = admit.NewAlwaysAdmit() genericConfig.EnableMetrics = true return &master.Config{ GenericConfig: genericConfig, StorageFactory: storageFactory, EnableCoreControllers: true, EnableWatchCache: true, KubeletClientConfig: kubeletclient.KubeletClientConfig{Port: 10250}, APIServerServicePort: 443, MasterCount: 1, } }