diff --git a/lib/foreman_azure_rm/azure_sdk_adapter.rb b/app/lib/foreman_azure_rm/azure_sdk_adapter.rb similarity index 88% rename from lib/foreman_azure_rm/azure_sdk_adapter.rb rename to app/lib/foreman_azure_rm/azure_sdk_adapter.rb index fadd5a8..4b0359f 100644 --- a/lib/foreman_azure_rm/azure_sdk_adapter.rb +++ b/app/lib/foreman_azure_rm/azure_sdk_adapter.rb @@ -11,7 +11,7 @@ def initialize(tenant, app_ident, secret_key, sub_id, azure_environment) end def resource_client - #resource_manager_endpoint_url + # resource_manager_endpoint_url @resource_client ||= Resources::Client.new(azure_credentials(@environment_settings.resource_manager_endpoint_url)) end @@ -33,11 +33,12 @@ def subscription_client def azure_credentials(base_url) provider = MsRestAzure::ApplicationTokenProvider.new( - @tenant, - @app_ident, - @secret_key, - @ad_settings) - + @tenant, + @app_ident, + @secret_key, + @ad_settings + ) + credentials = MsRest::TokenCredentials.new(provider) { @@ -46,7 +47,7 @@ def azure_credentials(base_url) client_id: @app_ident, client_secret: @secret_key, subscription_id: @sub_id, - base_url: base_url + base_url: base_url, } end @@ -91,7 +92,7 @@ def list_resources(filter) end def rgs - rgs = resource_client.resource_groups.list + rgs = resource_client.resource_groups.list rgs.map(&:name) end @@ -107,7 +108,7 @@ def public_ip(rg_name, pip_name) network_client.public_ipaddresses.get(rg_name, pip_name) end - def vm_nic(rg_name,nic_name) + def vm_nic(rg_name, nic_name) network_client.network_interfaces.get(rg_name, nic_name) end @@ -120,14 +121,15 @@ def get_vm_extension(rg_name, vm_name, vm_extension_name) end def list_vm_sizes(region) - return [] unless region.present? + return [] if region.blank? + stripped_region = region.gsub(/\s+/, '').downcase - compute_client.virtual_machine_sizes.list(stripped_region).value() + compute_client.virtual_machine_sizes.list(stripped_region).value end def list_vms(region) # List all VMs in a resource group - virtual_machines = compute_client.virtual_machines.list_by_location(region) + compute_client.virtual_machines.list_by_location(region) end def get_vm(rg_name, vm_name) @@ -166,7 +168,7 @@ def list_gallery_image_versions(rg_name, gallery_name, gallery_image_name) compute_client.gallery_image_versions.list_by_gallery_image(rg_name, gallery_name, gallery_image_name) end - def get_storage_accts + def get_storage_accts # rubocop:disable Naming/AccessorMethodName result = storage_client.storage_accounts.list result.value end @@ -177,9 +179,9 @@ def create_or_update_vm(rg_name, vm_name, parameters) def create_or_update_vm_extensions(rg_name, vm_name, vm_extension_name, extension_params) compute_client.virtual_machine_extensions.create_or_update(rg_name, - vm_name, - vm_extension_name, - extension_params) + vm_name, + vm_extension_name, + extension_params) end def create_or_update_pip(rg_name, pip_name, parameters) @@ -207,7 +209,7 @@ def delete_disk(rg_name, disk_name) end def check_vm_status(rg_name, vm_name) - virtual_machine = compute_client.virtual_machines.get(rg_name, vm_name, expand:'instanceView') + virtual_machine = compute_client.virtual_machines.get(rg_name, vm_name, expand: 'instanceView') get_status(virtual_machine) end @@ -215,9 +217,7 @@ def get_status(virtual_machine) vm_statuses = virtual_machine.instance_view.statuses vm_status = nil vm_statuses.each do |status| - if status.code.include? 'PowerState' - vm_status = status.code.split('/')[1] - end + vm_status = status.code.split('/')[1] if status.code.include? 'PowerState' end vm_status end @@ -238,11 +238,10 @@ def self.gallery_caching(rg_name) def actual_gallery_image_id(rg_name, image_id) gallery_names = list_galleries.map(&:name) - gallery_names.each do |gallery| - gallery_image = list_gallery_images(rg_name, gallery).detect { |image| image.name == image_id } - return gallery_image&.id - end - nil + return unless (gallery = gallery_names.first) + + gallery_image = list_gallery_images(rg_name, gallery).detect { |image| image.name == image_id } + gallery_image&.id end def fetch_gallery_image_id(rg_name, image_id) diff --git a/lib/foreman_azure_rm/engine.rb b/lib/foreman_azure_rm/engine.rb index 3792fcc..5c70af2 100644 --- a/lib/foreman_azure_rm/engine.rb +++ b/lib/foreman_azure_rm/engine.rb @@ -2,17 +2,19 @@ module ForemanAzureRm class Engine < ::Rails::Engine engine_name 'foreman_azure_rm' - #autoloading all files inside lib dir - config.eager_load_paths += Dir["#{config.root}/lib"] - config.eager_load_paths += Dir["#{config.root}/app/models/concerns/"] - config.eager_load_paths += Dir["#{config.root}/app/helpers/"] - - initializer 'foreman_azure_rm.register_plugin', :before => :finisher_hook do - Foreman::Plugin.register :foreman_azure_rm do - requires_foreman '>= 3.13' - register_gettext - compute_resource ForemanAzureRm::AzureRm - parameter_filter ComputeResource, :azure_vm, :tenant, :app_ident, :secret_key, :sub_id, :region, :cloud + lib = config.root.join('app', 'lib') + + config.autoload_paths << lib + config.eager_load_paths << lib + + initializer 'foreman_azure_rm.register_plugin', :before => :finisher_hook do |app| + app.reloader.to_prepare do + Foreman::Plugin.register :foreman_azure_rm do + requires_foreman '>= 3.13' + register_gettext + compute_resource ForemanAzureRm::AzureRm + parameter_filter ComputeResource, :azure_vm, :tenant, :app_ident, :secret_key, :sub_id, :region, :cloud + end end end @@ -29,14 +31,6 @@ class Engine < ::Rails::Engine end end - initializer "foreman_azure_rm.zeitwerk" do - Rails.autoloaders.each do |loader| - loader.ignore( - ForemanAzureRm::Engine.root.join('lib/foreman_azure_rm/version.rb') - ) - end - end - config.to_prepare do require 'azure_mgmt_resources' require 'azure_mgmt_network' diff --git a/test/unit/azure_rm_test.rb b/test/unit/azure_rm_test.rb index 3440e6b..5f897fb 100644 --- a/test/unit/azure_rm_test.rb +++ b/test/unit/azure_rm_test.rb @@ -1,143 +1,141 @@ require_relative '../test_plugin_helper' require_relative '../azure_rm_test_helper' -module ForemanAzureRm - class ForemanAzureRmTest < ActiveSupport::TestCase - include AzureRmTestHelper +class ForemanAzureRmTest < ActiveSupport::TestCase + include AzureRmTestHelper + setup do + @mock_sdk = mock('mock_sdk') + ForemanAzureRm::AzureRm.any_instance.stubs(:sdk).returns(@mock_sdk) + mock_region_sdk = mock('mock_region_sdk') + @mock_sdk.stubs(:list_regions).with('11111111-1111-1111-1111-111111111111').returns(mock_region_sdk) + eastus_region = mock('eastus_region') + westus_region = mock('westus_region') + mock_region_sdk.stubs(:value).returns([eastus_region, westus_region]) + eastus_region.stubs(:display_name => 'East US', :name => 'eastus') + westus_region.stubs(:display_name => 'West US', :name => 'westus') + + @azure_cr = FactoryBot.create(:azure_rm) + @azure_cr.stubs(:sdk).returns(@mock_sdk) + end + + test "list all valid regions" do + assert_equal [['East US', 'eastus'], ['West US', 'westus']], @azure_cr.regions + end + + test "list valid standard cloud name" do + cloud = %w[azure azureusgovernment azurechina azuregermancloud].sample + ForemanAzureRm::AzureRm.any_instance.stubs(:validate_cloud?).returns(true) + @azure_cr.cloud=(cloud) + assert @azure_cr.validate_cloud? + end + + test "list all resource groups" do + mock_resource_client = mock('mock_resource_client') + @mock_sdk.stubs(:resource_client).returns(mock_resource_client) + @mock_sdk.stubs(:rgs).returns(['rg1', 'rg2', 'rg3']) + assert ['rg1', 'rg2', 'rg3'], @azure_cr.resource_groups + end + + context 'sdk access' do setup do - @mock_sdk = mock('mock_sdk') - ForemanAzureRm::AzureRm.any_instance.stubs(:sdk).returns(@mock_sdk) - mock_region_sdk = mock('mock_region_sdk') - @mock_sdk.stubs(:list_regions).with('11111111-1111-1111-1111-111111111111').returns(mock_region_sdk) - eastus_region = mock('eastus_region') - westus_region = mock('westus_region') - mock_region_sdk.stubs(:value).returns([eastus_region, westus_region]) - eastus_region.stubs(:display_name => 'East US', :name => 'eastus') - westus_region.stubs(:display_name => 'West US', :name => 'westus') - - @azure_cr = FactoryBot.create(:azure_rm) - @azure_cr.stubs(:sdk).returns(@mock_sdk) + mock_sdk_results + @azure_cr.key_pair = @azure_cr.setup_key_pair + end + + test "create vm with password and without custom data" do + @mock_vm.stubs(:disable_password_authentication).returns(false) + @mock_vm.os_profile.stubs(:custom_data) + mock_create_or_update_vm_with_password + vm_args = base_vm_args.merge(with_password_auth).merge(with_marketplace_image) + actual_server = @azure_cr.create_vm(vm_args) + + assert_equal "ervin-golomb", actual_server.name + assert_equal "rg1", actual_server.resource_group + assert actual_server.password.present? + assert_equal 1, actual_server.interfaces.count + refute actual_server.azure_vm.disable_password_authentication + refute actual_server.azure_vm.os_profile.custom_data.present? end - test "list all valid regions" do - assert_equal [['East US', 'eastus'], ['West US', 'westus']], @azure_cr.regions + test "create vm with password, custom data and vm extension" do + @mock_vm.stubs(:disable_password_authentication).returns(false) + @mock_vm.os_profile.stubs(:custom_data).returns('ZWNobyBjdXN0b21EYXRh') + mock_create_or_update_vm_with_password + mock_vm_extension = mock('mock_vm_extension') + @mock_sdk.expects(:create_or_update_vm_extensions).with() do |actual_rg, vm_name, script_name, actual_ext| + actual_rg == "rg1" && + actual_ext.settings["commandToExecute"] == "su - \"testuser\" -c \"sudo sh /var/lib/waagent/custom-script/download/0/myscript.sh\"" && + actual_ext.settings["fileUris"] == ["https://gist.githubusercontent.com/apuntamb/f4e9ff4e2daf62bc847313b0c64e59f9/raw/73578e1bb7b03237ae1ac6b787b08d00d126adf0/myscript.sh"] + end.returns(mock_vm_extension) + vm_args = base_vm_args.merge(with_password_auth).merge(with_custom_data).merge(with_marketplace_image).merge(with_vm_extensions) + actual_server = @azure_cr.create_vm(vm_args) + + assert_equal "testpswd123", actual_server.password + assert actual_server.azure_vm.os_profile.custom_data.present? + refute actual_server.azure_vm.disable_password_authentication end - test "list valid standard cloud name" do - cloud = %w[azure azureusgovernment azurechina azuregermancloud].sample - ForemanAzureRm::AzureRm.any_instance.stubs(:validate_cloud?).returns(true) - @azure_cr.cloud=(cloud) - assert @azure_cr.validate_cloud? + test "create vm with sshkey and without custom data" do + @mock_vm.stubs(:disable_password_authentication).returns(true) + @mock_vm.os_profile.stubs(:custom_data) + @mock_sdk.expects(:create_or_update_vm_extensions).never + mock_create_or_update_vm_with_sshkey + vm_args = base_vm_args.merge(with_ssh_key_auth).merge(with_marketplace_image) + actual_server = @azure_cr.create_vm(vm_args) + + assert actual_server.azure_vm.disable_password_authentication + refute actual_server.azure_vm.os_profile.custom_data.present? end - test "list all resource groups" do - mock_resource_client = mock('mock_resource_client') - @mock_sdk.stubs(:resource_client).returns(mock_resource_client) - @mock_sdk.stubs(:rgs).returns(['rg1', 'rg2', 'rg3']) - assert ['rg1', 'rg2', 'rg3'], @azure_cr.resource_groups + test "create vm with sshkey, custom data and vm extension" do + @mock_vm.stubs(:disable_password_authentication).returns(true) + @mock_vm.os_profile.stubs(:custom_data).returns('ZWNobyBjdXN0b21EYXRh') + mock_create_or_update_vm_with_sshkey + mock_vm_extension = mock('mock_vm_extension') + @mock_sdk.expects(:create_or_update_vm_extensions).with() do |actual_rg, vm_name, script_name, actual_ext| + actual_rg == "rg1" && + actual_ext.settings["commandToExecute"] == "sudo sh /var/lib/waagent/custom-script/download/0/myscript.sh" && + actual_ext.settings["fileUris"] == ["https://gist.githubusercontent.com/apuntamb/f4e9ff4e2daf62bc847313b0c64e59f9/raw/73578e1bb7b03237ae1ac6b787b08d00d126adf0/myscript.sh"] + end.returns(mock_vm_extension) + vm_args = base_vm_args.merge(with_ssh_key_auth).merge(with_marketplace_image).merge(with_custom_data).merge(with_vm_extensions) + actual_server = @azure_cr.create_vm(vm_args) + + assert actual_server.azure_vm.disable_password_authentication + assert actual_server.azure_vm.os_profile.custom_data.present? end - context 'sdk access' do - setup do - mock_sdk_results - @azure_cr.key_pair = @azure_cr.setup_key_pair - end - - test "create vm with password and without custom data" do - @mock_vm.stubs(:disable_password_authentication).returns(false) - @mock_vm.os_profile.stubs(:custom_data) - mock_create_or_update_vm_with_password - vm_args = base_vm_args.merge(with_password_auth).merge(with_marketplace_image) - actual_server = @azure_cr.create_vm(vm_args) - - assert_equal "ervin-golomb", actual_server.name - assert_equal "rg1", actual_server.resource_group - assert actual_server.password.present? - assert_equal 1, actual_server.interfaces.count - refute actual_server.azure_vm.disable_password_authentication - refute actual_server.azure_vm.os_profile.custom_data.present? - end - - test "create vm with password, custom data and vm extension" do - @mock_vm.stubs(:disable_password_authentication).returns(false) - @mock_vm.os_profile.stubs(:custom_data).returns('ZWNobyBjdXN0b21EYXRh') - mock_create_or_update_vm_with_password - mock_vm_extension = mock('mock_vm_extension') - @mock_sdk.expects(:create_or_update_vm_extensions).with() do |actual_rg, vm_name, script_name, actual_ext| - actual_rg == "rg1" && - actual_ext.settings["commandToExecute"] == "su - \"testuser\" -c \"sudo sh /var/lib/waagent/custom-script/download/0/myscript.sh\"" && - actual_ext.settings["fileUris"] == ["https://gist.githubusercontent.com/apuntamb/f4e9ff4e2daf62bc847313b0c64e59f9/raw/73578e1bb7b03237ae1ac6b787b08d00d126adf0/myscript.sh"] - end.returns(mock_vm_extension) - vm_args = base_vm_args.merge(with_password_auth).merge(with_custom_data).merge(with_marketplace_image).merge(with_vm_extensions) - actual_server = @azure_cr.create_vm(vm_args) - - assert_equal "testpswd123", actual_server.password - assert actual_server.azure_vm.os_profile.custom_data.present? - refute actual_server.azure_vm.disable_password_authentication - end - - test "create vm with sshkey and without custom data" do - @mock_vm.stubs(:disable_password_authentication).returns(true) - @mock_vm.os_profile.stubs(:custom_data) - @mock_sdk.expects(:create_or_update_vm_extensions).never - mock_create_or_update_vm_with_sshkey - vm_args = base_vm_args.merge(with_ssh_key_auth).merge(with_marketplace_image) - actual_server = @azure_cr.create_vm(vm_args) - - assert actual_server.azure_vm.disable_password_authentication - refute actual_server.azure_vm.os_profile.custom_data.present? - end - - test "create vm with sshkey, custom data and vm extension" do - @mock_vm.stubs(:disable_password_authentication).returns(true) - @mock_vm.os_profile.stubs(:custom_data).returns('ZWNobyBjdXN0b21EYXRh') - mock_create_or_update_vm_with_sshkey - mock_vm_extension = mock('mock_vm_extension') - @mock_sdk.expects(:create_or_update_vm_extensions).with() do |actual_rg, vm_name, script_name, actual_ext| - actual_rg == "rg1" && - actual_ext.settings["commandToExecute"] == "sudo sh /var/lib/waagent/custom-script/download/0/myscript.sh" && - actual_ext.settings["fileUris"] == ["https://gist.githubusercontent.com/apuntamb/f4e9ff4e2daf62bc847313b0c64e59f9/raw/73578e1bb7b03237ae1ac6b787b08d00d126adf0/myscript.sh"] - end.returns(mock_vm_extension) - vm_args = base_vm_args.merge(with_ssh_key_auth).merge(with_marketplace_image).merge(with_custom_data).merge(with_vm_extensions) - actual_server = @azure_cr.create_vm(vm_args) - - assert actual_server.azure_vm.disable_password_authentication - assert actual_server.azure_vm.os_profile.custom_data.present? - end - - test "create vm with custom image and sshkey" do - @mock_vm.stubs(:disable_password_authentication).returns(true) - mock_custom_img = mock('mock_custom_img') - @mock_sdk.expects(:get_custom_image).with("rg1", "first_custom_img").returns(mock_custom_img) - mock_custom_img.stubs(:name).returns('first_custom_img') - mock_custom_img.stubs(:id).returns('/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/images/first_custom_img') - @mock_vm.storage_profile.image_reference.stubs(:id).returns('/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/images/first_custom_img') - @mock_sdk.stubs(:list_custom_images).returns([mock_custom_img]) - mock_create_or_update_vm_with_sshkey - @mock_sdk.expects(:create_or_update_vm_extensions).never - vm_args = base_vm_args.merge(with_ssh_key_auth).merge(with_custom_image) - actual_server = @azure_cr.create_vm(vm_args) - - assert actual_server.azure_vm.disable_password_authentication - assert_equal "custom://first_custom_img", actual_server.image_id - end - - - test "create vm with shared image gallery and password" do - @mock_vm.stubs(:disable_password_authentication).returns(false) - @mock_sdk.expects(:fetch_gallery_image_id).with("rg1", "first_gallery_img").returns("/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/galleries/first_gallery/images/first_gallery_img").times(2) - mock_gallery_image = mock('mock_gallery_image') - mock_gallery_image.stubs(:id).returns('/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/galleries/first_gallery/images/first_gallery_img') - @mock_vm.storage_profile.image_reference.stubs(:id).returns('/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/galleries/first_gallery/images/first_gallery_img') - @mock_sdk.stubs(:list_custom_images).returns([]) - mock_create_or_update_vm_with_password - vm_args = base_vm_args.merge(with_password_auth).merge(with_gallery_image) - actual_server = @azure_cr.create_vm(vm_args) - - refute actual_server.azure_vm.disable_password_authentication - assert_equal "testpswd123", actual_server.password - assert_equal "gallery://first_gallery_img", actual_server.image_id - end + test "create vm with custom image and sshkey" do + @mock_vm.stubs(:disable_password_authentication).returns(true) + mock_custom_img = mock('mock_custom_img') + @mock_sdk.expects(:get_custom_image).with("rg1", "first_custom_img").returns(mock_custom_img) + mock_custom_img.stubs(:name).returns('first_custom_img') + mock_custom_img.stubs(:id).returns('/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/images/first_custom_img') + @mock_vm.storage_profile.image_reference.stubs(:id).returns('/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/images/first_custom_img') + @mock_sdk.stubs(:list_custom_images).returns([mock_custom_img]) + mock_create_or_update_vm_with_sshkey + @mock_sdk.expects(:create_or_update_vm_extensions).never + vm_args = base_vm_args.merge(with_ssh_key_auth).merge(with_custom_image) + actual_server = @azure_cr.create_vm(vm_args) + + assert actual_server.azure_vm.disable_password_authentication + assert_equal "custom://first_custom_img", actual_server.image_id + end + + + test "create vm with shared image gallery and password" do + @mock_vm.stubs(:disable_password_authentication).returns(false) + @mock_sdk.expects(:fetch_gallery_image_id).with("rg1", "first_gallery_img").returns("/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/galleries/first_gallery/images/first_gallery_img").times(2) + mock_gallery_image = mock('mock_gallery_image') + mock_gallery_image.stubs(:id).returns('/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/galleries/first_gallery/images/first_gallery_img') + @mock_vm.storage_profile.image_reference.stubs(:id).returns('/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/rg1/providers/Microsoft.Compute/galleries/first_gallery/images/first_gallery_img') + @mock_sdk.stubs(:list_custom_images).returns([]) + mock_create_or_update_vm_with_password + vm_args = base_vm_args.merge(with_password_auth).merge(with_gallery_image) + actual_server = @azure_cr.create_vm(vm_args) + + refute actual_server.azure_vm.disable_password_authentication + assert_equal "testpswd123", actual_server.password + assert_equal "gallery://first_gallery_img", actual_server.image_id end end end diff --git a/test/unit/azure_sdk_adapter_test.rb b/test/unit/azure_sdk_adapter_test.rb index 2539a81..4800c46 100644 --- a/test/unit/azure_sdk_adapter_test.rb +++ b/test/unit/azure_sdk_adapter_test.rb @@ -1,25 +1,23 @@ require_relative '../test_plugin_helper' -module ForemanAzureRm - class AzureSdkAdapterTest < ActiveSupport::TestCase - setup do - compute_resource = FactoryBot.build(:azure_rm) - tenant = compute_resource.uuid - app_ident = compute_resource.app_ident - secret_key = compute_resource.password - sub_id = compute_resource.user - cloud = compute_resource.cloud - @test_adapter = AzureSdkAdapter.new(tenant, app_ident, secret_key, sub_id, cloud) - AzureSdkAdapter.stubs(:gallery_caching).with('test_rg').returns({}) - end +class AzureSdkAdapterTest < ActiveSupport::TestCase + setup do + compute_resource = FactoryBot.build(:azure_rm) + tenant = compute_resource.uuid + app_ident = compute_resource.app_ident + secret_key = compute_resource.password + sub_id = compute_resource.user + cloud = compute_resource.cloud + @test_adapter = ForemanAzureRm::AzureSdkAdapter.new(tenant, app_ident, secret_key, sub_id, cloud) + ForemanAzureRm::AzureSdkAdapter.stubs(:gallery_caching).with('test_rg').returns({}) + end - test "should call #actual_gallery_image_id when #gallery_caching is {} otherwise return #gallery_caching" do - @test_adapter.expects(:actual_gallery_image_id).with('test_rg', 'test_gallery_image_name').once.returns('test_gallery_img_id') - actual1 = @test_adapter.fetch_gallery_image_id('test_rg', 'test_gallery_image_name') - actual2 = @test_adapter.fetch_gallery_image_id('test_rg', 'test_gallery_image_name') + test "should call #actual_gallery_image_id when #gallery_caching is {} otherwise return #gallery_caching" do + @test_adapter.expects(:actual_gallery_image_id).with('test_rg', 'test_gallery_image_name').once.returns('test_gallery_img_id') + actual1 = @test_adapter.fetch_gallery_image_id('test_rg', 'test_gallery_image_name') + actual2 = @test_adapter.fetch_gallery_image_id('test_rg', 'test_gallery_image_name') - assert_equal actual1, actual2 - assert_equal 'test_gallery_img_id', actual1 - end + assert_equal actual1, actual2 + assert_equal 'test_gallery_img_id', actual1 end end