diff --git a/app/models/manageiq/providers/amazon/cloud_manager/orchestration_service_option_converter.rb b/app/models/manageiq/providers/amazon/cloud_manager/orchestration_service_option_converter.rb index 025a1cfd7..ae135a89f 100644 --- a/app/models/manageiq/providers/amazon/cloud_manager/orchestration_service_option_converter.rb +++ b/app/models/manageiq/providers/amazon/cloud_manager/orchestration_service_option_converter.rb @@ -1,10 +1,46 @@ class ManageIQ::Providers::Amazon::CloudManager::OrchestrationServiceOptionConverter < ::ServiceOrchestration::OptionConverter + REGEX_TAGS = /([^(=>), ]+)[(=>) ]+([^(=>), ]+)[, ]*/ + REGEX_ARRAY = /[, ]+/ + private_constant :REGEX_TAGS, :REGEX_TAGS + def stack_create_options - on_failure = @dialog_options['dialog_stack_onfailure'] timeout = @dialog_options['dialog_stack_timeout'] - stack_options = {:parameters => stack_parameters, :disable_rollback => on_failure != 'ROLLBACK'} - stack_options[:timeout_in_minutes] = timeout.to_i unless timeout.blank? + policy_body, policy_url = parse_policy(@dialog_options['dialog_stack_policy']) + + stack_options = { + :parameters => stack_parameters, + :on_failure => @dialog_options['dialog_stack_onfailure'], + :timeout_in_minutes => timeout.blank? ? nil : timeout.to_i, + :notification_arns => @dialog_options['dialog_stack_notifications'].try(:split, REGEX_ARRAY), + :capabilities => @dialog_options['dialog_stack_capabilities'], #multi-selected dropdown, as an array + :resource_types => @dialog_options['dialog_stack_resource_types'].try(:split, REGEX_ARRAY), + :role_arn => @dialog_options['dialog_stack_role'], + :stack_policy_body => policy_body, + :stack_policy_url => policy_url, + :tags => parse_tags(@dialog_options['dialog_stack_tags']) + } + + stack_options.select { |_k, v| v.present? } + end + + private + + def parse_tags(input) + return unless input + + # input example: "tag_key1 => tag_val1, tag_key2 => tag_val2" + input.scan(REGEX_TAGS).each_with_object([]) { |tag, arr| arr.push({:key => tag.first, :value => tag.last}) } + end + + def parse_policy(input) + return unless input - stack_options + begin + JSON.parse(input) + policy_body = input + rescue JSON::ParserError + policy_url = input + end + [policy_body, policy_url] end end diff --git a/spec/models/manageiq/providers/amazon/cloud_manager/orchestration_service_option_converter_spec.rb b/spec/models/manageiq/providers/amazon/cloud_manager/orchestration_service_option_converter_spec.rb new file mode 100644 index 000000000..6274bd953 --- /dev/null +++ b/spec/models/manageiq/providers/amazon/cloud_manager/orchestration_service_option_converter_spec.rb @@ -0,0 +1,75 @@ +describe ManageIQ::Providers::Amazon::CloudManager::OrchestrationServiceOptionConverter do + subject { described_class.new(options) } + + describe '#stack_create_options' do + context 'no option is set' do + let(:options) { {} } + + it 'returns an empty option hash for stack creation' do + expect(subject.stack_create_options).to be_empty + end + end + + context 'all options are empty' do + let(:options) do + { + "dialog_stack_timeout" => "", + "dialog_stack_onfailure" => "", + "dialog_stack_notifications" => "", + "dialog_stack_capabilities" => "", + "dialog_stack_resource_types" => "", + "dialog_stack_policy" => "", + "dialog_stack_role" => "", + "dialog_stack_tags" => "" + } + end + + it 'returns an empty option hash for stack creation' do + expect(subject.stack_create_options).to be_empty + end + end + end + + context 'timeout option' do + let(:options) { {'dialog_stack_timeout' => '30'} } + + it { expect(subject.stack_create_options[:timeout_in_minutes]).to eq(30) } + end + + context 'on_failure option' do + let(:options) { {'dialog_stack_onfailure' => 'ROLLBACK'} } + + it { expect(subject.stack_create_options[:on_failure]).to eq('ROLLBACK') } + end + + context 'notification arn option' do + let(:options) { {'dialog_stack_notifications' => 'ARN1, ARN2'} } + + it { expect(subject.stack_create_options[:notification_arns]).to eq(%w(ARN1 ARN2)) } + end + + context 'capabilities option' do + let(:options) { {'dialog_stack_capabilities' => %w(CAPABILITY_IAM CAPABILITY_NAMED_IAM)} } + + it { expect(subject.stack_create_options[:capabilities]).to eq(%w(CAPABILITY_IAM CAPABILITY_NAMED_IAM)) } + end + + context 'policy body option' do + let(:options) { {'dialog_stack_policy' => '{"valid":"JSON string"}'} } + + it { expect(subject.stack_create_options[:stack_policy_body]).to eq('{"valid":"JSON string"}') } + end + + context 'policy url option' do + let(:options) { {'dialog_stack_policy' => 'http://url'} } + + it { expect(subject.stack_create_options[:stack_policy_url]).to eq('http://url') } + end + + context 'tags option' do + let(:options) { {'dialog_stack_tags' => 'tag_key1 => tag_val1, tag_key2=>tag_val2'} } + + it { expect(subject.stack_create_options[:tags]).to eq( + [{:key => 'tag_key1', :value => 'tag_val1'}, {:key => 'tag_key2', :value => 'tag_val2'}]) } + end +end