PageRenderTime 57ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/spec/requests/api/project_clusters_spec.rb

https://gitlab.com/jamgregory/gitlab-ce
Ruby | 449 lines | 355 code | 93 blank | 1 comment | 0 complexity | 8b673e8f85a0c014cb0f4e666a44059e MD5 | raw file
  1. # frozen_string_literal: true
  2. require 'spec_helper'
  3. describe API::ProjectClusters do
  4. include KubernetesHelpers
  5. let(:current_user) { create(:user) }
  6. let(:developer_user) { create(:user) }
  7. let(:project) { create(:project) }
  8. before do
  9. project.add_maintainer(current_user)
  10. project.add_developer(developer_user)
  11. end
  12. describe 'GET /projects/:id/clusters' do
  13. let!(:extra_cluster) { create(:cluster, :provided_by_gcp, :project) }
  14. let!(:clusters) do
  15. create_list(:cluster, 5, :provided_by_gcp, :project, :production_environment,
  16. projects: [project])
  17. end
  18. context 'non-authorized user' do
  19. it 'responds with 403' do
  20. get api("/projects/#{project.id}/clusters", developer_user)
  21. expect(response).to have_gitlab_http_status(403)
  22. end
  23. end
  24. context 'authorized user' do
  25. before do
  26. get api("/projects/#{project.id}/clusters", current_user)
  27. end
  28. it 'responds with 200' do
  29. expect(response).to have_gitlab_http_status(200)
  30. end
  31. it 'includes pagination headers' do
  32. expect(response).to include_pagination_headers
  33. end
  34. it 'onlies include authorized clusters' do
  35. cluster_ids = json_response.map { |cluster| cluster['id'] }
  36. expect(cluster_ids).to match_array(clusters.pluck(:id))
  37. expect(cluster_ids).not_to include(extra_cluster.id)
  38. end
  39. end
  40. end
  41. describe 'GET /projects/:id/clusters/:cluster_id' do
  42. let(:cluster_id) { cluster.id }
  43. let(:platform_kubernetes) do
  44. create(:cluster_platform_kubernetes, :configured,
  45. namespace: 'project-namespace')
  46. end
  47. let(:cluster) do
  48. create(:cluster, :project, :provided_by_gcp, :with_domain,
  49. platform_kubernetes: platform_kubernetes,
  50. user: current_user,
  51. projects: [project])
  52. end
  53. context 'non-authorized user' do
  54. it 'responds with 403' do
  55. get api("/projects/#{project.id}/clusters/#{cluster_id}", developer_user)
  56. expect(response).to have_gitlab_http_status(403)
  57. end
  58. end
  59. context 'authorized user' do
  60. before do
  61. get api("/projects/#{project.id}/clusters/#{cluster_id}", current_user)
  62. end
  63. it 'returns specific cluster' do
  64. expect(json_response['id']).to eq(cluster.id)
  65. end
  66. it 'returns cluster information' do
  67. expect(json_response['provider_type']).to eq('gcp')
  68. expect(json_response['platform_type']).to eq('kubernetes')
  69. expect(json_response['environment_scope']).to eq('*')
  70. expect(json_response['cluster_type']).to eq('project_type')
  71. expect(json_response['domain']).to eq('example.com')
  72. end
  73. it 'returns project information' do
  74. cluster_project = json_response['project']
  75. expect(cluster_project['id']).to eq(project.id)
  76. expect(cluster_project['name']).to eq(project.name)
  77. expect(cluster_project['path']).to eq(project.path)
  78. end
  79. it 'returns kubernetes platform information' do
  80. platform = json_response['platform_kubernetes']
  81. expect(platform['api_url']).to eq('https://kubernetes.example.com')
  82. expect(platform['namespace']).to eq('project-namespace')
  83. expect(platform['ca_cert']).to be_present
  84. end
  85. it 'returns user information' do
  86. user = json_response['user']
  87. expect(user['id']).to eq(current_user.id)
  88. expect(user['username']).to eq(current_user.username)
  89. end
  90. it 'returns GCP provider information' do
  91. gcp_provider = json_response['provider_gcp']
  92. expect(gcp_provider['cluster_id']).to eq(cluster.id)
  93. expect(gcp_provider['status_name']).to eq('created')
  94. expect(gcp_provider['gcp_project_id']).to eq('test-gcp-project')
  95. expect(gcp_provider['zone']).to eq('us-central1-a')
  96. expect(gcp_provider['machine_type']).to eq('n1-standard-2')
  97. expect(gcp_provider['num_nodes']).to eq(3)
  98. expect(gcp_provider['endpoint']).to eq('111.111.111.111')
  99. end
  100. context 'when cluster has no provider' do
  101. let(:cluster) do
  102. create(:cluster, :project, :provided_by_user,
  103. projects: [project])
  104. end
  105. it 'does not include GCP provider info' do
  106. expect(json_response['provider_gcp']).not_to be_present
  107. end
  108. end
  109. context 'with non-existing cluster' do
  110. let(:cluster_id) { 123 }
  111. it 'returns 404' do
  112. expect(response).to have_gitlab_http_status(404)
  113. end
  114. end
  115. end
  116. end
  117. describe 'POST /projects/:id/clusters/user' do
  118. let(:api_url) { 'https://kubernetes.example.com' }
  119. let(:namespace) { project.path }
  120. let(:authorization_type) { 'rbac' }
  121. let(:platform_kubernetes_attributes) do
  122. {
  123. api_url: api_url,
  124. token: 'sample-token',
  125. namespace: namespace,
  126. authorization_type: authorization_type
  127. }
  128. end
  129. let(:cluster_params) do
  130. {
  131. name: 'test-cluster',
  132. domain: 'domain.example.com',
  133. managed: false,
  134. platform_kubernetes_attributes: platform_kubernetes_attributes
  135. }
  136. end
  137. context 'non-authorized user' do
  138. it 'responds with 403' do
  139. post api("/projects/#{project.id}/clusters/user", developer_user), params: cluster_params
  140. expect(response).to have_gitlab_http_status(403)
  141. end
  142. end
  143. context 'authorized user' do
  144. before do
  145. post api("/projects/#{project.id}/clusters/user", current_user), params: cluster_params
  146. end
  147. context 'with valid params' do
  148. it 'responds with 201' do
  149. expect(response).to have_gitlab_http_status(201)
  150. end
  151. it 'creates a new Cluster::Cluster' do
  152. cluster_result = Clusters::Cluster.find(json_response["id"])
  153. platform_kubernetes = cluster_result.platform
  154. expect(cluster_result).to be_user
  155. expect(cluster_result).to be_kubernetes
  156. expect(cluster_result.project).to eq(project)
  157. expect(cluster_result.name).to eq('test-cluster')
  158. expect(cluster_result.domain).to eq('domain.example.com')
  159. expect(cluster_result.managed).to be_falsy
  160. expect(platform_kubernetes.rbac?).to be_truthy
  161. expect(platform_kubernetes.api_url).to eq(api_url)
  162. expect(platform_kubernetes.namespace).to eq(namespace)
  163. expect(platform_kubernetes.token).to eq('sample-token')
  164. end
  165. end
  166. context 'when user does not indicate authorization type' do
  167. let(:platform_kubernetes_attributes) do
  168. {
  169. api_url: api_url,
  170. token: 'sample-token',
  171. namespace: namespace
  172. }
  173. end
  174. it 'defaults to RBAC' do
  175. cluster_result = Clusters::Cluster.find(json_response['id'])
  176. expect(cluster_result.platform_kubernetes.rbac?).to be_truthy
  177. end
  178. end
  179. context 'when user sets authorization type as ABAC' do
  180. let(:authorization_type) { 'abac' }
  181. it 'creates an ABAC cluster' do
  182. cluster_result = Clusters::Cluster.find(json_response['id'])
  183. expect(cluster_result.platform.abac?).to be_truthy
  184. end
  185. end
  186. context 'with invalid params' do
  187. let(:namespace) { 'invalid_namespace' }
  188. it 'responds with 400' do
  189. expect(response).to have_gitlab_http_status(400)
  190. end
  191. it 'does not create a new Clusters::Cluster' do
  192. expect(project.reload.clusters).to be_empty
  193. end
  194. it 'returns validation errors' do
  195. expect(json_response['message']['platform_kubernetes.namespace'].first).to be_present
  196. end
  197. end
  198. end
  199. context 'when user tries to add multiple clusters' do
  200. before do
  201. create(:cluster, :provided_by_gcp, :project,
  202. projects: [project])
  203. post api("/projects/#{project.id}/clusters/user", current_user), params: cluster_params
  204. end
  205. it 'responds with 403' do
  206. expect(response).to have_gitlab_http_status(403)
  207. end
  208. it 'returns an appropriate message' do
  209. expect(json_response['message']).to include('Instance does not support multiple Kubernetes clusters')
  210. end
  211. end
  212. end
  213. describe 'PUT /projects/:id/clusters/:cluster_id' do
  214. let(:api_url) { 'https://kubernetes.example.com' }
  215. let(:namespace) { 'new-namespace' }
  216. let(:platform_kubernetes_attributes) { { namespace: namespace } }
  217. let(:update_params) do
  218. {
  219. domain: 'new-domain.com',
  220. platform_kubernetes_attributes: platform_kubernetes_attributes
  221. }
  222. end
  223. let!(:kubernetes_namespace) do
  224. create(:cluster_kubernetes_namespace,
  225. cluster: cluster,
  226. project: project)
  227. end
  228. let(:cluster) do
  229. create(:cluster, :project, :provided_by_gcp,
  230. projects: [project])
  231. end
  232. context 'non-authorized user' do
  233. it 'responds with 403' do
  234. put api("/projects/#{project.id}/clusters/#{cluster.id}", developer_user), params: update_params
  235. expect(response).to have_gitlab_http_status(403)
  236. end
  237. end
  238. context 'authorized user' do
  239. before do
  240. put api("/projects/#{project.id}/clusters/#{cluster.id}", current_user), params: update_params
  241. cluster.reload
  242. end
  243. context 'with valid params' do
  244. it 'responds with 200' do
  245. expect(response).to have_gitlab_http_status(200)
  246. end
  247. it 'updates cluster attributes' do
  248. expect(cluster.domain).to eq('new-domain.com')
  249. expect(cluster.platform_kubernetes.namespace).to eq('new-namespace')
  250. end
  251. end
  252. context 'with invalid params' do
  253. let(:namespace) { 'invalid_namespace' }
  254. it 'responds with 400' do
  255. expect(response).to have_gitlab_http_status(400)
  256. end
  257. it 'does not update cluster attributes' do
  258. expect(cluster.domain).not_to eq('new_domain.com')
  259. expect(cluster.platform_kubernetes.namespace).not_to eq('invalid_namespace')
  260. expect(cluster.kubernetes_namespace_for(project)).not_to eq('invalid_namespace')
  261. end
  262. it 'returns validation errors' do
  263. expect(json_response['message']['platform_kubernetes.namespace'].first).to match('can contain only lowercase letters')
  264. end
  265. end
  266. context 'with a GCP cluster' do
  267. context 'when user tries to change GCP specific fields' do
  268. let(:platform_kubernetes_attributes) do
  269. {
  270. api_url: 'https://new-api-url.com',
  271. token: 'new-sample-token'
  272. }
  273. end
  274. it 'responds with 400' do
  275. expect(response).to have_gitlab_http_status(400)
  276. end
  277. it 'returns validation error' do
  278. expect(json_response['message']['platform_kubernetes.base'].first).to eq('Cannot modify managed Kubernetes cluster')
  279. end
  280. end
  281. context 'when user tries to change namespace' do
  282. let(:namespace) { 'new-namespace' }
  283. it 'responds with 200' do
  284. expect(response).to have_gitlab_http_status(200)
  285. end
  286. end
  287. end
  288. context 'with an user cluster' do
  289. let(:api_url) { 'https://new-api-url.com' }
  290. let(:cluster) do
  291. create(:cluster, :project, :provided_by_user,
  292. projects: [project])
  293. end
  294. let(:platform_kubernetes_attributes) do
  295. {
  296. api_url: api_url,
  297. namespace: 'new-namespace',
  298. token: 'new-sample-token'
  299. }
  300. end
  301. let(:update_params) do
  302. {
  303. name: 'new-name',
  304. platform_kubernetes_attributes: platform_kubernetes_attributes
  305. }
  306. end
  307. it 'responds with 200' do
  308. expect(response).to have_gitlab_http_status(200)
  309. end
  310. it 'updates platform kubernetes attributes' do
  311. platform_kubernetes = cluster.platform_kubernetes
  312. expect(cluster.name).to eq('new-name')
  313. expect(platform_kubernetes.namespace).to eq('new-namespace')
  314. expect(platform_kubernetes.api_url).to eq('https://new-api-url.com')
  315. expect(platform_kubernetes.token).to eq('new-sample-token')
  316. end
  317. end
  318. context 'with a cluster that does not belong to user' do
  319. let(:cluster) { create(:cluster, :project, :provided_by_user) }
  320. it 'responds with 404' do
  321. expect(response).to have_gitlab_http_status(404)
  322. end
  323. end
  324. end
  325. end
  326. describe 'DELETE /projects/:id/clusters/:cluster_id' do
  327. let(:cluster_params) { { cluster_id: cluster.id } }
  328. let(:cluster) do
  329. create(:cluster, :project, :provided_by_gcp,
  330. projects: [project])
  331. end
  332. context 'non-authorized user' do
  333. it 'responds with 403' do
  334. delete api("/projects/#{project.id}/clusters/#{cluster.id}", developer_user), params: cluster_params
  335. expect(response).to have_gitlab_http_status(403)
  336. end
  337. end
  338. context 'authorized user' do
  339. before do
  340. delete api("/projects/#{project.id}/clusters/#{cluster.id}", current_user), params: cluster_params
  341. end
  342. it 'responds with 204' do
  343. expect(response).to have_gitlab_http_status(204)
  344. end
  345. it 'deletes the cluster' do
  346. expect(Clusters::Cluster.exists?(id: cluster.id)).to be_falsy
  347. end
  348. context 'with a cluster that does not belong to user' do
  349. let(:cluster) { create(:cluster, :project, :provided_by_user) }
  350. it 'responds with 404' do
  351. expect(response).to have_gitlab_http_status(404)
  352. end
  353. end
  354. end
  355. end
  356. end