katello 4.13.0.rc1 → 4.13.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/registry/registry_proxies_controller.rb +334 -23
- data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +8 -0
- data/app/controllers/katello/api/v2/repositories_controller.rb +1 -1
- data/app/lib/actions/katello/capsule_content/sync_capsule.rb +7 -2
- data/app/lib/actions/katello/organization/manifest_delete.rb +6 -1
- data/app/lib/actions/katello/repository/create.rb +17 -11
- data/app/lib/actions/katello/repository/create_root.rb +4 -2
- data/app/lib/actions/katello/repository/discover.rb +11 -4
- data/app/lib/actions/katello/upstream_subscriptions/bind_entitlement.rb +1 -1
- data/app/lib/actions/pulp3/orchestration/orphan_cleanup/remove_orphans.rb +1 -0
- data/app/lib/actions/pulp3/orphan_cleanup/purge_completed_tasks.rb +15 -0
- data/app/lib/actions/pulp3/repository/create_publication.rb +4 -0
- data/app/lib/katello/repo_discovery.rb +4 -190
- data/app/lib/katello/resources/discovery/container.rb +127 -0
- data/app/lib/katello/resources/discovery/yum.rb +95 -0
- data/app/lib/katello/util/http_helper.rb +15 -0
- data/app/models/732bd3db9f64c621c64d2be4f2a838727aac0845.patch +61 -0
- data/app/models/katello/content_view.rb +2 -0
- data/app/models/katello/glue/pulp/repos.rb +8 -1
- data/app/models/katello/repository.rb +5 -1
- data/app/models/katello/repository.rb.bak +978 -0
- data/app/models/katello/root_repository.rb +14 -2
- data/app/models/katello/trace_status.rb +1 -1
- data/app/services/katello/pulp3/api/core.rb +8 -0
- data/app/services/katello/pulp3/api/docker.rb +4 -0
- data/app/services/katello/pulp3/content_view_version/import_validator.rb.bak +166 -0
- data/app/services/katello/pulp3/content_view_version/importable_repositories.rb.bak +164 -0
- data/app/services/katello/pulp3/repository/yum.rb +1 -6
- data/app/services/katello/repository_type.rb +1 -1
- data/app/views/foreman/smart_proxies/_content_tab.html.erb +3 -1
- data/config/initializers/monkeys.rb +0 -1
- data/db/migrate/20240520142245_add_container_push_props_to_repo.rb +7 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/checksum.service.js +6 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +3 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +0 -3
- data/lib/katello/plugin.rb +12 -0
- data/lib/katello/repository_types/docker.rb +1 -0
- data/lib/katello/repository_types/yum.rb +1 -0
- data/lib/katello/tasks/update_repository_expiry.rake +114 -0
- data/lib/katello/version.rb +1 -1
- data/lib/katello.rb +0 -2
- data/locale/bn/katello.po.time_stamp +0 -0
- data/locale/bn_IN/katello.po.time_stamp +0 -0
- data/locale/ca/katello.po.time_stamp +0 -0
- data/locale/cs/katello.po.time_stamp +0 -0
- data/locale/cs_CZ/katello.po.time_stamp +0 -0
- data/locale/de/katello.po.time_stamp +0 -0
- data/locale/de_AT/katello.po.time_stamp +0 -0
- data/locale/de_DE/katello.po.time_stamp +0 -0
- data/locale/el/katello.po.time_stamp +0 -0
- data/locale/en/katello.po.time_stamp +0 -0
- data/locale/en_GB/katello.po.time_stamp +0 -0
- data/locale/en_US/katello.po.time_stamp +0 -0
- data/locale/es/katello.po.time_stamp +0 -0
- data/locale/et_EE/katello.po.time_stamp +0 -0
- data/locale/fr/katello.po.time_stamp +0 -0
- data/locale/gl/katello.po.time_stamp +0 -0
- data/locale/gu/katello.po.time_stamp +0 -0
- data/locale/he_IL/katello.po.time_stamp +0 -0
- data/locale/hi/katello.po.time_stamp +0 -0
- data/locale/id/katello.po.time_stamp +0 -0
- data/locale/it/katello.po.time_stamp +0 -0
- data/locale/ja/katello.po.time_stamp +0 -0
- data/locale/ka/katello.po.time_stamp +0 -0
- data/locale/kn/katello.po.time_stamp +0 -0
- data/locale/ko/katello.po.time_stamp +0 -0
- data/locale/ml_IN/katello.po.time_stamp +0 -0
- data/locale/mr/katello.po.time_stamp +0 -0
- data/locale/nl_NL/katello.po.time_stamp +0 -0
- data/locale/or/katello.po.time_stamp +0 -0
- data/locale/pa/katello.po.time_stamp +0 -0
- data/locale/pl/katello.po.time_stamp +0 -0
- data/locale/pl_PL/katello.po.time_stamp +0 -0
- data/locale/pt/katello.po.time_stamp +0 -0
- data/locale/pt_BR/katello.po.time_stamp +0 -0
- data/locale/ro/katello.po.time_stamp +0 -0
- data/locale/ro_RO/katello.po.time_stamp +0 -0
- data/locale/ru/katello.po.time_stamp +0 -0
- data/locale/sl/katello.po.time_stamp +0 -0
- data/locale/sv_SE/katello.po.time_stamp +0 -0
- data/locale/ta/katello.po.time_stamp +0 -0
- data/locale/ta_IN/katello.po.time_stamp +0 -0
- data/locale/te/katello.po.time_stamp +0 -0
- data/locale/tr/katello.po.time_stamp +0 -0
- data/locale/vi/katello.po.time_stamp +0 -0
- data/locale/vi_VN/katello.po.time_stamp +0 -0
- data/locale/zh/katello.po.time_stamp +0 -0
- data/locale/zh_CN/katello.po.time_stamp +0 -0
- data/locale/zh_TW/katello.po.time_stamp +0 -0
- data/package.json +0 -1
- data/webpack/components/Content/ContentTable.js +0 -1
- data/webpack/components/Content/__tests__/__snapshots__/ContentTable.test.js.snap +0 -1
- data/webpack/global_test_setup.js.bak +59 -0
- data/webpack/scenes/ModuleStreams/ModuleStreamsPage.js +33 -39
- data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamPage.test.js +4 -2
- data/webpack/scenes/ModuleStreams/__tests__/__snapshots__/ModuleStreamsTable.test.js.snap +0 -1
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +4 -2
- metadata +87 -28
- data/lib/monkeys/anemone.rb +0 -33
- data/webpack/utils/__tests__/useParamsWithHash.test.js +0 -22
- data/webpack/utils/paramsFromHash.js +0 -16
- data/webpack/utils/useUrlParams.js +0 -14
@@ -17,7 +17,7 @@ module Katello
|
|
17
17
|
DOWNLOAD_POLICIES = [DOWNLOAD_IMMEDIATE, DOWNLOAD_ON_DEMAND].freeze
|
18
18
|
|
19
19
|
IGNORABLE_CONTENT_UNIT_TYPES = %w(srpm treeinfo).freeze
|
20
|
-
CHECKSUM_TYPES = %w(
|
20
|
+
CHECKSUM_TYPES = %w(sha256 sha384 sha512).freeze
|
21
21
|
|
22
22
|
SUBSCRIBABLE_TYPES = [Repository::YUM_TYPE, Repository::OSTREE_TYPE, Repository::DEB_TYPE].freeze
|
23
23
|
SKIPABLE_METADATA_TYPES = [Repository::YUM_TYPE, Repository::DEB_TYPE].freeze
|
@@ -60,6 +60,8 @@ module Katello
|
|
60
60
|
has_many :repository_references, :class_name => 'Katello::Pulp3::RepositoryReference',
|
61
61
|
:dependent => :destroy, :inverse_of => :root_repository
|
62
62
|
|
63
|
+
before_validation :remove_sha1_checksum_type, if: :sha1_checksum?
|
64
|
+
|
63
65
|
validates_lengths_from_database :except => [:label]
|
64
66
|
validates_with Validators::KatelloLabelFormatValidator, :attributes => :label
|
65
67
|
validates_with Validators::KatelloNameFormatValidator, :attributes => :name
|
@@ -112,6 +114,8 @@ module Katello
|
|
112
114
|
only_integer: true
|
113
115
|
}
|
114
116
|
|
117
|
+
validates :container_push_name_format, inclusion: { in: ['label', 'id'].freeze, allow_nil: true}
|
118
|
+
|
115
119
|
scope :subscribable, -> { where(content_type: RootRepository::SUBSCRIBABLE_TYPES) }
|
116
120
|
scope :skipable_metadata_check, -> { where(content_type: RootRepository::SKIPABLE_METADATA_TYPES) }
|
117
121
|
scope :has_url, -> { where.not(:url => nil) }
|
@@ -155,6 +159,14 @@ module Katello
|
|
155
159
|
joins(:product).where("#{Katello::Product.table_name}.organization_id" => org)
|
156
160
|
end
|
157
161
|
|
162
|
+
def sha1_checksum?
|
163
|
+
checksum_type == 'sha1'
|
164
|
+
end
|
165
|
+
|
166
|
+
def remove_sha1_checksum_type
|
167
|
+
self.checksum_type = nil
|
168
|
+
end
|
169
|
+
|
158
170
|
def ensure_content_attribute_restrictions
|
159
171
|
CONTENT_ATTRIBUTE_RESTRICTIONS.each do |attribute, value|
|
160
172
|
if self.send(attribute).present? && !value.include?(self.content_type)
|
@@ -195,7 +207,7 @@ module Katello
|
|
195
207
|
def ensure_docker_repo_unprotected
|
196
208
|
unless unprotected
|
197
209
|
errors.add(:base, _("Container Image Repositories are not protected at this time. " \
|
198
|
-
|
210
|
+
"They need to be published via http to be available to containers."))
|
199
211
|
end
|
200
212
|
end
|
201
213
|
|
@@ -36,7 +36,7 @@ module Katello
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def to_status(_options = {})
|
39
|
-
traces = host.host_traces.pluck(:app_type)
|
39
|
+
traces = host.host_traces.reload.pluck(:app_type)
|
40
40
|
traces.delete(Katello::HostTracer::TRACE_APP_TYPE_SESSION)
|
41
41
|
|
42
42
|
if traces.include?(Katello::HostTracer::TRACE_APP_TYPE_STATIC)
|
@@ -176,6 +176,14 @@ module Katello
|
|
176
176
|
nil
|
177
177
|
end
|
178
178
|
|
179
|
+
def purge_class
|
180
|
+
PulpcoreClient::Purge
|
181
|
+
end
|
182
|
+
|
183
|
+
def purge_completed_tasks
|
184
|
+
tasks_api.purge(purge_class.new(finished_before: DateTime.now - Setting[:completed_pulp_task_protection_days]))
|
185
|
+
end
|
186
|
+
|
179
187
|
def delete_orphans
|
180
188
|
[orphans_api.cleanup(PulpcoreClient::OrphansCleanup.new(orphan_protection_time: (smart_proxy.pulp_mirror? ? 0 : Setting[:orphan_protection_time])))]
|
181
189
|
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module Katello
|
2
|
+
module Pulp3
|
3
|
+
module ContentViewVersion
|
4
|
+
class ImportValidator
|
5
|
+
def initialize(import:)
|
6
|
+
@content_view = import.content_view
|
7
|
+
@path = import.path
|
8
|
+
@smart_proxy = import.smart_proxy
|
9
|
+
@organization = import.organization
|
10
|
+
@metadata_map = import.metadata_map
|
11
|
+
@interested_repos = import.intersecting_repos_library_and_metadata
|
12
|
+
@redhat_library_products = redhat_library_products
|
13
|
+
end
|
14
|
+
|
15
|
+
def check!
|
16
|
+
if @metadata_map.content_view.blank? && !metadata_map.syncable_format?
|
17
|
+
fail _("Content view not provided in the metadata")
|
18
|
+
end
|
19
|
+
|
20
|
+
ensure_non_syncable_path_valid! unless @metadata_map.syncable_format?
|
21
|
+
ensure_pulp_importable!
|
22
|
+
if @content_view && !@content_view.default?
|
23
|
+
ensure_non_composite!
|
24
|
+
ensure_importing_cvv_does_not_exist!
|
25
|
+
ensure_from_cvv_exists!
|
26
|
+
end
|
27
|
+
ensure_manifest_imported!
|
28
|
+
ensure_metadata_matches_repos_in_library!
|
29
|
+
ensure_redhat_products_metadata_are_in_the_library!
|
30
|
+
end
|
31
|
+
|
32
|
+
def ensure_non_syncable_path_valid!
|
33
|
+
uri = URI(@path)
|
34
|
+
unless uri.scheme.blank? || uri.scheme == "file"
|
35
|
+
fail _("Invalid path provided. Content can be only imported from file system. ")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def ensure_non_composite!
|
40
|
+
return if @content_view.blank?
|
41
|
+
fail _("Content cannot be imported into a Composite Content View. ") if @content_view.composite?
|
42
|
+
end
|
43
|
+
|
44
|
+
def ensure_pulp_importable!
|
45
|
+
return if @metadata_map.syncable_format?
|
46
|
+
api = ::Katello::Pulp3::Api::Core.new(@smart_proxy).importer_check_api
|
47
|
+
response = api.pulp_import_check_post(toc: "#{@path}/#{@metadata_map.toc}")
|
48
|
+
unless response.toc.is_valid
|
49
|
+
fail response.toc.messages.join("\n")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def ensure_importing_cvv_does_not_exist!
|
54
|
+
major = @metadata_map.content_view_version.major
|
55
|
+
minor = @metadata_map.content_view_version.minor
|
56
|
+
|
57
|
+
if ::Katello::ContentViewVersion.where(major: major, minor: minor, content_view: @content_view).exists?
|
58
|
+
fail _("Content View Version specified in the metadata - '%{name}' already exists. "\
|
59
|
+
"If you wish to replace the existing version, delete %{name} and try again. " % { name: "#{@content_view.name} #{major}.#{minor}" })
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def ensure_from_cvv_exists!
|
64
|
+
major = @metadata_map.content_view_version.major
|
65
|
+
minor = @metadata_map.content_view_version.minor
|
66
|
+
|
67
|
+
if @metadata_map.from_content_view_version
|
68
|
+
from_major = @metadata_map.from_content_view_version.major
|
69
|
+
from_minor = @metadata_map.from_content_view_version.minor
|
70
|
+
|
71
|
+
unless ::Katello::ContentViewVersion.where(major: from_major, minor: from_minor, content_view: @content_view).exists?
|
72
|
+
fail _("Prior Content View Version specified in the metadata - '%{name}' does not exist. "\
|
73
|
+
"Please import the metadata for '%{name}' before importing '%{current}' " % { name: "#{@content_view.name} #{from_major}.#{from_minor}",
|
74
|
+
current: "#{@content_view.name} #{major}.#{minor}"})
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def ensure_manifest_imported!
|
80
|
+
any_rh_repos = @metadata_map.repositories.any?(&:redhat)
|
81
|
+
if any_rh_repos && !@organization.manifest_imported?
|
82
|
+
fail _("No manifest found. Import a manifest with the appropriate subscriptions "\
|
83
|
+
"before importing content.")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def ensure_metadata_matches_repos_in_library!
|
88
|
+
bad_repos = @interested_repos.select do |katello_repo|
|
89
|
+
metadata_repo = metadata_repo_for_katello_repo(katello_repo)
|
90
|
+
|
91
|
+
next unless metadata_repo
|
92
|
+
|
93
|
+
!(katello_repo.content_type == metadata_repo.content_type &&
|
94
|
+
katello_repo.redhat? == metadata_repo.redhat)
|
95
|
+
end
|
96
|
+
|
97
|
+
if bad_repos.any?
|
98
|
+
fail _("The following repositories provided in the import metadata have an incorrect content type or provider type. "\
|
99
|
+
"Make sure the export and import repositories are of the same type before importing\n "\
|
100
|
+
"%{repos}" % { repos: generate_product_repo_i18n_string(bad_repos).join("")}
|
101
|
+
)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def ensure_redhat_products_metadata_are_in_the_library!
|
106
|
+
missing = @metadata_map.repositories.select do |repo|
|
107
|
+
repo.redhat && katello_product_for_metadata_repo(repo).nil?
|
108
|
+
end
|
109
|
+
|
110
|
+
if missing.any?
|
111
|
+
repos_in_import = generate_product_repo_i18n_string(missing)
|
112
|
+
fail _("The organization's manifest does not contain the subscriptions required to enable the following repositories.\n "\
|
113
|
+
"%{repos}" % { repos: repos_in_import.join("")}
|
114
|
+
)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def ensure_no_missing_rh_repos!
|
119
|
+
rh_repos = @metadata_map.repositories.select { |r| r.redhat }
|
120
|
+
helper = ::Katello::Pulp3::ContentViewVersion::ImportableRepositories.new(
|
121
|
+
organization: @organization,
|
122
|
+
metadata_repositories: rh_repos,
|
123
|
+
syncable_format: @metadata_map.syncable_format?,
|
124
|
+
path: path
|
125
|
+
)
|
126
|
+
helper.generate!
|
127
|
+
rh_repos = rh_repos.select do |repo|
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def katello_product_for_metadata_repo(metadata_repo)
|
135
|
+
@redhat_library_products.find do |product|
|
136
|
+
if metadata_repo.redhat && metadata_repo.product.cp_id
|
137
|
+
product.cp_id == metadata_repo.product.cp_id
|
138
|
+
else
|
139
|
+
product.label == metadata_repo.product.label
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def metadata_repo_for_katello_repo(repo)
|
145
|
+
@metadata_map.repositories.find do |metadata_repo|
|
146
|
+
if repo.redhat? && metadata_repo.product.cp_id
|
147
|
+
repo.label == metadata_repo.label && repo.product.cp_id == metadata_repo.product.cp_id
|
148
|
+
else
|
149
|
+
repo.label == metadata_repo.label && repo.product.label == metadata_repo.product.label
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def redhat_library_products
|
155
|
+
::Katello::Product.in_org(@organization).redhat
|
156
|
+
end
|
157
|
+
|
158
|
+
def generate_product_repo_i18n_string(metadata_repos)
|
159
|
+
metadata_repos.map do |repo|
|
160
|
+
_("\n* Product = '%{product}', Repository = '%{repository}'" % { product: repo.product.name, repository: repo.name })
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module Katello
|
2
|
+
module Pulp3
|
3
|
+
module ContentViewVersion
|
4
|
+
class ImportableRepositories
|
5
|
+
attr_reader :creatable, :updatable
|
6
|
+
|
7
|
+
def initialize(organization:,
|
8
|
+
metadata_repositories:,
|
9
|
+
syncable_format: false,
|
10
|
+
path: nil)
|
11
|
+
@organization = organization
|
12
|
+
@metadata_repositories = metadata_repositories
|
13
|
+
@creatable = []
|
14
|
+
@updatable = []
|
15
|
+
@syncable_format = syncable_format
|
16
|
+
@path = path
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_root_repo(metadata_repo:, product:)
|
20
|
+
product.root_repositories.find do |r|
|
21
|
+
if metadata_repo.content&.id && metadata_repo.redhat
|
22
|
+
next if (r.content.cp_content_id != metadata_repo.content.id)
|
23
|
+
next if metadata_repo.arch_substituted? && r.arch != metadata_repo.arch
|
24
|
+
next if metadata_repo.release_version_substituted? && (r.major != metadata_repo.major ||
|
25
|
+
r.minor != metadata_repo.minor)
|
26
|
+
true
|
27
|
+
else
|
28
|
+
r.label == metadata_repo.label
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def generate!
|
34
|
+
# For Red Hat repositories or Custom Repositories in the metadata exclusively
|
35
|
+
# Set up a 2 different list of importable root repositories
|
36
|
+
# creatable: repos that are part of the metadata but not in the library.
|
37
|
+
# They are ready to be created
|
38
|
+
# updatable: repo that are both in the metadata and library.
|
39
|
+
# These may contain updates to the repo and hence ready to be updated.
|
40
|
+
@metadata_repositories.each do |repo|
|
41
|
+
product = product_for_metadata_repo(repo)
|
42
|
+
fail _("Unable to find product '%s' in organization '%s'" % [repo.product.label, @organization.name]) if product.blank?
|
43
|
+
|
44
|
+
root = find_root_repo(product: product, metadata_repo: repo)
|
45
|
+
if root
|
46
|
+
updatable << { repository: root, options: update_repo_params(repo) }
|
47
|
+
elsif repo.redhat
|
48
|
+
product_content = fetch_product_content(repo.content, product)
|
49
|
+
substitutions = {}
|
50
|
+
substitutions[:basearch] = repo.arch if repo.content.arch_substituted?
|
51
|
+
substitutions[:releasever] = repo.minor if repo.content.release_version_substituted?
|
52
|
+
create_options = {
|
53
|
+
product: product,
|
54
|
+
content: product_content,
|
55
|
+
substitutions: substitutions,
|
56
|
+
override_url: fetch_feed_url(repo)
|
57
|
+
}
|
58
|
+
create_options[:override_arch] = repo.arch
|
59
|
+
creatable << create_options
|
60
|
+
else
|
61
|
+
creatable << { repository: product.add_repo(create_repo_params(repo, product)) }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def find_unique_name(metadata_repo, product)
|
69
|
+
name = metadata_repo.name
|
70
|
+
i = 1
|
71
|
+
while product.root_repositories.where(name: name).exists?
|
72
|
+
name = "#{metadata_repo.name} #{i}"
|
73
|
+
i += 1
|
74
|
+
end
|
75
|
+
name
|
76
|
+
end
|
77
|
+
|
78
|
+
def product_for_metadata_repo(repo)
|
79
|
+
if repo.redhat && repo.product.cp_id
|
80
|
+
@organization.products.includes(:root_repositories).find_by(cp_id: repo.product.cp_id)
|
81
|
+
else
|
82
|
+
@organization.products.includes(:root_repositories).find_by(label: repo.product.label)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def fetch_product_content(content_metadata, product)
|
87
|
+
query = ::Katello::Content.joins(:product_contents).where("#{Katello::ProductContent.table_name}.product_id": product.id)
|
88
|
+
table_name = Katello::Content.table_name
|
89
|
+
if content_metadata&.id
|
90
|
+
query.find_by("#{table_name}.cp_content_id": content_metadata.id)
|
91
|
+
else
|
92
|
+
query.find_by("#{table_name}.label": content_metadata.label)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def gpg_key_id(metadata_repo)
|
97
|
+
if metadata_repo.gpg_key
|
98
|
+
@organization.gpg_keys.find_by(name: metadata_repo.gpg_key.name).id
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def create_repo_params(metadata_repo, product)
|
103
|
+
keys = [
|
104
|
+
:label,
|
105
|
+
:description,
|
106
|
+
:arch,
|
107
|
+
:unprotected,
|
108
|
+
:content_type,
|
109
|
+
:checksum_type,
|
110
|
+
:os_versions,
|
111
|
+
:major,
|
112
|
+
:minor,
|
113
|
+
:download_policy,
|
114
|
+
:mirroring_policy
|
115
|
+
]
|
116
|
+
|
117
|
+
params = { name: find_unique_name(metadata_repo, product) }
|
118
|
+
params[:gpg_key_id] = gpg_key_id(metadata_repo)
|
119
|
+
keys.each do |key|
|
120
|
+
params[key] = metadata_repo.send(key)
|
121
|
+
end
|
122
|
+
url = fetch_feed_url(metadata_repo)
|
123
|
+
params[:url] = url if url
|
124
|
+
params
|
125
|
+
end
|
126
|
+
|
127
|
+
def fetch_feed_url(metadata_repo)
|
128
|
+
return unless @syncable_format
|
129
|
+
uri = URI(@path)
|
130
|
+
if uri.scheme.blank? || uri.scheme == "file"
|
131
|
+
"file://#{uri.path.chomp('/')}#{metadata_repo.content.url}"
|
132
|
+
else
|
133
|
+
"#{@path.chomp('/')}#{metadata_repo.content.url}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def update_repo_params(metadata_repo)
|
138
|
+
keys = [
|
139
|
+
:description,
|
140
|
+
:arch,
|
141
|
+
:unprotected,
|
142
|
+
:checksum_type,
|
143
|
+
:os_versions,
|
144
|
+
:major,
|
145
|
+
:minor,
|
146
|
+
:download_policy,
|
147
|
+
:mirroring_policy
|
148
|
+
]
|
149
|
+
params = {}
|
150
|
+
url = fetch_feed_url(metadata_repo)
|
151
|
+
params[:url] = url if url
|
152
|
+
params[:gpg_key_id] = gpg_key_id(metadata_repo)
|
153
|
+
|
154
|
+
keys.each do |key|
|
155
|
+
value = metadata_repo.send(key)
|
156
|
+
params[key] = value if value
|
157
|
+
end
|
158
|
+
|
159
|
+
params
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -22,12 +22,7 @@ module Katello
|
|
22
22
|
|
23
23
|
def publication_options(repository_version)
|
24
24
|
options = super(repository_version)
|
25
|
-
options.merge(
|
26
|
-
{
|
27
|
-
metadata_checksum_type: root.checksum_type,
|
28
|
-
package_checksum_type: root.checksum_type
|
29
|
-
}
|
30
|
-
)
|
25
|
+
options.merge(checksum_type: root.checksum_type)
|
31
26
|
end
|
32
27
|
|
33
28
|
def specific_create_options
|
@@ -17,7 +17,7 @@ module Katello
|
|
17
17
|
:repositories_api_class, :api_class, :remotes_api_class, :repository_versions_api_class,
|
18
18
|
:distributions_api_class, :remote_class, :repo_sync_url_class, :client_module_class,
|
19
19
|
:distribution_class, :publication_class, :publications_api_class, :url_description,
|
20
|
-
:test_url, :test_url_root_options
|
20
|
+
:test_url, :test_url_root_options, :repo_discovery_class
|
21
21
|
|
22
22
|
attr_accessor :metadata_publish_matching_check, :index_additional_data_proc
|
23
23
|
attr_reader :id, :unique_content_per_repo
|
@@ -1,3 +1,5 @@
|
|
1
|
-
|
1
|
+
<% content_for(:javascripts) do %>
|
2
|
+
<%= webpacked_plugins_js_for :katello %>
|
3
|
+
<% end %>
|
2
4
|
<% @smartProxyId= @smart_proxy.id %>
|
3
5
|
<%= react_component('Content', smartProxyId: @smartProxyId, organizationId: Organization.current&.id,) %>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class AddContainerPushPropsToRepo < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
|
+
add_column :katello_root_repositories, :is_container_push, :boolean, default: false
|
4
|
+
add_column :katello_root_repositories, :container_push_name, :string, default: nil
|
5
|
+
add_column :katello_root_repositories, :container_push_name_format, :string, default: nil
|
6
|
+
end
|
7
|
+
end
|
@@ -10,7 +10,12 @@
|
|
10
10
|
angular.module('Bastion.repositories').service('Checksum',
|
11
11
|
['translate', function (translate) {
|
12
12
|
|
13
|
-
this.checksums = [
|
13
|
+
this.checksums = [
|
14
|
+
{name: translate('Default'), id: null},
|
15
|
+
{id: 'sha256', name: 'sha256'},
|
16
|
+
{id: 'sha384', name: 'sha384'},
|
17
|
+
{id: 'sha512', name: 'sha512'}
|
18
|
+
];
|
14
19
|
|
15
20
|
this.checksumType = function (checksum) {
|
16
21
|
if (checksum === null) {
|
@@ -208,6 +208,9 @@
|
|
208
208
|
options="checksums"
|
209
209
|
on-save="save(repository)">
|
210
210
|
</dd>
|
211
|
+
<p ng-hide="repository.checksum_type !== 'sha1'" class="help-block" translate>
|
212
|
+
The sha1 checksum type is no longer supported. The checksum type will reset to 'Default' at the next edit or change in content.
|
213
|
+
</p>
|
211
214
|
</span>
|
212
215
|
|
213
216
|
<span ng-show="repository.content_type === 'yum' && repository.mirroring_policy === 'additive'">
|
@@ -371,9 +371,6 @@
|
|
371
371
|
ng-model="repository.checksum_type"
|
372
372
|
ng-options="type.id as type.name for type in checksums">
|
373
373
|
</select>
|
374
|
-
<p class="help-block" translate>
|
375
|
-
For older operating systems such as Red Hat Enterprise Linux 5 or CentOS 5 it is recommended to use sha1.
|
376
|
-
</p>
|
377
374
|
</div>
|
378
375
|
|
379
376
|
<div class="checkbox" ng-hide="repository.content_type === 'docker' || repository.content_type === 'ansible_collection'">
|
data/lib/katello/plugin.rb
CHANGED
@@ -634,6 +634,12 @@ Foreman::Plugin.register :katello do
|
|
634
634
|
full_name: N_('Orphaned Content Protection Time'),
|
635
635
|
description: N_('Time in minutes before content that is not contained within a repository and has not been accessed is considered orphaned.')
|
636
636
|
|
637
|
+
setting 'completed_pulp_task_protection_days',
|
638
|
+
type: :integer,
|
639
|
+
default: 30,
|
640
|
+
full_name: N_('Completed pulp task protection days'),
|
641
|
+
description: N_('How many days before a completed Pulp task is purged by Orphan Cleanup.')
|
642
|
+
|
637
643
|
setting 'remote_execution_prefer_registered_through_proxy',
|
638
644
|
type: :boolean,
|
639
645
|
default: false,
|
@@ -651,6 +657,12 @@ Foreman::Plugin.register :katello do
|
|
651
657
|
default: true,
|
652
658
|
full_name: N_('Distribute archived content view versions'),
|
653
659
|
description: N_("If this is enabled, repositories of content view versions without environments (\"archived\") will be distributed at '/pulp/content/<organization>/content_views/<content view>/X.Y/...'.")
|
660
|
+
|
661
|
+
setting 'automatic_content_count_updates',
|
662
|
+
type: :boolean,
|
663
|
+
default: true,
|
664
|
+
full_name: N_('Calculate content counts on smart proxies automatically'),
|
665
|
+
description: N_("If this is enabled, content counts on smart proxies will be updated automatically after content sync.")
|
654
666
|
end
|
655
667
|
end
|
656
668
|
|
@@ -2,6 +2,7 @@ Katello::RepositoryTypeManager.register(::Katello::Repository::DOCKER_TYPE) do
|
|
2
2
|
default_managed_content_type Katello::DockerManifest::CONTENT_TYPE
|
3
3
|
pulp3_service_class Katello::Pulp3::Repository::Docker
|
4
4
|
pulp3_api_class Katello::Pulp3::Api::Docker
|
5
|
+
repo_discovery_class ::Katello::Resources::Discovery::Container
|
5
6
|
pulp3_skip_publication true
|
6
7
|
pulp3_plugin 'container'
|
7
8
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
Katello::RepositoryTypeManager.register(::Katello::Repository::YUM_TYPE) do
|
2
2
|
pulp3_service_class Katello::Pulp3::Repository::Yum
|
3
3
|
pulp3_api_class Katello::Pulp3::Api::Yum
|
4
|
+
repo_discovery_class ::Katello::Resources::Discovery::Yum
|
4
5
|
pulp3_plugin 'rpm'
|
5
6
|
prevent_unneeded_metadata_publish
|
6
7
|
|
@@ -0,0 +1,114 @@
|
|
1
|
+
namespace :katello do
|
2
|
+
def commit?
|
3
|
+
ENV['COMMIT'] == 'true' || ENV['FOREMAN_UPGRADE'] == '1'
|
4
|
+
end
|
5
|
+
|
6
|
+
desc "Regnerate metadata for all repositories. Specify CONTENT_VIEW=name and LIFECYCLE_ENVIRONMENT=name to narrow repositories."
|
7
|
+
task :regenerate_repo_metadata => ["dynflow:client", "check_ping"] do
|
8
|
+
User.current = User.anonymous_api_admin
|
9
|
+
repos = lookup_repositories
|
10
|
+
|
11
|
+
if repos.any?
|
12
|
+
task = ForemanTasks.async_task(Actions::Katello::Repository::BulkMetadataGenerate, repos.all.order_by_root(:name))
|
13
|
+
puts "Regenerating #{repos.count} repositories. You can monitor these on task id #{task.id}\n"
|
14
|
+
else
|
15
|
+
puts "No repositories found for regeneration."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Refresh repository metadata for all repositories. Specify CONTENT_VIEW=name and LIFECYCLE_ENVIRONMENT=name to narrow repositories."
|
20
|
+
task :refresh_pulp_repo_details => ["dynflow:client", "check_ping"] do
|
21
|
+
User.current = User.anonymous_api_admin
|
22
|
+
repos = lookup_repositories
|
23
|
+
|
24
|
+
if repos.any?
|
25
|
+
task = ForemanTasks.async_task(::Actions::BulkAction, Actions::Katello::Repository::RefreshRepository, repos.all.order_by_root(:name))
|
26
|
+
puts "Refreshing #{repos.count} repositories. You can monitor these on task id #{task.id}\n"
|
27
|
+
else
|
28
|
+
puts "No repositories found for regeneration."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Correct missing pulp repositories. Specify CONTENT_VIEW=name and LIFECYCLE_ENVIRONMENT=name to narrow repositories. COMMIT=true to perform operation."
|
33
|
+
task :correct_repositories => ["environment", "check_ping"] do
|
34
|
+
puts "All operations will be skipped. Re-run with COMMIT=true to perform corrections." unless commit?
|
35
|
+
|
36
|
+
User.current = User.anonymous_api_admin
|
37
|
+
repos = lookup_repositories
|
38
|
+
|
39
|
+
repos.find_each.with_index do |repo, index|
|
40
|
+
puts "Processing Repository #{index + 1}/#{repos.count}: #{repo.name} (#{repo.id})"
|
41
|
+
unless repo_exists?(repo)
|
42
|
+
handle_missing_repo(repo)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
::Katello::RootRepository.orphaned.each do |root_repo|
|
47
|
+
handle_missing_root_repo(root_repo)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Change the download policy of all repos. Specify DOWNLOAD_POLICY=policy. Options are immediate or on_demand."
|
52
|
+
task :change_download_policy => ["environment", "check_ping"] do
|
53
|
+
policy = ENV['DOWNLOAD_POLICY']
|
54
|
+
unless ::Katello::RootRepository::DOWNLOAD_POLICIES.include?(policy)
|
55
|
+
puts "Invalid download policy specified: '#{policy}'. "
|
56
|
+
puts "Options are immediate or on_demand."
|
57
|
+
next
|
58
|
+
end
|
59
|
+
|
60
|
+
User.current = User.anonymous_api_admin
|
61
|
+
repos = Katello::Repository.yum_type.where(library_instance_id: nil)
|
62
|
+
|
63
|
+
repos.find_each.with_index do |repo, index|
|
64
|
+
puts "Processing Repository #{index + 1}/#{repos.count}: #{repo.name} (#{repo.id})"
|
65
|
+
begin
|
66
|
+
ForemanTasks.sync_task(::Actions::Katello::Repository::Update, repo.root,
|
67
|
+
download_policy: policy)
|
68
|
+
rescue => e
|
69
|
+
puts "Failed to update repository #{repo.name} (#{repo.id}): #{e.message}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def lookup_repositories
|
75
|
+
lifecycle_envs = Katello::KTEnvironment.where(:name => ENV['LIFECYCLE_ENVIRONMENT']) if ENV['LIFECYCLE_ENVIRONMENT']
|
76
|
+
content_views = Katello::ContentView.where(:name => ENV['CONTENT_VIEW']) if ENV['CONTENT_VIEW']
|
77
|
+
|
78
|
+
repos = ::Katello::Repository
|
79
|
+
repos = repos.in_environment(lifecycle_envs) if lifecycle_envs
|
80
|
+
repos = repos.in_content_views(content_views) if content_views
|
81
|
+
repos
|
82
|
+
end
|
83
|
+
|
84
|
+
def repo_exists?(repo)
|
85
|
+
if SmartProxy.pulp_primary!.pulp3_support?(repo)
|
86
|
+
backend_service = repo.backend_service(SmartProxy.pulp_primary!)
|
87
|
+
return false unless backend_service&.repository_reference&.repository_href
|
88
|
+
backend_service.api.repositories_api.read(backend_service.repository_reference.repository_href)
|
89
|
+
else
|
90
|
+
false
|
91
|
+
end
|
92
|
+
true
|
93
|
+
rescue StandardError => e
|
94
|
+
return false if e.code == 404
|
95
|
+
end
|
96
|
+
|
97
|
+
def handle_missing_repo(repo)
|
98
|
+
puts "Repository #{repo.id} Missing"
|
99
|
+
if repo.content_view.default?
|
100
|
+
puts "Recreating #{repo.id}"
|
101
|
+
if commit?
|
102
|
+
ForemanTasks.sync_task(::Actions::Katello::Repository::Create, repo, force_repo_create: true)
|
103
|
+
repo.reload.index_content
|
104
|
+
end
|
105
|
+
else
|
106
|
+
puts "Deleting #{repo.id}"
|
107
|
+
ForemanTasks.sync_task(::Actions::Katello::Repository::Destroy, repo) if commit?
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def handle_missing_root_repo(root_repo)
|
112
|
+
root_repo.destroy! if commit?
|
113
|
+
end
|
114
|
+
end
|
data/lib/katello/version.rb
CHANGED