katello 4.12.0 → 4.13.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of katello might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +0 -1
- data/app/assets/javascripts/katello/locale/bn/katello.js +3365 -3350
- data/app/assets/javascripts/katello/locale/bn_IN/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/ca/katello.js +3588 -3576
- data/app/assets/javascripts/katello/locale/cs/katello.js +3499 -3487
- data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +4186 -4186
- data/app/assets/javascripts/katello/locale/de/katello.js +5553 -5562
- data/app/assets/javascripts/katello/locale/de_AT/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/de_DE/katello.js +3066 -3051
- data/app/assets/javascripts/katello/locale/el/katello.js +3376 -3370
- data/app/assets/javascripts/katello/locale/en/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/en_GB/katello.js +3076 -3073
- data/app/assets/javascripts/katello/locale/en_US/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/es/katello.js +5366 -5372
- data/app/assets/javascripts/katello/locale/et_EE/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/fr/katello.js +5975 -5984
- data/app/assets/javascripts/katello/locale/gl/katello.js +3125 -3113
- data/app/assets/javascripts/katello/locale/gu/katello.js +3119 -3104
- data/app/assets/javascripts/katello/locale/he_IL/katello.js +3020 -3005
- data/app/assets/javascripts/katello/locale/hi/katello.js +3137 -3122
- data/app/assets/javascripts/katello/locale/id/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/it/katello.js +4469 -4466
- data/app/assets/javascripts/katello/locale/ja/katello.js +5969 -5978
- data/app/assets/javascripts/katello/locale/ka/katello.js +5649 -5652
- data/app/assets/javascripts/katello/locale/kn/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/ko/katello.js +4717 -4720
- data/app/assets/javascripts/katello/locale/locale/katello.js +1050 -1084
- data/app/assets/javascripts/katello/locale/ml_IN/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/mr/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/nl_NL/katello.js +3116 -3101
- data/app/assets/javascripts/katello/locale/or/katello.js +3137 -3122
- data/app/assets/javascripts/katello/locale/pa/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/pl/katello.js +3210 -3195
- data/app/assets/javascripts/katello/locale/pl_PL/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/pt/katello.js +3009 -2994
- data/app/assets/javascripts/katello/locale/pt_BR/katello.js +5362 -5368
- data/app/assets/javascripts/katello/locale/ro/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/ro_RO/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/ru/katello.js +4638 -4641
- data/app/assets/javascripts/katello/locale/sl/katello.js +3051 -3036
- data/app/assets/javascripts/katello/locale/sv_SE/katello.js +3156 -3144
- data/app/assets/javascripts/katello/locale/ta/katello.js +3365 -3350
- data/app/assets/javascripts/katello/locale/ta_IN/katello.js +3121 -3106
- data/app/assets/javascripts/katello/locale/te/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/tr/katello.js +3025 -3010
- data/app/assets/javascripts/katello/locale/vi/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/vi_VN/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/zh/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/zh_CN/katello.js +5968 -5977
- data/app/assets/javascripts/katello/locale/zh_TW/katello.js +4694 -4697
- data/app/assets/javascripts/katello/sync_management/sync_management.js +1 -0
- data/app/controllers/katello/api/registry/registry_proxies_controller.rb +51 -124
- data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +12 -20
- data/app/controllers/katello/api/v2/activation_keys_controller.rb +10 -4
- data/app/controllers/katello/api/v2/capsule_content_controller.rb +24 -0
- data/app/controllers/katello/api/v2/content_view_versions_controller.rb +9 -2
- data/app/controllers/katello/api/v2/debs_controller.rb +1 -1
- data/app/controllers/katello/api/v2/errata_controller.rb +1 -1
- data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +12 -4
- data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +3 -3
- data/app/controllers/katello/api/v2/organizations_controller.rb +0 -11
- data/app/controllers/katello/api/v2/packages_controller.rb +1 -1
- data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +1 -1
- data/app/controllers/katello/api/v2/repositories_controller.rb +18 -12
- data/app/controllers/katello/api/v2/repository_sets_controller.rb +2 -1
- data/app/controllers/katello/api/v2/simple_content_access_controller.rb +9 -22
- data/app/controllers/katello/concerns/api/v2/authorization.rb +1 -1
- data/app/helpers/katello/katello_urls_helper.rb +26 -1
- data/app/helpers/katello/subscription_mailer_helper.rb +1 -1
- data/app/jobs/create_manifest_expire_soon_warning_notifications.rb +11 -0
- data/app/lib/actions/candlepin/owner/regenerate_upstream_identity_cert.rb +21 -0
- data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
- data/app/lib/actions/katello/capsule_content/verify_checksum.rb +75 -0
- data/app/lib/actions/katello/content_view/promote.rb +1 -1
- data/app/lib/actions/katello/content_view/publish.rb +1 -1
- data/app/lib/actions/katello/content_view_version/verify_checksum.rb +29 -0
- data/app/lib/actions/katello/host/hypervisors_update.rb +1 -0
- data/app/lib/actions/katello/host/update_content_view.rb +2 -2
- data/app/lib/actions/katello/organization/manifest_import.rb +5 -0
- data/app/lib/actions/katello/organization/manifest_refresh.rb +3 -0
- data/app/lib/actions/katello/repository/metadata_generate.rb +7 -1
- data/app/lib/actions/katello/repository/remove_content.rb +1 -0
- data/app/lib/actions/katello/repository/sync.rb +2 -1
- data/app/lib/actions/katello/repository/upload_files.rb +1 -0
- data/app/lib/actions/pulp3/capsule_content/verify_checksum.rb +27 -0
- data/app/lib/actions/pulp3/orchestration/content_view_version/export_repository.rb +7 -9
- data/app/lib/actions/pulp3/orchestration/content_view_version/syncable_export.rb +5 -4
- data/app/lib/katello/concerns/base_template_scope_extensions.rb +7 -2
- data/app/lib/katello/errors.rb +4 -0
- data/app/lib/katello/http_resource.rb +6 -1
- data/app/lib/katello/resources/candlepin/consumer.rb +1 -1
- data/app/lib/katello/resources/candlepin/upstream_consumer.rb +18 -6
- data/app/lib/katello/resources/candlepin/upstream_job.rb +1 -1
- data/app/lib/katello/resources/registry.rb +25 -0
- data/app/mailers/katello/subscription_mailer.rb +3 -6
- data/app/models/katello/candlepin/repository_mapper.rb +1 -1
- data/app/models/katello/concerns/organization_extensions.rb +42 -3
- data/app/models/katello/content_view.rb +28 -0
- data/app/models/katello/content_view_environment_content_facet.rb +4 -2
- data/app/models/katello/glue/provider.rb +19 -12
- data/app/models/katello/glue/pulp/repos.rb +3 -8
- data/app/models/katello/host/content_facet.rb +1 -1
- data/app/models/katello/host/subscription_facet.rb +1 -1
- data/app/models/katello/host_collection.rb +12 -3
- data/app/models/katello/ping.rb +1 -1
- data/app/models/katello/repository.rb +33 -0
- data/app/models/katello/root_repository.rb +0 -4
- data/app/services/katello/content_unit_indexer.rb +9 -0
- data/app/services/katello/pulp3/alternate_content_source.rb +4 -6
- data/app/services/katello/pulp3/api/core.rb +13 -0
- data/app/services/katello/pulp3/api/yum.rb +11 -0
- data/app/services/katello/pulp3/docker_manifest.rb +5 -1
- data/app/services/katello/pulp3/repository/generic.rb +1 -1
- data/app/services/katello/pulp3/repository.rb +26 -6
- data/app/services/katello/pulp3/repository_mirror.rb +13 -12
- data/app/services/katello/pulp3/service_common.rb +2 -10
- data/app/services/katello/pulp3/smart_proxy_repository.rb +0 -2
- data/app/services/katello/ui_notifications/subscriptions/manifest_expire_soon_warning.rb +75 -0
- data/app/views/foreman/job_templates/update_package_-_katello_ansible_default.erb +5 -1
- data/app/views/foreman/job_templates/update_packages_by_search_query_-_katello_ansible_default.erb +2 -2
- data/app/views/foreman/job_templates/upload_profile.erb +16 -0
- data/app/views/katello/api/v2/content_view_filter_rules/show.json.rabl +9 -0
- data/app/views/katello/api/v2/docker_manifests/show.json.rabl +1 -0
- data/app/views/katello/api/v2/hosts/host_collections.json.rabl +5 -1
- data/app/views/katello/api/v2/organizations/show.json.rabl +9 -1
- data/app/views/katello/hosts/_errata_counts.html.erb +1 -1
- data/app/views/overrides/activation_keys/_host_environment_select.html.erb +1 -1
- data/app/views/overrides/activation_keys/_host_media_type_select.html.erb +15 -5
- data/app/views/overrides/activation_keys/_host_tab_pane.html.erb +1 -29
- data/config/routes/api/registry.rb +4 -8
- data/config/routes/api/v2.rb +2 -0
- data/db/migrate/20240423112842_add_fields_to_katello_docker_manifest.rb +8 -0
- data/db/migrate/20240502192021_change_katello_repository_rpms_id_seq_to_big_int.rb +9 -0
- data/db/seeds.d/109-katello-notification-blueprints.rb +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-repository-sets.controller.js +3 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/new/views/new-content-credential.html +2 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-repository-sets.controller.js +3 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +0 -15
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +8 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +12 -10
- data/lib/katello/permission_creator.rb +3 -3
- data/lib/katello/permissions/registry_permissions.rb +4 -7
- data/lib/katello/plugin.rb +10 -9
- data/lib/katello/repository_types/ostree.rb +7 -0
- data/lib/katello/scheduled_jobs.rb +7 -1
- data/lib/katello/tasks/clean_backend_objects.rake +1 -1
- data/lib/katello/tasks/repository.rake +22 -0
- data/lib/katello/version.rb +1 -1
- data/locale/action_names.rb +4 -3
- data/locale/bn/katello.po +166 -151
- data/locale/bn_IN/katello.po +166 -151
- data/locale/ca/katello.po +166 -151
- data/locale/cs/katello.po +166 -151
- data/locale/cs_CZ/LC_MESSAGES/katello.mo +0 -0
- data/locale/cs_CZ/katello.po +172 -157
- data/locale/de/LC_MESSAGES/katello.mo +0 -0
- data/locale/de/katello.po +178 -163
- data/locale/de_AT/katello.po +166 -151
- data/locale/de_DE/katello.po +166 -151
- data/locale/el/katello.po +166 -151
- data/locale/en/katello.po +166 -151
- data/locale/en_GB/katello.po +166 -151
- data/locale/en_US/katello.po +166 -151
- data/locale/es/LC_MESSAGES/katello.mo +0 -0
- data/locale/es/katello.po +178 -163
- data/locale/et_EE/katello.po +166 -151
- data/locale/fr/LC_MESSAGES/katello.mo +0 -0
- data/locale/fr/katello.po +179 -164
- data/locale/gl/katello.po +166 -151
- data/locale/gu/katello.po +166 -151
- data/locale/he_IL/katello.po +166 -151
- data/locale/hi/katello.po +166 -151
- data/locale/id/katello.po +166 -151
- data/locale/it/LC_MESSAGES/katello.mo +0 -0
- data/locale/it/katello.po +169 -154
- data/locale/ja/LC_MESSAGES/katello.mo +0 -0
- data/locale/ja/katello.po +179 -164
- data/locale/ka/LC_MESSAGES/katello.mo +0 -0
- data/locale/ka/katello.po +177 -162
- data/locale/katello.pot +1119 -1062
- data/locale/kn/katello.po +166 -151
- data/locale/ko/LC_MESSAGES/katello.mo +0 -0
- data/locale/ko/katello.po +174 -159
- data/locale/ml_IN/katello.po +166 -151
- data/locale/mr/katello.po +166 -151
- data/locale/nl_NL/katello.po +166 -151
- data/locale/or/katello.po +166 -151
- data/locale/pa/katello.po +166 -151
- data/locale/pl/katello.po +166 -151
- data/locale/pl_PL/katello.po +166 -151
- data/locale/pt/katello.po +166 -151
- data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
- data/locale/pt_BR/katello.po +178 -163
- data/locale/ro/katello.po +166 -151
- data/locale/ro_RO/katello.po +166 -151
- data/locale/ru/LC_MESSAGES/katello.mo +0 -0
- data/locale/ru/katello.po +171 -156
- data/locale/sl/katello.po +166 -151
- data/locale/sv_SE/katello.po +166 -151
- data/locale/ta/katello.po +166 -151
- data/locale/ta_IN/katello.po +166 -151
- data/locale/te/katello.po +166 -151
- data/locale/tr/katello.po +166 -151
- data/locale/vi/katello.po +166 -151
- data/locale/vi_VN/katello.po +166 -151
- data/locale/zh/katello.po +166 -151
- data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
- data/locale/zh_CN/katello.po +179 -164
- data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
- data/locale/zh_TW/katello.po +171 -156
- data/webpack/ForemanColumnExtensions/index.js +129 -0
- data/webpack/components/ActivationKeysSearch/ActivationKeysSearch.test.js +28 -0
- data/webpack/components/ActivationKeysSearch/index.js +222 -0
- data/webpack/components/Table/TableWrapper.js +14 -0
- data/webpack/components/extensions/HostDetails/ActionsBar/index.js +1 -1
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +1 -1
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +1 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +1 -0
- data/webpack/components/extensions/Hosts/ActionsBar/index.js +20 -1
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/BulkChangeHostCVModal.js +220 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/actions.js +23 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/index.js +25 -0
- data/webpack/components/extensions/Hosts/BulkActions/__tests__/bulkChangeHostCVModal.test.js +133 -0
- data/webpack/global_index.js +19 -0
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +6 -3
- data/webpack/scenes/Hosts/ChangeContentSource/actions.js +3 -1
- data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +63 -25
- data/webpack/scenes/Hosts/ChangeContentSource/index.js +24 -16
- data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +1 -0
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +64 -5
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +16 -13
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +14 -8
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +1 -0
- data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +1 -1
- metadata +61 -42
- data/app/assets/javascripts/katello/hosts/activation_key_edit.js +0 -167
- data/app/lib/actions/katello/host/upload_package_profile.rb +0 -45
- data/app/lib/actions/katello/host/upload_profiles.rb +0 -47
@@ -100,16 +100,55 @@ module Katello
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
-
def
|
104
|
-
|
103
|
+
def manifest_expiration_date(cached: true)
|
104
|
+
Rails.cache.fetch("#{self.label}_manifest_expiration_date", expires_in: 1.minute, force: !cached) do
|
105
|
+
unless manifest_imported?(cached: cached)
|
106
|
+
Rails.logger.error "Manifest not imported for organization #{self.label}"
|
107
|
+
return nil
|
108
|
+
end
|
109
|
+
manifest_expiry = owner_details.dig(:upstreamConsumer, :idCert, :serial, :expiration)
|
110
|
+
|
111
|
+
if manifest_expiry.present?
|
112
|
+
DateTime.parse(manifest_expiry)
|
113
|
+
else
|
114
|
+
Rails.logger.error "Unable to parse manifest expiration date from owner details"
|
115
|
+
nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def manifest_expired?(cached: true)
|
121
|
+
manifest_expiry = manifest_expiration_date(cached: cached)
|
105
122
|
|
106
123
|
if manifest_expiry
|
107
|
-
|
124
|
+
manifest_expiry < DateTime.now
|
108
125
|
else
|
109
126
|
false
|
110
127
|
end
|
111
128
|
end
|
112
129
|
|
130
|
+
def manifest_expiring_soon?(days = Setting[:expire_soon_days])
|
131
|
+
return false if !manifest_imported? || manifest_expired?
|
132
|
+
manifest_expiry = manifest_expiration_date
|
133
|
+
|
134
|
+
if manifest_expiry
|
135
|
+
manifest_expiry < DateTime.now + days.days
|
136
|
+
else
|
137
|
+
false
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def manifest_expire_days_remaining
|
142
|
+
manifest_expiry = manifest_expiration_date
|
143
|
+
return 0 if manifest_expired?
|
144
|
+
|
145
|
+
if manifest_expiry
|
146
|
+
(manifest_expiry - DateTime.now).to_i
|
147
|
+
else
|
148
|
+
0
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
113
152
|
def manifest_history
|
114
153
|
imports.map { |i| OpenStruct.new(i) }
|
115
154
|
end
|
@@ -634,6 +634,7 @@ module Katello
|
|
634
634
|
check_ready_to_import!
|
635
635
|
else
|
636
636
|
fail _("Import-only content views can not be published directly") if import_only? && !syncable
|
637
|
+
check_repositories_blocking_publish!
|
637
638
|
check_composite_action_allowed!(organization.library)
|
638
639
|
check_docker_repository_names!([organization.library])
|
639
640
|
check_orphaned_content_facets!(environments: self.environments)
|
@@ -642,6 +643,16 @@ module Katello
|
|
642
643
|
true
|
643
644
|
end
|
644
645
|
|
646
|
+
def check_repositories_blocking_publish!
|
647
|
+
blocking_tasks = repositories&.map { |repo| repo.blocking_task }&.compact
|
648
|
+
|
649
|
+
if blocking_tasks&.any?
|
650
|
+
errored_tasks = blocking_tasks.uniq.map { |task| "- #{Setting['foreman_url']}/foreman_tasks/tasks/#{task&.id}" }.join("\n")
|
651
|
+
fail _("Pending tasks detected in repositories of this content view. Please wait for the tasks: " +
|
652
|
+
errored_tasks + " before publishing.")
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
645
656
|
def check_docker_repository_names!(environments)
|
646
657
|
environments.each do |environment|
|
647
658
|
repositories = []
|
@@ -789,6 +800,10 @@ module Katello
|
|
789
800
|
repositories.any? { |repo| repo.last_indexed && repo.last_indexed > latest_version_object.created_at }
|
790
801
|
end
|
791
802
|
|
803
|
+
def unpublishable?
|
804
|
+
default? || import_only? || generated?
|
805
|
+
end
|
806
|
+
|
792
807
|
def needs_publish?
|
793
808
|
#Returns
|
794
809
|
# True:
|
@@ -808,7 +823,9 @@ module Katello
|
|
808
823
|
# a) No changes were detected via audits *and*
|
809
824
|
# Audit for CV publish exists (Audits haven't been cleaned up)
|
810
825
|
# *and* applied_filters field is set(Published after upgrade)
|
826
|
+
# b) Default, import only and generated CVs can not be published, hence these will always return false.
|
811
827
|
#
|
828
|
+
return false if unpublishable?
|
812
829
|
return true unless latest_version_object
|
813
830
|
return nil unless last_publish_task_success?
|
814
831
|
return composite_cv_components_changed? if composite?
|
@@ -868,6 +885,17 @@ module Katello
|
|
868
885
|
filters.present?
|
869
886
|
end
|
870
887
|
|
888
|
+
def blocking_task
|
889
|
+
blocking_task_labels = [
|
890
|
+
::Actions::Katello::ContentView::Publish.name
|
891
|
+
]
|
892
|
+
ForemanTasks::Task::DynflowTask.where(:label => blocking_task_labels)
|
893
|
+
.where.not(state: 'stopped')
|
894
|
+
.for_resource(self)
|
895
|
+
.order(:started_at)
|
896
|
+
.last
|
897
|
+
end
|
898
|
+
|
871
899
|
protected
|
872
900
|
|
873
901
|
def remove_repository(repository)
|
@@ -5,7 +5,7 @@ module Katello
|
|
5
5
|
|
6
6
|
validates :content_view_environment_id, presence: true
|
7
7
|
validates :content_facet_id, presence: true, unless: :new_record?
|
8
|
-
validate :ensure_valid_content_source
|
8
|
+
validate :ensure_valid_content_source, if: proc { Setting['validate_host_lce_content_source_coherence'] }
|
9
9
|
|
10
10
|
def ensure_valid_content_source
|
11
11
|
source = self.content_facet&.content_source
|
@@ -14,7 +14,9 @@ module Katello
|
|
14
14
|
hostname = self.content_facet&.host&.name
|
15
15
|
return unless [source, env].all? { |x| x.present? }
|
16
16
|
unless source.lifecycle_environments.include?(env)
|
17
|
-
|
17
|
+
error_msg = _("Host %{hostname}: Cannot add content view environment to content facet. The host's content source '%{content_source}' does not sync lifecycle environment '%{lce}'.") % { hostname: hostname, content_source: source.name, lce: env.name }
|
18
|
+
Rails.logger.warn error_msg
|
19
|
+
errors.add(:base, error_msg)
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -32,6 +32,10 @@ module Katello
|
|
32
32
|
|
33
33
|
module InstanceMethods
|
34
34
|
API_URL = 'https://subscription.rhsm.redhat.com/subscription/consumers/'.freeze
|
35
|
+
def api_url(upstream = {})
|
36
|
+
# Default to Red Hat
|
37
|
+
upstream['apiUrl'] || API_URL
|
38
|
+
end
|
35
39
|
|
36
40
|
def sync
|
37
41
|
Rails.logger.debug "Syncing provider #{name}"
|
@@ -62,34 +66,37 @@ module Katello
|
|
62
66
|
fail _("Upstream identity certificate not available")
|
63
67
|
end
|
64
68
|
|
65
|
-
# Default to Red Hat
|
66
|
-
url = upstream['apiUrl'] || API_URL
|
67
|
-
|
68
69
|
params = {}
|
69
70
|
params[:capabilities] = Resources::Candlepin::CandlepinPing.ping['managerCapabilities'].inject([]) do |result, element|
|
70
71
|
result << {'name' => element}
|
71
72
|
end
|
72
73
|
params[:facts] = {:distributor_version => DISTRIBUTOR_VERSION }
|
73
|
-
Resources::Candlepin::UpstreamConsumer.update("#{
|
74
|
+
Resources::Candlepin::UpstreamConsumer.update("#{api_url(upstream)}#{upstream['uuid']}", upstream['idCert']['cert'],
|
74
75
|
upstream['idCert']['key'], ca_file, params)
|
75
76
|
end
|
76
77
|
|
77
|
-
def
|
78
|
+
def owner_upstream_regenerate_identity_cert(upstream)
|
78
79
|
validate_upstream_identity_cert!(upstream)
|
79
|
-
|
80
|
+
Rails.logger.debug "Sending request to regenerate identity certificate for upstream consumer: #{upstream['uuid']}"
|
81
|
+
response = Resources::Candlepin::UpstreamConsumer.regenerate_upstream_identity("#{api_url(upstream)}#{upstream['uuid']}", upstream['idCert']['cert'],
|
82
|
+
upstream['idCert']['key'], ca_file)
|
83
|
+
JSON.parse(response)
|
84
|
+
end
|
80
85
|
|
81
|
-
|
86
|
+
def start_owner_upstream_export(upstream)
|
87
|
+
validate_upstream_identity_cert!(upstream)
|
88
|
+
response = Resources::Candlepin::UpstreamConsumer.start_upstream_export("#{api_url(upstream)}#{upstream['uuid']}/export/async", upstream['idCert']['cert'],
|
82
89
|
upstream['idCert']['key'], ca_file)
|
83
90
|
JSON.parse(response)
|
84
91
|
end
|
85
92
|
|
86
93
|
def retrieve_owner_upstream_export(upstream, zip_file_path, export_id)
|
87
94
|
validate_upstream_identity_cert!(upstream)
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
95
|
+
data = Resources::Candlepin::UpstreamConsumer.retrieve_upstream_export(
|
96
|
+
"#{api_url(upstream)}#{upstream['uuid']}/export/#{export_id}",
|
97
|
+
upstream['idCert']['cert'],
|
98
|
+
upstream['idCert']['key'], ca_file
|
99
|
+
)
|
93
100
|
File.write(zip_file_path, data, mode: 'wb')
|
94
101
|
|
95
102
|
true
|
@@ -6,12 +6,6 @@ module Katello
|
|
6
6
|
base.send :include, InstanceMethods
|
7
7
|
end
|
8
8
|
|
9
|
-
def self.repo_path_from_content_path(environment, content_path)
|
10
|
-
path = content_path.sub(%r|^/|, '')
|
11
|
-
path_prefix = [environment.organization.label, environment.label].join('/')
|
12
|
-
"#{path_prefix}/#{path}"
|
13
|
-
end
|
14
|
-
|
15
9
|
module InstanceMethods
|
16
10
|
def distributions(env)
|
17
11
|
to_ret = []
|
@@ -56,7 +50,7 @@ module Katello
|
|
56
50
|
end
|
57
51
|
|
58
52
|
def last_sync_audit
|
59
|
-
Audited::Audit.where(:auditable_id => self.repositories, :auditable_type => Katello::Repository.name).order(:created_at).last
|
53
|
+
Audited::Audit.where(:auditable_id => self.repositories, :auditable_type => Katello::Repository.name, :action => "sync").order(:created_at).last
|
60
54
|
end
|
61
55
|
|
62
56
|
def last_sync
|
@@ -64,13 +58,14 @@ module Katello
|
|
64
58
|
end
|
65
59
|
|
66
60
|
def last_repo_sync_task
|
67
|
-
@last_sync_task ||= last_repo_sync_tasks
|
61
|
+
@last_sync_task ||= last_repo_sync_tasks&.first
|
68
62
|
end
|
69
63
|
|
70
64
|
def last_repo_sync_tasks
|
71
65
|
ids = repos(self.library, nil, false).pluck(:id).join(',')
|
72
66
|
label = ::Actions::Katello::Repository::Sync.name
|
73
67
|
type = ::Katello::Repository.name
|
68
|
+
return nil if ids.empty?
|
74
69
|
ForemanTasks::Task.search_for("label = #{label} and resource_type = #{type} and resource_id ^ (#{ids})")
|
75
70
|
.order("started_at desc")
|
76
71
|
end
|
@@ -44,7 +44,7 @@ module Katello
|
|
44
44
|
|
45
45
|
validates_with ::AssociationExistsValidator, attributes: [:content_source]
|
46
46
|
validates_with Katello::Validators::GeneratedContentViewValidator
|
47
|
-
validates_associated :content_view_environment_content_facets
|
47
|
+
validates_associated :content_view_environment_content_facets, :message => _("invalid: The content source must sync the lifecycle environment assigned to the host. See the logs for more information.")
|
48
48
|
validates :host, :presence => true, :allow_blank => false
|
49
49
|
|
50
50
|
attr_accessor :cves_changed
|
@@ -67,7 +67,7 @@ module Katello
|
|
67
67
|
self.purpose_addon_ids = consumer_params['addOns'].map { |addon_name| ::Katello::PurposeAddon.find_or_create_by(name: addon_name).id }
|
68
68
|
end
|
69
69
|
|
70
|
-
unless consumer_params['releaseVer'].
|
70
|
+
unless consumer_params['releaseVer'].nil?
|
71
71
|
release = consumer_params['releaseVer']
|
72
72
|
release = release['releaseVer'] if release.is_a?(Hash)
|
73
73
|
self.release_version = release
|
@@ -29,7 +29,10 @@ module Katello
|
|
29
29
|
scoped_search :relation => :hosts, :on => :name, :rename => :host, :complete_value => true
|
30
30
|
|
31
31
|
def max_hosts_check
|
32
|
-
|
32
|
+
# NOTE: max_hosts_check and max_hosts_no_exceeded use size() instead of count() because
|
33
|
+
# the host list exists as an array rather than a DB query when run as a validation.
|
34
|
+
host_count = hosts.size
|
35
|
+
if !unlimited_hosts && (host_count > 0 && (host_count.to_i > max_hosts.to_i)) && max_hosts_changed?
|
33
36
|
errors.add :max_host, N_("may not be less than the number of hosts associated with the host collection.")
|
34
37
|
end
|
35
38
|
end
|
@@ -60,8 +63,14 @@ module Katello
|
|
60
63
|
type ? query.of_type(type) : query
|
61
64
|
end
|
62
65
|
|
63
|
-
def
|
64
|
-
|
66
|
+
def cache_key
|
67
|
+
"#{self.class.name}/#{self.id}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def total_hosts(cached: false)
|
71
|
+
Rails.cache.fetch("#{cache_key}/total_hosts", expires_in: 1.minute, force: !cached) do
|
72
|
+
hosts.count
|
73
|
+
end
|
65
74
|
end
|
66
75
|
|
67
76
|
# Retrieve the list of accessible host collections in the organization specified, returning
|
data/app/models/katello/ping.rb
CHANGED
@@ -2,7 +2,7 @@ module Katello
|
|
2
2
|
class Ping
|
3
3
|
OK_RETURN_CODE = 'ok'.freeze
|
4
4
|
FAIL_RETURN_CODE = 'FAIL'.freeze
|
5
|
-
PACKAGES = %w(katello candlepin pulp foreman hammer).freeze
|
5
|
+
PACKAGES = %w(katello candlepin pulp foreman hammer dynflow).freeze
|
6
6
|
|
7
7
|
class << self
|
8
8
|
def services(capsule_id = nil)
|
@@ -201,6 +201,12 @@ module Katello
|
|
201
201
|
joins(:root).where("#{Katello::RootRepository.table_name}.product_id" => products)
|
202
202
|
end
|
203
203
|
|
204
|
+
def self.repo_path_from_content_path(environment, content_path)
|
205
|
+
path = content_path.sub(%r|^/|, '')
|
206
|
+
path_prefix = [environment.organization.label, environment.label].join('/')
|
207
|
+
"#{path_prefix}/#{path}"
|
208
|
+
end
|
209
|
+
|
204
210
|
def to_label
|
205
211
|
name
|
206
212
|
end
|
@@ -645,6 +651,33 @@ module Katello
|
|
645
651
|
for_resource(self).order(:started_at).last
|
646
652
|
end
|
647
653
|
|
654
|
+
def blocking_task
|
655
|
+
blocking_task_labels = [
|
656
|
+
::Actions::Katello::Repository::Sync.name,
|
657
|
+
::Actions::Katello::Repository::UploadFiles.name,
|
658
|
+
::Actions::Katello::Repository::RemoveContent.name,
|
659
|
+
::Actions::Katello::Repository::MetadataGenerate.name
|
660
|
+
]
|
661
|
+
ForemanTasks::Task::DynflowTask.where(:label => blocking_task_labels)
|
662
|
+
.where.not(state: 'stopped')
|
663
|
+
.for_resource(self)
|
664
|
+
.order(:started_at)
|
665
|
+
.last
|
666
|
+
end
|
667
|
+
|
668
|
+
def check_ready_to_act!
|
669
|
+
blocking_tasks = content_views&.map { |cv| cv.blocking_task }&.compact
|
670
|
+
|
671
|
+
if blocking_tasks&.any?
|
672
|
+
errored_tasks = blocking_tasks
|
673
|
+
.uniq
|
674
|
+
.map { |task| "- #{Setting['foreman_url']}/foreman_tasks/tasks/#{task&.id}" }
|
675
|
+
.join("\n")
|
676
|
+
fail _("This repository has pending tasks in associated content views. Please wait for the tasks: " + errored_tasks +
|
677
|
+
" to complete before proceeding.")
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
648
681
|
# returns other instances of this repo with the same library
|
649
682
|
# equivalent of repo
|
650
683
|
def environmental_instances(view)
|
@@ -387,10 +387,6 @@ module Katello
|
|
387
387
|
Katello::RepositoryTypeManager.generic_repository_types(false).values.map(&:id).map(&:to_s).flatten.include? self.content_type
|
388
388
|
end
|
389
389
|
|
390
|
-
def metadata_generate_needed?
|
391
|
-
(%w(unprotected checksum_type container_repsoitory_name) & previous_changes.keys).any?
|
392
|
-
end
|
393
|
-
|
394
390
|
def using_mirrored_content?
|
395
391
|
self.mirroring_policy != Katello::RootRepository::MIRRORING_POLICY_ADDITIVE
|
396
392
|
end
|
@@ -55,6 +55,15 @@ module Katello
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
def reimport_units
|
59
|
+
units_from_pulp.each do |units|
|
60
|
+
to_update = units.map do |unit|
|
61
|
+
@service_class.generate_model_row(unit)
|
62
|
+
end
|
63
|
+
@model_class.upsert_all(to_update, unique_by: :pulp_id)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
58
67
|
def import_associations(units)
|
59
68
|
pulp_id_to_id = self.class.pulp_id_to_id_map(@content_type, units.map { |unit| unit[@service_class.unit_identifier] })
|
60
69
|
@service_class.insert_child_associations(units, pulp_id_to_id) if @service_class.respond_to?(:insert_child_associations)
|
@@ -88,18 +88,16 @@ module Katello
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def get_remote(href = smart_proxy_acs.remote_href)
|
91
|
-
|
91
|
+
api.get_remotes_api(href: href).read(href)
|
92
92
|
end
|
93
93
|
|
94
|
-
def update_remote
|
95
|
-
api.
|
94
|
+
def update_remote(href = smart_proxy_acs.remote_href)
|
95
|
+
api.get_remotes_api(href: href).partial_update(href, remote_options)
|
96
96
|
end
|
97
97
|
|
98
|
-
# The old repo URL is needed to determine which remote API to use.
|
99
98
|
def delete_remote(options = {})
|
100
99
|
options[:href] ||= smart_proxy_acs.remote_href
|
101
|
-
options[:
|
102
|
-
ignore_404_exception { options[:old_url]&.start_with?('uln') ? api.remotes_uln_api.delete(options[:href]) : api.remotes_api.delete(options[:href]) } if options[:href]
|
100
|
+
ignore_404_exception { api.get_remotes_api(href: options[:href]).delete(options[:href]) } if options[:href]
|
103
101
|
end
|
104
102
|
|
105
103
|
def create
|
@@ -47,6 +47,11 @@ module Katello
|
|
47
47
|
fail NotImplementedError
|
48
48
|
end
|
49
49
|
|
50
|
+
# Method is called with either :url or :href parameters for the sake of yum content.
|
51
|
+
def get_remotes_api(*)
|
52
|
+
remotes_api
|
53
|
+
end
|
54
|
+
|
50
55
|
def publications_api
|
51
56
|
repository_type.publications_api_class.new(api_client) #Optional
|
52
57
|
end
|
@@ -136,6 +141,10 @@ module Katello
|
|
136
141
|
client
|
137
142
|
end
|
138
143
|
|
144
|
+
def repair_api
|
145
|
+
PulpcoreClient::RepairApi.new(core_api_client)
|
146
|
+
end
|
147
|
+
|
139
148
|
def uploads_api
|
140
149
|
PulpcoreClient::UploadsApi.new(core_api_client)
|
141
150
|
end
|
@@ -230,6 +239,10 @@ module Katello
|
|
230
239
|
end
|
231
240
|
end
|
232
241
|
|
242
|
+
def repair
|
243
|
+
repair_api.post(PulpcoreClient::Repair.new(verify_checksums: true))
|
244
|
+
end
|
245
|
+
|
233
246
|
def self.fetch_from_list
|
234
247
|
page_size = Setting[:bulk_load_size]
|
235
248
|
page_opts = { "offset" => 0, limit: page_size }
|
@@ -32,6 +32,17 @@ module Katello
|
|
32
32
|
PulpRpmClient::RemotesUlnApi.new(api_client)
|
33
33
|
end
|
34
34
|
|
35
|
+
def get_remotes_api(href: nil, url: nil)
|
36
|
+
fail 'Provide exactly one of href or url for yum remote selection!' if url.blank? && href.blank?
|
37
|
+
fail 'The href must be a pulp_rpm remote href!' if href && !href.start_with?('/pulp/api/v3/remotes/rpm/')
|
38
|
+
|
39
|
+
if href&.start_with?('/pulp/api/v3/remotes/rpm/uln/') || url&.start_with?('uln')
|
40
|
+
remotes_uln_api
|
41
|
+
else
|
42
|
+
remotes_api
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
35
46
|
def copy_api
|
36
47
|
PulpRpmClient::RpmCopyApi.new(api_client)
|
37
48
|
end
|
@@ -26,7 +26,11 @@ module Katello
|
|
26
26
|
{
|
27
27
|
schema_version: unit['schema_version'],
|
28
28
|
digest: unit['digest'],
|
29
|
-
pulp_id: unit[unit_identifier]
|
29
|
+
pulp_id: unit[unit_identifier],
|
30
|
+
annotations: unit['annotations'],
|
31
|
+
labels: unit['labels'],
|
32
|
+
is_bootable: unit['is_bootable'],
|
33
|
+
is_flatpak: unit['is_flatpak']
|
30
34
|
}
|
31
35
|
end
|
32
36
|
end
|
@@ -3,7 +3,7 @@ module Katello
|
|
3
3
|
class Repository
|
4
4
|
class Generic < ::Katello::Pulp3::Repository
|
5
5
|
def copy_content_for_source(source_repository, _options = {})
|
6
|
-
copy_units_by_href(source_repository.
|
6
|
+
copy_units_by_href(source_repository.generic_content_units&.pluck(:pulp_id))
|
7
7
|
end
|
8
8
|
|
9
9
|
def distribution_options(path)
|
@@ -91,16 +91,21 @@ module Katello
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def remote_partial_update
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
94
|
+
url_type = remote_options[:url]&.start_with?('uln') ? 'uln' : 'default'
|
95
|
+
remote_type = repo.remote_href.start_with?('/pulp/api/v3/remotes/rpm/uln/') ? 'uln' : 'default'
|
96
|
+
href = repo.remote_href
|
97
|
+
|
98
|
+
if url_type == remote_type
|
99
|
+
api.get_remotes_api(href: href).partial_update(href, remote_options)
|
100
|
+
else # We need to recreate a remote of the correct type!
|
101
|
+
create_remote
|
102
|
+
delete_remote(href: href)
|
98
103
|
end
|
99
104
|
end
|
100
105
|
|
101
106
|
def delete_remote(options = {})
|
102
107
|
options[:href] ||= repo.remote_href
|
103
|
-
ignore_404_exception {
|
108
|
+
ignore_404_exception { api.get_remotes_api(href: options[:href]).delete(options[:href]) } if options[:href]
|
104
109
|
end
|
105
110
|
|
106
111
|
def self.instance_for_type(repo, smart_proxy)
|
@@ -139,7 +144,7 @@ module Katello
|
|
139
144
|
end
|
140
145
|
|
141
146
|
def get_remote(href = repo.remote_href)
|
142
|
-
|
147
|
+
api.get_remotes_api(href: href).read(href)
|
143
148
|
end
|
144
149
|
|
145
150
|
def get_distribution(href = distribution_reference.href)
|
@@ -210,6 +215,10 @@ module Katello
|
|
210
215
|
api.publications_api.create(publication_data)
|
211
216
|
end
|
212
217
|
|
218
|
+
def delete_publication
|
219
|
+
ignore_404_exception { api.publications_api.delete(repo.publication_href) } if repo.publication_href
|
220
|
+
end
|
221
|
+
|
213
222
|
def publication_options(repository_version)
|
214
223
|
{
|
215
224
|
repository_version: repository_version
|
@@ -329,6 +338,17 @@ module Katello
|
|
329
338
|
|
330
339
|
def delete_version
|
331
340
|
ignore_404_exception { api.repository_versions_api.delete(repo.version_href) } unless version_zero?
|
341
|
+
rescue api.api_exception_class => e
|
342
|
+
if e.message.include?("are currently being used to distribute content")
|
343
|
+
Rails.logger.warn "Exception when calling repository_versions_api->delete: #{e}"
|
344
|
+
publication_href = repo.publication_href
|
345
|
+
Rails.logger.warn "Trying to delete publication #{publication_href} for repository #{repo.id}}"
|
346
|
+
Rails.logger.error "Could not delete version: #{repo.version_href} because conflicting publication could not be looked up" unless publication_href
|
347
|
+
if publication_href
|
348
|
+
ignore_404_exception { api.publications_api.delete(publication_href) }
|
349
|
+
ignore_404_exception { api.repository_versions_api.delete(repo.version_href) }
|
350
|
+
end
|
351
|
+
end
|
332
352
|
end
|
333
353
|
|
334
354
|
def create_version(options = {})
|
@@ -24,11 +24,9 @@ module Katello
|
|
24
24
|
def refresh_entities
|
25
25
|
href = remote_href
|
26
26
|
if href
|
27
|
-
if
|
28
|
-
|
29
|
-
|
30
|
-
[api.remotes_api.partial_update(href, remote_options)]
|
31
|
-
end
|
27
|
+
# Do not consider remotes_uln_api, since the Katello server is not a ULN server. Even if the sync
|
28
|
+
# to Katello used ULN, the sync from Katello server to smart proxy will use a normal RPM remote!
|
29
|
+
[api.remotes_api.partial_update(href, remote_options)]
|
32
30
|
else
|
33
31
|
create_remote
|
34
32
|
[]
|
@@ -111,13 +109,10 @@ module Katello
|
|
111
109
|
end
|
112
110
|
|
113
111
|
def create_remote
|
114
|
-
if
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
remote_file_data = @repo_service.api.remote_class.new(remote_options)
|
119
|
-
api.remotes_api.create(remote_file_data)
|
120
|
-
end
|
112
|
+
# Do not consider remotes_uln_api, since the Katello server is not a ULN server. Even if the sync
|
113
|
+
# to Katello used ULN, the sync from Katello server to smart proxy will use a normal RPM remote!
|
114
|
+
remote_file_data = @repo_service.api.remote_class.new(remote_options)
|
115
|
+
api.remotes_api.create(remote_file_data)
|
121
116
|
end
|
122
117
|
|
123
118
|
def compute_remote_options
|
@@ -240,6 +235,12 @@ module Katello
|
|
240
235
|
distribution_data = api.distribution_class.new(distribution_options(path))
|
241
236
|
repo_service.distributions_api.create(distribution_data)
|
242
237
|
end
|
238
|
+
|
239
|
+
def repair
|
240
|
+
data = api.repair_class.new
|
241
|
+
fail "Could not lookup a version_href for repo #{repo_service.repo.id}" if version_href.nil?
|
242
|
+
api.repository_versions_api.repair(version_href, data)
|
243
|
+
end
|
243
244
|
end
|
244
245
|
end
|
245
246
|
end
|
@@ -9,11 +9,7 @@ module Katello
|
|
9
9
|
remote_file_data = api.remote_class.new(remote_options)
|
10
10
|
end
|
11
11
|
reformat_api_exception do
|
12
|
-
|
13
|
-
response = api.remotes_uln_api.create(remote_file_data)
|
14
|
-
else
|
15
|
-
response = api.remotes_api.create(remote_file_data)
|
16
|
-
end
|
12
|
+
response = api.get_remotes_api(url: remote_options[:url]).create(remote_file_data)
|
17
13
|
end
|
18
14
|
response
|
19
15
|
end
|
@@ -37,11 +33,7 @@ module Katello
|
|
37
33
|
end
|
38
34
|
|
39
35
|
reformat_api_exception do
|
40
|
-
|
41
|
-
response = api.remotes_uln_api.create(remote_file_data)
|
42
|
-
else
|
43
|
-
response = api.remotes_api.create(remote_file_data)
|
44
|
-
end
|
36
|
+
response = api.get_remotes_api(url: remote_options[:url]).create(remote_file_data)
|
45
37
|
#delete is async, but if its not properly deleted, orphan cleanup will take care of it later
|
46
38
|
delete_remote(href: response.pulp_href)
|
47
39
|
end
|
@@ -35,13 +35,11 @@ module Katello
|
|
35
35
|
|
36
36
|
def delete_orphan_repository_versions
|
37
37
|
tasks = []
|
38
|
-
|
39
38
|
orphan_repository_versions.each do |api, version_hrefs|
|
40
39
|
tasks << version_hrefs.collect do |href|
|
41
40
|
api.repository_versions_api.delete(href)
|
42
41
|
end
|
43
42
|
end
|
44
|
-
|
45
43
|
tasks.flatten
|
46
44
|
end
|
47
45
|
|