diff --git a/spec/models/manageiq/providers/cloud_manager_spec.rb b/spec/models/manageiq/providers/cloud_manager_spec.rb index 78818b0bbf58..c7d2cace8b93 100644 --- a/spec/models/manageiq/providers/cloud_manager_spec.rb +++ b/spec/models/manageiq/providers/cloud_manager_spec.rb @@ -278,6 +278,454 @@ def expect_created_tenant_tree expect(ems_cloud.source_tenant).to eq(tenant.parent) end end + + context "provider's user is changed between two synchronizations" do + let!(:vm_1) { FactoryGirl.create(:vm_openstack) } + let!(:vm_2) { FactoryGirl.create(:vm_openstack) } + let(:ct_name_1) { "c_t_1"} + let(:ct_name_2) { "c_t_2"} + let(:ct_name_3) { "c_t_3"} + let(:provider_tenant) { Tenant.root_tenant.children.first } + + def tenant_from_cloud_tenant_by(vm) + Tenant.find_by(:name => vm.cloud_tenant.name) + end + + let(:ct_3) do + FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :name => ct_name_3) + end + + before(:each) do + vm_1.cloud_tenant.update_attributes!(:parent => ct_3, :ext_management_system => ems_cloud, :name => ct_name_1) + vm_2.cloud_tenant.update_attributes!(:ext_management_system => ems_cloud, :name => ct_name_2) + end + + ###### + # ct - Cloud Tenant, t - Tenant + # ===== + # CloudTenant tree: + # ct_3 -> ct_1 (vm_1s) + # ct_2 + # + # Expected Tenant tree: + # My Company t + # -> Provider Tenant + # -> t_3 (ct_3's) -> t_1 + # -> t_2 (ct_2's) + ####### + it 'creates tenant tree from cloud tenants with VMs' do + ems_cloud.sync_cloud_tenants_with_tenants + + t_1_ct_vm_1 = tenant_from_cloud_tenant_by(vm_1) + expect(t_1_ct_vm_1.id).to eq(ct_1.source_tenant.id) + expect(t_1_ct_vm_1.parent.id).to eq(ct_3.source_tenant.id) + expect(t_1_ct_vm_1.children.first).to be_nil + expect(t_1_ct_vm_1.source_id).to eq(ct_1.id) + expect(t_1_ct_vm_1.source_type).to eq("CloudTenant") + + t_2_ct_vm_2 = tenant_from_cloud_tenant_by(vm_2) + expect(t_2_ct_vm_2.id).to eq(ct_2.source_tenant.id) + expect(t_2_ct_vm_2.parent.id).to eq(provider_tenant.id) + expect(t_2_ct_vm_2.children.first).to be_nil + expect(t_2_ct_vm_2.source_id).to eq(ct_2.id) + expect(t_2_ct_vm_2.source_type).to eq("CloudTenant") + + t_3_ct_3 = Tenant.find_by(:name => ct_name_3) + expect(t_3_ct_3.id).to eq(ct_3.source_tenant.id) + expect(t_3_ct_3.parent.id).to eq(provider_tenant.id) + expect(t_3_ct_3.children.first.id).to eq(ct_1.source_tenant.id) + expect(t_3_ct_3.source_id).to eq(ct_3.id) + expect(t_3_ct_3.source_type).to eq("CloudTenant") + + expect(t1_ct_vm_1.parent.id).to eq(ct_3.source_tenant.id) + expect(Tenant.find_by(:name => ct_3.name).id).to eq(ct_3.source_tenant.id) + + expect(Tenant.root_tenant.children.first.id).to eq(ct_3.source_tenant.parent.id) + end + + context "when the new user has cloud tenants with same names than previous provider's user" do + ###### + # ct - Cloud Tenant, t - Tenant + # ===== + # CloudTenant tree: + # ct_3 -> ct_1 (vm_1s) + # ct_2 + # + # first tenant synchronization + # + # Expected Tenant tree: + # My Company t + # -> Provider Tenant + # -> t_3 (ct_3's) -> t_1 + # -> t_2 (ct_2's) + # + ### after changed user with different set of cloud tenants + ### second synchronization + # ===== + # CloudTenant tree: + # new_ct_3(same name) -> new_ct_1 (vm_1s) -> new_ct_4(vm_4's cloud_tenant)) + # new_ct_2 + # + # second tenant synchronization + # + # Expected Tenant tree: + # My Company t + # -> Provider Tenant + # -> t_3 (new_ct_3's) -> t_1(new_ct_1's) + # -> t_2 (new_ct_2's) + ###### + let(:ct_1_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :parent => ct_3_new, :name => ct_name_1) } + let(:ct_2_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :name => ct_name_2) } + let(:ct_3_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :name => ct_name_3) } + + it "creates tenant tree from cloud tenants with correct source_tenant relations" do + expect(CloudTenant.count).to eq(3) + ems_cloud.sync_cloud_tenants_with_tenants + expect(Tenant.count).to eq(5) + + tenant_ids = Tenant.ids + old_cloud_tenant_ids = CloudTenant.ids + + # destroy old cloud tenants and replace them with new + vm_1.cloud_tenant.destroy + vm_1.update_attributes!(:cloud_tenant => ct_1_new) + vm_2.cloud_tenant.destroy + vm_2.update_attributes!(:cloud_tenant => ct_2_new) + ct_3.destroy + + expect(CloudTenant.count).to eq(3) + expect(CloudTenant.ids).not_to match_array(old_cloud_tenant_ids) + + ems_cloud.sync_cloud_tenants_with_tenants + expect(Tenant.ids).to match_array(tenant_ids) + + t_1_ct_vm_1 = tenant_from_cloud_tenant_by(vm_1) + expect(t_1_ct_vm_1.id).to eq(ct_1_new.source_tenant.id) + expect(t_1_ct_vm_1.parent.id).to eq(ct_3_new.source_tenant.id) + expect(t_1_ct_vm_1.children.first).to be_nil + expect(t_1_ct_vm_1.source_id).to eq(ct_1_new.id) + expect(t_1_ct_vm_1.source_type).to eq("CloudTenant") + + t_2_ct_vm_2 = tenant_from_cloud_tenant_by(vm_2) + expect(t_2_ct_vm_2.id).to eq(ct_2_new.source_tenant.id) + expect(t_2_ct_vm_2.parent.id).to eq(provider_tenant.id) + expect(t_2_ct_vm_2.children.first).to be_nil + expect(t_2_ct_vm_2.source_id).to eq(ct_2_new.id) + expect(t_2_ct_vm_2.source_type).to eq("CloudTenant") + + t_3_ct_3 = Tenant.find_by(:name => ct_name_3) + expect(t_3_ct_3.id).to eq(ct_3_new.source_tenant.id) + expect(t_3_ct_3.parent.id).to eq(provider_tenant.id) + expect(t_3_ct_3.children.first.id).to eq(ct_1_new.source_tenant.id) + expect(t_3_ct_3.source_id).to eq(ct_3_new.id) + expect(t_3_ct_3.source_type).to eq("CloudTenant") + + expect(t_1_ct_vm_1.parent.id).to eq(ct_3_new.source_tenant.id) + expect(Tenant.find_by(:name => ct_3_new.name).id).to eq(ct_3_new.source_tenant.id) + + expect(Tenant.root_tenant.children.first.id).to eq(ct_3_new.source_tenant.parent.id) + expect(Tenant.count).to eq(5) + end + end + + context "when the new user has cloud tenants with different names than previous provider's user" do + ###### + # ct - Cloud Tenant, t - Tenant + # ===== + # CloudTenant tree: + # ct_3 -> ct_1 (vm_1s) + # ct_2 + # + # first tenant synchronization + # + # Expected Tenant tree: + # My Company t + # -> Provider Tenant + # -> t_3 (ct_3's) -> t_1 + # -> t_2 (ct_2's) + # + ### after changed user with different set of cloud tenants + ### second synchronization + # ===== + # CloudTenant tree: + # new_ct_3(same name) -> new_ct_1 (vm_1s) + # new_ct_2 + # + # second tenant synchronization + # + # Expected Tenant tree: + # My Company t + # -> Provider Tenant + # -> new_t_3 (new_ct_3's) -> new_t_1(new_ct_1's) + # -> new_t_2 (new_ct_2's) + # -> t_1(old - moved out) + # -> t_2(old - moved out) + # -> t_3(old - moved out) + ###### + let(:ct_1_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :parent => ct_3_new, :name => ct_name_1 + "X") } + let(:ct_2_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :name => ct_name_2 + "X") } + let(:ct_3_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :name => ct_name_3 + "X") } + + it "creates tenant tree from cloud tenants with correct source_tenant relations" do + expect(CloudTenant.count).to eq(3) + ems_cloud.sync_cloud_tenants_with_tenants + expect(Tenant.count).to eq(5) + + old_cloud_tenant_ids = CloudTenant.ids + + # destroy old cloud tenants and replace them with new + vm_1.cloud_tenant.destroy + vm_1.update_attributes!(:cloud_tenant => ct_1_new) + vm_2.cloud_tenant.destroy + vm_2.update_attributes!(:cloud_tenant => ct_2_new) + ct_3.destroy + + expect(CloudTenant.count).to eq(3) + expect(CloudTenant.ids).not_to match_array(old_cloud_tenant_ids) + + ems_cloud.sync_cloud_tenants_with_tenants + + t_1_ct_vm_1 = tenant_from_cloud_tenant_by(vm_1) + expect(t_1_ct_vm_1.id).to eq(ct_1_new.source_tenant.id) + expect(t_1_ct_vm_1.parent.id).to eq(ct_3_new.source_tenant.id) + expect(t_1_ct_vm_1.children.first).to be_nil + expect(t_1_ct_vm_1.source_id).to eq(ct_1_new.id) + expect(t_1_ct_vm_1.source_type).to eq("CloudTenant") + + t_2_ct_vm_2 = tenant_from_cloud_tenant_by(vm_2) + expect(t_2_ct_vm_2.id).to eq(ct_2_new.source_tenant.id) + expect(t_2_ct_vm_2.parent.id).to eq(provider_tenant.id) + expect(t_2_ct_vm_2.children.first).to be_nil + expect(t_2_ct_vm_2.source_id).to eq(ct_2_new.id) + expect(t_2_ct_vm_2.source_type).to eq("CloudTenant") + + t_3_ct_3 = Tenant.find_by(:name => ct_name_3 + "X") + expect(t_3_ct_3.id).to eq(ct_3_new.source_tenant.id) + expect(t_3_ct_3.parent.id).to eq(provider_tenant.id) + expect(t_3_ct_3.children.first.id).to eq(ct_1_new.source_tenant.id) + expect(t_3_ct_3.source_id).to eq(ct_3_new.id) + expect(t_3_ct_3.source_type).to eq("CloudTenant") + + expect(t_1_ct_vm_1.parent.id).to eq(ct_3_new.source_tenant.id) + expect(t_3_ct_3.id).to eq(ct_3_new.source_tenant.id) + + provider_tenant = Tenant.root_tenant.children.first + expect(provider_tenant.id).to eq(ct_3_new.source_tenant.parent.id) + expect(Tenant.count).to eq(8) + + old_tenant_1 = Tenant.find_by(:name => ct_name_1) + expect(old_tenant_1.id).not_to eq(ct_1_new.source_tenant.id) + expect(old_tenant_1.parent.id).to eq(provider_tenant.id) + expect(old_tenant_1.children.first).to be_nil + expect(old_tenant_1.source_id).to be_nil + expect(old_tenant_1.source_type).to be_nil + + old_tenant_2 = Tenant.find_by(:name => ct_name_2) + expect(old_tenant_2.id).not_to eq(ct_2_new.source_tenant.id) + expect(old_tenant_2.parent.id).to eq(provider_tenant.id) + expect(old_tenant_2.children.first).to be_nil + expect(old_tenant_1.source_id).to be_nil + expect(old_tenant_1.source_type).to be_nil + + old_tenant_3 = Tenant.find_by(:name => ct_name_3) + expect(old_tenant_3.parent.id).to eq(provider_tenant.id) + expect(old_tenant_3.children.first).to be_nil + expect(old_tenant_3.source_id).to be_nil + expect(old_tenant_3.source_type).to be_nil + end + end + + context "when the new user has lower count of cloud tenants with than previous provider's user" do + ###### + # ct - Cloud Tenant, t - Tenant + # ===== + # CloudTenant tree: + # ct_3 -> ct_1 (vm_1s) + # ct_2 + # + # first tenant synchronization + # + # Expected Tenant tree: + # My Company t + # -> Provider Tenant + # -> t_3 (ct_3's) -> t_1 + # -> t_2 (ct_2's) + # + ### after changed user with different set of cloud tenants + ### second synchronization + # ===== + # CloudTenant tree: + # new_ct_1 (vm_1s) + # + # second tenant synchronization + # + # Expected Tenant tree: + # My Company t + # -> Provider Tenant + # -> new_t_1(new_ct_1's) + # -> t_2(old - moved out) + # -> t_3(old - moved out) + ###### + let(:ct_1_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :name => ct_name_1) } + + it "creates tenant tree from cloud tenants with correct source_tenant relations" do + expect(CloudTenant.count).to eq(3) + ems_cloud.sync_cloud_tenants_with_tenants + expect(Tenant.count).to eq(5) + + old_cloud_tenant_ids = CloudTenant.ids + + # destroy old cloud tenants and replace them with new + vm_1.cloud_tenant.destroy + vm_1.update_attributes!(:cloud_tenant => ct_1_new) + vm_2.cloud_tenant.destroy + vm_2.destroy + ct_3.destroy + + expect(CloudTenant.count).to eq(1) + expect(CloudTenant.ids).not_to match_array(old_cloud_tenant_ids) + ems_cloud.sync_cloud_tenants_with_tenants + + t_1_ct_vm_1 = tenant_from_cloud_tenant_by(vm_1) + expect(t_1_ct_vm_1.id).to eq(ct_1_new.source_tenant.id) + expect(t_1_ct_vm_1.parent.id).to eq(provider_tenant.id) + expect(t_1_ct_vm_1.children.first).to be_nil + expect(t_1_ct_vm_1.source_id).to eq(ct_1_new.id) + expect(t_1_ct_vm_1.source_type).to eq("CloudTenant") + + expect(provider_tenant.id).to eq(ct_1_new.source_tenant.parent.id) + expect(Tenant.count).to eq(5) + + # old tenants (related to deleted cloud tenants) are under provider tenant + old_tenant_2 = Tenant.find_by(:name => ct_name_2) + expect(old_tenant_2.parent.id).to eq(provider_tenant.id) + expect(old_tenant_2.children.first).to be_nil + expect(old_tenant_2.source_id).to be_nil + expect(old_tenant_2.source_type).to be_nil + + old_tenant_3 = Tenant.find_by(:name => ct_name_3) + expect(old_tenant_3.parent.id).to eq(provider_tenant.id) + expect(old_tenant_3.children.first).to be_nil + expect(old_tenant_3.source_id).to be_nil + expect(old_tenant_3.source_type).to be_nil + end + end + + context "when the new user has greater count of cloud tenants with than previous provider's user, some and different name" do + ###### + # ct - Cloud Tenant, t - Tenant + # ===== + # CloudTenant tree: + # ct_3 -> ct_1 (vm_1s) + # ct_2 + # + # first tenant synchronization + # + # Expected Tenant tree: + # My Company t + # -> Provider Tenant + # -> t_3 (ct_3's) -> t_1 + # -> t_2 (ct_2's) + # + ### after changed user with different set of cloud tenants + ### second synchronization + # ===== + # CloudTenant tree: + # new_ct_3(same name) -> new_ct_1 (vm_1s) -> new_ct_4(vm_4's cloud_tenant)) + # new_ct_2 + # + # second tenant synchronization + # + # Expected Tenant tree: + # My Company t + # -> Provider Tenant + # -> t_3 (new_ct_3's) -> new_t_1(new_ct_1's) -> new_t_4(vm_4's cloud_tenant) + # -> new_t_2 (new_ct_2's) + # -> t_1(old - moved out) + # -> t_2(old - moved out) + ###### + let(:ct_1_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :parent => ct_3_new, :name => ct_name_1 + "X") } + let(:ct_2_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :name => ct_name_2 + "X") } + let(:ct_3_new) { FactoryGirl.create(:cloud_tenant_openstack, :ext_management_system => ems_cloud, :name => ct_name_3) } + let(:ct_name_4) { "ct_name_4" } + let(:vm_4) do + vm = FactoryGirl.create(:vm_openstack) + vm.cloud_tenant.update_attributes!(:parent => ct_1_new, :ext_management_system => ems_cloud, :name => ct_name_4) + vm + end + + it "creates tenant tree from cloud tenants with correct source_tenant relations" do + expect(CloudTenant.count).to eq(3) + ems_cloud.sync_cloud_tenants_with_tenants + expect(Tenant.count).to eq(5) + + old_cloud_tenant_ids = CloudTenant.ids + + # destroy old cloud tenants and replace them with new + vm_1.cloud_tenant.destroy + vm_1.update_attributes!(:cloud_tenant => ct_1_new) + vm_2.cloud_tenant.destroy + vm_2.cloud_tenant.destroy + vm_2.update_attributes!(:cloud_tenant => ct_2_new) + ct_3.destroy + ct_2_new + vm_4 + + expect(CloudTenant.count).to eq(4) + expect(CloudTenant.ids).not_to match_array(old_cloud_tenant_ids) + + ems_cloud.sync_cloud_tenants_with_tenants + + # testing relations source, parent, children, source_tenant for each tenant + t_1_ct_vm_1 = tenant_from_cloud_tenant_by(vm_1) + expect(t_1_ct_vm_1.id).to eq(ct_1_new.source_tenant.id) + expect(t_1_ct_vm_1.parent.id).to eq(ct_3_new.source_tenant.id) + expect(t_1_ct_vm_1.children.first.id).to eq(vm_4.cloud_tenant.source_tenant.id) + expect(t_1_ct_vm_1.source_id).to eq(ct_1_new.id) + expect(t_1_ct_vm_1.source_type).to eq("CloudTenant") + + t_2_ct_vm_2 = tenant_from_cloud_tenant_by(vm_2) + expect(t_2_ct_vm_2.id).to eq(ct_2_new.source_tenant.id) + expect(t_2_ct_vm_2.parent.id).to eq(provider_tenant.id) + expect(t_2_ct_vm_2.children.first).to be_nil + expect(t_2_ct_vm_2.source_id).to eq(ct_2_new.id) + expect(t_2_ct_vm_2.source_type).to eq("CloudTenant") + + t_3_ct_3 = Tenant.find_by(:name => ct_name_3) + expect(t_3_ct_3.id).to eq(ct_3_new.source_tenant.id) + expect(t_3_ct_3.parent.id).to eq(provider_tenant.id) + expect(t_3_ct_3.children.first).to be_nil + expect(t_3_ct_3.source_id).to eq(ct_3_new.id) + expect(t_3_ct_3.source_type).to eq("CloudTenant") + t_4_ct_4 = Tenant.find_by(:name => ct_name_4) + expect(t_3_ct_3.descendants.ids).to match_array([t_1_ct_vm_1.id, t_4_ct_4.id]) + + expect(t_4_ct_4.id).to eq(vm_4.cloud_tenant.source_tenant.id) + expect(t_4_ct_4.parent.id).to eq(ct_1_new.source_tenant.id) + expect(t_4_ct_4.children.first).to be_nil + expect(t_4_ct_4.source_id).to eq(vm_4.cloud_tenant.id) + expect(t_4_ct_4.source_type).to eq("CloudTenant") + + expect(provider_tenant.id).to eq(ct_3_new.source_tenant.parent.id) + expect(Tenant.count).to eq(8) + + # old tenants (related to deleted cloud tenants) are under provider tenant + old_tenant_1 = Tenant.find_by(:name => ct_name_1) + expect(old_tenant_1.id).not_to eq(ct_1_new.source_tenant.id) + expect(old_tenant_1.parent.id).to eq(provider_tenant.id) + expect(old_tenant_1.children.first).to be_nil + expect(old_tenant_1.source_id).to be_nil + expect(old_tenant_1.source_type).to be_nil + + old_tenant_2 = Tenant.find_by(:name => ct_name_2) + expect(old_tenant_2.id).not_to eq(ct_2_new.source_tenant.id) + expect(old_tenant_2.parent.id).to eq(provider_tenant.id) + expect(old_tenant_2.children.first).to be_nil + expect(old_tenant_1.source_id).to be_nil + expect(old_tenant_1.source_type).to be_nil + end + end + end end end end