Skip to content

Commit

Permalink
Add method to copy service templates
Browse files Browse the repository at this point in the history
  • Loading branch information
d-m-u committed Feb 18, 2019
1 parent dc10156 commit 185380b
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 4 deletions.
4 changes: 4 additions & 0 deletions app/models/configuration_script_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ class ConfigurationScriptBase < ApplicationRecord
scope :with_manager, ->(manager_id) { where(:manager_id => manager_id) }

include ProviderObjectMixin

def service_template_resource_copy
self
end
end
4 changes: 4 additions & 0 deletions app/models/ext_management_system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ def self.supported_subclasses
end
end

def service_template_resource_copy
self
end

def self.supported_types_and_descriptions_hash
supported_subclasses.each_with_object({}) do |klass, hash|
if Vmdb::PermissionStores.instance.supported_ems_type?(klass.ems_type)
Expand Down
4 changes: 4 additions & 0 deletions app/models/miq_provision_request_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ def request_task_class
MiqProvision
end

def service_template_resource_copy
dup.tap(&:save!)
end

def execute
# Should not be called.
raise _("Provision Request Templates do not support the execute method.")
Expand Down
4 changes: 4 additions & 0 deletions app/models/miq_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ def resource
self
end

def service_template_copy
self
end

def miq_request
self
end
Expand Down
4 changes: 4 additions & 0 deletions app/models/orchestration_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ def self.find_with_content(template_content)
where(:draft => false).find_by(:md5 => calc_md5(with_universal_newline(template_content)))
end

def service_template_resource_copy
self
end

# Find only by template content. Here we only compare md5 considering the table is expected
# to be small and the chance of md5 collision is minimal.
#
Expand Down
2 changes: 2 additions & 0 deletions app/models/service_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ class ServiceTemplate < ApplicationRecord
include ArchivedMixin
include CiFeatureMixin
include_concern 'Filter'
include_concern 'Copy'

validates :name, :presence => true
belongs_to :tenant
# # These relationships are used to specify children spawned from a parent service
# has_many :child_services, :class_name => "ServiceTemplate", :foreign_key => :service_template_id
Expand Down
17 changes: 17 additions & 0 deletions app/models/service_template/copy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module ServiceTemplate::Copy
extend ActiveSupport::Concern

def copy(new_name = "Copy of " + name + Time.zone.now.to_s)
if template_valid? && type != 'ServiceTemplateAnsiblePlaybook'
ActiveRecord::Base.transaction do
dup.tap do |template|
template.update_attributes(:name => new_name, :guid => nil)
service_resources.each do |sr|
template.add_resource(sr.resource_type.constantize.find(sr.resource_id).try(:service_template_resource_copy))
end
end.save!
# new_srs.each { |sr| sr.try(:service_template_copy) ? sr.service_template_copy : "Service Template copy not supported for #{sr.class}" }
end
end
end
end
16 changes: 12 additions & 4 deletions spec/factories/service_template.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
FactoryBot.define do
factory :service_template
factory :service_template_orchestration, :class => 'ServiceTemplateOrchestration', :parent => :service_template
factory :service_template_ansible_playbook, :class => 'ServiceTemplateAnsiblePlaybook', :parent => :service_template
factory :service_template_container_template, :class => 'ServiceTemplateContainerTemplate', :parent => :service_template
factory :service_template do
sequence(:name) { |n| "service_template_#{seq_padded_for_sorting(n)}" }
end
factory :service_template_orchestration, :class => 'ServiceTemplateOrchestration', :parent => :service_template do
sequence(:name) { |n| "service_template_#{seq_padded_for_sorting(n)}" }
end
factory :service_template_ansible_playbook, :class => 'ServiceTemplateAnsiblePlaybook', :parent => :service_template do
sequence(:name) { |n| "service_template_#{seq_padded_for_sorting(n)}" }
end
factory :service_template_container_template, :class => 'ServiceTemplateContainerTemplate', :parent => :service_template do
sequence(:name) { |n| "service_template_#{seq_padded_for_sorting(n)}" }
end
factory :service_template_transformation_plan, :class => 'ServiceTemplateTransformationPlan', :parent => :service_template do
sequence(:name) { |n| "service_template_#{seq_padded_for_sorting(n)}" }
end
Expand Down
109 changes: 109 additions & 0 deletions spec/models/service_template_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,115 @@
end
end

context "#copy" do
before do
@st1 = FactoryBot.create(:service_template)
end

context "with given name" do
it "without resource " do
expect(ServiceTemplate.count).to eq(1)
@st1.copy("drew")
expect(ServiceTemplate.count).to eq(2)
expect(ServiceTemplate.find_by(:name => "drew")).not_to be(nil)
expect(ServiceTemplate.find_by(:name => "drew").guid).not_to eq(@st1.guid)
end

it "with non-copyable resource (configuration script base)" do
@st1.add_resource(FactoryBot.create(:configuration_script_base))
expect(ServiceTemplate.count).to eq(1)
@st1.copy("thing")
expect(ServiceTemplate.count).to eq(2)
expect(ServiceTemplate.find_by(:name => "thing").service_resources.first.resource_id).to eq(@st1.service_resources.first.resource_id)
expect(ConfigurationScriptBase.count).to eq(1)
expect(ServiceTemplate.find_by(:name => "thing").guid).not_to eq(@st1.guid)
end

it "with non-copyable resource (ext management system)" do
@st1.add_resource(FactoryBot.create(:ext_management_system))
expect(ServiceTemplate.count).to eq(1)
@st1.copy("thing")
expect(ServiceTemplate.count).to eq(2)
expect(ServiceTemplate.find_by(:name => "thing").service_resources.first.resource_id).to eq(@st1.service_resources.first.resource_id)
expect(ExtManagementSystem.count).to eq(1)
expect(ServiceTemplate.find_by(:name => "thing").guid).not_to eq(@st1.guid)
end

it "with non-copyable resource (orchestration template)" do
@st1.add_resource(FactoryBot.create(:orchestration_template))
expect(ServiceTemplate.count).to eq(1)
@st1.copy("thing")
expect(ServiceTemplate.count).to eq(2)
expect(ServiceTemplate.find_by(:name => "thing").service_resources.first.resource_id).to eq(@st1.service_resources.first.resource_id)
expect(OrchestrationTemplate.count).to eq(1)
expect(ServiceTemplate.find_by(:name => "thing").guid).not_to eq(@st1.guid)
end

it "with copyable resource" do
admin = FactoryBot.create(:user_admin)
vm_template = FactoryBot.create(:vm_openstack, :ext_management_system => FactoryBot.create(:ext_management_system))
ptr = FactoryBot.create(:miq_provision_request_template, :requester => admin, :src_vm_id => vm_template.id)
@st1.add_resource(ptr)
expect(ServiceTemplate.count).to eq(1)
@st1.copy("thing1")
expect(ServiceTemplate.count).to eq(2)
expect(MiqProvisionRequestTemplate.count).to eq(2)
expect(ServiceTemplate.find_by(:name => "thing1").guid).not_to eq(@st1.guid)
end
end

context "without given name" do
it "without resource" do
expect(ServiceTemplate.count).to eq(1)
@st1.copy
expect(ServiceTemplate.count).to eq(2)
expect(ServiceTemplate.find_by("name ILIKE ?", "Copy of service%").guid).not_to eq(@st1.guid)
end

it "with non-copyable resource (configuration_script_base)" do
@st1.add_resource(FactoryBot.create(:configuration_script_base))
expect(ServiceTemplate.count).to eq(1)
@st1.copy
expect(ServiceTemplate.count).to eq(2)
expect(ServiceTemplate.where("name ILIKE ?", "Copy of service%").first.service_resources.first.resource_id).to eq(@st1.service_resources.first.resource_id)
expect(ConfigurationScriptBase.count).to eq(1)
expect(ServiceTemplate.find_by("name ILIKE ?", "Copy of service%").guid).not_to eq(@st1.guid)
end

it "with non-copyable resource (ext management system)" do
@st1.add_resource(FactoryBot.create(:ext_management_system))
expect(ServiceTemplate.count).to eq(1)
@st1.copy
expect(ServiceTemplate.count).to eq(2)
expect(ServiceTemplate.where("name ILIKE ?", "Copy of service%").first.service_resources.first.resource_id).to eq(@st1.service_resources.first.resource_id)
expect(ExtManagementSystem.count).to eq(1)
expect(ServiceTemplate.find_by("name ILIKE ?", "Copy of service%").guid).not_to eq(@st1.guid)
end

it "with non-copyable resource (orchestration template)" do
@st1.add_resource(FactoryBot.create(:orchestration_template))
expect(ServiceTemplate.count).to eq(1)
@st1.copy
expect(ServiceTemplate.count).to eq(2)
expect(ServiceTemplate.where("name ILIKE ?", "Copy of service%").first.service_resources.first.resource_id).to eq(@st1.service_resources.first.resource_id)
expect(OrchestrationTemplate.count).to eq(1)
expect(ServiceTemplate.find_by("name ILIKE ?", "Copy of service%").guid).not_to eq(@st1.guid)
end

it "with copyable resource" do
admin = FactoryBot.create(:user_admin)
vm_template = FactoryBot.create(:vm_openstack, :ext_management_system => FactoryBot.create(:ext_management_system))
ptr = FactoryBot.create(:miq_provision_request_template, :requester => admin, :src_vm_id => vm_template.id)
@st1.add_resource(ptr)
expect(ServiceTemplate.count).to eq(1)
@st1.copy
expect(ServiceTemplate.count).to eq(2)
expect(MiqProvisionRequestTemplate.count).to eq(2)
expect(ServiceTemplate.find_by("name ILIKE ?", "Copy of service%").guid).not_to eq(@st1.guid)
end
end
end

context "#composite?" do
before do
@st1 = FactoryBot.create(:service_template)
Expand Down

0 comments on commit 185380b

Please sign in to comment.