func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { scheme := runtime.NewScheme() scheme.AddKnownTypeWithName("", "Type", &internalType{}) scheme.AddKnownTypeWithName("unlikelyversion", "Type", &externalType{}) //This tests that kubectl will not confuse the external scheme with the internal scheme, even when they accidentally have versions of the same name. scheme.AddKnownTypeWithName(testapi.Version(), "Type", &ExternalType2{}) codec := runtime.CodecFor(scheme, "unlikelyversion") validVersion := testapi.Version() mapper := meta.NewDefaultRESTMapper([]string{"unlikelyversion", validVersion}, func(version string) (*meta.VersionInterfaces, bool) { return &meta.VersionInterfaces{ Codec: runtime.CodecFor(scheme, version), ObjectConvertor: scheme, MetadataAccessor: meta.NewAccessor(), }, (version == validVersion || version == "unlikelyversion") }) for _, version := range []string{"unlikelyversion", validVersion} { for kind := range scheme.KnownTypes(version) { mixedCase := false scope := meta.RESTScopeNamespace mapper.Add(scope, kind, version, mixedCase) } } return scheme, mapper, codec }
func Merge(dst runtime.Object, fragment, kind string) error { // Ok, this is a little hairy, we'd rather not force the user to specify a kind for their JSON // So we pull it into a map, add the Kind field, and then reserialize. // We also pull the apiVersion for proper parsing var intermediate interface{} if err := json.Unmarshal([]byte(fragment), &intermediate); err != nil { return err } dataMap, ok := intermediate.(map[string]interface{}) if !ok { return fmt.Errorf("Expected a map, found something else: %s", fragment) } version, found := dataMap["apiVersion"] if !found { return fmt.Errorf("Inline JSON requires an apiVersion field") } versionString, ok := version.(string) if !ok { return fmt.Errorf("apiVersion must be a string") } codec := runtime.CodecFor(api.Scheme, versionString) dataMap["kind"] = kind data, err := json.Marshal(intermediate) if err != nil { return err } src, err := codec.Decode(data) if err != nil { return err } return mergo.Merge(dst, src) }
func init() { // Use the first API version in the list of registered versions as the latest. Version = registered.RegisteredVersions[0] OldestVersion = registered.RegisteredVersions[len(registered.RegisteredVersions)-1] Codec = runtime.CodecFor(api.Scheme, Version) // Put the registered versions in Versions in reverse order. versions := registered.RegisteredVersions Versions = []string{} for i := len(versions) - 1; i >= 0; i-- { Versions = append(Versions, versions[i]) } mapper := meta.NewDefaultRESTMapper( versions, func(version string) (*meta.VersionInterfaces, bool) { interfaces, err := InterfacesFor(version) if err != nil { return nil, false } return interfaces, true }, ) // the list of kinds that are scoped at the root of the api hierarchy // if a kind is not enumerated here, it is assumed to have a namespace scope kindToRootScope := map[string]bool{ "Node": true, "Minion": true, "Namespace": true, "PersistentVolume": true, "SecurityContextConstraints": true, } // setup aliases for groups of resources mapper.AddResourceAlias("all", userResources...) // these kinds should be excluded from the list of resources ignoredKinds := util.NewStringSet( "ListOptions", "DeleteOptions", "Status", "PodLogOptions", "PodExecOptions", "PodProxyOptions") // enumerate all supported versions, get the kinds, and register with the mapper how to address our resources. for _, version := range versions { for kind := range api.Scheme.KnownTypes(version) { if ignoredKinds.Has(kind) { continue } scope := meta.RESTScopeNamespace if kindToRootScope[kind] { scope = meta.RESTScopeRoot } mapper.Add(scope, kind, version, false) } } RESTMapper = mapper }
func init() { scheme = runtime.NewScheme() scheme.AddKnownTypes("", &TestResource{}) scheme.AddKnownTypes(testapi.Version(), &TestResource{}) codec = runtime.CodecFor(scheme, testapi.Version()) scheme.AddConversionFuncs( func(in *TestResource, out *TestResource, s conversion.Scope) error { *out = *in return nil }, ) }
func serviceErrorHandler(requestResolver *APIRequestInfoResolver, apiVersions []string, serviceErr restful.ServiceError, request *restful.Request, response *restful.Response) { requestInfo, err := requestResolver.GetAPIRequestInfo(request.Request) codec := latest.Codec if err == nil && requestInfo.APIVersion != "" { // check if the api version is valid. for _, version := range apiVersions { if requestInfo.APIVersion == version { // valid api version. codec = runtime.CodecFor(api.Scheme, requestInfo.APIVersion) break } } } errorJSON(apierrors.NewGenericServerResponse(serviceErr.Code, "", "", "", "", 0, false), codec, response.ResponseWriter) }
func getFakeClient(t *testing.T, validURLs []string) (ClientFunc, *httptest.Server) { handlerFunc := func(w http.ResponseWriter, r *http.Request) { for _, u := range validURLs { if u == r.RequestURI { return } } t.Errorf("Unexpected HTTP request: %s, expected %v", r.RequestURI, validURLs) } server := httptest.NewServer(http.HandlerFunc(handlerFunc)) return func(mapping *meta.RESTMapping) (*client.RESTClient, error) { fakeCodec := runtime.CodecFor(api.Scheme, "v1beta1") fakeUri, _ := url.Parse(server.URL + "/api/v1beta1") return client.NewRESTClient(fakeUri, fakeCodec), nil }, server }
func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { scheme := runtime.NewScheme() scheme.AddKnownTypeWithName("", "Type", &internalType{}) scheme.AddKnownTypeWithName("unlikelyversion", "Type", &externalType{}) codec := runtime.CodecFor(scheme, "unlikelyversion") mapper := meta.NewDefaultRESTMapper([]string{"unlikelyversion"}, func(version string) (*meta.VersionInterfaces, bool) { return &meta.VersionInterfaces{ Codec: codec, ObjectConvertor: scheme, MetadataAccessor: meta.NewAccessor(), }, (version == "unlikelyversion") }) mapper.Add(scheme, false, "unlikelyversion") return scheme, mapper, codec }
func init() { Version = registered.RegisteredVersions[0] Codec = runtime.CodecFor(api.Scheme, Version) // Put the registered versions in Versions in reverse order. for i := len(registered.RegisteredVersions) - 1; i >= 0; i-- { Versions = append(Versions, registered.RegisteredVersions[i]) } // the list of kinds that are scoped at the root of the api hierarchy // if a kind is not enumerated here, it is assumed to have a namespace scope rootScoped := util.NewStringSet() ignoredKinds := util.NewStringSet() RESTMapper = api.NewDefaultRESTMapper(Versions, InterfacesFor, importPrefix, ignoredKinds, rootScoped) api.RegisterRESTMapper(RESTMapper) }
func testCompatibility( t *testing.T, version string, input []byte, validator func(obj runtime.Object) fielderrors.ValidationErrorList, serialized map[string]string, ) { // Decode codec := runtime.CodecFor(api.Scheme, version) obj, err := codec.Decode(input) if err != nil { t.Fatalf("Unexpected error: %v", err) } // Validate errs := validator(obj) if len(errs) != 0 { t.Fatalf("Unexpected errors: %v", errs) } // Encode output, err := codec.Encode(obj) if err != nil { t.Fatalf("Unexpected error: %v", err) } // Validate old and new fields are encoded generic := map[string]interface{}{} if err := json.Unmarshal(output, &generic); err != nil { t.Fatalf("Unexpected error: %v", err) } for k, expectedValue := range serialized { keys := strings.Split(k, ".") if actualValue, ok, err := getJSONValue(generic, keys...); err != nil || !ok { t.Errorf("Unexpected error for %s: %v", k, err) } else if !reflect.DeepEqual(expectedValue, actualValue) { t.Errorf("Expected %v, got %v", expectedValue, actualValue) } } }
func TestEncode(t *testing.T) { scheme := runtime.NewScheme() scheme.AddKnownTypeWithName("", "Simple", &InternalSimple{}) scheme.AddKnownTypeWithName("externalVersion", "Simple", &ExternalSimple{}) codec := runtime.CodecFor(scheme, "externalVersion") test := &InternalSimple{ TestString: "I'm the same", } obj := runtime.Object(test) data, err := codec.Encode(obj) obj2, err2 := codec.Decode(data) if err != nil || err2 != nil { t.Fatalf("Failure: '%v' '%v'", err, err2) } if _, ok := obj2.(*InternalSimple); !ok { t.Fatalf("Got wrong type") } if !reflect.DeepEqual(obj2, test) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", &test, obj2) } }
func TestTypes(t *testing.T) { for kind, reflectType := range api.Scheme.KnownTypes("") { if !strings.Contains(reflectType.PkgPath(), "/origin/") { continue } t.Logf("About to test %v", reflectType) // Try a few times, since runTest uses random values. for i := 0; i < fuzzIters; i++ { item, err := api.Scheme.New("", kind) if err != nil { t.Errorf("Couldn't make a %v? %v", kind, err) continue } if _, err := meta.TypeAccessor(item); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } seed := rand.Int63() if versions, ok := skipStandardVersions[kind]; ok { for _, v := range versions { fuzzInternalObject(t, "", item, seed) roundTrip(t, runtime.CodecFor(api.Scheme, v), item) } continue } fuzzInternalObject(t, "", item, seed) roundTrip(t, osapi.Codec, item) if _, ok := skipV1beta3[kind]; !ok { fuzzInternalObject(t, "v1beta3", item, seed) roundTrip(t, v1beta3.Codec, item) } if _, ok := skipV1[kind]; !ok { fuzzInternalObject(t, "v1", item, seed) roundTrip(t, v1.Codec, item) } } } }
func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { scheme := runtime.NewScheme() scheme.AddKnownTypeWithName("", "Type", &internalType{}) scheme.AddKnownTypeWithName("unlikelyversion", "Type", &externalType{}) codec := runtime.CodecFor(scheme, "unlikelyversion") mapper := meta.NewDefaultRESTMapper([]string{"unlikelyversion"}, func(version string) (*meta.VersionInterfaces, bool) { return &meta.VersionInterfaces{ Codec: codec, ObjectConvertor: scheme, MetadataAccessor: meta.NewAccessor(), }, (version == "unlikelyversion") }) for _, version := range []string{"unlikelyversion"} { for kind := range scheme.KnownTypes(version) { mixedCase := false scope := meta.RESTScopeNamespace mapper.Add(scope, kind, version, mixedCase) } } return scheme, mapper, codec }
func init() { // Use the first API version in the list of registered versions as the latest. Version = registered.RegisteredVersions[0] OldestVersion = registered.RegisteredVersions[len(registered.RegisteredVersions)-1] Codec = runtime.CodecFor(api.Scheme, Version) // Put the registered versions in Versions in reverse order. versions := registered.RegisteredVersions Versions = []string{} for i := len(versions) - 1; i >= 0; i-- { Versions = append(Versions, versions[i]) } // the list of kinds that are scoped at the root of the api hierarchy // if a kind is not enumerated here, it is assumed to have a namespace scope rootScoped := util.NewStringSet( "Node", "Minion", "Namespace", "PersistentVolume", ) // these kinds should be excluded from the list of resources ignoredKinds := util.NewStringSet( "ListOptions", "DeleteOptions", "Status", "PodLogOptions", "PodExecOptions", "PodAttachOptions", "PodProxyOptions") mapper := api.NewDefaultRESTMapper(versions, InterfacesFor, importPrefix, ignoredKinds, rootScoped) // setup aliases for groups of resources mapper.AddResourceAlias("all", userResources...) RESTMapper = mapper api.RegisterRESTMapper(RESTMapper) }
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v1 import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/scheduler/api" ) // Codec encodes internal objects to the v1 scheme var Codec = runtime.CodecFor(api.Scheme, "v1") func init() { api.Scheme.AddKnownTypes("v1", &Policy{}, ) } func (*Policy) IsAnAPIObject() {}
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package api import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) // Codec is the identity codec for this package - it can only convert itself // to itself. var Codec = runtime.CodecFor(Scheme, "") // EmbeddedObject implements a Codec specific version of an // embedded object. type EmbeddedObject struct { runtime.Object } // UnmarshalJSON implements the json.Unmarshaler interface. func (a *EmbeddedObject) UnmarshalJSON(b []byte) error { obj, err := runtime.CodecUnmarshalJSON(Codec, b) a.Object = obj return err } // MarshalJSON implements the json.Marshaler interface.
func init() { scheme = runtime.NewScheme() scheme.AddKnownTypes("", &TestResource{}) scheme.AddKnownTypes("v1beta1", &TestResource{}) codec = runtime.CodecFor(scheme, "v1beta1") }
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package v1beta3 import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) // Codec encodes internal objects to the v1beta3 scheme var Codec = runtime.CodecFor(api.Scheme, "v1beta3") func init() { api.Scheme.AddKnownTypes("v1beta3", &Pod{}, &PodList{}, &PodStatusResult{}, &PodTemplate{}, &PodTemplateList{}, &ReplicationController{}, &ReplicationControllerList{}, &Service{}, &ServiceList{}, &Endpoints{}, &EndpointsList{}, &Node{},
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch" "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/admit" "github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/admission/deny" "github.com/emicklei/go-restful" ) func convert(obj runtime.Object) (runtime.Object, error) { return obj, nil } // This creates a fake API version, similar to api/latest.go const testVersion = "version" var versions = []string{testVersion} var codec = runtime.CodecFor(api.Scheme, testVersion) var accessor = meta.NewAccessor() var versioner runtime.ResourceVersioner = accessor var selfLinker runtime.SelfLinker = accessor var mapper, namespaceMapper, legacyNamespaceMapper meta.RESTMapper // The mappers with namespace and with legacy namespace scopes. var admissionControl admission.Interface var requestContextMapper api.RequestContextMapper func interfacesFor(version string) (*meta.VersionInterfaces, error) { switch version { case testVersion: return &meta.VersionInterfaces{ Codec: codec, ObjectConvertor: api.Scheme, MetadataAccessor: accessor, }, nil
// Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. // Because api.List is part of the Kube API, resource.Builder has to perform a conversion on // api.Scheme, which may not have access to all objects, and not all objects are at the same // internal versioning scheme. This test verifies that two isolated schemes (Test, and api.Scheme) // can be conjoined into a single output object. // // The expected behavior of the `kubectl get` command is: // 1. objects using unrecognized schemes will always be returned using that scheme/version, "unlikelyversion" in this test; // 2. if the specified output-version is a recognized, valid Scheme, then the list should use that scheme, and otherwise it will default to the client version, latest.Version in this test; // 3a. if the specified output-version is a recognized, valid Scheme, in which the requested object (replicationcontroller) can be represented, then the object should be returned using that version; // 3b. otherwise if the specified output-version is unrecognized, but the requested object (replicationcontroller) is recognized by the client's codec, then it will be converted to the client version, latest.Version in this test. func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { testCases := map[string]struct { outputVersion string listVersion string testtypeVersion string rcVersion string }{ "handles specific version": { outputVersion: latest.Version, listVersion: latest.Version, testtypeVersion: "unlikelyversion", rcVersion: latest.Version, }, "handles second specific version": { outputVersion: "unlikelyversion", listVersion: latest.Version, testtypeVersion: "unlikelyversion", rcVersion: latest.Version, // see expected behavior 3b }, "handles common version": { outputVersion: testapi.Version(), listVersion: testapi.Version(), testtypeVersion: "unlikelyversion", rcVersion: testapi.Version(), }, } for k, test := range testCases { apiCodec := runtime.CodecFor(api.Scheme, testapi.Version()) regularClient := &client.FakeRESTClient{ Codec: apiCodec, Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{StatusCode: 200, Body: objBody(apiCodec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}})}, nil }), } f, tf, codec := NewMixedFactory(regularClient) tf.Printer = &testPrinter{} tf.Client = &client.FakeRESTClient{ Codec: codec, Client: client.HTTPClientFunc(func(req *http.Request) (*http.Response, error) { return &http.Response{StatusCode: 200, Body: objBody(codec, &internalType{Name: "foo"})}, nil }), } tf.Namespace = "test" tf.ClientConfig = &client.Config{Version: latest.Version} buf := bytes.NewBuffer([]byte{}) cmd := NewCmdGet(f, buf) cmd.SetOutput(buf) cmd.Flags().Set("output", "json") cmd.Flags().Set("output-version", test.outputVersion) err := RunGet(f, buf, cmd, []string{"type/foo", "replicationcontrollers/foo"}) if err != nil { t.Errorf("%s: unexpected error: %v", k, err) continue } out := make(map[string]interface{}) if err := encjson.Unmarshal(buf.Bytes(), &out); err != nil { t.Errorf("%s: unexpected error: %v\n%s", k, err, buf.String()) continue } if out["apiVersion"] != test.listVersion { t.Errorf("%s: unexpected list: %#v", k, out) } arr := out["items"].([]interface{}) if arr[0].(map[string]interface{})["apiVersion"] != test.testtypeVersion { t.Errorf("%s: unexpected list: %#v", k, out) } if arr[1].(map[string]interface{})["apiVersion"] != test.rcVersion { t.Errorf("%s: unexpected list: %#v", k, out) } } }
See the License for the specific language governing permissions and limitations under the License. */ package runtime_test import ( "encoding/json" "reflect" "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) var scheme = runtime.NewScheme() var Codec = runtime.CodecFor(scheme, "v1test") type EmbeddedTest struct { runtime.TypeMeta `yaml:",inline" json:",inline"` ID string `yaml:"id,omitempty" json:"id,omitempty"` Object runtime.EmbeddedObject `yaml:"object,omitempty" json:"object,omitempty"` EmptyObject runtime.EmbeddedObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"` } type EmbeddedTestExternal struct { runtime.TypeMeta `yaml:",inline" json:",inline"` ID string `yaml:"id,omitempty" json:"id,omitempty"` Object runtime.RawExtension `yaml:"object,omitempty" json:"object,omitempty"` EmptyObject runtime.RawExtension `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"` }
func init() { // Use the first API version in the list of registered versions as the latest. Version = registered.RegisteredVersions[0] Codec = runtime.CodecFor(api.Scheme, Version) // Put the registered versions in Versions in reverse order. versions := registered.RegisteredVersions Versions = []string{} for i := len(versions) - 1; i >= 0; i-- { Versions = append(Versions, versions[i]) } mapper := meta.NewDefaultRESTMapper( versions, func(version string) (*meta.VersionInterfaces, bool) { interfaces, err := InterfacesFor(version) if err != nil { return nil, false } return interfaces, true }, ) // versions that used mixed case URL formats versionMixedCase := map[string]bool{ "v1beta1": true, "v1beta2": true, } // backwards compatibility, prior to v1beta3, we identified the namespace as a query parameter versionToNamespaceScope := map[string]meta.RESTScope{ "v1beta1": meta.RESTScopeNamespaceLegacy, "v1beta2": meta.RESTScopeNamespaceLegacy, "v1beta3": meta.RESTScopeNamespace, "v1": meta.RESTScopeNamespace, } // the list of kinds that are scoped at the root of the api hierarchy // if a kind is not enumerated here, it is assumed to have a namespace scope kindToRootScope := map[string]bool{ "Node": true, "Minion": true, "Namespace": true, "PersistentVolume": true, } // setup aliases for groups of resources mapper.AddResourceAlias("all", userResources...) // these kinds should be excluded from the list of resources ignoredKinds := util.NewStringSet( "ListOptions", "DeleteOptions", "Status", "ContainerManifest", "PodLogOptions", "PodExecOptions", "PodProxyOptions") // enumerate all supported versions, get the kinds, and register with the mapper how to address our resources. for _, version := range versions { for kind := range api.Scheme.KnownTypes(version) { if ignoredKinds.Has(kind) { continue } mixedCase, found := versionMixedCase[version] if !found { mixedCase = false } scope := versionToNamespaceScope[version] _, found = kindToRootScope[kind] if found { scope = meta.RESTScopeRoot } mapper.Add(scope, kind, version, mixedCase) } } RESTMapper = mapper }