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
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



575
576
577
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 575

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

#add_lifecycle_environment(environment) ⇒ Object



527
528
529
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 527

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

#alternate_content_sourcesObject



105
106
107
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 105

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



496
497
498
499
500
501
502
503
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 496

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



523
524
525
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 523

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

#associate_organizationsObject



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

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

#audit_capsule_syncObject



701
702
703
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 701

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

#available_lifecycle_environments(organization_id = nil) ⇒ Object



553
554
555
556
557
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 553

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



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

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



620
621
622
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 620

def cancel_sync
  active_sync_tasks.map(&:cancel)
end

#container_gateway_users(container_gateway_url: self.url) ⇒ Object



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

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

#content_service(content_type) ⇒ Object



505
506
507
508
509
510
511
512
513
514
515
516
517
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 505

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



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

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)


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

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



422
423
424
425
426
427
428
429
430
431
432
433
434
435
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 422

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



222
223
224
225
226
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 222

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



174
175
176
177
178
179
180
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 174

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



559
560
561
562
563
564
565
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 559

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



603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 603

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



579
580
581
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 579

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

#last_failed_sync_tasksObject



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

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

#last_sync_auditObject



587
588
589
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 587

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



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

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

#last_sync_timeObject



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

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

#load_balanced?Boolean

Returns:

  • (Boolean)


140
141
142
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 140

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

#load_balancer_pulp_content_urlObject



697
698
699
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 697

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)


418
419
420
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 418

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

#ping_pulp3Object



624
625
626
627
628
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 624

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



182
183
184
185
186
187
188
189
190
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 182

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



353
354
355
356
357
358
359
360
361
362
363
364
365
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 353

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)


447
448
449
450
451
452
453
454
455
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 447

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)


410
411
412
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 410

def pulp3_enabled?
  self.has_feature? PULP3_FEATURE
end

#pulp3_host!Object



463
464
465
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 463

def pulp3_host!
  pulp3_uri!.host
end

#pulp3_repository_type_support?(repository_type) ⇒ Boolean

Returns:

  • (Boolean)


437
438
439
440
441
442
443
444
445
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 437

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



367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 367

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)


414
415
416
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 414

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

#pulp3_uri!Object



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

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



467
468
469
470
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 467

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_content_urlObject



693
694
695
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 693

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

#pulp_disk_usageObject



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 381

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)


472
473
474
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 472

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

#pulp_primary?Boolean

Returns:

  • (Boolean)


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

def pulp_primary?
  !pulp_mirror?
end

#reclaim_space_tasksObject



571
572
573
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 571

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

#refresh_smart_proxy_sync_historiesObject



543
544
545
546
547
548
549
550
551
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 543

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



136
137
138
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 136

def registration_host
  registration_url.host
end

#registration_urlObject



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

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

#remove_lifecycle_environment(environment) ⇒ Object



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

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



215
216
217
218
219
220
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 215

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}}}}}



165
166
167
168
169
170
171
172
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 165

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



636
637
638
639
640
641
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 636

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



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

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



652
653
654
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 652

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

#rhsm_urlObject



664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 664

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



519
520
521
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 519

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

#subscription_facetsObject



109
110
111
112
113
114
115
116
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 109

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

#subscription_facets_for_syncObject



118
119
120
121
122
123
124
125
126
127
128
129
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 118

def subscription_facets_for_sync
  if load_balanced?
    sibling_ids = self.class.behind_load_balancer(registration_host).pluck(:id)
    ::Katello::Host::SubscriptionFacet.joins(:host => :content_facet)
      .includes(:host)
      .where('katello_content_facets.content_source_id IN (?)', sibling_ids) # matches host assigned to capsule behind load balancer.
      .where.not('katello_subscription_facets.uuid' => nil)
      .distinct
  else
    subscription_facets
  end
end

#supported_pulp_typesObject



480
481
482
483
484
485
486
487
488
489
490
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 480

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



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 228

def sync_container_gateway
  container_gateway_proxy = self_or_colocated_with_feature(::SmartProxy::CONTAINER_GATEWAY_FEATURE)
  return unless container_gateway_proxy

  cg_url = container_gateway_proxy.url

  begin
    update_container_repo_list(container_gateway_url: cg_url)
  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(container_gateway_url: cg_url)
    update_user_container_repo_mapping(users, container_gateway_url: cg_url) 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_for_sync
    if facets.exists?
      update_container_gateway_hosts(facets, container_gateway_url: cg_url)
      update_host_container_repo_mapping(facets, container_gateway_url: cg_url)
    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



567
568
569
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 567

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



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 192

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



344
345
346
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 344

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)


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

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, container_gateway_url: self.url) ⇒ Object



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 261

def update_container_gateway_hosts(facets = nil, container_gateway_url: self.url)
  facets ||= subscription_facets
  hosts = facets.map do |facet|
    {
      uuid: facet.uuid,
    }
  end
  ProxyAPI::ContainerGateway.new(url: container_gateway_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_list(container_gateway_url: self.url) ⇒ Object



278
279
280
281
282
283
284
285
286
287
288
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 278

def update_container_repo_list(container_gateway_url: self.url)
  # [{ 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: container_gateway_url).repository_list({ repositories: repo_list })
end

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



144
145
146
147
148
149
150
151
152
153
154
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 144

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, container_gateway_url: self.url) ⇒ Object



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 312

def update_host_container_repo_mapping(subscription_facets, container_gateway_url: self.url)
  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: container_gateway_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



328
329
330
331
332
333
334
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 328

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, container_gateway_url: self.url) ⇒ Object



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 290

def update_user_container_repo_mapping(users, container_gateway_url: self.url)
  # 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: container_gateway_url).user_repository_mapping(user_repo_map)
end

#verify_ueber_certsObject



630
631
632
633
634
# File 'app/models/katello/concerns/smart_proxy_extensions.rb', line 630

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