diff --git a/db/migrate/20181010134649_add_evm_owner_to_orchestration_stacks.rb b/db/migrate/20181010134649_add_evm_owner_to_orchestration_stacks.rb new file mode 100644 index 000000000..d9c6f1aff --- /dev/null +++ b/db/migrate/20181010134649_add_evm_owner_to_orchestration_stacks.rb @@ -0,0 +1,7 @@ +class AddEvmOwnerToOrchestrationStacks < ActiveRecord::Migration[5.0] + def change + add_reference :orchestration_stacks, :evm_owner, :type => :bigint, :index => true + add_reference :orchestration_stacks, :miq_group, :type => :bigint, :index => true + add_reference :orchestration_stacks, :tenant, :type => :bigint, :index => true + end +end diff --git a/db/migrate/20181016140921_migrate_orch_stacks_to_have_ownership_concept.rb b/db/migrate/20181016140921_migrate_orch_stacks_to_have_ownership_concept.rb new file mode 100644 index 000000000..c3728cdc1 --- /dev/null +++ b/db/migrate/20181016140921_migrate_orch_stacks_to_have_ownership_concept.rb @@ -0,0 +1,131 @@ +class MigrateOrchStacksToHaveOwnershipConcept < ActiveRecord::Migration[5.0] + class ExtManagementSystem < ActiveRecord::Base + self.inheritance_column = :_type_disabled # disable STI + + belongs_to :tenant, :class_name => "MigrateOrchStacksToHaveOwnershipConcept::Tenant" + + def tenant_identity + User.super_admin.tap { |u| u.current_group = tenant.default_miq_group } + end + end + + class Service < ActiveRecord::Base + self.inheritance_column = :_type_disabled # disable STI + + belongs_to :evm_owner, :class_name => "MigrateOrchStacksToHaveOwnershipConcept::User" + + def root + ancestry.present? ? self.class.find(ancestry.split("/").first) : self + end + alias root_service root + + def tenant_identity + user = evm_owner + if user.nil? || !user.miq_group_ids.include?(miq_group_id) + user = User.super_admin.tap { |u| u.current_group_id = miq_group_id } + end + user + end + end + + class MiqGroup < ActiveRecord::Base + TENANT_GROUP = "tenant".freeze + self.inheritance_column = :_type_disabled # disable STI + + belongs_to :tenant, :class_name => "MigrateOrchStacksToHaveOwnershipConcept::Tenant" + has_one :miq_user_role, :class_name => "MigrateOrchStacksToHaveOwnershipConcept::MiqUserRole" + + def self.create_tenant_group(tenant) + create_with( + :description => "Tenant access", + :default_tenant_role => MiqUserRole.default_tenant_role + ).find_or_create_by!( + :group_type => TENANT_GROUP, + :tenant_id => tenant.id, + ) + end + end + + class MiqUserRole < ActiveRecord::Base + DEFAULT_TENANT_ROLE_NAME = "EvmRole-tenant_administrator".freeze + self.inheritance_column = :_type_disabled # disable STI + + def self.default_tenant_role + find_by(:name => DEFAULT_TENANT_ROLE_NAME) + end + end + + class User < ActiveRecord::Base + self.inheritance_column = :_type_disabled # disable STI + + has_and_belongs_to_many :miq_groups, :class_name => "MigrateOrchStacksToHaveOwnershipConcept::MiqGroup" + belongs_to :current_group, :class_name => "MigrateOrchStacksToHaveOwnershipConcept::MiqGroup" + + include ActiveRecord::IdRegions + + def self.super_admin + in_my_region.find_by(:userid => "admin") + end + + def current_tenant + current_group.tenant + end + end + + class ServiceResource < ActiveRecord::Base + self.inheritance_column = :_type_disabled # disable STI + + belongs_to :service, :class_name => "MigrateOrchStacksToHaveOwnershipConcept::Service" + end + + class Tenant < ActiveRecord::Base + self.inheritance_column = :_type_disabled # disable STI + + belongs_to :default_miq_group, :class_name => "MigrateOrchStacksToHaveOwnershipConcept::MiqGroup", :dependent => :destroy + after_create :create_tenant_group + + def create_tenant_group + update_attributes!(:default_miq_group => MiqGroup.create_tenant_group(self)) unless default_miq_group_id + self + end + end + + class OrchestrationStack < ActiveRecord::Base + self.inheritance_column = :_type_disabled # disable STI + + has_many :service_resources, :as => :resource, :class_name => "MigrateOrchStacksToHaveOwnershipConcept::ServiceResource" + has_many :direct_services, :through => :service_resources, :source => :service + belongs_to :ext_management_system, :foreign_key => :ems_id + + def root + ancestry.present? ? self.class.find(ancestry.split("/").first) : self + end + + def direct_service + direct_services.first || (root.direct_services.first if root != self) + end + + def service + direct_service.try(:root_service) || (root.direct_service.try(:root_service) if root != self) + end + end + + def up + say_with_time("Migrating existing orchestration stacks to have direct owners, groups, tenant") do + OrchestrationStack.find_each do |stack| + user = if stack.service.present? + stack.service.tenant_identity + elsif !stack.ems_id.nil? + stack.ext_management_system.tenant_identity + else + User.super_admin + end + stack.update_attributes(:evm_owner_id => user.id, :tenant_id => user.current_tenant.id, :miq_group_id => user.current_group.id) + end + end + end + + def down + # blank because the down migration on AddEvmOwnerToOrchestrationStacks covers this + end +end diff --git a/spec/migrations/20181016140921_migrate_orch_stacks_to_have_ownership_concept_spec.rb b/spec/migrations/20181016140921_migrate_orch_stacks_to_have_ownership_concept_spec.rb new file mode 100644 index 000000000..c4bd3fd3b --- /dev/null +++ b/spec/migrations/20181016140921_migrate_orch_stacks_to_have_ownership_concept_spec.rb @@ -0,0 +1,56 @@ +require_migration + +describe MigrateOrchStacksToHaveOwnershipConcept do + let(:orchestration_stack) { migration_stub(:OrchestrationStack) } + let(:ems) { migration_stub(:ExtManagementSystem) } + let(:service) { migration_stub(:Service) } + let(:tenant) { migration_stub(:Tenant).create! } + let(:group) { migration_stub(:MiqGroup).create!(:tenant => tenant) } + let!(:user) { migration_stub(:User).create!(:userid => "admin", :miq_groups => [group], :current_group => group) } + + migration_context :up do + it "sets owner, tenant, and group from the user if neither the ems and service exist" do + stack = orchestration_stack.create!(:ext_management_system => nil) + expect(orchestration_stack.count).to eq(1) + + migrate + stack.reload + + expect(stack).to have_attributes(:tenant_id => user.current_tenant.id, :evm_owner_id => user.id, :miq_group_id => user.current_group.id) + end + + it "sets owner, tenant, and group from the ems if the ems exists and the service doesn't" do + ext_ms = ems.create!(:tenant => tenant) + stack = orchestration_stack.create!(:ext_management_system => ext_ms) + expect(orchestration_stack.count).to eq(1) + + migrate + stack.reload + + expect(stack).to have_attributes(:tenant_id => ext_ms.tenant_id, :evm_owner_id => ext_ms.tenant_identity.id, :miq_group_id => ext_ms.tenant_identity.current_group.id) + end + + it "sets owner, tenant, and group from the service if the service exists and ems doesn't" do + svc = service.create!(:tenant_id => tenant.id, :miq_group_id => group.id) + stack = orchestration_stack.create!(:direct_services => [svc]) + expect(orchestration_stack.count).to eq(1) + + migrate + stack.reload + + expect(stack).to have_attributes(:tenant_id => svc.tenant_id, :evm_owner_id => svc.tenant_identity.id, :miq_group_id => svc.tenant_identity.current_group.id) + end + + it "sets owner, tenant, and group from the service if the service and ems exists" do + ext_ms = ems.create!(:tenant => tenant) + svc = service.create!(:tenant_id => tenant.id, :miq_group_id => group.id) + stack = orchestration_stack.create!(:direct_services => [svc], :ext_management_system => ext_ms) + expect(orchestration_stack.count).to eq(1) + + migrate + stack.reload + + expect(stack).to have_attributes(:tenant_id => svc.tenant_id, :evm_owner_id => svc.tenant_identity.id, :miq_group_id => svc.tenant_identity.current_group.id) + end + end +end