diff --git a/app/controllers/remote_deployments_controller.rb b/app/controllers/remote_deployments_controller.rb index dc47815..3d2e9f6 100644 --- a/app/controllers/remote_deployments_controller.rb +++ b/app/controllers/remote_deployments_controller.rb @@ -22,6 +22,10 @@ def destroy respond_with deployment_service.destroy(params[:id]) end + def redeploy + respond_with deployment_service.redeploy(params[:id]), location: nil, status: 201 + end + private def deployment_service diff --git a/app/models/remote_deployment.rb b/app/models/remote_deployment.rb index 8f6a67a..4742526 100644 --- a/app/models/remote_deployment.rb +++ b/app/models/remote_deployment.rb @@ -1,5 +1,5 @@ class RemoteDeployment < ApiModel - attr_accessor :id, :name, :template, :service_ids, :status + attr_accessor :id, :name, :template, :service_ids, :status, :redeployable end diff --git a/app/services/deployment_service.rb b/app/services/deployment_service.rb index 4d597ba..2526c6b 100644 --- a/app/services/deployment_service.rb +++ b/app/services/deployment_service.rb @@ -5,8 +5,10 @@ def all connection.get '/deployments' end - response.body.map do |deployment_params| - RemoteDeployment.new(deployment_params) + handle_agent_response(response) do + response.body.map do |deployment_params| + RemoteDeployment.new(deployment_params) + end end end @@ -15,8 +17,7 @@ def find(deployment_id) connection.get "/deployments/#{deployment_id}" end - raise 'deployment not found' if response.status == 404 - RemoteDeployment.new(response.body) + handle_agent_response(response) { RemoteDeployment.new(response.body) } end def create(template:, override:) @@ -27,12 +28,35 @@ def create(template:, override:) }.to_json end - RemoteDeployment.new(response.body) + handle_agent_response(response) { RemoteDeployment.new(response.body) } end def destroy(deployment_id) - with_ssl_connection do |connection| + response = with_ssl_connection do |connection| connection.delete "/deployments/#{deployment_id}" end + + handle_agent_response(response) + end + + def redeploy(deployment_id) + response = with_ssl_connection do |connection| + connection.post "/deployments/#{deployment_id}/redeploy" + end + + handle_agent_response(response) { RemoteDeployment.new(response.body) } + end + + private + + def handle_agent_response(response) + case response.status + when 200..299 + yield if block_given? + when 404 + raise 'deployment not found' + else + raise response.body['message'] + end end end diff --git a/config/routes.rb b/config/routes.rb index 28977d4..95b16e9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,7 +27,11 @@ resources :deployment_targets do resources :deployments, controller: :remote_deployments, - only: [:index, :show, :create, :destroy] + only: [:index, :show, :create, :destroy] do + member do + post :redeploy + end + end post '/metadata/refresh', to: "remote_metadata_refreshes#create" end diff --git a/spec/controllers/remote_deployments_controller_spec.rb b/spec/controllers/remote_deployments_controller_spec.rb index 66e4b24..eec1dcb 100644 --- a/spec/controllers/remote_deployments_controller_spec.rb +++ b/spec/controllers/remote_deployments_controller_spec.rb @@ -172,4 +172,47 @@ expect(response.status).to eq 204 end end + + describe 'POST #redeploy' do + + before do + allow(deployment_service).to receive(:redeploy) + end + + context 'when the resource exists' do + + before do + allow(deployment_service).to receive(:redeploy).with('22').and_return(deployment) + end + + it 'returns a new deployment' do + get :redeploy, deployment_target_id: 44, id: 22, format: :json + expect(response.body).to eq deployment.to_json + end + + it 'returns a HTTP 201 status code' do + get :redeploy, deployment_target_id: 44, id: 22, format: :json + expect(response.status).to eq 201 + end + end + + context 'when the resource does not exist' do + let(:error_message) { 'deployment not found' } + + before do + allow(deployment_service).to receive(:redeploy).with('13').and_raise(error_message) + end + + it 'returns the requested deployment' do + get :redeploy, deployment_target_id: 44, id: 13, format: :json + expect(response.body).to eq "{\"message\":\"#{error_message}\"}" + end + + it 'returns a HTTP 500 status code' do + get :redeploy, deployment_target_id: 44, id: 13, format: :json + expect(response.status).to eq 500 + end + end + end + end diff --git a/spec/models/remote_deployment.rb b/spec/models/remote_deployment_spec.rb similarity index 85% rename from spec/models/remote_deployment.rb rename to spec/models/remote_deployment_spec.rb index 3c4543a..25bf9b7 100644 --- a/spec/models/remote_deployment.rb +++ b/spec/models/remote_deployment_spec.rb @@ -15,6 +15,8 @@ it { should respond_to :service_ids= } it { should respond_to :status } it { should respond_to :status= } + it { should respond_to :redeployable } + it { should respond_to :redeployable= } end end diff --git a/spec/services/deployment_service_spec.rb b/spec/services/deployment_service_spec.rb index 1c6bce3..644a007 100644 --- a/spec/services/deployment_service_spec.rb +++ b/spec/services/deployment_service_spec.rb @@ -36,6 +36,17 @@ expect(result.first).to be_kind_of(RemoteDeployment) expect(result.first.id).to eq deployment_id end + + context 'when an error occurs downstream' do + before do + stub_request(:get, "#{base_path}/deployments") + .to_return(body: { message: 'boom' }.to_json, status: 500) + end + + it 'returns an error' do + expect { subject.all }.to raise_error('boom') + end + end end describe '#find' do @@ -69,6 +80,17 @@ expect{ subject.find(deployment_id) }.to raise_error('deployment not found') end end + + context 'when an error occurs downstream' do + before do + stub_request(:get, "#{base_path}/deployments/#{deployment_id}") + .to_return(body: { message: 'boom' }.to_json, status: 500) + end + + it 'returns an error' do + expect { subject.find(deployment_id) }.to raise_error('boom') + end + end end describe '#create' do @@ -80,7 +102,13 @@ before do stub_request(:post, "#{base_path}/deployments") - .with(body: { template: TemplateFileSerializer.new(template), override: TemplateFileSerializer.new(override) }.to_json) + .with( + body: + { + template: TemplateFileSerializer.new(template), + override: TemplateFileSerializer.new(override) + }.to_json + ) .to_return(body: response, status: 201) end @@ -89,6 +117,24 @@ expect(result).to be_kind_of(RemoteDeployment) expect(result.id).to eq deployment_id end + + context 'when the deployment cannot be created' do + before do + stub_request(:post, "#{base_path}/deployments") + .with( + body: + { + template: TemplateFileSerializer.new(template), + override: TemplateFileSerializer.new(override) + }.to_json + ) + .to_return(body: { message: 'boom' }.to_json, status: 422) + end + + it 'returns an error' do + expect { subject.create(template: template, override: override) }.to raise_error('boom') + end + end end describe '#destroy' do @@ -102,5 +148,59 @@ it 'deletes the remote deployment' do subject.destroy(deployment_id) end + + context 'when an error occurs downstream' do + before do + stub_request(:delete, "#{base_path}/deployments/#{deployment_id}") + .to_return(body: { message: 'boom' }.to_json, status: 500) + end + + it 'returns an error' do + expect { subject.destroy(deployment_id) }.to raise_error('boom') + end + end + end + + describe '#redeploy' do + let(:deployment_id) { 123 } + + context 'when the deployment is found' do + let(:response) { { id: deployment_id + 1 }.to_json } + + before do + stub_request(:post, "#{base_path}/deployments/#{deployment_id}/redeploy") + .to_return(body: response, status: 201) + end + + it 'creates the remote deployment' do + result = subject.redeploy(deployment_id) + expect(result).to be_kind_of(RemoteDeployment) + end + end + + context 'when the deployment cannot be found' do + before do + stub_request(:post, "#{base_path}/deployments/#{deployment_id}/redeploy") + .to_return(status: 404) + end + + it 'returns nil' do + expect { subject.redeploy(deployment_id) }.to raise_error('deployment not found') + end + end + + context 'when the deployment is not redeployable' do + let(:response) { { message: 'deployment cannot be redeployed' }.to_json } + + before do + stub_request(:post, "#{base_path}/deployments/#{deployment_id}/redeploy") + .to_return(body: response, status: 500) + end + + it 'returns an error' do + expect { subject.redeploy(deployment_id) }.to raise_error('deployment cannot be redeployed') + end + + end end end