route_with_management_fields_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package route_test
  18. import (
  19. "io/ioutil"
  20. "net/http"
  21. "time"
  22. . "github.com/onsi/ginkgo/v2"
  23. . "github.com/onsi/gomega"
  24. "github.com/tidwall/gjson"
  25. "github.com/apisix/manager-api/test/e2e/base"
  26. )
  27. var _ = Describe("route with management fields", func() {
  28. var (
  29. createtime, updatetime gjson.Result
  30. )
  31. DescribeTable("test for route with name description",
  32. func(tc base.HttpTestCase) {
  33. base.RunTestCase(tc)
  34. },
  35. Entry("config route with name and desc (r1)", base.HttpTestCase{
  36. Object: base.ManagerApiExpect(),
  37. Path: "/apisix/admin/routes/r1",
  38. Method: http.MethodPut,
  39. Body: `{
  40. "name": "route1",
  41. "uri": "/hello",
  42. "name": "jack",
  43. "desc": "config route with name and desc",
  44. "upstream": {
  45. "type": "roundrobin",
  46. "nodes": {
  47. "` + base.UpstreamIp + `:1980": 1
  48. }
  49. }
  50. }`,
  51. Headers: map[string]string{"Authorization": base.GetToken()},
  52. ExpectBody: []string{`"code":0`, `"id":"r1"`, `"uri":"/hello"`, `"name":"jack"`,
  53. `"upstream":{"nodes":{"` + base.UpstreamIp + `:1980":1},"type":"roundrobin"}`},
  54. ExpectStatus: http.StatusOK,
  55. }),
  56. Entry("check route exists by name", base.HttpTestCase{
  57. Object: base.ManagerApiExpect(),
  58. Method: http.MethodGet,
  59. Path: "/apisix/admin/notexist/routes",
  60. Query: "name=jack",
  61. Headers: map[string]string{"Authorization": base.GetToken()},
  62. ExpectStatus: http.StatusBadRequest,
  63. ExpectBody: "Route name is reduplicate",
  64. Sleep: base.SleepTime,
  65. }),
  66. Entry("check route exists by name (exclude it self)", base.HttpTestCase{
  67. Object: base.ManagerApiExpect(),
  68. Method: http.MethodGet,
  69. Path: "/apisix/admin/notexist/routes",
  70. Query: "name=jack&exclude=r1",
  71. Headers: map[string]string{"Authorization": base.GetToken()},
  72. ExpectStatus: http.StatusOK,
  73. }),
  74. Entry("access the route's uri (r1)", base.HttpTestCase{
  75. Object: base.APISIXExpect(),
  76. Method: http.MethodGet,
  77. Path: "/hello",
  78. Headers: map[string]string{"Authorization": base.GetToken()},
  79. ExpectStatus: http.StatusOK,
  80. ExpectBody: "hello world",
  81. }),
  82. Entry("verify the route's content (r1)", base.HttpTestCase{
  83. Object: base.ManagerApiExpect(),
  84. Path: "/apisix/admin/routes/r1",
  85. Method: http.MethodGet,
  86. Headers: map[string]string{"Authorization": base.GetToken()},
  87. ExpectStatus: http.StatusOK,
  88. ExpectBody: "\"name\":\"jack\",\"desc\":\"config route with name and desc\"",
  89. }),
  90. )
  91. It("get the route information", func() {
  92. time.Sleep(time.Duration(100) * time.Millisecond)
  93. basepath := base.ManagerAPIHost + "/apisix/admin/routes"
  94. request, _ := http.NewRequest("GET", basepath+"/r1", nil)
  95. request.Header.Add("Authorization", base.GetToken())
  96. resp, err := http.DefaultClient.Do(request)
  97. Expect(err).Should(BeNil())
  98. defer resp.Body.Close()
  99. respBody, _ := ioutil.ReadAll(resp.Body)
  100. createtime = gjson.Get(string(respBody), "data.create_time")
  101. updatetime = gjson.Get(string(respBody), "data.update_time")
  102. Expect(createtime.Int()).To(SatisfyAll(
  103. BeNumerically(">=", time.Now().Unix()-1),
  104. BeNumerically("<=", time.Now().Unix()+1),
  105. ))
  106. Expect(updatetime.Int()).To(SatisfyAll(
  107. BeNumerically(">=", time.Now().Unix()-1),
  108. BeNumerically("<=", time.Now().Unix()+1),
  109. ))
  110. })
  111. DescribeTable("test for route with name description",
  112. func(tc base.HttpTestCase) {
  113. base.RunTestCase(tc)
  114. },
  115. Entry("update the route (r1)", base.HttpTestCase{
  116. Object: base.ManagerApiExpect(),
  117. Path: "/apisix/admin/routes/r1",
  118. Method: http.MethodPut,
  119. Body: `{
  120. "name": "route1",
  121. "uri": "/hello",
  122. "name": "new jack",
  123. "desc": "new desc",
  124. "upstream": {
  125. "type": "roundrobin",
  126. "nodes": {
  127. "` + base.UpstreamIp + `:1980": 1
  128. }
  129. }
  130. }`,
  131. Headers: map[string]string{"Authorization": base.GetToken()},
  132. ExpectStatus: http.StatusOK,
  133. ExpectBody: []string{`"code":0`, `"id":"r1"`, `"uri":"/hello"`, `"name":"new jack"`,
  134. `"upstream":{"nodes":{"` + base.UpstreamIp + `:1980":1},"type":"roundrobin"}`},
  135. Sleep: time.Duration(2) * time.Second,
  136. }),
  137. Entry("access the route's uri (r1)", base.HttpTestCase{
  138. Object: base.APISIXExpect(),
  139. Method: http.MethodGet,
  140. Path: "/hello",
  141. Headers: map[string]string{"Authorization": base.GetToken()},
  142. ExpectStatus: http.StatusOK,
  143. ExpectBody: "hello world",
  144. Sleep: base.SleepTime,
  145. }),
  146. )
  147. It("get the updated route information", func() {
  148. time.Sleep(time.Duration(100) * time.Millisecond)
  149. basepath := base.ManagerAPIHost + "/apisix/admin/routes"
  150. request, _ := http.NewRequest("GET", basepath+"/r1", nil)
  151. request.Header.Add("Authorization", base.GetToken())
  152. resp, _ := http.DefaultClient.Do(request)
  153. respBody, _ := ioutil.ReadAll(resp.Body)
  154. createtime2 := gjson.Get(string(respBody), "data.create_time")
  155. updatetime2 := gjson.Get(string(respBody), "data.update_time")
  156. //verify the route and compare result
  157. Expect(gjson.Get(string(respBody), "data.name").String()).To(Equal("new jack"))
  158. Expect(gjson.Get(string(respBody), "data.desc").String()).To(Equal("new desc"))
  159. Expect(createtime2.String()).To(Equal(createtime.String()))
  160. Expect(updatetime2.String()).NotTo(Equal(updatetime.String()))
  161. })
  162. It("delete the route (r1)", func() {
  163. base.RunTestCase(base.HttpTestCase{
  164. Object: base.ManagerApiExpect(),
  165. Method: http.MethodDelete,
  166. Path: "/apisix/admin/routes/r1",
  167. Headers: map[string]string{"Authorization": base.GetToken()},
  168. ExpectStatus: http.StatusOK,
  169. })
  170. })
  171. It("verify delete route (r1) success", func() {
  172. base.RunTestCase(base.HttpTestCase{
  173. Object: base.APISIXExpect(),
  174. Method: http.MethodGet,
  175. Path: "/hello",
  176. Headers: map[string]string{"Authorization": base.GetToken()},
  177. ExpectStatus: http.StatusNotFound,
  178. ExpectBody: `{"error_msg":"404 Route Not Found"}`,
  179. Sleep: base.SleepTime,
  180. })
  181. })
  182. })
  183. var _ = Describe("route with management fields", func() {
  184. DescribeTable("test route with label",
  185. func(tc base.HttpTestCase) {
  186. base.RunTestCase(tc)
  187. },
  188. Entry("config route with labels (r1)", base.HttpTestCase{
  189. Object: base.ManagerApiExpect(),
  190. Path: "/apisix/admin/routes/r1",
  191. Method: http.MethodPut,
  192. Body: `{
  193. "name": "route1",
  194. "uri": "/hello",
  195. "labels": {
  196. "build":"16",
  197. "env":"production",
  198. "version":"v2"
  199. },
  200. "upstream": {
  201. "type": "roundrobin",
  202. "nodes": {
  203. "` + base.UpstreamIp + `:1980": 1
  204. }
  205. }
  206. }`,
  207. Headers: map[string]string{"Authorization": base.GetToken()},
  208. ExpectBody: []string{`"code":0`, `"id":"r1"`, `"uri":"/hello"`, `"name":"route1"`,
  209. `"upstream":{"nodes":{"` + base.UpstreamIp + `:1980":1},"type":"roundrobin"}`,
  210. `"labels":{"build":"16","env":"production","version":"v2"}`},
  211. ExpectStatus: http.StatusOK,
  212. }),
  213. Entry("access the route's uri (r1)", base.HttpTestCase{
  214. Object: base.APISIXExpect(),
  215. Method: http.MethodGet,
  216. Path: "/hello",
  217. Headers: map[string]string{"Authorization": base.GetToken()},
  218. ExpectStatus: http.StatusOK,
  219. ExpectBody: "hello world",
  220. Sleep: base.SleepTime,
  221. }),
  222. Entry("verify the route's detail (r1)", base.HttpTestCase{
  223. Object: base.ManagerApiExpect(),
  224. Path: "/apisix/admin/routes/r1",
  225. Method: http.MethodGet,
  226. Headers: map[string]string{"Authorization": base.GetToken()},
  227. ExpectStatus: http.StatusOK,
  228. ExpectBody: `"labels":{"build":"16","env":"production","version":"v2"`,
  229. Sleep: base.SleepTime,
  230. }),
  231. Entry("delete the route (r1)", base.HttpTestCase{
  232. Object: base.ManagerApiExpect(),
  233. Method: http.MethodDelete,
  234. Path: "/apisix/admin/routes/r1",
  235. Headers: map[string]string{"Authorization": base.GetToken()},
  236. ExpectStatus: http.StatusOK,
  237. }),
  238. Entry("access the route after delete it", base.HttpTestCase{
  239. Object: base.APISIXExpect(),
  240. Method: http.MethodGet,
  241. Path: "/hello",
  242. Headers: map[string]string{"Authorization": base.GetToken()},
  243. ExpectStatus: http.StatusNotFound,
  244. ExpectBody: `{"error_msg":"404 Route Not Found"}`,
  245. Sleep: base.SleepTime,
  246. }),
  247. )
  248. })
  249. var _ = Describe("route with management fields", func() {
  250. DescribeTable("test route search with label",
  251. func(tc base.HttpTestCase) {
  252. base.RunTestCase(tc)
  253. },
  254. Entry("config route with labels (r1)", base.HttpTestCase{
  255. Object: base.ManagerApiExpect(),
  256. Path: "/apisix/admin/routes/r1",
  257. Method: http.MethodPut,
  258. Body: `{
  259. "name": "route1",
  260. "uri": "/hello",
  261. "labels": {
  262. "build":"16",
  263. "env":"production",
  264. "version":"v2"
  265. },
  266. "upstream": {
  267. "type": "roundrobin",
  268. "nodes": {
  269. "` + base.UpstreamIp + `:1980": 1
  270. }
  271. }
  272. }`,
  273. Headers: map[string]string{"Authorization": base.GetToken()},
  274. ExpectBody: []string{`"code":0`, `"id":"r1"`, `"uri":"/hello"`, `"name":"route1"`,
  275. `"upstream":{"nodes":{"` + base.UpstreamIp + `:1980":1},"type":"roundrobin"}`,
  276. `"labels":{"build":"16","env":"production","version":"v2"}`},
  277. ExpectStatus: http.StatusOK,
  278. }),
  279. Entry("config route with labels (r2)", base.HttpTestCase{
  280. Object: base.ManagerApiExpect(),
  281. Path: "/apisix/admin/routes/r2",
  282. Method: http.MethodPut,
  283. Body: `{
  284. "name": "route2",
  285. "uri": "/hello2",
  286. "labels": {
  287. "build":"17",
  288. "env":"dev",
  289. "version":"v2",
  290. "extra": "test"
  291. },
  292. "upstream": {
  293. "type": "roundrobin",
  294. "nodes": {
  295. "` + base.UpstreamIp + `:1980": 1
  296. }
  297. }
  298. }`,
  299. Headers: map[string]string{"Authorization": base.GetToken()},
  300. ExpectBody: []string{`"code":0`, `"id":"r2"`, `"uri":"/hello2"`, `"name":"route2"`,
  301. `"upstream":{"nodes":{"` + base.UpstreamIp + `:1980":1},"type":"roundrobin"}`,
  302. `"labels":{"build":"17","env":"dev","extra":"test","version":"v2"}`,
  303. },
  304. ExpectStatus: http.StatusOK,
  305. }),
  306. Entry("access the route's uri (r1)", base.HttpTestCase{
  307. Object: base.APISIXExpect(),
  308. Method: http.MethodGet,
  309. Path: "/hello",
  310. Headers: map[string]string{"Authorization": base.GetToken()},
  311. ExpectStatus: http.StatusOK,
  312. ExpectBody: "hello world",
  313. Sleep: base.SleepTime,
  314. }),
  315. Entry("verify the route's detail (r1)", base.HttpTestCase{
  316. Object: base.ManagerApiExpect(),
  317. Path: "/apisix/admin/routes/r1",
  318. Method: http.MethodGet,
  319. Headers: map[string]string{"Authorization": base.GetToken()},
  320. ExpectStatus: http.StatusOK,
  321. ExpectBody: `"labels":{"build":"16","env":"production","version":"v2"`,
  322. Sleep: base.SleepTime,
  323. }),
  324. Entry("search the route by label", base.HttpTestCase{
  325. Object: base.ManagerApiExpect(),
  326. Path: "/apisix/admin/routes",
  327. Query: "label=build:16",
  328. Method: http.MethodGet,
  329. Headers: map[string]string{"Authorization": base.GetToken()},
  330. ExpectStatus: http.StatusOK,
  331. ExpectBody: `"labels":{"build":"16","env":"production","version":"v2"`,
  332. Sleep: base.SleepTime,
  333. }),
  334. Entry("search the route by label (only key)", base.HttpTestCase{
  335. Object: base.ManagerApiExpect(),
  336. Path: "/apisix/admin/routes",
  337. Query: "label=extra",
  338. Method: http.MethodGet,
  339. Headers: map[string]string{"Authorization": base.GetToken()},
  340. ExpectStatus: http.StatusOK,
  341. ExpectBody: `"labels":{"build":"17","env":"dev","extra":"test","version":"v2"`,
  342. Sleep: base.SleepTime,
  343. }),
  344. Entry("search the route by label (combination)", base.HttpTestCase{
  345. Object: base.ManagerApiExpect(),
  346. Path: "/apisix/admin/routes",
  347. Query: "label=extra,build:16",
  348. Method: http.MethodGet,
  349. Headers: map[string]string{"Authorization": base.GetToken()},
  350. ExpectStatus: http.StatusOK,
  351. ExpectBody: `"total_size":2`,
  352. Sleep: base.SleepTime,
  353. }),
  354. Entry("search the route by label (combination)", base.HttpTestCase{
  355. Object: base.ManagerApiExpect(),
  356. Path: "/apisix/admin/routes",
  357. Query: "label=build:16,build:17",
  358. Method: http.MethodGet,
  359. Headers: map[string]string{"Authorization": base.GetToken()},
  360. ExpectStatus: http.StatusOK,
  361. ExpectBody: `"total_size":2`,
  362. Sleep: base.SleepTime,
  363. }),
  364. Entry("delete the route (r1)", base.HttpTestCase{
  365. Object: base.ManagerApiExpect(),
  366. Method: http.MethodDelete,
  367. Path: "/apisix/admin/routes/r1",
  368. Headers: map[string]string{"Authorization": base.GetToken()},
  369. ExpectStatus: http.StatusOK,
  370. }),
  371. Entry("delete the route (r2)", base.HttpTestCase{
  372. Object: base.ManagerApiExpect(),
  373. Method: http.MethodDelete,
  374. Path: "/apisix/admin/routes/r2",
  375. Headers: map[string]string{"Authorization": base.GetToken()},
  376. ExpectStatus: http.StatusOK,
  377. }),
  378. Entry("access the route after delete it", base.HttpTestCase{
  379. Object: base.APISIXExpect(),
  380. Method: http.MethodGet,
  381. Path: "/hello",
  382. Headers: map[string]string{"Authorization": base.GetToken()},
  383. ExpectStatus: http.StatusNotFound,
  384. ExpectBody: `{"error_msg":"404 Route Not Found"}`,
  385. Sleep: base.SleepTime,
  386. }),
  387. )
  388. })
  389. var _ = Describe("route with management fields", func() {
  390. DescribeTable("test route search with create time",
  391. func(tc base.HttpTestCase) {
  392. base.RunTestCase(tc)
  393. },
  394. Entry("create route with create_time", base.HttpTestCase{
  395. Object: base.ManagerApiExpect(),
  396. Path: "/apisix/admin/routes/r1",
  397. Method: http.MethodPut,
  398. Body: `{
  399. "name": "route1",
  400. "uri": "/hello",
  401. "create_time": 1608792721,
  402. "upstream": {
  403. "type": "roundrobin",
  404. "nodes": {
  405. "` + base.UpstreamIp + `:1980": 1
  406. }
  407. }
  408. }`,
  409. Headers: map[string]string{"Authorization": base.GetToken()},
  410. ExpectBody: `"message":"we don't accept create_time from client"`,
  411. ExpectStatus: http.StatusBadRequest,
  412. }),
  413. Entry("create route with update_time", base.HttpTestCase{
  414. Object: base.ManagerApiExpect(),
  415. Path: "/apisix/admin/routes/r1",
  416. Method: http.MethodPut,
  417. Body: `{
  418. "name": "route1",
  419. "uri": "/hello",
  420. "update_time": 1608792721,
  421. "upstream": {
  422. "type": "roundrobin",
  423. "nodes": {
  424. "` + base.UpstreamIp + `:1980": 1
  425. }
  426. }
  427. }`,
  428. Headers: map[string]string{"Authorization": base.GetToken()},
  429. ExpectBody: `"message":"we don't accept update_time from client"`,
  430. ExpectStatus: http.StatusBadRequest,
  431. }),
  432. Entry("create route with create_time and update_time", base.HttpTestCase{
  433. Object: base.ManagerApiExpect(),
  434. Path: "/apisix/admin/routes/r1",
  435. Method: http.MethodPut,
  436. Body: `{
  437. "name": "route1",
  438. "uri": "/hello",
  439. "create_time": 1608792721,
  440. "update_time": 1608792721,
  441. "upstream": {
  442. "type": "roundrobin",
  443. "nodes": {
  444. "` + base.UpstreamIp + `:1980": 1
  445. }
  446. }
  447. }`,
  448. Headers: map[string]string{"Authorization": base.GetToken()},
  449. ExpectBody: `"message":"we don't accept create_time from client"`,
  450. ExpectStatus: http.StatusBadRequest,
  451. }),
  452. Entry("make sure the route not created", base.HttpTestCase{
  453. Object: base.APISIXExpect(),
  454. Method: http.MethodGet,
  455. Path: "/hello",
  456. ExpectStatus: http.StatusNotFound,
  457. ExpectBody: `{"error_msg":"404 Route Not Found"}`,
  458. }),
  459. )
  460. })