From b82c87a1f49f94afcc94570eb8db5f11c651b924 Mon Sep 17 00:00:00 2001 From: Greg McCullough Date: Tue, 25 Apr 2017 17:30:30 -0400 Subject: [PATCH] Merge pull request #14830 from syncrou/deux_1438839_create_or_delete_catalog_item_on_update Create or delete a catalog item on update (cherry picked from commit 258dd189206418143b9f948bbc93aefac972ee66) https://bugzilla.redhat.com/show_bug.cgi?id=1445894 https://bugzilla.redhat.com/show_bug.cgi?id=1445942 --- .../service_template_ansible_playbook.rb | 81 ++++++++++++++----- .../service_template_ansible_playbook_spec.rb | 30 ++++++- 2 files changed, 87 insertions(+), 24 deletions(-) diff --git a/app/models/service_template_ansible_playbook.rb b/app/models/service_template_ansible_playbook.rb index ede59eda5a0..0ca6f6bced6 100644 --- a/app/models/service_template_ansible_playbook.rb +++ b/app/models/service_template_ansible_playbook.rb @@ -1,6 +1,6 @@ class ServiceTemplateAnsiblePlaybook < ServiceTemplateGeneric before_destroy :check_retirement_potential, :prepend => true - around_destroy :around_destroy_callback + around_destroy :around_destroy_callback, :prepend => true RETIREMENT_ENTRY_POINTS = { 'yes_without_playbook' => '/Service/Generic/StateMachines/GenericLifecycle/Retire_Basic_Resource', @@ -19,7 +19,6 @@ def self.default_retirement_entry_point RETIREMENT_ENTRY_POINTS['yes_without_playbook'] end - # create ServiceTemplate and supporting ServiceResources and ResourceActions # options # :name @@ -69,14 +68,19 @@ def create_new_dialog(dialog_name, job_template, hosts) end private :create_new_dialog - def self.create_job_templates(service_name, description, config_info, auth_user) + def self.create_job_templates(service_name, description, config_info, auth_user, service_template = nil) [:provision, :retirement, :reconfigure].each_with_object({}) do |action, hash| - next unless config_info[action] && config_info[action].key?(:playbook_id) - hash[action] = { :configuration_template => create_job_template("miq_#{service_name}_#{action}", description, config_info[action], auth_user) } + next unless new_job_template_required?(config_info[action], action, service_template) + hash[action] = { :configuration_template => create_job_template(build_name(service_name, action), description, config_info[action], auth_user) } end end private_class_method :create_job_templates + def self.build_name(basic_name, action) + "miq_#{basic_name}_#{action}" + end + private_class_method :build_name + def self.create_job_template(name, description, info, auth_user) tower, params = build_parameter_list(name, description, info) @@ -133,31 +137,23 @@ def self.validate_config_info(info) end private_class_method :validate_config_info - def validate_update_config_info(options) - opts = super - self.class.send(:validate_config_info, opts) - end def job_template(action) - resource_actions.find_by!(:action => action.to_s.capitalize).configuration_template + resource_actions.find_by(:action => action.to_s.capitalize).try(:configuration_template) end def update_catalog_item(options, auth_user = nil) config_info = validate_update_config_info(options) - name = options[:name] - description = options[:description] - [:provision, :retirement, :reconfigure].each do |action| - next unless config_info[action] - info = config_info[action] + name = options[:name] || name + description = options[:description] || description - new_dialog = create_new_dialog(info[:new_dialog_name], job_template(action), info[:hosts]) if info[:new_dialog_name] - config_info[action][:dialog_id] = new_dialog.id if new_dialog + update_job_templates(name, description, config_info, auth_user) + + updated_config = config_info.deep_merge(self.class.send(:create_job_templates, name, description, config_info, auth_user, self)) + + create_dialogs(updated_config) + options[:config_info] = updated_config - next unless info.key?(:playbook_id) - tower, params = self.class.send(:build_parameter_list, "miq_#{name}_#{action}", description, info) - params[:manager_ref] = job_template(action).manager_ref - ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ConfigurationScript.update_in_provider_queue(tower.id, params, auth_user) - end super end @@ -187,6 +183,15 @@ def check_retirement_potential throw :abort end + def create_dialogs(config_info) + [:provision, :retirement, :reconfigure].each do |action| + info = config_info[action] + if new_dialog_required?(info) + info[:dialog_id] = create_new_dialog(info[:new_dialog_name], job_template(action), info[:hosts]).id + end + end + end + def delete_job_templates(job_templates) auth_user = User.current_userid || 'system' job_templates.each do |job_template| @@ -194,4 +199,36 @@ def delete_job_templates(job_templates) .delete_in_provider_queue(job_template.manager.id, { :manager_ref => job_template.manager_ref }, auth_user) end end + + def new_dialog_required?(info) + info && info.key?(:new_dialog_name) + end + + def self.new_job_template_required?(info, action, service_template) + return info && info.key?(:playbook_id) if service_template.nil? + info && info.key?(:playbook_id) && service_template.job_template(action).nil? + end + private_class_method :new_job_template_required? + + def update_job_templates(name, description, config_info, auth_user) + [:provision, :retirement, :reconfigure].each do |action| + info = config_info[action] + next unless info + + job_template = job_template(action) + next unless job_template + if info.key?(:playbook_id) + tower, params = self.class.send(:build_parameter_list, self.class.send(:build_name, name, action), description, info) + params[:manager_ref] = job_template(action).manager_ref + ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ConfigurationScript.update_in_provider_queue(tower.id, params, auth_user) + else + delete_job_templates([job_template]) + end + end + end + + def validate_update_config_info(options) + opts = super + self.class.send(:validate_config_info, opts) + end end diff --git a/spec/models/service_template_ansible_playbook_spec.rb b/spec/models/service_template_ansible_playbook_spec.rb index c1e36a33587..8ac770997ff 100644 --- a/spec/models/service_template_ansible_playbook_spec.rb +++ b/spec/models/service_template_ansible_playbook_spec.rb @@ -201,8 +201,9 @@ end describe '#update_catalog_item' do + let(:service_template) { prebuild_service_template } + it 'updates and returns the modified catalog item' do - service_template = prebuild_service_template new_dialog_label = catalog_item_options_three .fetch_path(:config_info, :provision, :new_dialog_name) expect(Dialog.where(:label => new_dialog_label)).to be_empty @@ -221,7 +222,6 @@ end it 'uses the existing dialog if :service_dialog_id is passed in' do - service_template = prebuild_service_template info = catalog_item_options_three.fetch_path(:config_info, :provision) info.delete(:new_dialog_name) info[:service_dialog_id] = service_template.dialogs.first.id @@ -237,6 +237,32 @@ end end + describe '#update_job_templates' do + let(:service_template) { prebuild_service_template(:job_template => false) } + + it 'does not update a job_template if the there is no playbook_id' do + expect(ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ConfigurationScript) + .to receive(:update_in_provider_queue).never + service_template.send(:update_job_templates, 'blah', 'blah', catalog_item_options, user) + end + + it 'does update a job_template if a playbook_id is included' do + expect(ManageIQ::Providers::EmbeddedAnsible::AutomationManager::ConfigurationScript) + .to receive(:update_in_provider_queue) + service_template.send(:update_job_templates, 'blah', 'blah', catalog_item_options[:config_info], user) + end + + it 'deletes a job_template if a playbook id is not passed in' do + [:provision, :retirement, :reconfigure].each do |action| + next unless catalog_item_options[:config_info][action] + catalog_item_options[:config_info][action].delete(:playbook_id) + end + expect(service_template).to receive(:delete_job_templates) + + service_template.send(:update_job_templates, 'blah', 'blah', catalog_item_options[:config_info], user) + end + end + describe '#delete_job_templates' do let(:service) { FactoryGirl.create(:service_ansible_tower) }