Skip to content

Commit

Permalink
Merge pull request #472 from bdunne/central_admin
Browse files Browse the repository at this point in the history
Add basic CentralAdmin support to the API

(cherry picked from commit 4dbf6b0)

https://bugzilla.redhat.com/show_bug.cgi?id=1628658
  • Loading branch information
gtanzillo authored and simaishi committed Oct 8, 2018
1 parent a22161e commit 60cb7c9
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 2 deletions.
6 changes: 6 additions & 0 deletions app/controllers/api/instances_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class InstancesController < BaseController
include Subcollections::LoadBalancers
include Subcollections::SecurityGroups
include Subcollections::Snapshots
extend Api::Mixins::CentralAdmin

DEFAULT_ROLE = 'ems_operations'.freeze

Expand All @@ -29,6 +30,7 @@ def stop_resource(type, id = nil, _data = nil)
result
end
end
central_admin :stop_resource, :stop

def start_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for starting a #{type} resource" unless id
Expand All @@ -42,6 +44,7 @@ def start_resource(type, id = nil, _data = nil)
result
end
end
central_admin :start_resource, :start

def pause_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for pausing a #{type} resource" unless id
Expand All @@ -68,6 +71,7 @@ def suspend_resource(type, id = nil, _data = nil)
result
end
end
central_admin :suspend_resource, :suspend

def shelve_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for shelving a #{type} resource" unless id
Expand All @@ -94,6 +98,7 @@ def reboot_guest_resource(type, id = nil, _data = nil)
result
end
end
central_admin :reboot_guest_resource, :reboot_guest

def reset_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for resetting a #{type} resource" unless id
Expand All @@ -107,6 +112,7 @@ def reset_resource(type, id = nil, _data = nil)
result
end
end
central_admin :reset_resource, :reset

private

Expand Down
38 changes: 38 additions & 0 deletions app/controllers/api/mixins/central_admin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module Api
module Mixins
module CentralAdmin
def self.extended(klass)
unless klass.const_defined?("MethodRelay")
method_relay = klass.const_set("MethodRelay", Module.new)
klass.prepend(method_relay)
end
end

def central_admin(method, action = method)
const_get("MethodRelay").class_eval do
define_method(method) do |*meth_args, &meth_block|
api_args = yield(*meth_args) if block_given?

type, id, _rest = meth_args

if ApplicationRecord.id_in_current_region?(id.to_i)
super(*meth_args, &meth_block)
else
region_number = ApplicationRecord.id_to_region(id)
Api::Mixins::CentralAdmin.inter_region_call(region_number, @req.subject.to_sym, action, api_args, id).tap do |response|
add_href_to_result(response, type, id)
add_task_to_result(response, response["task_href"].split("api/tasks/").last) if response["task_href"]
end
end
end
end
end

def self.inter_region_call(region, collection, action, api_args, id)
InterRegionApiMethodRelay.exec_api_call(region, collection, action, api_args, id)
rescue InterRegionApiMethodRelay::InterRegionApiMethodRelayError => error
{"success" => false, "message" => error.message}
end
end
end
end
7 changes: 7 additions & 0 deletions app/controllers/api/vms_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class VmsController < BaseController
include Subcollections::Software
include Subcollections::Snapshots
include Subcollections::MetricRollups
extend Api::Mixins::CentralAdmin

VALID_EDIT_ATTRS = %w(description child_resources parent_resource).freeze
RELATIONSHIP_COLLECTIONS = %w(vms templates).freeze
Expand All @@ -26,6 +27,7 @@ def start_resource(type, id = nil, _data = nil)
result
end
end
central_admin :start_resource, :start

def stop_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for stopping a #{type} resource" unless id
Expand All @@ -39,6 +41,7 @@ def stop_resource(type, id = nil, _data = nil)
result
end
end
central_admin :stop_resource, :stop

def suspend_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for suspending a #{type} resource" unless id
Expand All @@ -52,6 +55,7 @@ def suspend_resource(type, id = nil, _data = nil)
result
end
end
central_admin :suspend_resource, :suspend

def pause_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for pausing a #{type} resource" unless id
Expand Down Expand Up @@ -188,6 +192,7 @@ def reset_resource(type, id = nil, _data = nil)
result
end
end
central_admin :reset_resource, :reset

def reboot_guest_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for rebooting a #{type} resource" unless id
Expand All @@ -201,6 +206,7 @@ def reboot_guest_resource(type, id = nil, _data = nil)
result
end
end
central_admin :reboot_guest_resource, :reboot_guest

def shutdown_guest_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for shutting down a #{type} resource" unless id
Expand All @@ -214,6 +220,7 @@ def shutdown_guest_resource(type, id = nil, _data = nil)
result
end
end
central_admin :shutdown_guest_resource, :shutdown_guest

def refresh_resource(type, id = nil, _data = nil)
raise BadRequestError, "Must specify an id for refreshing a #{type} resource" unless id
Expand Down
12 changes: 11 additions & 1 deletion spec/requests/instances_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def update_raw_power_state(state, *instances)
let(:instance_url) { api_instance_url(nil, instance) }
let(:instance1_url) { api_instance_url(nil, instance1) }
let(:instance2_url) { api_instance_url(nil, instance2) }
let(:invalid_instance_url) { api_instance_url(nil, 999_999) }
let(:invalid_instance_url) { api_instance_url(nil, ApplicationRecord.id_in_region(999_999, ApplicationRecord.my_region_number)) }
let(:instances_list) { [instance1_url, instance2_url] }
let(:instance_guid) { instance.guid }

Expand Down Expand Up @@ -843,4 +843,14 @@ def update_raw_power_state(state, *instances)
expect(response.parsed_body).to include(expected)
end
end

describe "/api/instances central admin" do
let(:resource_type) { "instance" }

include_examples "resource power operations", :vm_amazon, :reboot_guest
include_examples "resource power operations", :vm_amazon, :reset
include_examples "resource power operations", :vm_amazon, :start
include_examples "resource power operations", :vm_amazon, :stop
include_examples "resource power operations", :vm_amazon, :suspend
end
end
13 changes: 12 additions & 1 deletion spec/requests/vms_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
let(:vm_guid) { vm.guid }
let(:vm_url) { api_vm_url(nil, vm) }

let(:invalid_vm_url) { api_vm_url(nil, 999_999) }
let(:invalid_vm_url) { api_vm_url(nil, ApplicationRecord.id_in_region(999_999, ApplicationRecord.my_region_number)) }

def update_raw_power_state(state, *vms)
vms.each { |vm| vm.update_attributes!(:raw_power_state => state) }
Expand Down Expand Up @@ -1819,4 +1819,15 @@ def update_raw_power_state(state, *vms)
expect(response).to have_http_status(:forbidden)
end
end

describe "/api/vms central admin" do
let(:resource_type) { "vm" }

include_examples "resource power operations", :vm_vmware, :reboot_guest
include_examples "resource power operations", :vm_vmware, :reset
include_examples "resource power operations", :vm_vmware, :shutdown_guest
include_examples "resource power operations", :vm_vmware, :start
include_examples "resource power operations", :vm_vmware, :stop
include_examples "resource power operations", :vm_vmware, :suspend
end
end
20 changes: 20 additions & 0 deletions spec/support/shared_examples/resource_power_operations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
shared_examples "resource power operations" do |factory, operation|
let!(:resource) { FactoryGirl.create(factory, :id => ApplicationRecord.id_in_region(1, region_remote.region)) }
let(:api_client_collection) { double("/api/#{resource_type.pluralize}") }
let(:api_client_connection) { double("ApiClient", :instances => api_client_collection) }
let(:api_resource) { double(resource_type) }
let(:operation) { operation }
let(:region_remote) { FactoryGirl.create(:miq_region) }
let(:url) { send("api_#{resource_type}_url", nil, resource) }

it operation.to_s do
api_basic_authorize(action_identifier(resource_type.pluralize.to_sym, operation))

expect(api_client_connection).to receive(resource_type.pluralize).and_return(api_client_collection)
expect(InterRegionApiMethodRelay).to receive(:api_client_connection_for_region).with(region_remote.region).and_return(api_client_connection)
expect(api_client_collection).to receive(:find).with(resource.id).and_return(api_resource)
expect(api_resource).to receive(operation)

post(url, :params => gen_request(operation))
end
end

0 comments on commit 60cb7c9

Please sign in to comment.