foreman_ansible_director 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/app/controllers/foreman_ansible_director/api/v2/ansible_content_controller.rb +15 -2
  4. data/app/controllers/foreman_ansible_director/api/v2/ansible_director_api_controller.rb +1 -0
  5. data/app/controllers/foreman_ansible_director/api/v2/execution_environments_controller.rb +4 -0
  6. data/app/controllers/foreman_ansible_director/api/v2/lifecycle_environment_paths_controller.rb +4 -0
  7. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/bulk/destroy.rb +5 -2
  8. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/destroy.rb +58 -54
  9. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/destroy_providers/galaxy/destroy_full.rb +43 -0
  10. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/destroy_providers/galaxy/destroy_partial.rb +53 -0
  11. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/destroy_providers/git/destroy_full.rb +34 -0
  12. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/destroy_providers/git/destroy_partial.rb +41 -0
  13. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/extract_variables.rb +22 -3
  14. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/import.rb +5 -4
  15. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/import_providers/galaxy/update.rb +2 -0
  16. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/import_providers/galaxy/update_collection.rb +13 -15
  17. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/index/dynamic/index_git_collection.rb +3 -3
  18. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/index/index_git_collection.rb +12 -12
  19. data/app/lib/foreman_ansible_director/actions/ansible_content_unit/index/index_static.rb +78 -57
  20. data/app/lib/foreman_ansible_director/actions/base/ansible_director_action.rb +4 -3
  21. data/app/lib/foreman_ansible_director/actions/proxy/build_execution_environment.rb +12 -1
  22. data/app/lib/foreman_ansible_director/actions/remote_execution/Provider/ansible_navigator_provider.rb +15 -7
  23. data/app/lib/foreman_ansible_director/actions/remote_execution/Provider/ansible_script_provider.rb +4 -4
  24. data/app/lib/foreman_ansible_director/ansible_content/ansible_content_helpers.rb +33 -26
  25. data/app/lib/foreman_ansible_director/generators/content_generator.rb +1 -1
  26. data/app/lib/foreman_ansible_director/parsers/proxy/dynflow/task_status_parser.rb +13 -0
  27. data/app/models/foreman_ansible_director/ansible_collection.rb +2 -2
  28. data/app/models/foreman_ansible_director/content_unit.rb +9 -3
  29. data/app/models/foreman_ansible_director/execution_environment.rb +9 -5
  30. data/app/models/foreman_ansible_director/lifecycle_environment_path.rb +1 -23
  31. data/app/services/foreman_ansible_director/ansible_director_proxy_selector.rb +20 -0
  32. data/app/services/foreman_ansible_director/content_service.rb +35 -29
  33. data/app/services/foreman_ansible_director/execution_environment_service.rb +32 -20
  34. data/app/services/foreman_ansible_director/lifecycle_environment_path_service.rb +5 -0
  35. data/app/services/foreman_ansible_director/lifecycle_environment_service.rb +19 -2
  36. data/app/services/foreman_ansible_director/proxy/base_client.rb +9 -5
  37. data/app/services/foreman_ansible_director/pulp3/base_client.rb +1 -4
  38. data/app/views/foreman_ansible_director/ansible_content/_ansible_content_tab_content.html.erb +3 -3
  39. data/app/views/foreman_ansible_director/ansible_content/ansible_content/_ansible_content_tab_content.html.erb +3 -1
  40. data/app/views/foreman_ansible_director/api/v2/execution_environments/index.json.rabl +1 -1
  41. data/app/views/foreman_ansible_director/job_templates/apply_ansible_configuration.erb +12 -0
  42. data/config/routes.rb +3 -0
  43. data/db/migrate/20260316000001_ansible_director_schema.rb +278 -0
  44. data/db/seeds.d/62_ansible_director_proxy_feature.rb +6 -0
  45. data/lib/foreman_ansible_director/constants.rb +1 -1
  46. data/lib/foreman_ansible_director/register.rb +104 -38
  47. data/lib/foreman_ansible_director/remote_execution.rb +4 -5
  48. data/locale/en/foreman_ansible_director.po +257 -2
  49. data/locale/foreman_ansible_director.pot +460 -8
  50. data/locale/gemspec.rb +2 -1
  51. data/package.json +16 -5
  52. data/test/factories/ansible_content_factory.rb +2 -1
  53. data/test/services/unit/execution_environment_service_test.rb +6 -0
  54. data/tsconfig.json +1 -1
  55. data/webpack/components/ansible_content/AnsibleContentPage.tsx +4 -25
  56. data/webpack/components/ansible_content/components/AnsibleContentTable.tsx +8 -4
  57. data/webpack/components/ansible_content/components/AnsibleContentTablePrimaryRow.tsx +10 -9
  58. data/webpack/components/ansible_content/components/AnsibleContentTableSecondaryRow.tsx +19 -14
  59. data/webpack/components/ansible_content/components/AnsibleContentTableWrapper.tsx +93 -46
  60. data/webpack/components/ansible_content/components/AnsibleContentWizard/AnsibleContentWizard.tsx +19 -15
  61. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/ProviderSelectionStep.tsx +41 -27
  62. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/components/DefaultFooter.tsx +4 -0
  63. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/components/FinishFooter.tsx +2 -1
  64. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/components/GalaxyContentUnitInput.tsx +21 -15
  65. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/components/GitContentUnitInput.tsx +20 -20
  66. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/components/components/GitRefInput.tsx +9 -2
  67. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/components/components/VersionInput.tsx +13 -9
  68. data/webpack/components/ansible_content/components/AnsibleContentWizard/components/components/components/__test__/GitRefInput.test.tsx +103 -0
  69. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/AnsibleVariablesOverview.tsx +7 -4
  70. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/AnsibleVariablesSelector.tsx +146 -119
  71. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/OverrideCard.tsx +6 -2
  72. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/OverrideManagementModal.tsx +53 -26
  73. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/VariableManagementModalContent.tsx +7 -5
  74. data/webpack/components/ansible_content/components/AnsibleVariablesOverview/VariableManagementModal/VariableManagementModalWrapper.tsx +2 -1
  75. data/webpack/components/ansible_environments/AnsibleEnvironmentsPage.tsx +8 -2
  76. data/webpack/components/ansible_environments/components/AnsibleLcePathIndexWrapper.tsx +32 -6
  77. data/webpack/components/ansible_environments/components/components/AnsibleExecutionEnvSelectionModal.tsx +2 -2
  78. data/webpack/components/ansible_environments/components/components/AnsibleExecutionEnvSelectionModalWrapper.tsx +6 -1
  79. data/webpack/components/ansible_environments/components/components/AnsibleLceComponent.tsx +24 -5
  80. data/webpack/components/ansible_environments/components/components/AnsibleLceComponentHeaderActions.tsx +10 -12
  81. data/webpack/components/ansible_environments/components/components/AnsibleLceComponentWrapper.tsx +4 -1
  82. data/webpack/components/ansible_environments/components/components/AnsibleLcePathComponent.tsx +28 -20
  83. data/webpack/components/ansible_environments/components/components/AnsibleLcePathComponentHeaderActions.tsx +6 -4
  84. data/webpack/components/ansible_environments/components/components/AnsibleLcePathEmptyState.tsx +2 -2
  85. data/webpack/components/ansible_environments/components/components/AnsibleLibraryOverview.tsx +16 -5
  86. data/webpack/components/ansible_execution_environments/AnsibleExecutionEnvPage.tsx +16 -9
  87. data/webpack/components/ansible_execution_environments/ExecutionEnvGrid.tsx +31 -4
  88. data/webpack/components/ansible_execution_environments/components/ContentUnitModal.tsx +6 -3
  89. data/webpack/components/ansible_execution_environments/components/ExecutionEnvCard.tsx +10 -7
  90. data/webpack/components/ansible_execution_environments/components/ExecutionEnvCardHeaderActions.tsx +134 -51
  91. data/webpack/components/ansible_execution_environments/components/ExecutionEnvGridWrapper.tsx +28 -11
  92. data/webpack/components/ansible_execution_environments/components/components/ContentUnitSelectorWrapper.tsx +6 -1
  93. data/webpack/components/ansible_execution_environments/components/components/DropdownEditable.tsx +19 -14
  94. data/webpack/components/ansible_execution_environments/components/components/__test__/DropdownEditable.test.tsx +66 -0
  95. data/webpack/components/ansible_execution_environments/components/components/components/ContentUnitSelector.tsx +51 -23
  96. data/webpack/components/common/AdContextWrapper.tsx +3 -1
  97. data/webpack/components/common/Page.tsx +59 -59
  98. data/webpack/components/common/PermittedButton.tsx +10 -2
  99. data/webpack/components/common/__test__/Page.test.tsx +29 -0
  100. data/webpack/components/common/__test__/PermittedButton.test.tsx +99 -0
  101. data/webpack/components/extensions/components/LifecycleEnvComponentWrapper.tsx +3 -1
  102. data/webpack/components/extensions/create_host_tab/CreateHostAnsibleContentTab.tsx +1 -1
  103. data/webpack/components/extensions/host_details/HostDetailsLceCard/HostDetailsLceCard.tsx +7 -5
  104. data/webpack/components/extensions/host_details/HostDetailsLceCard/components/HostDetailsLceCardHeaderActions.tsx +5 -3
  105. data/webpack/components/extensions/host_details/HostDetailsLceCard/components/LcePathSelector.tsx +7 -5
  106. data/webpack/components/extensions/host_details/HostDetailsLceCard/components/LcePathSelectorWrapper.tsx +1 -1
  107. data/webpack/components/extensions/host_details/HostDetailsTab/HostDetailsTab.tsx +4 -3
  108. data/webpack/components/extensions/host_details/HostDetailsTab/components/AssignmentComponent.tsx +5 -4
  109. data/webpack/components/extensions/host_details/HostDetailsTab/components/AssignmentComponentWrapper.tsx +2 -1
  110. data/webpack/components/extensions/host_details/HostDetailsTab/components/LceAssignmentSelector.tsx +18 -8
  111. data/webpack/components/extensions/host_details/HostDetailsTab/components/LceContentList.tsx +1 -1
  112. data/webpack/components/extensions/host_details/HostDetailsTab/components/LceContentListWrapper.tsx +2 -1
  113. data/webpack/components/extensions/host_details/HostDetailsTab/components/OverrideGridWrapper.tsx +2 -1
  114. data/webpack/global_index.js +5 -4
  115. data/webpack/helpers/components/__test__/ConfirmationModal.test.tsx +124 -0
  116. data/webpack/helpers/typeGuards/executionEnvTypeGuards.ts +8 -0
  117. data/webpack/test_setup.js +2 -0
  118. data/webpack/types/AnsibleExecutionEnvTypes.d.ts +6 -2
  119. data/webpack/types/foremanReact/common/i18n.d.ts +1 -1
  120. data/webpack/types/foremanReact/components/PF4/TableIndexPage/Table/TableHooks.d.ts +6 -0
  121. data/webpack/types/foremanReact/components/SearchBar/index.d.ts +29 -0
  122. metadata +21 -25
  123. data/app/views/foreman_ansible_director/job_templates/ansible_collections_-_install_from_galaxy.erb +0 -28
  124. data/app/views/foreman_ansible_director/job_templates/ansible_roles_-_ansible_default.erb +0 -28
  125. data/app/views/foreman_ansible_director/job_templates/ansible_roles_-_install_from_galaxy.erb +0 -32
  126. data/app/views/foreman_ansible_director/job_templates/ansible_roles_-_install_from_git.erb +0 -31
  127. data/app/views/foreman_ansible_director/job_templates/ansible_windows_updates.erb +0 -160
  128. data/app/views/foreman_ansible_director/job_templates/capsule_update_-_ansible_default.erb +0 -73
  129. data/app/views/foreman_ansible_director/job_templates/capsule_upgrade_-_ansible_default.erb +0 -79
  130. data/app/views/foreman_ansible_director/job_templates/convert_to_rhel.erb +0 -79
  131. data/app/views/foreman_ansible_director/job_templates/download_and_execute_script.erb +0 -34
  132. data/app/views/foreman_ansible_director/job_templates/puppet_run_once_-_ansible_default.erb +0 -25
  133. data/app/views/foreman_ansible_director/job_templates/run_ansible_roles.erb +0 -12
  134. data/app/views/foreman_ansible_director/job_templates/service_action_-_enable_web_console.erb +0 -16
  135. data/app/views/foreman_ansible_director/job_templates/smart_proxy_upgrade_-_ansible_default.erb +0 -59
  136. data/db/migrate/20250601000004_create_ansible_schema.rb +0 -122
  137. data/db/migrate/20250606000001_add_lifecycle_envs.rb +0 -118
  138. data/db/migrate/20250806000001_add_hash_to_ee.rb +0 -7
  139. data/db/migrate/20250815000001_add_assignments.rb +0 -14
  140. data/db/migrate/20250930000001_extend_lookup_keys.rb +0 -7
  141. data/db/migrate/20251011000001_add_lce_to_hg.rb +0 -7
  142. data/db/migrate/20251202000001_add_child_to_lce.rb +0 -7
  143. data/db/migrate/20260107000001_git_cu.rb +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ffa2aaf3273097e77c353f512ca40ce5228279410f38103047f8071bb43f15f
4
- data.tar.gz: 634a14d971da5dfff74aec6db65447241f3fd88a19f84f965c051644e50116d6
3
+ metadata.gz: a4d8ce033fdae658dc74ed39b1e726223fd1f3f709c0912500eee63a959d1cfb
4
+ data.tar.gz: ff49758a3a1ab2654d8af19e4841eda385c14d3338e8fc1d925cbd53863265b2
5
5
  SHA512:
6
- metadata.gz: e7efa52aef7c260f1b919bbec8331a2d7e46fa0ae8dba115bdffb8e1227668f779a37bea706d6ff5779e30673d80f39f1e27c3bed54ccac300cae011ffa233c8
7
- data.tar.gz: f0e6ea032f1af335cd4e27f3b0d3b54a548b28d10838e82536100ebdea7f7b45cc0df1531b382d4db9389f6b98ce55ddbd51c652e8e508dcd908ff816ee612cc
6
+ metadata.gz: c65a3a229e2b3d482e3144dcfd0eb8a4c5de8e70acc1a089f09234686267ac0c597f98b9308e8b1d438be43c7e0b5301ee9e3d2ea86558656e2b52482e38897f
7
+ data.tar.gz: 165890d464e01ce17f4e673fe7ab88d4c391a28a34ce37f13274c1459d5fe37613c8ed8e4d3daf84ca14cc37a276a3f9400fb9647c09c0b6df11f625901bb9d3
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Foreman Ansible Director is a foreman plugin integrating Ansible into Foreman.
4
4
 
5
5
  ## Current Status
6
- > [!WARNING]
6
+ > [!WARNING]
7
7
  > At the time of publishing (2026-02-01), this plugin is in an intermediate state.
8
8
  > It is not ready for production use.
9
9
 
@@ -20,9 +20,9 @@ Breaking changes are expected until version 1.0.0 is reached.
20
20
  - Importing and deletion of Ansible content can be done via the Foreman web-UI
21
21
  - Ansible content can be imported from Ansible Galaxy and Git repositories
22
22
  - A dedicated lifecycle management system for Ansible content allows promotion of configurations along a path such as `Development` -> `Test` -> `Production` similar to Katello lifecycle environments.
23
- - Ansible and its dependencies are encapsulated in execution environments, which are used to run Ansible content.
24
- - Use of different ansible-core versions through execution environments.
25
- - Automatic provisioning of execution environments and Ansible content based on user-defined Ansible configurations.
23
+ - Ansible and its dependencies are encapsulated in Execution Environments, which are used to run Ansible content.
24
+ - Use of different ansible-core versions through Execution Environments.
25
+ - Automatic provisioning of Execution Environments and Ansible content based on user-defined Ansible configurations.
26
26
  - Unified interface (REST API) for both UI and external tools.
27
27
 
28
28
 
@@ -4,7 +4,7 @@ module ForemanAnsibleDirector
4
4
  module Api
5
5
  module V2
6
6
  class AnsibleContentController < AnsibleDirectorApiController
7
- before_action :find_organization, only: %i[create_units destroy_units]
7
+ before_action :find_organization, only: %i[create_units]
8
8
  before_action :find_optional_organization, only: %i[index]
9
9
 
10
10
  # TODO: APIDOC
@@ -36,15 +36,28 @@ module ForemanAnsibleDirector
36
36
  # TODO: This needs to check and invalidate built EEs
37
37
  def destroy_units
38
38
  resolved = ::ForemanAnsibleDirector::AnsibleContent::AnsibleContentHelpers.resolve_destroy_payload(
39
- params[:units]
39
+ destroy_params
40
40
  )
41
41
  @bulk_destroy_task =
42
42
  ForemanTasks.sync_task(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::Bulk::Destroy,
43
43
  resolved_content_units: resolved, organization_id: @organization.id)
44
44
  end
45
45
 
46
+ def model_of_controller
47
+ resource_class
48
+ end
49
+
46
50
  private
47
51
 
52
+ def destroy_params
53
+ params.require(:units).map do |unit|
54
+ unit.permit(
55
+ :unit_id,
56
+ unit_version_ids: []
57
+ )
58
+ end
59
+ end
60
+
48
61
  def validate_requirements_payload
49
62
  # TODO: Grammar
50
63
  params.require(:requirements_file)
@@ -5,6 +5,7 @@ module ForemanAnsibleDirector
5
5
  module V2
6
6
  class AnsibleDirectorApiController < ::Api::V2::BaseController
7
7
  include ::Api::Version2
8
+ include ::Foreman::Controller::AutoCompleteSearch
8
9
 
9
10
  def find_organization
10
11
  @organization = Organization.current || find_optional_organization
@@ -42,6 +42,10 @@ module ForemanAnsibleDirector
42
42
  ::ForemanAnsibleDirector::ExecutionEnvironmentService.destroy_execution_environment @execution_environment
43
43
  end
44
44
 
45
+ def model_of_controller
46
+ resource_class
47
+ end
48
+
45
49
  private
46
50
 
47
51
  def execution_environment_params
@@ -49,6 +49,10 @@ module ForemanAnsibleDirector
49
49
  )
50
50
  end
51
51
 
52
+ def model_of_controller
53
+ resource_class
54
+ end
55
+
52
56
  private
53
57
 
54
58
  def lifecycle_environment_path_params
@@ -12,9 +12,12 @@ module ForemanAnsibleDirector
12
12
 
13
13
  def plan(args)
14
14
  concurrence do
15
- args[:resolved_content_units].each do |unit|
15
+ args[:resolved_content_units].each do |unit_id, instruction|
16
+ complete = instruction.delete(:complete)
16
17
  plan_action(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::Destroy,
17
- unit: unit, organization_id: args[:organization_id])
18
+ unit_id: unit_id,
19
+ unit_version_ids: instruction[:versions],
20
+ complete: complete)
18
21
  end
19
22
  end
20
23
  end
@@ -5,84 +5,88 @@ module ForemanAnsibleDirector
5
5
  module AnsibleContentUnit
6
6
  class Destroy < ::ForemanAnsibleDirector::Actions::Base::AnsibleDirectorAction
7
7
  input_format do
8
- param :unit
9
- param :organization_id
8
+ param :unit_id
9
+ param :unit_version_ids # {git: [], galaxy: []}
10
+ param :complete, Boolean
10
11
  end
11
12
 
12
13
  def plan(args)
13
- unit = args[:unit]
14
- organization_id = args[:organization_id]
14
+ unit_id = args[:unit_id]
15
+ unit_version_ids = args[:unit_version_ids]
15
16
 
16
- if !unit.versions.empty?
17
- plan_partial_destroy(unit, organization_id)
17
+ complete = args[:complete]
18
+
19
+ if complete
20
+ plan_full_destroy(unit_id)
21
+ plan_self(
22
+ unit_id: unit_id
23
+ )
18
24
  else
19
- plan_full_destroy(unit, organization_id)
25
+ plan_partial_destroy(unit_id, unit_version_ids)
20
26
  end
21
- plan_self(
22
- organization_id: organization_id,
23
- unit_name: unit.unit_name,
24
- unit_namespace: unit.unit_namespace,
25
- unit_type: unit.unit_type,
26
- unit_versions: unit.versions
27
- )
28
27
  end
29
28
 
30
29
  def finalize
31
30
  acu = ::ForemanAnsibleDirector::ContentUnit.find_by(
32
- name: input[:unit_name],
33
- namespace: input[:unit_namespace],
34
- organization_id: input[:organization_id]
31
+ id: input[:unit_id]
35
32
  )
36
- if input[:unit_type] == 'collection'
37
- if !input[:unit_versions].empty? # partial
38
- input[:unit_versions].each do |version|
39
- acu&.content_unit_versions&.find_by(version: version)&.destroy
40
- end
41
- else
42
- acu&.destroy
43
- end
44
- else
45
- acu&.destroy
46
- end
33
+ acu&.destroy
47
34
  end
48
35
 
49
36
  private
50
37
 
51
- # rubocop:disable Layout/LineLength
52
- def plan_full_destroy(unit, organization_id)
53
- acu = ::ForemanAnsibleDirector::ContentUnit.find_by(name: unit.unit_name, namespace: unit.unit_namespace, organization_id: organization_id) # find_unit
38
+ # I am disabling the guard-clause rule here, because I don't think it makes a lot of sense in this case.
39
+ # galaxy_cuvs and git_cuvs are independent of each other, so early returning is not possible.
40
+ # rubocop: disable Style/GuardClause
41
+ def plan_full_destroy(unit_id)
42
+ galaxy_cuvs = ::ForemanAnsibleDirector::ContentUnit
43
+ .find_by(id: unit_id)
44
+ .content_unit_versions
45
+ .where(source_type: 'galaxy')
54
46
 
55
- concurrence do
56
- plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Repository::Destroy,
57
- repository_href: acu.pulp_repository_href)
58
- plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Distribution::Destroy,
59
- distribution_href: acu.pulp_distribution_href)
47
+ git_cuvs = ::ForemanAnsibleDirector::ContentUnit
48
+ .find_by(id: unit_id)
49
+ .content_unit_versions
50
+ .where(source_type: 'git')
60
51
 
61
- if acu.collection?
62
- plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Remote::Collection::Destroy,
63
- collection_remote_href: acu.pulp_remote_href)
64
- else
65
- plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Remote::Role::Destroy,
66
- role_remote_href: acu.pulp_remote_href)
52
+ unless galaxy_cuvs.empty?
53
+ plan_action(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::DestroyProviders::Galaxy::DestroyFull,
54
+ unit_id: unit_id,
55
+ unit_version_ids: galaxy_cuvs)
56
+ end
57
+
58
+ unless git_cuvs.empty?
59
+ git_cuvs.each do |git_cuv|
60
+ plan_action(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::DestroyProviders::Git::DestroyFull,
61
+ unit_id: unit_id,
62
+ unit_version_id: git_cuv)
67
63
  end
68
64
  end
69
65
  end
66
+ # rubocop: enable Style/GuardClause
70
67
 
71
- def plan_partial_destroy(unit, organization_id)
72
- acu = ::ForemanAnsibleDirector::AnsibleCollection.find_by(name: unit.unit_name, namespace: unit.unit_namespace, organization_id: organization_id) # Only collections
68
+ # Same as above
69
+ # rubocop: disable Style/GuardClause
70
+ def plan_partial_destroy(unit_id, unit_version_ids)
71
+ galaxy_cuvs = unit_version_ids[:galaxy]
72
+ git_cuvs = unit_version_ids[:git]
73
+
74
+ unless galaxy_cuvs.empty?
75
+ plan_action(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::DestroyProviders::Galaxy::DestroyPartial,
76
+ unit_id: unit_id,
77
+ unit_version_ids: galaxy_cuvs)
78
+ end
79
+
80
+ unless git_cuvs.empty?
81
+ git_cuvs.each do |git_cuv|
82
+ plan_action(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::DestroyProviders::Git::DestroyPartial,
83
+ unit_id: unit_id,
84
+ unit_version_id: git_cuv)
85
+ end
73
86
 
74
- sequence do
75
- _remote_update_action = plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Remote::Collection::Update,
76
- collection_remote_href: acu.pulp_remote_href,
77
- requirements: acu.requirements_file(unit, subtractive: true))
78
- _snyc_action = plan_action(
79
- ::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Repository::Sync,
80
- repository_href: acu.pulp_repository_href,
81
- remote_href: acu.pulp_remote_href
82
- )
83
87
  end
84
88
  end
85
- # rubocop:enable Layout/LineLength
89
+ # rubocop: enable Style/GuardClause
86
90
  end
87
91
  end
88
92
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAnsibleDirector
4
+ module Actions
5
+ module AnsibleContentUnit
6
+ module DestroyProviders
7
+ module Galaxy
8
+ class DestroyFull < ::ForemanAnsibleDirector::Actions::Base::AnsibleDirectorAction
9
+ input_format do
10
+ param :unit_id
11
+ param :unit_version_ids
12
+ end
13
+
14
+ def plan(args)
15
+ unit_id = args[:unit_id]
16
+
17
+ # Since Pulp objects are the same for content imported from Galaxy, any CUV will do
18
+ cuv = ::ForemanAnsibleDirector::ContentUnitVersion.where(
19
+ versionable_id: unit_id,
20
+ source_type: 'galaxy'
21
+ ).includes(:versionable).first
22
+
23
+ concurrence do
24
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Repository::Destroy,
25
+ repository_href: cuv.pulp_repository_href)
26
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Distribution::Destroy,
27
+ distribution_href: cuv.pulp_distribution_href)
28
+
29
+ if cuv.versionable.collection?
30
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Remote::Collection::Destroy,
31
+ collection_remote_href: cuv.pulp_remote_href)
32
+ else
33
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Remote::Role::Destroy,
34
+ role_remote_href: cuv.pulp_remote_href)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAnsibleDirector
4
+ module Actions
5
+ module AnsibleContentUnit
6
+ module DestroyProviders
7
+ module Galaxy
8
+ class DestroyPartial < ::ForemanAnsibleDirector::Actions::Base::AnsibleDirectorAction
9
+ input_format do
10
+ param :unit_id
11
+ param :unit_version_ids # []
12
+ end
13
+
14
+ def plan(args)
15
+ unit_version_ids = args[:unit_version_ids]
16
+
17
+ cuvs = ::ForemanAnsibleDirector::ContentUnitVersion.where(id: unit_version_ids)
18
+
19
+ versions_to_remove = cuvs.pluck(:version)
20
+ partial_scu = Struct.new(:versions).new(versions_to_remove)
21
+
22
+ # Shared between all versions_to_remove
23
+ cuv = cuvs[0]
24
+ acu = cuv.versionable
25
+
26
+ new_requirements = acu.requirements_file(partial_scu, subtractive: true)
27
+ remote_href = cuv.pulp_remote_href
28
+ repository_href = cuv.pulp_repository_href
29
+
30
+ _remote_update_action = plan_action(
31
+ ::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Remote::Collection::Update,
32
+ collection_remote_href: remote_href,
33
+ requirements: new_requirements
34
+ )
35
+ _snyc_action = plan_action(
36
+ ::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Repository::Sync,
37
+ repository_href: repository_href,
38
+ remote_href: remote_href
39
+ )
40
+
41
+ plan_self(unit_version_ids: unit_version_ids)
42
+ end
43
+
44
+ def finalize
45
+ unit_version_ids = input[:unit_version_ids]
46
+ ::ForemanAnsibleDirector::ContentUnitVersion.where(id: unit_version_ids).destroy_all
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAnsibleDirector
4
+ module Actions
5
+ module AnsibleContentUnit
6
+ module DestroyProviders
7
+ module Git
8
+ class DestroyFull < ::ForemanAnsibleDirector::Actions::Base::AnsibleDirectorAction
9
+ input_format do
10
+ param :unit_id
11
+ param :unit_version_id
12
+ end
13
+
14
+ def plan(args)
15
+ unit_version_id = args[:unit_version_id]
16
+
17
+ cuv = ::ForemanAnsibleDirector::ContentUnitVersion.find_by(id: unit_version_id)
18
+
19
+ concurrence do
20
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Repository::Destroy,
21
+ repository_href: cuv.pulp_repository_href)
22
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Distribution::Destroy,
23
+ distribution_href: cuv.pulp_distribution_href)
24
+
25
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Remote::Git::Destroy,
26
+ git_remote_href: cuv.pulp_remote_href)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanAnsibleDirector
4
+ module Actions
5
+ module AnsibleContentUnit
6
+ module DestroyProviders
7
+ module Git
8
+ class DestroyPartial < ::ForemanAnsibleDirector::Actions::Base::AnsibleDirectorAction
9
+ input_format do
10
+ param :unit_id
11
+ param :unit_version_id
12
+ end
13
+
14
+ def plan(args)
15
+ unit_version_id = args[:unit_version_id]
16
+
17
+ cuv = ::ForemanAnsibleDirector::ContentUnitVersion.find_by(id: unit_version_id)
18
+
19
+ concurrence do
20
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Repository::Destroy,
21
+ repository_href: cuv.pulp_repository_href)
22
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Distribution::Destroy,
23
+ distribution_href: cuv.pulp_distribution_href)
24
+
25
+ plan_action(::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Remote::Git::Destroy,
26
+ git_remote_href: cuv.pulp_remote_href)
27
+ end
28
+
29
+ plan_self(unit_version_id: unit_version_id)
30
+ end
31
+
32
+ def finalize
33
+ unit_version_id = input[:unit_version_id]
34
+ ::ForemanAnsibleDirector::ContentUnitVersion.find_by(id: unit_version_id)&.destroy
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -83,13 +83,32 @@ module ForemanAnsibleDirector
83
83
  roles.transform_values! do |v|
84
84
  all_defaults = {}
85
85
  v[:defaults].each do |defaults_yaml_str|
86
- if (loaded = YAML.safe_load(defaults_yaml_str))
87
- all_defaults.merge!(loaded)
88
- end
86
+ next unless (loaded = YAML.safe_load(defaults_yaml_str))
87
+ all_defaults.merge!(loaded.transform_values do |variable|
88
+ {
89
+ value: variable,
90
+ type: key_type(variable),
91
+ }
92
+ end)
89
93
  end
90
94
  all_defaults
91
95
  end
92
96
  end
97
+
98
+ def key_type(variable)
99
+ case variable
100
+ when TrueClass || FalseClass
101
+ 'boolean'
102
+ when String
103
+ 'string'
104
+ when Integer
105
+ 'integer'
106
+ when Float
107
+ 'float'
108
+ else
109
+ 'yaml'
110
+ end
111
+ end
93
112
  end
94
113
  end
95
114
  end
@@ -12,7 +12,9 @@ module ForemanAnsibleDirector
12
12
  def plan(args)
13
13
  unit = args[:unit]
14
14
  organization_id = args[:organization_id]
15
- op_type = operation_type unit
15
+ existing_unit = ::ForemanAnsibleDirector::ContentUnit.find_by(namespace: unit.unit_namespace,
16
+ name: unit.unit_name)
17
+ op_type = operation_type existing_unit, unit
16
18
 
17
19
  case op_type
18
20
  when :import
@@ -35,6 +37,7 @@ module ForemanAnsibleDirector
35
37
  when :galaxy
36
38
  plan_action(::ForemanAnsibleDirector::Actions::AnsibleContentUnit::ImportProviders::Galaxy::Update,
37
39
  unit: unit,
40
+ content_unit_id: existing_unit.id,
38
41
  organization_id: organization_id)
39
42
  else
40
43
  raise NotImplementedError
@@ -58,11 +61,9 @@ module ForemanAnsibleDirector
58
61
  # | 1 | 1 | 0 | NOOP |
59
62
  # | 1 | 1 | 1 | :update |
60
63
  # TODO: Unit test this
61
- def operation_type(unit)
64
+ def operation_type(existing_unit, unit)
62
65
  force_override = Setting[:ad_content_import_override]
63
66
 
64
- existing_unit = ::ForemanAnsibleDirector::ContentUnit.find_by(namespace: unit.unit_namespace,
65
- name: unit.unit_name)
66
67
  return :import unless existing_unit
67
68
 
68
69
  existing_unit_versions = existing_unit.content_unit_versions.select do |x|
@@ -8,6 +8,7 @@ module ForemanAnsibleDirector
8
8
  class Update < ::ForemanAnsibleDirector::Actions::Base::AnsibleDirectorAction
9
9
  input_format do
10
10
  param :unit, Object, required: true # SimpleAnsibleContentUnit
11
+ param :content_unit_id, String, required: true
11
12
  param :organization_id, required: true
12
13
  end
13
14
 
@@ -17,6 +18,7 @@ module ForemanAnsibleDirector
17
18
  plan_action(
18
19
  ::ForemanAnsibleDirector::Actions::AnsibleContentUnit::ImportProviders::Galaxy::UpdateCollection,
19
20
  unit: unit,
21
+ content_unit_id: args[:content_unit_id],
20
22
  organization_id: args[:organization_id]
21
23
  )
22
24
  end
@@ -8,28 +8,25 @@ module ForemanAnsibleDirector
8
8
  class UpdateCollection < ::ForemanAnsibleDirector::Actions::Base::AnsibleDirectorAction
9
9
  input_format do
10
10
  param :unit, Object, required: true # SimpleAnsibleContentUnit
11
+ param :content_unit_id, String, required: true
11
12
  param :organization_id, required: true
12
13
  end
13
14
 
14
15
  def plan(args)
15
- unit = args[:unit]
16
+ existing_unit = ::ForemanAnsibleDirector::AnsibleCollection.find_by(id: args[:content_unit_id])
17
+ new_unit = args[:unit]
16
18
  organization_id = args[:organization_id]
17
19
 
18
- existing_unit = ::ForemanAnsibleDirector::AnsibleCollection.find_by(
19
- namespace: unit.unit_namespace,
20
- name: unit.unit_name,
21
- organization_id: organization_id
22
- )
23
-
24
- repository_href = existing_unit.pulp_repository_href
25
- remote_href = existing_unit.pulp_remote_href
26
- distribution_href = existing_unit.pulp_distribution_href
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
27
24
 
28
25
  sequence do
29
26
  _remote_update_action = plan_action(
30
27
  ::ForemanAnsibleDirector::Actions::Pulp3::Ansible::Remote::Collection::Update,
31
28
  collection_remote_href: remote_href,
32
- requirements: existing_unit.requirements_file(unit)
29
+ requirements: existing_unit.requirements_file(new_unit)
33
30
  )
34
31
 
35
32
  _snyc_action = plan_action(
@@ -44,10 +41,11 @@ module ForemanAnsibleDirector
44
41
  repository_href: repository_href,
45
42
  remote_href: remote_href,
46
43
  distribution_href: distribution_href,
47
- content_unit_type: unit.unit_type,
48
- content_unit_source: unit.source,
49
- unit_name: unit.unit_name,
50
- unit_namespace: unit.unit_namespace,
44
+ content_unit_type: new_unit.unit_type,
45
+ content_unit_source: new_unit.source,
46
+ content_unit_id: args[:content_unit_id],
47
+ unit_name: new_unit.unit_name,
48
+ unit_namespace: new_unit.unit_namespace,
51
49
  organization_id: organization_id
52
50
  )
53
51
  end
@@ -104,11 +104,11 @@ module ForemanAnsibleDirector
104
104
  next if cr_variables.nil?
105
105
 
106
106
  ActiveRecord::Base.transaction do
107
- cr_variables.each do |variable_name, variable_value|
107
+ cr_variables.each do |variable_name, variable|
108
108
  ::ForemanAnsibleDirector::VariableService.create_variable(
109
109
  key: variable_name,
110
- type: 'yaml',
111
- default_value: variable_value,
110
+ type: variable[:type],
111
+ default_value: variable[:value],
112
112
  owner: collection_role_record
113
113
  )
114
114
  end
@@ -86,13 +86,6 @@ module ForemanAnsibleDirector
86
86
  unit_record = ::ForemanAnsibleDirector::ContentService.create_ansible_collection(
87
87
  name: input[:unit_name],
88
88
  namespace: input[:unit_namespace],
89
- source: input[:unit_source],
90
- source_type: 'git',
91
- latest_version_href:
92
- input[:repository_show_action_output][:repository_show_response][:latest_version_href],
93
- pulp_repository_href: input[:repository_href],
94
- pulp_remote_href: input[:remote_href],
95
- pulp_distribution_href: input[:distribution_href],
96
89
  organization_id: input[:organization_id]
97
90
  )
98
91
 
@@ -100,9 +93,16 @@ module ForemanAnsibleDirector
100
93
 
101
94
  version = input[:indexed_unit_versions][0]
102
95
 
103
- collection_version = ::ForemanAnsibleDirector::ContentService.create_ansible_collection_version(
104
- collection: unit_record,
96
+ collection_version = ::ForemanAnsibleDirector::ContentService.create_ansible_content_unit_version(
97
+ versionable: unit_record,
105
98
  version: input[:unit_version],
99
+ source: input[:unit_source],
100
+ source_type: 'git',
101
+ latest_version_href:
102
+ input[:repository_show_action_output][:repository_show_response][:latest_version_href],
103
+ pulp_repository_href: input[:repository_href],
104
+ pulp_remote_href: input[:remote_href],
105
+ pulp_distribution_href: input[:distribution_href],
106
106
  dynamic: input[:dynamic_reference]
107
107
  )
108
108
 
@@ -116,11 +116,11 @@ module ForemanAnsibleDirector
116
116
  next if cr_variables.nil?
117
117
 
118
118
  ActiveRecord::Base.transaction do
119
- cr_variables.each do |variable_name, variable_value|
119
+ cr_variables.each do |variable_name, variable|
120
120
  ::ForemanAnsibleDirector::VariableService.create_variable(
121
121
  key: variable_name,
122
- type: 'yaml',
123
- default_value: variable_value,
122
+ type: variable[:type],
123
+ default_value: variable[:value],
124
124
  owner: collection_role_record
125
125
  )
126
126
  end