foreman_ansible 6.4.0 → 7.0.2

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.
Files changed (140) 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/resolvers/ansible_role/path.rb +11 -0
  10. data/app/graphql/resolvers/ansible_variable/path.rb +11 -0
  11. data/app/graphql/types/ansible_role.rb +10 -0
  12. data/app/graphql/types/ansible_variable.rb +24 -0
  13. data/app/graphql/types/ansible_variable_override.rb +9 -0
  14. data/app/graphql/types/inherited_ansible_role.rb +13 -0
  15. data/app/graphql/types/overriden_ansible_variable.rb +27 -0
  16. data/app/helpers/foreman_ansible/ansible_roles_data_preparations.rb +22 -22
  17. data/app/models/concerns/foreman_ansible/host_managed_extensions.rb +23 -4
  18. data/app/models/concerns/foreman_ansible/hostgroup_extensions.rb +2 -1
  19. data/app/models/foreman_ansible/ansible_provider.rb +8 -6
  20. data/app/services/foreman_ansible/ansible_report_importer.rb +2 -6
  21. data/app/services/foreman_ansible/inventory_creator.rb +1 -1
  22. data/app/services/foreman_ansible/override_resolver.rb +22 -0
  23. data/app/views/api/v2/ansible_override_values/index.json.rabl +3 -0
  24. data/app/views/api/v2/ansible_variables/show.json.rabl +1 -1
  25. data/app/views/foreman_ansible/ansible_roles/_hostgroup_ansible_roles_button.erb +3 -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 +1 -17
  31. data/lib/foreman_ansible/register.rb +115 -4
  32. data/lib/foreman_ansible/version.rb +1 -1
  33. data/package.json +4 -2
  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/hostgroup_ansible_role_test.rb +13 -0
  41. data/test/unit/services/override_resolver_test.rb +34 -0
  42. data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.js +52 -27
  43. data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.scss +5 -1
  44. data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.test.js +12 -6
  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 +240 -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 +438 -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 +61 -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 +74 -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 +85 -0
  77. data/webpack/components/AnsibleHostDetail/components/RolesTab/RolesTable.js +131 -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 +191 -0
  80. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.test.js +79 -0
  81. data/webpack/components/AnsibleHostDetail/components/RolesTab/index.js +75 -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/AnsibleRolesAndVariables/__test__/AnsibleRolesAndVariablesImport.test.js +15 -10
  87. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.js +29 -0
  88. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.test.js +3 -0
  89. data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.js +2 -1
  90. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsibleRole.test.js.snap +3 -3
  91. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +4 -0
  92. data/webpack/components/DualList/DualList.scss +3 -0
  93. data/webpack/components/DualList/ListControls.js +65 -0
  94. data/webpack/components/DualList/ListHeader.js +16 -0
  95. data/webpack/components/DualList/ListItem.js +69 -0
  96. data/webpack/components/DualList/ListPane.js +95 -0
  97. data/webpack/components/DualList/SelectedStatus.js +21 -0
  98. data/webpack/components/DualList/index.js +103 -0
  99. data/webpack/components/ErrorState.js +16 -0
  100. data/webpack/components/withLoading.js +135 -0
  101. data/webpack/components/withPagination.js +0 -0
  102. data/webpack/formHelper.js +131 -0
  103. data/webpack/globalIdHelper.js +13 -0
  104. data/webpack/global_index.js +7 -1
  105. data/webpack/graphql/mutations/assignAnsibleRoles.gql +17 -0
  106. data/webpack/graphql/mutations/cancelRecurringLogic.gql +12 -0
  107. data/webpack/graphql/mutations/createAnsibleVariableOverride.gql +28 -0
  108. data/webpack/graphql/mutations/createJobInvocation.gql +11 -0
  109. data/webpack/graphql/mutations/deleteAnsibleVariableOverride.gql +17 -0
  110. data/webpack/graphql/mutations/updateAnsibleVariableOverride.gql +29 -0
  111. data/webpack/graphql/queries/allAnsibleRoles.gql +13 -0
  112. data/webpack/graphql/queries/ansibleRoles.gql +13 -0
  113. data/webpack/graphql/queries/currentUserAttributes.gql +11 -0
  114. data/webpack/graphql/queries/hostAnsibleRoles.gql +18 -0
  115. data/webpack/graphql/queries/hostAvailableAnsibleRoles.gql +11 -0
  116. data/webpack/graphql/queries/hostVariableOverrides.gql +40 -0
  117. data/webpack/graphql/queries/recurringJobs.gql +28 -0
  118. data/webpack/helpers/pageParamsHelper.js +40 -0
  119. data/webpack/helpers/paginationHelper.js +9 -0
  120. data/webpack/permissionsHelper.js +58 -0
  121. data/webpack/routes/HostgroupJobs/__test__/HostgroupJobs.fixtures.js +63 -0
  122. data/webpack/routes/HostgroupJobs/__test__/HostgroupJobs.test.js +112 -0
  123. data/webpack/routes/HostgroupJobs/index.js +26 -0
  124. data/webpack/routes/routes.js +10 -0
  125. data/webpack/testHelper.js +165 -0
  126. data/webpack/toastHelper.js +4 -0
  127. metadata +129 -54
  128. data/app/assets/images/foreman_ansible/Ansible.png +0 -0
  129. data/app/models/foreman_ansible/fact_name.rb +0 -16
  130. data/app/models/setting/ansible.rb +0 -106
  131. data/app/services/foreman_ansible/fact_importer.rb +0 -99
  132. data/app/services/foreman_ansible/fact_parser.rb +0 -126
  133. data/app/services/foreman_ansible/fact_sparser.rb +0 -37
  134. data/app/services/foreman_ansible/operating_system_parser.rb +0 -102
  135. data/app/services/foreman_ansible/structured_fact_importer.rb +0 -25
  136. data/test/unit/services/fact_importer_test.rb +0 -52
  137. data/test/unit/services/fact_parser_test.rb +0 -281
  138. data/test/unit/services/fact_sparser_test.rb +0 -24
  139. data/test/unit/services/structured_fact_importer_test.rb +0 -30
  140. data/webpack/components/AnsibleRolesAndVariables/__test__/__snapshots__/AnsibleRolesAndVariablesImport.test.js.snap +0 -177
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05c975cb77fe5add41b7281dfa1c2451bb22a09ab5dc6251ab06fd4d00b834e2
4
- data.tar.gz: 86613f4be767b5af80a06f83b9e13f8f030cd80bc362d866323111b61a0b23a9
3
+ metadata.gz: 299049c29764a0920259664c06288f37ea56d4b920e049243baeab9ad7f2e608
4
+ data.tar.gz: 779264101df1f9fa6e0188c8673a435b98eb4dbd9fd814e754f991247b5bb250
5
5
  SHA512:
6
- metadata.gz: dc27695cef374e8b709ddc3c3882056587cbf975ac7d497c1fec5aaa1885f85bcb3677c2c7fd3f2602f529cba0a6736017703f6d7ca413eb5f2ed7a6de112a94
7
- data.tar.gz: ba0c5f9b94a51b7328cc0df73bfcc0f47831b1004b275be935fa73a83ae9c6f12b81086071ebe69292c8aa5ad436c5389a6a6f1ac457720bcefe034b456c0ec8
6
+ metadata.gz: '08a1b935eb0c033ff08674e4922ee597d39ed602ef351b82d9ac763af9d850e5a32ff9ea482af7f74a641552ebaf62094b6fa59170cba317b5bba67949d31a8d'
7
+ data.tar.gz: 3f814381b2167e370757f761a0b5d3e1217e3c3ba4293d7f1ecf1e77599c232ef8c62beae293c8593d81ab4e305ae1cced983527bc6d29e248bbda3a3f4e731e
@@ -90,7 +90,7 @@ module Api
90
90
  private
91
91
 
92
92
  def schedule_params
93
- template_name = Setting::Ansible.find_by(:name => 'ansible_inventory_template').value
93
+ template_name = Setting['ansible_inventory_template']
94
94
  @report_template = ReportTemplate.find_by!(:name => template_name)
95
95
  params[:id] = @report_template.id
96
96
  params[:report_format] = 'json' if params[:report_format].blank?
@@ -0,0 +1,26 @@
1
+ module Mutations
2
+ module AnsibleVariableOverrides
3
+ class Create < ::Mutations::CreateMutation
4
+ graphql_name 'CreateAnsibleVariableOverrideMutation'
5
+ description 'Creates Ansible Variable Override'
6
+
7
+ resource_class LookupValue
8
+
9
+ argument :host_id, Int, required: true
10
+ argument :lookup_key_id, Int, required: true
11
+ argument :value, ::Types::RawJson, required: true
12
+ argument :match, String, required: true
13
+ argument :omit, Boolean
14
+
15
+ field :overriden_ansible_variable, ::Types::OverridenAnsibleVariable, :null => true
16
+
17
+ def resolve(host_id:, **kwargs)
18
+ result = super kwargs
19
+ host = Host.find host_id
20
+ vars = AnsibleVariable.where :id => kwargs[:lookup_key_id]
21
+ resolver = ::ForemanAnsible::OverrideResolver.new(host, vars)
22
+ result.merge :overriden_ansible_variable => ::Presenters::OverridenAnsibleVariablePresenter.new(vars.first, resolver)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,38 @@
1
+ module Mutations
2
+ module AnsibleVariableOverrides
3
+ class Delete < ::Mutations::DeleteMutation
4
+ graphql_name 'DeleteAnsibleVariableOverride'
5
+ description 'Deletes Ansible Variable Override'
6
+
7
+ resource_class LookupValue
8
+
9
+ argument :host_id, Int, required: true
10
+ argument :variable_id, Int, required: true
11
+
12
+ field :overriden_ansible_variable, ::Types::OverridenAnsibleVariable, :null => true
13
+
14
+ def resolve(id:, host_id:, variable_id:)
15
+ host = Host.find_by :id => host_id
16
+ variable = AnsibleVariable.find_by :id => variable_id
17
+ return resource_not_found(_('Host not found by id: %s'), host_id) unless host
18
+ return resource_not_found(_('Ansible Variable not found by id: %s'), variable_id) unless variable
19
+ authorize!(host, :view)
20
+ authorize!(variable, :edit)
21
+
22
+ result = super id: id
23
+ resolver = ::ForemanAnsible::OverrideResolver.new(host, [variable.id])
24
+ result.merge :overriden_ansible_variable => ::Presenters::OverridenAnsibleVariablePresenter.new(variable, resolver)
25
+ end
26
+
27
+ def resource_not_found(message)
28
+ {
29
+ :overriden_ansible_variable => nil,
30
+ :errros => [{
31
+ :path => ['base'],
32
+ :message => message
33
+ }]
34
+ }
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,26 @@
1
+ module Mutations
2
+ module AnsibleVariableOverrides
3
+ class Update < ::Mutations::UpdateMutation
4
+ graphql_name 'UpdateAnsibleVariableOverrideMutation'
5
+ description 'Updates Ansible Variable Override'
6
+
7
+ resource_class LookupValue
8
+
9
+ argument :value, ::Types::RawJson, required: true
10
+ argument :match, String, required: false
11
+ argument :omit, Boolean, required: false
12
+ argument :host_id, Int, required: true
13
+ argument :ansible_variable_id, Int, required: true
14
+
15
+ field :overriden_ansible_variable, ::Types::OverridenAnsibleVariable, :null => true
16
+
17
+ def resolve(host_id:, ansible_variable_id:, **kwargs)
18
+ result = super kwargs
19
+ host = Host.find host_id
20
+ vars = AnsibleVariable.where :id => ansible_variable_id
21
+ resolver = ::ForemanAnsible::OverrideResolver.new(host, vars.pluck(:id))
22
+ result.merge :overriden_ansible_variable => ::Presenters::OverridenAnsibleVariablePresenter.new(vars.first, resolver)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ module Mutations
2
+ module Hosts
3
+ class AssignAnsibleRoles < ::Mutations::UpdateMutation
4
+ resource_class Host::Managed
5
+
6
+ argument :ansible_role_ids, [Integer], required: true
7
+
8
+ field :host, Types::Host, 'The updated host.', null: false
9
+
10
+ def resolve(id:, ansible_role_ids:)
11
+ host = load_object_by(id: id)
12
+ authorize!(host, :edit)
13
+
14
+ existing = host.host_ansible_roles
15
+ updated_ids = []
16
+ attrs = []
17
+
18
+ ansible_role_ids.each do |role_id|
19
+ current = existing.find_by :ansible_role_id => role_id
20
+ attrs << { :id => current&.id, :position => attrs.count + 1, :ansible_role_id => role_id }
21
+ updated_ids << current.id if current
22
+ end
23
+
24
+ existing.where.not(:id => updated_ids).each do |item|
25
+ attrs << { :id => item.id, :position => attrs.count + 1, :_destroy => true }
26
+ end
27
+
28
+ host.host_ansible_roles_attributes = attrs
29
+ save_object(host)
30
+ end
31
+
32
+ def result_key
33
+ :host
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,12 @@
1
+ module Presenters
2
+ class AnsibleRolePresenter
3
+ attr_reader :ansible_role, :inherited
4
+
5
+ delegate :id, :name, :association, :to => :ansible_role
6
+
7
+ def initialize(ansible_role, inherited)
8
+ @ansible_role = ansible_role
9
+ @inherited = inherited
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ module Presenters
2
+ class OverridenAnsibleVariablePresenter
3
+ attr_reader :ansible_variable
4
+
5
+ delegate :id, :key, :description, :override?,
6
+ :parameter_type, :hidden_value?, :omit, :required,
7
+ :validator_type, :validator_rule, :default_value,
8
+ :ansible_role, :current_value, :to => :ansible_variable
9
+
10
+ def initialize(ansible_variable, override_resolver)
11
+ @ansible_variable = ansible_variable
12
+ @override_resolver = override_resolver
13
+ end
14
+
15
+ def current_value
16
+ @override_resolver.resolve @ansible_variable
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ module Resolvers
2
+ module AnsibleRole
3
+ class Path < Resolvers::BaseResolver
4
+ type String, null: false
5
+
6
+ def resolve
7
+ Rails.application.routes.url_helpers.ansible_roles_path(search: "name = #{object.name}")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Resolvers
2
+ module AnsibleVariable
3
+ class Path < Resolvers::BaseResolver
4
+ type String, null: false
5
+
6
+ def resolve
7
+ Rails.application.routes.url_helpers.edit_ansible_variable_path(object.ansible_variable)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Types
2
+ class AnsibleRole < BaseObject
3
+ description 'Ansible role'
4
+
5
+ global_id_field :id
6
+
7
+ field :name, String, :null => false
8
+ field :path, resolver: Resolvers::AnsibleRole::Path
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ module Types
2
+ class AnsibleVariable < BaseObject
3
+ description 'Ansible Variable'
4
+
5
+ global_id_field :id
6
+
7
+ field :key, String
8
+ field :path, resolver: Resolvers::AnsibleVariable::Path
9
+ field :override, Boolean
10
+ field :description, String
11
+ field :hidden_value, Boolean
12
+ field :parameter_type, String
13
+ field :omit, Boolean
14
+ field :required, Boolean
15
+ field :validator_type, String
16
+ field :validator_rule, String
17
+ field :default_value, ::Types::RawJson
18
+ field :ansible_role_name, String
19
+
20
+ def ansible_role_name
21
+ object.ansible_role.name
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ module Types
2
+ class AnsibleVariableOverride < GraphQL::Types::Relay::BaseObject
3
+ description 'Override value for Ansible Variable'
4
+
5
+ field :value, ::Types::RawJson, :null => false
6
+ field :element, ::Types::RawJson, :null => false
7
+ field :element_name, ::Types::RawJson, :null => false
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module Types
2
+ class InheritedAnsibleRole < ::Types::AnsibleRole
3
+ field :inherited, Boolean, :null => false
4
+
5
+ def object_class
6
+ object.ansible_role.class
7
+ end
8
+
9
+ def load_object
10
+ object.ansible_role
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ module Types
2
+ class OverridenAnsibleVariable < ::Types::AnsibleVariable
3
+ description 'Ansible Variable with an override value for a host'
4
+ model_class ::AnsibleVariable
5
+
6
+ field :current_value, ::Types::AnsibleVariableOverride, :null => true
7
+ field :lookup_values, ::Types::LookupValue.connection_type do
8
+ argument :match, String, required: false
9
+ end
10
+
11
+ field :meta, ::Types::Meta, resolve: (proc do |object|
12
+ {
13
+ :can_edit => ::User.current.can?(object.ansible_variable.permission_name(:edit), object.ansible_variable),
14
+ :can_destroy => ::User.current.can?(object.ansible_variable.permission_name(:destroy), object.ansible_variable)
15
+ }
16
+ end)
17
+
18
+ def lookup_values(match: nil)
19
+ return CollectionLoader.for(object.ansible_variable.class, :lookup_values).load(object.ansible_variable) unless match
20
+
21
+ scope = lambda do |sc|
22
+ sc.where(:match => match)
23
+ end
24
+ CollectionLoader.for(object.ansible_variable.class, :lookup_values, scope).load(object.ansible_variable)
25
+ end
26
+ end
27
+ end
@@ -2,22 +2,22 @@
2
2
 
3
3
  module ForemanAnsible
4
4
  module AnsibleRolesDataPreparations
5
- VARIABLE_ACTION_NAMES = { 'new' => N_('Add'), 'obsolete' => N_('Remove'), 'update' => N_('Update') }.freeze
6
- ROLE_ACTION_NAMES = { 'new' => N_('Import Role'), 'obsolete' => N_('Remove Role'), 'old' => N_('Update Role Variables') }.freeze
5
+ VARIABLE_ACTION_NAMES = { 'new' => _('Add'), 'obsolete' => _('Remove'), 'update' => _('Update') }.freeze
6
+ ROLE_ACTION_NAMES = { 'new' => _('Import Role'), 'obsolete' => _('Remove Role'), 'old' => _('Update Role Variables') }.freeze
7
7
 
8
- def get_variable_action(kind)
9
- _(VARIABLE_ACTION_NAMES[kind])
8
+ def variable_action_name(kind)
9
+ VARIABLE_ACTION_NAMES[kind]
10
10
  end
11
11
 
12
- def get_role_action(kind)
13
- _(ROLE_ACTION_NAMES[kind])
12
+ def role_action_name(kind)
13
+ ROLE_ACTION_NAMES[kind]
14
14
  end
15
15
 
16
16
  def get_old_roles_variables(imported_variables, role)
17
- variables = { 'Add' => [], 'Remove' => [], 'Update' => [] }
17
+ variables = { 'new' => [], 'obsolete' => [], 'update' => [] }
18
18
  imported_variables.each do |kind, temp_variables|
19
19
  temp_variables.each do |temp_variable|
20
- variables[get_variable_action(kind)].append(temp_variable.key) if temp_variable.ansible_role_id == role.id
20
+ variables[kind].append(temp_variable.key) if temp_variable.ansible_role_id == role.id
21
21
  end
22
22
  end
23
23
  variables
@@ -26,16 +26,16 @@ module ForemanAnsible
26
26
  def variables_to_s(variables)
27
27
  str = ''
28
28
  variables.each do |action, temp_variables|
29
- str += "#{action}: #{temp_variables.size}, " unless temp_variables.empty?
29
+ str += "#{variable_action_name action}: #{temp_variables.size}, " unless temp_variables.empty?
30
30
  end
31
31
  str[0..-3]
32
32
  end
33
33
 
34
34
  def get_roles_variables(imported_variables, variables_importer, kind, role)
35
35
  if kind == 'new'
36
- variables = { 'Add' => variables_importer.get_variables_names(role.name) }
36
+ variables = { 'new' => variables_importer.get_variables_names(role.name) }
37
37
  elsif kind == 'obsolete'
38
- variables = { 'Remove' => role.ansible_variables.map(&:key) }
38
+ variables = { 'obsolete' => role.ansible_variables.map(&:key) }
39
39
  elsif kind == 'old'
40
40
  variables = get_old_roles_variables(imported_variables, role)
41
41
  end
@@ -51,24 +51,25 @@ module ForemanAnsible
51
51
  match.to_s.empty? ? nil : match
52
52
  end
53
53
 
54
- def prepare_api_row(role, kind, variables, role_action)
54
+ def prepare_api_row(role, kind, variables)
55
55
  {
56
56
  name: role.name,
57
57
  id: role.id,
58
- role_action: role_action,
58
+ role_action: role_action_name(kind),
59
59
  variables: variables,
60
- hosts_count: role_action == 'Remove Role' ? role.hosts.count : '',
61
- hostgroup_count: role_action == 'Remove Role' ? role.hostgroups.count : '',
60
+ hosts_count: kind == 'obsolete' ? role.hosts.count : '',
61
+ hostgroup_count: kind == 'obsolete' ? role.hostgroups.count : '',
62
62
  kind: kind
63
63
  }
64
64
  end
65
65
 
66
- def prepare_ui_row(role, kind, variables, role_action)
66
+ def prepare_ui_row(role, kind, variables)
67
67
  { cells: [
68
68
  role.name,
69
- role_action, variables,
70
- role_action == 'Remove Role' ? role.hosts.count : '',
71
- role_action == 'Remove Role' ? role.hostgroups.count : ''
69
+ role_action_name(kind),
70
+ variables,
71
+ kind == 'obsolete' ? role.hosts.count : '',
72
+ kind == 'obsolete' ? role.hostgroups.count : ''
72
73
  ],
73
74
  role: role, kind: kind, id: role.name }
74
75
  end
@@ -81,11 +82,10 @@ module ForemanAnsible
81
82
  next if role_match_excluded_roles(role.name)
82
83
  variables = get_roles_variables(imported_variables, variables_importer, kind, role)
83
84
  next if variables.empty? && kind['old']
84
- role_action = get_role_action(kind)
85
85
  if is_ui
86
- rows.append(prepare_ui_row(role, kind, variables, role_action))
86
+ rows.append(prepare_ui_row(role, kind, variables))
87
87
  else
88
- rows.append(prepare_api_row(role, kind, variables, role_action))
88
+ rows.append(prepare_api_row(role, kind, variables))
89
89
  end
90
90
  end
91
91
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ipaddress'
3
+ require 'resolv'
4
4
  module ForemanAnsible
5
5
  # Relations to make Host::Managed 'have' ansible roles
6
6
  module HostManagedExtensions
@@ -16,7 +16,7 @@ module ForemanAnsible
16
16
  :dependent => :destroy
17
17
  scoped_search :relation => :ansible_roles, :on => :name,
18
18
  :complete_value => true, :rename => :ansible_role,
19
- :only_explicit => true
19
+ :only_explicit => true, ext_method: :search_by_role
20
20
 
21
21
  before_provision :play_ansible_roles
22
22
  audit_associations :ansible_roles
@@ -30,6 +30,14 @@ module ForemanAnsible
30
30
  hostgroup.inherited_and_own_ansible_roles
31
31
  end
32
32
 
33
+ def own_ansible_roles
34
+ ansible_roles.where.not(:id => inherited_ansible_roles.pluck(:id))
35
+ end
36
+
37
+ def available_ansible_roles
38
+ AnsibleRole.where.not(:id => all_ansible_roles.pluck(:id))
39
+ end
40
+
33
41
  # This one should be fixed, disabled for the moment as we're
34
42
  # in a rush to get the release out
35
43
  def play_ansible_roles
@@ -39,7 +47,7 @@ module ForemanAnsible
39
47
  composer.triggering.mode = :future
40
48
  composer.triggering.start_at = (
41
49
  Time.zone.now +
42
- Setting::Ansible[:ansible_post_provision_timeout].to_i.seconds
50
+ Setting[:ansible_post_provision_timeout].to_i.seconds
43
51
  )
44
52
  composer.trigger!
45
53
  logger.info("Task for Ansible roles on #{self} before_provision: "\
@@ -58,12 +66,23 @@ module ForemanAnsible
58
66
  def import_host(*args)
59
67
  host = super(*args)
60
68
  hostname = args[0]
61
- if IPAddress.valid?(hostname) &&
69
+ if (Resolv::IPv4::Regex.match?(hostname) || Resolv::IPv6::Regex.match?(hostname)) &&
62
70
  (host_nic = Nic::Interface.find_by(:ip => hostname))
63
71
  host = host_nic.host
64
72
  end
65
73
  host
66
74
  end
75
+
76
+ def search_by_role(_key, operator, value)
77
+ conditions = sanitize_sql_for_conditions(["ansible_roles.name #{operator} ?", value_to_sql(operator, value)])
78
+ host_ids = ::Host::Managed.joins(:ansible_roles).where(conditions).distinct.pluck(:id)
79
+ hostgroup_ids = ::Hostgroup.unscoped.with_taxonomy_scope.joins(:ansible_roles).where(conditions).map(&:subtree_ids).flatten
80
+
81
+ conds = []
82
+ conds << "hosts.id IN(#{host_ids.join(',')})" if host_ids.present?
83
+ conds << "hosts.hostgroup_id IN(#{hostgroup_ids.uniq.join(',')})" if hostgroup_ids.present?
84
+ { conditions: conds.join(' OR ').presence || '1 = 0' }
85
+ end
67
86
  end
68
87
  end
69
88
  end
@@ -6,13 +6,14 @@ module ForemanAnsible
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
- has_many :hostgroup_ansible_roles, :foreign_key => :hostgroup_id
9
+ has_many :hostgroup_ansible_roles, -> { order('hostgroup_ansible_roles.position ASC') }, :foreign_key => :hostgroup_id
10
10
  has_many :ansible_roles,
11
11
  -> { order('hostgroup_ansible_roles.position ASC') },
12
12
  :through => :hostgroup_ansible_roles,
13
13
  :dependent => :destroy
14
14
  accepts_nested_attributes_for :hostgroup_ansible_roles, :allow_destroy => true
15
15
  audit_associations :ansible_roles
16
+ include_in_clone :ansible_roles
16
17
 
17
18
  def inherited_ansible_roles
18
19
  ancestors.reduce([]) do |roles, hostgroup|
@@ -32,12 +32,14 @@ if defined? ForemanRemoteExecution
32
32
  template_invocation.template
33
33
  ),
34
34
  :name => host.name,
35
- :check_mode => host.host_param('ansible_roles_check_mode')
35
+ :check_mode => host.host_param('ansible_roles_check_mode'),
36
+ :cleanup_working_dirs => cleanup_working_dirs?(host)
36
37
  )
37
38
  end
38
39
 
39
40
  def secrets(host)
40
41
  {
42
+ :key_passphrase => Setting[:remote_execution_ssh_key_passphrase],
41
43
  'per-host' => {
42
44
  host.name => {
43
45
  'ansible_password' => rex_ssh_password(host),
@@ -55,10 +57,6 @@ if defined? ForemanRemoteExecution
55
57
  host_setting(host, 'remote_execution_effective_user_password')
56
58
  end
57
59
 
58
- def host_setting(host, setting)
59
- host.params[setting.to_s] || Setting[setting]
60
- end
61
-
62
60
  def supports_effective_user?
63
61
  true
64
62
  end
@@ -90,7 +88,7 @@ if defined? ForemanRemoteExecution
90
88
  :children => [
91
89
  {
92
90
  :name => :tags,
93
- :type => Array,
91
+ :type => String,
94
92
  :opts => { :required => false, :desc => N_('A comma separated list of tags to use for Ansible run') }
95
93
  },
96
94
  {
@@ -116,6 +114,10 @@ if defined? ForemanRemoteExecution
116
114
  'Proxy::Ansible::TaskLauncher::Playbook::PlaybookRunnerAction'
117
115
  end
118
116
 
117
+ def proxy_batch_size
118
+ Setting['foreman_ansible_proxy_batch_size']
119
+ end
120
+
119
121
  private
120
122
 
121
123
  def ansible_command?(template)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ipaddress'
3
+ require 'resolv'
4
4
  module ForemanAnsible
5
5
  # Ensures Ansible reports from hosts where the IP was used, are assigned
6
6
  # to the right hostname in Foreman
@@ -10,7 +10,7 @@ module ForemanAnsible
10
10
  def host
11
11
  hostname = name.downcase
12
12
  if AnsibleReportScanner.ansible_report?(raw) &&
13
- IPAddress.valid?(hostname) &&
13
+ (Resolv::IPv4::Regex.match?(hostname) || Resolv::IPv6::Regex.match?(hostname)) &&
14
14
  Nic::Interface.find_by(:ip => hostname)
15
15
  @host = Nic::Interface.find_by(:ip => hostname).host
16
16
  end
@@ -18,10 +18,6 @@ module ForemanAnsible
18
18
  partial_hostname_match(hostname)
19
19
  end
20
20
 
21
- def self.authorized_smart_proxy_features
22
- super + ['Ansible']
23
- end
24
-
25
21
  def partial_hostname_match(hostname)
26
22
  return @host unless @host.new_record?
27
23
  hosts = Host.where(Host.arel_table[:name].matches("#{hostname}.%"))
@@ -103,7 +103,7 @@ module ForemanAnsible
103
103
  'ansible_port' => host_setting(host, 'remote_execution_ssh_port'),
104
104
  'ansible_host' => AnsibleProvider.find_ip_or_hostname(host)
105
105
  }
106
- if @template_invocation.effective_user.present?
106
+ if @template_invocation.effective_user.present? && @template_invocation.effective_user != params['ansible_user']
107
107
  params['ansible_become_user'] = @template_invocation.effective_user
108
108
  params['ansible_become'] = true
109
109
  end
@@ -0,0 +1,22 @@
1
+ module ForemanAnsible
2
+ # Service which resolves override values for hosts
3
+ class OverrideResolver
4
+ attr_reader :overrides, :ansible_variables
5
+
6
+ def initialize(host, variable_ids = [])
7
+ raise(Foreman::Exception.new('OverrideResolver needs a host to resolve overrides')) unless host
8
+ @ansible_variables = if variable_ids.empty?
9
+ AnsibleVariable.where(:ansible_role_id => host.all_ansible_roles, :override => true)
10
+ else
11
+ AnsibleVariable.where(:id => variable_ids, :override => true)
12
+ end
13
+ @overrides = @ansible_variables.values_hash(host).raw
14
+ end
15
+
16
+ def resolve(ansible_variable)
17
+ override = @overrides[ansible_variable.id]
18
+ return unless override
19
+ override[ansible_variable.key]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ collection @override_values
2
+
3
+ extends 'api/v2/ansible_override_values/show'
@@ -10,7 +10,7 @@ attributes :id, :variable, :ansible_role, :ansible_role_id, :description, :overr
10
10
  node do |ansible_variable|
11
11
  {
12
12
  :override_values => partial(
13
- 'api/v2/override_values/index',
13
+ 'api/v2/ansible_override_values/index',
14
14
  :object => ansible_variable.lookup_values
15
15
  )
16
16
  }
@@ -5,11 +5,14 @@
5
5
  display_link_if_authorized(_('Run all Ansible roles'), hash_for_play_roles_hostgroup_path(id: hostgroup), :'data-no-turbolink' => true, title: _('Run all Ansible roles on hosts belonging to this host group'))
6
6
  end
7
7
 
8
+ assign_jobs = link_to(_("Configure Ansible Job"), "/ansible/hostgroups/#{hostgroup.id}", { class: 'la' })
9
+
8
10
  actions = [
9
11
  display_link_if_authorized(_('Nest'), hash_for_nest_hostgroup_path(:id => hostgroup)),
10
12
  display_link_if_authorized(_('Clone'), hash_for_clone_hostgroup_path(:id => hostgroup))
11
13
  ]
12
14
  actions.push play_roles if User.current.can?(:create_job_invocations)
15
+ actions.push assign_jobs if User.current.can?(:view_job_invocations) && User.current.can?(:view_recurring_logics)
13
16
  actions.push display_delete_if_authorized(hash_for_hostgroup_path(:id => hostgroup).merge(:auth_object => hostgroup, :authorizer => authorizer), :data => { :confirm => warning_message(hostgroup) })
14
17
 
15
18
  action_buttons(*actions)
@@ -5,13 +5,17 @@ template_inputs:
5
5
  - name: Activation Key
6
6
  required: true
7
7
  input_type: user
8
+ description: Set the activation key to assign the desired RHEL subscription and
9
+ life cycle environment to the converted machine at the registration step.
8
10
  advanced: false
9
- value_type: plain
11
+ value_type: resource
10
12
  resource_type: Katello::ActivationKey
11
13
  hidden_value: false
12
14
  - name: Restart
13
15
  required: true
14
16
  input_type: user
17
+ description: Restart the system when it is successfully converted to RHEL to boot
18
+ the new RHEL kernel.
15
19
  options: "yes\r\nno"
16
20
  advanced: false
17
21
  value_type: plain
@@ -34,7 +38,7 @@ kind: job_template
34
38
  url: <%= subscription_manager_configuration_url(@host) %>
35
39
  dest: /usr/share/convert2rhel/subscription-manager/katello-ca-consumer-latest.noarch.rpm
36
40
  - name: Start convert2rhel
37
- command: convert2rhel -y --activationkey "<%= input('Activation Key') %>" --org "<%= @host.organization.label %>" > /root/convert2rhel.log
41
+ command: convert2rhel -y --activationkey "<%= input_resource('Activation Key').name %>" --org "<%= @host.organization.label %>" --keep-rhsm
38
42
  <%- if input('Restart') == "yes" -%>
39
43
  - name: Reboot the machine
40
44
  reboot: