From 00984b765283691306b78ffd7bed6c9986a4bcee Mon Sep 17 00:00:00 2001 From: Oleh Fedorenko Date: Fri, 25 Mar 2022 13:25:37 +0000 Subject: [PATCH] Fixes #34121 - Add/Delete a single Ansible role to Host(group) --- lib/hammer_cli_foreman_ansible.rb | 1 + .../associated_ansible_resource.rb | 8 ++ lib/hammer_cli_foreman_ansible/host.rb | 37 ++++++ lib/hammer_cli_foreman_ansible/hostgroup.rb | 36 ++++++ test/functional/host_test.rb | 115 ++++++++++++++++++ test/functional/hostgroup_test.rb | 115 ++++++++++++++++++ 6 files changed, 312 insertions(+) create mode 100644 lib/hammer_cli_foreman_ansible/associated_ansible_resource.rb create mode 100644 test/functional/host_test.rb create mode 100644 test/functional/hostgroup_test.rb diff --git a/lib/hammer_cli_foreman_ansible.rb b/lib/hammer_cli_foreman_ansible.rb index 02f9fa0..a03431c 100644 --- a/lib/hammer_cli_foreman_ansible.rb +++ b/lib/hammer_cli_foreman_ansible.rb @@ -8,6 +8,7 @@ module HammerCLIForemanAnsible require 'hammer_cli_foreman_ansible/i18n' require 'hammer_cli_foreman_ansible/ansible' require 'hammer_cli_foreman_ansible/ansible_roles' + require 'hammer_cli_foreman_ansible/associated_ansible_resource' require 'hammer_cli_foreman_ansible/host' require 'hammer_cli_foreman_ansible/hostgroup' diff --git a/lib/hammer_cli_foreman_ansible/associated_ansible_resource.rb b/lib/hammer_cli_foreman_ansible/associated_ansible_resource.rb new file mode 100644 index 0000000..1b9bd08 --- /dev/null +++ b/lib/hammer_cli_foreman_ansible/associated_ansible_resource.rb @@ -0,0 +1,8 @@ +module HammerCLIForemanAnsible + module AssociatedAnsibleResource + def get_current_ids + resources = HammerCLIForeman.record_to_common_format(resource.call(association_name(true), { id: get_identifier })) + resources.map { |resource| resource['id'] || resource[:id] } + end + end +end diff --git a/lib/hammer_cli_foreman_ansible/host.rb b/lib/hammer_cli_foreman_ansible/host.rb index b81be30..c76b562 100644 --- a/lib/hammer_cli_foreman_ansible/host.rb +++ b/lib/hammer_cli_foreman_ansible/host.rb @@ -35,6 +35,43 @@ class AssignRolesCommand < HammerCLIForeman::Command build_options end + + class AddAnsibleRoleCommand < HammerCLIForeman::AddAssociatedCommand + prepend HammerCLIForemanAnsible::AssociatedAnsibleResource + + command_name 'add' + associated_resource :ansible_roles + desc _('Associate an Ansible role') + + success_message _('Ansible role has been associated.') + failure_message _('Could not associate the Ansible role') + + validate_options do + any(:option_name, :option_id).required + any(:option_ansible_role_name, :option_ansible_role_id).required + end + + build_options + end + + class RemoveAnsibleRoleCommand < HammerCLIForeman::RemoveAssociatedCommand + prepend HammerCLIForemanAnsible::AssociatedAnsibleResource + + command_name 'remove' + associated_resource :ansible_roles + desc _('Disassociate an Ansible role') + + success_message _('Ansible role has been disassociated.') + failure_message _('Could not disassociate the Ansible role') + + validate_options do + any(:option_name, :option_id).required + any(:option_ansible_role_name, :option_ansible_role_id).required + end + + build_options + end + autoload_subcommands end end diff --git a/lib/hammer_cli_foreman_ansible/hostgroup.rb b/lib/hammer_cli_foreman_ansible/hostgroup.rb index b28cf4d..5078578 100644 --- a/lib/hammer_cli_foreman_ansible/hostgroup.rb +++ b/lib/hammer_cli_foreman_ansible/hostgroup.rb @@ -36,6 +36,42 @@ class AssignRolesCommand < HammerCLIForeman::Command build_options end + class AddAnsibleRoleCommand < HammerCLIForeman::AddAssociatedCommand + prepend HammerCLIForemanAnsible::AssociatedAnsibleResource + + command_name 'add' + associated_resource :ansible_roles + desc _('Associate an Ansible role') + + success_message _('Ansible role has been associated.') + failure_message _('Could not associate the Ansible role') + + validate_options do + any(:option_name, :option_title, :option_id).required + any(:option_ansible_role_name, :option_ansible_role_id).required + end + + build_options + end + + class RemoveAnsibleRoleCommand < HammerCLIForeman::RemoveAssociatedCommand + prepend HammerCLIForemanAnsible::AssociatedAnsibleResource + + command_name 'remove' + associated_resource :ansible_roles + desc _('Disassociate an Ansible role') + + success_message _('Ansible role has been disassociated.') + failure_message _('Could not disassociate the Ansible role') + + validate_options do + any(:option_name, :option_title, :option_id).required + any(:option_ansible_role_name, :option_ansible_role_id).required + end + + build_options + end + autoload_subcommands end end diff --git a/test/functional/host_test.rb b/test/functional/host_test.rb new file mode 100644 index 0000000..cfc73de --- /dev/null +++ b/test/functional/host_test.rb @@ -0,0 +1,115 @@ +require File.join(File.dirname(__FILE__), 'test_helper') + +describe 'host' do + describe 'add ansible role' do + let(:cmd) { %w[host ansible-roles add] } + let(:ansible_role_1) do + { + 'id': 1, + 'name': 'role1' + } + end + + it 'requires host --id' do + expected_result = usage_error_result( + cmd, + 'At least one of options --name, --id is required.', + 'Could not associate the Ansible role' + ) + + api_expects_no_call + + result = run_cmd(cmd) + assert_cmd(expected_result, result) + end + + it 'requires host id and asnible role id' do + params = %w[--id=1] + expected_result = usage_error_result( + cmd, + 'At least one of options --ansible-role, --ansible-role-id is required.', + 'Could not associate the Ansible role' + ) + + api_expects_no_call + + result = run_cmd(cmd + params) + assert_cmd(expected_result, result) + end + + it 'associates ansible role with host' do + params = %w[--id=1 --ansible-role-id=2] + + api_expects(:hosts, :ansible_roles) do |par| + par[:id] == '1' + end.returns([ansible_role_1]) + + api_expects(:hosts, :update) do |par| + par['id'] == '1' && + par['host']['ansible_role_ids'] == %w[1 2] + end + + result = run_cmd(cmd + params) + assert_cmd(success_result("Ansible role has been associated.\n"), result) + end + end + + describe 'remove ansible role' do + let(:cmd) { %w[host ansible-roles remove] } + let(:ansible_roles) do + [ + { + 'id': 1, + 'name': 'role1' + }, + { + 'id': 2, + 'name': 'role2' + } + ] + end + + it 'requires host --id' do + expected_result = usage_error_result( + cmd, + 'At least one of options --name, --id is required.', + 'Could not disassociate the Ansible role' + ) + + api_expects_no_call + + result = run_cmd(cmd) + assert_cmd(expected_result, result) + end + + it 'requires host id and asnible role id' do + params = %w[--id=1] + expected_result = usage_error_result( + cmd, + 'At least one of options --ansible-role, --ansible-role-id is required.', + 'Could not disassociate the Ansible role' + ) + + api_expects_no_call + + result = run_cmd(cmd + params) + assert_cmd(expected_result, result) + end + + it 'disassociates ansible role from host' do + params = %w[--id=1 --ansible-role-id=2] + + api_expects(:hosts, :ansible_roles) do |par| + par[:id] == '1' + end.returns(ansible_roles) + + api_expects(:hosts, :update) do |par| + par['id'] == '1' && + par['host']['ansible_role_ids'] == %w[1] + end + + result = run_cmd(cmd + params) + assert_cmd(success_result("Ansible role has been disassociated.\n"), result) + end + end +end diff --git a/test/functional/hostgroup_test.rb b/test/functional/hostgroup_test.rb new file mode 100644 index 0000000..ac52d17 --- /dev/null +++ b/test/functional/hostgroup_test.rb @@ -0,0 +1,115 @@ +require File.join(File.dirname(__FILE__), 'test_helper') + +describe 'hostgroup' do + describe 'add ansible role' do + let(:cmd) { %w[hostgroup ansible-roles add] } + let(:ansible_role_1) do + { + 'id': 1, + 'name': 'role1' + } + end + + it 'requires hostgroup --id' do + expected_result = usage_error_result( + cmd, + 'At least one of options --name, --title, --id is required.', + 'Could not associate the Ansible role' + ) + + api_expects_no_call + + result = run_cmd(cmd) + assert_cmd(expected_result, result) + end + + it 'requires hostgroup id and asnible role id' do + params = %w[--id=1] + expected_result = usage_error_result( + cmd, + 'At least one of options --ansible-role, --ansible-role-id is required.', + 'Could not associate the Ansible role' + ) + + api_expects_no_call + + result = run_cmd(cmd + params) + assert_cmd(expected_result, result) + end + + it 'associates ansible role with hostgroup' do + params = %w[--id=1 --ansible-role-id=2] + + api_expects(:hostgroups, :ansible_roles) do |par| + par[:id] == '1' + end.returns([ansible_role_1]) + + api_expects(:hostgroups, :update) do |par| + par['id'] == '1' && + par['hostgroup']['ansible_role_ids'] == %w[1 2] + end + + result = run_cmd(cmd + params) + assert_cmd(success_result("Ansible role has been associated.\n"), result) + end + end + + describe 'remove ansible role' do + let(:cmd) { %w[hostgroup ansible-roles remove] } + let(:ansible_roles) do + [ + { + 'id': 1, + 'name': 'role1' + }, + { + 'id': 2, + 'name': 'role2' + } + ] + end + + it 'requires hostgroup --id' do + expected_result = usage_error_result( + cmd, + 'At least one of options --name, --title, --id is required.', + 'Could not disassociate the Ansible role' + ) + + api_expects_no_call + + result = run_cmd(cmd) + assert_cmd(expected_result, result) + end + + it 'requires hostgroup id and asnible role id' do + params = %w[--id=1] + expected_result = usage_error_result( + cmd, + 'At least one of options --ansible-role, --ansible-role-id is required.', + 'Could not disassociate the Ansible role' + ) + + api_expects_no_call + + result = run_cmd(cmd + params) + assert_cmd(expected_result, result) + end + + it 'disassociates ansible role from hostgroup' do + params = %w[--id=1 --ansible-role-id=2] + + api_expects(:hostgroups, :ansible_roles) do |par| + par[:id] == '1' + end.returns(ansible_roles) + + api_expects(:hostgroups, :update) do |par| + par['id'] == '1' && + par['hostgroup']['ansible_role_ids'] == %w[1] + end + + result = run_cmd(cmd + params) + assert_cmd(success_result("Ansible role has been disassociated.\n"), result) + end + end +end