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.

Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +1 -1
  3. data/app/controllers/katello/api/v2/repositories_controller.rb +22 -7
  4. data/app/graphql/types/host_collection.rb +18 -0
  5. data/app/lib/actions/pulp3/abstract_async_task.rb +1 -1
  6. data/app/models/katello/candlepin/repository_mapper.rb +1 -1
  7. data/app/models/katello/concerns/host_managed_extensions.rb +1 -1
  8. data/app/models/katello/glue/provider.rb +1 -1
  9. data/app/models/katello/glue/pulp/repos.rb +2 -0
  10. data/app/models/katello/repository.rb +5 -5
  11. data/app/models/katello/root_repository.rb +27 -1
  12. data/app/services/katello/component_view_presenter.rb +1 -1
  13. data/app/services/katello/organization_creator.rb +11 -4
  14. data/app/services/katello/pulp3/content_view_version/metadata_generator.rb +1 -1
  15. data/app/services/katello/pulp3/repository/yum.rb +2 -0
  16. data/app/services/katello/pulp3/repository.rb +2 -2
  17. data/app/services/katello/pulp3/repository_mirror.rb +1 -0
  18. data/app/services/katello/registration_manager.rb +1 -1
  19. data/app/views/katello/api/v2/repositories/base.json.rabl +1 -0
  20. data/app/views/katello/api/v2/repositories/show.json.rabl +1 -1
  21. data/db/migrate/20211202172358_add_repository_mirroring_policy.rb +26 -0
  22. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +5 -2
  23. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +19 -9
  24. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/mirroring-policy.service.js +30 -0
  25. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +9 -5
  26. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +13 -8
  27. data/lib/katello/plugin.rb +3 -0
  28. data/lib/katello/version.rb +1 -1
  29. data/webpack/components/Content/Details/ContentDetails.js +1 -1
  30. data/webpack/components/Content/Details/__tests__/__snapshots__/ContentDetails.test.js.snap +1 -1
  31. data/webpack/components/Errata/index.js +58 -0
  32. data/webpack/components/RoutedTabs/index.js +2 -1
  33. data/webpack/components/Table/TableWrapper.js +8 -4
  34. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.js +109 -0
  35. data/webpack/components/extensions/HostDetails/Cards/__tests__/errataOverviewCard.test.js +56 -0
  36. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/index.js +1 -0
  37. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab.js +57 -55
  38. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab.scss +2 -7
  39. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.js +38 -38
  40. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.scss +3 -7
  41. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +39 -39
  42. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.scss +3 -3
  43. data/webpack/components/extensions/HostDetails/Tabs/TracesTab.js +58 -56
  44. data/webpack/components/extensions/HostDetails/Tabs/TracesTab.scss +4 -5
  45. data/webpack/containers/Application/config.js +1 -1
  46. data/webpack/containers/Application/overrides.scss +56 -7
  47. data/webpack/global_index.js +3 -0
  48. data/webpack/scenes/Content/ContentPage.js +4 -4
  49. data/webpack/scenes/Content/Details/ContentDetails.js +22 -20
  50. data/webpack/scenes/Content/Details/ContentInfo.js +1 -1
  51. data/webpack/scenes/ContentViews/ContentViewsConstants.js +3 -3
  52. data/webpack/scenes/ContentViews/ContentViewsPage.js +17 -13
  53. data/webpack/scenes/ContentViews/Copy/CopyContentViewForm.js +1 -1
  54. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +1 -1
  55. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewAddModal.js +22 -11
  56. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewBulkAddModal.js +31 -18
  57. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +32 -30
  58. data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +1 -1
  59. data/webpack/scenes/ContentViews/Details/DetailsContainer.js +5 -3
  60. data/webpack/scenes/ContentViews/Details/Filters/Add/CVFilterAddModal.js +3 -0
  61. data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +3 -3
  62. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +5 -5
  63. data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +15 -8
  64. data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +3 -3
  65. data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +3 -3
  66. data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +3 -3
  67. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetailsHeader.js +3 -3
  68. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetails.scss +5 -2
  69. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +26 -25
  70. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +1 -1
  71. data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +1 -1
  72. data/webpack/scenes/ContentViews/components/CVBreadCrumb.js +1 -1
  73. data/webpack/scenes/ContentViews/components/ContentViewsCounter.js +1 -1
  74. data/webpack/scenes/ContentViews/expansions/RelatedContentViewComponentsModal.js +8 -8
  75. metadata +9 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83de032a01e5d20e480d164eb425db853b1eea9a4668eb1aa853bfaa5d6a703a
4
- data.tar.gz: aad3b14f2608df9c71cb039222ced8baf98bc89537c28967fcc1d47ac3ce3c5c
3
+ metadata.gz: 5bebacc5b4b127cfadaeb424ce9f04aa6e2ba132a0d8d959d8456bd393418abf
4
+ data.tar.gz: 473b94c0aec5d6b73a174f334edf1f9079d42c53d16ef0ab60cc939af0e0e4b0
5
5
  SHA512:
6
- metadata.gz: cb93e596697f4639b7b4ba3d512524f9880f63442bdba0b4963f73fe6aa18b61d4565f71f488a7cd99f54c0908cbe74cc59468b987450c5d02c9f8020a521761
7
- data.tar.gz: 9ffa356f5005ab1e2119c119c24837530c23d4d004c1a9c99a3b120fc648f443bf126faae8adff3a5763714ba70d9aa412976f50b6d886e6dc3bd0fb4257dcce
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 mirror on sync."), :required => true
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 mirror on sync."), :required => true
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, _("%s is required", import_attributes.api_param)
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
- 'Please disable \'mirror on sync\' because the upstream repository refers to external resources.'
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
- :mirror_on_sync => true
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
@@ -1,6 +1,6 @@
1
1
  module Katello
2
2
  module Glue::Provider
3
- DISTRIBUTOR_VERSION = 'sat-6.7'.freeze
3
+ DISTRIBUTOR_VERSION = 'sat-6.10'.freeze
4
4
 
5
5
  def self.included(base)
6
6
  base.send :include, InstanceMethods
@@ -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, :mirror_on_sync, :"mirror_on_sync?",
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 mirror_on_sync verify_ssl_on_sync
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(cv, component_content_view) }
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
- @organization.save!
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
- @organization.save!
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),
@@ -78,6 +78,8 @@ module Katello
78
78
 
79
79
  def sync_url_params(sync_options)
80
80
  params = super
81
+ params.delete(:mirror)
82
+ params[:sync_policy] = repo.mirroring_policy
81
83
  params[:optimize] = sync_options[:optimize] if sync_options.key?(:optimize)
82
84
  params
83
85
  end
@@ -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.mirror_on_sync}
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.mirror_on_sync?
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.systems.length >= host_collection.max_hosts
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 :mirror_on_sync, :verify_ssl_on_sync
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.mirror_on_sync === false">
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
- * #requires HttpProxyPolicy
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, 'mirror_on_sync': true, 'verify_ssl_on_sync': true,
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 class="checkbox" ng-hide="repository.content_type === 'ostree'">
276
- <label>
277
- <input id="mirror_on_sync" name="mirror_on_sync" ng-model="repository.mirror_on_sync" type="checkbox"/>
278
- <span translate>Mirror on Sync</span>
279
- </label>
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" translate>
282
- Selecting this option will result in contents that are no longer part of the upstream repository being removed during synchronization.
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.mirror_on_sync === false)">
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">
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "4.3.0.rc4".freeze
2
+ VERSION = "4.3.0".freeze
3
3
  end
@@ -37,7 +37,7 @@ const ContentDetails = (props) => {
37
37
  loadingText={__('Loading')}
38
38
  >
39
39
  <TabContainer id="content-tabs-container" defaultActiveKey={1}>
40
- <Grid bsClass="container-fluid">
40
+ <Grid>
41
41
  <Row>
42
42
  <Col sm={12}>
43
43
  <Nav id="content-nav-container" bsClass="nav nav-tabs">