PageRenderTime 42ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/spec/requests/api/runners_spec.rb

https://gitlab.com/NestorTejero/gitlab-ce
Ruby | 464 lines | 409 code | 54 blank | 1 comment | 3 complexity | 7ce01bb54514c1eac5bcb5375ae4a214 MD5 | raw file
  1. require 'spec_helper'
  2. describe API::Runners, api: true do
  3. include ApiHelpers
  4. let(:admin) { create(:user, :admin) }
  5. let(:user) { create(:user) }
  6. let(:user2) { create(:user) }
  7. let(:project) { create(:project, creator_id: user.id) }
  8. let(:project2) { create(:project, creator_id: user.id) }
  9. let!(:shared_runner) { create(:ci_runner, :shared) }
  10. let!(:unused_specific_runner) { create(:ci_runner) }
  11. let!(:specific_runner) do
  12. create(:ci_runner).tap do |runner|
  13. create(:ci_runner_project, runner: runner, project: project)
  14. end
  15. end
  16. let!(:two_projects_runner) do
  17. create(:ci_runner).tap do |runner|
  18. create(:ci_runner_project, runner: runner, project: project)
  19. create(:ci_runner_project, runner: runner, project: project2)
  20. end
  21. end
  22. before do
  23. # Set project access for users
  24. create(:project_member, :master, user: user, project: project)
  25. create(:project_member, :master, user: user, project: project2)
  26. create(:project_member, :reporter, user: user2, project: project)
  27. end
  28. describe 'GET /runners' do
  29. context 'authorized user' do
  30. it 'should return user available runners' do
  31. get api('/runners', user)
  32. shared = json_response.any?{ |r| r['is_shared'] }
  33. expect(response.status).to eq(200)
  34. expect(json_response).to be_an Array
  35. expect(shared).to be_falsey
  36. end
  37. it 'should filter runners by scope' do
  38. get api('/runners?scope=active', user)
  39. shared = json_response.any?{ |r| r['is_shared'] }
  40. expect(response.status).to eq(200)
  41. expect(json_response).to be_an Array
  42. expect(shared).to be_falsey
  43. end
  44. it 'should avoid filtering if scope is invalid' do
  45. get api('/runners?scope=unknown', user)
  46. expect(response.status).to eq(400)
  47. end
  48. end
  49. context 'unauthorized user' do
  50. it 'should not return runners' do
  51. get api('/runners')
  52. expect(response.status).to eq(401)
  53. end
  54. end
  55. end
  56. describe 'GET /runners/all' do
  57. context 'authorized user' do
  58. context 'with admin privileges' do
  59. it 'should return all runners' do
  60. get api('/runners/all', admin)
  61. shared = json_response.any?{ |r| r['is_shared'] }
  62. expect(response.status).to eq(200)
  63. expect(json_response).to be_an Array
  64. expect(shared).to be_truthy
  65. end
  66. end
  67. context 'without admin privileges' do
  68. it 'should not return runners list' do
  69. get api('/runners/all', user)
  70. expect(response.status).to eq(403)
  71. end
  72. end
  73. it 'should filter runners by scope' do
  74. get api('/runners/all?scope=specific', admin)
  75. shared = json_response.any?{ |r| r['is_shared'] }
  76. expect(response.status).to eq(200)
  77. expect(json_response).to be_an Array
  78. expect(shared).to be_falsey
  79. end
  80. it 'should avoid filtering if scope is invalid' do
  81. get api('/runners?scope=unknown', admin)
  82. expect(response.status).to eq(400)
  83. end
  84. end
  85. context 'unauthorized user' do
  86. it 'should not return runners' do
  87. get api('/runners')
  88. expect(response.status).to eq(401)
  89. end
  90. end
  91. end
  92. describe 'GET /runners/:id' do
  93. context 'admin user' do
  94. context 'when runner is shared' do
  95. it "should return runner's details" do
  96. get api("/runners/#{shared_runner.id}", admin)
  97. expect(response.status).to eq(200)
  98. expect(json_response['description']).to eq(shared_runner.description)
  99. end
  100. end
  101. context 'when runner is not shared' do
  102. it "should return runner's details" do
  103. get api("/runners/#{specific_runner.id}", admin)
  104. expect(response.status).to eq(200)
  105. expect(json_response['description']).to eq(specific_runner.description)
  106. end
  107. end
  108. it 'should return 404 if runner does not exists' do
  109. get api('/runners/9999', admin)
  110. expect(response.status).to eq(404)
  111. end
  112. end
  113. context "runner project's administrative user" do
  114. context 'when runner is not shared' do
  115. it "should return runner's details" do
  116. get api("/runners/#{specific_runner.id}", user)
  117. expect(response.status).to eq(200)
  118. expect(json_response['description']).to eq(specific_runner.description)
  119. end
  120. end
  121. context 'when runner is shared' do
  122. it "should return runner's details" do
  123. get api("/runners/#{shared_runner.id}", user)
  124. expect(response.status).to eq(200)
  125. expect(json_response['description']).to eq(shared_runner.description)
  126. end
  127. end
  128. end
  129. context 'other authorized user' do
  130. it "should not return runner's details" do
  131. get api("/runners/#{specific_runner.id}", user2)
  132. expect(response.status).to eq(403)
  133. end
  134. end
  135. context 'unauthorized user' do
  136. it "should not return runner's details" do
  137. get api("/runners/#{specific_runner.id}")
  138. expect(response.status).to eq(401)
  139. end
  140. end
  141. end
  142. describe 'PUT /runners/:id' do
  143. context 'admin user' do
  144. context 'when runner is shared' do
  145. it 'should update runner' do
  146. description = shared_runner.description
  147. active = shared_runner.active
  148. put api("/runners/#{shared_runner.id}", admin), description: "#{description}_updated", active: !active,
  149. tag_list: ['ruby2.1', 'pgsql', 'mysql']
  150. shared_runner.reload
  151. expect(response.status).to eq(200)
  152. expect(shared_runner.description).to eq("#{description}_updated")
  153. expect(shared_runner.active).to eq(!active)
  154. expect(shared_runner.tag_list).to include('ruby2.1', 'pgsql', 'mysql')
  155. end
  156. end
  157. context 'when runner is not shared' do
  158. it 'should update runner' do
  159. description = specific_runner.description
  160. put api("/runners/#{specific_runner.id}", admin), description: 'test'
  161. specific_runner.reload
  162. expect(response.status).to eq(200)
  163. expect(specific_runner.description).to eq('test')
  164. expect(specific_runner.description).not_to eq(description)
  165. end
  166. end
  167. it 'should return 404 if runner does not exists' do
  168. put api('/runners/9999', admin), description: 'test'
  169. expect(response.status).to eq(404)
  170. end
  171. end
  172. context 'authorized user' do
  173. context 'when runner is shared' do
  174. it 'should not update runner' do
  175. put api("/runners/#{shared_runner.id}", user)
  176. expect(response.status).to eq(403)
  177. end
  178. end
  179. context 'when runner is not shared' do
  180. it 'should not update runner without access to it' do
  181. put api("/runners/#{specific_runner.id}", user2)
  182. expect(response.status).to eq(403)
  183. end
  184. it 'should update runner with access to it' do
  185. description = specific_runner.description
  186. put api("/runners/#{specific_runner.id}", admin), description: 'test'
  187. specific_runner.reload
  188. expect(response.status).to eq(200)
  189. expect(specific_runner.description).to eq('test')
  190. expect(specific_runner.description).not_to eq(description)
  191. end
  192. end
  193. end
  194. context 'unauthorized user' do
  195. it 'should not delete runner' do
  196. put api("/runners/#{specific_runner.id}")
  197. expect(response.status).to eq(401)
  198. end
  199. end
  200. end
  201. describe 'DELETE /runners/:id' do
  202. context 'admin user' do
  203. context 'when runner is shared' do
  204. it 'should delete runner' do
  205. expect do
  206. delete api("/runners/#{shared_runner.id}", admin)
  207. end.to change{ Ci::Runner.shared.count }.by(-1)
  208. expect(response.status).to eq(200)
  209. end
  210. end
  211. context 'when runner is not shared' do
  212. it 'should delete unused runner' do
  213. expect do
  214. delete api("/runners/#{unused_specific_runner.id}", admin)
  215. end.to change{ Ci::Runner.specific.count }.by(-1)
  216. expect(response.status).to eq(200)
  217. end
  218. it 'should delete used runner' do
  219. expect do
  220. delete api("/runners/#{specific_runner.id}", admin)
  221. end.to change{ Ci::Runner.specific.count }.by(-1)
  222. expect(response.status).to eq(200)
  223. end
  224. end
  225. it 'should return 404 if runner does not exists' do
  226. delete api('/runners/9999', admin)
  227. expect(response.status).to eq(404)
  228. end
  229. end
  230. context 'authorized user' do
  231. context 'when runner is shared' do
  232. it 'should not delete runner' do
  233. delete api("/runners/#{shared_runner.id}", user)
  234. expect(response.status).to eq(403)
  235. end
  236. end
  237. context 'when runner is not shared' do
  238. it 'should not delete runner without access to it' do
  239. delete api("/runners/#{specific_runner.id}", user2)
  240. expect(response.status).to eq(403)
  241. end
  242. it 'should not delete runner with more than one associated project' do
  243. delete api("/runners/#{two_projects_runner.id}", user)
  244. expect(response.status).to eq(403)
  245. end
  246. it 'should delete runner for one owned project' do
  247. expect do
  248. delete api("/runners/#{specific_runner.id}", user)
  249. end.to change{ Ci::Runner.specific.count }.by(-1)
  250. expect(response.status).to eq(200)
  251. end
  252. end
  253. end
  254. context 'unauthorized user' do
  255. it 'should not delete runner' do
  256. delete api("/runners/#{specific_runner.id}")
  257. expect(response.status).to eq(401)
  258. end
  259. end
  260. end
  261. describe 'GET /projects/:id/runners' do
  262. context 'authorized user with master privileges' do
  263. it "should return project's runners" do
  264. get api("/projects/#{project.id}/runners", user)
  265. shared = json_response.any?{ |r| r['is_shared'] }
  266. expect(response.status).to eq(200)
  267. expect(json_response).to be_an Array
  268. expect(shared).to be_truthy
  269. end
  270. end
  271. context 'authorized user without master privileges' do
  272. it "should not return project's runners" do
  273. get api("/projects/#{project.id}/runners", user2)
  274. expect(response.status).to eq(403)
  275. end
  276. end
  277. context 'unauthorized user' do
  278. it "should not return project's runners" do
  279. get api("/projects/#{project.id}/runners")
  280. expect(response.status).to eq(401)
  281. end
  282. end
  283. end
  284. describe 'POST /projects/:id/runners' do
  285. context 'authorized user' do
  286. it 'should enable specific runner' do
  287. specific_runner2 = create(:ci_runner).tap do |runner|
  288. create(:ci_runner_project, runner: runner, project: project2)
  289. end
  290. expect do
  291. post api("/projects/#{project.id}/runners", user), runner_id: specific_runner2.id
  292. end.to change{ project.runners.count }.by(+1)
  293. expect(response.status).to eq(201)
  294. end
  295. it 'should avoid changes when enabling already enabled runner' do
  296. expect do
  297. post api("/projects/#{project.id}/runners", user), runner_id: specific_runner.id
  298. end.to change{ project.runners.count }.by(0)
  299. expect(response.status).to eq(201)
  300. end
  301. it 'should not enable shared runner' do
  302. post api("/projects/#{project.id}/runners", user), runner_id: shared_runner.id
  303. expect(response.status).to eq(403)
  304. end
  305. context 'user is admin' do
  306. it 'should enable any specific runner' do
  307. expect do
  308. post api("/projects/#{project.id}/runners", admin), runner_id: unused_specific_runner.id
  309. end.to change{ project.runners.count }.by(+1)
  310. expect(response.status).to eq(201)
  311. end
  312. end
  313. context 'user is not admin' do
  314. it 'should not enable runner without access to' do
  315. post api("/projects/#{project.id}/runners", user), runner_id: unused_specific_runner.id
  316. expect(response.status).to eq(403)
  317. end
  318. end
  319. it 'should raise an error when no runner_id param is provided' do
  320. post api("/projects/#{project.id}/runners", admin)
  321. expect(response.status).to eq(400)
  322. end
  323. end
  324. context 'authorized user without permissions' do
  325. it 'should not enable runner' do
  326. post api("/projects/#{project.id}/runners", user2)
  327. expect(response.status).to eq(403)
  328. end
  329. end
  330. context 'unauthorized user' do
  331. it 'should not enable runner' do
  332. post api("/projects/#{project.id}/runners")
  333. expect(response.status).to eq(401)
  334. end
  335. end
  336. end
  337. describe 'DELETE /projects/:id/runners/:runner_id' do
  338. context 'authorized user' do
  339. context 'when runner have more than one associated projects' do
  340. it "should disable project's runner" do
  341. expect do
  342. delete api("/projects/#{project.id}/runners/#{two_projects_runner.id}", user)
  343. end.to change{ project.runners.count }.by(-1)
  344. expect(response.status).to eq(200)
  345. end
  346. end
  347. context 'when runner have one associated projects' do
  348. it "should not disable project's runner" do
  349. expect do
  350. delete api("/projects/#{project.id}/runners/#{specific_runner.id}", user)
  351. end.to change{ project.runners.count }.by(0)
  352. expect(response.status).to eq(403)
  353. end
  354. end
  355. it 'should return 404 is runner is not found' do
  356. delete api("/projects/#{project.id}/runners/9999", user)
  357. expect(response.status).to eq(404)
  358. end
  359. end
  360. context 'authorized user without permissions' do
  361. it "should not disable project's runner" do
  362. delete api("/projects/#{project.id}/runners/#{specific_runner.id}", user2)
  363. expect(response.status).to eq(403)
  364. end
  365. end
  366. context 'unauthorized user' do
  367. it "should not disable project's runner" do
  368. delete api("/projects/#{project.id}/runners/#{specific_runner.id}")
  369. expect(response.status).to eq(401)
  370. end
  371. end
  372. end
  373. end