restmapper_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package meta
  14. import (
  15. "errors"
  16. "reflect"
  17. "strings"
  18. "testing"
  19. "k8s.io/kubernetes/pkg/api/unversioned"
  20. "k8s.io/kubernetes/pkg/runtime"
  21. )
  22. type fakeConvertor struct{}
  23. func (fakeConvertor) Convert(in, out, context interface{}) error {
  24. return nil
  25. }
  26. func (fakeConvertor) ConvertToVersion(in runtime.Object, _ runtime.GroupVersioner) (runtime.Object, error) {
  27. return in, nil
  28. }
  29. func (fakeConvertor) ConvertFieldLabel(version, kind, label, value string) (string, string, error) {
  30. return label, value, nil
  31. }
  32. var validAccessor = resourceAccessor{}
  33. var validConvertor = fakeConvertor{}
  34. func fakeInterfaces(version unversioned.GroupVersion) (*VersionInterfaces, error) {
  35. return &VersionInterfaces{ObjectConvertor: validConvertor, MetadataAccessor: validAccessor}, nil
  36. }
  37. var unmatchedErr = errors.New("no version")
  38. func unmatchedVersionInterfaces(version unversioned.GroupVersion) (*VersionInterfaces, error) {
  39. return nil, unmatchedErr
  40. }
  41. func TestRESTMapperVersionAndKindForResource(t *testing.T) {
  42. testGroup := "test.group"
  43. testVersion := "test"
  44. testGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: testVersion}
  45. testCases := []struct {
  46. Resource unversioned.GroupVersionResource
  47. GroupVersionToRegister unversioned.GroupVersion
  48. ExpectedGVK unversioned.GroupVersionKind
  49. Err bool
  50. }{
  51. {Resource: unversioned.GroupVersionResource{Resource: "internalobjec"}, Err: true},
  52. {Resource: unversioned.GroupVersionResource{Resource: "internalObjec"}, Err: true},
  53. {Resource: unversioned.GroupVersionResource{Resource: "internalobject"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
  54. {Resource: unversioned.GroupVersionResource{Resource: "internalobjects"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")},
  55. }
  56. for i, testCase := range testCases {
  57. mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion}, fakeInterfaces)
  58. if len(testCase.ExpectedGVK.Kind) != 0 {
  59. mapper.Add(testCase.ExpectedGVK, RESTScopeNamespace)
  60. }
  61. actualGVK, err := mapper.KindFor(testCase.Resource)
  62. hasErr := err != nil
  63. if hasErr != testCase.Err {
  64. t.Errorf("%d: unexpected error behavior %t: %v", i, testCase.Err, err)
  65. continue
  66. }
  67. if err != nil {
  68. continue
  69. }
  70. if actualGVK != testCase.ExpectedGVK {
  71. t.Errorf("%d: unexpected version and kind: e=%s a=%s", i, testCase.ExpectedGVK, actualGVK)
  72. }
  73. }
  74. }
  75. func TestRESTMapperGroupForResource(t *testing.T) {
  76. testCases := []struct {
  77. Resource unversioned.GroupVersionResource
  78. GroupVersionKind unversioned.GroupVersionKind
  79. Err bool
  80. }{
  81. {Resource: unversioned.GroupVersionResource{Resource: "myObject"}, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
  82. {Resource: unversioned.GroupVersionResource{Resource: "myobject"}, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi2", Version: "test", Kind: "MyObject"}},
  83. {Resource: unversioned.GroupVersionResource{Resource: "myObje"}, Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
  84. {Resource: unversioned.GroupVersionResource{Resource: "myobje"}, Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}},
  85. }
  86. for i, testCase := range testCases {
  87. mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testCase.GroupVersionKind.GroupVersion()}, fakeInterfaces)
  88. mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace)
  89. actualGVK, err := mapper.KindFor(testCase.Resource)
  90. if testCase.Err {
  91. if err == nil {
  92. t.Errorf("%d: expected error", i)
  93. }
  94. } else if err != nil {
  95. t.Errorf("%d: unexpected error: %v", i, err)
  96. } else if actualGVK != testCase.GroupVersionKind {
  97. t.Errorf("%d: expected group %q, got %q", i, testCase.GroupVersionKind, actualGVK)
  98. }
  99. }
  100. }
  101. func TestRESTMapperKindsFor(t *testing.T) {
  102. testCases := []struct {
  103. Name string
  104. PreferredOrder []unversioned.GroupVersion
  105. KindsToRegister []unversioned.GroupVersionKind
  106. PartialResourceToRequest unversioned.GroupVersionResource
  107. ExpectedKinds []unversioned.GroupVersionKind
  108. ExpectedKindErr string
  109. }{
  110. {
  111. Name: "ambiguous groups, with preference order",
  112. PreferredOrder: []unversioned.GroupVersion{
  113. {Group: "second-group", Version: "first-version"},
  114. {Group: "first-group", Version: "first-version"},
  115. },
  116. KindsToRegister: []unversioned.GroupVersionKind{
  117. {Group: "first-group", Version: "first-version", Kind: "my-kind"},
  118. {Group: "first-group", Version: "first-version", Kind: "your-kind"},
  119. {Group: "second-group", Version: "first-version", Kind: "my-kind"},
  120. {Group: "second-group", Version: "first-version", Kind: "your-kind"},
  121. },
  122. PartialResourceToRequest: unversioned.GroupVersionResource{Resource: "my-kinds"},
  123. ExpectedKinds: []unversioned.GroupVersionKind{
  124. {Group: "second-group", Version: "first-version", Kind: "my-kind"},
  125. {Group: "first-group", Version: "first-version", Kind: "my-kind"},
  126. },
  127. ExpectedKindErr: " matches multiple kinds ",
  128. },
  129. {
  130. Name: "ambiguous groups, with explicit group match",
  131. PreferredOrder: []unversioned.GroupVersion{
  132. {Group: "second-group", Version: "first-version"},
  133. {Group: "first-group", Version: "first-version"},
  134. },
  135. KindsToRegister: []unversioned.GroupVersionKind{
  136. {Group: "first-group", Version: "first-version", Kind: "my-kind"},
  137. {Group: "first-group", Version: "first-version", Kind: "your-kind"},
  138. {Group: "second-group", Version: "first-version", Kind: "my-kind"},
  139. {Group: "second-group", Version: "first-version", Kind: "your-kind"},
  140. },
  141. PartialResourceToRequest: unversioned.GroupVersionResource{Group: "first-group", Resource: "my-kinds"},
  142. ExpectedKinds: []unversioned.GroupVersionKind{
  143. {Group: "first-group", Version: "first-version", Kind: "my-kind"},
  144. },
  145. },
  146. {
  147. Name: "ambiguous groups, with ambiguous version match",
  148. PreferredOrder: []unversioned.GroupVersion{
  149. {Group: "first-group", Version: "first-version"},
  150. {Group: "second-group", Version: "first-version"},
  151. },
  152. KindsToRegister: []unversioned.GroupVersionKind{
  153. {Group: "first-group", Version: "first-version", Kind: "my-kind"},
  154. {Group: "first-group", Version: "first-version", Kind: "your-kind"},
  155. {Group: "second-group", Version: "first-version", Kind: "my-kind"},
  156. {Group: "second-group", Version: "first-version", Kind: "your-kind"},
  157. },
  158. PartialResourceToRequest: unversioned.GroupVersionResource{Version: "first-version", Resource: "my-kinds"},
  159. ExpectedKinds: []unversioned.GroupVersionKind{
  160. {Group: "first-group", Version: "first-version", Kind: "my-kind"},
  161. {Group: "second-group", Version: "first-version", Kind: "my-kind"},
  162. },
  163. ExpectedKindErr: " matches multiple kinds ",
  164. },
  165. }
  166. for _, testCase := range testCases {
  167. tcName := testCase.Name
  168. mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces)
  169. for _, kind := range testCase.KindsToRegister {
  170. mapper.Add(kind, RESTScopeNamespace)
  171. }
  172. actualKinds, err := mapper.KindsFor(testCase.PartialResourceToRequest)
  173. if err != nil {
  174. t.Errorf("%s: unexpected error: %v", tcName, err)
  175. continue
  176. }
  177. if !reflect.DeepEqual(testCase.ExpectedKinds, actualKinds) {
  178. t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKinds, actualKinds)
  179. }
  180. singleKind, err := mapper.KindFor(testCase.PartialResourceToRequest)
  181. if err == nil && len(testCase.ExpectedKindErr) != 0 {
  182. t.Errorf("%s: expected error: %v", tcName, testCase.ExpectedKindErr)
  183. continue
  184. }
  185. if err != nil {
  186. if len(testCase.ExpectedKindErr) == 0 {
  187. t.Errorf("%s: unexpected error: %v", tcName, err)
  188. continue
  189. } else {
  190. if !strings.Contains(err.Error(), testCase.ExpectedKindErr) {
  191. t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKindErr, err)
  192. continue
  193. }
  194. }
  195. } else {
  196. if testCase.ExpectedKinds[0] != singleKind {
  197. t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKinds[0], singleKind)
  198. }
  199. }
  200. }
  201. }
  202. func TestRESTMapperResourcesFor(t *testing.T) {
  203. testCases := []struct {
  204. Name string
  205. PreferredOrder []unversioned.GroupVersion
  206. KindsToRegister []unversioned.GroupVersionKind
  207. PluralPartialResourceToRequest unversioned.GroupVersionResource
  208. SingularPartialResourceToRequest unversioned.GroupVersionResource
  209. ExpectedResources []unversioned.GroupVersionResource
  210. ExpectedResourceErr string
  211. }{
  212. {
  213. Name: "ambiguous groups, with preference order",
  214. PreferredOrder: []unversioned.GroupVersion{
  215. {Group: "second-group", Version: "first-version"},
  216. {Group: "first-group", Version: "first-version"},
  217. },
  218. KindsToRegister: []unversioned.GroupVersionKind{
  219. {Group: "first-group", Version: "first-version", Kind: "my-kind"},
  220. {Group: "first-group", Version: "first-version", Kind: "your-kind"},
  221. {Group: "second-group", Version: "first-version", Kind: "my-kind"},
  222. {Group: "second-group", Version: "first-version", Kind: "your-kind"},
  223. },
  224. PluralPartialResourceToRequest: unversioned.GroupVersionResource{Resource: "my-kinds"},
  225. SingularPartialResourceToRequest: unversioned.GroupVersionResource{Resource: "my-kind"},
  226. ExpectedResources: []unversioned.GroupVersionResource{
  227. {Group: "second-group", Version: "first-version", Resource: "my-kinds"},
  228. {Group: "first-group", Version: "first-version", Resource: "my-kinds"},
  229. },
  230. ExpectedResourceErr: " matches multiple resources ",
  231. },
  232. {
  233. Name: "ambiguous groups, with explicit group match",
  234. PreferredOrder: []unversioned.GroupVersion{
  235. {Group: "second-group", Version: "first-version"},
  236. {Group: "first-group", Version: "first-version"},
  237. },
  238. KindsToRegister: []unversioned.GroupVersionKind{
  239. {Group: "first-group", Version: "first-version", Kind: "my-kind"},
  240. {Group: "first-group", Version: "first-version", Kind: "your-kind"},
  241. {Group: "second-group", Version: "first-version", Kind: "my-kind"},
  242. {Group: "second-group", Version: "first-version", Kind: "your-kind"},
  243. },
  244. PluralPartialResourceToRequest: unversioned.GroupVersionResource{Group: "first-group", Resource: "my-kinds"},
  245. SingularPartialResourceToRequest: unversioned.GroupVersionResource{Group: "first-group", Resource: "my-kind"},
  246. ExpectedResources: []unversioned.GroupVersionResource{
  247. {Group: "first-group", Version: "first-version", Resource: "my-kinds"},
  248. },
  249. },
  250. {
  251. Name: "ambiguous groups, with ambiguous version match",
  252. PreferredOrder: []unversioned.GroupVersion{
  253. {Group: "first-group", Version: "first-version"},
  254. {Group: "second-group", Version: "first-version"},
  255. },
  256. KindsToRegister: []unversioned.GroupVersionKind{
  257. {Group: "first-group", Version: "first-version", Kind: "my-kind"},
  258. {Group: "first-group", Version: "first-version", Kind: "your-kind"},
  259. {Group: "second-group", Version: "first-version", Kind: "my-kind"},
  260. {Group: "second-group", Version: "first-version", Kind: "your-kind"},
  261. },
  262. PluralPartialResourceToRequest: unversioned.GroupVersionResource{Version: "first-version", Resource: "my-kinds"},
  263. SingularPartialResourceToRequest: unversioned.GroupVersionResource{Version: "first-version", Resource: "my-kind"},
  264. ExpectedResources: []unversioned.GroupVersionResource{
  265. {Group: "first-group", Version: "first-version", Resource: "my-kinds"},
  266. {Group: "second-group", Version: "first-version", Resource: "my-kinds"},
  267. },
  268. ExpectedResourceErr: " matches multiple resources ",
  269. },
  270. }
  271. for _, testCase := range testCases {
  272. tcName := testCase.Name
  273. for _, partialResource := range []unversioned.GroupVersionResource{testCase.PluralPartialResourceToRequest, testCase.SingularPartialResourceToRequest} {
  274. mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces)
  275. for _, kind := range testCase.KindsToRegister {
  276. mapper.Add(kind, RESTScopeNamespace)
  277. }
  278. actualResources, err := mapper.ResourcesFor(partialResource)
  279. if err != nil {
  280. t.Errorf("%s: unexpected error: %v", tcName, err)
  281. continue
  282. }
  283. if !reflect.DeepEqual(testCase.ExpectedResources, actualResources) {
  284. t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResources, actualResources)
  285. }
  286. singleResource, err := mapper.ResourceFor(partialResource)
  287. if err == nil && len(testCase.ExpectedResourceErr) != 0 {
  288. t.Errorf("%s: expected error: %v", tcName, testCase.ExpectedResourceErr)
  289. continue
  290. }
  291. if err != nil {
  292. if len(testCase.ExpectedResourceErr) == 0 {
  293. t.Errorf("%s: unexpected error: %v", tcName, err)
  294. continue
  295. } else {
  296. if !strings.Contains(err.Error(), testCase.ExpectedResourceErr) {
  297. t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResourceErr, err)
  298. continue
  299. }
  300. }
  301. } else {
  302. if testCase.ExpectedResources[0] != singleResource {
  303. t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResources[0], singleResource)
  304. }
  305. }
  306. }
  307. }
  308. }
  309. func TestKindToResource(t *testing.T) {
  310. testCases := []struct {
  311. Kind string
  312. Plural, Singular string
  313. }{
  314. {Kind: "Pod", Plural: "pods", Singular: "pod"},
  315. {Kind: "ReplicationController", Plural: "replicationcontrollers", Singular: "replicationcontroller"},
  316. // Add "ies" when ending with "y"
  317. {Kind: "ImageRepository", Plural: "imagerepositories", Singular: "imagerepository"},
  318. // Add "es" when ending with "s"
  319. {Kind: "miss", Plural: "misses", Singular: "miss"},
  320. // Add "s" otherwise
  321. {Kind: "lowercase", Plural: "lowercases", Singular: "lowercase"},
  322. }
  323. for i, testCase := range testCases {
  324. version := unversioned.GroupVersion{}
  325. plural, singular := KindToResource(version.WithKind(testCase.Kind))
  326. if singular != version.WithResource(testCase.Singular) || plural != version.WithResource(testCase.Plural) {
  327. t.Errorf("%d: unexpected plural and singular: %v %v", i, plural, singular)
  328. }
  329. }
  330. }
  331. func TestRESTMapperResourceSingularizer(t *testing.T) {
  332. testGroupVersion := unversioned.GroupVersion{Group: "tgroup", Version: "test"}
  333. testCases := []struct {
  334. Kind string
  335. Plural string
  336. Singular string
  337. }{
  338. {Kind: "Pod", Plural: "pods", Singular: "pod"},
  339. {Kind: "ReplicationController", Plural: "replicationcontrollers", Singular: "replicationcontroller"},
  340. {Kind: "ImageRepository", Plural: "imagerepositories", Singular: "imagerepository"},
  341. {Kind: "Status", Plural: "statuses", Singular: "status"},
  342. {Kind: "lowercase", Plural: "lowercases", Singular: "lowercase"},
  343. // TODO this test is broken. This updates to reflect actual behavior. Kinds are expected to be singular
  344. // old (incorrect), coment: Don't add extra s if the original object is already plural
  345. {Kind: "lowercases", Plural: "lowercaseses", Singular: "lowercases"},
  346. }
  347. for i, testCase := range testCases {
  348. mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion}, fakeInterfaces)
  349. // create singular/plural mapping
  350. mapper.Add(testGroupVersion.WithKind(testCase.Kind), RESTScopeNamespace)
  351. singular, err := mapper.ResourceSingularizer(testCase.Plural)
  352. if err != nil {
  353. t.Errorf("%d: unexpected error: %v", i, err)
  354. }
  355. if singular != testCase.Singular {
  356. t.Errorf("%d: mismatched singular: got %v, expected %v", i, singular, testCase.Singular)
  357. }
  358. }
  359. }
  360. func TestRESTMapperRESTMapping(t *testing.T) {
  361. testGroup := "tgroup"
  362. testGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: "test"}
  363. internalGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: "test"}
  364. testCases := []struct {
  365. Kind string
  366. APIGroupVersions []unversioned.GroupVersion
  367. DefaultVersions []unversioned.GroupVersion
  368. Resource string
  369. ExpectedGroupVersion *unversioned.GroupVersion
  370. Err bool
  371. }{
  372. {Kind: "Unknown", Err: true},
  373. {Kind: "InternalObject", Err: true},
  374. {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "Unknown", Err: true},
  375. {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
  376. {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
  377. {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
  378. {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{}, Resource: "internalobjects", ExpectedGroupVersion: &unversioned.GroupVersion{Group: testGroup, Version: "test"}},
  379. {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"},
  380. // TODO: add test for a resource that exists in one version but not another
  381. }
  382. for i, testCase := range testCases {
  383. mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces)
  384. mapper.Add(internalGroupVersion.WithKind("InternalObject"), RESTScopeNamespace)
  385. preferredVersions := []string{}
  386. for _, gv := range testCase.APIGroupVersions {
  387. preferredVersions = append(preferredVersions, gv.Version)
  388. }
  389. gk := unversioned.GroupKind{Group: testGroup, Kind: testCase.Kind}
  390. mapping, err := mapper.RESTMapping(gk, preferredVersions...)
  391. hasErr := err != nil
  392. if hasErr != testCase.Err {
  393. t.Errorf("%d: unexpected error behavior %t: %v", i, testCase.Err, err)
  394. }
  395. if hasErr {
  396. continue
  397. }
  398. if mapping.Resource != testCase.Resource {
  399. t.Errorf("%d: unexpected resource: %#v", i, mapping)
  400. }
  401. if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil {
  402. t.Errorf("%d: missing codec and accessor: %#v", i, mapping)
  403. }
  404. groupVersion := testCase.ExpectedGroupVersion
  405. if groupVersion == nil {
  406. groupVersion = &testCase.APIGroupVersions[0]
  407. }
  408. if mapping.GroupVersionKind.GroupVersion() != *groupVersion {
  409. t.Errorf("%d: unexpected version: %#v", i, mapping)
  410. }
  411. }
  412. }
  413. func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) {
  414. expectedGroupVersion1 := unversioned.GroupVersion{Group: "tgroup", Version: "test1"}
  415. expectedGroupVersion2 := unversioned.GroupVersion{Group: "tgroup", Version: "test2"}
  416. expectedGroupVersion3 := unversioned.GroupVersion{Group: "tgroup", Version: "test3"}
  417. internalObjectGK := unversioned.GroupKind{Group: "tgroup", Kind: "InternalObject"}
  418. otherObjectGK := unversioned.GroupKind{Group: "tgroup", Kind: "OtherObject"}
  419. mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, fakeInterfaces)
  420. mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace)
  421. mapper.Add(expectedGroupVersion2.WithKind("OtherObject"), RESTScopeNamespace)
  422. // pick default matching object kind based on search order
  423. mapping, err := mapper.RESTMapping(otherObjectGK)
  424. if err != nil {
  425. t.Fatalf("unexpected error: %v", err)
  426. }
  427. if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 {
  428. t.Errorf("unexpected mapping: %#v", mapping)
  429. }
  430. mapping, err = mapper.RESTMapping(internalObjectGK)
  431. if err != nil {
  432. t.Fatalf("unexpected error: %v", err)
  433. }
  434. if mapping.Resource != "internalobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion1 {
  435. t.Errorf("unexpected mapping: %#v", mapping)
  436. }
  437. // mismatch of version
  438. mapping, err = mapper.RESTMapping(internalObjectGK, expectedGroupVersion2.Version)
  439. if err == nil {
  440. t.Errorf("unexpected non-error")
  441. }
  442. mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion1.Version)
  443. if err == nil {
  444. t.Errorf("unexpected non-error")
  445. }
  446. // not in the search versions
  447. mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion3.Version)
  448. if err == nil {
  449. t.Errorf("unexpected non-error")
  450. }
  451. // explicit search order
  452. mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion3.Version, expectedGroupVersion1.Version)
  453. if err == nil {
  454. t.Errorf("unexpected non-error")
  455. }
  456. mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion3.Version, expectedGroupVersion2.Version)
  457. if err != nil {
  458. t.Fatalf("unexpected error: %v", err)
  459. }
  460. if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 {
  461. t.Errorf("unexpected mapping: %#v", mapping)
  462. }
  463. }
  464. func TestRESTMapperReportsErrorOnBadVersion(t *testing.T) {
  465. expectedGroupVersion1 := unversioned.GroupVersion{Group: "tgroup", Version: "test1"}
  466. expectedGroupVersion2 := unversioned.GroupVersion{Group: "tgroup", Version: "test2"}
  467. internalObjectGK := unversioned.GroupKind{Group: "tgroup", Kind: "InternalObject"}
  468. mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, unmatchedVersionInterfaces)
  469. mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace)
  470. _, err := mapper.RESTMapping(internalObjectGK, expectedGroupVersion1.Version)
  471. if err == nil {
  472. t.Errorf("unexpected non-error")
  473. }
  474. }