apiserver_test.go 114 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364
  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 apiserver
  14. import (
  15. "bytes"
  16. "encoding/json"
  17. "errors"
  18. "fmt"
  19. "io"
  20. "io/ioutil"
  21. "net/http"
  22. "net/http/httptest"
  23. "net/url"
  24. "reflect"
  25. "strings"
  26. "sync"
  27. "testing"
  28. "time"
  29. "k8s.io/kubernetes/pkg/admission"
  30. "k8s.io/kubernetes/pkg/api"
  31. apierrs "k8s.io/kubernetes/pkg/api/errors"
  32. "k8s.io/kubernetes/pkg/api/meta"
  33. "k8s.io/kubernetes/pkg/api/rest"
  34. "k8s.io/kubernetes/pkg/api/unversioned"
  35. "k8s.io/kubernetes/pkg/api/v1"
  36. apiservertesting "k8s.io/kubernetes/pkg/apiserver/testing"
  37. "k8s.io/kubernetes/pkg/fields"
  38. "k8s.io/kubernetes/pkg/labels"
  39. "k8s.io/kubernetes/pkg/runtime"
  40. "k8s.io/kubernetes/pkg/util"
  41. "k8s.io/kubernetes/pkg/util/diff"
  42. "k8s.io/kubernetes/pkg/util/sets"
  43. "k8s.io/kubernetes/pkg/version"
  44. "k8s.io/kubernetes/pkg/watch"
  45. "k8s.io/kubernetes/pkg/watch/versioned"
  46. "k8s.io/kubernetes/plugin/pkg/admission/admit"
  47. "k8s.io/kubernetes/plugin/pkg/admission/deny"
  48. "github.com/emicklei/go-restful"
  49. )
  50. func convert(obj runtime.Object) (runtime.Object, error) {
  51. return obj, nil
  52. }
  53. // This creates fake API versions, similar to api/latest.go.
  54. var testAPIGroup = "test.group"
  55. var testAPIGroup2 = "test.group2"
  56. var testInternalGroupVersion = unversioned.GroupVersion{Group: testAPIGroup, Version: runtime.APIVersionInternal}
  57. var testGroupVersion = unversioned.GroupVersion{Group: testAPIGroup, Version: "version"}
  58. var newGroupVersion = unversioned.GroupVersion{Group: testAPIGroup, Version: "version2"}
  59. var testGroup2Version = unversioned.GroupVersion{Group: testAPIGroup2, Version: "version"}
  60. var testInternalGroup2Version = unversioned.GroupVersion{Group: testAPIGroup2, Version: runtime.APIVersionInternal}
  61. var prefix = "apis"
  62. var grouplessGroupVersion = unversioned.GroupVersion{Group: "", Version: "v1"}
  63. var grouplessInternalGroupVersion = unversioned.GroupVersion{Group: "", Version: runtime.APIVersionInternal}
  64. var grouplessPrefix = "api"
  65. var groupVersions = []unversioned.GroupVersion{grouplessGroupVersion, testGroupVersion, newGroupVersion}
  66. var codec = api.Codecs.LegacyCodec(groupVersions...)
  67. var grouplessCodec = api.Codecs.LegacyCodec(grouplessGroupVersion)
  68. var testCodec = api.Codecs.LegacyCodec(testGroupVersion)
  69. var newCodec = api.Codecs.LegacyCodec(newGroupVersion)
  70. var accessor = meta.NewAccessor()
  71. var versioner runtime.ResourceVersioner = accessor
  72. var selfLinker runtime.SelfLinker = accessor
  73. var mapper, namespaceMapper meta.RESTMapper // The mappers with namespace and with legacy namespace scopes.
  74. var admissionControl admission.Interface
  75. var requestContextMapper api.RequestContextMapper
  76. func interfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
  77. switch version {
  78. case testGroupVersion:
  79. return &meta.VersionInterfaces{
  80. ObjectConvertor: api.Scheme,
  81. MetadataAccessor: accessor,
  82. }, nil
  83. case newGroupVersion:
  84. return &meta.VersionInterfaces{
  85. ObjectConvertor: api.Scheme,
  86. MetadataAccessor: accessor,
  87. }, nil
  88. case grouplessGroupVersion:
  89. return &meta.VersionInterfaces{
  90. ObjectConvertor: api.Scheme,
  91. MetadataAccessor: accessor,
  92. }, nil
  93. case testGroup2Version:
  94. return &meta.VersionInterfaces{
  95. ObjectConvertor: api.Scheme,
  96. MetadataAccessor: accessor,
  97. }, nil
  98. default:
  99. return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, groupVersions)
  100. }
  101. }
  102. func newMapper() *meta.DefaultRESTMapper {
  103. return meta.NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion, newGroupVersion}, interfacesFor)
  104. }
  105. func addGrouplessTypes() {
  106. type ListOptions struct {
  107. Object runtime.Object
  108. unversioned.TypeMeta `json:",inline"`
  109. LabelSelector string `json:"labelSelector,omitempty"`
  110. FieldSelector string `json:"fieldSelector,omitempty"`
  111. Watch bool `json:"watch,omitempty"`
  112. ResourceVersion string `json:"resourceVersion,omitempty"`
  113. TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"`
  114. }
  115. api.Scheme.AddKnownTypes(grouplessGroupVersion,
  116. &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &ListOptions{},
  117. &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
  118. api.Scheme.AddKnownTypes(grouplessInternalGroupVersion,
  119. &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &api.ListOptions{},
  120. &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{})
  121. }
  122. func addTestTypes() {
  123. type ListOptions struct {
  124. Object runtime.Object
  125. unversioned.TypeMeta `json:",inline"`
  126. LabelSelector string `json:"labelSelector,omitempty"`
  127. FieldSelector string `json:"fieldSelector,omitempty"`
  128. Watch bool `json:"watch,omitempty"`
  129. ResourceVersion string `json:"resourceVersion,omitempty"`
  130. TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"`
  131. }
  132. api.Scheme.AddKnownTypes(testGroupVersion,
  133. &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &ListOptions{},
  134. &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{},
  135. &SimpleXGSubresource{})
  136. api.Scheme.AddKnownTypes(testGroupVersion, &v1.Pod{})
  137. api.Scheme.AddKnownTypes(testInternalGroupVersion,
  138. &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &api.ListOptions{},
  139. &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{},
  140. &SimpleXGSubresource{})
  141. api.Scheme.AddKnownTypes(testInternalGroupVersion, &api.Pod{})
  142. // Register SimpleXGSubresource in both testGroupVersion and testGroup2Version, and also their
  143. // their corresponding internal versions, to verify that the desired group version object is
  144. // served in the tests.
  145. api.Scheme.AddKnownTypes(testGroup2Version, &SimpleXGSubresource{})
  146. api.Scheme.AddKnownTypes(testInternalGroup2Version, &SimpleXGSubresource{})
  147. versioned.AddToGroupVersion(api.Scheme, testGroupVersion)
  148. }
  149. func addNewTestTypes() {
  150. type ListOptions struct {
  151. Object runtime.Object
  152. unversioned.TypeMeta `json:",inline"`
  153. LabelSelector string `json:"labelSelector,omitempty"`
  154. FieldSelector string `json:"fieldSelector,omitempty"`
  155. Watch bool `json:"watch,omitempty"`
  156. ResourceVersion string `json:"resourceVersion,omitempty"`
  157. TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"`
  158. }
  159. api.Scheme.AddKnownTypes(newGroupVersion,
  160. &apiservertesting.Simple{}, &apiservertesting.SimpleList{}, &ListOptions{},
  161. &api.DeleteOptions{}, &apiservertesting.SimpleGetOptions{}, &apiservertesting.SimpleRoot{},
  162. &v1.Pod{},
  163. )
  164. versioned.AddToGroupVersion(api.Scheme, newGroupVersion)
  165. }
  166. func init() {
  167. // Certain API objects are returned regardless of the contents of storage:
  168. // api.Status is returned in errors
  169. addGrouplessTypes()
  170. addTestTypes()
  171. addNewTestTypes()
  172. nsMapper := newMapper()
  173. // enumerate all supported versions, get the kinds, and register with
  174. // the mapper how to address our resources
  175. for _, gv := range groupVersions {
  176. for kind := range api.Scheme.KnownTypes(gv) {
  177. gvk := gv.WithKind(kind)
  178. root := bool(kind == "SimpleRoot")
  179. if root {
  180. nsMapper.Add(gvk, meta.RESTScopeRoot)
  181. } else {
  182. nsMapper.Add(gvk, meta.RESTScopeNamespace)
  183. }
  184. }
  185. }
  186. mapper = nsMapper
  187. namespaceMapper = nsMapper
  188. admissionControl = admit.NewAlwaysAdmit()
  189. requestContextMapper = api.NewRequestContextMapper()
  190. api.Scheme.AddFieldLabelConversionFunc(grouplessGroupVersion.String(), "Simple",
  191. func(label, value string) (string, string, error) {
  192. return label, value, nil
  193. },
  194. )
  195. api.Scheme.AddFieldLabelConversionFunc(testGroupVersion.String(), "Simple",
  196. func(label, value string) (string, string, error) {
  197. return label, value, nil
  198. },
  199. )
  200. api.Scheme.AddFieldLabelConversionFunc(newGroupVersion.String(), "Simple",
  201. func(label, value string) (string, string, error) {
  202. return label, value, nil
  203. },
  204. )
  205. }
  206. // defaultAPIServer exposes nested objects for testability.
  207. type defaultAPIServer struct {
  208. http.Handler
  209. container *restful.Container
  210. }
  211. // uses the default settings
  212. func handle(storage map[string]rest.Storage) http.Handler {
  213. return handleInternal(storage, admissionControl, selfLinker)
  214. }
  215. // tests with a deny admission controller
  216. func handleDeny(storage map[string]rest.Storage) http.Handler {
  217. return handleInternal(storage, deny.NewAlwaysDeny(), selfLinker)
  218. }
  219. // tests using the new namespace scope mechanism
  220. func handleNamespaced(storage map[string]rest.Storage) http.Handler {
  221. return handleInternal(storage, admissionControl, selfLinker)
  222. }
  223. // tests using a custom self linker
  224. func handleLinker(storage map[string]rest.Storage, selfLinker runtime.SelfLinker) http.Handler {
  225. return handleInternal(storage, admissionControl, selfLinker)
  226. }
  227. func newTestRequestInfoResolver() *RequestInfoResolver {
  228. return &RequestInfoResolver{sets.NewString("api", "apis"), sets.NewString("api")}
  229. }
  230. func handleInternal(storage map[string]rest.Storage, admissionControl admission.Interface, selfLinker runtime.SelfLinker) http.Handler {
  231. container := restful.NewContainer()
  232. container.Router(restful.CurlyRouter{})
  233. mux := container.ServeMux
  234. template := APIGroupVersion{
  235. Storage: storage,
  236. RequestInfoResolver: newTestRequestInfoResolver(),
  237. Creater: api.Scheme,
  238. Convertor: api.Scheme,
  239. Copier: api.Scheme,
  240. Typer: api.Scheme,
  241. Linker: selfLinker,
  242. Mapper: namespaceMapper,
  243. ParameterCodec: api.ParameterCodec,
  244. Admit: admissionControl,
  245. Context: requestContextMapper,
  246. }
  247. // groupless v1 version
  248. {
  249. group := template
  250. group.Root = "/" + grouplessPrefix
  251. group.GroupVersion = grouplessGroupVersion
  252. group.OptionsExternalVersion = &grouplessGroupVersion
  253. group.Serializer = api.Codecs
  254. if err := (&group).InstallREST(container); err != nil {
  255. panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err))
  256. }
  257. }
  258. // group version 1
  259. {
  260. group := template
  261. group.Root = "/" + prefix
  262. group.GroupVersion = testGroupVersion
  263. group.OptionsExternalVersion = &testGroupVersion
  264. group.Serializer = api.Codecs
  265. if err := (&group).InstallREST(container); err != nil {
  266. panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err))
  267. }
  268. }
  269. // group version 2
  270. {
  271. group := template
  272. group.Root = "/" + prefix
  273. group.GroupVersion = newGroupVersion
  274. group.OptionsExternalVersion = &newGroupVersion
  275. group.Serializer = api.Codecs
  276. if err := (&group).InstallREST(container); err != nil {
  277. panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err))
  278. }
  279. }
  280. InstallVersionHandler(mux, container)
  281. return &defaultAPIServer{mux, container}
  282. }
  283. func TestSimpleSetupRight(t *testing.T) {
  284. s := &apiservertesting.Simple{ObjectMeta: api.ObjectMeta{Name: "aName"}}
  285. wire, err := runtime.Encode(codec, s)
  286. if err != nil {
  287. t.Fatal(err)
  288. }
  289. s2, err := runtime.Decode(codec, wire)
  290. if err != nil {
  291. t.Fatal(err)
  292. }
  293. if !reflect.DeepEqual(s, s2) {
  294. t.Fatalf("encode/decode broken:\n%#v\n%#v\n", s, s2)
  295. }
  296. }
  297. func TestSimpleOptionsSetupRight(t *testing.T) {
  298. s := &apiservertesting.SimpleGetOptions{}
  299. wire, err := runtime.Encode(codec, s)
  300. if err != nil {
  301. t.Fatal(err)
  302. }
  303. s2, err := runtime.Decode(codec, wire)
  304. if err != nil {
  305. t.Fatal(err)
  306. }
  307. if !reflect.DeepEqual(s, s2) {
  308. t.Fatalf("encode/decode broken:\n%#v\n%#v\n", s, s2)
  309. }
  310. }
  311. type SimpleRESTStorage struct {
  312. lock sync.Mutex
  313. errors map[string]error
  314. list []apiservertesting.Simple
  315. item apiservertesting.Simple
  316. updated *apiservertesting.Simple
  317. created *apiservertesting.Simple
  318. stream *SimpleStream
  319. deleted string
  320. deleteOptions *api.DeleteOptions
  321. actualNamespace string
  322. namespacePresent bool
  323. // These are set when Watch is called
  324. fakeWatch *watch.FakeWatcher
  325. requestedLabelSelector labels.Selector
  326. requestedFieldSelector fields.Selector
  327. requestedResourceVersion string
  328. requestedResourceNamespace string
  329. // The id requested, and location to return for ResourceLocation
  330. requestedResourceLocationID string
  331. resourceLocation *url.URL
  332. resourceLocationTransport http.RoundTripper
  333. expectedResourceNamespace string
  334. // If non-nil, called inside the WorkFunc when answering update, delete, create.
  335. // obj receives the original input to the update, delete, or create call.
  336. injectedFunction func(obj runtime.Object) (returnObj runtime.Object, err error)
  337. }
  338. func (storage *SimpleRESTStorage) Export(ctx api.Context, name string, opts unversioned.ExportOptions) (runtime.Object, error) {
  339. obj, err := storage.Get(ctx, name)
  340. if err != nil {
  341. return nil, err
  342. }
  343. s, ok := obj.(*apiservertesting.Simple)
  344. if !ok {
  345. return nil, fmt.Errorf("unexpected object")
  346. }
  347. // Set a marker to verify the method was called
  348. s.Other = "exported"
  349. return obj, storage.errors["export"]
  350. }
  351. func (storage *SimpleRESTStorage) List(ctx api.Context, options *api.ListOptions) (runtime.Object, error) {
  352. storage.checkContext(ctx)
  353. result := &apiservertesting.SimpleList{
  354. Items: storage.list,
  355. }
  356. storage.requestedLabelSelector = labels.Everything()
  357. if options != nil && options.LabelSelector != nil {
  358. storage.requestedLabelSelector = options.LabelSelector
  359. }
  360. storage.requestedFieldSelector = fields.Everything()
  361. if options != nil && options.FieldSelector != nil {
  362. storage.requestedFieldSelector = options.FieldSelector
  363. }
  364. return result, storage.errors["list"]
  365. }
  366. type SimpleStream struct {
  367. version string
  368. accept string
  369. contentType string
  370. err error
  371. io.Reader
  372. closed bool
  373. }
  374. func (s *SimpleStream) Close() error {
  375. s.closed = true
  376. return nil
  377. }
  378. func (obj *SimpleStream) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind }
  379. func (s *SimpleStream) InputStream(version, accept string) (io.ReadCloser, bool, string, error) {
  380. s.version = version
  381. s.accept = accept
  382. return s, false, s.contentType, s.err
  383. }
  384. type OutputConnect struct {
  385. response string
  386. }
  387. func (h *OutputConnect) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  388. w.Write([]byte(h.response))
  389. }
  390. func (storage *SimpleRESTStorage) Get(ctx api.Context, id string) (runtime.Object, error) {
  391. storage.checkContext(ctx)
  392. if id == "binary" {
  393. return storage.stream, storage.errors["get"]
  394. }
  395. copied, err := api.Scheme.Copy(&storage.item)
  396. if err != nil {
  397. panic(err)
  398. }
  399. return copied, storage.errors["get"]
  400. }
  401. func (storage *SimpleRESTStorage) checkContext(ctx api.Context) {
  402. storage.actualNamespace, storage.namespacePresent = api.NamespaceFrom(ctx)
  403. }
  404. func (storage *SimpleRESTStorage) Delete(ctx api.Context, id string, options *api.DeleteOptions) (runtime.Object, error) {
  405. storage.checkContext(ctx)
  406. storage.deleted = id
  407. storage.deleteOptions = options
  408. if err := storage.errors["delete"]; err != nil {
  409. return nil, err
  410. }
  411. var obj runtime.Object = &unversioned.Status{Status: unversioned.StatusSuccess}
  412. var err error
  413. if storage.injectedFunction != nil {
  414. obj, err = storage.injectedFunction(&apiservertesting.Simple{ObjectMeta: api.ObjectMeta{Name: id}})
  415. }
  416. return obj, err
  417. }
  418. func (storage *SimpleRESTStorage) New() runtime.Object {
  419. return &apiservertesting.Simple{}
  420. }
  421. func (storage *SimpleRESTStorage) NewList() runtime.Object {
  422. return &apiservertesting.SimpleList{}
  423. }
  424. func (storage *SimpleRESTStorage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) {
  425. storage.checkContext(ctx)
  426. storage.created = obj.(*apiservertesting.Simple)
  427. if err := storage.errors["create"]; err != nil {
  428. return nil, err
  429. }
  430. var err error
  431. if storage.injectedFunction != nil {
  432. obj, err = storage.injectedFunction(obj)
  433. }
  434. return obj, err
  435. }
  436. func (storage *SimpleRESTStorage) Update(ctx api.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
  437. storage.checkContext(ctx)
  438. obj, err := objInfo.UpdatedObject(ctx, &storage.item)
  439. if err != nil {
  440. return nil, false, err
  441. }
  442. storage.updated = obj.(*apiservertesting.Simple)
  443. if err := storage.errors["update"]; err != nil {
  444. return nil, false, err
  445. }
  446. if storage.injectedFunction != nil {
  447. obj, err = storage.injectedFunction(obj)
  448. }
  449. return obj, false, err
  450. }
  451. // Implement ResourceWatcher.
  452. func (storage *SimpleRESTStorage) Watch(ctx api.Context, options *api.ListOptions) (watch.Interface, error) {
  453. storage.lock.Lock()
  454. defer storage.lock.Unlock()
  455. storage.checkContext(ctx)
  456. storage.requestedLabelSelector = labels.Everything()
  457. if options != nil && options.LabelSelector != nil {
  458. storage.requestedLabelSelector = options.LabelSelector
  459. }
  460. storage.requestedFieldSelector = fields.Everything()
  461. if options != nil && options.FieldSelector != nil {
  462. storage.requestedFieldSelector = options.FieldSelector
  463. }
  464. storage.requestedResourceVersion = ""
  465. if options != nil {
  466. storage.requestedResourceVersion = options.ResourceVersion
  467. }
  468. storage.requestedResourceNamespace = api.NamespaceValue(ctx)
  469. if err := storage.errors["watch"]; err != nil {
  470. return nil, err
  471. }
  472. storage.fakeWatch = watch.NewFake()
  473. return storage.fakeWatch, nil
  474. }
  475. func (storage *SimpleRESTStorage) Watcher() *watch.FakeWatcher {
  476. storage.lock.Lock()
  477. defer storage.lock.Unlock()
  478. return storage.fakeWatch
  479. }
  480. // Implement Redirector.
  481. var _ = rest.Redirector(&SimpleRESTStorage{})
  482. // Implement Redirector.
  483. func (storage *SimpleRESTStorage) ResourceLocation(ctx api.Context, id string) (*url.URL, http.RoundTripper, error) {
  484. storage.checkContext(ctx)
  485. // validate that the namespace context on the request matches the expected input
  486. storage.requestedResourceNamespace = api.NamespaceValue(ctx)
  487. if storage.expectedResourceNamespace != storage.requestedResourceNamespace {
  488. return nil, nil, fmt.Errorf("Expected request namespace %s, but got namespace %s", storage.expectedResourceNamespace, storage.requestedResourceNamespace)
  489. }
  490. storage.requestedResourceLocationID = id
  491. if err := storage.errors["resourceLocation"]; err != nil {
  492. return nil, nil, err
  493. }
  494. // Make a copy so the internal URL never gets mutated
  495. locationCopy := *storage.resourceLocation
  496. return &locationCopy, storage.resourceLocationTransport, nil
  497. }
  498. // Implement Connecter
  499. type ConnecterRESTStorage struct {
  500. connectHandler http.Handler
  501. handlerFunc func() http.Handler
  502. emptyConnectOptions runtime.Object
  503. receivedConnectOptions runtime.Object
  504. receivedID string
  505. receivedResponder rest.Responder
  506. takesPath string
  507. }
  508. // Implement Connecter
  509. var _ = rest.Connecter(&ConnecterRESTStorage{})
  510. func (s *ConnecterRESTStorage) New() runtime.Object {
  511. return &apiservertesting.Simple{}
  512. }
  513. func (s *ConnecterRESTStorage) Connect(ctx api.Context, id string, options runtime.Object, responder rest.Responder) (http.Handler, error) {
  514. s.receivedConnectOptions = options
  515. s.receivedID = id
  516. s.receivedResponder = responder
  517. if s.handlerFunc != nil {
  518. return s.handlerFunc(), nil
  519. }
  520. return s.connectHandler, nil
  521. }
  522. func (s *ConnecterRESTStorage) ConnectMethods() []string {
  523. return []string{"GET", "POST", "PUT", "DELETE"}
  524. }
  525. func (s *ConnecterRESTStorage) NewConnectOptions() (runtime.Object, bool, string) {
  526. if len(s.takesPath) > 0 {
  527. return s.emptyConnectOptions, true, s.takesPath
  528. }
  529. return s.emptyConnectOptions, false, ""
  530. }
  531. type LegacyRESTStorage struct {
  532. *SimpleRESTStorage
  533. }
  534. func (storage LegacyRESTStorage) Delete(ctx api.Context, id string) (runtime.Object, error) {
  535. return storage.SimpleRESTStorage.Delete(ctx, id, nil)
  536. }
  537. type MetadataRESTStorage struct {
  538. *SimpleRESTStorage
  539. types []string
  540. }
  541. func (m *MetadataRESTStorage) ProducesMIMETypes(method string) []string {
  542. return m.types
  543. }
  544. var _ rest.StorageMetadata = &MetadataRESTStorage{}
  545. type GetWithOptionsRESTStorage struct {
  546. *SimpleRESTStorage
  547. optionsReceived runtime.Object
  548. takesPath string
  549. }
  550. func (r *GetWithOptionsRESTStorage) Get(ctx api.Context, name string, options runtime.Object) (runtime.Object, error) {
  551. if _, ok := options.(*apiservertesting.SimpleGetOptions); !ok {
  552. return nil, fmt.Errorf("Unexpected options object: %#v", options)
  553. }
  554. r.optionsReceived = options
  555. return r.SimpleRESTStorage.Get(ctx, name)
  556. }
  557. func (r *GetWithOptionsRESTStorage) NewGetOptions() (runtime.Object, bool, string) {
  558. if len(r.takesPath) > 0 {
  559. return &apiservertesting.SimpleGetOptions{}, true, r.takesPath
  560. }
  561. return &apiservertesting.SimpleGetOptions{}, false, ""
  562. }
  563. var _ rest.GetterWithOptions = &GetWithOptionsRESTStorage{}
  564. type NamedCreaterRESTStorage struct {
  565. *SimpleRESTStorage
  566. createdName string
  567. }
  568. func (storage *NamedCreaterRESTStorage) Create(ctx api.Context, name string, obj runtime.Object) (runtime.Object, error) {
  569. storage.checkContext(ctx)
  570. storage.created = obj.(*apiservertesting.Simple)
  571. storage.createdName = name
  572. if err := storage.errors["create"]; err != nil {
  573. return nil, err
  574. }
  575. var err error
  576. if storage.injectedFunction != nil {
  577. obj, err = storage.injectedFunction(obj)
  578. }
  579. return obj, err
  580. }
  581. type SimpleTypedStorage struct {
  582. errors map[string]error
  583. item runtime.Object
  584. baseType runtime.Object
  585. actualNamespace string
  586. namespacePresent bool
  587. }
  588. func (storage *SimpleTypedStorage) New() runtime.Object {
  589. return storage.baseType
  590. }
  591. func (storage *SimpleTypedStorage) Get(ctx api.Context, id string) (runtime.Object, error) {
  592. storage.checkContext(ctx)
  593. copied, err := api.Scheme.Copy(storage.item)
  594. if err != nil {
  595. panic(err)
  596. }
  597. return copied, storage.errors["get"]
  598. }
  599. func (storage *SimpleTypedStorage) checkContext(ctx api.Context) {
  600. storage.actualNamespace, storage.namespacePresent = api.NamespaceFrom(ctx)
  601. }
  602. func extractBody(response *http.Response, object runtime.Object) (string, error) {
  603. return extractBodyDecoder(response, object, codec)
  604. }
  605. func extractBodyDecoder(response *http.Response, object runtime.Object, decoder runtime.Decoder) (string, error) {
  606. defer response.Body.Close()
  607. body, err := ioutil.ReadAll(response.Body)
  608. if err != nil {
  609. return string(body), err
  610. }
  611. return string(body), runtime.DecodeInto(decoder, body, object)
  612. }
  613. func TestNotFound(t *testing.T) {
  614. type T struct {
  615. Method string
  616. Path string
  617. Status int
  618. }
  619. cases := map[string]T{
  620. // Positive checks to make sure everything is wired correctly
  621. "groupless GET root": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusOK},
  622. "groupless GET namespaced": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusOK},
  623. "groupless GET long prefix": {"GET", "/" + grouplessPrefix + "/", http.StatusNotFound},
  624. "groupless root PATCH method": {"PATCH", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
  625. "groupless root GET missing storage": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/blah", http.StatusNotFound},
  626. "groupless root GET with extra segment": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
  627. "groupless root DELETE without extra segment": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
  628. "groupless root DELETE with extra segment": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
  629. "groupless root PUT without extra segment": {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
  630. "groupless root PUT with extra segment": {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
  631. "groupless root watch missing storage": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/", http.StatusNotFound},
  632. "groupless namespaced PATCH method": {"PATCH", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
  633. "groupless namespaced GET long prefix": {"GET", "/" + grouplessPrefix + "/", http.StatusNotFound},
  634. "groupless namespaced GET missing storage": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/blah", http.StatusNotFound},
  635. "groupless namespaced GET with extra segment": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
  636. "groupless namespaced POST with extra segment": {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
  637. "groupless namespaced DELETE without extra segment": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
  638. "groupless namespaced DELETE with extra segment": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
  639. "groupless namespaced PUT without extra segment": {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
  640. "groupless namespaced PUT with extra segment": {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
  641. "groupless namespaced watch missing storage": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/", http.StatusNotFound},
  642. "groupless namespaced watch with bad method": {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
  643. // Positive checks to make sure everything is wired correctly
  644. "GET root": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusOK},
  645. // TODO: JTL: "GET root item": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar", http.StatusOK},
  646. "GET namespaced": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusOK},
  647. // TODO: JTL: "GET namespaced item": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar", http.StatusOK},
  648. "GET long prefix": {"GET", "/" + prefix + "/", http.StatusNotFound},
  649. "root PATCH method": {"PATCH", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
  650. "root GET missing storage": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/blah", http.StatusNotFound},
  651. "root GET with extra segment": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
  652. // TODO: JTL: "root POST with extra segment": {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar", http.StatusMethodNotAllowed},
  653. "root DELETE without extra segment": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
  654. "root DELETE with extra segment": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
  655. "root PUT without extra segment": {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots", http.StatusMethodNotAllowed},
  656. "root PUT with extra segment": {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simpleroots/bar/baz", http.StatusNotFound},
  657. "root watch missing storage": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/", http.StatusNotFound},
  658. // TODO: JTL: "root watch with bad method": {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/simpleroot/bar", http.StatusMethodNotAllowed},
  659. "namespaced PATCH method": {"PATCH", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
  660. "namespaced GET long prefix": {"GET", "/" + prefix + "/", http.StatusNotFound},
  661. "namespaced GET missing storage": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/blah", http.StatusNotFound},
  662. "namespaced GET with extra segment": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
  663. "namespaced POST with extra segment": {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
  664. "namespaced DELETE without extra segment": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
  665. "namespaced DELETE with extra segment": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
  666. "namespaced PUT without extra segment": {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples", http.StatusMethodNotAllowed},
  667. "namespaced PUT with extra segment": {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/ns/simples/bar/baz", http.StatusNotFound},
  668. "namespaced watch missing storage": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/", http.StatusNotFound},
  669. "namespaced watch with bad method": {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/namespaces/ns/simples/bar", http.StatusMethodNotAllowed},
  670. }
  671. handler := handle(map[string]rest.Storage{
  672. "simples": &SimpleRESTStorage{},
  673. "simpleroots": &SimpleRESTStorage{},
  674. })
  675. server := httptest.NewServer(handler)
  676. defer server.Close()
  677. client := http.Client{}
  678. for k, v := range cases {
  679. request, err := http.NewRequest(v.Method, server.URL+v.Path, nil)
  680. if err != nil {
  681. t.Fatalf("unexpected error: %v", err)
  682. }
  683. response, err := client.Do(request)
  684. if err != nil {
  685. t.Errorf("unexpected error: %v", err)
  686. }
  687. if response.StatusCode != v.Status {
  688. t.Errorf("Expected %d for %s (%s), Got %#v", v.Status, v.Method, k, response)
  689. t.Errorf("MAPPER: %v", mapper)
  690. }
  691. }
  692. }
  693. type UnimplementedRESTStorage struct{}
  694. func (UnimplementedRESTStorage) New() runtime.Object {
  695. return &apiservertesting.Simple{}
  696. }
  697. // TestUnimplementedRESTStorage ensures that if a rest.Storage does not implement a given
  698. // method, that it is literally not registered with the server. In the past,
  699. // we registered everything, and returned method not supported if it didn't support
  700. // a verb. Now we literally do not register a storage if it does not implement anything.
  701. // TODO: in future, we should update proxy/redirect
  702. func TestUnimplementedRESTStorage(t *testing.T) {
  703. type T struct {
  704. Method string
  705. Path string
  706. ErrCode int
  707. }
  708. cases := map[string]T{
  709. "groupless GET object": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo/bar", http.StatusNotFound},
  710. "groupless GET list": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo", http.StatusNotFound},
  711. "groupless POST list": {"POST", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo", http.StatusNotFound},
  712. "groupless PUT object": {"PUT", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo/bar", http.StatusNotFound},
  713. "groupless DELETE object": {"DELETE", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/foo/bar", http.StatusNotFound},
  714. "groupless watch list": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/foo", http.StatusNotFound},
  715. "groupless watch object": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/watch/foo/bar", http.StatusNotFound},
  716. "groupless proxy object": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/proxy/foo/bar", http.StatusNotFound},
  717. "groupless redirect object": {"GET", "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/redirect/foo/bar", http.StatusNotFound},
  718. "GET object": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
  719. "GET list": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo", http.StatusNotFound},
  720. "POST list": {"POST", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo", http.StatusNotFound},
  721. "PUT object": {"PUT", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
  722. "DELETE object": {"DELETE", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/foo/bar", http.StatusNotFound},
  723. "watch list": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/foo", http.StatusNotFound},
  724. "watch object": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/watch/foo/bar", http.StatusNotFound},
  725. "proxy object": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/proxy/foo/bar", http.StatusNotFound},
  726. "redirect object": {"GET", "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/redirect/foo/bar", http.StatusNotFound},
  727. }
  728. handler := handle(map[string]rest.Storage{
  729. "foo": UnimplementedRESTStorage{},
  730. })
  731. server := httptest.NewServer(handler)
  732. defer server.Close()
  733. client := http.Client{}
  734. for k, v := range cases {
  735. request, err := http.NewRequest(v.Method, server.URL+v.Path, bytes.NewReader([]byte(`{"kind":"Simple","apiVersion":"version"}`)))
  736. if err != nil {
  737. t.Fatalf("unexpected error: %v", err)
  738. }
  739. response, err := client.Do(request)
  740. if err != nil {
  741. t.Fatalf("unexpected error: %v", err)
  742. }
  743. defer response.Body.Close()
  744. data, err := ioutil.ReadAll(response.Body)
  745. if err != nil {
  746. t.Fatalf("unexpected error: %v", err)
  747. }
  748. if response.StatusCode != v.ErrCode {
  749. t.Errorf("%s: expected %d for %s, Got %s", k, v.ErrCode, v.Method, string(data))
  750. continue
  751. }
  752. }
  753. }
  754. func TestVersion(t *testing.T) {
  755. handler := handle(map[string]rest.Storage{})
  756. server := httptest.NewServer(handler)
  757. defer server.Close()
  758. client := http.Client{}
  759. request, err := http.NewRequest("GET", server.URL+"/version", nil)
  760. if err != nil {
  761. t.Errorf("unexpected error: %v", err)
  762. }
  763. response, err := client.Do(request)
  764. if err != nil {
  765. t.Errorf("unexpected error: %v", err)
  766. }
  767. var info version.Info
  768. err = json.NewDecoder(response.Body).Decode(&info)
  769. if err != nil {
  770. t.Errorf("unexpected error: %v", err)
  771. }
  772. if !reflect.DeepEqual(version.Get(), info) {
  773. t.Errorf("Expected %#v, Got %#v", version.Get(), info)
  774. }
  775. }
  776. func TestList(t *testing.T) {
  777. testCases := []struct {
  778. url string
  779. namespace string
  780. selfLink string
  781. legacy bool
  782. label string
  783. field string
  784. }{
  785. // Groupless API
  786. // legacy namespace param is ignored
  787. {
  788. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple?namespace=",
  789. namespace: "",
  790. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple",
  791. legacy: true,
  792. },
  793. {
  794. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple?namespace=other",
  795. namespace: "",
  796. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple",
  797. legacy: true,
  798. },
  799. {
  800. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple?namespace=other&labelSelector=a%3Db&fieldSelector=c%3Dd",
  801. namespace: "",
  802. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple",
  803. legacy: true,
  804. label: "a=b",
  805. field: "c=d",
  806. },
  807. // legacy api version is honored
  808. {
  809. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple",
  810. namespace: "",
  811. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple",
  812. legacy: true,
  813. },
  814. {
  815. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/other/simple",
  816. namespace: "other",
  817. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/other/simple",
  818. legacy: true,
  819. },
  820. {
  821. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd",
  822. namespace: "other",
  823. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/other/simple",
  824. legacy: true,
  825. label: "a=b",
  826. field: "c=d",
  827. },
  828. // list items across all namespaces
  829. {
  830. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple",
  831. namespace: "",
  832. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple",
  833. legacy: true,
  834. },
  835. // list items in a namespace in the path
  836. {
  837. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/simple",
  838. namespace: "default",
  839. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/default/simple",
  840. },
  841. {
  842. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/other/simple",
  843. namespace: "other",
  844. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/other/simple",
  845. },
  846. {
  847. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd",
  848. namespace: "other",
  849. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/namespaces/other/simple",
  850. label: "a=b",
  851. field: "c=d",
  852. },
  853. // list items across all namespaces
  854. {
  855. url: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple",
  856. namespace: "",
  857. selfLink: "/" + grouplessPrefix + "/" + grouplessGroupVersion.Version + "/simple",
  858. },
  859. // Group API
  860. // legacy namespace param is ignored
  861. {
  862. url: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple?namespace=",
  863. namespace: "",
  864. selfLink: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple",
  865. legacy: true,
  866. },
  867. {
  868. url: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple?namespace=other",
  869. namespace: "",
  870. selfLink: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple",
  871. legacy: true,
  872. },
  873. {
  874. url: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple?namespace=other&labelSelector=a%3Db&fieldSelector=c%3Dd",
  875. namespace: "",
  876. selfLink: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple",
  877. legacy: true,
  878. label: "a=b",
  879. field: "c=d",
  880. },
  881. // legacy api version is honored
  882. {
  883. url: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple",
  884. namespace: "",
  885. selfLink: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple",
  886. legacy: true,
  887. },
  888. {
  889. url: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/other/simple",
  890. namespace: "other",
  891. selfLink: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/other/simple",
  892. legacy: true,
  893. },
  894. {
  895. url: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd",
  896. namespace: "other",
  897. selfLink: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/other/simple",
  898. legacy: true,
  899. label: "a=b",
  900. field: "c=d",
  901. },
  902. // list items across all namespaces
  903. {
  904. url: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple",
  905. namespace: "",
  906. selfLink: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple",
  907. legacy: true,
  908. },
  909. // list items in a namespace in the path
  910. {
  911. url: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/default/simple",
  912. namespace: "default",
  913. selfLink: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/default/simple",
  914. },
  915. {
  916. url: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/other/simple",
  917. namespace: "other",
  918. selfLink: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/other/simple",
  919. },
  920. {
  921. url: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/other/simple?labelSelector=a%3Db&fieldSelector=c%3Dd",
  922. namespace: "other",
  923. selfLink: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/other/simple",
  924. label: "a=b",
  925. field: "c=d",
  926. },
  927. // list items across all namespaces
  928. {
  929. url: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/simple",
  930. namespace: "",
  931. selfLink: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/simple",
  932. },
  933. }
  934. for i, testCase := range testCases {
  935. storage := map[string]rest.Storage{}
  936. simpleStorage := SimpleRESTStorage{expectedResourceNamespace: testCase.namespace}
  937. storage["simple"] = &simpleStorage
  938. selfLinker := &setTestSelfLinker{
  939. t: t,
  940. namespace: testCase.namespace,
  941. expectedSet: testCase.selfLink,
  942. }
  943. var handler = handleInternal(storage, admissionControl, selfLinker)
  944. server := httptest.NewServer(handler)
  945. defer server.Close()
  946. resp, err := http.Get(server.URL + testCase.url)
  947. if err != nil {
  948. t.Errorf("%d: unexpected error: %v", i, err)
  949. continue
  950. }
  951. defer resp.Body.Close()
  952. if resp.StatusCode != http.StatusOK {
  953. t.Errorf("%d: unexpected status: %d from url %s, Expected: %d, %#v", i, resp.StatusCode, testCase.url, http.StatusOK, resp)
  954. body, err := ioutil.ReadAll(resp.Body)
  955. if err != nil {
  956. t.Errorf("%d: unexpected error: %v", i, err)
  957. continue
  958. }
  959. t.Logf("%d: body: %s", i, string(body))
  960. continue
  961. }
  962. // TODO: future, restore get links
  963. if !selfLinker.called {
  964. t.Errorf("%d: never set self link", i)
  965. }
  966. if !simpleStorage.namespacePresent {
  967. t.Errorf("%d: namespace not set", i)
  968. } else if simpleStorage.actualNamespace != testCase.namespace {
  969. t.Errorf("%d: unexpected resource namespace: %s", i, simpleStorage.actualNamespace)
  970. }
  971. if simpleStorage.requestedLabelSelector == nil || simpleStorage.requestedLabelSelector.String() != testCase.label {
  972. t.Errorf("%d: unexpected label selector: %v", i, simpleStorage.requestedLabelSelector)
  973. }
  974. if simpleStorage.requestedFieldSelector == nil || simpleStorage.requestedFieldSelector.String() != testCase.field {
  975. t.Errorf("%d: unexpected field selector: %v", i, simpleStorage.requestedFieldSelector)
  976. }
  977. }
  978. }
  979. func TestLogs(t *testing.T) {
  980. handler := handle(map[string]rest.Storage{})
  981. server := httptest.NewServer(handler)
  982. defer server.Close()
  983. client := http.Client{}
  984. request, err := http.NewRequest("GET", server.URL+"/logs", nil)
  985. if err != nil {
  986. t.Errorf("unexpected error: %v", err)
  987. }
  988. response, err := client.Do(request)
  989. if err != nil {
  990. t.Errorf("unexpected error: %v", err)
  991. }
  992. body, err := ioutil.ReadAll(response.Body)
  993. if err != nil {
  994. t.Fatalf("unexpected error: %v", err)
  995. }
  996. t.Logf("Data: %s", string(body))
  997. }
  998. func TestErrorList(t *testing.T) {
  999. storage := map[string]rest.Storage{}
  1000. simpleStorage := SimpleRESTStorage{
  1001. errors: map[string]error{"list": fmt.Errorf("test Error")},
  1002. }
  1003. storage["simple"] = &simpleStorage
  1004. handler := handle(storage)
  1005. server := httptest.NewServer(handler)
  1006. defer server.Close()
  1007. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple")
  1008. if err != nil {
  1009. t.Fatalf("unexpected error: %v", err)
  1010. }
  1011. if resp.StatusCode != http.StatusInternalServerError {
  1012. t.Errorf("Unexpected status: %d, Expected: %d, %#v", resp.StatusCode, http.StatusInternalServerError, resp)
  1013. }
  1014. }
  1015. func TestNonEmptyList(t *testing.T) {
  1016. storage := map[string]rest.Storage{}
  1017. simpleStorage := SimpleRESTStorage{
  1018. list: []apiservertesting.Simple{
  1019. {
  1020. ObjectMeta: api.ObjectMeta{Name: "something", Namespace: "other"},
  1021. Other: "foo",
  1022. },
  1023. },
  1024. }
  1025. storage["simple"] = &simpleStorage
  1026. handler := handle(storage)
  1027. server := httptest.NewServer(handler)
  1028. defer server.Close()
  1029. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple")
  1030. if err != nil {
  1031. t.Fatalf("unexpected error: %v", err)
  1032. }
  1033. if resp.StatusCode != http.StatusOK {
  1034. t.Errorf("Unexpected status: %d, Expected: %d, %#v", resp.StatusCode, http.StatusOK, resp)
  1035. body, err := ioutil.ReadAll(resp.Body)
  1036. if err != nil {
  1037. t.Fatalf("unexpected error: %v", err)
  1038. }
  1039. t.Logf("Data: %s", string(body))
  1040. }
  1041. var listOut apiservertesting.SimpleList
  1042. body, err := extractBody(resp, &listOut)
  1043. if err != nil {
  1044. t.Fatalf("unexpected error: %v", err)
  1045. }
  1046. if len(listOut.Items) != 1 {
  1047. t.Errorf("Unexpected response: %#v", listOut)
  1048. return
  1049. }
  1050. if listOut.Items[0].Other != simpleStorage.list[0].Other {
  1051. t.Errorf("Unexpected data: %#v, %s", listOut.Items[0], string(body))
  1052. }
  1053. if listOut.SelfLink != "/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/simple" {
  1054. t.Errorf("unexpected list self link: %#v", listOut)
  1055. }
  1056. expectedSelfLink := "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/other/simple/something"
  1057. if listOut.Items[0].ObjectMeta.SelfLink != expectedSelfLink {
  1058. t.Errorf("Unexpected data: %#v, %s", listOut.Items[0].ObjectMeta.SelfLink, expectedSelfLink)
  1059. }
  1060. }
  1061. func TestSelfLinkSkipsEmptyName(t *testing.T) {
  1062. storage := map[string]rest.Storage{}
  1063. simpleStorage := SimpleRESTStorage{
  1064. list: []apiservertesting.Simple{
  1065. {
  1066. ObjectMeta: api.ObjectMeta{Namespace: "other"},
  1067. Other: "foo",
  1068. },
  1069. },
  1070. }
  1071. storage["simple"] = &simpleStorage
  1072. handler := handle(storage)
  1073. server := httptest.NewServer(handler)
  1074. defer server.Close()
  1075. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/simple")
  1076. if err != nil {
  1077. t.Fatalf("unexpected error: %v", err)
  1078. }
  1079. if resp.StatusCode != http.StatusOK {
  1080. t.Errorf("Unexpected status: %d, Expected: %d, %#v", resp.StatusCode, http.StatusOK, resp)
  1081. body, err := ioutil.ReadAll(resp.Body)
  1082. if err != nil {
  1083. t.Fatalf("unexpected error: %v", err)
  1084. }
  1085. t.Logf("Data: %s", string(body))
  1086. }
  1087. var listOut apiservertesting.SimpleList
  1088. body, err := extractBody(resp, &listOut)
  1089. if err != nil {
  1090. t.Fatalf("unexpected error: %v", err)
  1091. }
  1092. if len(listOut.Items) != 1 {
  1093. t.Errorf("Unexpected response: %#v", listOut)
  1094. return
  1095. }
  1096. if listOut.Items[0].Other != simpleStorage.list[0].Other {
  1097. t.Errorf("Unexpected data: %#v, %s", listOut.Items[0], string(body))
  1098. }
  1099. if listOut.SelfLink != "/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/simple" {
  1100. t.Errorf("unexpected list self link: %#v", listOut)
  1101. }
  1102. expectedSelfLink := ""
  1103. if listOut.Items[0].ObjectMeta.SelfLink != expectedSelfLink {
  1104. t.Errorf("Unexpected data: %#v, %s", listOut.Items[0].ObjectMeta.SelfLink, expectedSelfLink)
  1105. }
  1106. }
  1107. func TestMetadata(t *testing.T) {
  1108. simpleStorage := &MetadataRESTStorage{&SimpleRESTStorage{}, []string{"text/plain"}}
  1109. h := handle(map[string]rest.Storage{"simple": simpleStorage})
  1110. ws := h.(*defaultAPIServer).container.RegisteredWebServices()
  1111. if len(ws) == 0 {
  1112. t.Fatal("no web services registered")
  1113. }
  1114. matches := map[string]int{}
  1115. for _, w := range ws {
  1116. for _, r := range w.Routes() {
  1117. s := strings.Join(r.Produces, ",")
  1118. i := matches[s]
  1119. matches[s] = i + 1
  1120. }
  1121. }
  1122. if matches["text/plain,application/json,application/yaml,application/vnd.kubernetes.protobuf"] == 0 ||
  1123. matches["application/json,application/json;stream=watch,application/vnd.kubernetes.protobuf,application/vnd.kubernetes.protobuf;stream=watch"] == 0 ||
  1124. matches["application/json,application/yaml,application/vnd.kubernetes.protobuf"] == 0 ||
  1125. matches["application/json"] == 0 ||
  1126. matches["*/*"] == 0 ||
  1127. len(matches) != 5 {
  1128. t.Errorf("unexpected mime types: %v", matches)
  1129. }
  1130. }
  1131. func TestExport(t *testing.T) {
  1132. storage := map[string]rest.Storage{}
  1133. simpleStorage := SimpleRESTStorage{
  1134. item: apiservertesting.Simple{
  1135. ObjectMeta: api.ObjectMeta{
  1136. ResourceVersion: "1234",
  1137. CreationTimestamp: unversioned.NewTime(time.Unix(10, 10)),
  1138. },
  1139. Other: "foo",
  1140. },
  1141. }
  1142. selfLinker := &setTestSelfLinker{
  1143. t: t,
  1144. expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/id",
  1145. name: "id",
  1146. namespace: "default",
  1147. }
  1148. storage["simple"] = &simpleStorage
  1149. handler := handleLinker(storage, selfLinker)
  1150. server := httptest.NewServer(handler)
  1151. defer server.Close()
  1152. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/id?export=true")
  1153. if err != nil {
  1154. t.Fatalf("unexpected error: %v", err)
  1155. }
  1156. if resp.StatusCode != http.StatusOK {
  1157. data, _ := ioutil.ReadAll(resp.Body)
  1158. resp.Body.Close()
  1159. t.Fatalf("unexpected response: %#v\n%s\n", resp, string(data))
  1160. }
  1161. var itemOut apiservertesting.Simple
  1162. body, err := extractBody(resp, &itemOut)
  1163. if err != nil {
  1164. t.Errorf("unexpected error: %v", err)
  1165. }
  1166. if itemOut.Name != simpleStorage.item.Name {
  1167. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simpleStorage.item, string(body))
  1168. }
  1169. if itemOut.Other != "exported" {
  1170. t.Errorf("Expected: exported, saw: %s", itemOut.Other)
  1171. }
  1172. if !selfLinker.called {
  1173. t.Errorf("Never set self link")
  1174. }
  1175. }
  1176. func TestGet(t *testing.T) {
  1177. storage := map[string]rest.Storage{}
  1178. simpleStorage := SimpleRESTStorage{
  1179. item: apiservertesting.Simple{
  1180. Other: "foo",
  1181. },
  1182. }
  1183. selfLinker := &setTestSelfLinker{
  1184. t: t,
  1185. expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/id",
  1186. name: "id",
  1187. namespace: "default",
  1188. }
  1189. storage["simple"] = &simpleStorage
  1190. handler := handleLinker(storage, selfLinker)
  1191. server := httptest.NewServer(handler)
  1192. defer server.Close()
  1193. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/id")
  1194. if err != nil {
  1195. t.Fatalf("unexpected error: %v", err)
  1196. }
  1197. if resp.StatusCode != http.StatusOK {
  1198. t.Fatalf("unexpected response: %#v", resp)
  1199. }
  1200. var itemOut apiservertesting.Simple
  1201. body, err := extractBody(resp, &itemOut)
  1202. if err != nil {
  1203. t.Errorf("unexpected error: %v", err)
  1204. }
  1205. if itemOut.Name != simpleStorage.item.Name {
  1206. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simpleStorage.item, string(body))
  1207. }
  1208. if !selfLinker.called {
  1209. t.Errorf("Never set self link")
  1210. }
  1211. }
  1212. func TestGetBinary(t *testing.T) {
  1213. simpleStorage := SimpleRESTStorage{
  1214. stream: &SimpleStream{
  1215. contentType: "text/plain",
  1216. Reader: bytes.NewBufferString("response data"),
  1217. },
  1218. }
  1219. stream := simpleStorage.stream
  1220. server := httptest.NewServer(handle(map[string]rest.Storage{"simple": &simpleStorage}))
  1221. defer server.Close()
  1222. req, err := http.NewRequest("GET", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/binary", nil)
  1223. if err != nil {
  1224. t.Fatalf("unexpected error: %v", err)
  1225. }
  1226. req.Header.Add("Accept", "text/other, */*")
  1227. resp, err := http.DefaultClient.Do(req)
  1228. if err != nil {
  1229. t.Fatalf("unexpected error: %v", err)
  1230. }
  1231. if resp.StatusCode != http.StatusOK {
  1232. t.Fatalf("unexpected response: %#v", resp)
  1233. }
  1234. body, err := ioutil.ReadAll(resp.Body)
  1235. if err != nil {
  1236. t.Errorf("unexpected error: %v", err)
  1237. }
  1238. if !stream.closed || stream.version != testGroupVersion.String() || stream.accept != "text/other, */*" ||
  1239. resp.Header.Get("Content-Type") != stream.contentType || string(body) != "response data" {
  1240. t.Errorf("unexpected stream: %#v", stream)
  1241. }
  1242. }
  1243. func validateSimpleGetOptionsParams(t *testing.T, route *restful.Route) {
  1244. // Validate name and description
  1245. expectedParams := map[string]string{
  1246. "param1": "description for param1",
  1247. "param2": "description for param2",
  1248. "atAPath": "",
  1249. }
  1250. for _, p := range route.ParameterDocs {
  1251. data := p.Data()
  1252. if desc, exists := expectedParams[data.Name]; exists {
  1253. if desc != data.Description {
  1254. t.Errorf("unexpected description for parameter %s: %s\n", data.Name, data.Description)
  1255. }
  1256. delete(expectedParams, data.Name)
  1257. }
  1258. }
  1259. if len(expectedParams) > 0 {
  1260. t.Errorf("did not find all expected parameters: %#v", expectedParams)
  1261. }
  1262. }
  1263. func TestGetWithOptionsRouteParams(t *testing.T) {
  1264. storage := map[string]rest.Storage{}
  1265. simpleStorage := GetWithOptionsRESTStorage{
  1266. SimpleRESTStorage: &SimpleRESTStorage{},
  1267. }
  1268. storage["simple"] = &simpleStorage
  1269. handler := handle(storage)
  1270. ws := handler.(*defaultAPIServer).container.RegisteredWebServices()
  1271. if len(ws) == 0 {
  1272. t.Fatal("no web services registered")
  1273. }
  1274. routes := ws[0].Routes()
  1275. for i := range routes {
  1276. if routes[i].Method == "GET" && routes[i].Operation == "readNamespacedSimple" {
  1277. validateSimpleGetOptionsParams(t, &routes[i])
  1278. break
  1279. }
  1280. }
  1281. }
  1282. func TestGetWithOptions(t *testing.T) {
  1283. storage := map[string]rest.Storage{}
  1284. simpleStorage := GetWithOptionsRESTStorage{
  1285. SimpleRESTStorage: &SimpleRESTStorage{
  1286. item: apiservertesting.Simple{
  1287. Other: "foo",
  1288. },
  1289. },
  1290. }
  1291. storage["simple"] = &simpleStorage
  1292. handler := handle(storage)
  1293. server := httptest.NewServer(handler)
  1294. defer server.Close()
  1295. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/id?param1=test1&param2=test2")
  1296. if err != nil {
  1297. t.Fatalf("unexpected error: %v", err)
  1298. }
  1299. if resp.StatusCode != http.StatusOK {
  1300. t.Fatalf("unexpected response: %#v", resp)
  1301. }
  1302. var itemOut apiservertesting.Simple
  1303. body, err := extractBody(resp, &itemOut)
  1304. if err != nil {
  1305. t.Errorf("unexpected error: %v", err)
  1306. }
  1307. if itemOut.Name != simpleStorage.item.Name {
  1308. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simpleStorage.item, string(body))
  1309. }
  1310. opts, ok := simpleStorage.optionsReceived.(*apiservertesting.SimpleGetOptions)
  1311. if !ok {
  1312. t.Errorf("Unexpected options object received: %#v", simpleStorage.optionsReceived)
  1313. return
  1314. }
  1315. if opts.Param1 != "test1" || opts.Param2 != "test2" {
  1316. t.Errorf("Did not receive expected options: %#v", opts)
  1317. }
  1318. }
  1319. func TestGetWithOptionsAndPath(t *testing.T) {
  1320. storage := map[string]rest.Storage{}
  1321. simpleStorage := GetWithOptionsRESTStorage{
  1322. SimpleRESTStorage: &SimpleRESTStorage{
  1323. item: apiservertesting.Simple{
  1324. Other: "foo",
  1325. },
  1326. },
  1327. takesPath: "atAPath",
  1328. }
  1329. storage["simple"] = &simpleStorage
  1330. handler := handle(storage)
  1331. server := httptest.NewServer(handler)
  1332. defer server.Close()
  1333. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/id/a/different/path?param1=test1&param2=test2&atAPath=not")
  1334. if err != nil {
  1335. t.Fatalf("unexpected error: %v", err)
  1336. }
  1337. if resp.StatusCode != http.StatusOK {
  1338. t.Fatalf("unexpected response: %#v", resp)
  1339. }
  1340. var itemOut apiservertesting.Simple
  1341. body, err := extractBody(resp, &itemOut)
  1342. if err != nil {
  1343. t.Errorf("unexpected error: %v", err)
  1344. }
  1345. if itemOut.Name != simpleStorage.item.Name {
  1346. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simpleStorage.item, string(body))
  1347. }
  1348. opts, ok := simpleStorage.optionsReceived.(*apiservertesting.SimpleGetOptions)
  1349. if !ok {
  1350. t.Errorf("Unexpected options object received: %#v", simpleStorage.optionsReceived)
  1351. return
  1352. }
  1353. if opts.Param1 != "test1" || opts.Param2 != "test2" || opts.Path != "a/different/path" {
  1354. t.Errorf("Did not receive expected options: %#v", opts)
  1355. }
  1356. }
  1357. func TestGetAlternateSelfLink(t *testing.T) {
  1358. storage := map[string]rest.Storage{}
  1359. simpleStorage := SimpleRESTStorage{
  1360. item: apiservertesting.Simple{
  1361. Other: "foo",
  1362. },
  1363. }
  1364. selfLinker := &setTestSelfLinker{
  1365. t: t,
  1366. expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/test/simple/id",
  1367. name: "id",
  1368. namespace: "test",
  1369. }
  1370. storage["simple"] = &simpleStorage
  1371. handler := handleLinker(storage, selfLinker)
  1372. server := httptest.NewServer(handler)
  1373. defer server.Close()
  1374. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/test/simple/id")
  1375. if err != nil {
  1376. t.Fatalf("unexpected error: %v", err)
  1377. }
  1378. if resp.StatusCode != http.StatusOK {
  1379. t.Fatalf("unexpected response: %#v", resp)
  1380. }
  1381. var itemOut apiservertesting.Simple
  1382. body, err := extractBody(resp, &itemOut)
  1383. if err != nil {
  1384. t.Fatalf("unexpected error: %v", err)
  1385. }
  1386. if itemOut.Name != simpleStorage.item.Name {
  1387. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simpleStorage.item, string(body))
  1388. }
  1389. if !selfLinker.called {
  1390. t.Errorf("Never set self link")
  1391. }
  1392. }
  1393. func TestGetNamespaceSelfLink(t *testing.T) {
  1394. storage := map[string]rest.Storage{}
  1395. simpleStorage := SimpleRESTStorage{
  1396. item: apiservertesting.Simple{
  1397. Other: "foo",
  1398. },
  1399. }
  1400. selfLinker := &setTestSelfLinker{
  1401. t: t,
  1402. expectedSet: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/foo/simple/id",
  1403. name: "id",
  1404. namespace: "foo",
  1405. }
  1406. storage["simple"] = &simpleStorage
  1407. handler := handleInternal(storage, admissionControl, selfLinker)
  1408. server := httptest.NewServer(handler)
  1409. defer server.Close()
  1410. resp, err := http.Get(server.URL + "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/foo/simple/id")
  1411. if err != nil {
  1412. t.Fatalf("unexpected error: %v", err)
  1413. }
  1414. if resp.StatusCode != http.StatusOK {
  1415. t.Fatalf("unexpected response: %#v", resp)
  1416. }
  1417. var itemOut apiservertesting.Simple
  1418. body, err := extractBody(resp, &itemOut)
  1419. if err != nil {
  1420. t.Fatalf("unexpected error: %v", err)
  1421. }
  1422. if itemOut.Name != simpleStorage.item.Name {
  1423. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simpleStorage.item, string(body))
  1424. }
  1425. if !selfLinker.called {
  1426. t.Errorf("Never set self link")
  1427. }
  1428. }
  1429. func TestGetMissing(t *testing.T) {
  1430. storage := map[string]rest.Storage{}
  1431. simpleStorage := SimpleRESTStorage{
  1432. errors: map[string]error{"get": apierrs.NewNotFound(api.Resource("simples"), "id")},
  1433. }
  1434. storage["simple"] = &simpleStorage
  1435. handler := handle(storage)
  1436. server := httptest.NewServer(handler)
  1437. defer server.Close()
  1438. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/id")
  1439. if err != nil {
  1440. t.Errorf("unexpected error: %v", err)
  1441. }
  1442. if resp.StatusCode != http.StatusNotFound {
  1443. t.Errorf("Unexpected response %#v", resp)
  1444. }
  1445. }
  1446. func TestGetRetryAfter(t *testing.T) {
  1447. storage := map[string]rest.Storage{}
  1448. simpleStorage := SimpleRESTStorage{
  1449. errors: map[string]error{"get": apierrs.NewServerTimeout(api.Resource("simples"), "id", 2)},
  1450. }
  1451. storage["simple"] = &simpleStorage
  1452. handler := handle(storage)
  1453. server := httptest.NewServer(handler)
  1454. defer server.Close()
  1455. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/id")
  1456. if err != nil {
  1457. t.Errorf("unexpected error: %v", err)
  1458. }
  1459. if resp.StatusCode != http.StatusInternalServerError {
  1460. t.Errorf("Unexpected response %#v", resp)
  1461. }
  1462. if resp.Header.Get("Retry-After") != "2" {
  1463. t.Errorf("Unexpected Retry-After header: %v", resp.Header)
  1464. }
  1465. }
  1466. func TestConnect(t *testing.T) {
  1467. responseText := "Hello World"
  1468. itemID := "theID"
  1469. connectStorage := &ConnecterRESTStorage{
  1470. connectHandler: &OutputConnect{
  1471. response: responseText,
  1472. },
  1473. }
  1474. storage := map[string]rest.Storage{
  1475. "simple": &SimpleRESTStorage{},
  1476. "simple/connect": connectStorage,
  1477. }
  1478. handler := handle(storage)
  1479. server := httptest.NewServer(handler)
  1480. defer server.Close()
  1481. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + itemID + "/connect")
  1482. if err != nil {
  1483. t.Errorf("unexpected error: %v", err)
  1484. }
  1485. if resp.StatusCode != http.StatusOK {
  1486. t.Errorf("unexpected response: %#v", resp)
  1487. }
  1488. defer resp.Body.Close()
  1489. body, err := ioutil.ReadAll(resp.Body)
  1490. if err != nil {
  1491. t.Fatalf("Unexpected error: %v", err)
  1492. }
  1493. if connectStorage.receivedID != itemID {
  1494. t.Errorf("Unexpected item id. Expected: %s. Actual: %s.", itemID, connectStorage.receivedID)
  1495. }
  1496. if string(body) != responseText {
  1497. t.Errorf("Unexpected response. Expected: %s. Actual: %s.", responseText, string(body))
  1498. }
  1499. }
  1500. func TestConnectResponderObject(t *testing.T) {
  1501. itemID := "theID"
  1502. simple := &apiservertesting.Simple{Other: "foo"}
  1503. connectStorage := &ConnecterRESTStorage{}
  1504. connectStorage.handlerFunc = func() http.Handler {
  1505. return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  1506. connectStorage.receivedResponder.Object(http.StatusCreated, simple)
  1507. })
  1508. }
  1509. storage := map[string]rest.Storage{
  1510. "simple": &SimpleRESTStorage{},
  1511. "simple/connect": connectStorage,
  1512. }
  1513. handler := handle(storage)
  1514. server := httptest.NewServer(handler)
  1515. defer server.Close()
  1516. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + itemID + "/connect")
  1517. if err != nil {
  1518. t.Errorf("unexpected error: %v", err)
  1519. }
  1520. if resp.StatusCode != http.StatusCreated {
  1521. t.Errorf("unexpected response: %#v", resp)
  1522. }
  1523. defer resp.Body.Close()
  1524. body, err := ioutil.ReadAll(resp.Body)
  1525. if err != nil {
  1526. t.Fatalf("Unexpected error: %v", err)
  1527. }
  1528. if connectStorage.receivedID != itemID {
  1529. t.Errorf("Unexpected item id. Expected: %s. Actual: %s.", itemID, connectStorage.receivedID)
  1530. }
  1531. obj, err := runtime.Decode(codec, body)
  1532. if err != nil {
  1533. t.Fatal(err)
  1534. }
  1535. if !api.Semantic.DeepEqual(obj, simple) {
  1536. t.Errorf("Unexpected response: %#v", obj)
  1537. }
  1538. }
  1539. func TestConnectResponderError(t *testing.T) {
  1540. itemID := "theID"
  1541. connectStorage := &ConnecterRESTStorage{}
  1542. connectStorage.handlerFunc = func() http.Handler {
  1543. return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  1544. connectStorage.receivedResponder.Error(apierrs.NewForbidden(api.Resource("simples"), itemID, errors.New("you are terminated")))
  1545. })
  1546. }
  1547. storage := map[string]rest.Storage{
  1548. "simple": &SimpleRESTStorage{},
  1549. "simple/connect": connectStorage,
  1550. }
  1551. handler := handle(storage)
  1552. server := httptest.NewServer(handler)
  1553. defer server.Close()
  1554. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + itemID + "/connect")
  1555. if err != nil {
  1556. t.Errorf("unexpected error: %v", err)
  1557. }
  1558. if resp.StatusCode != http.StatusForbidden {
  1559. t.Errorf("unexpected response: %#v", resp)
  1560. }
  1561. defer resp.Body.Close()
  1562. body, err := ioutil.ReadAll(resp.Body)
  1563. if err != nil {
  1564. t.Fatalf("Unexpected error: %v", err)
  1565. }
  1566. if connectStorage.receivedID != itemID {
  1567. t.Errorf("Unexpected item id. Expected: %s. Actual: %s.", itemID, connectStorage.receivedID)
  1568. }
  1569. obj, err := runtime.Decode(codec, body)
  1570. if err != nil {
  1571. t.Fatal(err)
  1572. }
  1573. if obj.(*unversioned.Status).Code != http.StatusForbidden {
  1574. t.Errorf("Unexpected response: %#v", obj)
  1575. }
  1576. }
  1577. func TestConnectWithOptionsRouteParams(t *testing.T) {
  1578. connectStorage := &ConnecterRESTStorage{
  1579. connectHandler: &OutputConnect{},
  1580. emptyConnectOptions: &apiservertesting.SimpleGetOptions{},
  1581. }
  1582. storage := map[string]rest.Storage{
  1583. "simple": &SimpleRESTStorage{},
  1584. "simple/connect": connectStorage,
  1585. }
  1586. handler := handle(storage)
  1587. ws := handler.(*defaultAPIServer).container.RegisteredWebServices()
  1588. if len(ws) == 0 {
  1589. t.Fatal("no web services registered")
  1590. }
  1591. routes := ws[0].Routes()
  1592. for i := range routes {
  1593. switch routes[i].Operation {
  1594. case "connectGetNamespacedSimpleConnect":
  1595. case "connectPostNamespacedSimpleConnect":
  1596. case "connectPutNamespacedSimpleConnect":
  1597. case "connectDeleteNamespacedSimpleConnect":
  1598. validateSimpleGetOptionsParams(t, &routes[i])
  1599. }
  1600. }
  1601. }
  1602. func TestConnectWithOptions(t *testing.T) {
  1603. responseText := "Hello World"
  1604. itemID := "theID"
  1605. connectStorage := &ConnecterRESTStorage{
  1606. connectHandler: &OutputConnect{
  1607. response: responseText,
  1608. },
  1609. emptyConnectOptions: &apiservertesting.SimpleGetOptions{},
  1610. }
  1611. storage := map[string]rest.Storage{
  1612. "simple": &SimpleRESTStorage{},
  1613. "simple/connect": connectStorage,
  1614. }
  1615. handler := handle(storage)
  1616. server := httptest.NewServer(handler)
  1617. defer server.Close()
  1618. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + itemID + "/connect?param1=value1&param2=value2")
  1619. if err != nil {
  1620. t.Errorf("unexpected error: %v", err)
  1621. }
  1622. if resp.StatusCode != http.StatusOK {
  1623. t.Errorf("unexpected response: %#v", resp)
  1624. }
  1625. defer resp.Body.Close()
  1626. body, err := ioutil.ReadAll(resp.Body)
  1627. if err != nil {
  1628. t.Fatalf("Unexpected error: %v", err)
  1629. }
  1630. if connectStorage.receivedID != itemID {
  1631. t.Errorf("Unexpected item id. Expected: %s. Actual: %s.", itemID, connectStorage.receivedID)
  1632. }
  1633. if string(body) != responseText {
  1634. t.Errorf("Unexpected response. Expected: %s. Actual: %s.", responseText, string(body))
  1635. }
  1636. if connectStorage.receivedResponder == nil {
  1637. t.Errorf("Unexpected responder")
  1638. }
  1639. opts, ok := connectStorage.receivedConnectOptions.(*apiservertesting.SimpleGetOptions)
  1640. if !ok {
  1641. t.Fatalf("Unexpected options type: %#v", connectStorage.receivedConnectOptions)
  1642. }
  1643. if opts.Param1 != "value1" && opts.Param2 != "value2" {
  1644. t.Errorf("Unexpected options value: %#v", opts)
  1645. }
  1646. }
  1647. func TestConnectWithOptionsAndPath(t *testing.T) {
  1648. responseText := "Hello World"
  1649. itemID := "theID"
  1650. testPath := "a/b/c/def"
  1651. connectStorage := &ConnecterRESTStorage{
  1652. connectHandler: &OutputConnect{
  1653. response: responseText,
  1654. },
  1655. emptyConnectOptions: &apiservertesting.SimpleGetOptions{},
  1656. takesPath: "atAPath",
  1657. }
  1658. storage := map[string]rest.Storage{
  1659. "simple": &SimpleRESTStorage{},
  1660. "simple/connect": connectStorage,
  1661. }
  1662. handler := handle(storage)
  1663. server := httptest.NewServer(handler)
  1664. defer server.Close()
  1665. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + itemID + "/connect/" + testPath + "?param1=value1&param2=value2")
  1666. if err != nil {
  1667. t.Errorf("unexpected error: %v", err)
  1668. }
  1669. if resp.StatusCode != http.StatusOK {
  1670. t.Errorf("unexpected response: %#v", resp)
  1671. }
  1672. defer resp.Body.Close()
  1673. body, err := ioutil.ReadAll(resp.Body)
  1674. if err != nil {
  1675. t.Fatalf("Unexpected error: %v", err)
  1676. }
  1677. if connectStorage.receivedID != itemID {
  1678. t.Errorf("Unexpected item id. Expected: %s. Actual: %s.", itemID, connectStorage.receivedID)
  1679. }
  1680. if string(body) != responseText {
  1681. t.Errorf("Unexpected response. Expected: %s. Actual: %s.", responseText, string(body))
  1682. }
  1683. opts, ok := connectStorage.receivedConnectOptions.(*apiservertesting.SimpleGetOptions)
  1684. if !ok {
  1685. t.Fatalf("Unexpected options type: %#v", connectStorage.receivedConnectOptions)
  1686. }
  1687. if opts.Param1 != "value1" && opts.Param2 != "value2" {
  1688. t.Errorf("Unexpected options value: %#v", opts)
  1689. }
  1690. if opts.Path != testPath {
  1691. t.Errorf("Unexpected path value. Expected: %s. Actual: %s.", testPath, opts.Path)
  1692. }
  1693. }
  1694. func TestDelete(t *testing.T) {
  1695. storage := map[string]rest.Storage{}
  1696. simpleStorage := SimpleRESTStorage{}
  1697. ID := "id"
  1698. storage["simple"] = &simpleStorage
  1699. handler := handle(storage)
  1700. server := httptest.NewServer(handler)
  1701. defer server.Close()
  1702. client := http.Client{}
  1703. request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
  1704. res, err := client.Do(request)
  1705. if err != nil {
  1706. t.Fatalf("unexpected error: %v", err)
  1707. }
  1708. if res.StatusCode != http.StatusOK {
  1709. t.Errorf("unexpected response: %#v", res)
  1710. }
  1711. if simpleStorage.deleted != ID {
  1712. t.Errorf("Unexpected delete: %s, expected %s", simpleStorage.deleted, ID)
  1713. }
  1714. }
  1715. func TestDeleteWithOptions(t *testing.T) {
  1716. storage := map[string]rest.Storage{}
  1717. simpleStorage := SimpleRESTStorage{}
  1718. ID := "id"
  1719. storage["simple"] = &simpleStorage
  1720. handler := handle(storage)
  1721. server := httptest.NewServer(handler)
  1722. defer server.Close()
  1723. grace := int64(300)
  1724. item := &api.DeleteOptions{
  1725. GracePeriodSeconds: &grace,
  1726. }
  1727. body, err := runtime.Encode(codec, item)
  1728. if err != nil {
  1729. t.Fatalf("unexpected error: %v", err)
  1730. }
  1731. client := http.Client{}
  1732. request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
  1733. res, err := client.Do(request)
  1734. if err != nil {
  1735. t.Fatalf("unexpected error: %v", err)
  1736. }
  1737. if res.StatusCode != http.StatusOK {
  1738. t.Errorf("unexpected response: %s %#v", request.URL, res)
  1739. s, err := ioutil.ReadAll(res.Body)
  1740. if err != nil {
  1741. t.Fatalf("unexpected error: %v", err)
  1742. }
  1743. t.Logf(string(s))
  1744. }
  1745. if simpleStorage.deleted != ID {
  1746. t.Errorf("Unexpected delete: %s, expected %s", simpleStorage.deleted, ID)
  1747. }
  1748. simpleStorage.deleteOptions.GetObjectKind().SetGroupVersionKind(unversioned.GroupVersionKind{})
  1749. if !api.Semantic.DeepEqual(simpleStorage.deleteOptions, item) {
  1750. t.Errorf("unexpected delete options: %s", diff.ObjectDiff(simpleStorage.deleteOptions, item))
  1751. }
  1752. }
  1753. func TestLegacyDelete(t *testing.T) {
  1754. storage := map[string]rest.Storage{}
  1755. simpleStorage := SimpleRESTStorage{}
  1756. ID := "id"
  1757. storage["simple"] = LegacyRESTStorage{&simpleStorage}
  1758. var _ rest.Deleter = storage["simple"].(LegacyRESTStorage)
  1759. handler := handle(storage)
  1760. server := httptest.NewServer(handler)
  1761. defer server.Close()
  1762. client := http.Client{}
  1763. request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
  1764. res, err := client.Do(request)
  1765. if err != nil {
  1766. t.Fatalf("unexpected error: %v", err)
  1767. }
  1768. if res.StatusCode != http.StatusOK {
  1769. t.Errorf("unexpected response: %#v", res)
  1770. }
  1771. if simpleStorage.deleted != ID {
  1772. t.Errorf("Unexpected delete: %s, expected %s", simpleStorage.deleted, ID)
  1773. }
  1774. if simpleStorage.deleteOptions != nil {
  1775. t.Errorf("unexpected delete options: %#v", simpleStorage.deleteOptions)
  1776. }
  1777. }
  1778. func TestLegacyDeleteIgnoresOptions(t *testing.T) {
  1779. storage := map[string]rest.Storage{}
  1780. simpleStorage := SimpleRESTStorage{}
  1781. ID := "id"
  1782. storage["simple"] = LegacyRESTStorage{&simpleStorage}
  1783. handler := handle(storage)
  1784. server := httptest.NewServer(handler)
  1785. defer server.Close()
  1786. item := api.NewDeleteOptions(300)
  1787. body, err := runtime.Encode(codec, item)
  1788. if err != nil {
  1789. t.Fatalf("unexpected error: %v", err)
  1790. }
  1791. client := http.Client{}
  1792. request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
  1793. res, err := client.Do(request)
  1794. if err != nil {
  1795. t.Fatalf("unexpected error: %v", err)
  1796. }
  1797. if res.StatusCode != http.StatusOK {
  1798. t.Errorf("unexpected response: %#v", res)
  1799. }
  1800. if simpleStorage.deleted != ID {
  1801. t.Errorf("Unexpected delete: %s, expected %s", simpleStorage.deleted, ID)
  1802. }
  1803. if simpleStorage.deleteOptions != nil {
  1804. t.Errorf("unexpected delete options: %#v", simpleStorage.deleteOptions)
  1805. }
  1806. }
  1807. func TestDeleteInvokesAdmissionControl(t *testing.T) {
  1808. storage := map[string]rest.Storage{}
  1809. simpleStorage := SimpleRESTStorage{}
  1810. ID := "id"
  1811. storage["simple"] = &simpleStorage
  1812. handler := handleDeny(storage)
  1813. server := httptest.NewServer(handler)
  1814. defer server.Close()
  1815. client := http.Client{}
  1816. request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
  1817. response, err := client.Do(request)
  1818. if err != nil {
  1819. t.Errorf("unexpected error: %v", err)
  1820. }
  1821. if response.StatusCode != http.StatusForbidden {
  1822. t.Errorf("Unexpected response %#v", response)
  1823. }
  1824. }
  1825. func TestDeleteMissing(t *testing.T) {
  1826. storage := map[string]rest.Storage{}
  1827. ID := "id"
  1828. simpleStorage := SimpleRESTStorage{
  1829. errors: map[string]error{"delete": apierrs.NewNotFound(api.Resource("simples"), ID)},
  1830. }
  1831. storage["simple"] = &simpleStorage
  1832. handler := handle(storage)
  1833. server := httptest.NewServer(handler)
  1834. defer server.Close()
  1835. client := http.Client{}
  1836. request, err := http.NewRequest("DELETE", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, nil)
  1837. response, err := client.Do(request)
  1838. if err != nil {
  1839. t.Errorf("unexpected error: %v", err)
  1840. }
  1841. if response.StatusCode != http.StatusNotFound {
  1842. t.Errorf("Unexpected response %#v", response)
  1843. }
  1844. }
  1845. func TestPatch(t *testing.T) {
  1846. storage := map[string]rest.Storage{}
  1847. ID := "id"
  1848. item := &apiservertesting.Simple{
  1849. ObjectMeta: api.ObjectMeta{
  1850. Name: ID,
  1851. Namespace: "", // update should allow the client to send an empty namespace
  1852. UID: "uid",
  1853. },
  1854. Other: "bar",
  1855. }
  1856. simpleStorage := SimpleRESTStorage{item: *item}
  1857. storage["simple"] = &simpleStorage
  1858. selfLinker := &setTestSelfLinker{
  1859. t: t,
  1860. expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + ID,
  1861. name: ID,
  1862. namespace: api.NamespaceDefault,
  1863. }
  1864. handler := handleLinker(storage, selfLinker)
  1865. server := httptest.NewServer(handler)
  1866. defer server.Close()
  1867. client := http.Client{}
  1868. request, err := http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"labels":{"foo":"bar"}}`)))
  1869. request.Header.Set("Content-Type", "application/merge-patch+json; charset=UTF-8")
  1870. _, err = client.Do(request)
  1871. if err != nil {
  1872. t.Errorf("unexpected error: %v", err)
  1873. }
  1874. if simpleStorage.updated == nil || simpleStorage.updated.Labels["foo"] != "bar" {
  1875. t.Errorf("Unexpected update value %#v, expected %#v.", simpleStorage.updated, item)
  1876. }
  1877. if !selfLinker.called {
  1878. t.Errorf("Never set self link")
  1879. }
  1880. }
  1881. func TestPatchRequiresMatchingName(t *testing.T) {
  1882. storage := map[string]rest.Storage{}
  1883. ID := "id"
  1884. item := &apiservertesting.Simple{
  1885. ObjectMeta: api.ObjectMeta{
  1886. Name: ID,
  1887. Namespace: "", // update should allow the client to send an empty namespace
  1888. UID: "uid",
  1889. },
  1890. Other: "bar",
  1891. }
  1892. simpleStorage := SimpleRESTStorage{item: *item}
  1893. storage["simple"] = &simpleStorage
  1894. handler := handle(storage)
  1895. server := httptest.NewServer(handler)
  1896. defer server.Close()
  1897. client := http.Client{}
  1898. request, err := http.NewRequest("PATCH", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader([]byte(`{"metadata":{"name":"idbar"}}`)))
  1899. request.Header.Set("Content-Type", "application/merge-patch+json")
  1900. response, err := client.Do(request)
  1901. if err != nil {
  1902. t.Errorf("unexpected error: %v", err)
  1903. }
  1904. if response.StatusCode != http.StatusBadRequest {
  1905. t.Errorf("Unexpected response %#v", response)
  1906. }
  1907. }
  1908. func TestUpdate(t *testing.T) {
  1909. storage := map[string]rest.Storage{}
  1910. simpleStorage := SimpleRESTStorage{}
  1911. ID := "id"
  1912. storage["simple"] = &simpleStorage
  1913. selfLinker := &setTestSelfLinker{
  1914. t: t,
  1915. expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + ID,
  1916. name: ID,
  1917. namespace: api.NamespaceDefault,
  1918. }
  1919. handler := handleLinker(storage, selfLinker)
  1920. server := httptest.NewServer(handler)
  1921. defer server.Close()
  1922. item := &apiservertesting.Simple{
  1923. ObjectMeta: api.ObjectMeta{
  1924. Name: ID,
  1925. Namespace: "", // update should allow the client to send an empty namespace
  1926. },
  1927. Other: "bar",
  1928. }
  1929. body, err := runtime.Encode(testCodec, item)
  1930. if err != nil {
  1931. // The following cases will fail, so die now
  1932. t.Fatalf("unexpected error: %v", err)
  1933. }
  1934. client := http.Client{}
  1935. request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
  1936. _, err = client.Do(request)
  1937. if err != nil {
  1938. t.Errorf("unexpected error: %v", err)
  1939. }
  1940. if simpleStorage.updated == nil || simpleStorage.updated.Name != item.Name {
  1941. t.Errorf("Unexpected update value %#v, expected %#v.", simpleStorage.updated, item)
  1942. }
  1943. if !selfLinker.called {
  1944. t.Errorf("Never set self link")
  1945. }
  1946. }
  1947. func TestUpdateInvokesAdmissionControl(t *testing.T) {
  1948. storage := map[string]rest.Storage{}
  1949. simpleStorage := SimpleRESTStorage{}
  1950. ID := "id"
  1951. storage["simple"] = &simpleStorage
  1952. handler := handleDeny(storage)
  1953. server := httptest.NewServer(handler)
  1954. defer server.Close()
  1955. item := &apiservertesting.Simple{
  1956. ObjectMeta: api.ObjectMeta{
  1957. Name: ID,
  1958. Namespace: api.NamespaceDefault,
  1959. },
  1960. Other: "bar",
  1961. }
  1962. body, err := runtime.Encode(testCodec, item)
  1963. if err != nil {
  1964. // The following cases will fail, so die now
  1965. t.Fatalf("unexpected error: %v", err)
  1966. }
  1967. client := http.Client{}
  1968. request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
  1969. response, err := client.Do(request)
  1970. if err != nil {
  1971. t.Errorf("unexpected error: %v", err)
  1972. }
  1973. if response.StatusCode != http.StatusForbidden {
  1974. t.Errorf("Unexpected response %#v", response)
  1975. }
  1976. }
  1977. func TestUpdateRequiresMatchingName(t *testing.T) {
  1978. storage := map[string]rest.Storage{}
  1979. simpleStorage := SimpleRESTStorage{}
  1980. ID := "id"
  1981. storage["simple"] = &simpleStorage
  1982. handler := handleDeny(storage)
  1983. server := httptest.NewServer(handler)
  1984. defer server.Close()
  1985. item := &apiservertesting.Simple{
  1986. Other: "bar",
  1987. }
  1988. body, err := runtime.Encode(testCodec, item)
  1989. if err != nil {
  1990. // The following cases will fail, so die now
  1991. t.Fatalf("unexpected error: %v", err)
  1992. }
  1993. client := http.Client{}
  1994. request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
  1995. response, err := client.Do(request)
  1996. if err != nil {
  1997. t.Errorf("unexpected error: %v", err)
  1998. }
  1999. if response.StatusCode != http.StatusBadRequest {
  2000. t.Errorf("Unexpected response %#v", response)
  2001. }
  2002. }
  2003. func TestUpdateAllowsMissingNamespace(t *testing.T) {
  2004. storage := map[string]rest.Storage{}
  2005. simpleStorage := SimpleRESTStorage{}
  2006. ID := "id"
  2007. storage["simple"] = &simpleStorage
  2008. handler := handle(storage)
  2009. server := httptest.NewServer(handler)
  2010. defer server.Close()
  2011. item := &apiservertesting.Simple{
  2012. ObjectMeta: api.ObjectMeta{
  2013. Name: ID,
  2014. },
  2015. Other: "bar",
  2016. }
  2017. body, err := runtime.Encode(testCodec, item)
  2018. if err != nil {
  2019. // The following cases will fail, so die now
  2020. t.Fatalf("unexpected error: %v", err)
  2021. }
  2022. client := http.Client{}
  2023. request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
  2024. response, err := client.Do(request)
  2025. if err != nil {
  2026. t.Errorf("unexpected error: %v", err)
  2027. }
  2028. if response.StatusCode != http.StatusOK {
  2029. t.Errorf("Unexpected response %#v", response)
  2030. }
  2031. }
  2032. // when the object name and namespace can't be retrieved, skip name checking
  2033. func TestUpdateAllowsMismatchedNamespaceOnError(t *testing.T) {
  2034. storage := map[string]rest.Storage{}
  2035. simpleStorage := SimpleRESTStorage{}
  2036. ID := "id"
  2037. storage["simple"] = &simpleStorage
  2038. selfLinker := &setTestSelfLinker{
  2039. t: t,
  2040. err: fmt.Errorf("test error"),
  2041. }
  2042. handler := handleLinker(storage, selfLinker)
  2043. server := httptest.NewServer(handler)
  2044. defer server.Close()
  2045. item := &apiservertesting.Simple{
  2046. ObjectMeta: api.ObjectMeta{
  2047. Name: ID,
  2048. Namespace: "other", // does not match request
  2049. },
  2050. Other: "bar",
  2051. }
  2052. body, err := runtime.Encode(testCodec, item)
  2053. if err != nil {
  2054. // The following cases will fail, so die now
  2055. t.Fatalf("unexpected error: %v", err)
  2056. }
  2057. client := http.Client{}
  2058. request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
  2059. _, err = client.Do(request)
  2060. if err != nil {
  2061. t.Errorf("unexpected error: %v", err)
  2062. }
  2063. if simpleStorage.updated == nil || simpleStorage.updated.Name != item.Name {
  2064. t.Errorf("Unexpected update value %#v, expected %#v.", simpleStorage.updated, item)
  2065. }
  2066. if selfLinker.called {
  2067. t.Errorf("self link ignored")
  2068. }
  2069. }
  2070. func TestUpdatePreventsMismatchedNamespace(t *testing.T) {
  2071. storage := map[string]rest.Storage{}
  2072. simpleStorage := SimpleRESTStorage{}
  2073. ID := "id"
  2074. storage["simple"] = &simpleStorage
  2075. handler := handle(storage)
  2076. server := httptest.NewServer(handler)
  2077. defer server.Close()
  2078. item := &apiservertesting.Simple{
  2079. ObjectMeta: api.ObjectMeta{
  2080. Name: ID,
  2081. Namespace: "other",
  2082. },
  2083. Other: "bar",
  2084. }
  2085. body, err := runtime.Encode(testCodec, item)
  2086. if err != nil {
  2087. // The following cases will fail, so die now
  2088. t.Fatalf("unexpected error: %v", err)
  2089. }
  2090. client := http.Client{}
  2091. request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
  2092. response, err := client.Do(request)
  2093. if err != nil {
  2094. t.Errorf("unexpected error: %v", err)
  2095. }
  2096. if response.StatusCode != http.StatusBadRequest {
  2097. t.Errorf("Unexpected response %#v", response)
  2098. }
  2099. }
  2100. func TestUpdateMissing(t *testing.T) {
  2101. storage := map[string]rest.Storage{}
  2102. ID := "id"
  2103. simpleStorage := SimpleRESTStorage{
  2104. errors: map[string]error{"update": apierrs.NewNotFound(api.Resource("simples"), ID)},
  2105. }
  2106. storage["simple"] = &simpleStorage
  2107. handler := handle(storage)
  2108. server := httptest.NewServer(handler)
  2109. defer server.Close()
  2110. item := &apiservertesting.Simple{
  2111. ObjectMeta: api.ObjectMeta{
  2112. Name: ID,
  2113. Namespace: api.NamespaceDefault,
  2114. },
  2115. Other: "bar",
  2116. }
  2117. body, err := runtime.Encode(testCodec, item)
  2118. if err != nil {
  2119. t.Errorf("unexpected error: %v", err)
  2120. }
  2121. client := http.Client{}
  2122. request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+ID, bytes.NewReader(body))
  2123. response, err := client.Do(request)
  2124. if err != nil {
  2125. t.Errorf("unexpected error: %v", err)
  2126. }
  2127. if response.StatusCode != http.StatusNotFound {
  2128. t.Errorf("Unexpected response %#v", response)
  2129. }
  2130. }
  2131. func TestCreateNotFound(t *testing.T) {
  2132. handler := handle(map[string]rest.Storage{
  2133. "simple": &SimpleRESTStorage{
  2134. // storage.Create can fail with not found error in theory.
  2135. // See http://pr.k8s.io/486#discussion_r15037092.
  2136. errors: map[string]error{"create": apierrs.NewNotFound(api.Resource("simples"), "id")},
  2137. },
  2138. })
  2139. server := httptest.NewServer(handler)
  2140. defer server.Close()
  2141. client := http.Client{}
  2142. simple := &apiservertesting.Simple{Other: "foo"}
  2143. data, err := runtime.Encode(testCodec, simple)
  2144. if err != nil {
  2145. t.Errorf("unexpected error: %v", err)
  2146. }
  2147. request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
  2148. if err != nil {
  2149. t.Errorf("unexpected error: %v", err)
  2150. }
  2151. response, err := client.Do(request)
  2152. if err != nil {
  2153. t.Errorf("unexpected error: %v", err)
  2154. }
  2155. if response.StatusCode != http.StatusNotFound {
  2156. t.Errorf("Unexpected response %#v", response)
  2157. }
  2158. }
  2159. func TestCreateChecksDecode(t *testing.T) {
  2160. handler := handle(map[string]rest.Storage{"simple": &SimpleRESTStorage{}})
  2161. server := httptest.NewServer(handler)
  2162. defer server.Close()
  2163. client := http.Client{}
  2164. simple := &api.Pod{}
  2165. data, err := runtime.Encode(testCodec, simple)
  2166. if err != nil {
  2167. t.Errorf("unexpected error: %v", err)
  2168. }
  2169. request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
  2170. if err != nil {
  2171. t.Errorf("unexpected error: %v", err)
  2172. }
  2173. response, err := client.Do(request)
  2174. if err != nil {
  2175. t.Errorf("unexpected error: %v", err)
  2176. }
  2177. if response.StatusCode != http.StatusBadRequest {
  2178. t.Errorf("Unexpected response %#v", response)
  2179. }
  2180. b, err := ioutil.ReadAll(response.Body)
  2181. if err != nil {
  2182. t.Errorf("unexpected error: %v", err)
  2183. } else if !strings.Contains(string(b), "cannot be handled as a Simple") {
  2184. t.Errorf("unexpected response: %s", string(b))
  2185. }
  2186. }
  2187. // TestUpdateREST tests that you can add new rest implementations to a pre-existing
  2188. // web service.
  2189. func TestUpdateREST(t *testing.T) {
  2190. makeGroup := func(storage map[string]rest.Storage) *APIGroupVersion {
  2191. return &APIGroupVersion{
  2192. Storage: storage,
  2193. Root: "/" + prefix,
  2194. RequestInfoResolver: newTestRequestInfoResolver(),
  2195. Creater: api.Scheme,
  2196. Convertor: api.Scheme,
  2197. Copier: api.Scheme,
  2198. Typer: api.Scheme,
  2199. Linker: selfLinker,
  2200. Admit: admissionControl,
  2201. Context: requestContextMapper,
  2202. Mapper: namespaceMapper,
  2203. GroupVersion: newGroupVersion,
  2204. OptionsExternalVersion: &newGroupVersion,
  2205. Serializer: api.Codecs,
  2206. ParameterCodec: api.ParameterCodec,
  2207. }
  2208. }
  2209. makeStorage := func(paths ...string) map[string]rest.Storage {
  2210. storage := map[string]rest.Storage{}
  2211. for _, s := range paths {
  2212. storage[s] = &SimpleRESTStorage{}
  2213. }
  2214. return storage
  2215. }
  2216. testREST := func(t *testing.T, container *restful.Container, barCode int) {
  2217. w := httptest.NewRecorder()
  2218. container.ServeHTTP(w, &http.Request{Method: "GET", URL: &url.URL{Path: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/test/foo/test"}})
  2219. if w.Code != http.StatusOK {
  2220. t.Fatalf("expected OK: %#v", w)
  2221. }
  2222. w = httptest.NewRecorder()
  2223. container.ServeHTTP(w, &http.Request{Method: "GET", URL: &url.URL{Path: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/test/bar/test"}})
  2224. if w.Code != barCode {
  2225. t.Errorf("expected response code %d for GET to bar but received %d", barCode, w.Code)
  2226. }
  2227. }
  2228. storage1 := makeStorage("foo")
  2229. group1 := makeGroup(storage1)
  2230. storage2 := makeStorage("bar")
  2231. group2 := makeGroup(storage2)
  2232. container := restful.NewContainer()
  2233. // install group1. Ensure that
  2234. // 1. Foo storage is accessible
  2235. // 2. Bar storage is not accessible
  2236. if err := group1.InstallREST(container); err != nil {
  2237. t.Fatal(err)
  2238. }
  2239. testREST(t, container, http.StatusNotFound)
  2240. // update with group2. Ensure that
  2241. // 1. Foo storage is still accessible
  2242. // 2. Bar storage is now accessible
  2243. if err := group2.UpdateREST(container); err != nil {
  2244. t.Fatal(err)
  2245. }
  2246. testREST(t, container, http.StatusOK)
  2247. // try to update a group that does not have an existing webservice with a matching prefix
  2248. // should not affect the existing registered webservice
  2249. invalidGroup := makeGroup(storage1)
  2250. invalidGroup.Root = "bad"
  2251. if err := invalidGroup.UpdateREST(container); err == nil {
  2252. t.Fatal("expected an error from UpdateREST when updating a non-existing prefix but got none")
  2253. }
  2254. testREST(t, container, http.StatusOK)
  2255. }
  2256. func TestParentResourceIsRequired(t *testing.T) {
  2257. storage := &SimpleTypedStorage{
  2258. baseType: &apiservertesting.SimpleRoot{}, // a root scoped type
  2259. item: &apiservertesting.SimpleRoot{},
  2260. }
  2261. group := &APIGroupVersion{
  2262. Storage: map[string]rest.Storage{
  2263. "simple/sub": storage,
  2264. },
  2265. Root: "/" + prefix,
  2266. RequestInfoResolver: newTestRequestInfoResolver(),
  2267. Creater: api.Scheme,
  2268. Convertor: api.Scheme,
  2269. Copier: api.Scheme,
  2270. Typer: api.Scheme,
  2271. Linker: selfLinker,
  2272. Admit: admissionControl,
  2273. Context: requestContextMapper,
  2274. Mapper: namespaceMapper,
  2275. GroupVersion: newGroupVersion,
  2276. OptionsExternalVersion: &newGroupVersion,
  2277. Serializer: api.Codecs,
  2278. ParameterCodec: api.ParameterCodec,
  2279. }
  2280. container := restful.NewContainer()
  2281. if err := group.InstallREST(container); err == nil {
  2282. t.Fatal("expected error")
  2283. }
  2284. storage = &SimpleTypedStorage{
  2285. baseType: &apiservertesting.SimpleRoot{}, // a root scoped type
  2286. item: &apiservertesting.SimpleRoot{},
  2287. }
  2288. group = &APIGroupVersion{
  2289. Storage: map[string]rest.Storage{
  2290. "simple": &SimpleRESTStorage{},
  2291. "simple/sub": storage,
  2292. },
  2293. Root: "/" + prefix,
  2294. RequestInfoResolver: newTestRequestInfoResolver(),
  2295. Creater: api.Scheme,
  2296. Convertor: api.Scheme,
  2297. Copier: api.Scheme,
  2298. Typer: api.Scheme,
  2299. Linker: selfLinker,
  2300. Admit: admissionControl,
  2301. Context: requestContextMapper,
  2302. Mapper: namespaceMapper,
  2303. GroupVersion: newGroupVersion,
  2304. OptionsExternalVersion: &newGroupVersion,
  2305. Serializer: api.Codecs,
  2306. ParameterCodec: api.ParameterCodec,
  2307. }
  2308. container = restful.NewContainer()
  2309. if err := group.InstallREST(container); err != nil {
  2310. t.Fatal(err)
  2311. }
  2312. // resource is NOT registered in the root scope
  2313. w := httptest.NewRecorder()
  2314. container.ServeHTTP(w, &http.Request{Method: "GET", URL: &url.URL{Path: "/" + prefix + "/simple/test/sub"}})
  2315. if w.Code != http.StatusNotFound {
  2316. t.Errorf("expected not found: %#v", w)
  2317. }
  2318. // resource is registered in the namespace scope
  2319. w = httptest.NewRecorder()
  2320. container.ServeHTTP(w, &http.Request{Method: "GET", URL: &url.URL{Path: "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/test/simple/test/sub"}})
  2321. if w.Code != http.StatusOK {
  2322. t.Fatalf("expected OK: %#v", w)
  2323. }
  2324. if storage.actualNamespace != "test" {
  2325. t.Errorf("namespace should be set %#v", storage)
  2326. }
  2327. }
  2328. func TestCreateWithName(t *testing.T) {
  2329. pathName := "helloworld"
  2330. storage := &NamedCreaterRESTStorage{SimpleRESTStorage: &SimpleRESTStorage{}}
  2331. handler := handle(map[string]rest.Storage{
  2332. "simple": &SimpleRESTStorage{},
  2333. "simple/sub": storage,
  2334. })
  2335. server := httptest.NewServer(handler)
  2336. defer server.Close()
  2337. client := http.Client{}
  2338. simple := &apiservertesting.Simple{Other: "foo"}
  2339. data, err := runtime.Encode(testCodec, simple)
  2340. if err != nil {
  2341. t.Errorf("unexpected error: %v", err)
  2342. }
  2343. request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/"+pathName+"/sub", bytes.NewBuffer(data))
  2344. if err != nil {
  2345. t.Errorf("unexpected error: %v", err)
  2346. }
  2347. response, err := client.Do(request)
  2348. if err != nil {
  2349. t.Errorf("unexpected error: %v", err)
  2350. }
  2351. if response.StatusCode != http.StatusCreated {
  2352. t.Errorf("Unexpected response %#v", response)
  2353. }
  2354. if storage.createdName != pathName {
  2355. t.Errorf("Did not get expected name in create context. Got: %s, Expected: %s", storage.createdName, pathName)
  2356. }
  2357. }
  2358. func TestUpdateChecksDecode(t *testing.T) {
  2359. handler := handle(map[string]rest.Storage{"simple": &SimpleRESTStorage{}})
  2360. server := httptest.NewServer(handler)
  2361. defer server.Close()
  2362. client := http.Client{}
  2363. simple := &api.Pod{}
  2364. data, err := runtime.Encode(testCodec, simple)
  2365. if err != nil {
  2366. t.Errorf("unexpected error: %v", err)
  2367. }
  2368. request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/bar", bytes.NewBuffer(data))
  2369. if err != nil {
  2370. t.Errorf("unexpected error: %v", err)
  2371. }
  2372. response, err := client.Do(request)
  2373. if err != nil {
  2374. t.Errorf("unexpected error: %v", err)
  2375. }
  2376. if response.StatusCode != http.StatusBadRequest {
  2377. t.Errorf("Unexpected response %#v\n%s", response, readBodyOrDie(response.Body))
  2378. }
  2379. b, err := ioutil.ReadAll(response.Body)
  2380. if err != nil {
  2381. t.Errorf("unexpected error: %v", err)
  2382. } else if !strings.Contains(string(b), "cannot be handled as a Simple") {
  2383. t.Errorf("unexpected response: %s", string(b))
  2384. }
  2385. }
  2386. func TestParseTimeout(t *testing.T) {
  2387. if d := parseTimeout(""); d != 30*time.Second {
  2388. t.Errorf("blank timeout produces %v", d)
  2389. }
  2390. if d := parseTimeout("not a timeout"); d != 30*time.Second {
  2391. t.Errorf("bad timeout produces %v", d)
  2392. }
  2393. if d := parseTimeout("10s"); d != 10*time.Second {
  2394. t.Errorf("10s timeout produced: %v", d)
  2395. }
  2396. }
  2397. type setTestSelfLinker struct {
  2398. t *testing.T
  2399. expectedSet string
  2400. name string
  2401. namespace string
  2402. called bool
  2403. err error
  2404. }
  2405. func (s *setTestSelfLinker) Namespace(runtime.Object) (string, error) { return s.namespace, s.err }
  2406. func (s *setTestSelfLinker) Name(runtime.Object) (string, error) { return s.name, s.err }
  2407. func (s *setTestSelfLinker) SelfLink(runtime.Object) (string, error) { return "", s.err }
  2408. func (s *setTestSelfLinker) SetSelfLink(obj runtime.Object, selfLink string) error {
  2409. if e, a := s.expectedSet, selfLink; e != a {
  2410. s.t.Errorf("expected '%v', got '%v'", e, a)
  2411. }
  2412. s.called = true
  2413. return s.err
  2414. }
  2415. func TestCreate(t *testing.T) {
  2416. storage := SimpleRESTStorage{
  2417. injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
  2418. time.Sleep(5 * time.Millisecond)
  2419. return obj, nil
  2420. },
  2421. }
  2422. selfLinker := &setTestSelfLinker{
  2423. t: t,
  2424. name: "bar",
  2425. namespace: "default",
  2426. expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo/bar",
  2427. }
  2428. handler := handleLinker(map[string]rest.Storage{"foo": &storage}, selfLinker)
  2429. server := httptest.NewServer(handler)
  2430. defer server.Close()
  2431. client := http.Client{}
  2432. simple := &apiservertesting.Simple{
  2433. Other: "bar",
  2434. }
  2435. data, err := runtime.Encode(testCodec, simple)
  2436. if err != nil {
  2437. t.Errorf("unexpected error: %v", err)
  2438. }
  2439. request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
  2440. if err != nil {
  2441. t.Errorf("unexpected error: %v", err)
  2442. }
  2443. wg := sync.WaitGroup{}
  2444. wg.Add(1)
  2445. var response *http.Response
  2446. go func() {
  2447. response, err = client.Do(request)
  2448. wg.Done()
  2449. }()
  2450. wg.Wait()
  2451. if err != nil {
  2452. t.Errorf("unexpected error: %v", err)
  2453. }
  2454. var itemOut apiservertesting.Simple
  2455. body, err := extractBody(response, &itemOut)
  2456. if err != nil {
  2457. t.Errorf("unexpected error: %v %#v", err, response)
  2458. }
  2459. itemOut.GetObjectKind().SetGroupVersionKind(unversioned.GroupVersionKind{})
  2460. if !reflect.DeepEqual(&itemOut, simple) {
  2461. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simple, string(body))
  2462. }
  2463. if response.StatusCode != http.StatusCreated {
  2464. t.Errorf("Unexpected status: %d, Expected: %d, %#v", response.StatusCode, http.StatusOK, response)
  2465. }
  2466. if !selfLinker.called {
  2467. t.Errorf("Never set self link")
  2468. }
  2469. }
  2470. func TestCreateYAML(t *testing.T) {
  2471. storage := SimpleRESTStorage{
  2472. injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
  2473. time.Sleep(5 * time.Millisecond)
  2474. return obj, nil
  2475. },
  2476. }
  2477. selfLinker := &setTestSelfLinker{
  2478. t: t,
  2479. name: "bar",
  2480. namespace: "default",
  2481. expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/foo/bar",
  2482. }
  2483. handler := handleLinker(map[string]rest.Storage{"foo": &storage}, selfLinker)
  2484. server := httptest.NewServer(handler)
  2485. defer server.Close()
  2486. client := http.Client{}
  2487. // yaml encoder
  2488. simple := &apiservertesting.Simple{
  2489. Other: "bar",
  2490. }
  2491. serializer, ok := api.Codecs.SerializerForMediaType("application/yaml", nil)
  2492. if !ok {
  2493. t.Fatal("No yaml serializer")
  2494. }
  2495. encoder := api.Codecs.EncoderForVersion(serializer, testGroupVersion)
  2496. decoder := api.Codecs.DecoderToVersion(serializer, testInternalGroupVersion)
  2497. data, err := runtime.Encode(encoder, simple)
  2498. if err != nil {
  2499. t.Fatalf("unexpected error: %v", err)
  2500. }
  2501. request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo", bytes.NewBuffer(data))
  2502. if err != nil {
  2503. t.Fatalf("unexpected error: %v", err)
  2504. }
  2505. request.Header.Set("Accept", "application/yaml, application/json")
  2506. request.Header.Set("Content-Type", "application/yaml")
  2507. wg := sync.WaitGroup{}
  2508. wg.Add(1)
  2509. var response *http.Response
  2510. go func() {
  2511. response, err = client.Do(request)
  2512. wg.Done()
  2513. }()
  2514. wg.Wait()
  2515. if err != nil {
  2516. t.Fatalf("unexpected error: %v", err)
  2517. }
  2518. var itemOut apiservertesting.Simple
  2519. body, err := extractBodyDecoder(response, &itemOut, decoder)
  2520. if err != nil {
  2521. t.Fatalf("unexpected error: %v %#v", err, response)
  2522. }
  2523. itemOut.GetObjectKind().SetGroupVersionKind(unversioned.GroupVersionKind{})
  2524. if !reflect.DeepEqual(&itemOut, simple) {
  2525. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simple, string(body))
  2526. }
  2527. if response.StatusCode != http.StatusCreated {
  2528. t.Errorf("Unexpected status: %d, Expected: %d, %#v", response.StatusCode, http.StatusOK, response)
  2529. }
  2530. if !selfLinker.called {
  2531. t.Errorf("Never set self link")
  2532. }
  2533. }
  2534. func TestCreateInNamespace(t *testing.T) {
  2535. storage := SimpleRESTStorage{
  2536. injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
  2537. time.Sleep(5 * time.Millisecond)
  2538. return obj, nil
  2539. },
  2540. }
  2541. selfLinker := &setTestSelfLinker{
  2542. t: t,
  2543. name: "bar",
  2544. namespace: "other",
  2545. expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/other/foo/bar",
  2546. }
  2547. handler := handleLinker(map[string]rest.Storage{"foo": &storage}, selfLinker)
  2548. server := httptest.NewServer(handler)
  2549. defer server.Close()
  2550. client := http.Client{}
  2551. simple := &apiservertesting.Simple{
  2552. Other: "bar",
  2553. }
  2554. data, err := runtime.Encode(testCodec, simple)
  2555. if err != nil {
  2556. t.Fatalf("unexpected error: %v", err)
  2557. }
  2558. request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/foo", bytes.NewBuffer(data))
  2559. if err != nil {
  2560. t.Fatalf("unexpected error: %v", err)
  2561. }
  2562. wg := sync.WaitGroup{}
  2563. wg.Add(1)
  2564. var response *http.Response
  2565. go func() {
  2566. response, err = client.Do(request)
  2567. wg.Done()
  2568. }()
  2569. wg.Wait()
  2570. if err != nil {
  2571. t.Fatalf("unexpected error: %v", err)
  2572. }
  2573. var itemOut apiservertesting.Simple
  2574. body, err := extractBody(response, &itemOut)
  2575. if err != nil {
  2576. t.Fatalf("unexpected error: %v\n%s", err, data)
  2577. }
  2578. itemOut.GetObjectKind().SetGroupVersionKind(unversioned.GroupVersionKind{})
  2579. if !reflect.DeepEqual(&itemOut, simple) {
  2580. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, simple, string(body))
  2581. }
  2582. if response.StatusCode != http.StatusCreated {
  2583. t.Errorf("Unexpected status: %d, Expected: %d, %#v", response.StatusCode, http.StatusOK, response)
  2584. }
  2585. if !selfLinker.called {
  2586. t.Errorf("Never set self link")
  2587. }
  2588. }
  2589. func TestCreateInvokesAdmissionControl(t *testing.T) {
  2590. storage := SimpleRESTStorage{
  2591. injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
  2592. time.Sleep(5 * time.Millisecond)
  2593. return obj, nil
  2594. },
  2595. }
  2596. selfLinker := &setTestSelfLinker{
  2597. t: t,
  2598. name: "bar",
  2599. namespace: "other",
  2600. expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/other/foo/bar",
  2601. }
  2602. handler := handleInternal(map[string]rest.Storage{"foo": &storage}, deny.NewAlwaysDeny(), selfLinker)
  2603. server := httptest.NewServer(handler)
  2604. defer server.Close()
  2605. client := http.Client{}
  2606. simple := &apiservertesting.Simple{
  2607. Other: "bar",
  2608. }
  2609. data, err := runtime.Encode(testCodec, simple)
  2610. if err != nil {
  2611. t.Errorf("unexpected error: %v", err)
  2612. }
  2613. request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/other/foo", bytes.NewBuffer(data))
  2614. if err != nil {
  2615. t.Errorf("unexpected error: %v", err)
  2616. }
  2617. wg := sync.WaitGroup{}
  2618. wg.Add(1)
  2619. var response *http.Response
  2620. go func() {
  2621. response, err = client.Do(request)
  2622. wg.Done()
  2623. }()
  2624. wg.Wait()
  2625. if err != nil {
  2626. t.Errorf("unexpected error: %v", err)
  2627. }
  2628. if response.StatusCode != http.StatusForbidden {
  2629. t.Errorf("Unexpected status: %d, Expected: %d, %#v", response.StatusCode, http.StatusForbidden, response)
  2630. }
  2631. }
  2632. func expectApiStatus(t *testing.T, method, url string, data []byte, code int) *unversioned.Status {
  2633. client := http.Client{}
  2634. request, err := http.NewRequest(method, url, bytes.NewBuffer(data))
  2635. if err != nil {
  2636. t.Fatalf("unexpected error %#v", err)
  2637. return nil
  2638. }
  2639. response, err := client.Do(request)
  2640. if err != nil {
  2641. t.Fatalf("unexpected error on %s %s: %v", method, url, err)
  2642. return nil
  2643. }
  2644. var status unversioned.Status
  2645. if body, err := extractBody(response, &status); err != nil {
  2646. t.Fatalf("unexpected error on %s %s: %v\nbody:\n%s", method, url, err, body)
  2647. return nil
  2648. }
  2649. if code != response.StatusCode {
  2650. t.Fatalf("Expected %s %s to return %d, Got %d", method, url, code, response.StatusCode)
  2651. }
  2652. return &status
  2653. }
  2654. func TestDelayReturnsError(t *testing.T) {
  2655. storage := SimpleRESTStorage{
  2656. injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
  2657. return nil, apierrs.NewAlreadyExists(api.Resource("foos"), "bar")
  2658. },
  2659. }
  2660. handler := handle(map[string]rest.Storage{"foo": &storage})
  2661. server := httptest.NewServer(handler)
  2662. defer server.Close()
  2663. status := expectApiStatus(t, "DELETE", fmt.Sprintf("%s/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo/bar", server.URL), nil, http.StatusConflict)
  2664. if status.Status != unversioned.StatusFailure || status.Message == "" || status.Details == nil || status.Reason != unversioned.StatusReasonAlreadyExists {
  2665. t.Errorf("Unexpected status %#v", status)
  2666. }
  2667. }
  2668. type UnregisteredAPIObject struct {
  2669. Value string
  2670. }
  2671. func (obj *UnregisteredAPIObject) GetObjectKind() unversioned.ObjectKind {
  2672. return unversioned.EmptyObjectKind
  2673. }
  2674. func TestWriteJSONDecodeError(t *testing.T) {
  2675. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  2676. writeNegotiated(api.Codecs, newGroupVersion, w, req, http.StatusOK, &UnregisteredAPIObject{"Undecodable"})
  2677. }))
  2678. defer server.Close()
  2679. // We send a 200 status code before we encode the object, so we expect OK, but there will
  2680. // still be an error object. This seems ok, the alternative is to validate the object before
  2681. // encoding, but this really should never happen, so it's wasted compute for every API request.
  2682. status := expectApiStatus(t, "GET", server.URL, nil, http.StatusOK)
  2683. if status.Reason != unversioned.StatusReasonUnknown {
  2684. t.Errorf("unexpected reason %#v", status)
  2685. }
  2686. if !strings.Contains(status.Message, "no kind is registered for the type apiserver.UnregisteredAPIObject") {
  2687. t.Errorf("unexpected message %#v", status)
  2688. }
  2689. }
  2690. type marshalError struct {
  2691. err error
  2692. }
  2693. func (m *marshalError) MarshalJSON() ([]byte, error) {
  2694. return []byte{}, m.err
  2695. }
  2696. func TestWriteRAWJSONMarshalError(t *testing.T) {
  2697. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  2698. writeRawJSON(http.StatusOK, &marshalError{errors.New("Undecodable")}, w)
  2699. }))
  2700. defer server.Close()
  2701. client := http.Client{}
  2702. resp, err := client.Get(server.URL)
  2703. if err != nil {
  2704. t.Errorf("unexpected error: %v", err)
  2705. }
  2706. if resp.StatusCode != http.StatusInternalServerError {
  2707. t.Errorf("unexpected status code %d", resp.StatusCode)
  2708. }
  2709. }
  2710. func TestCreateTimeout(t *testing.T) {
  2711. testOver := make(chan struct{})
  2712. defer close(testOver)
  2713. storage := SimpleRESTStorage{
  2714. injectedFunction: func(obj runtime.Object) (runtime.Object, error) {
  2715. // Eliminate flakes by ensuring the create operation takes longer than this test.
  2716. <-testOver
  2717. return obj, nil
  2718. },
  2719. }
  2720. handler := handle(map[string]rest.Storage{
  2721. "foo": &storage,
  2722. })
  2723. server := httptest.NewServer(handler)
  2724. defer server.Close()
  2725. simple := &apiservertesting.Simple{Other: "foo"}
  2726. data, err := runtime.Encode(testCodec, simple)
  2727. if err != nil {
  2728. t.Errorf("unexpected error: %v", err)
  2729. }
  2730. itemOut := expectApiStatus(t, "POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/foo?timeout=4ms", data, apierrs.StatusServerTimeout)
  2731. if itemOut.Status != unversioned.StatusFailure || itemOut.Reason != unversioned.StatusReasonTimeout {
  2732. t.Errorf("Unexpected status %#v", itemOut)
  2733. }
  2734. }
  2735. func TestCORSAllowedOrigins(t *testing.T) {
  2736. table := []struct {
  2737. allowedOrigins []string
  2738. origin string
  2739. allowed bool
  2740. }{
  2741. {[]string{}, "example.com", false},
  2742. {[]string{"example.com"}, "example.com", true},
  2743. {[]string{"example.com"}, "not-allowed.com", false},
  2744. {[]string{"not-matching.com", "example.com"}, "example.com", true},
  2745. {[]string{".*"}, "example.com", true},
  2746. }
  2747. for _, item := range table {
  2748. allowedOriginRegexps, err := util.CompileRegexps(item.allowedOrigins)
  2749. if err != nil {
  2750. t.Errorf("unexpected error: %v", err)
  2751. }
  2752. handler := CORS(
  2753. handle(map[string]rest.Storage{}),
  2754. allowedOriginRegexps, nil, nil, "true",
  2755. )
  2756. server := httptest.NewServer(handler)
  2757. defer server.Close()
  2758. client := http.Client{}
  2759. request, err := http.NewRequest("GET", server.URL+"/version", nil)
  2760. if err != nil {
  2761. t.Errorf("unexpected error: %v", err)
  2762. }
  2763. request.Header.Set("Origin", item.origin)
  2764. response, err := client.Do(request)
  2765. if err != nil {
  2766. t.Errorf("unexpected error: %v", err)
  2767. }
  2768. if item.allowed {
  2769. if !reflect.DeepEqual(item.origin, response.Header.Get("Access-Control-Allow-Origin")) {
  2770. t.Errorf("Expected %#v, Got %#v", item.origin, response.Header.Get("Access-Control-Allow-Origin"))
  2771. }
  2772. if response.Header.Get("Access-Control-Allow-Credentials") == "" {
  2773. t.Errorf("Expected Access-Control-Allow-Credentials header to be set")
  2774. }
  2775. if response.Header.Get("Access-Control-Allow-Headers") == "" {
  2776. t.Errorf("Expected Access-Control-Allow-Headers header to be set")
  2777. }
  2778. if response.Header.Get("Access-Control-Allow-Methods") == "" {
  2779. t.Errorf("Expected Access-Control-Allow-Methods header to be set")
  2780. }
  2781. } else {
  2782. if response.Header.Get("Access-Control-Allow-Origin") != "" {
  2783. t.Errorf("Expected Access-Control-Allow-Origin header to not be set")
  2784. }
  2785. if response.Header.Get("Access-Control-Allow-Credentials") != "" {
  2786. t.Errorf("Expected Access-Control-Allow-Credentials header to not be set")
  2787. }
  2788. if response.Header.Get("Access-Control-Allow-Headers") != "" {
  2789. t.Errorf("Expected Access-Control-Allow-Headers header to not be set")
  2790. }
  2791. if response.Header.Get("Access-Control-Allow-Methods") != "" {
  2792. t.Errorf("Expected Access-Control-Allow-Methods header to not be set")
  2793. }
  2794. }
  2795. }
  2796. }
  2797. func TestCreateChecksAPIVersion(t *testing.T) {
  2798. handler := handle(map[string]rest.Storage{"simple": &SimpleRESTStorage{}})
  2799. server := httptest.NewServer(handler)
  2800. defer server.Close()
  2801. client := http.Client{}
  2802. simple := &apiservertesting.Simple{}
  2803. //using newCodec and send the request to testVersion URL shall cause a discrepancy in apiVersion
  2804. data, err := runtime.Encode(newCodec, simple)
  2805. if err != nil {
  2806. t.Errorf("unexpected error: %v", err)
  2807. }
  2808. request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
  2809. if err != nil {
  2810. t.Errorf("unexpected error: %v", err)
  2811. }
  2812. response, err := client.Do(request)
  2813. if err != nil {
  2814. t.Errorf("unexpected error: %v", err)
  2815. }
  2816. if response.StatusCode != http.StatusBadRequest {
  2817. t.Errorf("Unexpected response %#v", response)
  2818. }
  2819. b, err := ioutil.ReadAll(response.Body)
  2820. if err != nil {
  2821. t.Errorf("unexpected error: %v", err)
  2822. } else if !strings.Contains(string(b), "does not match the expected API version") {
  2823. t.Errorf("unexpected response: %s", string(b))
  2824. }
  2825. }
  2826. func TestCreateDefaultsAPIVersion(t *testing.T) {
  2827. handler := handle(map[string]rest.Storage{"simple": &SimpleRESTStorage{}})
  2828. server := httptest.NewServer(handler)
  2829. defer server.Close()
  2830. client := http.Client{}
  2831. simple := &apiservertesting.Simple{}
  2832. data, err := runtime.Encode(codec, simple)
  2833. if err != nil {
  2834. t.Errorf("unexpected error: %v", err)
  2835. }
  2836. m := make(map[string]interface{})
  2837. if err := json.Unmarshal(data, &m); err != nil {
  2838. t.Errorf("unexpected error: %v", err)
  2839. }
  2840. delete(m, "apiVersion")
  2841. data, err = json.Marshal(m)
  2842. if err != nil {
  2843. t.Errorf("unexpected error: %v", err)
  2844. }
  2845. request, err := http.NewRequest("POST", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple", bytes.NewBuffer(data))
  2846. if err != nil {
  2847. t.Errorf("unexpected error: %v", err)
  2848. }
  2849. response, err := client.Do(request)
  2850. if err != nil {
  2851. t.Errorf("unexpected error: %v", err)
  2852. }
  2853. if response.StatusCode != http.StatusCreated {
  2854. t.Errorf("unexpected status: %d, Expected: %d, %#v", response.StatusCode, http.StatusCreated, response)
  2855. }
  2856. }
  2857. func TestUpdateChecksAPIVersion(t *testing.T) {
  2858. handler := handle(map[string]rest.Storage{"simple": &SimpleRESTStorage{}})
  2859. server := httptest.NewServer(handler)
  2860. defer server.Close()
  2861. client := http.Client{}
  2862. simple := &apiservertesting.Simple{ObjectMeta: api.ObjectMeta{Name: "bar"}}
  2863. data, err := runtime.Encode(newCodec, simple)
  2864. if err != nil {
  2865. t.Fatalf("unexpected error: %v", err)
  2866. }
  2867. request, err := http.NewRequest("PUT", server.URL+"/"+prefix+"/"+testGroupVersion.Group+"/"+testGroupVersion.Version+"/namespaces/default/simple/bar", bytes.NewBuffer(data))
  2868. if err != nil {
  2869. t.Fatalf("unexpected error: %v", err)
  2870. }
  2871. response, err := client.Do(request)
  2872. if err != nil {
  2873. t.Fatalf("unexpected error: %v", err)
  2874. }
  2875. if response.StatusCode != http.StatusBadRequest {
  2876. t.Errorf("Unexpected response %#v", response)
  2877. }
  2878. b, err := ioutil.ReadAll(response.Body)
  2879. if err != nil {
  2880. t.Errorf("unexpected error: %v", err)
  2881. } else if !strings.Contains(string(b), "does not match the expected API version") {
  2882. t.Errorf("unexpected response: %s", string(b))
  2883. }
  2884. }
  2885. // SimpleXGSubresource is a cross group subresource, i.e. the subresource does not belong to the
  2886. // same group as its parent resource.
  2887. type SimpleXGSubresource struct {
  2888. unversioned.TypeMeta `json:",inline"`
  2889. api.ObjectMeta `json:"metadata"`
  2890. SubresourceInfo string `json:"subresourceInfo,omitempty"`
  2891. Labels map[string]string `json:"labels,omitempty"`
  2892. }
  2893. func (obj *SimpleXGSubresource) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
  2894. type SimpleXGSubresourceRESTStorage struct {
  2895. item SimpleXGSubresource
  2896. }
  2897. func (storage *SimpleXGSubresourceRESTStorage) New() runtime.Object {
  2898. return &SimpleXGSubresource{}
  2899. }
  2900. func (storage *SimpleXGSubresourceRESTStorage) Get(ctx api.Context, id string) (runtime.Object, error) {
  2901. copied, err := api.Scheme.Copy(&storage.item)
  2902. if err != nil {
  2903. panic(err)
  2904. }
  2905. return copied, nil
  2906. }
  2907. func TestXGSubresource(t *testing.T) {
  2908. container := restful.NewContainer()
  2909. container.Router(restful.CurlyRouter{})
  2910. mux := container.ServeMux
  2911. itemID := "theID"
  2912. subresourceStorage := &SimpleXGSubresourceRESTStorage{
  2913. item: SimpleXGSubresource{
  2914. SubresourceInfo: "foo",
  2915. },
  2916. }
  2917. storage := map[string]rest.Storage{
  2918. "simple": &SimpleRESTStorage{},
  2919. "simple/subsimple": subresourceStorage,
  2920. }
  2921. group := APIGroupVersion{
  2922. Storage: storage,
  2923. RequestInfoResolver: newTestRequestInfoResolver(),
  2924. Creater: api.Scheme,
  2925. Convertor: api.Scheme,
  2926. Copier: api.Scheme,
  2927. Typer: api.Scheme,
  2928. Linker: selfLinker,
  2929. Mapper: namespaceMapper,
  2930. ParameterCodec: api.ParameterCodec,
  2931. Admit: admissionControl,
  2932. Context: requestContextMapper,
  2933. Root: "/" + prefix,
  2934. GroupVersion: testGroupVersion,
  2935. OptionsExternalVersion: &testGroupVersion,
  2936. Serializer: api.Codecs,
  2937. SubresourceGroupVersionKind: map[string]unversioned.GroupVersionKind{
  2938. "simple/subsimple": testGroup2Version.WithKind("SimpleXGSubresource"),
  2939. },
  2940. }
  2941. if err := (&group).InstallREST(container); err != nil {
  2942. panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err))
  2943. }
  2944. InstallVersionHandler(mux, container)
  2945. handler := defaultAPIServer{mux, container}
  2946. server := httptest.NewServer(handler)
  2947. defer server.Close()
  2948. resp, err := http.Get(server.URL + "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + itemID + "/subsimple")
  2949. if err != nil {
  2950. t.Fatalf("unexpected error: %v", err)
  2951. }
  2952. if resp.StatusCode != http.StatusOK {
  2953. t.Fatalf("unexpected response: %#v", resp)
  2954. }
  2955. var itemOut SimpleXGSubresource
  2956. body, err := extractBody(resp, &itemOut)
  2957. if err != nil {
  2958. t.Errorf("unexpected error: %v", err)
  2959. }
  2960. // Test if the returned object has the expected group, version and kind
  2961. // We are directly unmarshaling JSON here because TypeMeta cannot be decoded through the
  2962. // installed decoders. TypeMeta cannot be decoded because it is added to the ignored
  2963. // conversion type list in API scheme and hence cannot be converted from input type object
  2964. // to output type object. So it's values don't appear in the decoded output object.
  2965. decoder := json.NewDecoder(strings.NewReader(body))
  2966. var itemFromBody SimpleXGSubresource
  2967. err = decoder.Decode(&itemFromBody)
  2968. if err != nil {
  2969. t.Errorf("unexpected JSON decoding error: %v", err)
  2970. }
  2971. if want := fmt.Sprintf("%s/%s", testGroup2Version.Group, testGroup2Version.Version); itemFromBody.APIVersion != want {
  2972. t.Errorf("unexpected APIVersion got: %+v want: %+v", itemFromBody.APIVersion, want)
  2973. }
  2974. if itemFromBody.Kind != "SimpleXGSubresource" {
  2975. t.Errorf("unexpected Kind got: %+v want: SimpleXGSubresource", itemFromBody.Kind)
  2976. }
  2977. if itemOut.Name != subresourceStorage.item.Name {
  2978. t.Errorf("Unexpected data: %#v, expected %#v (%s)", itemOut, subresourceStorage.item, string(body))
  2979. }
  2980. }
  2981. func readBodyOrDie(r io.Reader) []byte {
  2982. body, err := ioutil.ReadAll(r)
  2983. if err != nil {
  2984. panic(err)
  2985. }
  2986. return body
  2987. }
  2988. // BenchmarkUpdateProtobuf measures the cost of processing an update on the server in proto
  2989. func BenchmarkUpdateProtobuf(b *testing.B) {
  2990. items := benchmarkItems()
  2991. simpleStorage := &SimpleRESTStorage{}
  2992. handler := handle(map[string]rest.Storage{"simples": simpleStorage})
  2993. server := httptest.NewServer(handler)
  2994. defer server.Close()
  2995. client := http.Client{}
  2996. dest, _ := url.Parse(server.URL)
  2997. dest.Path = "/" + prefix + "/" + newGroupVersion.Group + "/" + newGroupVersion.Version + "/namespaces/foo/simples/bar"
  2998. dest.RawQuery = ""
  2999. info, _ := api.Codecs.SerializerForMediaType("application/vnd.kubernetes.protobuf", nil)
  3000. e := api.Codecs.EncoderForVersion(info.Serializer, newGroupVersion)
  3001. data, err := runtime.Encode(e, &items[0])
  3002. if err != nil {
  3003. b.Fatal(err)
  3004. }
  3005. b.ResetTimer()
  3006. for i := 0; i < b.N; i++ {
  3007. request, err := http.NewRequest("PUT", dest.String(), bytes.NewReader(data))
  3008. if err != nil {
  3009. b.Fatalf("unexpected error: %v", err)
  3010. }
  3011. request.Header.Set("Accept", "application/vnd.kubernetes.protobuf")
  3012. request.Header.Set("Content-Type", "application/vnd.kubernetes.protobuf")
  3013. response, err := client.Do(request)
  3014. if err != nil {
  3015. b.Fatalf("unexpected error: %v", err)
  3016. }
  3017. if response.StatusCode != http.StatusBadRequest {
  3018. body, _ := ioutil.ReadAll(response.Body)
  3019. b.Fatalf("Unexpected response %#v\n%s", response, body)
  3020. }
  3021. _, _ = ioutil.ReadAll(response.Body)
  3022. response.Body.Close()
  3023. }
  3024. b.StopTimer()
  3025. }