hammer_cli_foreman_ansible 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22b04f4732021b83a5f201c450ae645183a249b1fac74f9573eebc5b893e4761
4
- data.tar.gz: 1e9a7ce94688a284ebd784178cc479ce19e83e1a5ba5c2e28d259ca1a5508565
3
+ metadata.gz: 12f80a5bb288d8683aad9b3629edffbbd32bfb4afdf7aa597e4b370e2c19da58
4
+ data.tar.gz: 03d9f616b2d17580d15e93cae6fb79e0c6b599091fa4f0ed9cb7d6d2db986cdf
5
5
  SHA512:
6
- metadata.gz: 8444e5efcd1d36fef6925ae3fb2a6320c74da8d8a9e05e18efc257214ec2d7607bb8267f8d4451177f875fb69dc38da57c6ef844dfb84d57c3a506d98a410039
7
- data.tar.gz: c3622e78574949e8ea728f18cbe6fc8368a2f6d4052c3015da1151d4ce0a7ad83d4c9fb872cca12d257dea6d3763377f49426c9c0018b19571b47fef111890ec
6
+ metadata.gz: 12f88c7777fae85e77ae1288aafb09e08d569989b7a19bedbc939cbaa0d374161b47e23de3f3a4ec35ae78567982d0dc832f4974a14223d0aed05e76092ff7f1
7
+ data.tar.gz: 4bf5229134f1ce01c9ab517d5a9adb9281a5b9be0cced399fa78bbe55134e571525e51e9aed1c7802ef464a36162f7965eb3683faa294b89f5f99cf73be19c7f
@@ -16,6 +16,12 @@ module HammerCLIForemanAnsible
16
16
  'hammer_cli_foreman_ansible/ansible_variables'
17
17
  )
18
18
 
19
+ lazy_subcommand(
20
+ 'inventory',
21
+ _('Ansible Inventory'),
22
+ 'HammerCLIForemanAnsible::AnsibleInventoryCommand',
23
+ 'hammer_cli_foreman_ansible/ansible_inventory'
24
+ )
19
25
  autoload_subcommands
20
26
  end
21
27
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HammerCLIForemanAnsible
4
+ class AnsibleInventoryCommand < HammerCLIForeman::Command
5
+ resource :ansible_inventories
6
+
7
+ class HostsCommand < HammerCLIForeman::Command
8
+ action :hosts
9
+ command_name 'hosts'
10
+ option '--as-json', :flag, _('Full response as json')
11
+
12
+ def print_data(data)
13
+ return super unless option_as_json?
14
+
15
+ puts JSON.pretty_generate(data)
16
+ end
17
+ build_options
18
+
19
+ extend_with(HammerCLIForemanAnsible::CommandExtensions::Inventory.new)
20
+ end
21
+
22
+ class HostgroupsCommand < HammerCLIForeman::Command
23
+ action :hostgroups
24
+ command_name 'hostgroups'
25
+ option '--as-json', :flag, _('Full response as json')
26
+
27
+ def print_data(data)
28
+ return super unless option_as_json?
29
+
30
+ puts JSON.pretty_generate(data)
31
+ end
32
+ build_options
33
+
34
+ extend_with(HammerCLIForemanAnsible::CommandExtensions::Inventory.new)
35
+ end
36
+
37
+ class ScheduleCommand < HammerCLIForeman::Command
38
+ action :schedule
39
+ command_name 'schedule'
40
+
41
+ output do
42
+ field :job_id, _('Job Id')
43
+ field :data_url, _('Data URL')
44
+ end
45
+
46
+ build_options
47
+ end
48
+
49
+ autoload_subcommands
50
+ end
51
+ end
52
+
@@ -0,0 +1,85 @@
1
+ module HammerCLIForemanAnsible
2
+ module AssociatedAnsibleRole
3
+ # This method fetches all associated resource (ansible roles) ids
4
+ # to send them back via :update endpoint of the main resource (host/hostgroup)
5
+ # We use this array of ids to add or remove direct associations
6
+ # This method is used to 'reset' associated ids via HammerCLIForeman::[Add|Remove]AssociatedCommand
7
+ def get_current_ids
8
+ roles = HammerCLIForeman.record_to_common_format(resource.call(association_name(true), { id: get_identifier }))
9
+ return ids_to_keep_for_removal(roles) if self.class.command_names.include?('remove')
10
+
11
+ ids_to_keep_for_addition(roles)
12
+ end
13
+
14
+ # Since there are no option_sources available to deal with such cases (AssociatedCommand)
15
+ # Make sure we get id of the provided role before we try to get already associated ones
16
+ def get_new_ids
17
+ associated_identifiers = get_associated_identifiers
18
+ @associated_identifier = get_associated_identifier
19
+
20
+ ids = get_current_ids.map(&:to_s)
21
+
22
+ required_ids = associated_identifiers.nil? ? [] : associated_identifiers.map(&:to_s)
23
+ required_ids << @associated_identifier.to_s unless @associated_identifier.nil?
24
+
25
+ ids = if self.class.command_names.include?('remove')
26
+ ids.delete_if { |id| required_ids.include? id }
27
+ else
28
+ ids + required_ids
29
+ end
30
+ ids.uniq
31
+ end
32
+
33
+ private
34
+
35
+ # Treat inherited as we do in UI:
36
+ # - Don't allow to directly associate them (the role is not available to select)
37
+ # - If the same role was assigned AND inherited then treat it as it was just assigned (keep it)
38
+ # - If the role is indirectly associated only then don't associate it directly unless --force provided
39
+ def ids_to_keep_for_addition(roles)
40
+ roles.map do |role|
41
+ # Keep directly associated roles
42
+ next role['id'] if role['directly_assigned']
43
+
44
+ # Host groups can have not inherited and not directly assigned roles in the response.
45
+ # This means those roles are from hosts, skip them.
46
+ # Hosts cannot have such case.
47
+
48
+ # Pre-check to force stop the command if we're trying to add an already inherited role
49
+ # (in case we don't have it directly associated as well)
50
+ if @associated_identifier == role['id'] && role['inherited']
51
+ next role['id'] if option_force?
52
+
53
+ msg = _(
54
+ 'Ansible role %{name} is already inherited from a host group. Please use %{option} for direct association.'
55
+ ) % { name: role['name'], option: '--force' }
56
+ raise ArgumentError, msg
57
+ end
58
+
59
+ # We skip not directly assigned and inherited
60
+ # Also skip not inherited for host groups
61
+ nil
62
+ end.compact
63
+ end
64
+
65
+ # Treat inherited as we do in UI:
66
+ # - Don't allow to remove them (the role is not available to select)
67
+ # - If the same role was assigned AND inherited then treat it as it was just assigned (keep or remove it)
68
+ # - If the role was inherited only then don't remove it
69
+ def ids_to_keep_for_removal(roles)
70
+ roles.map do |role|
71
+ # Keep or remove later directly associated roles
72
+ next role['id'] if role['directly_assigned']
73
+
74
+ # Pre-check to force stop the command if we're trying to remove not directly assigned role
75
+ if role['id'] == @associated_identifier
76
+ raise ArgumentError, _('Ansible role %s is not assigned directly and cannot be removed.') % role['name']
77
+ end
78
+
79
+ # We skip not directly assigned and inherited
80
+ # Also skip not inherited for host groups
81
+ nil
82
+ end.compact
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HammerCLIForemanAnsible
4
+ module CommandExtensions
5
+ class Inventory < HammerCLI::CommandExtensions
6
+ output do |definition|
7
+ definition.append do
8
+ from 'foreman' do
9
+ field :hostname, _('Name')
10
+ field :fqdn, _('FQDN')
11
+ field :hostgroup, _('Host Group')
12
+ field :location, _('Location')
13
+ field :organization, _('Organization')
14
+ field :domainname, _('Domain')
15
+ field :foreman_domain_description, _('Foreman domain description')
16
+ field :owner_name, _('Owner name')
17
+ field :owner_email, _('Owner email')
18
+ field :ssh_authorized_keys, _('SSH authorized keys')
19
+ field :root_pw, _('Root password')
20
+ field :foreman_config_groups, _('Foreman config groups')
21
+ field :puppetmaster, _('Puppet master')
22
+ field :foreman_env, _('Puppet environment')
23
+
24
+ collection :foreman_subnets, _('Subnets') do
25
+ field :name, _('Name')
26
+ field :network, _('Network')
27
+ field :mask, _('Mask')
28
+ field :gateway, _('Gateway')
29
+ field :dns_primary, _('Primary DNS')
30
+ field :dns_secondary, _('Secondary DNS')
31
+ field :from, _('From')
32
+ field :to, _('To')
33
+ field :boot_mode, _('Boot mode')
34
+ field :ipam, _('IPAM')
35
+ field :vlanid, _('VLAN ID')
36
+ field :mtu, _('MTU')
37
+ field :nic_delay, _('NIC delay')
38
+ field :network_type, _('Network type')
39
+ field :description, _('Description')
40
+ end
41
+
42
+ collection :foreman_interfaces, _('Network interfaces') do
43
+ field :name, _('Interface Name')
44
+ field :identifier, _('Identifier')
45
+ field :attrs, _('Attributes'),Fields::Field, hide_blank: true
46
+ field :mac, _('MAC address')
47
+ field :ip, _('IPv4 address'), Fields::Field, hide_blank: true
48
+ field :ip6, _('IPv6 address'), Fields::Field, hide_blank: true
49
+ field :virtual, _('Virtual'), Fields::Boolean
50
+ field :link, _('Link'), Fields::Boolean
51
+ field :managed, _('Managed'), Fields::Boolean
52
+ field :primary, _('Primary'), Fields::Boolean
53
+ field :provision, _('Provision'), Fields::Boolean
54
+ field :subnet6, _('IPv6 subnet')
55
+ field :tag, _('Tag')
56
+ field :attached_to, _('Attached to')
57
+ field :type, _('Type')
58
+ field :attached_devices, _('Attached devices')
59
+ from 'subnet' do
60
+ label _('Subnet'), hide_blank: true do
61
+ field :name, _('Name')
62
+ field :network, _('Network')
63
+ field :mask, _('Mask')
64
+ field :gateway, _('Gateway')
65
+ field :dns_primary, _('Primary DNS')
66
+ field :dns_secondary, _('Secondary DNS')
67
+ field :from, _('From')
68
+ field :to, _('To')
69
+ field :boot_mode, _('Boot mode')
70
+ field :ipam, _('IPAM')
71
+ field :vlanid, _('VLAN ID')
72
+ field :mtu, _('MTU')
73
+ field :nic_delay, _('NIC delay')
74
+ field :network_type, _('Network type')
75
+ field :description, _('Description')
76
+ end
77
+ end
78
+ end
79
+
80
+ collection :foreman_users, _('Foreman Users'), numbered: false do
81
+ field :firstname, _('First name')
82
+ field :lastname, _('Last name')
83
+ field :mail, _('Email')
84
+ field :description, _('Description')
85
+ field :fullname, _('Full name')
86
+ field :ssh_authorized_keys, _('SSH authorized keys')
87
+ end
88
+ end
89
+
90
+ collection :foreman_ansible_roles, _('Foreman Ansible Roles'), numbered: false do
91
+ field :name, _('Role')
92
+ end
93
+
94
+ field :ansible_roles_check_mode, _('Ansible role check mode'), Fields::Boolean
95
+ field :host_packages, _('Host packages')
96
+ field :host_registration_insights, _('Host registration insights'), Fields::Boolean
97
+ field :host_registration_remote_execution, _('Host registration remote execution'), Fields::Boolean
98
+ field :remote_execution_ssh_keys, _('Remote execution ssh keys')
99
+ field :remote_execution_ssh_user, _('Remote execution ssh user')
100
+ field :remote_execution_effective_user_method, _('Remote execution effective user method')
101
+ field :remote_execution_connect_by_ip, _('Remote execution connect by IP'), Fields::Boolean
102
+ end
103
+ end
104
+
105
+ before_print do |data, cmd_obj|
106
+ unless cmd_obj.option_as_json?
107
+ new_data = data['all']['hosts'].each_with_object([]) do |hostname, arr|
108
+ data['_meta']['hostvars'][hostname]['foreman']['foreman_users'] = data['_meta']['hostvars'][hostname]['foreman']['foreman_users']&.map { |u| u[1] }
109
+ data['_meta']['hostvars'][hostname]['foreman_ansible_roles'] = data['_meta']['hostvars'][hostname]['foreman_ansible_roles']&.map { |r| { 'name' => r } }
110
+ arr << {
111
+ 'hostname' => hostname
112
+ }.merge(data['_meta']['hostvars'][hostname])
113
+ end
114
+ data.clear
115
+ data['results'] = new_data
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -1 +1,2 @@
1
1
  require 'hammer_cli_foreman_ansible/command_extensions/resolver'
2
+ require 'hammer_cli_foreman_ansible/command_extensions/inventory'
@@ -11,7 +11,10 @@ module HammerCLIForemanAnsible
11
11
  class ListCommand < HammerCLIForeman::ListCommand
12
12
  action :ansible_roles
13
13
 
14
- output HammerCLIForemanAnsible::AnsibleRolesCommand::ListCommand.output_definition
14
+ output(HammerCLIForemanAnsible::AnsibleRolesCommand::ListCommand.output_definition) do
15
+ field :inherited, _('Inherited'), Fields::Boolean
16
+ field :directly_assigned, _('Directly assigned'), Fields::Boolean
17
+ end
15
18
 
16
19
  build_options
17
20
  end
@@ -35,6 +38,45 @@ module HammerCLIForemanAnsible
35
38
 
36
39
  build_options
37
40
  end
41
+
42
+ class AddAnsibleRoleCommand < HammerCLIForeman::AddAssociatedCommand
43
+ prepend HammerCLIForemanAnsible::AssociatedAnsibleRole
44
+
45
+ command_name 'add'
46
+ associated_resource :ansible_roles
47
+ desc _('Associate an Ansible role')
48
+
49
+ option '--force', :flag, _('Associate the Ansible role even if it already is associated indirectly')
50
+
51
+ success_message _('Ansible role has been associated.')
52
+ failure_message _('Could not associate the Ansible role')
53
+
54
+ validate_options do
55
+ any(:option_name, :option_id).required
56
+ any(:option_ansible_role_name, :option_ansible_role_id).required
57
+ end
58
+
59
+ build_options
60
+ end
61
+
62
+ class RemoveAnsibleRoleCommand < HammerCLIForeman::RemoveAssociatedCommand
63
+ prepend HammerCLIForemanAnsible::AssociatedAnsibleRole
64
+
65
+ command_name 'remove'
66
+ associated_resource :ansible_roles
67
+ desc _('Disassociate an Ansible role')
68
+
69
+ success_message _('Ansible role has been disassociated.')
70
+ failure_message _('Could not disassociate the Ansible role')
71
+
72
+ validate_options do
73
+ any(:option_name, :option_id).required
74
+ any(:option_ansible_role_name, :option_ansible_role_id).required
75
+ end
76
+
77
+ build_options
78
+ end
79
+
38
80
  autoload_subcommands
39
81
  end
40
82
  end
@@ -11,7 +11,10 @@ module HammerCLIForemanAnsible
11
11
  class ListCommand < HammerCLIForeman::ListCommand
12
12
  action :ansible_roles
13
13
 
14
- output HammerCLIForemanAnsible::AnsibleRolesCommand::ListCommand.output_definition
14
+ output(HammerCLIForemanAnsible::AnsibleRolesCommand::ListCommand.output_definition) do
15
+ field :inherited, _('Inherited'), Fields::Boolean
16
+ field :directly_assigned, _('Directly assigned'), Fields::Boolean
17
+ end
15
18
 
16
19
  build_options
17
20
  end
@@ -36,6 +39,44 @@ module HammerCLIForemanAnsible
36
39
  build_options
37
40
  end
38
41
 
42
+ class AddAnsibleRoleCommand < HammerCLIForeman::AddAssociatedCommand
43
+ prepend HammerCLIForemanAnsible::AssociatedAnsibleRole
44
+
45
+ command_name 'add'
46
+ associated_resource :ansible_roles
47
+ desc _('Associate an Ansible role')
48
+
49
+ option '--force', :flag, _('Associate the Ansible role even if it already is associated indirectly')
50
+
51
+ success_message _('Ansible role has been associated.')
52
+ failure_message _('Could not associate the Ansible role')
53
+
54
+ validate_options do
55
+ any(:option_name, :option_title, :option_id).required
56
+ any(:option_ansible_role_name, :option_ansible_role_id).required
57
+ end
58
+
59
+ build_options
60
+ end
61
+
62
+ class RemoveAnsibleRoleCommand < HammerCLIForeman::RemoveAssociatedCommand
63
+ prepend HammerCLIForemanAnsible::AssociatedAnsibleRole
64
+
65
+ command_name 'remove'
66
+ associated_resource :ansible_roles
67
+ desc _('Disassociate an Ansible role')
68
+
69
+ success_message _('Ansible role has been disassociated.')
70
+ failure_message _('Could not disassociate the Ansible role')
71
+
72
+ validate_options do
73
+ any(:option_name, :option_title, :option_id).required
74
+ any(:option_ansible_role_name, :option_ansible_role_id).required
75
+ end
76
+
77
+ build_options
78
+ end
79
+
39
80
  autoload_subcommands
40
81
  end
41
82
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module HammerCLIForemanAnsible
4
4
  def self.version
5
- @version ||= Gem::Version.new '0.3.4'
5
+ @version ||= Gem::Version.new '0.4.0'
6
6
  end
7
7
  end
@@ -8,6 +8,7 @@ module HammerCLIForemanAnsible
8
8
  require 'hammer_cli_foreman_ansible/i18n'
9
9
  require 'hammer_cli_foreman_ansible/ansible'
10
10
  require 'hammer_cli_foreman_ansible/ansible_roles'
11
+ require 'hammer_cli_foreman_ansible/associated_ansible_role'
11
12
  require 'hammer_cli_foreman_ansible/host'
12
13
  require 'hammer_cli_foreman_ansible/hostgroup'
13
14