katello 4.4.0.rc1 → 4.4.0.1
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/app/controllers/katello/api/v2/content_views_controller.rb +2 -0
- data/app/controllers/katello/api/v2/environments_controller.rb +2 -0
- data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +10 -1
- data/app/controllers/katello/api/v2/repositories_controller.rb +3 -0
- data/app/lib/actions/katello/cdn_configuration/update.rb +2 -2
- data/app/lib/actions/katello/repository/errata_mail.rb +4 -5
- data/app/lib/actions/katello/repository/sync.rb +2 -2
- data/app/lib/actions/pulp3/abstract.rb +1 -1
- data/app/lib/actions/pulp3/content_view/delete_repository_references.rb +14 -4
- data/app/lib/actions/pulp3/content_view_version/create_import_history.rb +1 -2
- data/app/lib/actions/pulp3/repository/reclaim_space.rb +3 -10
- data/app/lib/katello/resources/cdn/katello_cdn.rb +37 -14
- data/app/lib/katello/util/pulpcore_content_filters.rb +2 -1
- data/app/models/katello/candlepin/repository_mapper.rb +11 -2
- data/app/models/katello/cdn_configuration.rb +2 -0
- data/app/models/katello/concerns/audit_comment_extensions.rb +17 -0
- data/app/models/katello/concerns/host_managed_extensions.rb +11 -1
- data/app/models/katello/concerns/smart_proxy_extensions.rb +1 -0
- data/app/models/katello/content_view_version_export_history.rb +2 -1
- data/app/models/katello/content_view_version_import_history.rb +4 -4
- data/app/models/katello/host_available_module_stream.rb +10 -0
- data/app/models/katello/installed_package.rb +1 -0
- data/app/models/katello/kt_environment.rb +1 -0
- data/app/models/katello/root_repository.rb +14 -2
- data/app/models/setting/content.rb +9 -2
- data/app/services/katello/organization_creator.rb +9 -5
- data/app/services/katello/pulp3/api/yum.rb +4 -0
- data/app/services/katello/pulp3/repository/yum.rb +11 -4
- data/app/services/katello/pulp3/repository.rb +4 -2
- data/app/services/katello/registration_manager.rb +1 -0
- data/app/views/foreman/job_templates/remove_packages_by_search_query.erb +19 -0
- data/app/views/foreman/job_templates/update_packages_by_search_query.erb +19 -0
- data/app/views/katello/api/v2/content_views/base.json.rabl +8 -4
- data/app/views/katello/api/v2/host_module_streams/base.json.rabl +1 -0
- data/app/views/katello/api/v2/repositories/show.json.rabl +2 -2
- data/db/migrate/20210119162528_delete_puppet_and_ostree_repos.rb +2 -0
- data/db/migrate/20211019192121_create_cdn_configuration.katello.rb +11 -2
- data/db/migrate/20220124191056_add_type_to_cdn_configuration.rb +1 -7
- data/db/migrate/20220209205137_expand_sync_timeout_settings.rb +23 -0
- data/db/migrate/20220303160220_remove_duplicate_errata.rb +40 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/apply-errata.controller.js +10 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +4 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +17 -12
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/sync-plans/details/views/sync-plan-products.html +1 -1
- data/lib/katello/plugin.rb +2 -0
- data/lib/katello/repository_types/ostree.rb +0 -6
- data/lib/katello/tasks/pulp2to3_migrate_deb_attributes.rake +20 -0
- data/lib/katello/version.rb +1 -1
- data/webpack/components/Errata/index.js +57 -57
- data/webpack/components/ErratumTypeLabel.js +16 -16
- data/webpack/components/MultiSelect/index.js +2 -2
- data/webpack/components/Select/Select.js +1 -1
- data/webpack/components/SelectOrg/SelectOrgReducer.js +15 -15
- data/webpack/components/SelectOrg/SetOrganization.js +1 -1
- data/webpack/components/Table/TableHooks.js +1 -0
- data/webpack/components/Table/TableWrapper.js +4 -1
- data/webpack/components/TypeAhead/helpers/commonPropTypes.js +1 -1
- data/webpack/components/TypeAhead/helpers/helpers.js +14 -14
- data/webpack/components/TypeAhead/pf3Search/TypeAheadSearch.js +1 -1
- data/webpack/components/WithOrganization/withOrganization.js +3 -3
- data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard.js +2 -1
- data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.js +2 -1
- data/webpack/components/extensions/HostDetails/Cards/__tests__/contentViewDetailsCard.test.js +30 -31
- data/webpack/components/extensions/HostDetails/Cards/__tests__/errataOverviewCard.test.js +30 -3
- data/webpack/components/extensions/HostDetails/Tabs/ContentTab/SecondaryTabsRoutes.js +6 -4
- data/webpack/components/extensions/HostDetails/Tabs/ContentTab/constants.js +1 -0
- data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErrataTab.js +1 -1
- data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErratumExpansionContents.js +3 -3
- data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsActions.js +16 -0
- data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsConstants.js +3 -0
- data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsSelectors.js +19 -0
- data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +241 -0
- data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/__tests__/moduleStreamsTab.test.js +108 -0
- data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/__tests__/modules.fixtures.json +34 -0
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/HostPackagesActions.js +58 -0
- data/webpack/components/extensions/HostDetails/{HostPackages → Tabs/PackagesTab}/HostPackagesConstants.js +3 -2
- data/webpack/components/extensions/HostDetails/{HostPackages → Tabs/PackagesTab}/HostPackagesSelectors.js +0 -0
- data/webpack/components/extensions/HostDetails/Tabs/{PackageInstallModal.js → PackagesTab/PackageInstallModal.js} +14 -14
- data/webpack/components/extensions/HostDetails/Tabs/{PackageInstallModal.scss → PackagesTab/PackageInstallModal.scss} +0 -0
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +420 -0
- data/webpack/components/extensions/HostDetails/Tabs/{PackagesTab.scss → PackagesTab/PackagesTab.scss} +0 -0
- data/webpack/components/extensions/HostDetails/{YumInstallablePackages → Tabs/PackagesTab}/YumInstallablePackagesActions.js +1 -1
- data/webpack/components/extensions/HostDetails/{YumInstallablePackages → Tabs/PackagesTab}/YumInstallablePackagesConstants.js +0 -0
- data/webpack/components/extensions/HostDetails/{YumInstallablePackages → Tabs/PackagesTab}/YumInstallablePackagesSelectors.js +0 -0
- data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +77 -1
- data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionConstants.js +4 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +2 -2
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +260 -10
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +22 -26
- data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +14 -1
- data/webpack/components/extensions/HostDetails/hostDetailsHelpers.js +10 -1
- data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/ActivationKeys.test.js.snap +4 -0
- data/webpack/components/extensions/RegistrationCommands/fields/ActivationKeys.js +1 -1
- data/webpack/components/extensions/RegistrationCommands/fields/LifecycleEnvironment.js +1 -1
- data/webpack/components/extensions/about/SystemStatuses.js +1 -1
- data/webpack/components/extensions/about/SystemStatusesReducer.js +10 -10
- data/webpack/components/pf3Table/components/Table.js +2 -2
- data/webpack/components/pf3Table/components/TableBody.js +2 -2
- data/webpack/global_index.js +4 -3
- data/webpack/redux/OrganizationProducts/OrganizationProductsReducer.js +15 -15
- data/webpack/redux/reducers/RedHatRepositories/enabled.js +43 -43
- data/webpack/redux/reducers/RedHatRepositories/repositorySetRepositories.js +43 -43
- data/webpack/redux/reducers/RedHatRepositories/sets.js +31 -31
- data/webpack/scenes/AnsibleCollections/AnsibleCollectionsReducer.js +26 -26
- data/webpack/scenes/AnsibleCollections/Details/AnsibleCollectionDetailsReducer.js +19 -19
- data/webpack/scenes/Content/Table/ContentTable.js +1 -1
- data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +2 -1
- data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReassignHostsForm.js +2 -2
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +1 -1
- data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +1 -1
- data/webpack/scenes/ContentViews/Details/ContentViewDetailReducer.js +8 -8
- data/webpack/scenes/ContentViews/Details/Filters/AffectedRepositories/AffectedRepositoryTable.js +1 -1
- data/webpack/scenes/ContentViews/Details/Filters/ArtifactsWithNoErrata.js +8 -8
- data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +1 -1
- data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +1 -1
- data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +1 -1
- data/webpack/scenes/ContentViews/Details/Filters/CVFilterDetailType.js +46 -46
- data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +14 -14
- data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +14 -14
- data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +1 -1
- data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +1 -1
- data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +17 -17
- data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +1 -1
- data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionContent.js +19 -18
- data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVEnvironmentSelectionForm.js +18 -18
- data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignActivationKeysForm.js +3 -3
- data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignHostsForm.js +3 -3
- data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedActivationKeys.js +1 -1
- data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedHosts.js +1 -1
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailConfig.js +1 -1
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +15 -19
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsTable.js +46 -34
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionRepositoryCell.js +65 -48
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.test.js +1 -1
- data/webpack/scenes/ContentViews/Publish/CVPublishFinish.js +2 -2
- data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +4 -4
- data/webpack/scenes/ContentViews/components/EnvironmentLabels.js +18 -18
- data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +10 -10
- data/webpack/scenes/ContentViews/expansions/DetailsExpansion.js +2 -2
- data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +7 -7
- data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceTemplate.js +7 -7
- data/webpack/scenes/Hosts/ChangeContentSource/components/FormField.js +3 -3
- data/webpack/scenes/ModuleStreams/Details/ModuleStreamDetailsReducer.js +18 -18
- data/webpack/scenes/ModuleStreams/ModuleStreamsReducer.js +26 -26
- data/webpack/scenes/Organizations/OrganizationReducer.js +8 -8
- data/webpack/scenes/RedHatRepositories/components/EnabledRepository/EnabledRepositoryContent.js +4 -4
- data/webpack/scenes/RedHatRepositories/components/RepositorySetRepositories.js +1 -1
- data/webpack/scenes/Settings/SettingsReducer.js +14 -14
- data/webpack/scenes/Settings/Tables/TableReducer.js +23 -23
- data/webpack/scenes/Subscriptions/Details/SubscriptionDetailInfo.js +2 -2
- data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProductContent.js +15 -15
- data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProducts.js +1 -1
- data/webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js +34 -34
- data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +13 -13
- data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/AirGappedTypeForm.js +3 -3
- data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnTypeForm.js +4 -4
- data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/UpstreamServerTypeForm.js +6 -5
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +5 -5
- data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryReducer.js +16 -16
- data/webpack/scenes/Subscriptions/SubscriptionReducer.js +149 -149
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsReducer.js +41 -41
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Dialogs/DeleteDialog.js +6 -6
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Table.js +12 -12
- data/webpack/services/index.js +36 -36
- data/webpack/utils/helpers.js +5 -5
- metadata +30 -18
- data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesActions.js +0 -27
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.js +0 -244
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b7c14fb8d3608a0596bbe874028ed8966b14c2d530e8f22dd33253e678e7f7b
|
4
|
+
data.tar.gz: 4d762d2ac2cbe0c7362b52901c4fdf671421aae11fe9c3fdf6146b8729221895
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63470c8748cb2f52087d0e6afb152b3e1d7ac7b0985f755ea662189acf807945fba766f6def46417995b665a914adfcf62d5041bb2ea1381c03031a07d34ac34
|
7
|
+
data.tar.gz: 39dfbe4fe023dd34b8f371b2df102ffe8a9318c7f8ee0e67aa37b371c06ac171a8ab73fe6359ca17209209c73e7d083caf91e301b9e3ff040bb68069d48103c0
|
@@ -53,6 +53,7 @@ module Katello
|
|
53
53
|
param :composite, :bool, :desc => N_("Filter only composite content views")
|
54
54
|
param :without, Array, :desc => N_("Do not include this array of content views")
|
55
55
|
param :name, String, :desc => N_("Name of the content view"), :required => false
|
56
|
+
param :label, String, :desc => N_("Label of the content view"), :required => false
|
56
57
|
param_group :search, Api::V2::ApiController
|
57
58
|
add_scoped_search_description_for(ContentView)
|
58
59
|
def index
|
@@ -69,6 +70,7 @@ module Katello
|
|
69
70
|
content_views = ::Foreman::Cast.to_bool(params[:noncomposite]) ? content_views.non_composite : content_views.composite if params[:noncomposite]
|
70
71
|
content_views = ::Foreman::Cast.to_bool(params[:composite]) ? content_views.composite : content_views.non_composite if params[:composite]
|
71
72
|
content_views = content_views.where(:name => params[:name]) if params[:name]
|
73
|
+
content_views = content_views.where(:label => params[:label]) if params[:label]
|
72
74
|
content_views = content_views.where("#{ContentView.table_name}.id NOT IN (?)", params[:without]) if params[:without]
|
73
75
|
content_views
|
74
76
|
end
|
@@ -48,6 +48,7 @@ module Katello
|
|
48
48
|
param :organization_id, :number, :desc => N_("organization identifier")
|
49
49
|
param :library, [true, false], :desc => N_("set true if you want to see only library environments")
|
50
50
|
param :name, String, :desc => N_("filter only environments containing this name")
|
51
|
+
param :label, String, :desc => N_("filter only environments containing this label"), :required => false
|
51
52
|
param_group :search, Api::V2::ApiController
|
52
53
|
add_scoped_search_description_for(KTEnvironment)
|
53
54
|
def index
|
@@ -58,6 +59,7 @@ module Katello
|
|
58
59
|
query = KTEnvironment.readable
|
59
60
|
query = query.where(organization: @organization) if @organization
|
60
61
|
query = query.where(:name => params[:name]) if params[:name]
|
62
|
+
query = query.where(:label => params[:label]) if params[:label]
|
61
63
|
query = query.where(:library => params[:library]) if params[:library]
|
62
64
|
query
|
63
65
|
end
|
@@ -53,7 +53,16 @@ module Katello
|
|
53
53
|
api :POST, "/repositories/bulk/reclaim_space", N_("Reclaim space from On Demand repositories")
|
54
54
|
param :ids, Array, :desc => N_("List of repository ids"), :required => true
|
55
55
|
def reclaim_space_from_repositories
|
56
|
-
|
56
|
+
if @repositories.empty?
|
57
|
+
fail _("No repositories selected.")
|
58
|
+
end
|
59
|
+
repositories = @repositories.select { |repo| repo.download_policy == ::Katello::RootRepository::DOWNLOAD_ON_DEMAND }
|
60
|
+
if repositories.empty?
|
61
|
+
fail _("Only On Demand repositories may have space reclaimed.")
|
62
|
+
end
|
63
|
+
task = async_task(::Actions::BulkAction,
|
64
|
+
::Actions::Pulp3::Repository::ReclaimSpace,
|
65
|
+
repositories)
|
57
66
|
|
58
67
|
respond_for_async :resource => task
|
59
68
|
end
|
@@ -327,6 +327,9 @@ module Katello
|
|
327
327
|
api :POST, "/repositories/:id/reclaim_space", N_("Reclaim space from an On Demand repository")
|
328
328
|
param :id, :number, :required => true, :desc => N_("repository ID")
|
329
329
|
def reclaim_space
|
330
|
+
if @repository.download_policy != ::Katello::RootRepository::DOWNLOAD_ON_DEMAND
|
331
|
+
fail HttpErrors::BadRequest, _("Only On Demand repositories may have space reclaimed.")
|
332
|
+
end
|
330
333
|
task = async_task(::Actions::Pulp3::Repository::ReclaimSpace, @repository)
|
331
334
|
respond_for_async :resource => task
|
332
335
|
rescue Errors::InvalidActionOptionError => e
|
@@ -4,10 +4,10 @@ module Actions
|
|
4
4
|
class Update < Actions::EntryAction
|
5
5
|
def plan(cdn_configuration, options)
|
6
6
|
cdn_configuration.update!(options)
|
7
|
-
return if cdn_configuration.airgapped?
|
8
7
|
|
9
8
|
if cdn_configuration.upstream_server?
|
10
9
|
resource = ::Katello::Resources::CDN::CdnResource.create(cdn_configuration: cdn_configuration)
|
10
|
+
resource.validate!
|
11
11
|
keypair = resource.debug_certificate
|
12
12
|
cdn_configuration.ssl_cert = OpenSSL::X509::Certificate.new(keypair)
|
13
13
|
cdn_configuration.ssl_key = OpenSSL::PKey::RSA.new(keypair)
|
@@ -20,7 +20,7 @@ module Actions
|
|
20
20
|
roots.each do |root|
|
21
21
|
full_path = if cdn_configuration.redhat_cdn?
|
22
22
|
root.product.repo_url(root.library_instance.generate_content_path)
|
23
|
-
|
23
|
+
elsif cdn_configuration.upstream_server?
|
24
24
|
resource.repository_url(content_label: root.content.label)
|
25
25
|
end
|
26
26
|
plan_action(::Actions::Katello::Repository::Update, root, url: full_path)
|
@@ -4,17 +4,16 @@ module Actions
|
|
4
4
|
class ErrataMail < Actions::EntryAction
|
5
5
|
middleware.use Actions::Middleware::ExecuteIfContentsChanged
|
6
6
|
|
7
|
-
def plan(repo,
|
8
|
-
|
9
|
-
plan_self(:repo => repo.id, :last_updated => last_updated.to_s, :contents_changed => contents_changed)
|
7
|
+
def plan(repo, contents_changed = nil)
|
8
|
+
plan_self(:repo => repo.id, :contents_changed => contents_changed)
|
10
9
|
end
|
11
10
|
|
12
11
|
def run
|
13
12
|
::User.current = ::User.anonymous_admin
|
14
|
-
|
15
13
|
repo = ::Katello::Repository.find(input[:repo])
|
14
|
+
last_updated = repo.repository_errata.order('updated_at ASC').last.try(:updated_at) || Time.now
|
16
15
|
users = ::User.select { |user| user.receives?(:sync_errata) && user.organization_ids.include?(repo.organization.id) && user.can?(:view_products, repo.product) }.compact
|
17
|
-
errata = ::Katello::Erratum.where(:id => repo.repository_errata.where('katello_repository_errata.updated_at > ?',
|
16
|
+
errata = ::Katello::Erratum.where(:id => repo.repository_errata.where('katello_repository_errata.updated_at > ?', last_updated).pluck(:erratum_id))
|
18
17
|
|
19
18
|
begin
|
20
19
|
MailNotification[:sync_errata].deliver(:users => users, :repo => repo, :errata => errata) unless (users.blank? || errata.blank?)
|
@@ -51,11 +51,11 @@ module Actions
|
|
51
51
|
plan_action(Katello::Repository::FetchPxeFiles, :id => repo.id)
|
52
52
|
plan_action(Katello::Repository::CorrectChecksum, repo)
|
53
53
|
concurrence do
|
54
|
-
plan_action(Katello::Repository::ErrataMail, repo,
|
54
|
+
plan_action(Katello::Repository::ErrataMail, repo, output[:contents_changed])
|
55
55
|
plan_action(Actions::Katello::Applicability::Repository::Regenerate, :repo_ids => [repo.id]) if generate_applicability
|
56
56
|
end
|
57
57
|
plan_self(:id => repo.id, :sync_result => output, :skip_metadata_check => skip_metadata_check, :validate_contents => validate_contents,
|
58
|
-
:contents_changed => contents_changed)
|
58
|
+
:contents_changed => output[:contents_changed])
|
59
59
|
plan_action(Katello::Repository::SyncHook, :id => repo.id)
|
60
60
|
end
|
61
61
|
end
|
@@ -11,15 +11,25 @@ module Actions
|
|
11
11
|
def invoke_external_task
|
12
12
|
tasks = []
|
13
13
|
content_view = ::Katello::ContentView.find(input[:content_view_id])
|
14
|
-
content_view.repository_references.
|
14
|
+
to_delete = content_view.repository_references.select do |repository_reference|
|
15
15
|
repo = repository_reference.root_repository.library_instance
|
16
|
-
|
17
|
-
|
16
|
+
if delete_href?(repository_reference.repository_href, content_view)
|
17
|
+
#force pulp3 in case we've done migrations, but haven't switched over yet
|
18
|
+
tasks << repo.backend_service(smart_proxy, true).delete_repository(repository_reference)
|
19
|
+
true
|
20
|
+
else
|
21
|
+
false
|
22
|
+
end
|
18
23
|
end
|
19
|
-
|
24
|
+
to_delete.each(&:destroy)
|
20
25
|
|
21
26
|
output[:pulp_tasks] = tasks
|
22
27
|
end
|
28
|
+
|
29
|
+
#migrated composites may have the same RepositoryReference as their component
|
30
|
+
def delete_href?(href, content_view)
|
31
|
+
::Katello::Pulp3::RepositoryReference.where(:repository_href => href).where.not(:content_view_id => content_view.id).empty?
|
32
|
+
end
|
23
33
|
end
|
24
34
|
end
|
25
35
|
end
|
@@ -18,8 +18,7 @@ module Actions
|
|
18
18
|
content_view_version_id: input[:content_view_version_id],
|
19
19
|
path: input[:path],
|
20
20
|
metadata: input[:metadata],
|
21
|
-
audit_comment: ::Katello::ContentViewVersionImportHistory.generate_audit_comment(
|
22
|
-
user: User.current,
|
21
|
+
audit_comment: ::Katello::ContentViewVersionImportHistory.generate_audit_comment(user: User.current,
|
23
22
|
content_view_name: input[:content_view_name])
|
24
23
|
)
|
25
24
|
output[:import_history_id] = history.id
|
@@ -2,16 +2,9 @@ module Actions
|
|
2
2
|
module Pulp3
|
3
3
|
module Repository
|
4
4
|
class ReclaimSpace < Pulp3::AbstractAsyncTask
|
5
|
-
def plan(
|
6
|
-
|
7
|
-
|
8
|
-
fail _("No repositories selected.")
|
9
|
-
end
|
10
|
-
repositories = repositories.select { |repo| repo.download_policy == ::Katello::RootRepository::DOWNLOAD_ON_DEMAND }
|
11
|
-
if repositories.empty?
|
12
|
-
fail _("Only On Demand repositories may have space reclaimed.")
|
13
|
-
end
|
14
|
-
repository_hrefs = ::Katello::Pulp3::RepositoryReference.default_cv_repository_hrefs(repositories, Organization.current)
|
5
|
+
def plan(repo, smart_proxy = SmartProxy.pulp_primary)
|
6
|
+
action_subject(repo)
|
7
|
+
repository_hrefs = ::Katello::Pulp3::RepositoryReference.default_cv_repository_hrefs([repo], Organization.current || repositories.first.organization)
|
15
8
|
plan_self(repository_hrefs: repository_hrefs, smart_proxy_id: smart_proxy.id)
|
16
9
|
end
|
17
10
|
|
@@ -4,8 +4,8 @@ module Katello
|
|
4
4
|
class KatelloCdn < CdnResource
|
5
5
|
def initialize(url, options)
|
6
6
|
@organization_label = options.delete(:organization_label)
|
7
|
-
@content_view_label = options.delete(:content_view_label)
|
8
|
-
@lifecycle_environment_label = options.delete(:lifecycle_environment_label)
|
7
|
+
@content_view_label = options.delete(:content_view_label) || ::Katello::OrganizationCreator::DEFAULT_CONTENT_VIEW_LABEL
|
8
|
+
@lifecycle_environment_label = options.delete(:lifecycle_environment_label) || ::Katello::OrganizationCreator::DEFAULT_LIFECYCLE_ENV_LABEL
|
9
9
|
fail ArgumentError, "No upstream organization was specified" if @organization_label.nil?
|
10
10
|
|
11
11
|
super
|
@@ -18,16 +18,33 @@ module Katello
|
|
18
18
|
|
19
19
|
fail _("Upstream organization %s does not provide this content path") % @organization_label if repo_set.nil?
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
params = {
|
22
|
+
full_result: true,
|
23
|
+
organization_id: organization['id'],
|
24
|
+
content_view_id: content_view_id,
|
25
|
+
environment_id: lifecycle_environment_id,
|
26
|
+
search: CGI.escape("content_label = #{repo_set['label']}")
|
27
|
+
}
|
28
|
+
query_params = params.map { |key, value| "#{key}=#{value}" }
|
29
|
+
|
30
|
+
url = "/katello/api/v2/repositories?#{query_params.join("&")}"
|
23
31
|
response = get(url)
|
24
32
|
json_body = JSON.parse(response)
|
25
33
|
results = json_body['results']
|
26
34
|
|
27
|
-
results.map do |
|
35
|
+
results.map do |repo|
|
36
|
+
arch = repo['arch']
|
37
|
+
arch = nil if arch == "noarch"
|
38
|
+
substitutions = {
|
39
|
+
:releasever => repo['minor'],
|
40
|
+
:basearch => arch
|
41
|
+
}.compact
|
42
|
+
path = substitutions.inject(content_path) do |path_url, (key, value)|
|
43
|
+
path_url.gsub("$#{key}", value)
|
44
|
+
end
|
28
45
|
{
|
29
|
-
path:
|
30
|
-
substitutions:
|
46
|
+
path: path,
|
47
|
+
substitutions: substitutions
|
31
48
|
}
|
32
49
|
end
|
33
50
|
end
|
@@ -36,12 +53,16 @@ module Katello
|
|
36
53
|
true
|
37
54
|
end
|
38
55
|
|
56
|
+
def validate!
|
57
|
+
organization && content_view_id && lifecycle_environment_id
|
58
|
+
end
|
59
|
+
|
39
60
|
def debug_certificate
|
40
61
|
get("/katello/api/v2/organizations/#{organization['id']}/download_debug_certificate")
|
41
62
|
end
|
42
63
|
|
43
64
|
def content_view_id
|
44
|
-
rs = get("/katello/api/v2/organizations/#{organization['id']}/content_views?
|
65
|
+
rs = get("/katello/api/v2/organizations/#{organization['id']}/content_views?search=#{CGI.escape("label=#{@content_view_label}")}")
|
45
66
|
content_view = JSON.parse(rs)['results']&.first
|
46
67
|
if content_view.blank?
|
47
68
|
fail _("Upstream organization %{org_label} does not have a content view with the label %{cv_label}") % { org_label: @organization_label,
|
@@ -51,7 +72,7 @@ module Katello
|
|
51
72
|
end
|
52
73
|
|
53
74
|
def lifecycle_environment_id
|
54
|
-
rs = get("/katello/api/v2/organizations/#{organization['id']}/environments")
|
75
|
+
rs = get("/katello/api/v2/organizations/#{organization['id']}/environments?full_result=true")
|
55
76
|
env = JSON.parse(rs)['results'].find { |lce| lce['label'] == @lifecycle_environment_label }
|
56
77
|
|
57
78
|
if env.blank?
|
@@ -61,7 +82,7 @@ module Katello
|
|
61
82
|
env["id"]
|
62
83
|
end
|
63
84
|
|
64
|
-
def repository_url(content_label:)
|
85
|
+
def repository_url(content_label:, arch:, major:, minor:)
|
65
86
|
params = {
|
66
87
|
search: CGI.escape("content_label = #{content_label}")
|
67
88
|
}
|
@@ -72,17 +93,19 @@ module Katello
|
|
72
93
|
query_params = params.map { |key, value| "#{key}=#{value}" }
|
73
94
|
url = "/katello/api/v2/organizations/#{organization['id']}/repositories?#{query_params.join('&')}"
|
74
95
|
response = get(url)
|
75
|
-
repository = JSON.parse(response)['results']
|
76
|
-
|
96
|
+
repository = JSON.parse(response)['results']&.find { |r| r['arch'] == arch && r['major'] == major && r['minor'] == minor }
|
77
97
|
if repository.nil?
|
78
98
|
msg_params = { content_label: content_label,
|
99
|
+
arch: arch,
|
100
|
+
major: major,
|
101
|
+
minor: minor,
|
79
102
|
org_label: @organization_label,
|
80
103
|
cv_label: @content_view_label || Katello::OrganizationCreator::DEFAULT_CONTENT_VIEW_LABEL,
|
81
104
|
env_label: @lifecycle_environment_label || Katello::OrganizationCreator::DEFAULT_LIFECYCLE_ENV_LABEL
|
82
105
|
}
|
83
106
|
|
84
|
-
fail _("Repository with content label %{content_label} was not found in upstream organization %{org_label},"\
|
85
|
-
" content view %{cv_label} and lifecycle environment %{env_label}
|
107
|
+
fail _("Repository with content label: '%{content_label}'#{arch ? ', arch: \'%{arch}\'' : ''}#{minor ? ', version: \'%{minor}\'' : ''} was not found in upstream organization '%{org_label}',"\
|
108
|
+
" content view '%{cv_label}' and lifecycle environment '%{env_label}'") % msg_params
|
86
109
|
end
|
87
110
|
repository['full_path']
|
88
111
|
end
|
@@ -8,8 +8,9 @@ module Katello
|
|
8
8
|
def filter_package_groups_by_pulp_href(package_groups, package_pulp_hrefs)
|
9
9
|
rpms = Katello::Rpm.where(:pulp_id => package_pulp_hrefs)
|
10
10
|
package_groups.reject do |package_group|
|
11
|
+
#copy the package group as long as we have 1 package from the group
|
11
12
|
package_group.package_names.empty? ||
|
12
|
-
(package_group.package_names
|
13
|
+
(package_group.package_names & rpms.pluck(:name)).empty?
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
@@ -34,7 +34,7 @@ module Katello
|
|
34
34
|
:content_type => katello_content_type,
|
35
35
|
:unprotected => unprotected?,
|
36
36
|
:download_policy => download_policy,
|
37
|
-
:mirroring_policy =>
|
37
|
+
:mirroring_policy => mirroring_policy
|
38
38
|
)
|
39
39
|
|
40
40
|
Repository.new(:root => root,
|
@@ -74,8 +74,9 @@ module Katello
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def feed_url
|
77
|
+
return if product.organization.cdn_configuration.airgapped?
|
77
78
|
@feed_url ||= if product.cdn_resource&.respond_to?(:repository_url)
|
78
|
-
product.cdn_resource.repository_url(content_label: content.label)
|
79
|
+
product.cdn_resource.repository_url(content_label: content.label, arch: arch, major: version[:major], minor: version[:minor])
|
79
80
|
else
|
80
81
|
product.repo_url(path)
|
81
82
|
end
|
@@ -136,6 +137,14 @@ module Katello
|
|
136
137
|
""
|
137
138
|
end
|
138
139
|
end
|
140
|
+
|
141
|
+
def mirroring_policy
|
142
|
+
if katello_content_type == Repository::YUM_TYPE
|
143
|
+
Katello::RootRepository::MIRRORING_POLICY_COMPLETE
|
144
|
+
else
|
145
|
+
Katello::RootRepository::MIRRORING_POLICY_CONTENT
|
146
|
+
end
|
147
|
+
end
|
139
148
|
end
|
140
149
|
end
|
141
150
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Katello
|
2
|
+
module Concerns::AuditCommentExtensions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
# to prevent PG::StringDataRightTruncation: ERROR: value too long for type character varying(255)
|
7
|
+
def truncate_audit_comment(long_comment)
|
8
|
+
if long_comment.length > 255
|
9
|
+
Rails.logger.info "Truncating audit comment: #{long_comment}"
|
10
|
+
"#{long_comment[0..250]}..."
|
11
|
+
else
|
12
|
+
long_comment
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -401,10 +401,20 @@ module Katello
|
|
401
401
|
end
|
402
402
|
|
403
403
|
def package_names_for_job_template(action:, search:)
|
404
|
-
actions =
|
404
|
+
actions = %w(install remove update).freeze
|
405
405
|
case action
|
406
406
|
when 'install'
|
407
407
|
::Katello::Rpm.yum_installable_for_host(self).search_for(search).distinct.pluck(:name)
|
408
|
+
when 'remove'
|
409
|
+
return [] if search.empty?
|
410
|
+
|
411
|
+
installed_packages.search_for(search).distinct.pluck(:name)
|
412
|
+
when 'update'
|
413
|
+
return [] if search.empty?
|
414
|
+
|
415
|
+
pkg_names = installed_packages.search_for(search).distinct.pluck(:name)
|
416
|
+
upgrades = ::Katello::Rpm.installable_for_hosts([self]).select(:id, :name, :nvra, :evr).order(evr: :desc).group_by(&:name)
|
417
|
+
pkg_names.map { |p| upgrades[p]&.first&.nvra }.compact
|
408
418
|
else
|
409
419
|
fail ::Foreman::Exception.new(N_("package_names_for_job_template: Action must be one of %s"), actions.join(', '))
|
410
420
|
end
|
@@ -179,6 +179,7 @@ module Katello
|
|
179
179
|
config.scheme = uri.scheme
|
180
180
|
pulp3_ssl_configuration(config)
|
181
181
|
config.debugging = false
|
182
|
+
config.timeout = SETTINGS[:katello][:rest_client_timeout]
|
182
183
|
config.logger = ::Foreman::Logging.logger('katello/pulp_rest')
|
183
184
|
config.username = self.setting(PULP3_FEATURE, 'username')
|
184
185
|
config.password = self.setting(PULP3_FEATURE, 'password')
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Katello
|
2
2
|
class ContentViewVersionExportHistory < Katello::Model
|
3
3
|
include Authorization::ContentViewVersionExportHistory
|
4
|
+
include Concerns::AuditCommentExtensions
|
4
5
|
audited except: :metadata
|
5
6
|
delegate :organization, to: :content_view_version
|
6
7
|
delegate :id, to: :organization, prefix: true
|
@@ -58,7 +59,7 @@ module Katello
|
|
58
59
|
export_descriptor = "export of content view '#{content_view_version.content_view.name}' version #{content_view_version.version}"
|
59
60
|
export_descriptor += " from #{from_version.name}" if from_version
|
60
61
|
end
|
61
|
-
"#{export_type&.capitalize} #{export_descriptor} created by #{user.to_label}"
|
62
|
+
truncate_audit_comment("#{export_type&.capitalize} #{export_descriptor} created by #{user.to_label}")
|
62
63
|
end
|
63
64
|
end
|
64
65
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module Katello
|
2
2
|
class ContentViewVersionImportHistory < Katello::Model
|
3
3
|
include Authorization::ContentViewVersionImportHistory
|
4
|
+
include Concerns::AuditCommentExtensions
|
4
5
|
|
5
6
|
audited except: :metadata
|
6
7
|
delegate :organization, to: :content_view_version
|
@@ -31,12 +32,11 @@ module Katello
|
|
31
32
|
scoped_search :on => :id, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
|
32
33
|
scoped_search :on => :import_type, :rename => :type, :complete_value => ContentViewVersionExportHistory::EXPORT_TYPES
|
33
34
|
|
34
|
-
def self.generate_audit_comment(user:,
|
35
|
-
_("Content imported
|
36
|
-
path: path,
|
35
|
+
def self.generate_audit_comment(user:, content_view_name:)
|
36
|
+
truncate_audit_comment(_("Content imported by %{user} into content view '%{name}'") % {
|
37
37
|
user: user.to_label,
|
38
38
|
name: content_view_name
|
39
|
-
}
|
39
|
+
})
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -37,6 +37,16 @@ module Katello
|
|
37
37
|
:stream => available_module_stream.stream}).exists?
|
38
38
|
end
|
39
39
|
|
40
|
+
def install_status
|
41
|
+
return 'Not installed' if installed_profiles.blank?
|
42
|
+
case status
|
43
|
+
when 'disabled'
|
44
|
+
'Installed'
|
45
|
+
when 'enabled'
|
46
|
+
upgradable? ? 'Upgradable' : 'Up-to-date'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
40
50
|
def self.upgradable(host)
|
41
51
|
upgradable_module_name_streams = ModuleStream.installable_for_hosts([host]).select(:name, :stream)
|
42
52
|
|
@@ -15,6 +15,7 @@ module Katello
|
|
15
15
|
has_many :host_installed_packages, :class_name => "Katello::HostInstalledPackage", :dependent => :destroy, :inverse_of => :installed_package
|
16
16
|
has_many :hosts, :through => :host_installed_packages, :class_name => "::Host"
|
17
17
|
|
18
|
+
scoped_search :on => :id, :complete_value => true
|
18
19
|
scoped_search :on => :name, :complete_value => true
|
19
20
|
scoped_search :on => :nvrea
|
20
21
|
scoped_search :on => :nvra
|
@@ -75,6 +75,7 @@ module Katello
|
|
75
75
|
ERROR_CLASS_NAME = "Environment".freeze
|
76
76
|
|
77
77
|
scoped_search :on => :name, :complete_value => true
|
78
|
+
scoped_search :on => :label, :complete_value => true
|
78
79
|
scoped_search :on => :organization_id, :complete_value => true, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
|
79
80
|
scoped_search :on => :id, :complete_value => true, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
|
80
81
|
|
@@ -62,7 +62,8 @@ module Katello
|
|
62
62
|
validates_lengths_from_database :except => [:label]
|
63
63
|
validates_with Validators::KatelloLabelFormatValidator, :attributes => :label
|
64
64
|
validates_with Validators::KatelloNameFormatValidator, :attributes => :name
|
65
|
-
validates_with Validators::KatelloUrlFormatValidator, :attributes => :url,
|
65
|
+
validates_with Validators::KatelloUrlFormatValidator, :attributes => :url,
|
66
|
+
:nil_allowed => proc { |repo| repo.custom? || repo.organization.cdn_configuration.airgapped? },
|
66
67
|
:field_name => :url
|
67
68
|
validates_with Validators::RootRepositoryUniqueAttributeValidator, :attributes => :name
|
68
69
|
validates_with Validators::RootRepositoryUniqueAttributeValidator, :attributes => :label
|
@@ -83,6 +84,7 @@ module Katello
|
|
83
84
|
validate :ensure_valid_deb_constraints, :if => :deb?
|
84
85
|
validate :ensure_no_checksum_on_demand
|
85
86
|
validate :ensure_valid_mirroring_policy
|
87
|
+
validate :ensure_valid_retain_package_versions_count
|
86
88
|
validates :checksum_type, :inclusion => {:in => CHECKSUM_TYPES}, :allow_blank => true
|
87
89
|
validates :product_id, :presence => true
|
88
90
|
validates :content_type, :inclusion => {
|
@@ -306,6 +308,16 @@ module Katello
|
|
306
308
|
end
|
307
309
|
end
|
308
310
|
|
311
|
+
def ensure_valid_retain_package_versions_count
|
312
|
+
return unless self.retain_package_versions_count
|
313
|
+
unless yum?
|
314
|
+
errors.add(:retain_package_versions_count, N_("is only allowed for Yum repositories."))
|
315
|
+
end
|
316
|
+
if self.retain_package_versions_count.to_i < 0
|
317
|
+
errors.add(:retain_package_versions_count, N_("must not be a negative value."))
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
309
321
|
def custom_content_path
|
310
322
|
parts = []
|
311
323
|
# We generate repo path only for custom product content. We add this
|
@@ -372,7 +384,7 @@ module Katello
|
|
372
384
|
|
373
385
|
def pulp_update_needed?
|
374
386
|
changeable_attributes = %w(url unprotected checksum_type docker_upstream_name download_policy mirroring_policy verify_ssl_on_sync
|
375
|
-
upstream_username upstream_password ignorable_content
|
387
|
+
upstream_username upstream_password ignorable_content retain_package_versions_count
|
376
388
|
ssl_ca_cert_id ssl_client_cert_id ssl_client_key_id http_proxy_policy http_proxy_id download_concurrency)
|
377
389
|
changeable_attributes += %w(name container_repository_name include_tags exclude_tags) if docker?
|
378
390
|
changeable_attributes += %w(deb_releases deb_components deb_architectures gpg_key_id) if deb?
|
@@ -105,8 +105,15 @@ class Setting::Content < Setting
|
|
105
105
|
"/etc/pki/katello/private/pulp-client.key", N_('Pulp client key')),
|
106
106
|
self.set('pulp_client_cert', N_("Path for ssl cert used for pulp server auth"),
|
107
107
|
"/etc/pki/katello/certs/pulp-client.crt", N_('Pulp client cert')),
|
108
|
-
self.set('
|
109
|
-
|
108
|
+
self.set('sync_total_timeout', N_("The maximum number of second that Pulp can take to do a single sync operation, e.g., download a single metadata file."),
|
109
|
+
3600, N_('Sync Total Timeout')),
|
110
|
+
self.set('sync_connect_timeout_v2',
|
111
|
+
N_("The maximum number of seconds for Pulp to establish a new connection or for waiting for a free connection from a pool if pool connection limits are exceeded."),
|
112
|
+
60, N_('Sync Connect Timeout')),
|
113
|
+
self.set('sync_sock_connect_timeout', N_("The maximum number of seconds for Pulp to connect to a peer for a new connection not given from a pool."),
|
114
|
+
60, N_('Sync Sock Connect Timeout')),
|
115
|
+
self.set('sync_sock_read_timeout', N_("The maximum number of seconds that Pulp can take to download a file, not counting connection time."),
|
116
|
+
3600, N_('Sync Sock Read Timeout')),
|
110
117
|
self.set('remote_execution_by_default', N_("If this is enabled, remote execution is used instead of katello-agent for remote actions"),
|
111
118
|
false, N_('Use remote execution by default')),
|
112
119
|
self.set('unregister_delete_host', N_("When unregistering a host via subscription-manager, also delete the host record. Managed resources linked to host " \
|
@@ -133,11 +133,15 @@ module Katello
|
|
133
133
|
end
|
134
134
|
|
135
135
|
def create_cdn_configuration
|
136
|
-
@cdn_configuration = Katello::CdnConfiguration.where(
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
136
|
+
@cdn_configuration = Katello::CdnConfiguration.where(organization: @organization)
|
137
|
+
|
138
|
+
if @cdn_configuration.blank?
|
139
|
+
Katello::CdnConfiguration.where(
|
140
|
+
organization: @organization,
|
141
|
+
url: ::Katello::Resources::CDN::CdnResource.redhat_cdn_url,
|
142
|
+
type: ::Katello::CdnConfiguration::CDN_TYPE
|
143
|
+
).first_or_create!
|
144
|
+
end
|
141
145
|
end
|
142
146
|
end
|
143
147
|
end
|
@@ -36,6 +36,10 @@ module Katello
|
|
36
36
|
PulpRpmClient::ContentPackageenvironmentsApi.new(api_client)
|
37
37
|
end
|
38
38
|
|
39
|
+
def content_modulemd_defaults_api
|
40
|
+
PulpRpmClient::ContentModulemdDefaultsApi.new(api_client)
|
41
|
+
end
|
42
|
+
|
39
43
|
def content_repo_metadata_files_api
|
40
44
|
PulpRpmClient::ContentRepoMetadataFilesApi.new(api_client)
|
41
45
|
end
|