foreman_ansible 6.3.3 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/ansible_inventories_controller.rb +1 -1
  3. data/app/graphql/mutations/ansible_variable_overrides/create.rb +26 -0
  4. data/app/graphql/mutations/ansible_variable_overrides/delete.rb +38 -0
  5. data/app/graphql/mutations/ansible_variable_overrides/update.rb +26 -0
  6. data/app/graphql/mutations/hosts/assign_ansible_roles.rb +37 -0
  7. data/app/graphql/presenters/ansible_role_presenter.rb +12 -0
  8. data/app/graphql/presenters/overriden_ansible_variable_presenter.rb +19 -0
  9. data/app/graphql/types/ansible_role.rb +9 -0
  10. data/app/graphql/types/ansible_variable.rb +23 -0
  11. data/app/graphql/types/ansible_variable_override.rb +9 -0
  12. data/app/graphql/types/inherited_ansible_role.rb +13 -0
  13. data/app/graphql/types/overriden_ansible_variable.rb +27 -0
  14. data/app/helpers/foreman_ansible/ansible_reports_helper.rb +35 -54
  15. data/app/models/concerns/foreman_ansible/host_managed_extensions.rb +23 -4
  16. data/app/models/concerns/foreman_ansible/hostgroup_extensions.rb +1 -0
  17. data/app/models/foreman_ansible/ansible_provider.rb +56 -6
  18. data/app/services/foreman_ansible/ansible_report_importer.rb +2 -2
  19. data/app/services/foreman_ansible/inventory_creator.rb +1 -1
  20. data/app/services/foreman_ansible/override_resolver.rb +22 -0
  21. data/app/views/api/v2/ansible_override_values/index.json.rabl +3 -0
  22. data/app/views/api/v2/ansible_variables/show.json.rabl +1 -1
  23. data/app/views/foreman_ansible/ansible_roles/_hostgroup_ansible_roles_button.erb +3 -0
  24. data/app/views/foreman_ansible/config_reports/_ansible.html.erb +14 -5
  25. data/app/views/foreman_ansible/job_templates/ansible_roles_-_ansible_default.erb +4 -0
  26. data/app/views/foreman_ansible/job_templates/convert_to_rhel.erb +6 -2
  27. data/app/views/foreman_ansible/job_templates/run_openscap_scans_-_ansible_default.erb +20 -0
  28. data/config/routes.rb +3 -0
  29. data/db/migrate/20210818083407_fix_ansible_setting_category_to_dsl.rb +5 -0
  30. data/lib/foreman_ansible/engine.rb +0 -18
  31. data/lib/foreman_ansible/register.rb +114 -2
  32. data/lib/foreman_ansible/version.rb +1 -1
  33. data/package.json +10 -6
  34. data/test/functional/api/v2/ansible_inventories_controller_test.rb +1 -2
  35. data/test/graphql/mutations/hosts/assign_ansible_roles_mutation_test.rb +96 -0
  36. data/test/graphql/queries/ansible_roles_query_test.rb +35 -0
  37. data/test/unit/ansible_provider_test.rb +3 -6
  38. data/test/unit/concerns/host_managed_extensions_test.rb +8 -0
  39. data/test/unit/concerns/hostgroup_extensions_test.rb +6 -0
  40. data/test/unit/helpers/ansible_reports_helper_test.rb +4 -30
  41. data/test/unit/services/override_resolver_test.rb +34 -0
  42. data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.js +59 -0
  43. data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.scss +6 -0
  44. data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.test.js +20 -0
  45. data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/AnsibleHostInventory.js +22 -0
  46. data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/AnsibleHostInventory.scss +4 -0
  47. data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/AnsibleHostInventory.test.js +104 -0
  48. data/webpack/components/AnsibleHostDetail/components/AnsibleHostInventory/index.js +38 -0
  49. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverrides.scss +3 -0
  50. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTable.js +238 -0
  51. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTableHelper.js +111 -0
  52. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableAction.js +161 -0
  53. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableAction.scss +7 -0
  54. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableActionHelper.js +49 -0
  55. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableValue.js +70 -0
  56. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableValueHelper.js +35 -0
  57. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverrides.fixtures.js +429 -0
  58. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverrides.test.js +71 -0
  59. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverridesDelete.test.js +74 -0
  60. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/__test__/AnsibleVariableOverridesUpdate.test.js +188 -0
  61. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/index.js +58 -0
  62. data/webpack/components/AnsibleHostDetail/components/JobsTab/JobsTabHelper.js +79 -0
  63. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobHelper.js +106 -0
  64. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobModal.js +129 -0
  65. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobModal.scss +7 -0
  66. data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js +103 -0
  67. data/webpack/components/AnsibleHostDetail/components/JobsTab/RecurringJobsTable.js +96 -0
  68. data/webpack/components/AnsibleHostDetail/components/JobsTab/__test__/JobsTab.fixtures.js +184 -0
  69. data/webpack/components/AnsibleHostDetail/components/JobsTab/__test__/JobsTab.test.js +195 -0
  70. data/webpack/components/AnsibleHostDetail/components/JobsTab/index.js +88 -0
  71. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/AllRolesTable.js +89 -0
  72. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/index.js +80 -0
  73. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesForm.js +90 -0
  74. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesModal.scss +3 -0
  75. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesModalHelper.js +40 -0
  76. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/index.js +82 -0
  77. data/webpack/components/AnsibleHostDetail/components/RolesTab/RolesTable.js +129 -0
  78. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/EditRoles.test.js +85 -0
  79. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.fixtures.js +180 -0
  80. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.test.js +75 -0
  81. data/webpack/components/AnsibleHostDetail/components/RolesTab/index.js +51 -0
  82. data/webpack/components/AnsibleHostDetail/components/SecondaryTabRoutes.js +60 -0
  83. data/webpack/components/AnsibleHostDetail/components/TabLayout.js +12 -0
  84. data/webpack/components/AnsibleHostDetail/constants.js +9 -0
  85. data/webpack/components/AnsibleHostDetail/helpers.js +4 -0
  86. data/webpack/components/AnsibleHostDetail/index.js +6 -0
  87. data/webpack/components/AnsibleRolesAndVariables/__test__/AnsibleRolesAndVariablesImport.test.js +15 -10
  88. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.js +29 -0
  89. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.test.js +3 -0
  90. data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.js +2 -1
  91. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsiblePermissionDenied.test.js.snap +2 -0
  92. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsibleRole.test.js.snap +3 -3
  93. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AssignedRolesList.test.js.snap +4 -4
  94. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +9 -0
  95. data/webpack/components/DualList/DualList.scss +3 -0
  96. data/webpack/components/DualList/ListControls.js +65 -0
  97. data/webpack/components/DualList/ListHeader.js +16 -0
  98. data/webpack/components/DualList/ListItem.js +69 -0
  99. data/webpack/components/DualList/ListPane.js +95 -0
  100. data/webpack/components/DualList/SelectedStatus.js +21 -0
  101. data/webpack/components/DualList/index.js +103 -0
  102. data/webpack/components/ErrorState.js +16 -0
  103. data/webpack/components/withLoading.js +135 -0
  104. data/webpack/components/withPagination.js +0 -0
  105. data/webpack/formHelper.js +131 -0
  106. data/webpack/globalIdHelper.js +13 -0
  107. data/webpack/global_index.js +18 -0
  108. data/webpack/graphql/mutations/assignAnsibleRoles.gql +17 -0
  109. data/webpack/graphql/mutations/cancelRecurringLogic.gql +12 -0
  110. data/webpack/graphql/mutations/createAnsibleVariableOverride.gql +28 -0
  111. data/webpack/graphql/mutations/createJobInvocation.gql +11 -0
  112. data/webpack/graphql/mutations/deleteAnsibleVariableOverride.gql +17 -0
  113. data/webpack/graphql/mutations/updateAnsibleVariableOverride.gql +29 -0
  114. data/webpack/graphql/queries/allAnsibleRoles.gql +13 -0
  115. data/webpack/graphql/queries/ansibleRoles.gql +13 -0
  116. data/webpack/graphql/queries/currentUserAttributes.gql +11 -0
  117. data/webpack/graphql/queries/hostAnsibleRoles.gql +17 -0
  118. data/webpack/graphql/queries/hostAvailableAnsibleRoles.gql +11 -0
  119. data/webpack/graphql/queries/hostVariableOverrides.gql +39 -0
  120. data/webpack/graphql/queries/recurringJobs.gql +28 -0
  121. data/webpack/helpers/pageParamsHelper.js +40 -0
  122. data/webpack/helpers/paginationHelper.js +9 -0
  123. data/webpack/permissionsHelper.js +58 -0
  124. data/webpack/routes/HostgroupJobs/__test__/HostgroupJobs.fixtures.js +63 -0
  125. data/webpack/routes/HostgroupJobs/__test__/HostgroupJobs.test.js +112 -0
  126. data/webpack/routes/HostgroupJobs/index.js +26 -0
  127. data/webpack/routes/routes.js +10 -0
  128. data/webpack/testHelper.js +165 -0
  129. data/webpack/toastHelper.js +4 -0
  130. metadata +130 -78
  131. data/app/assets/images/foreman_ansible/Ansible.png +0 -0
  132. data/app/models/foreman_ansible/fact_name.rb +0 -16
  133. data/app/models/setting/ansible.rb +0 -106
  134. data/app/services/foreman_ansible/fact_importer.rb +0 -99
  135. data/app/services/foreman_ansible/fact_parser.rb +0 -126
  136. data/app/services/foreman_ansible/fact_sparser.rb +0 -37
  137. data/app/services/foreman_ansible/operating_system_parser.rb +0 -102
  138. data/app/services/foreman_ansible/structured_fact_importer.rb +0 -25
  139. data/test/unit/lib/foreman_ansible_core/ansible_runner_test.rb +0 -51
  140. data/test/unit/lib/foreman_ansible_core/command_creator_test.rb +0 -64
  141. data/test/unit/lib/foreman_ansible_core/playbook_runner_test.rb +0 -110
  142. data/test/unit/services/fact_importer_test.rb +0 -52
  143. data/test/unit/services/fact_parser_test.rb +0 -281
  144. data/test/unit/services/fact_sparser_test.rb +0 -24
  145. data/test/unit/services/structured_fact_importer_test.rb +0 -30
  146. data/webpack/__mocks__/foremanReact/common/I18n.js +0 -1
  147. data/webpack/__mocks__/foremanReact/common/helpers.js +0 -13
  148. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +0 -2
  149. data/webpack/__mocks__/foremanReact/components/common/EmptyState.js +0 -5
  150. data/webpack/__mocks__/foremanReact/components/common/forms/OrderableSelect/helpers.js +0 -5
  151. data/webpack/__mocks__/foremanReact/redux/API.js +0 -7
  152. data/webpack/components/AnsibleRolesAndVariables/__test__/__snapshots__/AnsibleRolesAndVariablesImport.test.js.snap +0 -177
@@ -1,126 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ForemanAnsible
4
- # Override methods from Foreman app/services/fact_parser so that facts
5
- # representing host properties are understood when they come from Ansible.
6
- class FactParser < ::FactParser
7
- include OperatingSystemParser
8
- attr_reader :facts
9
-
10
- def initialize(facts)
11
- @facts = HashWithIndifferentAccess.new(facts[:ansible_facts])
12
- end
13
-
14
- # Don't do anything as there's no env in Ansible
15
- def environment; end
16
-
17
- def architecture
18
- name = facts[:ansible_architecture] || facts[:facter_architecture]
19
- Architecture.where(:name => name).first_or_create if name.present?
20
- end
21
-
22
- def model
23
- name = detect_fact([:ansible_product_name, :facter_virtual,
24
- :facter_productname, :facter_model, :model])
25
- Model.where(:name => name.strip).first_or_create if name.present?
26
- end
27
-
28
- def domain
29
- name = detect_fact([:ansible_domain, :facter_domain,
30
- :ohai_domain, :domain])
31
- Domain.where(:name => name).first_or_create if name.present?
32
- end
33
-
34
- def support_interfaces_parsing?
35
- true
36
- end
37
-
38
- # Move ansible's default interface first in the list of interfaces since
39
- # Foreman picks the first one that is usable. If ansible has no
40
- # preference otherwise at least sort the list.
41
- #
42
- # This method overrides app/services/fact_parser.rb on Foreman and returns
43
- # an array of interface names, ['eth0', 'wlan1', etc...]
44
- def get_interfaces # rubocop:disable Naming/AccessorMethodName
45
- pref = facts[:ansible_default_ipv4] &&
46
- facts[:ansible_default_ipv4]['interface']
47
- if pref.present?
48
- (facts[:ansible_interfaces] - [pref]).unshift(pref)
49
- else
50
- ansible_interfaces
51
- end
52
- end
53
-
54
- def get_facts_for_interface(iface_name)
55
- interface = iface_name.tr('-', '_') # virbr1-nic -> virbr1_nic
56
- interface_facts = facts[:"ansible_#{interface}"]
57
- ipaddress = ip_from_interface(interface)
58
- ipaddress6 = ipv6_from_interface(interface)
59
- macaddress = mac_from_interface(interface)
60
- iface_facts = HashWithIndifferentAccess[
61
- interface_facts.merge(:ipaddress => ipaddress,
62
- :ipaddress6 => ipaddress6,
63
- :macaddress => macaddress)
64
- ]
65
- logger.debug { "Ansible interface #{interface} facts: #{iface_facts.inspect}" }
66
- iface_facts
67
- end
68
-
69
- def ipmi_interface; end
70
-
71
- def boot_timestamp
72
- Time.zone.now.to_i - facts['ansible_uptime_seconds'].to_i
73
- end
74
-
75
- def virtual
76
- facts['ansible_virtualization_role'] == 'guest'
77
- end
78
-
79
- def ram
80
- facts['ansible_memtotal_mb'].to_i
81
- end
82
-
83
- def sockets
84
- facts['ansible_processor_count'].to_i
85
- end
86
-
87
- def cores
88
- facts['ansible_processor_cores'].to_i
89
- end
90
-
91
- private
92
-
93
- def ansible_interfaces
94
- return [] if facts[:ansible_interfaces].blank?
95
- facts[:ansible_interfaces].sort
96
- end
97
-
98
- def mac_from_interface(interface)
99
- facts[:"ansible_#{interface}"]['perm_macaddress'].presence || facts[:"ansible_#{interface}"]['macaddress']
100
- end
101
-
102
- def ip_from_interface(interface)
103
- return if facts[:"ansible_#{interface}"]['ipv4'].blank?
104
- if facts[:"ansible_#{interface}"]['ipv4'].is_a?(Array)
105
- facts[:"ansible_#{interface}"]['ipv4'][0]['address']
106
- else
107
- facts[:"ansible_#{interface}"]['ipv4']['address']
108
- end
109
- end
110
-
111
- def ipv6_from_interface(interface)
112
- return if facts[:"ansible_#{interface}"]['ipv6'].blank?
113
-
114
- facts[:"ansible_#{interface}"]['ipv6'].first['address']
115
- end
116
-
117
- # Returns first non-empty fact. Needed to check for empty strings.
118
- def detect_fact(fact_names)
119
- facts[
120
- fact_names.detect do |fact_name|
121
- facts[fact_name].present?
122
- end
123
- ]
124
- end
125
- end
126
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ForemanAnsible
4
- # See sparse and unsparse documentation
5
- class FactSparser
6
- class << self
7
- # Sparses facts, so that it converts a facts hash
8
- # { operatingsystem : { major: 20, name : 'fedora' }
9
- # into
10
- # { operatingsystem::major: 20,
11
- # operatingsystem::name: 'fedora' }
12
- def sparse(hash, options = {})
13
- hash.map do |k, v|
14
- prefix = options.fetch(:prefix, []) + [k]
15
- next sparse(v, options.merge(:prefix => prefix)) if v.is_a? Hash
16
- { prefix.join(options.fetch(:separator, FactName::SEPARATOR)) => v }
17
- end.reduce(:merge) || {}
18
- end
19
-
20
- # Unsparses facts, so that it converts a hash with facts
21
- # { operatingsystem::major: 20,
22
- # operatingsystem::name: 'fedora' }
23
- # into
24
- # { operatingsystem : { major: 20, name: 'fedora' } }
25
- def unsparse(facts_hash)
26
- ret = {}
27
- sparse(facts_hash).each do |full_name, value|
28
- current = ret
29
- fact_name = full_name.to_s.split(FactName::SEPARATOR)
30
- current = (current[fact_name.shift] ||= {}) until fact_name.size <= 1
31
- current[fact_name.first] = value
32
- end
33
- ret
34
- end
35
- end
36
- end
37
- end
@@ -1,102 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ForemanAnsible
4
- # Methods to parse facts related to the OS
5
- module OperatingSystemParser
6
- def operatingsystem
7
- args = { :name => os_name, :major => os_major, :minor => os_minor }
8
- args[:release_name] = os_release_name if os_name == 'Debian' || os_name == 'Ubuntu'
9
- return @local_os if local_os(args).present?
10
- return @new_os if new_os(args).present?
11
- logger.debug do
12
- 'Ansible facts parser: No OS could be created with '\
13
- "os_name='#{os_name}' os_major='#{os_major}' "\
14
- "os_minor='#{os_minor}': "\
15
- "#{@new_os.errors if @new_os.present?}"
16
- end
17
- nil
18
- end
19
-
20
- def local_os(args)
21
- @local_os = Operatingsystem.where(args).first
22
- end
23
-
24
- def new_os(args)
25
- return @new_os if @new_os.present?
26
- @new_os = Operatingsystem.new(args.merge(:description => os_description))
27
- @new_os if @new_os.valid? && @new_os.save
28
- end
29
-
30
- def debian_os_major_sid
31
- case facts[:ansible_distribution_major_version]
32
- when /wheezy/i
33
- '7'
34
- when /jessie/i
35
- '8'
36
- when /stretch/i
37
- '9'
38
- when /buster/i
39
- '10'
40
- end
41
- end
42
-
43
- def os_release_name
44
- return '' if os_name != 'Debian' && os_name != 'Ubuntu'
45
- facts[:ansible_distribution_release]
46
- end
47
-
48
- def os_major
49
- if os_name == 'Debian' &&
50
- facts[:ansible_distribution_major_version][%r{\/sid}i]
51
- debian_os_major_sid
52
- else
53
- facts[:ansible_distribution_major_version] ||
54
- facts[:ansible_lsb] && facts[:ansible_lsb]['major_release'] ||
55
- (facts[:version].split('R')[0] if os_name == 'junos')
56
- end
57
- end
58
-
59
- def os_release
60
- facts[:ansible_distribution_version] ||
61
- facts[:ansible_lsb] && facts[:ansible_lsb]['release']
62
- end
63
-
64
- def os_minor
65
- _, minor = os_release&.split('.', 2) ||
66
- (facts[:version].split('R') if os_name == 'junos')
67
- # Until Foreman supports os.minor as something that's not a number,
68
- # we should remove the extra dots in the version. E.g:
69
- # '6.1.7601.65536' becomes '6.1.760165536'
70
- if facts[:ansible_os_family] == 'Windows'
71
- minor, patch = minor.split('.', 2)
72
- patch.tr!('.', '')
73
- minor = "#{minor}.#{patch}"
74
- end
75
- minor || ''
76
- end
77
-
78
- def os_name
79
- if facts[:ansible_os_family] == 'Windows'
80
- facts[:ansible_os_name].tr(" \n\t", '') ||
81
- facts[:ansible_distribution].tr(" \n\t", '')
82
- else
83
- distribution = facts[:ansible_lsb].try(:[], 'id') || facts[:ansible_distribution]
84
-
85
- if distribution == 'RedHat' &&
86
- facts[:ansible_lsb].try(:[], 'id') == 'RedHatEnterpriseWorkstation'
87
- distribution += '_Workstation'
88
- end
89
-
90
- distribution
91
- end
92
- end
93
-
94
- def os_description
95
- if facts[:ansible_os_family] == 'Windows'
96
- facts[:ansible_os_name].strip || facts[:ansible_distribution].strip
97
- else
98
- facts[:ansible_lsb] && facts[:ansible_lsb]['description']
99
- end
100
- end
101
- end
102
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ForemanAnsible
4
- # On 1.13+ , use the parser for structured facts (like Facter 2) that comes
5
- # from core
6
- class StructuredFactImporter < ::StructuredFactImporter
7
- def fact_name_class
8
- ForemanAnsible::FactName
9
- end
10
-
11
- def self.authorized_smart_proxy_features
12
- 'Ansible'
13
- end
14
-
15
- def initialize(host, facts = {})
16
- # Try to assign these facts to the correct host as per the facts say
17
- # If that host isn't created yet, the host parameter will contain it
18
- @host = Host.find_by(:name => facts[:ansible_facts][:ansible_fqdn] ||
19
- facts[:ansible_facts][:fqdn]) ||
20
- host
21
- @facts = normalize(facts[:ansible_facts])
22
- @counters = {}
23
- end
24
- end
25
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- module ForemanAnsibleCore
6
- module Runner
7
- class AnsibleRunnerTest < ActiveSupport::TestCase
8
- describe AnsibleRunner do
9
- it 'parses files without event data' do
10
- content = <<~JSON
11
- {"uuid": "a29d8592-f805-4d0e-b73d-7a53cc35a92e", "stdout": " [WARNING]: Consider using the yum module rather than running 'yum'. If you", "counter": 8, "end_line": 8, "runner_ident": "e2d9ae11-026a-4f9f-9679-401e4b852ab0", "start_line": 7, "event": "verbose"}
12
- JSON
13
-
14
- File.expects(:read).with('fake.json').returns(content)
15
- runner = AnsibleRunner.allocate
16
- runner.expects(:handle_broadcast_data)
17
- assert runner.send(:handle_event_file, 'fake.json')
18
- end
19
- end
20
-
21
- describe '#rebuild_secrets' do
22
- let(:inventory) do
23
- { 'all' => { 'hosts' => ['foreman.example.com'] },
24
- '_meta' => { 'hostvars' => { 'foreman.example.com' => {} } } }
25
- end
26
- let(:input) do
27
- host_secrets = { 'ansible_password' => 'letmein', 'ansible_become_password' => 'iamroot' }
28
- secrets = { 'per-host' => { 'foreman.example.com' => host_secrets } }
29
- host_input = { 'input' => { 'action_input' => { 'secrets' => secrets } } }
30
- { 'foreman.example.com' => host_input }
31
- end
32
- let(:runner) { ForemanAnsibleCore::Runner::AnsibleRunner.allocate }
33
-
34
- test 'uses secrets from inventory' do
35
- test_inventory = inventory.merge('ssh_password' => 'sshpass', 'effective_user_password' => 'mypass')
36
- rebuilt = runner.send(:rebuild_secrets, test_inventory, input)
37
- host_vars = rebuilt.dig('_meta', 'hostvars', 'foreman.example.com')
38
- assert_equal 'sshpass', host_vars['ansible_password']
39
- assert_equal 'mypass', host_vars['ansible_become_password']
40
- end
41
-
42
- test 'host secrets are used when not overriden by inventory secrest' do
43
- rebuilt = runner.send(:rebuild_secrets, inventory, input)
44
- host_vars = rebuilt.dig('_meta', 'hostvars', 'foreman.example.com')
45
- assert_equal 'letmein', host_vars['ansible_password']
46
- assert_equal 'iamroot', host_vars['ansible_become_password']
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class CommandCreatorTest < ActiveSupport::TestCase
6
- let(:inventory_file) { 'test_inventory' }
7
- let(:playbook_file) { 'test_palybook.yml' }
8
- subject do
9
- ForemanAnsibleCore::CommandCreator.new(inventory_file, playbook_file, {})
10
- end
11
-
12
- test 'returns a command array including the ansible-playbook command' do
13
- assert command_parts.include?('ansible-playbook')
14
- end
15
-
16
- test 'the last argument is the playbook_file' do
17
- assert command_parts.last == playbook_file
18
- end
19
-
20
- describe 'environment variables' do
21
- let(:environment_variables) { subject.command.first }
22
-
23
- test 'has a JSON_INVENTORY_FILE set' do
24
- assert environment_variables['JSON_INVENTORY_FILE']
25
- end
26
-
27
- test 'has no ANSIBLE_CALLBACK_WHITELIST set by default' do
28
- assert_not environment_variables['ANSIBLE_CALLBACK_WHITELIST']
29
- end
30
-
31
- test 'with a REX command it sets ANSIBLE_CALLBACK_WHITELIST to empty' do
32
- set_command_options(:remote_execution_command, true)
33
- assert environment_variables['ANSIBLE_CALLBACK_WHITELIST']
34
- end
35
- end
36
-
37
- describe 'command options' do
38
- it 'can have verbosity set' do
39
- level = '3'
40
- level_string = Array.new(level.to_i).map { 'v' }.join
41
- set_command_options(:verbosity_level, level)
42
- assert command_parts.any? do |part|
43
- part == "-#{level_string}"
44
- end
45
- end
46
-
47
- it 'can have a timeout set' do
48
- timeout = '5555'
49
- set_command_options(:timeout, timeout)
50
- assert command_parts.include?(timeout)
51
- end
52
- end
53
-
54
- private
55
-
56
- def command_parts
57
- subject.command.flatten.map(&:to_s)
58
- end
59
-
60
- def set_command_options(option, value)
61
- subject.instance_eval("@options[:#{option}] = \"#{value}\"",
62
- __FILE__, __LINE__ - 1)
63
- end
64
- end
@@ -1,110 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- # Playbook Runner - this class uses foreman_tasks_core
6
- # to run playbooks
7
- class PlaybookRunnerTest < ActiveSupport::TestCase
8
- context 'roles dir' do
9
- test 'reads default when none provided' do
10
- ForemanAnsibleCore::Runner::Playbook.any_instance.stubs(:unknown_hosts).
11
- returns([])
12
- File.expects(:exist?).with(Dir.home).returns(true)
13
- ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(nil)
14
- runner = ForemanAnsibleCore::Runner::Playbook.new(nil, nil, :suspended_action => nil)
15
- assert '/etc/ansible', runner.instance_variable_get('@ansible_dir')
16
- end
17
- end
18
-
19
- context 'working_dir' do
20
- setup do
21
- ForemanAnsibleCore::Runner::Playbook.any_instance.stubs(:unknown_hosts).
22
- returns([])
23
- end
24
-
25
- test 'creates temp one if not provided' do
26
- Dir.expects(:mktmpdir)
27
- File.expects(:exist?).with(Dir.home).returns(true)
28
- ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(nil)
29
- ForemanAnsibleCore::Runner::Playbook.new(nil, nil, :suspended_action => nil)
30
- end
31
-
32
- test 'reads it when provided' do
33
- settings = { :working_dir => '/foo', :ansible_dir => '/etc/foo' }
34
- ForemanAnsibleCore.expects(:settings).returns(settings)
35
- File.expects(:exist?).with(settings[:ansible_dir]).returns(true)
36
- Dir.expects(:mktmpdir).never
37
- ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(nil)
38
- runner = ForemanAnsibleCore::Runner::Playbook.new(nil, nil, :suspended_action => nil)
39
- assert '/foo', runner.instance_variable_get('@working_dir')
40
- end
41
- end
42
-
43
- context 'TOFU policy' do # Trust On First Use
44
- setup do
45
- @inventory = { 'all' => { 'hosts' => ['foreman.example.com'] } }
46
- @output = StringIO.new
47
- logger = Logger.new(@output)
48
- ForemanAnsibleCore::Runner::Playbook.any_instance.stubs(:logger).
49
- returns(logger)
50
- end
51
-
52
- test 'ignores known hosts' do
53
- Net::SSH::KnownHosts.expects(:search_for).
54
- with('foreman.example.com').returns(['somekey'])
55
- ForemanAnsibleCore::Runner::Playbook.any_instance.
56
- expects(:add_to_known_hosts).never
57
- ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(@inventory)
58
- ForemanAnsibleCore::Runner::Playbook.new(@inventory, nil, :suspended_action => nil)
59
- end
60
-
61
- test 'adds unknown hosts to known_hosts' do
62
- Net::SSH::KnownHosts.expects(:search_for).
63
- with('foreman.example.com').returns([])
64
- ForemanAnsibleCore::Runner::Playbook.any_instance.
65
- expects(:add_to_known_hosts).with('foreman.example.com')
66
- ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(@inventory)
67
- ForemanAnsibleCore::Runner::Playbook.new(@inventory, nil, :suspended_action => nil)
68
- end
69
-
70
- test 'logs error when it cannot add to known_hosts' do
71
- Net::SSH::KnownHosts.expects(:search_for).
72
- with('foreman.example.com').returns([])
73
- Net::SSH::Transport::Session.expects(:new).with('foreman.example.com').
74
- raises(Net::Error)
75
- ForemanAnsibleCore::Runner::Playbook.any_instance.expects(:rebuild_secrets).returns(@inventory)
76
- ForemanAnsibleCore::Runner::Playbook.new(@inventory, nil, :suspended_action => nil)
77
- assert_match(
78
- /ERROR.*Failed to save host key for foreman.example.com: Net::Error/,
79
- @output.string
80
- )
81
- end
82
- end
83
-
84
- context 'rebuild secrets' do
85
- let(:inventory) do
86
- { 'all' => { 'hosts' => ['foreman.example.com'] },
87
- '_meta' => { 'hostvars' => { 'foreman.example.com' => {} } } }
88
- end
89
- let(:secrets) do
90
- host_secrets = { 'ansible_password' => 'letmein', 'ansible_become_password' => 'iamroot' }
91
- { 'per-host' => { 'foreman.example.com' => host_secrets } }
92
- end
93
- let(:runner) { ForemanAnsibleCore::Runner::Playbook.allocate }
94
-
95
- test 'uses secrets from inventory' do
96
- test_inventory = inventory.merge('ssh_password' => 'sshpass', 'effective_user_password' => 'mypass')
97
- rebuilt = runner.send(:rebuild_secrets, test_inventory, secrets)
98
- host_vars = rebuilt.dig('_meta', 'hostvars', 'foreman.example.com')
99
- assert_equal 'sshpass', host_vars['ansible_password']
100
- assert_equal 'mypass', host_vars['ansible_become_password']
101
- end
102
-
103
- test 'host secrets are used when not overriden by inventory secrest' do
104
- rebuilt = runner.send(:rebuild_secrets, inventory, secrets)
105
- host_vars = rebuilt.dig('_meta', 'hostvars', 'foreman.example.com')
106
- assert_equal 'letmein', host_vars['ansible_password']
107
- assert_equal 'iamroot', host_vars['ansible_become_password']
108
- end
109
- end
110
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_plugin_helper'
4
-
5
- module ForemanAnsible
6
- # Test for the facts importer - only verify that given
7
- # a set of facts it's able to import them
8
- class FactImporterTest < ActiveSupport::TestCase
9
- setup do
10
- @host = FactoryBot.build(:host)
11
- end
12
-
13
- test 'add new facts adds all fact names in the fixture' do
14
- @fact_importer = FactImporter.new(@host, facts_json)
15
- facts_to_be_added = FactSparser.sparse(facts_json[:ansible_facts]).keys +
16
- FactSparser.unsparse(facts_json[:ansible_facts]).keys
17
- @fact_importer.send(:add_new_facts)
18
- assert((facts_to_be_added - FactName.all.map(&:name)).empty?)
19
- end
20
-
21
- test 'missing_facts returns facts we do not have in the database' do
22
- @fact_importer = FactImporter.new(@host, facts_json)
23
- @fact_importer.expects(:host_fact_names).
24
- returns(['ansible_cmdline'])
25
- refute @fact_importer.send(:missing_facts).include?('ansible_cmdline')
26
- end
27
-
28
- describe '#add_fact_value' do
29
- setup do
30
- @fact_importer = FactImporter.new(@host, :ansible_facts => {})
31
- end
32
- test 'does not add existing facts' do
33
- existing_fact = FactoryBot.build(:fact_name)
34
- @fact_importer.expects(:missing_facts).returns([])
35
- assert_nil @fact_importer.send(:add_fact_value, nil, existing_fact)
36
- end
37
-
38
- test 'adds missing facts' do
39
- missing_fact = FactoryBot.build(:fact_name)
40
- @fact_importer.expects(:missing_facts).returns([missing_fact.name])
41
- @fact_importer.counters[:added] = 0
42
- assert_difference('@host.fact_values.count', 1) do
43
- @fact_importer.send(:add_fact_value, 'missing_value', missing_fact)
44
- @host.save
45
- # We have to save the host in order to ensure @host.fact_values.count
46
- # resolves properly (otherwise) :add_fact_value just won't save the
47
- # relation
48
- end
49
- end
50
- end
51
- end
52
- end