katello 4.3.0.rc4 → 4.3.0
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_view_versions_controller.rb +1 -1
- data/app/controllers/katello/api/v2/repositories_controller.rb +22 -7
- data/app/graphql/types/host_collection.rb +18 -0
- data/app/lib/actions/pulp3/abstract_async_task.rb +1 -1
- data/app/models/katello/candlepin/repository_mapper.rb +1 -1
- data/app/models/katello/concerns/host_managed_extensions.rb +1 -1
- data/app/models/katello/glue/provider.rb +1 -1
- data/app/models/katello/glue/pulp/repos.rb +2 -0
- data/app/models/katello/repository.rb +5 -5
- data/app/models/katello/root_repository.rb +27 -1
- data/app/services/katello/component_view_presenter.rb +1 -1
- data/app/services/katello/organization_creator.rb +11 -4
- data/app/services/katello/pulp3/content_view_version/metadata_generator.rb +1 -1
- data/app/services/katello/pulp3/repository/yum.rb +2 -0
- data/app/services/katello/pulp3/repository.rb +2 -2
- data/app/services/katello/pulp3/repository_mirror.rb +1 -0
- data/app/services/katello/registration_manager.rb +1 -1
- data/app/views/katello/api/v2/repositories/base.json.rabl +1 -0
- data/app/views/katello/api/v2/repositories/show.json.rabl +1 -1
- data/db/migrate/20211202172358_add_repository_mirroring_policy.rb +26 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +5 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +19 -9
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/mirroring-policy.service.js +30 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +9 -5
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +13 -8
- data/lib/katello/plugin.rb +3 -0
- data/lib/katello/version.rb +1 -1
- data/webpack/components/Content/Details/ContentDetails.js +1 -1
- data/webpack/components/Content/Details/__tests__/__snapshots__/ContentDetails.test.js.snap +1 -1
- data/webpack/components/Errata/index.js +58 -0
- data/webpack/components/RoutedTabs/index.js +2 -1
- data/webpack/components/Table/TableWrapper.js +8 -4
- data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.js +109 -0
- data/webpack/components/extensions/HostDetails/Cards/__tests__/errataOverviewCard.test.js +56 -0
- data/webpack/components/extensions/HostDetails/Tabs/ContentTab/index.js +1 -0
- data/webpack/components/extensions/HostDetails/Tabs/ErrataTab.js +57 -55
- data/webpack/components/extensions/HostDetails/Tabs/ErrataTab.scss +2 -7
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.js +38 -38
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.scss +3 -7
- data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +39 -39
- data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.scss +3 -3
- data/webpack/components/extensions/HostDetails/Tabs/TracesTab.js +58 -56
- data/webpack/components/extensions/HostDetails/Tabs/TracesTab.scss +4 -5
- data/webpack/containers/Application/config.js +1 -1
- data/webpack/containers/Application/overrides.scss +56 -7
- data/webpack/global_index.js +3 -0
- data/webpack/scenes/Content/ContentPage.js +4 -4
- data/webpack/scenes/Content/Details/ContentDetails.js +22 -20
- data/webpack/scenes/Content/Details/ContentInfo.js +1 -1
- data/webpack/scenes/ContentViews/ContentViewsConstants.js +3 -3
- data/webpack/scenes/ContentViews/ContentViewsPage.js +17 -13
- data/webpack/scenes/ContentViews/Copy/CopyContentViewForm.js +1 -1
- data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +1 -1
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewAddModal.js +22 -11
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewBulkAddModal.js +31 -18
- data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +32 -30
- data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +1 -1
- data/webpack/scenes/ContentViews/Details/DetailsContainer.js +5 -3
- data/webpack/scenes/ContentViews/Details/Filters/Add/CVFilterAddModal.js +3 -0
- data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +3 -3
- data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +5 -5
- data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +15 -8
- data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +3 -3
- data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +3 -3
- data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +3 -3
- data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetailsHeader.js +3 -3
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetails.scss +5 -2
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +26 -25
- data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +1 -1
- data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +1 -1
- data/webpack/scenes/ContentViews/components/CVBreadCrumb.js +1 -1
- data/webpack/scenes/ContentViews/components/ContentViewsCounter.js +1 -1
- data/webpack/scenes/ContentViews/expansions/RelatedContentViewComponentsModal.js +8 -8
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bebacc5b4b127cfadaeb424ce9f04aa6e2ba132a0d8d959d8456bd393418abf
|
4
|
+
data.tar.gz: 473b94c0aec5d6b73a174f334edf1f9079d42c53d16ef0ab60cc939af0e0e4b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 000e85ae93b95be282c88d10eec6f364526cfdb9e377de7b56d82a8df882e8390c40690b4d7b0740c24196fa10d20d166b48779f3422699e7a970bfb1722cdc2
|
7
|
+
data.tar.gz: 23a1e59f555ddbe334a98d6937aa64de3d46b1bc6b8fb33a61166e317792686fae9f30af480d0037226eebf6d341769a15acd1972d7bb05d20696ab6af1fb9dc
|
@@ -76,7 +76,7 @@ module Katello
|
|
76
76
|
|
77
77
|
api :PUT, "/content_view_versions/:id/republish_repositories", N_("Forces a republish of the version's repositories' metadata")
|
78
78
|
param :id, :number, :desc => N_("Content view version identifier"), :required => true
|
79
|
-
param :force, :bool, :desc => N_("Force metadata regeneration to proceed. Dangerous when repositories use
|
79
|
+
param :force, :bool, :desc => N_("Force metadata regeneration to proceed. Dangerous when repositories use the 'Complete Mirroring' mirroring policy"), :required => true
|
80
80
|
def republish_repositories
|
81
81
|
unless ::Foreman::Cast.to_bool(params[:force])
|
82
82
|
fail HttpErrors::BadRequest, _("Metadata republishing must be forced because it is a dangerous operation.")
|
@@ -7,7 +7,7 @@ module Katello
|
|
7
7
|
generic_repo_wrap_params << option.name
|
8
8
|
end
|
9
9
|
|
10
|
-
repo_wrap_params = RootRepository.attribute_names.concat([:ignore_global_proxy]) + generic_repo_wrap_params
|
10
|
+
repo_wrap_params = RootRepository.attribute_names.concat([:ignore_global_proxy, :mirror_on_sync]) + generic_repo_wrap_params
|
11
11
|
|
12
12
|
wrap_parameters :repository, :include => repo_wrap_params
|
13
13
|
|
@@ -53,7 +53,8 @@ module Katello
|
|
53
53
|
param :docker_tags_whitelist, Array, :desc => N_("Comma-separated list of tags to sync for Container Image repository")
|
54
54
|
param :download_policy, ["immediate", "on_demand"], :desc => N_("download policy for yum repos (either 'immediate' or 'on_demand')")
|
55
55
|
param :download_concurrency, :number, :desc => N_("Used to determine download concurrency of the repository in pulp3. Use value less than 20. Defaults to 10")
|
56
|
-
param :mirror_on_sync, :bool, :desc => N_("true if this repository when synced has to be mirrored from the source and stale rpms removed")
|
56
|
+
param :mirror_on_sync, :bool, :desc => N_("true if this repository when synced has to be mirrored from the source and stale rpms removed (Deprecated)")
|
57
|
+
param :mirroring_policy, Katello::RootRepository::MIRRORING_POLICIES, :desc => N_("Policy to set for mirroring content. Must be one of %s.") % RootRepository::MIRRORING_POLICIES
|
57
58
|
param :verify_ssl_on_sync, :bool, :desc => N_("if true, Katello will verify the upstream url's SSL certifcates are signed by a trusted CA")
|
58
59
|
param :upstream_username, String, :desc => N_("Username of the upstream repository user used for authentication")
|
59
60
|
param :upstream_password, String, :desc => N_("Password of the upstream repository user used for authentication")
|
@@ -268,7 +269,7 @@ module Katello
|
|
268
269
|
|
269
270
|
api :PUT, "/repositories/:id/republish", N_("Forces a republish of the specified repository, regenerating metadata and symlinks on the filesystem.")
|
270
271
|
param :id, :number, :desc => N_("Repository identifier"), :required => true
|
271
|
-
param :force, :bool, :desc => N_("Force metadata regeneration to proceed. Dangerous when repositories use
|
272
|
+
param :force, :bool, :desc => N_("Force metadata regeneration to proceed. Dangerous when repositories use the 'Complete Mirroring' mirroring policy."), :required => true
|
272
273
|
def republish
|
273
274
|
unless ::Foreman::Cast.to_bool(params[:force])
|
274
275
|
fail HttpErrors::BadRequest, _('Metadata republishing must be forced because it is a dangerous operation.')
|
@@ -501,7 +502,7 @@ module Katello
|
|
501
502
|
|
502
503
|
# rubocop:disable Metrics/CyclomaticComplexity
|
503
504
|
def repository_params
|
504
|
-
keys = [:download_policy, :mirror_on_sync, :arch, :verify_ssl_on_sync, :upstream_password,
|
505
|
+
keys = [:download_policy, :mirror_on_sync, :mirroring_policy, :sync_policy, :arch, :verify_ssl_on_sync, :upstream_password,
|
505
506
|
:upstream_username, :download_concurrency, :upstream_authentication_token,
|
506
507
|
{:os_versions => []}, :deb_releases, :deb_components, :deb_architectures, :description,
|
507
508
|
:http_proxy_policy, :http_proxy_id, :retain_package_versions_count, {:ignorable_content => []}
|
@@ -525,7 +526,8 @@ module Katello
|
|
525
526
|
keys += [:url, :gpg_key_id, :ssl_ca_cert_id, :ssl_client_cert_id, :ssl_client_key_id, :unprotected, :name,
|
526
527
|
:checksum_type]
|
527
528
|
end
|
528
|
-
params.require(:repository).permit(*keys).to_h.with_indifferent_access
|
529
|
+
to_return = params.require(:repository).permit(*keys).to_h.with_indifferent_access
|
530
|
+
handle_mirror_on_sync(to_return)
|
529
531
|
end
|
530
532
|
|
531
533
|
def get_content_credential(repo_params, content_type)
|
@@ -545,8 +547,8 @@ module Katello
|
|
545
547
|
:checksum_type, :download_policy, :http_proxy_policy).to_h.with_indifferent_access)
|
546
548
|
root.docker_upstream_name = repo_params[:docker_upstream_name] if repo_params[:docker_upstream_name]
|
547
549
|
root.docker_tags_whitelist = repo_params.fetch(:docker_tags_whitelist, []) if root.docker?
|
548
|
-
root.mirror_on_sync = ::Foreman::Cast.to_bool(repo_params[:mirror_on_sync]) if repo_params.key?(:mirror_on_sync)
|
549
550
|
root.verify_ssl_on_sync = ::Foreman::Cast.to_bool(repo_params[:verify_ssl_on_sync]) if repo_params.key?(:verify_ssl_on_sync)
|
551
|
+
root.mirroring_policy = repo_params[:mirroring_policy] || Katello::RootRepository::MIRRORING_POLICY_CONTENT
|
550
552
|
root.upstream_username = repo_params[:upstream_username] if repo_params.key?(:upstream_username)
|
551
553
|
root.upstream_password = repo_params[:upstream_password] if repo_params.key?(:upstream_password)
|
552
554
|
root.upstream_authentication_token = repo_params[:upstream_authentication_token] if repo_params.key?(:upstream_authentication_token)
|
@@ -577,6 +579,19 @@ module Katello
|
|
577
579
|
end
|
578
580
|
# rubocop:enable Metrics/CyclomaticComplexity
|
579
581
|
|
582
|
+
def handle_mirror_on_sync(repo_params)
|
583
|
+
if !repo_params.key?(:mirroring_policy) && repo_params.key?(:mirror_on_sync)
|
584
|
+
::Foreman::Deprecation.api_deprecation_warning("mirror_on_sync is deprecated in favor of mirroring_policy. It will be removed in Katello 4.6.")
|
585
|
+
if ::Foreman::Cast.to_bool(repo_params[:mirror_on_sync])
|
586
|
+
repo_params[:mirroring_policy] = Katello::RootRepository::MIRRORING_POLICY_CONTENT
|
587
|
+
else
|
588
|
+
repo_params[:mirroring_policy] = Katello::RootRepository::MIRRORING_POLICY_ADDITIVE
|
589
|
+
end
|
590
|
+
end
|
591
|
+
repo_params.delete(:mirror_on_sync)
|
592
|
+
repo_params
|
593
|
+
end
|
594
|
+
|
580
595
|
def error_on_rh_product
|
581
596
|
fail HttpErrors::BadRequest, _("Red Hat products cannot be manipulated.") if @product.redhat?
|
582
597
|
end
|
@@ -652,7 +667,7 @@ module Katello
|
|
652
667
|
def check_import_parameters
|
653
668
|
@repository.repository_type&.import_attributes&.each do |import_attribute|
|
654
669
|
if import_attribute.required && params[import_attribute.api_param].blank?
|
655
|
-
fail HttpErrors::UnprocessableEntity, _(
|
670
|
+
fail HttpErrors::UnprocessableEntity, _('%s is required') % import_attribute.api_param
|
656
671
|
end
|
657
672
|
end
|
658
673
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Types
|
2
|
+
class HostCollection < BaseObject
|
3
|
+
description "A collection of hosts"
|
4
|
+
model_class ::Katello::HostCollection
|
5
|
+
|
6
|
+
global_id_field :id
|
7
|
+
timestamps
|
8
|
+
field :name, String
|
9
|
+
field :description, String
|
10
|
+
field :max_hosts, Integer
|
11
|
+
field :unlimited_hosts, Boolean
|
12
|
+
has_many :hosts, Types::Host
|
13
|
+
|
14
|
+
def self.graphql_definition
|
15
|
+
super.tap { |type| type.instance_variable_set(:@name, 'Katello::HostCollection') }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -113,7 +113,7 @@ module Actions
|
|
113
113
|
def overwrite_pulp_error(message)
|
114
114
|
case message
|
115
115
|
when 'This repository uses features which are incompatible with \'mirror\' sync. Please sync without mirroring enabled.'
|
116
|
-
'
|
116
|
+
'The "Complete Mirroring" mirroring policy is not compatible with this repository. You may want to update it to use "Content Only"'
|
117
117
|
else
|
118
118
|
message
|
119
119
|
end
|
@@ -34,7 +34,7 @@ module Katello
|
|
34
34
|
:content_type => katello_content_type,
|
35
35
|
:unprotected => unprotected?,
|
36
36
|
:download_policy => download_policy,
|
37
|
-
:
|
37
|
+
:mirroring_policy => Katello::RootRepository::MIRRORING_POLICY_COMPLETE
|
38
38
|
)
|
39
39
|
|
40
40
|
Repository.new(:root => root,
|
@@ -109,7 +109,7 @@ module Katello
|
|
109
109
|
self.host_statuses.where(type: ::Katello::HostStatusManager::STATUSES.map(&:name)).each do |status|
|
110
110
|
status.refresh!
|
111
111
|
end
|
112
|
-
refresh_global_status
|
112
|
+
refresh_global_status
|
113
113
|
end
|
114
114
|
|
115
115
|
def queue_refresh_content_host_status
|
@@ -136,6 +136,8 @@ module Katello
|
|
136
136
|
repo_param[:download_policy] = Setting[:default_download_policy]
|
137
137
|
end
|
138
138
|
|
139
|
+
repo_param[:mirroring_policy] = Katello::RootRepository::MIRRORING_POLICY_ADDITIVE if repo_param[:mirroring_policy].blank?
|
140
|
+
|
139
141
|
RootRepository.new(repo_param.merge(:product_id => self.id))
|
140
142
|
end
|
141
143
|
end
|
@@ -173,7 +173,7 @@ module Katello
|
|
173
173
|
delegate :name, :label, :docker_upstream_name, :url, :download_concurrency, :to => :root
|
174
174
|
|
175
175
|
delegate :name, :created_at, :updated_at, :major, :minor, :gpg_key_id, :gpg_key, :arch, :label, :url, :unprotected,
|
176
|
-
:content_type, :product_id, :checksum_type, :docker_upstream_name, :
|
176
|
+
:content_type, :product_id, :checksum_type, :docker_upstream_name, :mirroring_policy,
|
177
177
|
:download_policy, :verify_ssl_on_sync, :"verify_ssl_on_sync?", :upstream_username, :upstream_password,
|
178
178
|
:upstream_authentication_token, :deb_releases,
|
179
179
|
:deb_components, :deb_architectures, :ssl_ca_cert_id, :ssl_ca_cert, :ssl_client_cert, :ssl_client_cert_id,
|
@@ -285,14 +285,14 @@ module Katello
|
|
285
285
|
::Katello::Resources::CDN::CdnResource.ca_file if ::Katello::Resources::CDN::CdnResource.redhat_cdn?(url)
|
286
286
|
end
|
287
287
|
|
288
|
-
def using_mirrored_metadata?
|
289
|
-
self.yum? && self.library_instance? && self.mirror_on_sync
|
290
|
-
end
|
291
|
-
|
292
288
|
def archive?
|
293
289
|
self.environment.nil?
|
294
290
|
end
|
295
291
|
|
292
|
+
def using_mirrored_metadata?
|
293
|
+
self.yum? && self.library_instance? && self.root.mirroring_policy == Katello::RootRepository::MIRRORING_POLICY_COMPLETE
|
294
|
+
end
|
295
|
+
|
296
296
|
def in_default_view?
|
297
297
|
content_view_version&.default_content_view?
|
298
298
|
end
|
@@ -38,6 +38,11 @@ module Katello
|
|
38
38
|
RHEL9 = 'rhel-9'.freeze
|
39
39
|
ALLOWED_OS_VERSIONS = [RHEL6, RHEL7, RHEL8, RHEL9].freeze
|
40
40
|
|
41
|
+
MIRRORING_POLICY_ADDITIVE = 'additive'.freeze
|
42
|
+
MIRRORING_POLICY_CONTENT = 'mirror_content_only'.freeze
|
43
|
+
MIRRORING_POLICY_COMPLETE = 'mirror_complete'.freeze
|
44
|
+
MIRRORING_POLICIES = [MIRRORING_POLICY_ADDITIVE, MIRRORING_POLICY_COMPLETE, MIRRORING_POLICY_CONTENT].freeze
|
45
|
+
|
41
46
|
belongs_to :product, :inverse_of => :root_repositories, :class_name => "Katello::Product"
|
42
47
|
has_one :provider, :through => :product
|
43
48
|
|
@@ -74,6 +79,7 @@ module Katello
|
|
74
79
|
validate :ensure_valid_authentication_token, :if => :yum?
|
75
80
|
validate :ensure_valid_deb_constraints, :if => :deb?
|
76
81
|
validate :ensure_no_checksum_on_demand
|
82
|
+
validate :ensure_valid_mirroring_policy
|
77
83
|
validates :checksum_type, :inclusion => {:in => CHECKSUM_TYPES}, :allow_blank => true
|
78
84
|
validates :product_id, :presence => true
|
79
85
|
validates :content_type, :inclusion => {
|
@@ -107,6 +113,7 @@ module Katello
|
|
107
113
|
}
|
108
114
|
scope :orphaned, -> { where.not(id: Katello::Repository.pluck(:root_id).uniq) }
|
109
115
|
scope :redhat, -> { joins(:provider).merge(Katello::Provider.redhat) }
|
116
|
+
scope :custom, -> { where.not(:id => self.redhat) }
|
110
117
|
delegate :redhat?, :provider, :organization, to: :product
|
111
118
|
delegate :cdn_configuration, to: :organization
|
112
119
|
|
@@ -145,6 +152,21 @@ module Katello
|
|
145
152
|
end
|
146
153
|
end
|
147
154
|
|
155
|
+
def valid_mirroring_policies
|
156
|
+
if self.yum?
|
157
|
+
MIRRORING_POLICIES
|
158
|
+
else
|
159
|
+
[MIRRORING_POLICY_ADDITIVE, MIRRORING_POLICY_CONTENT]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def ensure_valid_mirroring_policy
|
164
|
+
unless valid_mirroring_policies.include?(self.mirroring_policy)
|
165
|
+
errors.add(:mirroring_policy, _("Invalid mirroring policy for repository type %{type}, only %{policies} are valid.") %
|
166
|
+
{:type => self.content_type, :policies => valid_mirroring_policies.join(', ')})
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
148
170
|
def ensure_valid_docker_attributes
|
149
171
|
if (!url.blank? && docker_upstream_name.blank?)
|
150
172
|
errors.add(:docker_upstream_name, N_("cannot be blank when Repository URL is provided."))
|
@@ -325,12 +347,16 @@ module Katello
|
|
325
347
|
(%w(unprotected checksum_type container_repsoitory_name) & previous_changes.keys).any?
|
326
348
|
end
|
327
349
|
|
350
|
+
def using_mirrored_content?
|
351
|
+
self.mirroring_policy != Katello::RootRepository::MIRRORING_POLICY_ADDITIVE
|
352
|
+
end
|
353
|
+
|
328
354
|
def on_demand?
|
329
355
|
self.download_policy == DOWNLOAD_ON_DEMAND
|
330
356
|
end
|
331
357
|
|
332
358
|
def pulp_update_needed?
|
333
|
-
changeable_attributes = %w(url unprotected checksum_type docker_upstream_name download_policy
|
359
|
+
changeable_attributes = %w(url unprotected checksum_type docker_upstream_name download_policy mirroring_policy verify_ssl_on_sync
|
334
360
|
upstream_username upstream_password ignorable_content
|
335
361
|
ssl_ca_cert_id ssl_client_cert_id ssl_client_key_id http_proxy_policy http_proxy_id download_concurrency)
|
336
362
|
changeable_attributes += %w(name container_repository_name docker_tags_whitelist) if docker?
|
@@ -20,7 +20,7 @@ module Katello
|
|
20
20
|
not_added_cvs = views.reject { |component_content_view| Katello::ContentViewComponent.where(composite_content_view_id: composite_cv.id, content_view_id: component_content_view.id).first }
|
21
21
|
not_added_cvs.map { |component_content_view| ComponentViewPresenter.new(composite_cv, nil, Katello::ContentViewComponent.where(composite_content_view_id: composite_cv.id, content_view_id: component_content_view.id, latest: true).new) }
|
22
22
|
else
|
23
|
-
views.map { |component_content_view| ComponentViewPresenter.new(
|
23
|
+
views.map { |component_content_view| ComponentViewPresenter.new(composite_cv, component_content_view) }
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -16,7 +16,7 @@ module Katello
|
|
16
16
|
User.as_anonymous_admin do
|
17
17
|
Organization.not_created_in_katello.each do |org|
|
18
18
|
creator = self.new(org)
|
19
|
-
creator.create!
|
19
|
+
creator.create!(raise_validation_errors: false)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -28,7 +28,9 @@ module Katello
|
|
28
28
|
def seed!
|
29
29
|
ActiveRecord::Base.transaction do
|
30
30
|
@organization.setup_label_from_name
|
31
|
-
|
31
|
+
|
32
|
+
# existing validation errors are not resolvable here, so don't validatate
|
33
|
+
@organization.save(validate: false)
|
32
34
|
|
33
35
|
create_library_environment
|
34
36
|
create_library_view
|
@@ -40,14 +42,19 @@ module Katello
|
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
|
-
def create!
|
45
|
+
def create!(raise_validation_errors: true)
|
44
46
|
ActiveRecord::Base.transaction do
|
45
47
|
seed!
|
46
48
|
|
47
49
|
create_backend_objects!
|
48
50
|
|
49
51
|
@organization.created_in_katello = true
|
50
|
-
|
52
|
+
|
53
|
+
begin
|
54
|
+
@organization.save!
|
55
|
+
rescue => e
|
56
|
+
raise e if raise_validation_errors
|
57
|
+
end
|
51
58
|
end
|
52
59
|
end
|
53
60
|
|
@@ -43,7 +43,7 @@ module Katello
|
|
43
43
|
|
44
44
|
def generate_repository_metadata(repo)
|
45
45
|
repo.slice(:name, :label, :description, :arch, :content_type, :unprotected,
|
46
|
-
:checksum_type, :os_versions, :major, :minor).
|
46
|
+
:checksum_type, :os_versions, :major, :minor, :download_policy, :mirroring_policy).
|
47
47
|
merge(product: generate_product_metadata(repo.product),
|
48
48
|
gpg_key: generate_gpg_metadata(repo.gpg_key),
|
49
49
|
content: generate_content_metadata(repo.content),
|
@@ -252,7 +252,7 @@ module Katello
|
|
252
252
|
end
|
253
253
|
|
254
254
|
def sync_url_params(_sync_options)
|
255
|
-
params = {remote: repo.remote_href, mirror: repo.root.
|
255
|
+
params = {remote: repo.remote_href, mirror: repo.root.mirroring_policy == Katello::RootRepository::MIRRORING_POLICY_CONTENT}
|
256
256
|
params[:skip_types] = skip_types if skip_types
|
257
257
|
params
|
258
258
|
end
|
@@ -505,7 +505,7 @@ module Katello
|
|
505
505
|
end
|
506
506
|
|
507
507
|
def retain_package_versions_count
|
508
|
-
return 0 if root.retain_package_versions_count.nil? || root.
|
508
|
+
return 0 if root.retain_package_versions_count.nil? || root.using_mirrored_content?
|
509
509
|
root.retain_package_versions_count.to_i
|
510
510
|
end
|
511
511
|
end
|
@@ -128,6 +128,7 @@ module Katello
|
|
128
128
|
sync_params = repo_service.sync_url_params(options)
|
129
129
|
sync_params[:remote] = remote_href
|
130
130
|
sync_params[:mirror] = true
|
131
|
+
sync_params.delete(:sync_policy)
|
131
132
|
repository_sync_url_data = api.repository_sync_url_class.new(sync_params)
|
132
133
|
[api.repositories_api.sync(repository_href, repository_sync_url_data)]
|
133
134
|
end
|
@@ -234,7 +234,7 @@ module Katello
|
|
234
234
|
host_collection_ids.each do |host_collection_id|
|
235
235
|
host_collection = ::Katello::HostCollection.find(host_collection_id)
|
236
236
|
if !host_collection.unlimited_hosts && host_collection.max_hosts >= 0 &&
|
237
|
-
host_collection.
|
237
|
+
host_collection.hosts.length >= host_collection.max_hosts
|
238
238
|
fail _("Host collection '%{name}' exceeds maximum usage limit of '%{limit}'") %
|
239
239
|
{:limit => host_collection.max_hosts, :name => host_collection.name}
|
240
240
|
end
|
@@ -6,6 +6,7 @@ attributes :pulp_id => :backend_identifier
|
|
6
6
|
attributes :relative_path, :container_repository_name, :full_path, :library_instance_id
|
7
7
|
attributes :version_href, :remote_href, :publication_href
|
8
8
|
attributes :content_counts
|
9
|
+
attributes :mirroring_policy
|
9
10
|
|
10
11
|
glue(@object.root) do
|
11
12
|
attributes :content_type, :url, :arch, :os_versions, :content_id, :generic_remote_options
|
@@ -8,7 +8,7 @@ glue(@resource.root) do
|
|
8
8
|
attributes :content_type
|
9
9
|
attributes :docker_upstream_name
|
10
10
|
attributes :docker_tags_whitelist
|
11
|
-
attributes :
|
11
|
+
attributes :verify_ssl_on_sync
|
12
12
|
attributes :unprotected, :full_path, :checksum_type
|
13
13
|
attributes :container_repository_name
|
14
14
|
attributes :download_policy
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class AddRepositoryMirroringPolicy < ActiveRecord::Migration[6.0]
|
2
|
+
def up
|
3
|
+
add_column :katello_root_repositories, :mirroring_policy, :string
|
4
|
+
|
5
|
+
#RH repos can handle COMPLETE always, but custom cannot, so lets migrate custom to 'MIRRORING_POLICY_CONTENT'
|
6
|
+
Katello::RootRepository.where(:content_type => 'yum').redhat.where(:mirror_on_sync => true).update_all(:mirroring_policy => ::Katello::RootRepository::MIRRORING_POLICY_COMPLETE)
|
7
|
+
Katello::RootRepository.where(:content_type => 'yum').custom.where(:mirror_on_sync => true).update_all(:mirroring_policy => ::Katello::RootRepository::MIRRORING_POLICY_CONTENT)
|
8
|
+
|
9
|
+
Katello::RootRepository.where.not(:content_type => 'yum').where(:mirror_on_sync => true).update_all(:mirroring_policy => ::Katello::RootRepository::MIRRORING_POLICY_CONTENT)
|
10
|
+
Katello::RootRepository.where(:mirror_on_sync => false).update_all(:mirroring_policy => ::Katello::RootRepository::MIRRORING_POLICY_ADDITIVE)
|
11
|
+
|
12
|
+
change_column :katello_root_repositories, :mirroring_policy, :string, :null => false
|
13
|
+
remove_column :katello_root_repositories, :mirror_on_sync
|
14
|
+
end
|
15
|
+
|
16
|
+
def down
|
17
|
+
add_column :katello_root_repositories, :mirror_on_sync, :boolean, default: true, null: true
|
18
|
+
|
19
|
+
Katello::RootRepository.where(:mirroring_policy => ::Katello::RootRepository::MIRRORING_POLICY_COMPLETE).update_all(:mirror_on_sync => true)
|
20
|
+
Katello::RootRepository.where(:mirroring_policy => ::Katello::RootRepository::MIRRORING_POLICY_CONTENT).update_all(:mirror_on_sync => true)
|
21
|
+
Katello::RootRepository.where(:mirroring_policy => ::Katello::RootRepository::MIRRORING_POLICY_ADDITIVE).update_all(:mirror_on_sync => false)
|
22
|
+
change_column :katello_root_repositories, :mirror_on_sync, :boolean, :null => false, :default => true
|
23
|
+
|
24
|
+
remove_column :katello_root_repositories, :mirroring_policy
|
25
|
+
end
|
26
|
+
end
|
@@ -19,8 +19,8 @@
|
|
19
19
|
* Provides the functionality for the repository details info page.
|
20
20
|
*/
|
21
21
|
angular.module('Bastion.repositories').controller('RepositoryDetailsInfoController',
|
22
|
-
['$scope', '$q', 'translate', 'Notification', 'ContentCredential', 'CurrentOrganization', 'Checksum', 'DownloadPolicy', 'Architecture', 'HttpProxy', 'HttpProxyPolicy', 'OSVersions', 'RepositoryTypesService',
|
23
|
-
function ($scope, $q, translate, Notification, ContentCredential, CurrentOrganization, Checksum, DownloadPolicy, Architecture, HttpProxy, HttpProxyPolicy, OSVersions, RepositoryTypesService) {
|
22
|
+
['$scope', '$q', 'translate', 'Notification', 'ContentCredential', 'CurrentOrganization', 'Checksum', 'DownloadPolicy', 'Architecture', 'HttpProxy', 'HttpProxyPolicy', 'OSVersions', 'RepositoryTypesService', 'MirroringPolicy',
|
23
|
+
function ($scope, $q, translate, Notification, ContentCredential, CurrentOrganization, Checksum, DownloadPolicy, Architecture, HttpProxy, HttpProxyPolicy, OSVersions, RepositoryTypesService, MirroringPolicy) {
|
24
24
|
$scope.organization = CurrentOrganization;
|
25
25
|
|
26
26
|
$scope.progress = {uploading: false};
|
@@ -198,6 +198,7 @@ angular.module('Bastion.repositories').controller('RepositoryDetailsInfoControll
|
|
198
198
|
|
199
199
|
$scope.checksums = Checksum.checksums;
|
200
200
|
$scope.downloadPolicies = DownloadPolicy.downloadPolicies;
|
201
|
+
$scope.mirroringPolicies = MirroringPolicy.mirroringPolicies;
|
201
202
|
|
202
203
|
$scope.checksumTypeDisplay = function (checksum) {
|
203
204
|
return Checksum.checksumType(checksum);
|
@@ -207,6 +208,8 @@ angular.module('Bastion.repositories').controller('RepositoryDetailsInfoControll
|
|
207
208
|
return DownloadPolicy.downloadPolicyName(downloadPolicy);
|
208
209
|
};
|
209
210
|
|
211
|
+
$scope.mirroringPolicyDisplay = MirroringPolicy.mirroringPolicyName;
|
212
|
+
|
210
213
|
$scope.clearUpstreamAuth = function () {
|
211
214
|
$scope.repository['upstream_password'] = null;
|
212
215
|
$scope.repository['upstream_auth_exists'] = false;
|
@@ -194,16 +194,8 @@
|
|
194
194
|
on-save="save(repository)">
|
195
195
|
</dd>
|
196
196
|
</span>
|
197
|
-
<span ng-hide="repository.content_type === 'ostree'">
|
198
|
-
<dt translate>Mirror on Sync</dt>
|
199
|
-
<dd bst-edit-checkbox="repository.mirror_on_sync"
|
200
|
-
formatter="booleanToYesNo"
|
201
|
-
on-save="save(repository)"
|
202
|
-
readonly="denied('edit_products', product)">
|
203
|
-
</dd>
|
204
|
-
</span>
|
205
197
|
|
206
|
-
<span ng-show="repository.content_type === 'yum' && repository.
|
198
|
+
<span ng-show="repository.content_type === 'yum' && repository.mirroring_policy === 'additive'">
|
207
199
|
<dt translate>Retain package versions</dt>
|
208
200
|
<dd bst-edit-number="repository.retain_package_versions_count"
|
209
201
|
on-save="save(repository)"
|
@@ -322,6 +314,24 @@
|
|
322
314
|
on-save="save(repository)">
|
323
315
|
</dd>
|
324
316
|
</span>
|
317
|
+
<span>
|
318
|
+
<dt translate>Mirroring Policy</dt>
|
319
|
+
|
320
|
+
<dd bst-edit-select="mirroringPolicyDisplay(repository.mirroring_policy, repository.content_type)"
|
321
|
+
readonly="denied('edit_products', product)"
|
322
|
+
selector="repository.mirroring_policy"
|
323
|
+
options="mirroringPolicies(repository.content_type)"
|
324
|
+
options-format="id as name for (id, name) in options"
|
325
|
+
on-save="save(repository)">
|
326
|
+
</dd>
|
327
|
+
</span>
|
328
|
+
<span ng-if="repository.content_type == 'docker'">
|
329
|
+
<dt translate>Limit Sync Tags</dt>
|
330
|
+
<dd bst-edit-text="repository.commaTagsWhitelist"
|
331
|
+
on-save="save(repository)"
|
332
|
+
readonly="denied('edit_products', product)">
|
333
|
+
</dd>
|
334
|
+
</span>
|
325
335
|
<span ng-if="repository.content_type == 'docker'">
|
326
336
|
<dt translate>Limit Sync Tags</dt>
|
327
337
|
<dd bst-edit-text="repository.commaTagsWhitelist"
|
@@ -0,0 +1,30 @@
|
|
1
|
+
/**
|
2
|
+
* @ngdoc service
|
3
|
+
* @name Bastion.repository.service:mirroringPolicy
|
4
|
+
*
|
5
|
+
* @requires translate
|
6
|
+
*
|
7
|
+
* @description
|
8
|
+
* Provides a mirroringPolicy for repositories
|
9
|
+
*/
|
10
|
+
angular.module('Bastion.repositories').service('MirroringPolicy',
|
11
|
+
['translate', function (translate) {
|
12
|
+
|
13
|
+
this.defaultMirroringPolicy = 'additive';
|
14
|
+
|
15
|
+
this.mirroringPolicies = function(repoType) {
|
16
|
+
var policies = {
|
17
|
+
'additive': translate('Additive'),
|
18
|
+
'mirror_content_only': translate('Content Only')
|
19
|
+
};
|
20
|
+
if (repoType === 'yum') {
|
21
|
+
policies['mirror_complete'] = translate('Complete Mirroring');
|
22
|
+
}
|
23
|
+
return policies;
|
24
|
+
};
|
25
|
+
|
26
|
+
this.mirroringPolicyName = function (policy, repoType) {
|
27
|
+
return this.mirroringPolicies(repoType)[policy];
|
28
|
+
};
|
29
|
+
}]
|
30
|
+
);
|
@@ -17,14 +17,15 @@
|
|
17
17
|
* @requires Architecture
|
18
18
|
* @requires RepositoryTypesService
|
19
19
|
* @requires OSVersions
|
20
|
-
*
|
20
|
+
* @requires HttpProxyPolicy
|
21
|
+
* @requires MirroringPolicy
|
21
22
|
*
|
22
23
|
* @description
|
23
24
|
* Controls the creation of an empty Repository object for use by sub-controllers.
|
24
25
|
*/
|
25
26
|
angular.module('Bastion.repositories').controller('NewRepositoryController',
|
26
|
-
['$scope', '$sce', 'Repository', 'Product', 'ContentCredential', 'FormUtils', 'translate', 'Notification', 'ApiErrorHandler', 'BastionConfig', 'Checksum', 'DownloadPolicy', 'Architecture', 'RepositoryTypesService', 'HttpProxy', 'HttpProxyPolicy', 'OSVersions',
|
27
|
-
function ($scope, $sce, Repository, Product, ContentCredential, FormUtils, translate, Notification, ApiErrorHandler, BastionConfig, Checksum, DownloadPolicy, Architecture, RepositoryTypesService, HttpProxy, HttpProxyPolicy, OSVersions) {
|
27
|
+
['$scope', '$sce', 'Repository', 'Product', 'ContentCredential', 'FormUtils', 'translate', 'Notification', 'ApiErrorHandler', 'BastionConfig', 'Checksum', 'DownloadPolicy', 'Architecture', 'RepositoryTypesService', 'HttpProxy', 'HttpProxyPolicy', 'OSVersions', 'MirroringPolicy',
|
28
|
+
function ($scope, $sce, Repository, Product, ContentCredential, FormUtils, translate, Notification, ApiErrorHandler, BastionConfig, Checksum, DownloadPolicy, Architecture, RepositoryTypesService, HttpProxy, HttpProxyPolicy, OSVersions, MirroringPolicy) {
|
28
29
|
|
29
30
|
function success() {
|
30
31
|
Notification.setSuccessMessage(translate('Repository %s successfully created.').replace('%s', $scope.repository.name));
|
@@ -61,8 +62,9 @@ angular.module('Bastion.repositories').controller('NewRepositoryController',
|
|
61
62
|
};
|
62
63
|
|
63
64
|
$scope.repository = new Repository({'product_id': $scope.$stateParams.productId, unprotected: true,
|
64
|
-
'checksum_type': null, '
|
65
|
-
'download_policy': BastionConfig.defaultDownloadPolicy, 'arch': null
|
65
|
+
'checksum_type': null, 'verify_ssl_on_sync': true,
|
66
|
+
'download_policy': BastionConfig.defaultDownloadPolicy, 'arch': null,
|
67
|
+
'mirroring_policy': MirroringPolicy.defaultMirroringPolicy});
|
66
68
|
|
67
69
|
$scope.product = Product.get({id: $scope.$stateParams.productId}, function () {
|
68
70
|
$scope.page.loading = false;
|
@@ -77,6 +79,8 @@ angular.module('Bastion.repositories').controller('NewRepositoryController',
|
|
77
79
|
$scope.checksums = Checksum.checksums;
|
78
80
|
$scope.downloadPolicies = DownloadPolicy.downloadPolicies;
|
79
81
|
|
82
|
+
$scope.mirroringPolicies = MirroringPolicy.mirroringPolicies;
|
83
|
+
|
80
84
|
$scope.$watch('repository.name', function () {
|
81
85
|
if ($scope.repositoryForm && $scope.repositoryForm.name) {
|
82
86
|
$scope.repositoryForm.name.$setValidity('server', true);
|
@@ -272,18 +272,23 @@
|
|
272
272
|
</p>
|
273
273
|
</div>
|
274
274
|
|
275
|
-
<div
|
276
|
-
<
|
277
|
-
|
278
|
-
|
279
|
-
|
275
|
+
<div bst-form-group label="{{ 'Mirroring Policy' | translate }}">
|
276
|
+
<select id="mirroring_policy"
|
277
|
+
name="mirroring_policy"
|
278
|
+
ng-model="repository.mirroring_policy"
|
279
|
+
ng-options="id as name for (id, name) in mirroringPolicies(repository.content_type)">
|
280
|
+
</select>
|
280
281
|
|
281
|
-
<p class="help-block"
|
282
|
-
|
282
|
+
<p class="help-block">
|
283
|
+
<ul>
|
284
|
+
<li translate><b>Additive:</b> new content available during sync will be added to the repository, and no content will be removed. </li>
|
285
|
+
<li translate><b>Mirror Content Only</b>: any new content available during sync will be added to the repository and any content removed from the upstream repository will be removed from the local repository.</li>
|
286
|
+
<li translate ng-show="repository.content_type == 'yum'"><b>Mirror Complete</b>: a sync behaves exactly like "Mirror Content Only", but also mirrors metadata as well. This is the fastest method, and preserves repository signatures, but is only supported by yum and not by all upstream repositories.</li>
|
287
|
+
</ul>
|
283
288
|
</p>
|
284
289
|
</div>
|
285
290
|
|
286
|
-
<div bst-form-group label="{{ 'Retain package versions' | translate }}" ng-if="(repository.content_type === 'yum' && repository.
|
291
|
+
<div bst-form-group label="{{ 'Retain package versions' | translate }}" ng-if="(repository.content_type === 'yum' && repository.mirroring_policy === 'additive')">
|
287
292
|
<input id="retain_package_versions_count" name="retain_package_versions_count" ng-model="repository.retain_package_versions_count" type="number"/>
|
288
293
|
|
289
294
|
<p class="help-block">
|
data/lib/katello/plugin.rb
CHANGED
@@ -199,6 +199,9 @@ Foreman::Plugin.register :katello do
|
|
199
199
|
|
200
200
|
register_global_js_file 'global'
|
201
201
|
|
202
|
+
register_graphql_query_field :host_collection, '::Types::HostCollection', :record_field
|
203
|
+
register_graphql_query_field :host_collections, '::Types::HostCollection', :collection_field
|
204
|
+
|
202
205
|
search_path_override("Katello") do |resource|
|
203
206
|
"/#{Katello::Util::Model.model_to_controller_path(resource)}/auto_complete_search"
|
204
207
|
end
|
data/lib/katello/version.rb
CHANGED
@@ -37,7 +37,7 @@ const ContentDetails = (props) => {
|
|
37
37
|
loadingText={__('Loading')}
|
38
38
|
>
|
39
39
|
<TabContainer id="content-tabs-container" defaultActiveKey={1}>
|
40
|
-
<Grid
|
40
|
+
<Grid>
|
41
41
|
<Row>
|
42
42
|
<Col sm={12}>
|
43
43
|
<Nav id="content-nav-container" bsClass="nav nav-tabs">
|