Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support operations on CloudObjectStoreContainer
Browse files Browse the repository at this point in the history
CloudObjectStoreContainer model had no support for operations
(e.g. delete) since they were not supported by backend. Well,
now the backend supports deleting bucket hence we add "Configuration"
menu option for this.

This commit brings a new mid-page menu item "Configuration->Remove
Object Storage Container" to the following pages:

* cloud object container details page
* cloud object container full list
* cloud object container list per StorageManager

Signed-off-by: Miha Pleško <[email protected]>
miha-plesko committed Feb 27, 2017
1 parent 78170f0 commit a229590
Showing 8 changed files with 327 additions and 6 deletions.
57 changes: 57 additions & 0 deletions app/controllers/application_controller/ci_processing.rb
Original file line number Diff line number Diff line change
@@ -1840,6 +1840,49 @@ def vm_button_operation(method, display_name, partial_after_single_selection = n
vms.count
end

def process_cloud_object_storage_buttons
assert_privileges(params[:pressed])

klass = get_rec_cls
task = params[:pressed].sub("#{klass.name.underscore.to_sym}_", "")

return tag(klass) if task == "tag"

cloud_object_store_button_operation(klass, task)
end

def cloud_object_store_button_operation(klass, task)
method = "raw_#{task}"
display_name = _(task.capitalize)

items = []

# Either a list or coming from a different controller
if @lastaction == "show_list" || !%w(cloud_object_store_container).include?(request.parameters["controller"])
items = find_checked_items
if items.empty?
add_flash(_("No %{model} were selected for %{task}") %
{:model => ui_lookup(:models => klass.name), :task => display_name}, :error)
elsif klass.find(items).any? { |item| !item.supports?(task) }
add_flash(_("%{task} does not apply to at least one of the selected items") %
{:task => display_name}, :error)
else
process_objects(items, method, display_name)
end
elsif params[:id].nil? || klass.find_by(:id => params[:id]).nil?
add_flash(_("%{record} no longer exists") %
{:record => ui_lookup(:table => request.parameters["controller"])}, :error)
show_list unless @explorer
@refresh_partial = "layouts/gtl"
elsif !klass.find_by(:id => params[:id]).supports?(task)
add_flash(_("%{task} does not apply to this item") %
{:task => display_name}, :error)
else
items.push(params[:id])
process_objects(items, method, display_name) unless items.empty?
end
end

def get_rec_cls
case request.parameters["controller"]
when "miq_template"
@@ -1848,6 +1891,14 @@ def get_rec_cls
return OrchestrationStack
when "service"
return Service
when "cloud_object_store_container"
CloudObjectStoreContainer
when "ems_storage"
if params[:pressed].starts_with? "cloud_object_store_object"
CloudObjectStoreObject
else
CloudObjectStoreContainer
end
else
return VmOrTemplate
end
@@ -1864,6 +1915,12 @@ def process_objects(objs, task, display_name = nil)
when "VmOrTemplate"
objs, _objs_out_reg = filter_ids_in_region(objs, "VM") unless VmOrTemplate::REMOTE_REGION_TASKS.include?(task)
klass = Vm
when "CloudObjectStoreContainer"
objs, _objs_out_reg = filter_ids_in_region(objs, "CloudObjectStoreContainer")
klass = CloudObjectStoreContainer
when "CloudObjectStoreObject"
objs, _objs_out_reg = filter_ids_in_region(objs, "CloudObjectStoreObject")
klass = CloudObjectStoreObject
end

assert_rbac(current_user, get_rec_cls, objs)
11 changes: 10 additions & 1 deletion app/controllers/cloud_object_store_container_controller.rb
Original file line number Diff line number Diff line change
@@ -16,7 +16,16 @@ def breadcrumb_name(_model)
def button
@edit = session[:edit] # Restore @edit for adv search box
params[:page] = @current_page unless @current_page.nil? # Save current page for list refresh
return tag("CloudObjectStoreContainer") if params[:pressed] == 'cloud_object_store_container_tag'

process_cloud_object_storage_buttons

if !@flash_array.nil? && params[:pressed].ends_with?("delete")
javascript_redirect :action => 'show_list',
:flash_msg => @flash_array[0][:message],
:flash_error => @flash_array[0][:level] == :error
elsif !@flash_array.nil?
render_flash unless performed?
end
end

def self.display_methods
8 changes: 5 additions & 3 deletions app/controllers/ems_common.rb
Original file line number Diff line number Diff line change
@@ -332,7 +332,6 @@ def button
# Handle buttons from sub-items screen
if params[:pressed].starts_with?("availability_zone_",
"cloud_network_",
"cloud_object_store_container_",
"cloud_subnet_",
"cloud_tenant_",
"cloud_volume_",
@@ -380,7 +379,6 @@ def button
# Edit Tags for Network Manager Relationship pages
when "availability_zone_tag" then tag(AvailabilityZone)
when "cloud_network_tag" then tag(CloudNetwork)
when "cloud_object_store_container_tag" then tag(CloudObjectStoreContainer)
when "cloud_subnet_tag" then tag(CloudSubnet)
when "cloud_tenant_tag" then tag(CloudTenant)
when "cloud_volume_tag" then tag(CloudVolume)
@@ -416,6 +414,8 @@ def button
show # Handle EMS buttons
end
end
elsif params[:pressed].starts_with?("cloud_object_store_")
process_cloud_object_storage_buttons
else
@refresh_div = "main_div" # Default div for button.rjs to refresh
redirect_to :action => "new" if params[:pressed] == "new"
@@ -496,7 +496,9 @@ def button
end

if !@flash_array.nil? && params[:pressed] == "#{@table_name}_delete" && @single_delete
javascript_redirect :action => 'show_list', :flash_msg => @flash_array[0][:message] # redirect to build the retire screen
javascript_redirect :action => 'show_list',
:flash_msg => @flash_array[0][:message],
:flash_error => @flash_array[0][:level] == :error
elsif params[:pressed] == "host_aggregate_edit"
javascript_redirect :controller => "host_aggregate", :action => "edit", :id => find_checked_items[0]
elsif params[:pressed] == "cloud_tenant_edit"
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
class ApplicationHelper::Toolbar::CloudObjectStoreContainerCenter < ApplicationHelper::Toolbar::Basic
button_group(
'cloud_object_store_container_vmdb',
[
select(
:cloud_object_store_container_vmdb_choice,
'fa fa-cog fa-lg',
t = N_('Configuration'),
t,
:items => [
button(
:cloud_object_store_container_delete,
'pficon pficon-delete fa-lg',
N_('Remove selected Object Storage Containers'),
N_('Remove Object Storage Container'),
:url_parms => "main_div",
:confirm => N_("Warning: The selected Object Storage Container and ALL related Objects will be "\
"permanently removed!"),
:klass => ApplicationHelper::Button::GenericFeatureButtonWithDisable,
:options => {:feature => :delete}
),
]
),
]
)
button_group('cloud_object_store_container_policy', [
select(
:cloud_object_store_container_policy_choice,
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
class ApplicationHelper::Toolbar::CloudObjectStoreContainersCenter < ApplicationHelper::Toolbar::Basic
button_group(
'cloud_object_store_container_vmdb',
[
select(
:cloud_object_store_container_vmdb_choice,
'fa fa-cog fa-lg',
t = N_('Configuration'),
t,
:enabled => false,
:onwhen => "1+",
:items => [
button(
:cloud_object_store_container_delete,
'pficon pficon-delete fa-lg',
N_('Remove selected Object Storage Containers'),
N_('Remove Object Storage Container'),
:url_parms => "main_div",
:confirm => N_("Warning: The selected Object Storage Containers and ALL related Objects will be "\
"permanently removed!"),
:enabled => false,
:onwhen => "1+"
),
]
),
]
)
button_group('cloud_object_store_container_policy', [
select(
:cloud_object_store_container_policy_choice,
144 changes: 144 additions & 0 deletions spec/controllers/application_controller/ci_processing_spec.rb
Original file line number Diff line number Diff line change
@@ -18,6 +18,150 @@
end
end

context "Delete object store container" do
before do
@container1 = FactoryGirl.create(:cloud_object_store_container, :id => 123)
@container2 = FactoryGirl.create(:cloud_object_store_container, :id => 456)
allow(controller).to receive(:assert_rbac).and_return(nil)
allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(true)
end

context "from list view" do
before do
controller.params[:pressed] = 'cloud_object_store_container_delete'
controller.params[:miq_grid_checks] = '123, 456'
request.parameters["controller"] = "ems_storage"
end

it "get_rec_cls" do
expect(controller.send(:get_rec_cls)).to eq(CloudObjectStoreContainer)
end

it "invokes cloud_object_store_button_operation" do
expect(controller).to receive(:cloud_object_store_button_operation).with(
CloudObjectStoreContainer,
'delete'
)
controller.send(:process_cloud_object_storage_buttons)
end

it "invokes process_objects" do
expect(controller).to receive(:process_objects).with(
[123, 456],
'raw_delete',
'Delete'
)
controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'delete')
end

it "invokes process_tasks on container class" do
expect(CloudObjectStoreContainer).to receive(:process_tasks).with(
:ids => [123, 456],
:task => 'raw_delete',
:userid => anything
)
controller.send(:process_objects, [123, 456], 'raw_delete', 'delete')
end

it "invokes process_tasks overall (when selected)" do
expect(CloudObjectStoreContainer).to receive(:process_tasks).with(
:ids => [123, 456],
:task => 'raw_delete',
:userid => anything
)
controller.send(:process_cloud_object_storage_buttons)
end

it "does not invoke process_tasks overall when nothing selected" do
controller.params[:miq_grid_checks] = ''
expect(CloudObjectStoreContainer).not_to receive(:process_tasks)
controller.send(:process_cloud_object_storage_buttons)
end

it "flash - nothing selected" do
controller.params[:miq_grid_checks] = ''
controller.send(:process_cloud_object_storage_buttons)
expect(assigns(:flash_array).first[:message]).to include(
"No Cloud Object Store Containers were selected for Delete"
)
end

it "flash - task not supported" do
allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false)
controller.send(:process_cloud_object_storage_buttons)
expect(assigns(:flash_array).first[:message]).to include(
"Delete does not apply to at least one of the selected items"
)
end
end

context "from details view" do
before do
@container = FactoryGirl.create(:cloud_object_store_container, :name => "cloud-object-store-container-01")
@container_id = @container.id
allow(controller).to receive(:show_list).and_return(nil)
controller.params[:pressed] = 'cloud_object_store_container_delete'
controller.params[:id] = @container_id
request.parameters["controller"] = "cloud_object_store_container"
end

it "get_rec_cls" do
expect(controller.send(:get_rec_cls)).to eq(CloudObjectStoreContainer)
end

it "invokes cloud_object_store_button_operation" do
expect(controller).to receive(:cloud_object_store_button_operation).with(
CloudObjectStoreContainer,
'delete'
)
controller.send(:process_cloud_object_storage_buttons)
end

it "invokes process_objects" do
expect(controller).to receive(:process_objects).with(
[@container_id],
'raw_delete',
'Delete'
)
controller.send(:cloud_object_store_button_operation, CloudObjectStoreContainer, 'delete')
end

it "invokes process_tasks on container class" do
expect(CloudObjectStoreContainer).to receive(:process_tasks).with(
:ids => [@container_id],
:task => 'raw_delete',
:userid => anything
)
controller.send(:process_objects, [@container_id], 'raw_delete', 'delete')
end

it "invokes process_tasks overall" do
expect(CloudObjectStoreContainer).to receive(:process_tasks).with(
:ids => [@container_id],
:task => 'raw_delete',
:userid => anything
)
controller.send(:process_cloud_object_storage_buttons)
end

it "flash - container no longer exists" do
@container.destroy
controller.send(:process_cloud_object_storage_buttons)
expect(assigns(:flash_array).first[:message]).to include(
"Cloud Object Store Container no longer exists"
)
end

it "flash - task not supported" do
allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(false)
controller.send(:process_cloud_object_storage_buttons)
expect(assigns(:flash_array).first[:message]).to include(
"Delete does not apply to this item"
)
end
end
end

# some methods should not be accessible through the legacy routes
# either by being private or through the hide_action mechanism
it 'should not allow call of hidden/private actions' do
58 changes: 56 additions & 2 deletions spec/controllers/cloud_object_store_container_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
describe CloudObjectStoreContainerController do
before do
EvmSpecHelper.create_guid_miq_server_zone
@container = FactoryGirl.create(:cloud_object_store_container, :name => "cloud-object-store-container-01")
allow_any_instance_of(CloudObjectStoreContainer).to receive(:supports?).and_return(true)
end

context "#tags_edit" do
let!(:user) { stub_user(:features => :all) }
before(:each) do
EvmSpecHelper.create_guid_miq_server_zone
@container = FactoryGirl.create(:cloud_object_store_container, :name => "cloud-object-store-container-01")
allow(@container).to receive(:tagged_with).with(:cat => user.userid).and_return("my tags")
classification = FactoryGirl.create(:classification, :name => "department", :description => "D epartment")
@tag1 = FactoryGirl.create(:classification_tag,
@@ -48,5 +52,55 @@
end
end

context "delete object store container" do
before do
login_as FactoryGirl.create(:user, :features => "everything")
request.parameters["controller"] = "cloud_object_store_container"
allow(controller).to receive(:role_allows?).and_return(true)
end

it "delete invokes process_cloud_object_storage_buttons" do
expect(controller).to receive(:process_cloud_object_storage_buttons)
post :button, :pressed => "cloud_object_store_container_delete", :format => :js, :id => @container.id
end

it "delete triggers delete" do
expect(controller).to receive(:cloud_object_store_button_operation).with(
CloudObjectStoreContainer,
'delete'
)
post :button, :pressed => "cloud_object_store_container_delete", :format => :js, :id => @container.id
end

it "delete redirects to show_list" do
expect(controller).to receive(:javascript_redirect).with(
:action => 'show_list',
:flash_msg => anything,
:flash_error => false
)
post :button, :pressed => "cloud_object_store_container_delete", :format => :js, :id => @container.id
end

it "delete shows expected flash" do
post :button, :pressed => "cloud_object_store_container_delete", :format => :js, :id => @container.id

expect(assigns(:flash_array).first[:message]).to include(
"Delete initiated for 1 Cloud Object Store Container from the ManageIQ Database"
)
expect(response.status).to eq(200)
end

it "delete shows expected flash (non-existing container)" do
@container.destroy

post :button, :pressed => "cloud_object_store_container_delete", :format => :js, :id => @container.id

expect(assigns(:flash_array).first[:message]).to include(
"Cloud Object Store Container no longer exists"
)
expect(response.status).to eq(200)
end
end

include_examples '#download_summary_pdf', :cloud_object_store_container
end
5 changes: 5 additions & 0 deletions spec/controllers/ems_common_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -153,6 +153,11 @@
expect(response.status).to eq 200
expect(response.body).to include('orchestration_stack/retire')
end

it "when Delete Button is pressed for CloudObjectStoreContainer" do
expect(controller).to receive(:process_cloud_object_storage_buttons)
post :button, :params => { :pressed => "cloud_object_store_container_delete" }
end
end
end

0 comments on commit a229590

Please sign in to comment.