Commit 1b72256f authored by Z.J. van de Weg's avatar Z.J. van de Weg

Use Grape DSL for environment endpoints

Also a couple of minor edits for this branch are included
parent 76e9b684
...@@ -741,7 +741,7 @@ Rails.application.routes.draw do ...@@ -741,7 +741,7 @@ Rails.application.routes.draw do
end end
end end
resources :environments, constraints: { id: /\d+/ } resources :environments
resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do
collection do collection do
......
...@@ -32,7 +32,7 @@ Example response: ...@@ -32,7 +32,7 @@ Example response:
Creates a new environment with the given name and external_url. Creates a new environment with the given name and external_url.
It returns 200 if the environment was successfully created, 400 for wrong parameters. It returns 201 if the environment was successfully created, 400 for wrong parameters.
``` ```
POST /projects/:id/environment POST /projects/:id/environment
...@@ -58,21 +58,25 @@ Example response: ...@@ -58,21 +58,25 @@ Example response:
} }
``` ```
## Delete an environment ## Edit an existing environment
It returns 200 if the environment was successfully deleted, and 404 if the environment does not exist. Updates an existing environment's name and/or external_url.
It returns 200 if the environment was successfully updated. In case of an error, a status code 400 is returned.
``` ```
DELETE /projects/:id/environments/:environment_id PUT /projects/:id/environments/:environments_id
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- | | --------------- | ------- | --------------------------------- | ------------------------------- |
| `id` | integer | yes | The ID of the project | | `id` | integer | yes | The ID of the project |
| `environment_id` | integer | yes | The ID of the environment | | `environment_id` | integer | yes | The ID of the environment | The ID of the environment |
| `name` | string | no | The new name of the environment |
| `external_url` | string | no | The new external_url |
```bash ```bash
curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/environment/1" curl -X PUT --data "name=staging&external_url=https://staging.example.gitlab.com" -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/environment/1"
``` ```
Example response: Example response:
...@@ -80,30 +84,26 @@ Example response: ...@@ -80,30 +84,26 @@ Example response:
```json ```json
{ {
"id": 1, "id": 1,
"name": "deploy", "name": "staging",
"external_url": "https://deploy.example.gitlab.com" "external_url": "https://staging.example.gitlab.com"
} }
``` ```
## Edit an existing environment ## Delete an environment
Updates an existing environment's name and/or external_url.
It returns 200 if the label was successfully updated, In case of an error, an additional error message is returned. It returns 200 if the environment was successfully deleted, and 404 if the environment does not exist.
``` ```
PUT /projects/:id/environments/:environments_id DELETE /projects/:id/environments/:environment_id
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
| --------------- | ------- | --------------------------------- | ------------------------------- | | --------- | ------- | -------- | --------------------- |
| `id` | integer | yes | The ID of the project | | `id` | integer | yes | The ID of the project |
| `environment_id` | integer | yes | The ID of the environment | The ID of the environment | | `environment_id` | integer | yes | The ID of the environment |
| `name` | string | no | The new name of the environment |
| `external_url` | string | no | The new external_url |
```bash ```bash
curl -X PUT --data "name=staging&external_url=https://staging.example.gitlab.com" -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/environment/1" curl -X DELETE -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v3/projects/1/environment/1"
``` ```
Example response: Example response:
...@@ -111,7 +111,7 @@ Example response: ...@@ -111,7 +111,7 @@ Example response:
```json ```json
{ {
"id": 1, "id": 1,
"name": "staging", "name": "deploy",
"external_url": "https://staging.example.gitlab.com" "external_url": "https://deploy.example.gitlab.com"
} }
``` ```
...@@ -7,6 +7,10 @@ module API ...@@ -7,6 +7,10 @@ module API
rack_response({ 'message' => '404 Not found' }.to_json, 404) rack_response({ 'message' => '404 Not found' }.to_json, 404)
end end
rescue_from Grape::Exceptions::ValidationErrors do |e|
error!({ messages: e.full_messages }, 400)
end
rescue_from :all do |exception| rescue_from :all do |exception|
# lifted from https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb#L60 # lifted from https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb#L60
# why is this not wrapped in something reusable? # why is this not wrapped in something reusable?
......
...@@ -3,82 +3,77 @@ module API ...@@ -3,82 +3,77 @@ module API
class Environments < Grape::API class Environments < Grape::API
before { authenticate! } before { authenticate! }
params do
requires :id, type: String, desc: 'The project ID'
end
resource :projects do resource :projects do
# Get all labels of the project desc 'Get all environments of the project' do
# detail 'This feature was introduced in GitLab 8.11.'
# Parameters: success Entities::Environment
# id (required) - The ID of a project end
# Example Request:
# GET /projects/:id/environments
get ':id/environments' do get ':id/environments' do
authorize! :read_environment, user_project authorize! :read_environment, user_project
present paginate(user_project.environments), with: Entities::Environment present paginate(user_project.environments), with: Entities::Environment
end end
# Creates a new environment desc 'Creates a new environment' do
# detail 'This feature was introduced in GitLab 8.11.'
# Parameters: success Entities::Environment
# id (required) - The ID of a project end
# name (required) - The name of the environment to be created params do
# external_url (optional) - URL on which this deployment is viewable requires :name, type: String, desc: 'The name of the environment to be created'
# optional :external_url, type: String, desc: 'URL on which this deployment is viewable'
# Example Request: end
# POST /projects/:id/labels
post ':id/environments' do post ':id/environments' do
authorize! :create_environment, user_project authorize! :create_environment, user_project
required_attributes! [:name]
attrs = attributes_for_keys [:name, :external_url]
environment = user_project.environments.create(attrs) create_params = declared(params, include_parent_namespaces: false).to_h
environment = user_project.environments.create(create_params)
if environment.valid? if environment.persisted?
present environment, with: Entities::Environment present environment, with: Entities::Environment
else else
render_validation_error!(environment) render_validation_error!(environment)
end end
end end
# Deletes an existing environment desc 'Updates an existing environment' do
# detail 'This feature was introduced in GitLab 8.11.'
# Parameters: success Entities::Environment
# id (required) - The ID of a project end
# environment_id (required) - The name of the environment to be deleted params do
# requires :environment_id, type: Integer, desc: 'The environment ID'
# Example Request: optional :name, type: String, desc: 'The new environment name'
# DELETE /projects/:id/environments/:environment_id optional :external_url, type: String, desc: 'The new URL on which this deployment is viewable'
delete ':id/environments/:environment_id' do
authorize! :update_environment, user_project
environment = user_project.environments.find(params[:environment_id])
present environment.destroy, with: Entities::Environment
end end
# Updates an existing environment
#
# Parameters:
# id (required) - The ID of a project
# environment_id (required) - The ID of the environment
# name (optional) - The name of the label to be deleted
# external_url (optional) - The new name of the label
#
# Example Request:
# PUT /projects/:id/environments/:environment_id
put ':id/environments/:environment_id' do put ':id/environments/:environment_id' do
authorize! :update_environment, user_project authorize! :update_environment, user_project
environment = user_project.environments.find(params[:environment_id]) environment = user_project.environments.find(params[:environment_id])
attrs = attributes_for_keys [:name, :external_url] update_params = declared(params, include_missing: false).extract!(:name, :external_url).to_h
if environment.update(update_params)
if environment.update(attrs)
present environment, with: Entities::Environment present environment, with: Entities::Environment
else else
render_validation_error!(environment) render_validation_error!(environment)
end end
end end
desc 'Deletes an existing environment' do
detail 'This feature was introduced in GitLab 8.11.'
success Entities::Environment
end
params do
requires :environment_id, type: Integer, desc: 'The environment ID'
end
delete ':id/environments/:environment_id' do
authorize! :update_environment, user_project
environment = user_project.environments.find(params[:environment_id])
present environment.destroy, with: Entities::Environment
end
end end
end end
end end
...@@ -27,6 +27,7 @@ describe Environment, models: true do ...@@ -27,6 +27,7 @@ describe Environment, models: true do
env = build(:environment, external_url: "") env = build(:environment, external_url: "")
expect(env.save).to be true expect(env.save).to be true
expect(env.external_url).to be_nil
end end
end end
end end
...@@ -14,7 +14,7 @@ describe API::API, api: true do ...@@ -14,7 +14,7 @@ describe API::API, api: true do
describe 'GET /projects/:id/environments' do describe 'GET /projects/:id/environments' do
context 'as member of the project' do context 'as member of the project' do
it 'should return project environments' do it 'returns project environments' do
get api("/projects/#{project.id}/environments", user) get api("/projects/#{project.id}/environments", user)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
...@@ -26,7 +26,7 @@ describe API::API, api: true do ...@@ -26,7 +26,7 @@ describe API::API, api: true do
end end
context 'as non member' do context 'as non member' do
it 'should return a 404 status code' do it 'returns a 404 status code' do
get api("/projects/#{project.id}/environments", non_member) get api("/projects/#{project.id}/environments", non_member)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
...@@ -50,7 +50,7 @@ describe API::API, api: true do ...@@ -50,7 +50,7 @@ describe API::API, api: true do
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
end end
it 'should return 400 if environment already exists' do it 'returns a 400 if environment already exists' do
post api("/projects/#{project.id}/environments", user), name: environment.name post api("/projects/#{project.id}/environments", user), name: environment.name
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
...@@ -61,42 +61,53 @@ describe API::API, api: true do ...@@ -61,42 +61,53 @@ describe API::API, api: true do
it 'rejects the request' do it 'rejects the request' do
post api("/projects/#{project.id}/environments", non_member) post api("/projects/#{project.id}/environments", non_member)
expect(response).to have_http_status(404) expect(response).to have_http_status(400)
end end
end end
end end
describe 'DELETE /projects/:id/environments/:environment_id' do describe 'PUT /projects/:id/environments/:environment_id' do
context 'as a master' do it 'returns a 200 if name and external_url are changed' do
it 'should return 200 for an existing environment' do url = 'https://mepmep.whatever.ninja'
delete api("/projects/#{project.id}/environments/#{environment.id}", user) put api("/projects/#{project.id}/environments/#{environment.id}", user),
name: 'Mepmep', external_url: url
expect(response).to have_http_status(200)
end
it 'should return 404 for non existing id' do
delete api("/projects/#{project.id}/environments/12345", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(200)
expect(json_response['message']).to eq('404 Not found') expect(json_response['name']).to eq('Mepmep')
end expect(json_response['external_url']).to eq(url)
end end
end
describe 'PUT /projects/:id/environments/:environment_id' do it "won't update the external_url if only the name is passed" do
it 'should return 200 if name and external_url are changed' do url = environment.external_url
put api("/projects/#{project.id}/environments/#{environment.id}", user), put api("/projects/#{project.id}/environments/#{environment.id}", user),
name: 'Mepmep', external_url: 'https://mepmep.whatever.ninja' name: 'Mepmep'
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response['name']).to eq('Mepmep') expect(json_response['name']).to eq('Mepmep')
expect(json_response['external_url']).to eq('https://mepmep.whatever.ninja') expect(json_response['external_url']).to eq(url)
end end
it 'should return 404 if the environment does not exist' do it 'returns a 404 if the environment does not exist' do
put api("/projects/#{project.id}/environments/12345", user) put api("/projects/#{project.id}/environments/12345", user)
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
end end
describe 'DELETE /projects/:id/environments/:environment_id' do
context 'as a master' do
it 'returns a 200 for an existing environment' do
delete api("/projects/#{project.id}/environments/#{environment.id}", user)
expect(response).to have_http_status(200)
end
it 'returns a 404 for non existing id' do
delete api("/projects/#{project.id}/environments/12345", user)
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Not found')
end
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment