Skip to content

Commit

Permalink
remove resources from service https://www.pivotaltracker.com/story/sh…
Browse files Browse the repository at this point in the history
  • Loading branch information
Jillian Tullo committed Mar 31, 2017
1 parent 2846cb3 commit 3f4a286
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 10 deletions.
33 changes: 25 additions & 8 deletions app/controllers/api/services_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,23 @@ def add_resource_resource(type, id, data)
raise "Must specify a service href or id to add_resource to" unless id
svc = resource_search(id, type, collection_class(type))

resource_href = data.fetch_path("resource", "href")
raise "Must specify a resource reference" unless resource_href

resource_type, resource_id = parse_href(resource_href)
raise "Invalid resource href specified #{resource_href}" unless resource_type && resource_id

resource = resource_search(resource_id, resource_type, collection_class(resource_type))
resource_type, resource = validate_resource(data)
raise "Cannot assign #{resource_type} to #{service_ident(svc)}" unless resource.respond_to? :add_to_service

resource.add_to_service(svc)
action_result(true, "Assigned resource #{resource_type} id:#{resource_id} to #{service_ident(svc)}")
action_result(true, "Assigned resource #{resource_type} id:#{resource.id} to #{service_ident(svc)}")
rescue => err
action_result(false, err.to_s)
end

def remove_resource_resource(type, id, data)
raise 'Must specify a resource to remove_resource from' unless id
svc = resource_search(id, type, collection_class(type))

resource_type, resource = validate_resource(data)

svc.remove_resource(resource)
action_result(true, "Unassigned resource #{resource_type} id:#{resource.id} from #{service_ident(svc)}")
rescue => err
action_result(false, err.to_s)
end
Expand Down Expand Up @@ -103,6 +109,17 @@ def suspend_resource(type, id = nil, _data = nil)

private

def validate_resource(data)
resource_href = data.fetch_path("resource", "href")
raise "Must specify a resource reference" unless resource_href

resource_type, resource_id = parse_href(resource_href)
raise "Invalid resource href specified #{resource_href}" unless resource_type && resource_id

resource = resource_search(resource_id, resource_type, collection_class(resource_type))
[resource_type, resource]
end

def build_service_attributes(data)
attributes = data.dup
attributes['job_template'] = fetch_configuration_script(data['job_template']) if data['job_template']
Expand Down
4 changes: 4 additions & 0 deletions config/api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1931,6 +1931,8 @@
:identifier: service_tag
- :name: add_resource
:identifier: service_edit
- :name: remove_resource
:identifier: service_edit
:resource_actions:
:get:
- :name: read
Expand All @@ -1956,6 +1958,8 @@
:identifier: service_delete
- :name: add_resource
:identifier: service_edit
- :name: remove_resource
:identifier: service_edit
:delete:
- :name: delete
:identifier: service_delete
Expand Down
4 changes: 2 additions & 2 deletions spec/requests/api/custom_actions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def expect_result_to_have_custom_actions_hash
run_get services_url(svc1.id)

expect_result_to_have_keys(%w(id href actions))
expect(response.parsed_body["actions"].collect { |a| a["name"] }).to match_array(%w(edit add_resource))
expect(response.parsed_body["actions"].collect { |a| a["name"] }).to match_array(%w(edit add_resource remove_resource))
end
end

Expand All @@ -91,7 +91,7 @@ def expect_result_to_have_custom_actions_hash
run_get services_url(svc1.id)

expect_result_to_have_keys(%w(id href actions))
expect(response.parsed_body["actions"].collect { |a| a["name"] }).to match_array(%w(edit button1 button2 button3 add_resource))
expect(response.parsed_body["actions"].collect { |a| a["name"] }).to match_array(%w(edit button1 button2 button3 add_resource remove_resource))
end

it "supports the custom_actions attribute" do
Expand Down
108 changes: 108 additions & 0 deletions spec/requests/api/services_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -820,4 +820,112 @@ def expect_svc_with_vms
expect(response).to have_http_status(:forbidden)
end
end

describe 'remove_resource' do
let(:vm1) { FactoryGirl.create(:vm_vmware) }
let(:vm2) { FactoryGirl.create(:vm_vmware) }

before do
svc.add_resource(vm1)
svc1.add_resource(vm2)
end

it 'cannot remove vms from services without an appropriate role' do
api_basic_authorize

run_post(services_url, 'action' => 'remove_resource')

expect(response).to have_http_status(:forbidden)
end

it 'can remove vms from multiple services by href with an appropriate role' do
api_basic_authorize collection_action_identifier(:services, :remove_resource)
request = {
'action' => 'remove_resource',
'resources' => [
{ 'href' => services_url(svc.id), 'resource' => { 'href' => vms_url(vm1.id)} },
{ 'href' => services_url(svc1.id), 'resource' => { 'href' => vms_url(vm2.id)} }
]
}

run_post(services_url, request)

expected = {
'results' => [
{ 'success' => true, 'message' => "Unassigned resource vms id:#{vm1.id} from Service id:#{svc.id} name:'#{svc.name}'" },
{ 'success' => true, 'message' => "Unassigned resource vms id:#{vm2.id} from Service id:#{svc1.id} name:'#{svc1.name}'" }
]
}
expect(response).to have_http_status(:ok)
expect(response.parsed_body).to eq(expected)
expect(svc.reload.service_resources).to eq([])
expect(svc1.reload.service_resources).to eq([])
end

it 'requires a service id to be specified' do
api_basic_authorize collection_action_identifier(:services, :remove_resource)
request = {
'action' => 'remove_resource',
'resources' => [
{ 'href' => services_url, 'resource' => { 'href' => vms_url(vm1.id)} }
]
}

run_post(services_url, request)

expected = {
'results' => [
{ 'success' => false, 'message' => 'Must specify a resource to remove_resource from' }
]
}
expect(response).to have_http_status(:ok)
expect(response.parsed_body).to eq(expected)
end

it 'requires that a resource be specified' do
api_basic_authorize collection_action_identifier(:services, :remove_resource)
request = {
'action' => 'remove_resource',
'resources' => [
{ 'href' => services_url(svc.id), 'resource' => {} }
]
}

run_post(services_url, request)

expected = {
'results' => [
{ 'success' => false, 'message' => 'Must specify a resource reference' }
]
}
expect(response).to have_http_status(:ok)
expect(response.parsed_body).to eq(expected)
end

it 'cannot remove a vm from a service without an appropriate role' do
api_basic_authorize

run_post(services_url(svc.id), 'action' => 'remove_resource')

expect(response).to have_http_status(:forbidden)
end

it 'can remove a vm from a service by href with an appropriate role' do
api_basic_authorize collection_action_identifier(:services, :remove_resource)
request = {
'action' => 'remove_resource',
'resource' => { 'resource' => {'href' => vms_url(vm1.id)} }
}

run_post(services_url(svc.id), request)

expected = {
'success' => true,
'message' => "Unassigned resource vms id:#{vm1.id} from Service id:#{svc.id} name:'#{svc.name}'"
}
expect(response).to have_http_status(:ok)
expect(response.parsed_body).to eq(expected)
expect(svc.reload.service_resources).to eq([])
end
end
end

0 comments on commit 3f4a286

Please sign in to comment.