Skip to content

Commit

Permalink
Merge pull request #651 from miha-plesko/add_aws_bucket
Browse files Browse the repository at this point in the history
Support operation `create` on CloudObjectStoreContainer
  • Loading branch information
h-kataria authored Apr 24, 2017
2 parents 5f71d23 + 731488e commit ac62737
Show file tree
Hide file tree
Showing 8 changed files with 326 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
ManageIQ.angular.app.controller('cloudObjectStoreContainerFormController', ['miqService', 'API', 'storageManagerId', function(miqService, API, storageManagerId) {
var vm = this;

var init = function() {
vm.afterGet = false;
vm.cloudContainerModel = {
name: '',
emstype: '',
parent_emstype: '',
provider_region: '',
};

// fetch StorageManager from querystring
vm.cloudContainerModel.storage_manager_id = storageManagerId;

vm.model = 'cloudContainerModel';
vm.newRecord = true;

ManageIQ.angular.scope = vm;
vm.saveable = miqService.saveable;

miqService.sparkleOn();
API.get('/api/providers?expand=resources&attributes=id,name&filter[]=supports_cloud_object_store_container_create?=true')
.then(getStorageManagers)
.catch(miqService.handleFailure);

setForm();
};

vm.addClicked = function() {
var url = 'create' + '?button=add';
miqService.miqAjaxButton(url, vm.cloudContainerModel, { complete: false });
};

vm.cancelClicked = function() {
miqService.miqAjaxButton('/cloud_object_store_container/create?button=cancel');
};

vm.storageManagerChanged = function(id) {
miqService.sparkleOn();

API.get('/api/providers/' + id + '?attributes=type,parent_manager.type')
.then(getStorageManagerFormData)
.catch(miqService.handleFailure);
};

function getStorageManagerFormData(data) {
vm.afterGet = true;
vm.cloudContainerModel.emstype = data.type;
vm.cloudContainerModel.parent_emstype = data.parent_manager.type;

miqService.sparkleOff();
}

function setForm() {
vm.modelCopy = angular.copy(vm.cloudContainerModel);
vm.afterGet = true;
miqService.sparkleOff();
}

function getStorageManagers(data) {
vm.storageManagers = data.resources;

// If storage manager ID was provided, we need to refresh the form and show
// corresponding form fields.
if (storageManagerId) {
vm.storageManagerChanged(vm.cloudContainerModel.storage_manager_id);
}
}

init();
}]);
92 changes: 91 additions & 1 deletion app/controllers/cloud_object_store_container_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ 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

process_cloud_object_storage_buttons(params[:pressed])
case params[:pressed]
when "cloud_object_store_container_new"
return javascript_redirect(:action => "new")
else
process_cloud_object_storage_buttons(params[:pressed])
end

if !@flash_array.nil? && params[:pressed].ends_with?("delete")
javascript_redirect :action => 'show_list',
Expand All @@ -32,8 +37,93 @@ def self.display_methods
%w(cloud_object_store_objects)
end

def new
assert_privileges("cloud_object_store_container_new")
@in_a_form = true
if params[:storage_manager_id]
@storage_manager = find_record_with_rbac(ExtManagementSystem, params[:storage_manager_id])
end
@provider_regions = retrieve_provider_regions
drop_breadcrumb(
:name => _("Add New %{model}") % {:model => ui_lookup(:table => 'cloud_object_store_container')},
:url => "/cloud_object_store_container/new"
)
end

def create
assert_privileges("cloud_object_store_container_new")
case params[:button]
when "cancel"
javascript_redirect previous_breadcrumb_url
when "add"
options = form_params_create
ext_management_system = options.delete(:ems)

# Queue task
task_id = CloudObjectStoreContainer.cloud_object_store_container_create_queue(
session[:userid],
ext_management_system,
options
)

if task_id.kind_of?(Integer)
initiate_wait_for_task(:task_id => task_id, :action => "create_finished")
else
add_flash(_("Cloud Object Store Container creation failed: Task start failed"), :error)
javascript_flash(:spinner_off => true)
end
end
end

def create_finished
task_id = session[:async][:params][:task_id]
container_name = session[:async][:params][:name]
task = MiqTask.find(task_id)
if MiqTask.status_ok?(task.status)
add_flash(_("Cloud Object Store Container \"%{name}\" created") % {
:name => container_name
})
else
add_flash(_("Unable to create Cloud Object Store Container \"%{name}\": %{details}") % {
:name => container_name,
:details => task.message
}, :error)
end

session[:flash_msgs] = @flash_array.dup if @flash_array
javascript_redirect previous_breadcrumb_url
end

def form_params_create
options = {}
options[:name] = params[:name] if params[:name]

# Depending on the storage manager type, collect required form params.
case params[:emstype]
when "ManageIQ::Providers::Amazon::StorageManager::S3"
if params[:provider_region]
options[:create_bucket_configuration] = {
:location_constraint => params[:provider_region]
}
end

# Get the storage manager.
storage_manager_id = params[:storage_manager_id] if params[:storage_manager_id]
options[:ems] = find_record_with_rbac(ExtManagementSystem, storage_manager_id)
end
options
end

private

def retrieve_provider_regions
managers = ManageIQ::Providers::CloudManager.supported_subclasses.select(&:supports_regions?)
managers.each_with_object({}) do |manager, provider_regions|
regions = manager.parent::Regions.all.sort_by { |r| r[:description] }
provider_regions[manager.name] = regions.map { |region| [region[:description], region[:name]] }
end
end

def textual_group_list
[%i(properties relationships), %i(tags)]
end
Expand Down
8 changes: 7 additions & 1 deletion app/controllers/ems_common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,13 @@ def button
end
end
elsif params[:pressed].starts_with?("cloud_object_store_")
process_cloud_object_storage_buttons(params[:pressed])
case params[:pressed]
when "cloud_object_store_container_new"
return javascript_redirect(:controller => "cloud_object_store_container", :action => "new",
:storage_manager_id => params[:id])
else
process_cloud_object_storage_buttons(params[:pressed])
end
else
@refresh_div = "main_div" # Default div for button.rjs to refresh
redirect_to :action => "new" if params[:pressed] == "new"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class ApplicationHelper::Button::CloudObjectStoreContainerNew < ApplicationHelper::Button::Basic
def calculate_properties
super
if disabled?
self[:title] = _("No storage managers support creating cloud object store containers.")
end
end

def disabled?
!ExtManagementSystem.any? { |ems| ems.supports?(:cloud_object_store_container_create) }
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ class ApplicationHelper::Toolbar::CloudObjectStoreContainersCenter < Application
'fa fa-cog fa-lg',
t = N_('Configuration'),
t,
:enabled => false,
:onwhen => "1+",
:enabled => true,
:items => [
button(
:cloud_object_store_container_new,
'pficon pficon-add-circle-o fa-lg',
t = N_('Add a new Cloud Object Store Container'),
t,
:klass => ApplicationHelper::Button::CloudObjectStoreContainerNew
),
separator,
button(
:cloud_object_store_container_clear,
'pficon pficon-delete fa-lg',
Expand All @@ -21,7 +28,6 @@ class ApplicationHelper::Toolbar::CloudObjectStoreContainersCenter < Application
:enabled => false,
:onwhen => "1+"
),
separator,
button(
:cloud_object_store_container_delete,
'pficon pficon-delete fa-lg',
Expand Down
65 changes: 65 additions & 0 deletions app/views/cloud_object_store_container/new.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
%form#form_div{:name => "angularForm",
'ng-controller' => "cloudObjectStoreContainerFormController as vm",
"ng-show" => "vm.afterGet",
"ng-cloak" => "",
"miq-form" => true,
"model" => "vm.cloudContainerModel",
"model-copy" => "vm.modelCopy"}
= render :partial => "layouts/flash_msg"
.form-horizontal
.form-group{"ng-class" => "{'has-error': angularForm.storage_manager_id.$invalid}"}
%label.col-md-2.control-label
= _('Storage Manager')
.col-md-8
%select{"name" => "storage_manager_id",
"ng-model" => "vm.cloudContainerModel.storage_manager_id",
"ng-options" => "mgr.id|number as mgr.name for mgr in vm.storageManagers",
"ng-change" => "vm.storageManagerChanged(vm.cloudContainerModel.storage_manager_id)",
"required" => "",
"disabled" => !@storage_manager.nil?,
:checkchange => true,
"pf-select" => true}
%option{"value" => "", "disabled" => ""}
= "<#{_('Choose')}>"
%span.help-block{"ng-show" => "angularForm.storage_manager_id.$error.required"}
= _("Required")

.form-group{"ng-class" => "{'has-error': angularForm.name.$invalid}"}
%label.col-md-2.control-label
= _('Container Name')
.col-md-8
%input.form-control{:type => "text",
:name => "name",
"ng-model" => "vm.cloudContainerModel.name",
"ng-maxlength" => 255,
"required" => "",
:miqrequired => true,
:checkchange => true}
%span.help-block{"ng-show" => "angularForm.name.$error.required"}
= _("Required")
%div{"ng-if" => "vm.cloudContainerModel.emstype === 'ManageIQ::Providers::Amazon::StorageManager::S3'"}
.form-horizontal
.form-group{"ng-class" => "{'has-error': angularForm.provider_region.$invalid}",
"ng-if" => "#{@provider_regions.keys.to_json}.includes(vm.cloudContainerModel.parent_emstype)",
"ng-switch" => "",
"on" => "vm.cloudContainerModel.parent_emstype"}
%label.col-md-2.control-label{"for" => "ems_region"}
= _('Region')
.col-md-8
- @provider_regions.each do |name, regions|
= select_tag('provider_region',
options_for_select([["<#{_('Choose')}>", nil]] + regions, disabled: ["<#{_('Choose')}>", nil]),
"ng-model" => "vm.cloudContainerModel.provider_region",
"ng-switch-when" => name,
"required" => "",
"checkchange" => "",
"selectpicker-for-select-tag" => "",
"multiple" => false,
"data-live-search" => true)
%span.help-block{"ng-show" => "angularForm.provider_region.$error.required"}
= _("Required")
= render :partial => "layouts/angular/generic_form_buttons"
:javascript
ManageIQ.angular.app.value('storageManagerId', '#{@storage_manager.try(:id)}');
miq_bootstrap('#form_div');
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@
show_list
tagging_edit
tag_edit_form_field_changed
new
) + compare_get,
:post => %w(
button
Expand All @@ -412,6 +413,8 @@
show_list
tagging_edit
tag_edit_form_field_changed
create
wait_for_task
) + compare_post + adv_search_post + exp_post + save_post
},

Expand Down
67 changes: 67 additions & 0 deletions spec/controllers/cloud_object_store_container_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,72 @@
end
end

describe "create object store container" do
before do
stub_user(:features => :all)
end

shared_examples "queue create container task" do
let(:task_options) do
{
:action => "creating Cloud Object Store Container for user %{user}" %
{:user => controller.current_user.userid},
:userid => controller.current_user.userid
}
end

let(:queue_options) do
{
:class_name => "CloudObjectStoreContainer",
:method_name => 'cloud_object_store_container_create',
:role => 'ems_operations',
:zone => @ems.my_zone,
:args => [@ems.id, @expected_args]
}
end

it "builds add new container screen" do
post :button, :params => { :pressed => "cloud_object_store_container_new", :format => :js }
expect(assigns(:flash_array)).to be_nil
end

it "queues the create cloud object store container action form" do
expect(MiqTask).to receive(:generic_action_with_callback).with(task_options, queue_options)
post :create, :params => @form_params.merge(:button => "add", :format => :js)
end
end

context "in Amazon S3" do
before do
@cloud_manager = FactoryGirl.create(:ems_amazon)
@ems = @cloud_manager.s3_storage_manager

@form_params = {
:name => "bucket-01",
:emstype => "ManageIQ::Providers::Amazon::StorageManager::S3",
:parent_emstype => "ManageIQ::Providers::Amazon::CloudManager",
:storage_manager_id => @ems.id,
:provider_region => "eu-central-1",
}

@expected_args = {
:name => "bucket-01",
:create_bucket_configuration => {:location_constraint => "eu-central-1"}
}
end

context "create" do
it_behaves_like "queue create container task"
end

it "aws regions" do
provider_regions = controller.send(:retrieve_provider_regions)

expect(provider_regions["ManageIQ::Providers::Amazon::CloudManager"]).not_to be_nil
expect(provider_regions["ManageIQ::Providers::Amazon::CloudManager"].count).to be > 0
end
end
end

include_examples '#download_summary_pdf', :cloud_object_store_container
end

0 comments on commit ac62737

Please sign in to comment.