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

Refactor amazon_customizerequest method for VM Provisioning. #628

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,99 +2,166 @@
# Description: This method is used to Customize the Amazon Provisioning Request
#

# process_customization - mapping instance_types, key pairs, security groups and cloud-init templates
def process_customization(mapping, prov, template, product, provider )
log(:info, "Processing Amazon customizations...", true)
case mapping
when 0
# No mapping
when 1
ws_values = prov.options.fetch(:ws_values, {})

if prov.get_option(:instance_type).nil? && ws_values.has_key?(:instance_type)
provider.flavors.each do |flavor|
if flavor.name.downcase == ws_values[:instance_type].downcase
prov.set_option(:instance_type, [flavor.id, "#{flavor.name}':'#{flavor.description}"])
log(:info, "Provisioning object updated {:instance_type => #{prov.get_option(:instance_type).inspect}}")
end
end
end
module ManageIQ
module Automate
module Cloud
module VM
module Provisioning
module StateMachines
module Methods
class AmazonCustomizeRequest
def initialize(handle = $evm)
@handle = handle
@mapping = false
end

if prov.get_option(:guest_access_key_pair).nil? && ws_values.has_key?(:guest_access_key_pair)
provider.key_pairs.each do |keypair|
if keypair.name == ws_values[:guest_access_key_pair]
prov.set_option(:guest_access_key_pair, [keypair.id,keypair.name])
log(:info, "Provisioning object updated {:guest_access_key_pair => #{prov.get_option(:guest_access_key_pair).inspect}}")
end
end
end
def main
log(:info, "Provision:<#{prov.id}> Request:<#{prov.miq_provision_request.id}> Type:<#{prov.type}>")
log(:info, "Template: #{template.name} Provider: #{provider.name} Vendor: #{template.vendor} Product: #{product}")
log(:info, "Processing Amazon customizations...", true)
process_customization if @mapping
log(:info, "Processing Amazon customizations...Complete", true)
end

if prov.get_option(:security_groups).blank? && ws_values.has_key?(:security_groups)
provider.security_groups.each do |securitygroup|
if securitygroup.name == ws_values[:security_groups]
prov.set_option(:security_groups, [securitygroup.id])
log(:info, "Provisioning object updated {:security_groups => #{prov.get_option(:security_groups).inspect}}")
end
end
end
private

if prov.get_option(:customization_template_id).nil?
customization_template_search_by_function = "#{prov.type}_#{prov.get_tags[:function]}" rescue nil
customization_template_search_by_template_name = template.name
customization_template_search_by_ws_values = ws_values[:customization_template] rescue nil
log(:info, "prov.eligible_customization_templates: #{prov.eligible_customization_templates.inspect}")
customization_template = nil

unless customization_template_search_by_function.nil?
# Search for customization templates enabled for Cloud-Init that equal MiqProvisionAmazon_prov.get_tags[:function]
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: #{customization_template_search_by_function}")
customization_template = prov.eligible_customization_templates.detect { |ct| ct.name.casecmp(customization_template_search_by_function)==0 }
end
end
unless customization_template_search_by_template_name.nil?
# Search for customization templates enabled for Cloud-Init that match the template/image name
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: #{customization_template_search_by_template_name}")
customization_template = prov.eligible_customization_templates.detect { |ct| ct.name.casecmp(customization_template_search_by_template_name)==0 }
end
end
unless customization_template_search_by_ws_values.nil?
# Search for customization templates enabled for Cloud-Init that match ws_values[:customization_template]
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: #{customization_template_search_by_ws_values}")
customization_template = prov.eligible_customization_templates.detect { |ct| ct.name.casecmp(customization_template_search_by_ws_values)==0 }
end
end
if customization_template.blank?
log(:warn, "Failed to find matching Customization Template", true)
else
log(:info, "Found Customization Template ID: #{customization_template.id} Name: #{customization_template.name} Description: #{customization_template.description}")
prov.set_customization_template(customization_template) rescue nil
log(:info, "Provisioning object updated {:customization_template_id => #{prov.get_option(:customization_template_id).inspect}}")
log(:info, "Provisioning object updated {:customization_template_script => #{prov.get_option(:customization_template_script).inspect}}")
end
else
log(:info, "Customization Template selected from dialog ID: #{prov.get_option(:customization_template_id).inspect}} Script: #{prov.get_option(:customization_template_script).inspect}")
end
end # case mapping
log(:info, "Processing Amazon customizations...Complete", true)
end
def prov
@prov ||= @handle.root["miq_provision"].tap do |req|
raise 'miq_provision not specified' if req.nil?
end
end

def log(level, msg, update_message=false)
$evm.log(level, "#{msg}")
$evm.root['miq_provision'].message = "#{msg}" if $evm.root['miq_provision'] && update_message
end
def template
@template ||= prov.vm_template.tap do |req|
raise 'vm_template not specified' if req.nil?
end
end

def provider
@provider ||= template.ext_management_system.tap do |ems|
raise 'ext_management_system not specified' if ems.nil?
end
end

def product
@product ||= template.operating_system&.product_name&.downcase
end

def ws_values
@ws_values ||= prov.options.fetch(:ws_values, {})
end

def process_customization
set_options
set_customization_template
end

def set_options
if prov.get_option(:instance_type).nil? && ws_values.key?(:instance_type)
provider.flavors.each do |flavor|
if flavor.name.downcase == ws_values[:instance_type].downcase
prov.set_option(:instance_type, [flavor.id, "#{flavor.name}':'#{flavor.description}"])
log(:info, "Provisioning object updated {:instance_type => #{prov.get_option(:instance_type).inspect}}")
end
end
end

# Get provisioning object
prov = $evm.root["miq_provision"]
if prov.get_option(:guest_access_key_pair).nil? && ws_values.key?(:guest_access_key_pair)
provider.key_pairs.each do |keypair|
if keypair.name == ws_values[:guest_access_key_pair]
prov.set_option(:guest_access_key_pair, [keypair.id, keypair.name])
log(:info, "Provisioning object updated {:guest_access_key_pair => #{prov.get_option(:guest_access_key_pair).inspect}}")
end
end
end

log(:info, "Provision:<#{prov.id}> Request:<#{prov.miq_provision_request.id}> Type:<#{prov.type}>")
if prov.get_option(:security_groups).blank? && ws_values.key?(:security_groups)
provider.security_groups.each do |securitygroup|
if securitygroup.name == ws_values[:security_groups]
prov.set_option(:security_groups, [securitygroup.id])
log(:info, "Provisioning object updated {:security_groups => #{prov.get_option(:security_groups).inspect}}")
end
end
end
end

template = prov.vm_template
provider = template.ext_management_system
product = template.operating_system['product_name'].downcase rescue nil
log(:info, "Template: #{template.name} Provider: #{provider.name} Vendor: #{template.vendor} Product: #{product}")
def set_customization_template
if prov.get_option(:customization_template_id).present?
log(:info, "Customization Template selected from dialog ID: %{id} Script: %{script}" % {
:id => prov.get_option(:customization_template_id).inspect,
:script => prov.get_option(:customization_template_script).inspect
})
return
end

customization_template_search_by_function = "#{prov.type}_#{prov.get_tags[:function]}"
customization_template_search_by_template_name = template.name
customization_template_search_by_ws_values = ws_values[:customization_template]
log(:info, "prov.eligible_customization_templates: #{prov.eligible_customization_templates.inspect}")
customization_template = nil

unless customization_template_search_by_function.nil?
# Search for customization templates enabled for Cloud-Init that equal MiqProvisionAmazon_prov.get_tags[:function]
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: %{function}" % {
:function => customization_template_search_by_function
})
customization_template = prov.eligible_customization_templates.detect do |ct|
ct.name.casecmp(customization_template_search_by_function) == 0
end
end
end
unless customization_template_search_by_template_name.nil?
# Search for customization templates enabled for Cloud-Init that match the template/image name
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: %{name}" % {
:name => customization_template_search_by_template_name
})
customization_template = prov.eligible_customization_templates.detect do |ct|
ct.name.casecmp(customization_template_search_by_template_name) == 0
end
end
end
unless customization_template_search_by_ws_values.nil?
# Search for customization templates enabled for Cloud-Init that match ws_values[:customization_template]
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: %{ws_value}" % {
:ws_value => customization_template_search_by_ws_values
})
customization_template = prov.eligible_customization_templates.detect do |ct|
ct.name.casecmp(customization_template_search_by_ws_values) == 0
end
end
end
if customization_template.blank?
log(:warn, "Failed to find matching Customization Template", true)
else
log(:info, "Found Customization Template ID: %{id} Name: %{name} Description: %{desc}" % {
:id => customization_template.id,
:name => customization_template.name,
:desc => customization_template.description
})
prov.set_customization_template(customization_template) rescue nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only one I'm not really sure about and may want to keep in this refactoring and address later.

log(:info, "Provisioning object updated {:customization_template_id => %{id}}" % {
:id => prov.get_option(:customization_template_id).inspect
})
log(:info, "Provisioning object updated {:customization_template_script => %{script}}" % {
:script => prov.get_option(:customization_template_script).inspect
})
end
end

def log(level, msg, update_message = false)
@handle.log(level, msg)
@handle.root['miq_provision'].message = msg if @handle.root['miq_provision'] && update_message
end
end
end
end
end
end
end
end
end

mapping = 0
process_customization(mapping, prov, template, product, provider)
ManageIQ::Automate::Cloud::VM::Provisioning::StateMachines::Methods::AmazonCustomizeRequest.new.main
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
require_domain_file

describe ManageIQ::Automate::Cloud::VM::Provisioning::StateMachines::Methods::AmazonCustomizeRequest do
let(:ems) { FactoryBot.create(:ems_amazon_with_authentication) }
let(:template) { FactoryBot.create(:miq_template, :ext_management_system => ems) }
let(:prov_req) { FactoryBot.create(:miq_provision_request, :options => {:src_vm_id => template.id}) }
let(:prov) { FactoryBot.create(:miq_provision, :miq_provision_request => prov_req, :options => {:src_vm_id => template.id}) }
let(:svc_prov) { MiqAeMethodService::MiqAeServiceMiqProvision.find(prov.id) }
let(:root_hash) { {'miq_provision' => svc_prov} }
let(:root_object) { Spec::Support::MiqAeMockObject.new(root_hash) }
let(:ae_service) do
Spec::Support::MiqAeMockService.new(root_object).tap do |service|
current_object = Spec::Support::MiqAeMockObject.new
current_object.parent = root_object
service.object = current_object
end
end

it "process customization without mapping" do
described_class.new(ae_service).main
expect(svc_prov.message).to eq("Processing Amazon customizations...Complete")
end

context 'customization with mapping' do
let(:customization_template) { FactoryBot.create(:customization_template) }

after(:each) { expect(svc_prov.message).to eq("Processing Amazon customizations...Complete") }

def options_with_template(ws_values)
ae_service.root["miq_provision"].options[:ws_values] = ws_values
ae_service.root["miq_provision"].options[:customization_template_id] = customization_template.id
ae_service.root["miq_provision"].options[:customization_template_script] = customization_template.script
end

context '#instance_type' do
let(:ems) { FactoryBot.create(:ems_amazon_with_authentication, :flavors => [flavor]) }
let(:flavor) { FactoryBot.create(:flavor, :description => 'desc') }

it "sets flavor as an instance_type" do
options_with_template(:instance_type => flavor.name)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
expect(svc_prov.options[:instance_type]).to eq([flavor.id, "#{flavor.name}':'#{flavor.description}"])
end
end

context '#guest_access_key_pair' do
let(:keypair) { FactoryBot.create(:auth_key_pair_cloud, :name => "test_auth_key_pair_cloud") }
let(:ems) { FactoryBot.create(:ems_amazon_with_authentication, :key_pairs => [keypair]) }

it "sets keypair as a guest_access_key_pair" do
options_with_template(:guest_access_key_pair => keypair.name)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
expect(svc_prov.options[:guest_access_key_pair]).to eq([keypair.id, keypair.name])
end
end

context '#security_groups' do
let(:sec_group) { FactoryBot.create(:security_group_amazon) }

it "sets security_groups for network_manager" do
options_with_template(:security_groups => sec_group.name)
ems.network_manager.security_groups = [sec_group]

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
expect(svc_prov.options[:security_groups]).to eq([sec_group.id])
end
end

context '#customization_templates' do
it "fails to find template" do
allow(ae_service.root["miq_provision"]).to receive(:eligible_customization_templates).and_return([])
expect(ae_service.root["miq_provision"]).not_to receive(:set_customization_template)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
end

it "finds a template by name" do
customization_template.name = template.name
allow(ae_service.root["miq_provision"]).to receive(:eligible_customization_templates).and_return([customization_template])
expect(ae_service.root["miq_provision"]).to receive(:set_customization_template).with(customization_template)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
end

it "finds a template by ws_values" do
ae_service.root["miq_provision"].options[:ws_values] = {:customization_template => customization_template.name}
allow(ae_service.root["miq_provision"]).to receive(:eligible_customization_templates).and_return([customization_template])
expect(ae_service.root["miq_provision"]).to receive(:set_customization_template).with(customization_template)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
end

it "finds a template by functions" do
customization_template.name = "#{svc_prov.type}_#{svc_prov.get_tags[:function]}"
allow(ae_service.root["miq_provision"]).to receive(:eligible_customization_templates).and_return([customization_template])
expect(ae_service.root["miq_provision"]).to receive(:set_customization_template).with(customization_template)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
end
end
end

it 'raises error for missing miq_provision' do
ae_service.root["miq_provision"] = nil
expect { described_class.new(ae_service).main }.to raise_error('miq_provision not specified')
end

it 'raises error for missing vm_template' do
allow(ae_service.root["miq_provision"]).to receive(:vm_template).and_return(nil)
expect { described_class.new(ae_service).main }.to raise_error('vm_template not specified')
end

it 'raises error for missing ext_management_system' do
allow_any_instance_of(MiqAeMethodService::MiqAeServiceMiqTemplate).to receive(:ext_management_system).and_return(nil)
expect { described_class.new(ae_service).main }.to raise_error('ext_management_system not specified')
end
end