katello 4.8.0.rc1 → 4.8.0.rc2

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +2 -18
  3. data/app/controllers/katello/api/v2/alternate_content_sources_controller.rb +7 -5
  4. data/app/controllers/katello/api/v2/repositories_controller.rb +3 -18
  5. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +13 -8
  6. data/app/lib/actions/katello/alternate_content_source/create.rb +3 -1
  7. data/app/lib/actions/katello/alternate_content_source/update.rb +3 -1
  8. data/app/lib/actions/pulp3/orchestration/content_view_version/copy_version_units_to_library.rb +1 -1
  9. data/app/lib/actions/pulp3/orchestration/content_view_version/export.rb +11 -11
  10. data/app/lib/actions/pulp3/orchestration/content_view_version/syncable_export.rb +0 -2
  11. data/app/lib/actions/pulp3/repository/reclaim_space.rb +1 -1
  12. data/app/lib/katello/api/v2/error_handling.rb +12 -2
  13. data/app/lib/katello/concerns/base_template_scope_extensions.rb +7 -3
  14. data/app/models/katello/alternate_content_source.rb +54 -4
  15. data/app/models/katello/concerns/host_managed_extensions.rb +14 -0
  16. data/app/models/katello/glue/provider.rb +1 -1
  17. data/app/models/katello/host/content_facet.rb +2 -0
  18. data/app/services/katello/pulp3/content_view_version/export_validation_error.rb +1 -1
  19. data/app/services/katello/pulp3/content_view_version/export_validator.rb +16 -0
  20. data/app/views/foreman/smart_proxies/_content_sync.html.erb +1 -1
  21. data/db/migrate/20230203141353_set_new_acs_verify_ssl_default.rb +5 -0
  22. data/db/seeds.d/111-upgrade_tasks.rb +2 -1
  23. data/lib/katello/tasks/upgrades/4.8/regenerate_imported_repository_metadata.rake +33 -0
  24. data/lib/katello/version.rb +1 -1
  25. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/ChangeHostCVModal.js +10 -72
  26. data/webpack/redux/actions/RedHatRepositories/helpers.js +5 -3
  27. data/webpack/scenes/AlternateContentSources/Details/ACSExpandableDetails.js +6 -5
  28. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditCredentials.js +1 -0
  29. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditDetails.js +3 -2
  30. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditProducts.js +1 -0
  31. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditSmartProxies.js +2 -0
  32. data/webpack/scenes/AlternateContentSources/Details/EditModals/ACSEditURLPaths.js +1 -0
  33. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +1 -0
  34. data/webpack/scenes/ContentViews/components/ContentViewSelect/ContentViewSelectOption.js +87 -0
  35. data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +1 -1
  36. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +153 -28
  37. data/webpack/scenes/Hosts/ChangeContentSource/index.js +14 -15
  38. data/webpack/scenes/Hosts/ChangeContentSource/selectors.js +4 -0
  39. data/webpack/scenes/Hosts/ChangeContentSource/styles.scss +4 -0
  40. metadata +6 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4b8d6a07335f66fa2aa32144b730a13949137d827c6df5d6418d732f3c16ffb
4
- data.tar.gz: 8b38219d487f142d85e53a53f0c839e021b31edfca2b3ba71cd789dee1e1d378
3
+ metadata.gz: 623f96f2d316d946b9a19bbed0bd70a58c56541dfcde05261848efb7f868881d
4
+ data.tar.gz: f39b3c6dca68f3b742f6a09fb5a821ab5e9d11128835023f09a5a8df30a27272
5
5
  SHA512:
6
- metadata.gz: c7a5a28b77b887eafbef71455fa92c9321c031bd986d76b4fa0a70609031aaebea564363463c96b354cbe4efd44c377ee4aa7b564f9b2e4e2a0a099923bff26e
7
- data.tar.gz: 7e951a7f6782c464d0cf07f0a7fbdfcfbe8b273680e89cb49bfff44cc7ee136c4c76268c86f316f7e0a80e109011f23b7bc2a5646ac8f3c7997560d9b803516f
6
+ metadata.gz: 3d4e46aa5cdededbea344d58cc4dd5c43c1fcdd480e5a62594a1bf0892ff80c048e07a3a7460646b2778502849cc58d7ab6f8f22aaeb1ce3fd0ea8aa59f844c7
7
+ data.tar.gz: 97fa1540ab108458032dc4a4963b9644af0a6c7207079bf2c3ef2cc895cacab6521eec73e4ed4aadc2eaf8428fc3b2d5b7bec489a03f02a2d972310344b7c07f
@@ -161,25 +161,9 @@ module Katello
161
161
  end
162
162
 
163
163
  if (manifest_response = redirect_client { Resources::Registry::Proxy.get(@_request.fullpath, headers) })
164
- #for some requests, we get a redirect, but for others we get the actual manifest in response
165
- results = JSON.parse(manifest_response)
166
164
  response.header['Docker-Content-Digest'] = manifest_response.headers[:docker_content_digest]
167
- # https://docs.docker.com/registry/spec/manifest-v2-2/
168
- # If its v2 schema 2 only the mediaType attribute will be present in the manifest
169
- media_type = results['mediaType']
170
- if media_type.blank?
171
- # so mediaType is not schema2 v2 only set the mediaType based on
172
- # https://docs.docker.com/registry/spec/manifest-v2-1/
173
- media_type = if results["signatures"].blank?
174
- 'application/vnd.docker.distribution.manifest.v1+json'
175
- else
176
- 'application/vnd.docker.distribution.manifest.v1+prettyjws'
177
- end
178
- end
179
- response.headers['Content-Type'] = media_type
180
- length = manifest_response.try(:body).try(:size)
181
- length ||= 0
182
- response.header['Content-Length'] = "#{length}"
165
+ response.headers['Content-Type'] = manifest_response.headers[:content_type]
166
+ response.header['Content-Length'] = manifest_response.headers[:content_length]
183
167
  render json: manifest_response
184
168
  end
185
169
  end
@@ -70,7 +70,6 @@ module Katello
70
70
  param_group :acs
71
71
  def create
72
72
  @alternate_content_source = ::Katello::AlternateContentSource.new(acs_params.except(:smart_proxy_ids, :smart_proxy_names, :product_ids))
73
- @alternate_content_source.verify_ssl = nil if @alternate_content_source.simplified?
74
73
  sync_task(::Actions::Katello::AlternateContentSource::Create, @alternate_content_source, @smart_proxies, @products)
75
74
  @alternate_content_source.reload
76
75
  respond_for_create(resource: @alternate_content_source)
@@ -88,7 +87,6 @@ module Katello
88
87
  else
89
88
  find_smart_proxies
90
89
  end
91
-
92
90
  if params[:product_ids].nil?
93
91
  @products = @alternate_content_source.products
94
92
  elsif params[:product_ids] == []
@@ -96,6 +94,7 @@ module Katello
96
94
  else
97
95
  find_products
98
96
  end
97
+
99
98
  sync_task(::Actions::Katello::AlternateContentSource::Update, @alternate_content_source, @smart_proxies, @products, acs_params.except(:smart_proxy_ids, :smart_proxy_names, :product_ids))
100
99
  respond_for_show(:resource => @alternate_content_source)
101
100
  end
@@ -117,9 +116,12 @@ module Katello
117
116
  protected
118
117
 
119
118
  def acs_params
120
- keys = [:name, :label, :description, {smart_proxy_ids: []}, {smart_proxy_names: []}, :content_type, :alternate_content_source_type, :use_http_proxies]
121
- keys += [:base_url, {subpaths: []}, :upstream_username, :upstream_password, :ssl_ca_cert_id, :ssl_client_cert_id, :ssl_client_key_id, :verify_ssl] if params[:action] == 'create' || @alternate_content_source&.custom? || @alternate_content_source&.rhui?
122
- keys += [{product_ids: []}] if params[:action] == 'create' || @alternate_content_source&.simplified?
119
+ keys = [
120
+ :name, :label, :description, {smart_proxy_ids: []}, {smart_proxy_names: []}, :content_type,
121
+ :alternate_content_source_type, :use_http_proxies, :base_url, {subpaths: []}, :upstream_username,
122
+ :upstream_password, :ssl_ca_cert_id, :ssl_client_cert_id, :ssl_client_key_id, :verify_ssl, {product_ids: []}
123
+ ]
124
+
123
125
  params.require(:alternate_content_source).permit(*keys).to_h.with_indifferent_access
124
126
  end
125
127
 
@@ -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 + [:mirror_on_sync] + generic_repo_wrap_params
10
+ repo_wrap_params = RootRepository.attribute_names + generic_repo_wrap_params
11
11
 
12
12
  wrap_parameters :repository, :include => repo_wrap_params
13
13
 
@@ -55,7 +55,6 @@ module Katello
55
55
  param :exclude_tags, Array, :desc => N_("Comma-separated list of tags to exclude when syncing a container image repository. Default: any tag ending in \"-source\"")
56
56
  param :download_policy, ["immediate", "on_demand"], :desc => N_("download policy for yum, deb, and docker repos (either 'immediate' or 'on_demand')")
57
57
  param :download_concurrency, :number, :desc => N_("Used to determine download concurrency of the repository in pulp3. Use value less than 20. Defaults to 10")
58
- 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)")
59
58
  param :mirroring_policy, Katello::RootRepository::MIRRORING_POLICIES, :desc => N_("Policy to set for mirroring content. Must be one of %s.") % RootRepository::MIRRORING_POLICIES
60
59
  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")
61
60
  param :upstream_username, String, :desc => N_("Username of the upstream repository user used for authentication")
@@ -580,7 +579,7 @@ module Katello
580
579
 
581
580
  # rubocop:disable Metrics/CyclomaticComplexity
582
581
  def repository_params
583
- keys = [:download_policy, :mirror_on_sync, :mirroring_policy, :sync_policy, :arch, :verify_ssl_on_sync, :upstream_password,
582
+ keys = [:download_policy, :mirroring_policy, :sync_policy, :arch, :verify_ssl_on_sync, :upstream_password,
584
583
  :upstream_username, :download_concurrency, :upstream_authentication_token,
585
584
  {:os_versions => []}, :deb_releases, :deb_components, :deb_architectures, :description,
586
585
  :http_proxy_policy, :http_proxy_id, :retain_package_versions_count, {:ignorable_content => []}
@@ -604,8 +603,7 @@ module Katello
604
603
  keys += [:url, :gpg_key_id, :ssl_ca_cert_id, :ssl_client_cert_id, :ssl_client_key_id, :unprotected, :name,
605
604
  :checksum_type]
606
605
  end
607
- to_return = params.require(:repository).permit(*keys).to_h.with_indifferent_access
608
- handle_mirror_on_sync(to_return)
606
+ params.require(:repository).permit(*keys).to_h.with_indifferent_access
609
607
  end
610
608
 
611
609
  def get_content_credential(repo_params, content_type)
@@ -664,19 +662,6 @@ module Katello
664
662
  end
665
663
  # rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength
666
664
 
667
- def handle_mirror_on_sync(repo_params)
668
- if !repo_params.key?(:mirroring_policy) && repo_params.key?(:mirror_on_sync)
669
- ::Foreman::Deprecation.api_deprecation_warning("mirror_on_sync is deprecated in favor of mirroring_policy. It will be removed in Katello 4.8.")
670
- if ::Foreman::Cast.to_bool(repo_params[:mirror_on_sync])
671
- repo_params[:mirroring_policy] = Katello::RootRepository::MIRRORING_POLICY_CONTENT
672
- else
673
- repo_params[:mirroring_policy] = Katello::RootRepository::MIRRORING_POLICY_ADDITIVE
674
- end
675
- end
676
- repo_params.delete(:mirror_on_sync)
677
- repo_params
678
- end
679
-
680
665
  def error_on_rh_product
681
666
  fail HttpErrors::BadRequest, _("Red Hat products cannot be manipulated.") if @product.redhat?
682
667
  end
@@ -212,10 +212,13 @@ module Katello
212
212
  new_host.content_facet = hostgroup_content_facet(host, param_host)
213
213
  elsif host.content_facet.present?
214
214
  new_host.content_facet = ::Katello::Host::ContentFacet.new(:content_source_id => host.content_source_id)
215
- new_host.content_facet.assign_single_environment(
216
- :lifecycle_environment => host.content_facet.single_lifecycle_environment,
217
- :content_view => host.content_facet.single_content_view
218
- )
215
+ if host.single_content_view_environment?
216
+ # assign new_host the same CVE as host
217
+ new_host.content_facet.assign_single_environment(
218
+ :lifecycle_environment => host.content_facet.single_lifecycle_environment,
219
+ :content_view => host.content_facet.single_content_view
220
+ )
221
+ end
219
222
  end
220
223
  new_host.operatingsystem.kickstart_repos(new_host).map { |repo| OpenStruct.new(repo) }
221
224
  else
@@ -344,10 +347,12 @@ module Katello
344
347
  lifecycle_environment_id, content_view_id = inherited_or_own_facet_attributes(param_host, hostgroup)
345
348
  content_source_id = inherited_or_own_content_source_id(param_host, hostgroup)
346
349
  facet = ::Katello::Host::ContentFacet.new(:content_source_id => content_source_id)
347
- facet.assign_single_environment(
348
- :lifecycle_environment_id => lifecycle_environment_id,
349
- :content_view_id => content_view_id
350
- )
350
+ if content_view_id && lifecycle_environment_id
351
+ facet.assign_single_environment(
352
+ :lifecycle_environment_id => lifecycle_environment_id,
353
+ :content_view_id => content_view_id
354
+ )
355
+ end
351
356
  facet
352
357
  end
353
358
  end
@@ -7,7 +7,9 @@ module Actions
7
7
  def plan(acs, smart_proxies, products = nil)
8
8
  acs.save!
9
9
  action_subject(acs)
10
- acs.products << products if products.present?
10
+ if products.present?
11
+ acs.update!(products: products)
12
+ end
11
13
  smart_proxies = smart_proxies.present? ? smart_proxies.uniq : []
12
14
  concurrence do
13
15
  smart_proxies.each do |smart_proxy|
@@ -19,7 +19,7 @@ module Actions
19
19
  products_to_associate = []
20
20
  products_to_disassociate = []
21
21
 
22
- if acs.simplified?
22
+ if products.present? || acs.products.present?
23
23
  products = products.uniq
24
24
  products_to_associate = products - acs.products
25
25
  products_to_disassociate = acs.products - products
@@ -28,6 +28,8 @@ module Actions
28
28
  acs.audit_updated_products(old_product_ids) unless products_to_associate.empty? && products_to_disassociate.empty?
29
29
  end
30
30
 
31
+ acs.save!
32
+
31
33
  concurrence do
32
34
  create_acss(acs, smart_proxies_to_associate)
33
35
  delete_acss(acs, smart_proxies_to_disassociate)
@@ -13,7 +13,7 @@ module Actions
13
13
  mirror: content_view_version.content_view.generated?)
14
14
  plan_action(Actions::Pulp3::Repository::SaveVersion, repo.library_instance)
15
15
  plan_action(Katello::Repository::IndexContent, id: repo.library_instance_id)
16
- plan_action(Katello::Repository::MetadataGenerate, repo.library_instance, :force => true)
16
+ plan_action(Katello::Repository::MetadataGenerate, repo.library_instance, force_publication: true)
17
17
  end
18
18
  end
19
19
  end
@@ -17,12 +17,23 @@ module Actions
17
17
  param :exported_file_checksum, Hash
18
18
  param :export_path, String
19
19
  end
20
+
20
21
  def plan(content_view_version:, destination_server: nil,
21
22
  chunk_size: nil, from_history: nil,
22
23
  validate_incremental: true,
23
24
  fail_on_missing_content: false,
24
25
  format: ::Katello::Pulp3::ContentViewVersion::Export::IMPORTABLE)
25
26
  smart_proxy = SmartProxy.pulp_primary!
27
+ from_content_view_version = from_history&.content_view_version
28
+ export_service = ::Katello::Pulp3::ContentViewVersion::Export.create(
29
+ smart_proxy: smart_proxy,
30
+ content_view_version: content_view_version,
31
+ destination_server: destination_server,
32
+ from_content_view_version: from_content_view_version,
33
+ format: format)
34
+ export_service.validate!(fail_on_missing_content: fail_on_missing_content,
35
+ validate_incremental: validate_incremental,
36
+ chunk_size: chunk_size)
26
37
 
27
38
  if format == ::Katello::Pulp3::ContentViewVersion::Export::SYNCABLE
28
39
  sequence do
@@ -38,17 +49,6 @@ module Actions
38
49
  end
39
50
 
40
51
  sequence do
41
- from_content_view_version = from_history&.content_view_version
42
- export_service = ::Katello::Pulp3::ContentViewVersion::Export.create(
43
- smart_proxy: smart_proxy,
44
- content_view_version: content_view_version,
45
- destination_server: destination_server,
46
- from_content_view_version: from_content_view_version,
47
- format: format)
48
- export_service.validate!(fail_on_missing_content: fail_on_missing_content,
49
- validate_incremental: validate_incremental,
50
- chunk_size: chunk_size)
51
-
52
52
  action_output = plan_action(::Actions::Pulp3::ContentViewVersion::CreateExporter,
53
53
  content_view_version_id: content_view_version.id,
54
54
  smart_proxy_id: smart_proxy.id,
@@ -18,7 +18,6 @@ module Actions
18
18
 
19
19
  def plan(content_view_version:,
20
20
  smart_proxy:,
21
- fail_on_missing_content: false,
22
21
  destination_server:,
23
22
  from_content_view_version:)
24
23
  format = ::Katello::Pulp3::ContentViewVersion::Export::SYNCABLE
@@ -29,7 +28,6 @@ module Actions
29
28
  from_content_view_version: from_content_view_version,
30
29
  format: format,
31
30
  destination_server: destination_server)
32
- export_service.validate!(fail_on_missing_content: fail_on_missing_content)
33
31
  base_path = export_service.generate_exporter_path
34
32
  export_service.repositories.each do |repository|
35
33
  action_output = plan_action(::Actions::Pulp3::ContentViewVersion::CreateExporter,
@@ -4,7 +4,7 @@ module Actions
4
4
  class ReclaimSpace < Pulp3::AbstractAsyncTask
5
5
  def plan(repo, smart_proxy = SmartProxy.pulp_primary)
6
6
  action_subject(repo)
7
- repository_hrefs = ::Katello::Pulp3::RepositoryReference.default_cv_repository_hrefs([repo], Organization.current || repositories.first.organization)
7
+ repository_hrefs = ::Katello::Pulp3::RepositoryReference.default_cv_repository_hrefs([repo], repo.organization)
8
8
  plan_self(repository_hrefs: repository_hrefs, smart_proxy_id: smart_proxy.id)
9
9
  end
10
10
 
@@ -21,6 +21,7 @@ module Katello
21
21
  rescue_from Errors::UnsupportedActionException, :with => :rescue_from_unsupported_action_exception
22
22
  rescue_from Errors::MaxHostsReachedException, :with => :rescue_from_max_hosts_reached_exception
23
23
  rescue_from Errors::CdnSubstitutionError, :with => :rescue_from_bad_data
24
+ rescue_from Katello::Pulp3::ContentViewVersion::ExportValidationError, :with => :rescue_from_export_validation_error
24
25
  rescue_from Errors::RegistrationError, :with => :rescue_from_bad_data
25
26
  rescue_from ActionController::ParameterMissing, :with => :rescue_from_missing_param
26
27
  rescue_from ::ForemanTasks::Lock::LockConflict, :with => :rescue_from_bad_data
@@ -85,6 +86,10 @@ module Katello
85
86
  respond_for_exception(exception, :status => :conflict, :with_logging => false)
86
87
  end
87
88
 
89
+ def rescue_from_export_validation_error(exception)
90
+ respond_for_exception(exception, :force_json => true, :status => :unprocessable_entity)
91
+ end
92
+
88
93
  def rescue_from_conflict_exception(exception)
89
94
  respond_for_exception(exception, :status => :conflict)
90
95
  end
@@ -122,11 +127,16 @@ module Katello
122
127
  options[:errors] = exception.try(:record).try(:errors) || [exception.message]
123
128
 
124
129
  logger.error pp_exception(exception) if options[:with_logging]
125
-
126
130
  respond_to do |format|
127
131
  #json has to be displayMessage for older RHEL 5.7 subscription managers
128
132
  format.json { render :json => { :displayMessage => options[:display_message], :errors => options[:errors]}, :status => options[:status] }
129
- format.all { render :plain => options[:text], :status => options[:status] }
133
+ format.all do
134
+ if options[:force_json]
135
+ render :json => { :displayMessage => options[:display_message], :errors => options[:errors]}, :status => options[:status]
136
+ else
137
+ render :plain => options[:text], :status => options[:status]
138
+ end
139
+ end
130
140
  end
131
141
  end
132
142
 
@@ -240,14 +240,17 @@ module Katello
240
240
  seen_host_ids &= only_host_ids if only_host_ids
241
241
 
242
242
  # preload errata in one query for this batch
243
- preloaded_errata = Katello::Erratum.where(:errata_id => seen_errata_ids).pluck(:errata_id, :errata_type)
243
+ preloaded_errata = Katello::Erratum.where(:errata_id => seen_errata_ids).pluck(:errata_id, :errata_type, :issued)
244
244
  preloaded_hosts = ::Host.where(:id => seen_host_ids).includes(:reported_data)
245
245
 
246
246
  batch.each do |task|
247
247
  next if skip_task?(task)
248
- next unless only_host_ids.nil? || only_host_ids.include?(task.input['host']['id'].to_i)
248
+ next unless only_host_ids.nil? || only_host_ids.include?(get_task_input(task)['host']['id'].to_i)
249
249
  parse_errata(task).each do |erratum_id|
250
- current_erratum_errata_type = preloaded_errata.find { |k, _| k == erratum_id }.last
250
+ current_erratum = preloaded_errata.find { |k, _| k == erratum_id }
251
+ next if current_erratum.nil?
252
+ current_erratum_errata_type = current_erratum[1]
253
+ current_erratum_issued = current_erratum.last
251
254
 
252
255
  if filter_errata_type != 'all'
253
256
  next unless filter_errata_type == current_erratum_errata_type
@@ -258,6 +261,7 @@ module Katello
258
261
  :hostname => get_task_input(task)['host']['name'],
259
262
  :erratum_id => erratum_id,
260
263
  :erratum_type => current_erratum_errata_type,
264
+ :issued => current_erratum_issued,
261
265
  :status => task.result
262
266
  }
263
267
 
@@ -19,6 +19,9 @@ module Katello
19
19
  belongs_to :ssl_ca_cert, inverse_of: :ssl_ca_alternate_content_sources, class_name: "Katello::ContentCredential"
20
20
  belongs_to :ssl_client_cert, inverse_of: :ssl_client_alternate_content_sources, class_name: "Katello::ContentCredential"
21
21
  belongs_to :ssl_client_key, inverse_of: :ssl_key_alternate_content_sources, class_name: "Katello::ContentCredential"
22
+ # We breakout ssl-* validation into a function to allow for us to set
23
+ # the object name correctly in complex error messages
24
+ validate :validate_ssl_ids
22
25
 
23
26
  has_many :alternate_content_source_products, dependent: :delete_all, inverse_of: :alternate_content_source,
24
27
  class_name: "Katello::AlternateContentSourceProduct"
@@ -29,13 +32,21 @@ module Katello
29
32
  inverse_of: :alternate_content_source
30
33
  has_many :smart_proxies, -> { distinct }, through: :smart_proxy_alternate_content_sources
31
34
 
32
- validates :base_url, :subpaths, :verify_ssl, :upstream_username,
33
- :upstream_password, :ssl_ca_cert, :ssl_client_cert, :ssl_client_key, if: :simplified?, absence: true
35
+ validates :base_url, :subpaths, :upstream_username,
36
+ :upstream_password, if: :simplified?, absence: true
34
37
  validates :base_url, if: -> { custom? || rhui? }, presence: true
35
38
  validates :products, if: -> { custom? || rhui? }, absence: true
36
39
  validates :label, :uniqueness => true
37
40
  validates :name, :uniqueness => true, presence: true
38
- validates :verify_ssl, if: :custom?, exclusion: [nil]
41
+ # verify ssl must be validated this way due to presence: <bool> failing on a value of false
42
+ validates :verify_ssl, if: -> { custom? || rhui? }, inclusion: {
43
+ in: [true, false],
44
+ message: "can't be blank"
45
+ }
46
+ validates :verify_ssl, if: :simplified?, inclusion: {
47
+ in: [nil],
48
+ message: "must be blank"
49
+ }
39
50
  validates :alternate_content_source_type, inclusion: {
40
51
  in: ->(_) { ACS_TYPES },
41
52
  allow_blank: false,
@@ -50,6 +61,7 @@ module Katello
50
61
  in: [::Katello::Repository::YUM_TYPE],
51
62
  message: "'%{value}' is not valid for RHUI ACS"
52
63
  }
64
+ validate :constraint_acs_update, on: :update
53
65
  validates_with Validators::AlternateContentSourcePathValidator, :attributes => [:base_url, :subpaths], :if => :custom?
54
66
 
55
67
  scope :uses_http_proxies, -> { where(use_http_proxies: true) }
@@ -110,8 +122,46 @@ module Katello
110
122
  write_audit(action: 'update', comment: _('Products updated.'), audited_changes: { 'product_ids' => [old_product_ids, product_ids] })
111
123
  end
112
124
 
113
- def self.humanize_class_name
125
+ def self.humanize_class_name(_name = nil)
114
126
  "Alternate Content Sources"
115
127
  end
128
+
129
+ # Disallow static properties from being modified on update
130
+ def constraint_acs_update
131
+ if changes.keys.include? "content_type"
132
+ errors.add(:content_type, "cannot be modified once an ACS is created")
133
+ end
134
+ if changes.keys.include? "alternate_content_source_type"
135
+ errors.add(:alternate_content_source_type, "cannot be modified once an ACS is created")
136
+ end
137
+ end
138
+
139
+ # Validate ssl-* ids which require complex/custom error messages
140
+ def validate_ssl_ids
141
+ # Simplified ACS's should never have ssl-* params populated
142
+ if simplified?
143
+ if changes.keys.include? "ssl_ca_cert_id"
144
+ errors.add(:ssl_ca_cert, "must be blank")
145
+ end
146
+ if changes.keys.include? "ssl_client_cert_id"
147
+ errors.add(:ssl_client_cert, "must be blank")
148
+ end
149
+ if changes.keys.include? "ssl_client_key_id"
150
+ errors.add(:ssl_client_key, "must be blank")
151
+ end
152
+
153
+ # Custom and RHUI ACS's should have valid keys where populated
154
+ else
155
+ if ssl_ca_cert_id.present? && ssl_ca_cert.nil?
156
+ errors.add(:ssl_ca_cert, "with ID '#{ssl_ca_cert_id}' couldn't be found")
157
+ end
158
+ if ssl_client_cert_id.present? && ssl_client_cert.nil?
159
+ errors.add(:ssl_client_cert, "with ID '#{ssl_client_cert_id}' couldn't be found")
160
+ end
161
+ if ssl_client_key_id.present? && ssl_client_key.nil?
162
+ errors.add(:ssl_client_key, "with ID '#{ssl_client_key_id}' couldn't be found")
163
+ end
164
+ end
165
+ end
116
166
  end
117
167
  end
@@ -6,6 +6,20 @@ module Katello
6
6
  include ForemanTasks::Concerns::ActionSubject
7
7
 
8
8
  module Overrides
9
+ def update(attrs)
10
+ if attrs[:content_facet_attributes]
11
+ cv_id = attrs[:content_facet_attributes].delete(:content_view_id)
12
+ lce_id = attrs[:content_facet_attributes].delete(:lifecycle_environment_id)
13
+ if cv_id && lce_id
14
+ content_facet.assign_single_environment(content_view_id: cv_id, lifecycle_environment_id: lce_id)
15
+ end
16
+ if (cv_id.present? && lce_id.blank?) || (cv_id.blank? && lce_id.present?)
17
+ fail "content_view_id and lifecycle_environment_id must be provided together"
18
+ end
19
+ end
20
+ super
21
+ end
22
+
9
23
  def validate_media?
10
24
  (content_source_id.blank? || (content_facet && content_facet.kickstart_repository.blank?)) && super
11
25
  end
@@ -12,7 +12,7 @@ module Katello
12
12
  if product_provider.redhat_provider?
13
13
  false
14
14
  else
15
- Rails.logger.warn "Found orphaned object with id #{cp_id} in Candlepin. Skipping import into Katello; run rake katello:delete_orphaned_custom_products to remove it from Candlepin."
15
+ Rails.logger.warn "Found orphaned object with id #{cp_id} in Candlepin. Skipping import into Katello; run rake katello:clean_candlepin_orphaned_products to remove it from Candlepin."
16
16
  true
17
17
  end
18
18
  end
@@ -65,10 +65,12 @@ module Katello
65
65
  end
66
66
 
67
67
  def multi_content_view_environment?
68
+ # returns false if there are no content view environments
68
69
  content_view_environments.size > 1
69
70
  end
70
71
 
71
72
  def single_content_view_environment?
73
+ # also returns false if there are no content view environments
72
74
  content_view_environments.size == 1
73
75
  end
74
76
 
@@ -1,7 +1,7 @@
1
1
  module Katello
2
2
  module Pulp3
3
3
  module ContentViewVersion
4
- class ExportValidationError < HttpErrors::BadRequest; end
4
+ class ExportValidationError < StandardError; end
5
5
  end
6
6
  end
7
7
  end
@@ -13,12 +13,28 @@ module Katello
13
13
  end
14
14
 
15
15
  def validate!
16
+ validate_has_repos!
16
17
  validate_repositories_immediate! if @fail_on_missing_content
17
18
  validate_incremental_export! if @validate_incremental && !from_content_view_version.blank?
18
19
  validate_chunk_size
19
20
  validate_export_types! if @fail_on_missing_content
20
21
  end
21
22
 
23
+ def validate_has_repos!
24
+ repos = repositories(fetch_all: true).where(id: ::Katello::Repository.exportable(format: format))
25
+ if repos.empty?
26
+ fail ExportValidationError,
27
+ _("NOTE: Content view version '%{content_view} %{current}'"\
28
+ " does not have any exportable repositories. At least one repository with"\
29
+ " any of the following types"\
30
+ " is required to be able to export: '%{exportable_types}'." %
31
+ { content_view: content_view_version.content_view.name,
32
+ current: content_view_version.version,
33
+ exportable_types: ::Katello::Repository.exportable_types(format: format).join("', '")
34
+ })
35
+ end
36
+ end
37
+
22
38
  def validate_chunk_size
23
39
  return if @chunk_size.blank?
24
40
 
@@ -19,7 +19,7 @@
19
19
  </div>
20
20
 
21
21
  <br>
22
- <div ng-hide="syncStatus.unsyncable_content_types.length == 0">
22
+ <div ng-hide="syncStatus === undefined || syncStatus.unsyncable_content_types.length == 0">
23
23
  <span translate>
24
24
  Pulp plugin missing for synchronizable content types: <b>{{ syncStatus.unsyncable_content_types.join(", ") }}.</b><br />
25
25
  Repositories containing these content types will not be synced.
@@ -0,0 +1,5 @@
1
+ class SetNewAcsVerifySslDefault < ActiveRecord::Migration[6.1]
2
+ def change
3
+ change_column_default(:katello_alternate_content_sources, :verify_ssl, nil)
4
+ end
5
+ end
@@ -8,6 +8,7 @@ UpgradeTask.define_tasks(:katello) do
8
8
  {:name => 'katello:upgrades:4.1:reupdate_content_import_export_perms'},
9
9
  {:name => 'katello:upgrades:4.2:remove_checksum_values'},
10
10
  {:name => 'katello:upgrades:4.4:publish_import_cvvs'},
11
- {:name => 'katello:upgrades:4.8:fix_incorrect_providers'}
11
+ {:name => 'katello:upgrades:4.8:fix_incorrect_providers'},
12
+ {:name => 'katello:upgrades:4.8:regenerate_imported_repository_metadata'}
12
13
  ]
13
14
  end
@@ -0,0 +1,33 @@
1
+ namespace :katello do
2
+ namespace :upgrades do
3
+ namespace '4.8' do
4
+ desc "Regenerates metadata for library repositories that were imported"
5
+ task :regenerate_imported_repository_metadata => ["dynflow:client", "environment"] do
6
+ User.current = User.anonymous_admin #set a user for orchestration
7
+ versions = Katello::ContentViewVersionImportHistory.all.map(&:content_view_version)
8
+ repos = versions.map do |ver|
9
+ rps = if ver.default?
10
+ ver.repositories
11
+ else
12
+ ver.archived_repos
13
+ end
14
+ rps.exportable
15
+ .map(&:library_instance_or_self)
16
+ .select(&:using_mirrored_metadata?)
17
+ end
18
+ repos.flatten!
19
+ repos.uniq!
20
+
21
+ if repos.any?
22
+ task = ForemanTasks.async_task(::Actions::BulkAction,
23
+ ::Actions::Katello::Repository::MetadataGenerate,
24
+ repos,
25
+ force_publication: true)
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
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "4.8.0.rc1".freeze
2
+ VERSION = "4.8.0.rc2".freeze
3
3
  end