From 6507cfde4e7f57660ddf8266d27c38d84cedeea0 Mon Sep 17 00:00:00 2001 From: Lucy Fu Date: Thu, 8 Jun 2017 16:35:50 -0400 Subject: [PATCH] Add ServiceTemplateContainerTemplate. --- app/models/service_template.rb | 23 ++--- .../service_template_container_template.rb | 86 +++++++++++++++++++ spec/factories/service_template.rb | 2 + ...ervice_template_container_template_spec.rb | 84 ++++++++++++++++++ 4 files changed, 184 insertions(+), 11 deletions(-) create mode 100644 app/models/service_template_container_template.rb create mode 100644 spec/models/service_template_container_template_spec.rb diff --git a/app/models/service_template.rb b/app/models/service_template.rb index 082a829f63b..9ff8e3b0334 100644 --- a/app/models/service_template.rb +++ b/app/models/service_template.rb @@ -11,17 +11,18 @@ class ServiceTemplate < ApplicationRecord }.freeze CATALOG_ITEM_TYPES = { - "amazon" => _("Amazon"), - "azure" => _("Azure"), - "generic" => _("Generic"), - "generic_orchestration" => _("Orchestration"), - "generic_ansible_playbook" => _("Ansible Playbook"), - "generic_ansible_tower" => _("AnsibleTower"), - "google" => _("Google"), - "microsoft" => _("SCVMM"), - "openstack" => _("OpenStack"), - "redhat" => _("RHEV"), - "vmware" => _("VMware") + "amazon" => _("Amazon"), + "azure" => _("Azure"), + "generic" => _("Generic"), + "generic_orchestration" => _("Orchestration"), + "generic_ansible_playbook" => _("Ansible Playbook"), + "generic_ansible_tower" => _("AnsibleTower"), + "generic_container_template" => _("Container Template"), + "google" => _("Google"), + "microsoft" => _("SCVMM"), + "openstack" => _("OpenStack"), + "redhat" => _("RHEV"), + "vmware" => _("VMware") }.freeze RESOURCE_ACTION_UPDATE_ATTRS = [:dialog, diff --git a/app/models/service_template_container_template.rb b/app/models/service_template_container_template.rb new file mode 100644 index 00000000000..448e4f74110 --- /dev/null +++ b/app/models/service_template_container_template.rb @@ -0,0 +1,86 @@ +class ServiceTemplateContainerTemplate < ServiceTemplateGeneric + def self.default_provisioning_entry_point(_service_type) + '/Service/Generic/StateMachines/GenericLifecycle/provision' + end + + def self.default_retirement_entry_point + nil + end + + # create ServiceTemplate and supporting ServiceResources and ResourceActions + # options + # :name + # :description + # :service_template_catalog_id + # :config_info + # :provision + # :dialog_id or :dialog + # :container_template_id or :container_template + # + def self.create_catalog_item(options) + options = options.merge(:service_type => 'atomic', :prov_type => 'generic_container_template') + config_info = validate_config_info(options[:config_info]) + enhanced_config = config_info.deep_merge( + :provision => { + :configuration_template => container_template_from_config_info(config_info) + } + ) + + transaction do + create_from_options(options).tap do |service_template| + service_template.create_resource_actions(enhanced_config) + end + end + end + + def self.validate_config_info(info) + info[:provision][:fqname] ||= default_provisioning_entry_point('atomic') if info.key?(:provision) + + # TODO: Add more validation for required fields + info + end + private_class_method :validate_config_info + + def self.container_template_from_config_info(info) + template_id = info[:provision][:container_template_id] + template_id ? ContainerTemplate.find(template_id) : info[:provision][:container_template] + end + private_class_method :container_template_from_config_info + + def container_template + resource_actions.find_by(:action => "Provision").try(:configuration_template) + end + + def container_manager + container_template.try(:ext_management_system) + end + + def update_catalog_item(options) + config_info = validate_update_config_info(options) + config_info[:provision][:configuration_template] ||= container_template_from_config_info(config_info) if config_info.key?(:provision) + + options[:config_info] = config_info + + super + end + + private + + def container_template_from_config_info(info) + self.class.send(:container_template_from_config_info, info) + end + + def validate_update_config_info(options) + opts = super + self.class.send(:validate_config_info, opts) + end + + def update_service_resources(_config_info, _auth_user = nil) + # do nothing since no service resources for this template + end + + def update_from_options(params) + options[:config_info] = Hash[params[:config_info].collect { |k, v| [k, v.except(:configuration_template)] }] + update_attributes!(params.except(:config_info)) + end +end diff --git a/spec/factories/service_template.rb b/spec/factories/service_template.rb index 97c5dc26c75..2d0d11a6f5b 100644 --- a/spec/factories/service_template.rb +++ b/spec/factories/service_template.rb @@ -6,4 +6,6 @@ end factory :service_template_ansible_playbook, :class => 'ServiceTemplateAnsiblePlaybook', :parent => :service_template + + factory :service_template_container_template, :class => 'ServiceTemplateContainerTemplate', :parent => :service_template end diff --git a/spec/models/service_template_container_template_spec.rb b/spec/models/service_template_container_template_spec.rb new file mode 100644 index 00000000000..2e8351737f0 --- /dev/null +++ b/spec/models/service_template_container_template_spec.rb @@ -0,0 +1,84 @@ +describe ServiceTemplateContainerTemplate do + let(:service_template_catalog) { FactoryGirl.create(:service_template_catalog) } + let(:container_template) { FactoryGirl.create(:container_template, :ems_id => ems.id) } + let(:ems) { FactoryGirl.create(:ems_openshift) } + let(:dialog) { FactoryGirl.create(:dialog) } + let(:dialog2) { FactoryGirl.create(:dialog) } + + let(:catalog_item_options) do + { + :name => 'container_template_catalog_item', + :description => 'test container template', + :service_template_catalog_id => service_template_catalog.id, + :display => true, + :config_info => { + :provision => { + :dialog_id => dialog.id, + :container_template_id => container_template.id + }, + } + } + end + + let(:catalog_item_options_2) do + changed_items = { + :name => 'test_update_item', + :description => 'test updated container template item', + :config_info => { + :provision => { + :dialog_id => dialog2.id + } + } + } + catalog_item_options.deep_merge(changed_items) + end + + describe '.create_catalog_item' do + it 'creates and returns a catalog item' do + service_template = described_class.create_catalog_item(catalog_item_options) + + expect(service_template.name).to eq(catalog_item_options[:name]) + expect(service_template.config_info[:provision]).to include(catalog_item_options[:config_info][:provision]) + expect(service_template.container_template).to eq(container_template) + expect(service_template.resource_actions.first).to have_attributes( + :action => 'Provision', + :fqname => described_class.default_provisioning_entry_point('atomic'), + :configuration_template => container_template, + :dialog_id => dialog.id + ) + + saved_options = catalog_item_options[:config_info] + expect(service_template.options[:config_info]).to include(saved_options) + end + end + + describe '.validate_config_info' do + context 'provisioning entry point is given' do + it 'keeps the given entry point' do + opts = described_class.send(:validate_config_info, :provision => {:fqname => 'a/b/c'}) + expect(opts[:provision][:fqname]).to eq('a/b/c') + end + end + + context 'provisioning entry point is not given' do + it 'sets the default entry point' do + opts = described_class.send(:validate_config_info, :provision => {}) + expect(opts[:provision][:fqname]).to eq(described_class.default_provisioning_entry_point('atomic')) + end + end + end + + describe '#update_catalog_item' do + subject(:service_template) { described_class.create_catalog_item(catalog_item_options) } + + it 'updates and returns the modified catalog item' do + service_template.update_catalog_item(catalog_item_options_2) + + expect(service_template.name).to eq(catalog_item_options_2[:name]) + expect(service_template.description).to eq(catalog_item_options_2[:description]) + expect(service_template.dialogs.first.id).to eq(dialog2.id) + expect(service_template.options[:config_info][:provision]).not_to have_key(:configuration_template) + expect(service_template.options[:config_info][:provision][:dialog_id]).to eq(dialog2.id) + end + end +end