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

Add rake task to import custom buttons #17726

Merged
merged 2 commits into from
Aug 2, 2018
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
80 changes: 80 additions & 0 deletions lib/task_helpers/imports/custom_buttons.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
module TaskHelpers
class Imports
class CustomButtons
def import(options)
return unless options[:source]
glob = File.file?(options[:source]) ? options[:source] : "#{options[:source]}/*.yaml"
Dir.glob(glob) do |filename|
begin
import_custom_buttons(filename)
rescue StandardError
raise StandardError, "Error importing #{filename} at #{$@}"
end
end
end

private

class ImportArInstances
def self.import(obj_hash)
new.import(obj_hash)
end

def import(obj_hash)
ActiveRecord::Base.transaction { obj_hash.each { |obj_def| create_object(*obj_def) } }
end

def create_object(class_name, obj_array)
klass = class_name.camelize.constantize

obj_array.collect do |obj|
begin
klass.create!(obj['attributes']&.except('guid')).tap do |new_obj|
add_children(obj, new_obj)
add_associations(obj, new_obj)
try("#{class_name}_post", new_obj)
end
rescue StandardError
raise
end
end
end

def add_children(obj, new_obj)
if obj['children'].present?
obj['children'].each do |child|
new_obj.add_members(create_object(*child))
end
end
end

def add_associations(obj, new_obj)
if obj['associations'].present?
obj['associations'].each do |assoc|
new_obj.send("#{assoc.first}=", create_object(*assoc).first)
end
end
end

def custom_button_set_post(new_obj)
new_obj.set_data[:button_order] = new_obj.custom_buttons.collect(&:id)
new_obj.save!
end

def custom_button_post(new_obj)
check_user(new_obj)
end

def check_user(new_obj)
existing_user = User.find_by(:name => new_obj[:userid])
new_obj.update_attributes(:userid => existing_user.nil? ? "admin" : existing_user)
end
end

def import_custom_buttons(filename)
custom_buttons = YAML.load_file(filename)
ImportArInstances.import(custom_buttons)
end
end
end
end
8 changes: 8 additions & 0 deletions lib/tasks/evm_export_import.rake
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,13 @@ namespace :evm do

exit # exit so that parameters to the first rake task are not run as rake tasks
end

desc 'Imports all custom buttons from YAML file'
task :custom_buttons => :environment do
options = TaskHelpers::Imports.parse_options
TaskHelpers::Imports::CustomButtons.new.import(options)

exit # exit so that parameters to the first rake task are not run as rake tasks
end
end
end
89 changes: 89 additions & 0 deletions spec/lib/task_helpers/imports/custom_buttons_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
describe TaskHelpers::Imports::CustomButtons do
let(:data_dir) { File.join(File.expand_path(__dir__), 'data', 'custom_buttons') }
let(:custom_button_file) { 'CustomButtons.yaml' }
let(:bad_custom_button_file) { 'CustomButtonsBad.yaml' }
let(:custom_button_set_name) { 'group1|Vm|' }
let(:custom_button_set_description) { 'group1' }
let(:resource_action_ae_namespace) { 'SYSTEM' }
let(:options) { {:source => source} }

describe "#import" do
describe "when the source is a directory" do
let(:source) { data_dir }

context "without existing buttons" do
it 'imports all formatted .yaml files in a specified directory' do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_test_custom_button_set_present
end
end

context "with existing identical buttons" do
it 'should raise' do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_raises_import_error
end
end

context "yaml import failure" do
it 'should raise' do
file = Tempfile.new('foo.yaml', data_dir)
file.write("bad yaml here")
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_raises_import_error
assert_imports_only_custom_button_set_one
end
end
end

describe "when the source is a file" do
let(:source) { "#{data_dir}/#{custom_button_file}" }

context "without existing buttons" do
context "only imports good yaml" do
it 'imports a specified file' do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_test_custom_button_set_present
assert_imports_only_custom_button_set_one
end
end

context "doesn't import bad yaml" do
let(:source) { "#{data_dir}/#{bad_custom_button_file}" }
it 'does not imports a specified file' do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_imports_no_custom_buttons
end
end
end

context "with existing identical buttons" do
it 'should not import anything' do
TaskHelpers::Imports::CustomButtons.new.import(options)
assert_raises_import_error
assert_imports_only_custom_button_set_one
end
end
end
end

def assert_test_custom_button_set_present
cbs = CustomButtonSet.find_by(:name => custom_button_set_name)
expect(cbs.custom_buttons.count).to eq(3)
expect(cbs.description).to eq(custom_button_set_description)
expect(cbs.custom_buttons.first.resource_action.ae_namespace).to eq(resource_action_ae_namespace)
expect(cbs.custom_buttons.pluck(:userid)).to eq(%w(admin admin admin))
end

def assert_imports_only_custom_button_set_one
expect(CustomButton.count).to eq(3)
end

def assert_imports_no_custom_buttons
expect(CustomButton.count).to eq(0)
end

def assert_raises_import_error
expect { TaskHelpers::Imports::CustomButtons.new.import(options) }.to raise_error(StandardError, /Error importing/)
end
end
134 changes: 134 additions & 0 deletions spec/lib/task_helpers/imports/data/custom_buttons/CustomButtons.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
---
custom_button_set:
- attributes:
name: group1|Vm|
description: group1
set_type: CustomButtonSet
guid: ba4ff235-75eb-4fa4-a9f9-b854d4186c3a
read_only:
set_data:
:button_order:
- 2
- 3
- 10
:button_icon: ff ff-class
:button_color: "#a341ab"
:display: true
:applies_to_class: Vm
:group_index: 1
mode:
owner_type:
owner_id:
userid:
group_id:
children:
custom_button:
- attributes:
guid: f059931f-8703-4bcf-b876-e482d38ce8ea
description: button 1
applies_to_class: Vm
visibility_expression:
options:
:button_icon: pficon pficon-cpu
:button_type: default
:display: true
:open_url: false
:display_for: single
:submit_how: one
userid: admin
wait_for_complete:
name: button 1
visibility:
:roles:
- _ALL_
applies_to_id:
enablement_expression:
disabled_text:
associations:
resource_action:
- attributes:
action:
resource_type: CustomButton
ae_namespace: SYSTEM
ae_class: PROCESS
ae_instance: Request
ae_message:
ae_attributes:
request: test1
configuration_template_id:
configuration_template_type:
- attributes:
guid: 3f50d617-851e-451f-95ae-a17fc548cb11
description: button 2
applies_to_class: Vm
visibility_expression:
options:
:button_icon: pficon pficon-home
:button_color: "#c03638"
:button_type: default
:display: true
:open_url: false
:display_for: single
:submit_how: one
userid:
wait_for_complete:
name: button 2
visibility:
:roles:
- _ALL_
applies_to_id:
enablement_expression:
disabled_text:
associations:
resource_action:
- attributes:
action:
resource_type: CustomButton
ae_namespace: SYSTEM
ae_class: PROCESS
ae_instance: Request
ae_message:
ae_attributes:
request: test2
configuration_template_id:
configuration_template_type:
- attributes:
guid: d3cd608a-f476-48b7-aa25-a930ec046e00
description: multiselect
applies_to_class: Vm
visibility_expression: !ruby/object:MiqExpression
exp:
"=":
field: Vm-power_state
value: 'on'
context_type:
options:
:button_icon: fa fa-users
:button_color: "#996633"
:button_type: default
:display: true
:open_url: false
:display_for: both
:submit_how: all
userid: admin
wait_for_complete:
name: multiselect
visibility:
:roles:
- _ALL_
applies_to_id:
enablement_expression:
disabled_text:
associations:
resource_action:
- attributes:
action:
resource_type: CustomButton
ae_namespace: SYSTEM
ae_class: PROCESS
ae_instance: Request
ae_message:
ae_attributes:
request: multiselect
configuration_template_id:
configuration_template_type:
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
custom_button:
- attributes:
guid: f059931f-8703-4bcf-b876-e482d38ce8ea
description: button 1
applies_to_class: Vm
visibility_expression:
options:
:button_icon: pficon pficon-cpu
:button_type: default
:display: true
:open_url: false
:display_for: single
:submit_how: one
userid: admin
wait_for_complete:
name: button 1
visibility:
:roles:
- _ALL_
applies_to_id:
enablement_expression:
disabled_text:
associations:
resource_action:
- attributes:
action:
resource_type: CustomButton
ae_namespace: SYSTEM
ae_class: PROCESS
ae_instance: Request
ae_message:
ae_attributes:
request: test1
configuration_template_id:
configuration_template_type: