Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove resources from service #14581

Merged
merged 1 commit into from
Apr 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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