foreman_ansible_director 0.5.0 → 0.6.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.
Files changed (195) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_ansible_director/api/v2/ansible_content_controller.rb +21 -6
  3. data/app/controllers/foreman_ansible_director/api/v2/ansible_director_api_controller.rb +13 -0
  4. data/app/controllers/foreman_ansible_director/api/v2/ansible_variable_overrides_controller.rb +4 -0
  5. data/app/controllers/foreman_ansible_director/api/v2/ansible_variables_controller.rb +4 -0
  6. data/app/controllers/foreman_ansible_director/api/v2/assignments_controller.rb +53 -115
  7. data/app/controllers/foreman_ansible_director/api/v2/execution_environments_controller.rb +8 -1
  8. data/app/controllers/foreman_ansible_director/api/v2/lifecycle_environment_paths_controller.rb +1 -1
  9. data/app/controllers/foreman_ansible_director/api/v2/lifecycle_environments_controller.rb +7 -4
  10. data/app/controllers/foreman_ansible_director/api/v2/status_controller.rb +0 -9
  11. data/app/lib/foreman_ansible_director/abstract/content_resolution_node.rb +27 -0
  12. data/app/lib/foreman_ansible_director/abstract/content_source.rb +19 -0
  13. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/bulk/destroy.rb +14 -10
  14. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/bulk/import.rb +19 -8
  15. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/import.rb +13 -28
  16. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/import_providers/galaxy/update_collection.rb +13 -3
  17. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/index/index_static.rb +15 -7
  18. data/app/lib/foreman_ansible_director/actions/consistency_check/check/collection_remotes.rb +52 -0
  19. data/app/lib/foreman_ansible_director/actions/consistency_check/check/distributions.rb +50 -0
  20. data/app/lib/foreman_ansible_director/actions/consistency_check/check/git_remotes.rb +52 -0
  21. data/app/lib/foreman_ansible_director/actions/consistency_check/check/repositories.rb +50 -0
  22. data/app/lib/foreman_ansible_director/actions/consistency_check/check/role_remotes.rb +50 -0
  23. data/app/lib/foreman_ansible_director/actions/consistency_check/destroy/collection_remotes.rb +29 -0
  24. data/app/lib/foreman_ansible_director/actions/consistency_check/destroy/distributions.rb +29 -0
  25. data/app/lib/foreman_ansible_director/actions/consistency_check/destroy/git_remotes.rb +29 -0
  26. data/app/lib/foreman_ansible_director/actions/consistency_check/destroy/repositories.rb +29 -0
  27. data/app/lib/foreman_ansible_director/actions/consistency_check/destroy/role_remotes.rb +29 -0
  28. data/app/lib/foreman_ansible_director/actions/consistency_check/perform.rb +83 -0
  29. data/app/lib/foreman_ansible_director/actions/pulp3/ansible/distribution/list_all.rb +53 -0
  30. data/app/lib/foreman_ansible_director/actions/pulp3/ansible/remote/collection/list_all.rb +57 -0
  31. data/app/lib/foreman_ansible_director/actions/pulp3/ansible/remote/git/list_all.rb +57 -0
  32. data/app/lib/foreman_ansible_director/actions/pulp3/ansible/remote/role/list_all.rb +57 -0
  33. data/app/lib/foreman_ansible_director/actions/pulp3/ansible/repository/list_all.rb +53 -0
  34. data/app/lib/foreman_ansible_director/actions/pulp3/util/destroy_all.rb +84 -0
  35. data/app/lib/foreman_ansible_director/actions/remote_execution/Provider/ansible_navigator_provider.rb +50 -25
  36. data/app/lib/foreman_ansible_director/actions/remote_execution/Provider/ansible_script_provider.rb +1 -1
  37. data/app/lib/foreman_ansible_director/ansible_content/ansible_content_helpers.rb +1 -1
  38. data/app/lib/foreman_ansible_director/ansible_content/parsed_ansible_content_unit.rb +1 -1
  39. data/app/lib/foreman_ansible_director/ansible_content/simple_ansible_content_unit.rb +5 -4
  40. data/app/lib/foreman_ansible_director/generators/content_generator.rb +33 -34
  41. data/app/lib/foreman_ansible_director/generators/inventory_generator.rb +3 -3
  42. data/app/lib/foreman_ansible_director/generators/playbook_generator.rb +17 -22
  43. data/app/lib/foreman_ansible_director/generators/variable_generator.rb +20 -17
  44. data/app/lib/foreman_ansible_director/issues/base_issue.rb +29 -0
  45. data/app/lib/foreman_ansible_director/issues/errors/base_error.rb +9 -0
  46. data/app/lib/foreman_ansible_director/issues/warnings/base_warning.rb +9 -0
  47. data/app/lib/foreman_ansible_director/issues/warnings/no_resolution_candidate_for_collection_role.rb +42 -0
  48. data/app/lib/foreman_ansible_director/issues/warnings/no_resolution_candidate_for_role.rb +39 -0
  49. data/app/lib/foreman_ansible_director/logging/loggable_model.rb +33 -0
  50. data/app/models/foreman_ansible_director/ansible_content_assignment.rb +0 -10
  51. data/app/models/foreman_ansible_director/ansible_director_model.rb +2 -0
  52. data/app/models/foreman_ansible_director/ansible_variable.rb +17 -0
  53. data/app/models/foreman_ansible_director/concerns/content_consumer.rb +1 -1
  54. data/app/models/foreman_ansible_director/concerns/host_extensions.rb +22 -0
  55. data/app/models/foreman_ansible_director/concerns/hostgroup_extensions.rb +21 -0
  56. data/app/models/foreman_ansible_director/content_unit_version.rb +0 -2
  57. data/app/models/foreman_ansible_director/lifecycle_environment.rb +16 -8
  58. data/app/overrides/hostgroups_ansible_content_tab.rb +15 -0
  59. data/app/services/foreman_ansible_director/action_service.rb +31 -0
  60. data/app/services/foreman_ansible_director/ansible_director_service.rb +9 -0
  61. data/app/services/foreman_ansible_director/assignment_service.rb +169 -24
  62. data/app/services/foreman_ansible_director/execution_environment_service.rb +7 -13
  63. data/app/services/foreman_ansible_director/lifecycle_environment_service.rb +8 -3
  64. data/app/services/foreman_ansible_director/logging/action_logger.rb +30 -0
  65. data/app/services/foreman_ansible_director/logging/crud_logger.rb +44 -0
  66. data/app/services/foreman_ansible_director/pulp3/ansible/distribution/list.rb +25 -0
  67. data/app/services/foreman_ansible_director/pulp3/ansible/remote/collection/list.rb +27 -0
  68. data/app/services/foreman_ansible_director/pulp3/ansible/remote/git/list.rb +27 -0
  69. data/app/services/foreman_ansible_director/pulp3/ansible/remote/role/list.rb +27 -0
  70. data/app/services/foreman_ansible_director/pulp3/ansible/repository/list.rb +25 -0
  71. data/app/services/foreman_ansible_director/pulp3/base_client.rb +1 -1
  72. data/app/services/foreman_ansible_director/request_ctx/request_context.rb +99 -0
  73. data/app/services/foreman_ansible_director/request_ctx/request_context_helper.rb +11 -0
  74. data/app/services/foreman_ansible_director/variable_service.rb +63 -72
  75. data/app/views/foreman_ansible_director/api/v2/ansible_content/consistency_check.json.rabl +13 -0
  76. data/app/views/foreman_ansible_director/api/v2/ansible_content/create_units.rabl +11 -2
  77. data/app/views/foreman_ansible_director/api/v2/ansible_content/destroy_units.rabl +11 -2
  78. data/app/views/foreman_ansible_director/api/v2/ansible_variables/show.json.rabl +1 -1
  79. data/app/views/foreman_ansible_director/api/v2/assignments/assign.json.rabl +3 -0
  80. data/app/views/foreman_ansible_director/api/v2/assignments/assignments.json.rabl +57 -26
  81. data/app/views/foreman_ansible_director/api/v2/common/response.json.rabl +25 -0
  82. data/app/views/foreman_ansible_director/api/v2/execution_environments/show.json.rabl +22 -0
  83. data/app/views/foreman_ansible_director/api/v2/hostgroups/ansible_content_source.rabl +24 -0
  84. data/app/views/foreman_ansible_director/api/v2/hosts/ansible_content_source.rabl +24 -0
  85. data/app/views/foreman_ansible_director/api/v2/lifecycle_environments/show.json.rabl +7 -4
  86. data/app/views/foreman_ansible_director/overrides/_hostgroups_main_fields.erb +32 -0
  87. data/app/views/foreman_ansible_director/overrides/_hostgroups_tab_content.erb +11 -0
  88. data/app/views/foreman_ansible_director/overrides/_hostgroups_tab_title.erb +3 -0
  89. data/config/routes.rb +3 -3
  90. data/db/migrate/20260316000001_ansible_director_schema.rb +12 -4
  91. data/lib/foreman_ansible_director/constants.rb +1 -1
  92. data/lib/foreman_ansible_director/engine.rb +0 -1
  93. data/lib/foreman_ansible_director/register.rb +70 -30
  94. data/lib/tasks/uninstall.rake +44 -0
  95. data/package.json +1 -1
  96. data/test/ansible_content/unit/simple_ansible_content_unit_test.rb +164 -0
  97. data/test/factories/ansible_content_assignments_factory.rb +23 -0
  98. data/test/foreman_ansible_director_test_helper.rb +22 -2
  99. data/test/generators/unit/variable_generator_test.rb +98 -0
  100. data/test/models/unit/ansible_variable_test.rb +37 -0
  101. data/test/models/unit/execution_environment_test.rb +212 -0
  102. data/test/services/unit/action_service_test.rb +173 -0
  103. data/test/services/unit/assignment_service_test.rb +236 -89
  104. data/test/services/unit/content_service_test.rb +153 -0
  105. data/test/services/unit/execution_environment_service_test.rb +7 -31
  106. data/test/services/unit/variable_service_test.rb +282 -15
  107. data/webpack/components/ansible_content/AnsibleContentPageWrapper.tsx +5 -3
  108. data/webpack/components/ansible_content/components/AnsibleContentTable.tsx +7 -7
  109. data/webpack/components/ansible_content/components/AnsibleContentTablePrimaryRow.tsx +37 -9
  110. data/webpack/components/ansible_content/components/AnsibleContentTableSecondaryRow.tsx +39 -12
  111. data/webpack/components/ansible_content/components/AnsibleContentTableWrapper.tsx +28 -5
  112. data/webpack/components/ansible_content/components/AnsibleContentWizard/AnsibleContentWizard.tsx +1 -5
  113. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/components/FinishFooter.tsx +42 -17
  114. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/components/GalaxyContentUnitInput.tsx +3 -2
  115. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/AnsibleVariablesOverview.tsx +1 -1
  116. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/AnsibleVariablesSelector.tsx +3 -3
  117. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/MatcherSelector.tsx +143 -98
  118. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/OverrideCard.tsx +31 -5
  119. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/OverrideManagementModal.tsx +17 -61
  120. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/OverridesTabContent.tsx +73 -0
  121. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/VariableManagementModalContent.tsx +38 -18
  122. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/VariableManagementModalWrapper.tsx +7 -0
  123. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/tabConstants.ts +2 -0
  124. data/webpack/components/ansible_content/components/ConsistencyCheckModal.tsx +140 -0
  125. data/webpack/components/ansible_environments/AnsibleEnvironmentsPageWrapper.tsx +5 -2
  126. data/webpack/components/ansible_environments/components/AnsibleLcePathIndex.tsx +5 -3
  127. data/webpack/components/ansible_environments/components/components/AnsibleLcePathComponent.tsx +1 -1
  128. data/webpack/components/ansible_execution_environments/AnsibleExecutionEnvPageWrapper.tsx +5 -2
  129. data/webpack/components/ansible_execution_environments/ExecutionEnvGrid.tsx +6 -37
  130. data/webpack/components/ansible_execution_environments/components/ExecutionEnvCard.tsx +11 -17
  131. data/webpack/components/ansible_execution_environments/components/ExecutionEnvCardHeaderActions.tsx +54 -24
  132. data/webpack/components/ansible_execution_environments/components/ExecutionEnvCardWrapper.tsx +278 -0
  133. data/webpack/components/ansible_execution_environments/components/ExecutionEnvCreateCard.tsx +33 -13
  134. data/webpack/components/ansible_execution_environments/components/ExecutionEnvEditCard.tsx +3 -0
  135. data/webpack/components/ansible_execution_environments/components/ExecutionEnvGridWrapper.tsx +2 -118
  136. data/webpack/components/common/AlertModal.tsx +52 -0
  137. data/webpack/components/common/AnsibleContentAssignment/AnsibleContentAssignment.tsx +354 -0
  138. data/webpack/components/common/AnsibleContentAssignment/AnsibleContentAssignmentMain.tsx +78 -0
  139. data/webpack/components/common/AnsibleContentAssignment/AnsibleContentAssignmentWrapper.tsx +82 -0
  140. data/webpack/components/common/AnsibleContentAssignment/components/AssignmentSelector.tsx +304 -0
  141. data/webpack/components/common/AnsibleContentAssignment/components/AssignmentSelectorWrapper.tsx +164 -0
  142. data/webpack/components/common/AnsibleContentAssignment/components/ContentAssignmentTable.tsx +285 -0
  143. data/webpack/components/common/AnsibleContentAssignment/components/HierarchyLevelSelector.tsx +47 -0
  144. data/webpack/components/{extensions/host_details/HostDetailsTab/components → common/AnsibleContentAssignment/components/Variables}/MergedOverrideCard.tsx +42 -17
  145. data/webpack/components/{extensions/host_details/HostDetailsTab/components → common/AnsibleContentAssignment/components/Variables}/OverrideGrid.tsx +28 -8
  146. data/webpack/components/{extensions/host_details/HostDetailsTab/components → common/AnsibleContentAssignment/components/Variables}/OverrideGridWrapper.tsx +15 -7
  147. data/webpack/components/common/AnsibleContentAssignment/helpers.ts +50 -0
  148. data/webpack/components/common/ForceTaxonomy.tsx +248 -0
  149. data/webpack/components/common/Permitted.tsx +47 -0
  150. data/webpack/components/common/__test__/Permitted.test.tsx +88 -0
  151. data/webpack/components/common/components/TaxonSelector.tsx +81 -0
  152. data/webpack/components/extensions/host_details/HostDetailsLceCard/HostDetailsLceCard.tsx +145 -57
  153. data/webpack/components/extensions/host_details/HostDetailsLceCard/components/HostDetailsLceCardHeaderActions.tsx +60 -45
  154. data/webpack/components/extensions/host_details/HostDetailsLceCard/components/LcePathSelector.tsx +15 -3
  155. data/webpack/components/extensions/host_details/HostDetailsTab/HostDetailsTab.tsx +9 -62
  156. data/webpack/constants/foremanAnsibleDirectorPermissions.ts +6 -6
  157. data/webpack/helpers/adContext.ts +17 -0
  158. data/webpack/helpers/comparisons.ts +6 -0
  159. data/webpack/helpers/components/ConfirmationModal.tsx +22 -15
  160. data/webpack/helpers/components/__test__/ConfirmationModal.test.tsx +0 -25
  161. data/webpack/helpers/constants.ts +2 -0
  162. data/webpack/helpers/hooks/useHybridSearch.ts +261 -0
  163. data/webpack/helpers/typeGuards/contentAssignmentTypeGuards.ts +22 -0
  164. data/webpack/index.js +3 -3
  165. data/webpack/routes/routes.tsx +6 -6
  166. data/webpack/types/AnsibleContentAssignmentTypes.d.ts +59 -0
  167. data/webpack/types/AnsibleContentTypes.d.ts +9 -0
  168. data/webpack/types/AnsibleExecutionEnvTypes.d.ts +1 -1
  169. data/webpack/types/common.d.ts +59 -0
  170. data/webpack/types/foremanReact/Root/Context/ForemanContext.d.ts +28 -8
  171. data/webpack/types/foremanReact/components/PermissionDenied/PermissionDenied.d.ts +13 -0
  172. data/webpack/types/foremanReact/components/ToastsList/slice.d.ts +1 -1
  173. data/webpack/types/issues/errors.d.ts +4 -0
  174. data/webpack/types/issues/warnings.d.ts +9 -0
  175. metadata +91 -26
  176. data/app/controllers/foreman_ansible_director/api/v2/ansible_runs_controller.rb +0 -35
  177. data/app/models/foreman_ansible_director/ansible_content_assignment_collection_role.rb +0 -9
  178. data/app/views/foreman_ansible_director/ansible_content/_ansible_content_tab_content.html.erb +0 -6
  179. data/app/views/foreman_ansible_director/ansible_content/_ansible_content_tab_title.html.erb +0 -1
  180. data/app/views/foreman_ansible_director/ansible_content/ansible_content/_ansible_content_tab_content.html.erb +0 -8
  181. data/app/views/foreman_ansible_director/ansible_content/ansible_content/_ansible_content_tab_title.html.erb +0 -1
  182. data/app/views/foreman_ansible_director/api/v2/hosts/ansible_lifecycle_environment.json.rabl +0 -3
  183. data/test/factories/ansible_content_assignments_factroy.rb +0 -20
  184. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/AnsibleVariablesViewer.tsx +0 -0
  185. data/webpack/components/ansible_content/index.tsx +0 -9
  186. data/webpack/components/ansible_environments/index.tsx +0 -9
  187. data/webpack/components/ansible_execution_environments/index.tsx +0 -9
  188. data/webpack/components/common/AdContextWrapper.tsx +0 -63
  189. data/webpack/components/extensions/host_details/HostDetailsLceCard/components/LcePathSelectorWrapper.tsx +0 -122
  190. data/webpack/components/extensions/host_details/HostDetailsTab/components/AssignmentComponent.tsx +0 -165
  191. data/webpack/components/extensions/host_details/HostDetailsTab/components/AssignmentComponentWrapper.tsx +0 -116
  192. data/webpack/components/extensions/host_details/HostDetailsTab/components/LceAssignmentSelector.tsx +0 -323
  193. data/webpack/components/extensions/host_details/HostDetailsTab/components/LceContentList.tsx +0 -115
  194. data/webpack/components/extensions/host_details/HostDetailsTab/components/LceContentListWrapper.tsx +0 -36
  195. data/webpack/types/foremanReact/components/Permitted/Permitted.d.ts +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ad5a385698810d3de3c2a7807d683ef2deacc5e12d3ec40d340ca2b3ce13b512
4
- data.tar.gz: 396708fd055a23d192e4355d08fe5a76396869d8ec36785c4951cc9572268e13
3
+ metadata.gz: 9bfa5c13b50ecdad46dceeb00e2691c16c586e8060094b5fe21eb1b19ae0eb60
4
+ data.tar.gz: 12749d98c77fe7008baf803bdfcc627b428f82f1192da8f904602611dbbac9f6
5
5
  SHA512:
6
- metadata.gz: de0b152a577bfc6cd2f45bb43ee16d456fbd15146510fe6429158cf05a2bad4d6ed1f963131e12e27fd74524bafacb85fb2737ab2c3886be277632889d827ead
7
- data.tar.gz: 28b6076faaae3c7b027cfe31528d5ea650e88cd0bd682a93d7feca85ae7660a976e628c3d5aac0334fde8dc6b420911873249d9716f2d3fab3e20424e1ec606b
6
+ metadata.gz: 8650021501539c07fc71f21cacaea22dae5abe0066b209354b9ae68b8bc2d802c7ea5440c55df65b3d53f5b218b67bcbdb7d88c9699cd6c2219bd46749c69e17
7
+ data.tar.gz: 5537935a1c0f62ca5a3465b7fc998bb713e8dd22a2fdfa193b5db14a6e1176367112268124f2bb879d139bd8740706e44d620347c60e40e251c6386975130efb
@@ -59,10 +59,12 @@ module ForemanAnsibleDirector
59
59
  resolved = ::ForemanAnsibleDirector::AnsibleContent::AnsibleContentHelpers.resolve_import_payload(
60
60
  params[:units]
61
61
  )
62
- @bulk_create_task = ForemanTasks.sync_task(
62
+ @bulk_create_task = ::ForemanAnsibleDirector::ActionService.trigger(
63
63
  ::ForemanAnsibleDirector::Actions::AnsibleContentUnit::Bulk::Import,
64
- resolved_content_units: resolved,
65
- organization_id: @organization.id
64
+ task_args: {
65
+ resolved_content_units: resolved,
66
+ organization_id: @organization.id,
67
+ }
66
68
  )
67
69
  end
68
70
 
@@ -122,9 +124,22 @@ module ForemanAnsibleDirector
122
124
  resolved = ::ForemanAnsibleDirector::AnsibleContent::AnsibleContentHelpers.resolve_destroy_payload(
123
125
  destroy_params
124
126
  )
125
- @bulk_destroy_task =
126
- ForemanTasks.sync_task(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::Bulk::Destroy,
127
- resolved_content_units: resolved)
127
+ @bulk_destroy_task = ::ForemanAnsibleDirector::ActionService.trigger(
128
+ ::ForemanAnsibleDirector::Actions::AnsibleContentUnit::Bulk::Destroy,
129
+ task_args: {
130
+ resolved_content_units: resolved,
131
+ }
132
+ )
133
+ end
134
+
135
+ # region ApiDoc: POST /api/v2/ansible_director/ansible_content/consistency_check
136
+ api :POST, '/v2/ansible_director/ansible_content/consistency_check',
137
+ N_('Run a consistency check to clean up the database after a failed content import.')
138
+ # endregion
139
+ def consistency_check
140
+ @consistency_check = ::ForemanAnsibleDirector::ActionService.trigger(
141
+ ::ForemanAnsibleDirector::Actions::ConsistencyCheck::Perform
142
+ )
128
143
  end
129
144
 
130
145
  def model_of_controller
@@ -7,6 +7,19 @@ module ForemanAnsibleDirector
7
7
  include ::Api::Version2
8
8
  include ::Foreman::Controller::AutoCompleteSearch
9
9
 
10
+ include ::ForemanAnsibleDirector::RequestCtx::RequestContextHelper
11
+
12
+ around_action :attach_request_ctx
13
+
14
+ def attach_request_ctx
15
+ ::ForemanAnsibleDirector::RequestCtx::RequestContext.with_context(
16
+ ::ForemanAnsibleDirector::RequestCtx::RequestContext.new(request.request_id)
17
+ ) do
18
+ @ctx = ctx
19
+ yield
20
+ end
21
+ end
22
+
10
23
  def find_organization
11
24
  @organization = Organization.current || find_optional_organization
12
25
  if @organization.nil?
@@ -193,6 +193,10 @@ module ForemanAnsibleDirector
193
193
  }
194
194
  )
195
195
  end
196
+
197
+ def controller_permission
198
+ 'ansible_director_variable_overrides'
199
+ end
196
200
  end
197
201
  end
198
202
  end
@@ -78,6 +78,10 @@ module ForemanAnsibleDirector
78
78
  def resource_class
79
79
  ::ForemanAnsibleDirector::AnsibleVariable
80
80
  end
81
+
82
+ def controller_permission
83
+ 'ansible_director_variables'
84
+ end
81
85
  end
82
86
  end
83
87
  end
@@ -8,24 +8,30 @@ module ForemanAnsibleDirector
8
8
 
9
9
  resource_description { resource_id 'AD Ansible Content Assignments' }
10
10
 
11
- # region ApiDoc: GET /api/v2/ansible_director/assignments
12
- api :GET, '/v2/ansible_director/assignments', N_('List resolved Ansible content assignments for a target')
11
+ # region ApiDoc: GET /api/v2/ansible_director/assignments/:target/:target_id
12
+ api :GET, '/v2/ansible_director/assignments/:target/:target_id',
13
+ N_('List Ansible content assignments for a target')
13
14
  # TRANSLATORS: ApiDoc, do not translate!
14
15
  description <<~DESC
15
- Retrieve all Ansible content units *resolved* for a given target (host or hostgroup).
16
- This includes content inherited through the assignment hierarchy or direct assignments.
16
+ Retrieve all Ansible content units for a given target (host or hostgroup).
17
+ This includes content inherited through the assignment hierarchy and direct assignments.
18
+ If resolve is true, the server will try to map the assignment to an actual content unit available to target.
17
19
  DESC
18
20
  param :target,
19
- %w[HOST HOSTGROUP],
21
+ %w[host hostgroup],
20
22
  desc: N_('Type of the target entity.'),
21
23
  required: true
22
24
  param :target_id,
23
25
  :number,
24
26
  desc: N_('ID of the target entity.'),
25
27
  required: true
28
+ param :resolve,
29
+ :boolean,
30
+ desc: N_('Resolve content units for assignments.'),
31
+ required: false
26
32
  # TRANSLATORS: ApiDoc, do not translate!
27
33
  example <<~EXAMPLE
28
- GET /api/v2/ansible_director/assignments?target=HOST&target_id=123
34
+ GET /api/v2/ansible_director/assignments/host/1
29
35
  EXAMPLE
30
36
  # endregion
31
37
  def assignments
@@ -34,130 +40,65 @@ module ForemanAnsibleDirector
34
40
  target_id: params[:target_id]
35
41
  )
36
42
  # TODO: Null check target
37
- @assignments = target.resolved_ansible_content
38
- end
39
-
40
- # region ApiDoc: POST /api/v2/ansible_director/assignments
41
- api :POST, '/v2/ansible_director/assignments', N_('Assign Ansible content to a target')
42
- # TRANSLATORS: ApiDoc, do not translate!
43
- description <<~DESC
44
- Assign Ansible content from a source (e.g., a lifecycle environment) to a target.
45
- DESC
46
- param :assignment, Hash, desc: N_('Assignment definition'), required: true do
47
- param :source, Hash, desc: N_('Source (provider of content)'), required: true do
48
- param :type,
49
- %w[ACR],
50
- desc: N_('Type of source. Currently, only Ansible collection roles (ACR) are supported as sources.'),
51
- example: 'ACR',
52
- required: true
53
- param :id,
54
- :number,
55
- desc: N_('ID of the source entity.'),
56
- example: 5,
57
- required: true
58
- end
59
- param :target, Hash, desc: N_('Target (receiver of content)'), required: true do
60
- param :type,
61
- %w[HOST HOSTGROUP],
62
- desc: N_('Type of target. Both hosts (HOST) and hostgroups (HOSTGROUP) are supported as targets.'),
63
- example: 'HOST',
64
- required: true
65
- param :id,
66
- :number,
67
- desc: N_('ID of the target entity.'),
68
- example: 6,
69
- required: true
70
- end
71
- end
72
- # TRANSLATORS: ApiDoc, do not translate!
73
- example <<~EXAMPLE
74
- {
75
- "assignment": {
76
- "source": {
77
- "type": "ACR",
78
- "id": 109
79
- },
80
- "target": {
81
- "type": "HOST",
82
- "id": 1
83
- }
84
- }
85
- }
86
- EXAMPLE
87
- # endregion
88
- def assign
89
- assignment = assignment_params
90
-
91
- source = ::ForemanAnsibleDirector::AssignmentService.find_target(
92
- target_type: assignment[:source][:type],
93
- target_id: assignment[:source][:id]
94
- )
95
-
96
- target = ::ForemanAnsibleDirector::AssignmentService.find_target(
97
- target_type: assignment[:target][:type],
98
- target_id: assignment[:target][:id]
99
- )
100
-
101
- ::ForemanAnsibleDirector::AssignmentService.create_assignment(
102
- consumable: source,
103
- assignable: target
43
+ @assignments, @resolved_assignments, @hierarchy = ::ForemanAnsibleDirector::AssignmentService.assignments_for(
44
+ target: target,
45
+ resolve: ::Foreman::Cast.to_bool(params[:resolve])
104
46
  )
105
47
  end
106
48
 
107
- # region ApiDoc: POST /api/v2/ansible_director/assignments/bulk
108
- api :POST, '/v2/ansible_director/assignments/bulk', N_('Bulk assign Ansible content')
49
+ # region ApiDoc: POST /api/v2/ansible_director/assignments/:target/:target_id
50
+ api :POST, '/v2/ansible_director/assignments/:target/:target_id', N_('Assign Ansible content.')
109
51
  # TRANSLATORS: ApiDoc, do not translate!
110
52
  description <<~DESC
111
- Bulk-assign Ansible content from a source (e.g., a lifecycle environment) to targets.
112
- Equivalent to calling `/assign` multiple times.
53
+ Create Ansible content assignments for a target.
54
+ An assignment represents an Ansible role or Ansible collection role.
55
+ The version of this role is determined dynamically.
113
56
  DESC
114
- param :assignments, Array, desc: N_('Array of assignment objects'), required: true do
115
- param :source, Hash, desc: N_('Source (provider of content)'), required: true do
116
- param :type,
117
- %w[ACR],
118
- desc: N_('Type of source. Currently, only Ansible collection roles (ACR) are supported as sources.'),
119
- example: 'ACR',
120
- required: true
121
- param :id,
122
- :number,
123
- desc: N_('ID of the source entity.'),
124
- example: 5,
125
- required: true
126
- end
127
- param :target, Hash, desc: N_('Target (receiver of content)'), required: true do
128
- param :type,
129
- %w[HOST HOSTGROUP],
130
- desc: N_('Type of target. Both hosts (HOST) and hostgroups (HOSTGROUP) are supported as targets.'),
131
- example: 'HOST',
132
- required: true
133
- param :id,
134
- :number,
135
- desc: N_('ID of the target entity.'),
136
- example: 6,
137
- required: true
138
- end
57
+ param :assignments, Array, desc: N_('Array of assignment objects.'), required: true do
58
+ param :assignable_type,
59
+ %w[ForemanAnsibleDirector::AnsibleCollectionRole ForemanAnsibleDirector::AnsibleRole],
60
+ desc: N_('Type of the Ansible content unit.'),
61
+ required: true
62
+ param :assignable_namespace,
63
+ String,
64
+ desc: N_('Namespace of the Ansible content unit.'),
65
+ required: true
66
+ param :assignable_name,
67
+ String,
68
+ desc: N_('Name of the Ansible content unit.'),
69
+ required: true
70
+ param :assignable_role_name,
71
+ String,
72
+ desc: <<~DESC,
73
+ Only required if assignable_type = "ForemanAnsibleDirector::AnsibleCollectionRole".
74
+ An identifier of a role in the supplied collection.
75
+ $assignable_namespace.$assignable_name.$assignable_role_name must form a fully qualified role name.
76
+ DESC
77
+ required: false
139
78
  end
140
79
  # TRANSLATORS: ApiDoc, do not translate!
141
80
  example <<~EXAMPLE
142
81
  {
143
82
  "assignments": [
144
83
  {
145
- "source": {
146
- "type": "ACR",
147
- "id": 109
148
- },
149
- "target": {
150
- "type": "HOST",
151
- "id": 1
152
- }
84
+ "assignable_type": "ForemanAnsibleDirector::AnsibleCollectionRole",
85
+ "assignable_namespace": "manala",
86
+ "assignable_name": "roles",
87
+ "assignable_role_name": "motd"
153
88
  }
154
89
  ]
155
90
  }
156
91
  EXAMPLE
157
92
  # endregion
158
- def assign_bulk
93
+ def assign
94
+ target = ::ForemanAnsibleDirector::AssignmentService.find_target(
95
+ target_type: params[:target],
96
+ target_id: params[:target_id]
97
+ )
98
+
159
99
  assignments = bulk_assignment_params
160
100
  ::ForemanAnsibleDirector::AssignmentService.create_bulk_assignments(
101
+ target: target,
161
102
  assignments: assignments
162
103
  )
163
104
  end
@@ -194,10 +135,7 @@ module ForemanAnsibleDirector
194
135
  return [] if params[:assignments].empty?
195
136
 
196
137
  params.require(:assignments).map do |assignment|
197
- assignment.permit(
198
- source: %i[type id],
199
- target: %i[type id]
200
- )
138
+ assignment.permit(:assignable_type, :assignable_namespace, :assignable_name, :assignable_role_name)
201
139
  end
202
140
  end
203
141
  end
@@ -6,7 +6,7 @@ module ForemanAnsibleDirector
6
6
  class ExecutionEnvironmentsController < AnsibleDirectorApiController
7
7
  include ::Api::Version2
8
8
 
9
- before_action :find_resource, only: %i[update destroy]
9
+ before_action :find_resource, only: %i[show update destroy]
10
10
  before_action :find_organization, only: %i[create]
11
11
 
12
12
  resource_description { resource_id 'AD Ansible Execution Environments' }
@@ -20,6 +20,13 @@ module ForemanAnsibleDirector
20
20
  @execution_environments = resource_scope_for_index
21
21
  end
22
22
 
23
+ # region ApiDoc: GET /api/v2/ansible_director/execution_environments/:id
24
+ api :GET, '/v2/ansible_director/execution_environments/:id', N_('Show details of an execution environment')
25
+ param :id, :number, desc: N_('Execution Environment identifier.'), required: true
26
+ # endregion
27
+ def show
28
+ end
29
+
23
30
  # region ApiDoc: POST /api/v2/ansible_director/execution_environments
24
31
  api :POST, '/v2/ansible_director/execution_environments', N_('Create an Execution Environment')
25
32
  param :organization_id, :number, desc: N_('Organization identifier'), required: true
@@ -105,7 +105,7 @@ module ForemanAnsibleDirector
105
105
  # TRANSLATORS: ApiDoc, do not translate!
106
106
  description <<~DESC
107
107
  Promote content between environments in a lifecycle path.
108
- If the 'ad_lce_path_force_incremental' setting is false, 'target_environment' must be the immediate successor to 'source_environment'.
108
+ If the 'ansible_director_lce_path_force_incremental' setting is false, 'target_environment' must be the immediate successor to 'source_environment'.
109
109
  DESC
110
110
  param :promote, Hash, desc: N_('Promotion parameters'), required: true do
111
111
  param :source_environment_id,
@@ -219,19 +219,22 @@ module ForemanAnsibleDirector
219
219
  required: true
220
220
  param :target_id,
221
221
  :number,
222
- desc: N_('ID of the target entity.'),
222
+ desc: N_('ID of the target entity. Special values are "none" and "inherit".'),
223
223
  required: true
224
224
  # TRANSLATORS: ApiDoc, do not translate!
225
225
  example <<~EXAMPLE
226
226
  {
227
- "target_type": "HOST",
227
+ "target_type": "host",
228
228
  "target_id": 7
229
229
  }
230
230
  EXAMPLE
231
231
  # endregion
232
232
  def assign
233
- if params[:id] == 'library'
234
- ::ForemanAnsibleDirector::LifecycleEnvironmentService.assign_library @target
233
+ case params[:id]
234
+ when 'none'
235
+ ::ForemanAnsibleDirector::LifecycleEnvironmentService.assign_none(target: @target)
236
+ when 'inherit'
237
+ ::ForemanAnsibleDirector::LifecycleEnvironmentService.assign_inherit(target: @target)
235
238
  else
236
239
  lce = ::ForemanAnsibleDirector::LifecycleEnvironment.find_by(id: params[:id])
237
240
  ::ForemanAnsibleDirector::LifecycleEnvironmentService.assign(
@@ -13,15 +13,6 @@ module ForemanAnsibleDirector
13
13
  execution_environments: ::ForemanAnsibleDirector::ExecutionEnvironment.count,
14
14
  }
15
15
  end
16
-
17
- def context
18
- @context = {
19
- settings: {
20
- ad_default_galaxy_url: Setting[:ad_default_galaxy_url],
21
- ad_default_ansible_core_version: Setting[:ad_default_ansible_core_version],
22
- },
23
- }
24
- end
25
16
  end
26
17
  end
27
18
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAnsibleDirector
4
+ module Abstract
5
+ module ContentResolutionNode
6
+ def cr_immediate_predecessor
7
+ raise NotImplementedError
8
+ end
9
+
10
+ def cr_content_assignments
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def cr_name
15
+ raise NotImplementedError
16
+ end
17
+
18
+ def cr_content_source
19
+ raise NotImplementedError
20
+ end
21
+
22
+ def cr_content_source_state
23
+ raise NotImplementedError
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAnsibleDirector
4
+ module Abstract
5
+ module ContentSource
6
+ def cs_content_unit_versions
7
+ raise NotImplementedError
8
+ end
9
+
10
+ def cs_name
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def cs_execution_environment
15
+ raise NotImplementedError
16
+ end
17
+ end
18
+ end
19
+ end
@@ -5,22 +5,26 @@ module ForemanAnsibleDirector
5
5
  module AnsibleContentUnit
6
6
  module Bulk
7
7
  class Destroy < ::ForemanAnsibleDirector::Actions::Base::AnsibleDirectorAction
8
+ include Dynflow::Action::V2::WithSubPlans
9
+
8
10
  input_format do
9
- param :resolved_content_units, type: Array
11
+ param :resolved_content_units, type: Hash
10
12
  param :organization_id, type: Integer
11
13
  end
12
14
 
13
- def plan(args)
14
- concurrence do
15
- args[:resolved_content_units].each do |unit_id, instruction|
16
- complete = instruction.delete(:complete)
17
- plan_action(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::Destroy,
18
- unit_id: unit_id,
19
- unit_version_ids: instruction[:versions],
20
- complete: complete)
21
- end
15
+ def create_sub_plans
16
+ input[:resolved_content_units].each do |unit_id, instruction|
17
+ complete = instruction.delete(:complete)
18
+ trigger(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::Destroy,
19
+ unit_id: unit_id,
20
+ unit_version_ids: instruction[:versions],
21
+ complete: complete)
22
22
  end
23
23
  end
24
+
25
+ def total_count
26
+ input[:resolved_content_units].keys.length
27
+ end
24
28
  end
25
29
  end
26
30
  end
@@ -5,20 +5,31 @@ module ForemanAnsibleDirector
5
5
  module AnsibleContentUnit
6
6
  module Bulk
7
7
  class Import < ::ForemanAnsibleDirector::Actions::Base::AnsibleDirectorAction
8
+ include Dynflow::Action::V2::WithSubPlans
9
+
8
10
  input_format do
9
- param :resolved_content_units, type: Array
11
+ param :resolved_content_units, type: Hash
10
12
  param :organization_id, type: Integer
11
13
  end
12
14
 
13
- def plan(args)
14
- concurrence do
15
- args[:resolved_content_units].each do |unit|
16
- plan_action(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::Import,
17
- unit: unit,
18
- organization_id: args[:organization_id])
19
- end
15
+ def create_sub_plans
16
+ input[:resolved_content_units].each do |unit|
17
+ trigger(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::Import,
18
+ # Downstream actions expect SimpleAnsibleContentUnit objects, but input has already been serialized
19
+ unit: ::ForemanAnsibleDirector::AnsibleContent::SimpleAnsibleContentUnit.new(
20
+ unit_type: unit[:unit_type].to_sym,
21
+ unit_name: unit[:unit_name],
22
+ unit_source_type: unit[:source_type].to_sym,
23
+ unit_source: unit[:source],
24
+ unit_versions: unit[:versions]
25
+ ),
26
+ organization_id: input[:organization_id])
20
27
  end
21
28
  end
29
+
30
+ def total_count
31
+ input[:resolved_content_units].size
32
+ end
22
33
  end
23
34
  end
24
35
  end
@@ -14,7 +14,7 @@ module ForemanAnsibleDirector
14
14
  organization_id = args[:organization_id]
15
15
  existing_unit = ::ForemanAnsibleDirector::ContentUnit.find_by(namespace: unit.unit_namespace,
16
16
  name: unit.unit_name)
17
- op_type = operation_type existing_unit, unit
17
+ op_type = operation_type! existing_unit, unit
18
18
 
19
19
  case op_type
20
20
  when :import
@@ -42,42 +42,27 @@ module ForemanAnsibleDirector
42
42
  else
43
43
  raise NotImplementedError
44
44
  end
45
- else
46
- raise NotImplementedError
47
45
  end
48
46
  end
49
47
 
50
48
  private
51
49
 
52
- # Helper method to decide the operation type:
53
- # e = Unit exists; v = Unit.version exists; s = Force override
54
- # | e | v | s | operation |
55
- # | 0 | 0 | 0 | :import |
56
- # | 0 | 0 | 1 | :import |
57
- # | 0 | 1 | 0 | INVALID |
58
- # | 0 | 1 | 1 | INVALID |
59
- # | 1 | 0 | 0 | :update |
60
- # | 1 | 0 | 1 | :update |
61
- # | 1 | 1 | 0 | NOOP |
62
- # | 1 | 1 | 1 | :update |
63
- # TODO: Unit test this
64
- def operation_type(existing_unit, unit)
65
- force_override = Setting[:ad_content_import_override]
66
-
50
+ # This function also mutates the versions array of unit to filter out existing units
51
+ def operation_type!(existing_unit, unit)
67
52
  return :import unless existing_unit
68
53
 
69
- existing_unit_versions = existing_unit.content_unit_versions.select do |x|
70
- unit.versions.include? x.version
71
- end
54
+ existing_versions = existing_unit.content_unit_versions.map(&:version).map(&:to_s)
72
55
 
73
- filtered_versions = existing_unit_versions.select do |x|
74
- unit.source_type == x.source_type
75
- end
56
+ unit.versions = unit.versions.map(&:to_s) - existing_versions
76
57
 
77
- return :import if filtered_versions.empty?
78
-
79
- return :noop if !existing_unit_versions.empty? && !force_override
80
- :update
58
+ if unit.versions.empty?
59
+ :noop
60
+ # Also import if source_type = :galaxy and no galaxy version exists
61
+ elsif unit.source_type == :git || !(existing_unit.content_unit_versions.pluck(:source_type).include? 'galaxy')
62
+ :import
63
+ else
64
+ :update
65
+ end
81
66
  end
82
67
  end
83
68
  end
@@ -18,9 +18,19 @@ module ForemanAnsibleDirector
18
18
  organization_id = args[:organization_id]
19
19
 
20
20
  # For collections coming from Ansible Galaxy, we can reuse the existing Pulp objects
21
- repository_href = existing_unit.content_unit_versions.first.pulp_repository_href
22
- remote_href = existing_unit.content_unit_versions.first.pulp_remote_href
23
- distribution_href = existing_unit.content_unit_versions.first.pulp_distribution_href
21
+ repository_href = existing_unit
22
+ .content_unit_versions
23
+ .where(source_type: 'galaxy')
24
+ .first
25
+ .pulp_repository_href
26
+ remote_href = existing_unit.content_unit_versions
27
+ .where(source_type: 'galaxy')
28
+ .first
29
+ .pulp_remote_href
30
+ distribution_href = existing_unit.content_unit_versions
31
+ .where(source_type: 'galaxy')
32
+ .first
33
+ .pulp_distribution_href
24
34
 
25
35
  sequence do
26
36
  _remote_update_action = plan_action(
@@ -181,10 +181,18 @@ module ForemanAnsibleDirector
181
181
  existing_unit_versions.include?(unit_version[:version])
182
182
  end
183
183
 
184
- source = existing_unit.content_unit_versions.first.source
185
- repository_href = existing_unit.content_unit_versions.first.pulp_repository_href
186
- remote_href = existing_unit.content_unit_versions.first.pulp_remote_href
187
- distribution_href = existing_unit.content_unit_versions.first.pulp_distribution_href
184
+ source = existing_unit.content_unit_versions
185
+ .where(source_type: 'galaxy')
186
+ .first.source
187
+ repository_href = existing_unit.content_unit_versions
188
+ .where(source_type: 'galaxy')
189
+ .first.pulp_repository_href
190
+ remote_href = existing_unit.content_unit_versions
191
+ .where(source_type: 'galaxy')
192
+ .first.pulp_remote_href
193
+ distribution_href = existing_unit.content_unit_versions
194
+ .where(source_type: 'galaxy')
195
+ .first.pulp_distribution_href
188
196
 
189
197
  new_unit_versions.each do |new_version|
190
198
  collection_version = ::ForemanAnsibleDirector::ContentService.create_ansible_content_unit_version(
@@ -210,11 +218,11 @@ module ForemanAnsibleDirector
210
218
  next if cr_variables.nil?
211
219
 
212
220
  ActiveRecord::Base.transaction do
213
- cr_variables.each do |variable_name, variable_value|
221
+ cr_variables.each do |variable_name, variable|
214
222
  ::ForemanAnsibleDirector::VariableService.create_variable(
215
223
  key: variable_name,
216
- type: 'yaml',
217
- default_value: variable_value,
224
+ type: variable[:type],
225
+ default_value: variable[:value],
218
226
  owner: collection_role_record
219
227
  )
220
228
  end