Module: Katello::Concerns::SmartProxyExtensions

Extended by:
ActiveSupport::Concern
Defined in:
app/models/katello/concerns/smart_proxy_extensions.rb

Overview

rubocop:disable Metrics/ModuleLength

Defined Under Namespace

Modules: Overrides

Constant Summary collapse

PULP3_FEATURE =
"Pulpcore".freeze
PULP_FEATURE =
"Pulp".freeze
PULP_NODE_FEATURE =
"Pulp Node".freeze
CONTAINER_GATEWAY_FEATURE =
"Container_Gateway".freeze
DOWNLOAD_INHERIT =
'inherit'.freeze
DOWNLOAD_STREAMED =
'streamed'.freeze
DOWNLOAD_POLICIES =
[::Katello::RootRepository::DOWNLOAD_ON_DEMAND, ::Katello::RootRepository::DOWNLOAD_IMMEDIATE, DOWNLOAD_INHERIT, DOWNLOAD_STREAMED].freeze

Instance Method Summary collapse

Instance Method Details

#active_sync_tasksObject



598
599
600
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 598

def active_sync_tasks
  sync_tasks.where(:result => 'pending')
end

#add_lifecycle_environment(environment) ⇒ Object



550
551
552
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 550

def add_lifecycle_environment(environment)
  self.lifecycle_environments << environment
end

#alternate_content_sourcesObject



131
132
133
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 131

def alternate_content_sources
  SmartProxy.joins(:smart_proxy_alternate_content_sources).where('katello_smart_proxy_alternate_content_sources.smart_proxy_id' => self.id)
end

#associate_default_locationsObject



519
520
521
522
523
524
525
526
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 519

def associate_default_locations
  return unless self.pulp_primary?
  default_location = ::Location.unscoped.find_by_title(
    ::Setting[:default_location_subscribed_hosts])
  if default_location.present? && !locations.include?(default_location)
    self.locations << default_location
  end
end

#associate_lifecycle_environmentsObject



546
547
548
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 546

def associate_lifecycle_environments
  self.lifecycle_environments = Katello::KTEnvironment.all if self.pulp_primary?
end

#associate_organizationsObject



515
516
517
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 515

def associate_organizations
  self.organizations = Organization.all if self.pulp_primary?
end

#audit_capsule_syncObject



730
731
732
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 730

def audit_capsule_sync
  write_audit(action: "sync capsule", comment: _('Successfully synced capsule.'), audited_changes: {})
end

#available_lifecycle_environments(organization_id = nil) ⇒ Object



576
577
578
579
580
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 576

def available_lifecycle_environments(organization_id = nil)
  scope = Katello::KTEnvironment.not_in_capsule(self)
  scope = scope.where(organization_id: organization_id) if organization_id
  scope
end

#build_repo_list(repositories) ⇒ Object



346
347
348
349
350
351
352
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 346

def build_repo_list(repositories)
  unauthenticated_repositories = unauthenticated_container_repositories
  repositories.filter_map do |repo|
    next if repo.container_repository_name.nil? || unauthenticated_repositories.include?(repo.id)
    { repository: repo.container_repository_name, auth_required: true }
  end
end

#cancel_syncObject



643
644
645
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 643

def cancel_sync
  active_sync_tasks.map(&:cancel)
end

#container_gateway_usersObject



358
359
360
361
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 358

def container_gateway_users
  usernames = ProxyAPI::ContainerGateway.new(url: self.url).users
  ::User.where(login: usernames['users'])
end

#content_service(content_type) ⇒ Object



528
529
530
531
532
533
534
535
536
537
538
539
540
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 528

def content_service(content_type)
  if content_type.is_a?(String)
    content_type_obj = RepositoryTypeManager.find_content_type(content_type)
  else
    content_type_obj = content_type
  end
  content_type_string = content_type_obj&.label || content_type
  unless content_type_obj
    fail _("Content type %{content_type_string} does not belong to an enabled repo type.") %
           { content_type_string: content_type_string }
  end
  content_type_obj.pulp3_service_class
end

#current_repositories_data(environment = nil, content_view = nil) ⇒ Object



676
677
678
679
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 676

def current_repositories_data(environment = nil, content_view = nil)
  return repos_in_sync_history unless (environment || content_view)
  repos_in_sync_history & repos_in_env_cv(environment, content_view)
end

#environment_syncable?(env) ⇒ Boolean

Returns:

  • (Boolean)


622
623
624
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 622

def environment_syncable?(env)
  last_sync_time.nil? || env.content_view_environments.where('updated_at > ?', last_sync_time).any?
end

#fix_pulp3_capabilities(type) ⇒ Object



441
442
443
444
445
446
447
448
449
450
451
452
453
454
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 441

def fix_pulp3_capabilities(type)
  if type.is_a?(String) || type.is_a?(Symbol)
    repository_type_obj = Katello::RepositoryTypeManager.defined_repository_types[type]
  else
    repository_type_obj = type
  end

  if missing_pulp3_capabilities? && repository_type_obj.pulp3_plugin
    self.refresh
    if self.capabilities(::SmartProxy::PULP3_FEATURE).empty?
      fail Katello::Errors::PulpcoreMissingCapabilities
    end
  end
end

#global_content_countsObject



235
236
237
238
239
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 235

def global_content_counts
  smart_proxy_helper = ::Katello::SmartProxyHelper.new(self)
  repos = smart_proxy_helper.repositories_available_to_capsule
  repos_content_count(repos, reset: true)
end

#initialize_content_counts(reset: false) ⇒ Object



187
188
189
190
191
192
193
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 187

def initialize_content_counts(reset: false)
  if reset || content_counts.empty?
    { content_view_versions: {} }.with_indifferent_access
  else
    content_counts.deep_dup.with_indifferent_access
  end
end

#last_complete_sync_taskObject



582
583
584
585
586
587
588
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 582

def last_complete_sync_task
  ForemanTasks::Task.for_resource(self).where(:label => 'Actions::Katello::CapsuleContent::Sync').order(started_at: :desc).detect do |task|
    task.input.with_indifferent_access.dig(:options, :environment_id).nil? &&
    task.input.with_indifferent_access.dig(:options, :content_view_id).nil? &&
    task.input.with_indifferent_access.dig(:options, :repository_id).nil?
  end
end

#last_env_sync_task(env) ⇒ Object



626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 626

def last_env_sync_task(env)
  last_env_sync_task = sync_tasks.order(ended_at: :desc).detect { |task| task.input.with_indifferent_access.dig(:options, :environment_id) == env.id || task.input.with_indifferent_access.dig(:options, :environment_ids)&.include?(env.id) }

  # env_ids_task_exists checks if any full syncs have run since we started tracking env_ids at time of sync.
  # If yes, return last_env_sync_task which checks for env_id specific sync + full syncs which contain env as part of env_ids
  env_ids_task_exists = sync_tasks.order(ended_at: :desc).any? { |task| task.input.with_indifferent_access.dig(:options, :environment_ids) }
  return last_env_sync_task if env_ids_task_exists

  if (last_complete_sync_task&.ended_at && last_env_sync_task&.ended_at)
    return last_complete_sync_task.ended_at > last_env_sync_task.ended_at ? last_complete_sync_task : last_env_sync_task
  elsif last_env_sync_task
    return last_env_sync_task
  elsif last_complete_sync_task
    return last_complete_sync_task
  end
end

#last_failed_reclaim_tasksObject



602
603
604
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 602

def last_failed_reclaim_tasks
  reclaim_space_tasks.where('started_at > ?', last_sync_time).where.not(:result => 'pending')
end

#last_failed_sync_tasksObject



606
607
608
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 606

def last_failed_sync_tasks
  sync_tasks.where('started_at > ?', last_sync_time).where.not(:result => 'pending')
end

#last_sync_auditObject



610
611
612
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 610

def last_sync_audit
  Audited::Audit.where(:auditable_id => self, :auditable_type => SmartProxy.name, action: "sync capsule").order(:created_at).last
end

#last_sync_taskObject



614
615
616
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 614

def last_sync_task
  sync_tasks.where.not(:ended_at => nil).where(:result => 'success').order(:ended_at).last
end

#last_sync_timeObject



618
619
620
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 618

def last_sync_time
  last_sync_task&.ended_at || last_sync_audit&.created_at&.to_s
end

#load_balanced?Boolean

Returns:

  • (Boolean)


153
154
155
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 153

def load_balanced?
  URI.parse(self.url).host != self.registration_host
end

#load_balancer_pulp_content_urlObject



726
727
728
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 726

def load_balancer_pulp_content_url
  URI::HTTPS.build(host: registration_url.host, path: pulp_content_url.path)
end

#missing_pulp3_capabilities?Boolean

Returns:

  • (Boolean)


437
438
439
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 437

def missing_pulp3_capabilities?
  pulp3_enabled? && self.capabilities(PULP3_FEATURE).empty?
end

#ping_pulpObject



647
648
649
650
651
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 647

def ping_pulp
  ::Katello::Ping.pulp_without_auth(self.pulp_url)
rescue Errno::EHOSTUNREACH, Errno::ECONNREFUSED, RestClient::Exception => error
  raise ::Katello::Errors::CapsuleCannotBeReached, _("%s is unreachable. %s" % [self.name, error])
end

#ping_pulp3Object



653
654
655
656
657
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 653

def ping_pulp3
  ::Katello::Ping.pulp3_without_auth(self.pulp3_url)
rescue Errno::EHOSTUNREACH, Errno::ECONNREFUSED, RestClient::Exception => error
  raise ::Katello::Errors::CapsuleCannotBeReached, _("%s is unreachable. %s" % [self.name, error])
end

#process_repository(repo, content_counts) ⇒ Object



195
196
197
198
199
200
201
202
203
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 195

def process_repository(repo, content_counts)
  repo_mirror_service = repo.backend_service(self).with_mirror_adapter
  repo_content_counts = repo_mirror_service.latest_content_counts
  translated_counts = translate_counts(repo, repo_mirror_service, repo_content_counts)
  if content_counts[:content_view_versions][repo.content_view_version_id.to_s].empty?
    content_counts[:content_view_versions][repo.content_view_version_id.to_s] = { repositories: {}}.with_indifferent_access
  end
  content_counts[:content_view_versions][repo.content_view_version_id.to_s][:repositories][repo.id.to_s] = translated_counts
end

#pulp3_configuration(config_class) ⇒ Object



372
373
374
375
376
377
378
379
380
381
382
383
384
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 372

def pulp3_configuration(config_class)
  config_class.new do |config|
    uri = pulp3_uri!
    config.host = uri.host
    config.scheme = uri.scheme
    pulp3_ssl_configuration(config)
    config.debugging = ::Foreman::Logging.logger('katello/pulp_rest').debug?
    config.timeout = SETTINGS[:katello][:rest_client_timeout]
    config.logger = ::Foreman::Logging.logger('katello/pulp_rest')
    config.username = self.setting(PULP3_FEATURE, 'username')
    config.password = self.setting(PULP3_FEATURE, 'password')
  end
end

#pulp3_content_support?(content_type) ⇒ Boolean

Returns:

  • (Boolean)


466
467
468
469
470
471
472
473
474
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 466

def pulp3_content_support?(content_type)
  content_type_obj = content_type.is_a?(String) ? Katello::RepositoryTypeManager.find_content_type(content_type) : content_type
  content_type_string = content_type_obj&.label || content_type
  fail "Content type #{content_type_string} does not belong to an enabled repo type." unless content_type_obj

  found_type = Katello::RepositoryTypeManager.enabled_repository_types.values.find { |repo_type| repo_type.content_types.include?(content_type_obj) }
  fail "Cannot find repository type for content_type #{content_type}, is it enabled?" unless found_type
  pulp3_repository_type_support?(found_type)
end

#pulp3_enabled?Boolean

Returns:

  • (Boolean)


429
430
431
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 429

def pulp3_enabled?
  self.has_feature? PULP3_FEATURE
end

#pulp3_host!Object



482
483
484
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 482

def pulp3_host!
  pulp3_uri!.host
end

#pulp3_repository_type_support?(repository_type) ⇒ Boolean

Returns:

  • (Boolean)


456
457
458
459
460
461
462
463
464
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 456

def pulp3_repository_type_support?(repository_type)
  repository_type_obj = repository_type.is_a?(String) ? Katello::RepositoryTypeManager.find(repository_type) : repository_type
  fail "Cannot find repository type #{repository_type}, is it enabled?" unless repository_type_obj

  repository_type_obj.pulp3_plugin.present? &&
    pulp3_enabled? &&
    (self.capabilities(PULP3_FEATURE).try(:include?, repository_type_obj.pulp3_plugin) ||
      self.capabilities(PULP3_FEATURE).try(:include?, 'pulp_' + repository_type_obj.pulp3_plugin))
end

#pulp3_ssl_configuration(config, connection_adapter = Faraday.default_adapter) ⇒ Object



386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 386

def pulp3_ssl_configuration(config, connection_adapter = Faraday.default_adapter)
  config.ssl_ca_file = ::Cert::Certs.backend_ca_cert_file(:pulp)
  case connection_adapter
  when :excon
    config.ssl_client_cert = ::Cert::Certs.ssl_client_cert_filename
    config.ssl_client_key = ::Cert::Certs.ssl_client_key_filename
  when :net_http
    config.ssl_client_cert = ::Cert::Certs.ssl_client_cert
    config.ssl_client_key = ::Cert::Certs.ssl_client_key
  else
    fail "Unexpected connection_adapter #{connection_adapter}!  Cannot continue, this is likely a bug."
  end
end

#pulp3_support?(repository) ⇒ Boolean

Returns:

  • (Boolean)


433
434
435
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 433

def pulp3_support?(repository)
  repository ? pulp3_repository_type_support?(repository.try(:content_type)) : false
end

#pulp3_uri!Object



476
477
478
479
480
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 476

def pulp3_uri!
  url = self.setting(PULP3_FEATURE, 'pulp_url')
  fail "Cannot determine pulp3 url, check smart proxy configuration" unless url
  URI.parse(url)
end

#pulp3_url(path = '/pulp/api/v3') ⇒ Object



486
487
488
489
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 486

def pulp3_url(path = '/pulp/api/v3')
  pulp_url = self.setting(PULP3_FEATURE, 'pulp_url')
  path.blank? ? pulp_url : "#{pulp_url.sub(%r|/$|, '')}/#{path.sub(%r|^/|, '')}"
end

#pulp_apiObject Also known as: pulp_node



368
369
370
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 368

def pulp_api
  @pulp_api ||= Katello::Pulp::Server.config(pulp_url, User.remote_user)
end

#pulp_content_urlObject



722
723
724
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 722

def pulp_content_url
  URI(setting(SmartProxy::PULP3_FEATURE, 'content_app_url'))
end

#pulp_disk_usageObject



400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 400

def pulp_disk_usage
  if pulp3_enabled?
    storage = ping_pulp3['storage']
    if storage.nil?
      [
        {
          description: 'Pulp Storage (no detailed information available)',
          total: -1,
          used: -1,
          free: -1,
          percentage: -1,
          label: 'cloud-storage',
        }.with_indifferent_access,
      ]
    else
      [
        {
          description: 'Pulp Storage (/var/lib/pulp by default)',
          total: storage['total'],
          used: storage['used'],
          free: storage['free'],
          percentage: (storage['used'] / storage['total'].to_f * 100).to_i,
          label: 'pulp_dir',
        }.with_indifferent_access,
      ]
    end
  end
end

#pulp_mirror?Boolean

Returns:

  • (Boolean)


491
492
493
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 491

def pulp_mirror?
  self.has_feature?(PULP_NODE_FEATURE) || self.setting(SmartProxy::PULP3_FEATURE, 'mirror')
end

#pulp_primary?Boolean Also known as: default_capsule?

Returns:

  • (Boolean)


495
496
497
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 495

def pulp_primary?
  self.has_feature?(PULP_FEATURE) || self.setting(SmartProxy::PULP3_FEATURE, 'mirror') == false
end

#pulp_urlObject



363
364
365
366
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 363

def pulp_url
  uri = URI.parse(url)
  "#{uri.scheme}://#{uri.host}/pulp/api/v2/"
end

#reclaim_space_tasksObject



594
595
596
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 594

def reclaim_space_tasks
  ForemanTasks::Task.for_resource(self).where(:label => 'Actions::Pulp3::CapsuleContent::ReclaimSpace')
end

#refresh_smart_proxy_sync_historiesObject



566
567
568
569
570
571
572
573
574
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 566

def refresh_smart_proxy_sync_histories
  smart_proxy_helper = ::Katello::SmartProxyHelper.new(self)
  repos = smart_proxy_helper.repositories_available_to_capsule.select(:id)
  if repos.size == 0
    self.smart_proxy_sync_histories.delete_all
  else
    self.smart_proxy_sync_histories.where.not(repository_id: repos).delete_all
  end
end

#registration_hostObject



149
150
151
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 149

def registration_host
  registration_url.host
end

#registration_urlObject



144
145
146
147
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 144

def registration_url
  url = self.setting('Registration', 'registration_url').presence || self.url
  URI(url)
end

#remove_lifecycle_environment(environment) ⇒ Object



554
555
556
557
558
559
560
561
562
563
564
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 554

def remove_lifecycle_environment(environment)
  smart_proxy_helper = ::Katello::SmartProxyHelper.new(self)
  repos = smart_proxy_helper.repositories_available_to_capsule(environment)
  smart_proxy_helper.clear_smart_proxy_sync_histories(repos) unless repos.empty?
  self.lifecycle_environments.find(environment.id)
  unless self.lifecycle_environments.destroy(environment)
    fail _("Could not remove the lifecycle environment from the smart proxy")
  end
rescue ActiveRecord::RecordNotFound
  raise _("Lifecycle environment was not attached to the smart proxy; therefore, no changes were made.")
end

#remove_unavailable_versions(content_counts) ⇒ Object



228
229
230
231
232
233
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 228

def remove_unavailable_versions(content_counts)
  version_ids_available_to_proxy = Katello::ContentViewVersion.in_environment(lifecycle_environments)&.pluck(:id)&.uniq
  version_ids_in_count_map = content_counts[:content_view_versions].keys&.map(&:to_i)
  version_ids_to_remove = version_ids_in_count_map - version_ids_available_to_proxy
  version_ids_to_remove.each { |id| content_counts[:content_view_versions].delete(id.to_s) }
end

#repos_content_count(repos, reset: false) ⇒ Object

{"5"=>
  {"repositories"=>
    {"20"=>{"counts"=>{"rpm"=>32, "erratum"=>4, "metadata"=>"product_id"=>1, "content_type"=>"yum", "library_instance_id"=>14},
     "21"=>"counts"=>{"file"=>3, "metadata"=>"product_id"=>1, "content_type"=>"file", "library_instance_id"=>15},
     "22"=>"counts"=>{"file"=>3, "metadata"=>"product_id"=>1, "content_type"=>"file", "library_instance_id"=>15},
     "23"=>"erratum"=>4, "metadata"=>"product_id"=>1, "content_type"=>"yum", "library_instance_id"=>14}}}}}


178
179
180
181
182
183
184
185
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 178

def repos_content_count(repos, reset: false)
  new_content_counts = initialize_content_counts(reset: reset)
  repos.each do |repo|
    process_repository(repo, new_content_counts)
  end
  remove_unavailable_versions(new_content_counts)
  update(content_counts: new_content_counts)
end

#repos_in_env_cv(environment = nil, content_view = nil) ⇒ Object



665
666
667
668
669
670
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 665

def repos_in_env_cv(environment = nil, content_view = nil)
  repos = Katello::Repository
  repos = repos.in_environment(environment) if environment
  repos = repos.in_content_views([content_view]) if content_view
  repos.respond_to?(:to_a) ? repos : repos.none
end

#repos_in_sync_historyObject



672
673
674
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 672

def repos_in_sync_history
  smart_proxy_sync_histories.map { |sync_history| sync_history.repository }
end

#repos_pending_sync(environment = nil, content_view = nil) ⇒ Object



681
682
683
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 681

def repos_pending_sync(environment = nil, content_view = nil)
  repos_in_env_cv(environment, content_view) - repos_in_sync_history
end

#rhsm_urlObject



693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 693

def rhsm_url
  rhsm_url_setting = setting(SmartProxy::PULP3_FEATURE, 'rhsm_url').presence

  url = if rhsm_url_setting
          URI(rhsm_url_setting)
        else
          # TODO: get this from routes
          uri = URI.parse(Setting[:foreman_url])
          uri.path = '/rhsm'
          uri
        end

  # RHSM requires HTTPS for certificate-based authentication
  unless url.scheme == 'https'
    error_msg = if rhsm_url_setting
                  _("Smart Proxy '%{proxy}' has an 'rhsm_url' setting that must use HTTPS protocol. " \
                    "Current value: '%{url}'. Please update the Smart Proxy's rhsm_url setting.") % { proxy: name, url: url.to_s }
                else
                  _("Smart Proxy '%{proxy}': RHSM URL must use HTTPS protocol. The URL is derived from the 'foreman_url' setting. " \
                    "Current value: '%{url}'. Please update the 'foreman_url' setting to use HTTPS.") % { proxy: name, url: url.to_s }
                end

    Rails.logger.error("RHSM HTTPS validation failed for Smart Proxy '#{name}': #{error_msg}")
    fail Katello::Errors::InvalidConfiguration, error_msg
  end

  url
end

#set_default_download_policyObject



542
543
544
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 542

def set_default_download_policy
  self.download_policy ||= ::Setting[:default_proxy_download_policy] || ::Katello::RootRepository::DOWNLOAD_ON_DEMAND
end

#subscription_facetsObject



135
136
137
138
139
140
141
142
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 135

def subscription_facets
  ::Katello::Host::SubscriptionFacet
    .joins(:host => :content_facet)
    .includes(:host)
    .where('katello_content_facets.content_source_id = ?', id)
    .where.not('katello_subscription_facets.uuid' => nil)
    .distinct
end

#supported_pulp_typesObject



499
500
501
502
503
504
505
506
507
508
509
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 499

def supported_pulp_types
  supported_types = []

  ::Katello::RepositoryTypeManager.enabled_repository_types.keys.each do |type|
    if pulp3_repository_type_support?(type)
      supported_types << type
    end
  end

  supported_types
end

#sync_container_gatewayObject



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 241

def sync_container_gateway
  return unless has_feature?(::SmartProxy::CONTAINER_GATEWAY_FEATURE)

  begin
    update_container_repo_list
  rescue StandardError => e
    Rails.logger.error("Failed to update container repository list for #{name}: #{e.message}")
    Rails.logger.debug(e.backtrace.join("\n"))
  end

  begin
    users = container_gateway_users
    update_user_container_repo_mapping(users) if users.any?
  rescue StandardError => e
    Rails.logger.error("Failed to update user container repository mapping for #{name}: #{e.message}")
    Rails.logger.debug(e.backtrace.join("\n"))
  end

  begin
    facets = subscription_facets
    if facets.exists?
      update_container_gateway_hosts(facets)
      update_host_container_repo_mapping(facets)
    end
  rescue StandardError => e
    Rails.logger.error("Failed to update host container gateway data for #{name}: #{e.message}")
    Rails.logger.debug(e.backtrace.join("\n"))
  end
end

#sync_tasksObject



590
591
592
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 590

def sync_tasks
  ForemanTasks::Task.for_resource(self).where(:label => 'Actions::Katello::CapsuleContent::Sync')
end

#translate_counts(repo, repo_mirror_service, repo_content_counts) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 205

def translate_counts(repo, repo_mirror_service, repo_content_counts)
  translated_counts = {metadata: {}, counts: {}}
  translated_counts[:metadata] = {
    env_id: repo.environment_id,
    library_instance_id: repo.library_instance_or_self.id,
    product_id: repo.product_id,
    content_type: repo.content_type,
  }
  repo_content_counts&.each do |name, count|
    count = count[:count]
    if name == 'rpm.package' && repo.content_counts['srpm'] > 0
      translated_counts[:counts]['srpm'] = repo_mirror_service.count_by_pulpcore_type(::Katello::Pulp3::Srpm)
      translated_counts[:counts]['rpm'] = count - translated_counts[:counts]['srpm']
    elsif name == 'container.manifest' && repo.content_counts['docker_manifest_list'] > 0
      translated_counts[:counts]['docker_manifest_list'] = repo_mirror_service.count_by_pulpcore_type(::Katello::Pulp3::DockerManifestList)
      translated_counts[:counts]['docker_manifest'] = count - translated_counts[:counts]['docker_manifest_list']
    else
      translated_counts[:counts][::Katello::Pulp3::PulpContentUnit.katello_name_from_pulpcore_name(name, repo)] = count
    end
  end
  translated_counts
end

#unauthenticated_container_repositoriesObject



354
355
356
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 354

def unauthenticated_container_repositories
  ::Katello::Repository.joins(:environment).where("#{::Katello::KTEnvironment.table_name}.registry_unauthenticated_pull" => true).select(:id).pluck(:id)
end

#up_to_date?(environment = nil, content_view = nil) ⇒ Boolean

Returns:

  • (Boolean)


685
686
687
688
689
690
691
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 685

def up_to_date?(environment = nil, content_view = nil)
  total_repos = repos_in_env_cv(environment, content_view)&.count
  pending_sync = repos_pending_sync(environment, content_view)&.count
  return true if pending_sync&.zero? && total_repos&.positive?
  return false if total_repos.to_i == pending_sync.to_i
  return 'partial'
end

#update_container_gateway_hosts(facets = nil) ⇒ Object



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 271

def update_container_gateway_hosts(facets = nil)
  facets ||= subscription_facets
  hosts = facets.map do |facet|
    {
      uuid: facet.uuid,
    }
  end
  ProxyAPI::ContainerGateway.new(url: self.url).update_hosts({ hosts: hosts })
rescue StandardError => e
  if e.is_a?(ProxyAPI::ProxyException) && e.wrapped_exception.is_a?(RestClient::NotFound)
    Rails.logger.warn("Capsule #{name} does not support the update_hosts endpoint (likely running an older version). Skipping host updates.")
  else
    Rails.logger.warn("Failed to update hosts for capsule #{name}: #{e.message}")
    Rails.logger.warn(e.backtrace.join("\n"))
  end
end

#update_container_repo_listObject



288
289
290
291
292
293
294
295
296
297
298
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 288

def update_container_repo_list
  # [{ repository: "repoA", auth_required: false }]
  repo_list = []
  ::Katello::SmartProxyHelper.new(self).combined_repos_available_to_capsule.each do |repo|
    if repo.docker? && !repo.container_repository_name.nil?
      repo_list << { repository: repo.container_repository_name,
                     auth_required: !unauthenticated_container_repositories.include?(repo.id) }
    end
  end
  ::ProxyAPI::ContainerGateway.new(url: self.url).repository_list({ repositories: repo_list })
end

#update_content_counts!(environment: nil, content_view: nil, repository: nil) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 157

def update_content_counts!(environment: nil, content_view: nil, repository: nil)
  if environment.nil? && content_view.nil? && repository.nil?
    global_content_counts
  else
    smart_proxy_helper = ::Katello::SmartProxyHelper.new(self)
    repos = repository ? [repository] : smart_proxy_helper.repositories_available_to_capsule(environment, content_view)
    self.with_lock do
      repos_content_count(repos)
    end
  end
end

#update_host_container_repo_mapping(subscription_facets) ⇒ Object



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 322

def update_host_container_repo_mapping(subscription_facets)
  host_repo_map = { hosts: [] }
  subscription_facets.each do |facet|
    repositories = ::Katello::Repository.readable_docker_catalog(facet.host)
    host_repo_map[:hosts] << { facet.uuid => build_repo_list(repositories) }
  end
  ProxyAPI::ContainerGateway.new(url: self.url).host_repository_mapping(host_repo_map)
rescue StandardError => e
  if e.is_a?(ProxyAPI::ProxyException) && e.wrapped_exception.is_a?(RestClient::NotFound)
    Rails.logger.warn("Capsule #{name} does not support the host_repository_mapping endpoint (likely running an older version). Skipping host-repository mapping updates.")
  else
    Rails.logger.warn("Failed to update host-repository mapping for capsule #{name}: #{e.message}")
    Rails.logger.warn(e.backtrace.join("\n"))
  end
end

#update_host_repositories(host) ⇒ Object



338
339
340
341
342
343
344
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 338

def update_host_repositories(host)
  return unless host&.subscription_facet&.uuid
  host_repos = { hosts: [] }
  repositories = ::Katello::Repository.readable_docker_catalog(host)
  host_repos[:hosts] << { host.subscription_facet.uuid => build_repo_list(repositories) }
  ProxyAPI::ContainerGateway.new(url: self.url).update_host_repositories(host_repos)
end

#update_user_container_repo_mapping(users) ⇒ Object



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 300

def update_user_container_repo_mapping(users)
  # Example user-repo mapping:
  # { users:
  #   [
  #     'user a' => [{ repository: 'repo 1', auth_required: true }]
  #   ]
  # }

  user_repo_map = { users: [] }
  users.each do |user|
    inner_repo_list = []
    repositories = ::Katello::Repository.readable_docker_catalog_as(user)
    repositories.each do |repo|
      next if repo.container_repository_name.nil?
      inner_repo_list << { repository: repo.container_repository_name,
                           auth_required: !unauthenticated_container_repositories.include?(repo.id) }
    end
    user_repo_map[:users] << { user. => inner_repo_list }
  end
  ProxyAPI::ContainerGateway.new(url: self.url).user_repository_mapping(user_repo_map)
end

#verify_ueber_certsObject



659
660
661
662
663
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 659

def verify_ueber_certs
  self.organizations.each do |org|
    Cert::Certs.verify_ueber_cert(org)
  end
end