Class: Katello::Repository

Inherits:
Model
  • Object
show all
Includes:
ERB::Util, ForemanTasks::Concerns::ActionSubject, Authorization::Repository, Glue, Glue::Candlepin::Repository, ScopedSearchExtensions
Defined in:
app/models/katello/repository.rb

Overview

rubocop:disable Metrics/ClassLength

Defined Under Namespace

Classes: Jail

Constant Summary collapse

PULP_ID_MAX_LENGTH =

pulp uses pulp id to sync with ‘yum_distributor’ on the end

220
AUDIT_SYNC_ACTION =
'sync'.freeze
DEB_TYPE =
'deb'.freeze
YUM_TYPE =
'yum'.freeze
FILE_TYPE =
'file'.freeze
DOCKER_TYPE =
'docker'.freeze
OSTREE_TYPE =
'ostree'.freeze
ANSIBLE_COLLECTION_TYPE =
'ansible_collection'.freeze
GENERIC_TYPE =
'generic'.freeze
EXPORTABLE_TYPES =
[YUM_TYPE, FILE_TYPE, ANSIBLE_COLLECTION_TYPE, DOCKER_TYPE].freeze

Constants included from Glue::Candlepin::Repository

Glue::Candlepin::Repository::CANDLEPIN_DOCKER_TYPE, Glue::Candlepin::Repository::CANDLEPIN_OSTREE_TYPE

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Authorization::Repository

#deletable?, #readable?, #redhat_deletable?

Methods included from Glue

logger

Methods included from Glue::Candlepin::Repository

included

Methods inherited from Model

#destroy!

Class Method Details

.clean_container_name(name) ⇒ Object



884
885
886
# File 'app/models/katello/repository.rb', line 884

def self.clean_container_name(name)
  name.gsub(/[^-\/\w]/, "_").gsub(/_{3,}/, "_").gsub(/-_|^_+|_+$/, "").downcase.strip
end

.errata_with_module_stream_counts(repo) ⇒ Object



368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'app/models/katello/repository.rb', line 368

def self.errata_with_module_stream_counts(repo)
  repository_errata = Katello::RepositoryErratum.table_name
  errata = Katello::Erratum.table_name
  erratum_package = Katello::ErratumPackage.table_name
  repository_module_stream = Katello::RepositoryModuleStream.table_name
  msep = ::Katello::ModuleStreamErratumPackage.table_name
  ::Katello::Erratum.joins(
    "INNER JOIN #{erratum_package} on #{erratum_package}.erratum_id = #{errata}.id",
    "INNER JOIN #{msep} on #{msep}.erratum_package_id = #{erratum_package}.id",
    "INNER JOIN #{repository_errata} on #{repository_errata}.erratum_id = #{errata}.id",
    "INNER JOIN #{repository_module_stream} on #{repository_module_stream}.module_stream_id = #{msep}.module_stream_id").
    where("#{repository_module_stream}.repository_id" => repo.id).
    where("#{repository_errata}.repository_id" => repo.id).
    group("#{errata}.id").count
end

.errata_with_package_counts(repo) ⇒ Object



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

def self.errata_with_package_counts(repo)
  repository_rpm = Katello::RepositoryRpm.table_name
  repository_errata = Katello::RepositoryErratum.table_name
  rpm = Katello::Rpm.table_name
  errata = Katello::Erratum.table_name
  erratum_package = Katello::ErratumPackage.table_name
  ::Katello::Erratum.joins(
    "INNER JOIN #{erratum_package} on #{erratum_package}.erratum_id = #{errata}.id",
    "INNER JOIN #{repository_errata} on #{repository_errata}.erratum_id = #{errata}.id",
    "INNER JOIN #{rpm} on #{rpm}.filename = #{erratum_package}.filename",
    "INNER JOIN #{repository_rpm} on #{repository_rpm}.rpm_id = #{rpm}.id").
    where("#{repository_rpm}.repository_id" => repo.id).
    where("#{repository_errata}.repository_id" => repo.id).
    group("#{errata}.id").count
end

.exportable(format: ::Katello::Pulp3::ContentViewVersion::Export::IMPORTABLE) ⇒ Object



192
193
194
# File 'app/models/katello/repository.rb', line 192

def self.exportable(format: ::Katello::Pulp3::ContentViewVersion::Export::IMPORTABLE)
  with_type(exportable_types(format: format))
end

.exportable_types(format: ::Katello::Pulp3::ContentViewVersion::Export::IMPORTABLE) ⇒ Object



187
188
189
190
# File 'app/models/katello/repository.rb', line 187

def self.exportable_types(format: ::Katello::Pulp3::ContentViewVersion::Export::IMPORTABLE)
  return [YUM_TYPE, FILE_TYPE] if format == ::Katello::Pulp3::ContentViewVersion::Export::SYNCABLE
  EXPORTABLE_TYPES
end

.feed_ca_cert(url) ⇒ Object



286
287
288
289
# File 'app/models/katello/repository.rb', line 286

def self.feed_ca_cert(url)
  file = feed_ca_file(url)
  File.read(file) if file
end

.feed_ca_file(url) ⇒ Object



291
292
293
# File 'app/models/katello/repository.rb', line 291

def self.feed_ca_file(url)
  ::Katello::Resources::CDN::CdnResource.ca_file if ::Katello::Resources::CDN::CdnResource.redhat_cdn?(url)
end

.for_products(products) ⇒ Object



200
201
202
# File 'app/models/katello/repository.rb', line 200

def self.for_products(products)
  joins(:root).where("#{Katello::RootRepository.table_name}.product_id" => products)
end

.import_distributionsObject



714
715
716
717
718
# File 'app/models/katello/repository.rb', line 714

def self.import_distributions
  self.all.each do |repo|
    repo.import_distribution_data
  end
end

.in_content_views(views) ⇒ Object



281
282
283
284
# File 'app/models/katello/repository.rb', line 281

def self.in_content_views(views)
  joins(:content_view_version)
    .where("#{Katello::ContentViewVersion.table_name}.content_view_id" => views.map(&:id))
end

.in_environment(env_id) ⇒ Object



273
274
275
# File 'app/models/katello/repository.rb', line 273

def self.in_environment(env_id)
  where(environment_id: env_id)
end

.in_organization(org) ⇒ Object



269
270
271
# File 'app/models/katello/repository.rb', line 269

def self.in_organization(org)
  where("#{Repository.table_name}.environment_id" => org.kt_environments.pluck("#{KTEnvironment.table_name}.id"))
end

.in_product(prod) ⇒ Object



277
278
279
# File 'app/models/katello/repository.rb', line 277

def self.in_product(prod)
  where(:root_id => RootRepository.where(product_id: prod))
end

.linked_repositoriesObject



829
830
831
832
833
834
835
# File 'app/models/katello/repository.rb', line 829

def self.linked_repositories
  to_return = []
  Katello::Repository.yum_type.in_non_default_view.find_each do |repo|
    to_return << repo if repo.link?
  end
  to_return
end

.safe_render_container_name(repository, pattern = nil) ⇒ Object



862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
# File 'app/models/katello/repository.rb', line 862

def self.safe_render_container_name(repository, pattern = nil)
  if (pattern && !pattern.blank?) || (repository.environment && !repository.environment.registry_name_pattern.empty?)
    pattern ||= repository.environment.registry_name_pattern
    allowed_methods = {}
    allowed_vars = {}
    scope_variables = {repository: repository, organization: repository.organization, product: repository.product,
                       lifecycle_environment: repository.environment, content_view: repository.content_view_version.content_view,
                       content_view_version: repository.content_view_version}
    box = Safemode::Box.new(repository, allowed_methods)
    erb = ERB.new(pattern)
    pattern = box.eval(erb.src, allowed_vars, scope_variables)
    return Repository.clean_container_name(pattern)
  elsif repository.content_view.default?
    items = [repository.organization.label, repository.product.label, repository.label]
  elsif repository.environment
    items = [repository.organization.label, repository.environment.label, repository.content_view.label, repository.product.label, repository.label]
  else
    items = [repository.organization.label, repository.content_view.label, repository.content_view_version.version, repository.product.label, repository.label]
  end
  Repository.clean_container_name(items.compact.join("-"))
end

.search_by_content_label(_key, operator, value) ⇒ Object



851
852
853
854
855
856
857
858
859
860
# File 'app/models/katello/repository.rb', line 851

def self.(_key, operator, value)
  conditions = sanitize_sql_for_conditions(["label #{operator} ?", value_to_sql(operator, value)])
  contents = Katello::Content.where(conditions).pluck(:cp_content_id)
  root_ids = Katello::RootRepository.where(:content_id => contents).pluck(:id)
  if root_ids.empty?
    { :conditions => "1=0" }
  else
    { :conditions => "#{Katello::Repository.table_name}.root_id IN (#{root_ids.join(',')})" }
  end
end

.search_by_redhat(_key, operator, value) ⇒ Object



837
838
839
840
841
842
843
844
845
846
847
848
849
# File 'app/models/katello/repository.rb', line 837

def self.search_by_redhat(_key, operator, value)
  value = value == 'true'
  value = !value if operator == '<>'

  product_ids = Katello::Product.redhat.select(:id)
  root_ids = Katello::RootRepository.where(:product_id => product_ids).pluck(:id)
  if product_ids.empty?
    {:conditions => "1=0"}
  else
    operator = value ? 'IN' : 'NOT IN'
    {:conditions => "#{Katello::Repository.table_name}.root_id #{operator} (#{root_ids.join(',')})"}
  end
end

.smart_proxy_syncableObject



674
675
676
677
678
# File 'app/models/katello/repository.rb', line 674

def self.smart_proxy_syncable
  joins(:content_view_version => :content_view).
    merge(ContentView.ignore_generated).
    where.not(environment_id: nil)
end

.synced_on_capsule(smart_proxy) ⇒ Object



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

def self.synced_on_capsule(smart_proxy)
  smart_proxy.smart_proxy_sync_histories.map { |sph| sph.repository unless sph.finished_at.nil? }
end

.undisplayable_typesObject



265
266
267
# File 'app/models/katello/repository.rb', line 265

def self.undisplayable_types
  [::Katello::Repository::CANDLEPIN_DOCKER_TYPE]
end

.with_errata(errata) ⇒ Object



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

def self.with_errata(errata)
  joins(:repository_errata).where("#{Katello::RepositoryErratum.table_name}.erratum_id" => errata)
end

.with_type(content_type) ⇒ Object



196
197
198
# File 'app/models/katello/repository.rb', line 196

def self.with_type(content_type)
  joins(:root).where("#{RootRepository.table_name}.content_type" => content_type)
end

Instance Method Details

#all_instancesObject



434
435
436
# File 'app/models/katello/repository.rb', line 434

def all_instances
  self.root.repositories
end

#archive?Boolean

Returns:

  • (Boolean)


300
301
302
# File 'app/models/katello/repository.rb', line 300

def archive?
  self.environment.nil?
end

#archived_instanceObject



650
651
652
653
654
655
656
# File 'app/models/katello/repository.rb', line 650

def archived_instance
  if self.environment_id.nil? || self.library_instance_id.nil?
    self
  else
    self.content_view_version.archived_repos.where(:root_id => self.root_id).first
  end
end

#assert_deletableObject



783
784
785
# File 'app/models/katello/repository.rb', line 783

def assert_deletable
  throw :abort unless destroyable?
end

#audit_syncObject



234
235
236
# File 'app/models/katello/repository.rb', line 234

def audit_sync
  write_audit(action: AUDIT_SYNC_ACTION, comment: _('Successfully synchronized.'), audited_changes: {})
end

#backend_content_service(smart_proxy) ⇒ Object



214
215
216
# File 'app/models/katello/repository.rb', line 214

def backend_content_service(smart_proxy)
  backend_service(smart_proxy).content_service
end

#backend_content_unit_service(smart_proxy, content_unit_type) ⇒ Object



218
219
220
# File 'app/models/katello/repository.rb', line 218

def backend_content_unit_service(smart_proxy, content_unit_type)
  backend_service(smart_proxy).content_service(content_unit_type)
end

#backend_service(smart_proxy) ⇒ Object



208
209
210
211
212
# File 'app/models/katello/repository.rb', line 208

def backend_service(smart_proxy)
  fail('Pulp 3 not supported') unless smart_proxy.pulp3_support?(self)

  @service ||= Katello::Pulp3::Repository.instance_for_type(self, smart_proxy)
end

#build_clone(options) ⇒ Object

TODO: break up method



560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
# File 'app/models/katello/repository.rb', line 560

def build_clone(options)
  to_env       = options[:environment]
  version      = options[:version]
  content_view = options[:content_view] || to_env.default_content_view
  to_version   = version || content_view.version(to_env)

  fail _("Cannot clone into the Default Content View") if content_view.default?

  if to_env && version
    fail "Cannot clone into both an environment and a content view version archive"
  end

  if to_version.nil?
    fail _("View %{view} has not been promoted to %{env}") %
              {:view => content_view.name, :env => to_env.name}
  end

  if to_env && self.clones.in_content_views([content_view]).in_environment(to_env).any?
    fail _("Repository has already been cloned to %{cv_name} in environment %{to_env}") %
              {:to_env => to_env, :cv_name => content_view.name}
  end

  if self.yum?
    if self.library_instance?
      checksum_type = root.checksum_type
    else
      checksum_type = self.saved_checksum_type
    end
  end
  clone = Repository.new(:environment => to_env,
                 :library_instance => library_instance_or_self,
                 :root => self.root,
                 :content_view_version => to_version,
                 :saved_checksum_type => checksum_type)

  clone.relative_path = clone.docker? ? clone.generate_docker_repo_path : clone.generate_repo_path
  clone
end

#cancel_dynflow_syncObject



627
628
629
630
631
632
633
634
635
636
637
# File 'app/models/katello/repository.rb', line 627

def cancel_dynflow_sync
  if latest_dynflow_sync
    plan = latest_dynflow_sync.execution_plan

    plan.steps.each_pair do |_number, step|
      if step.cancellable? && step.is_a?(Dynflow::ExecutionPlan::Steps::RunStep)
        ::ForemanTasks.dynflow.world.event(plan.id, step.id, Dynflow::Action::Cancellable::Cancel)
      end
    end
  end
end

#clear_smart_proxy_sync_histories(smart_proxy = nil) ⇒ Object



603
604
605
606
607
608
609
# File 'app/models/katello/repository.rb', line 603

def clear_smart_proxy_sync_histories(smart_proxy = nil)
  if smart_proxy
    self.smart_proxy_sync_histories.where(:smart_proxy_id => smart_proxy.id).try(:delete_all)
  else
    self.smart_proxy_sync_histories.delete_all
  end
end

#cloned_in?(env) ⇒ Boolean

is the repo cloned in the specified environment

Returns:

  • (Boolean)


459
460
461
# File 'app/models/katello/repository.rb', line 459

def cloned_in?(env)
  !get_clone(env).nil?
end

#clonesObject



430
431
432
# File 'app/models/katello/repository.rb', line 430

def clones
  self.root.repositories.where.not(:id => library_instance_id || id)
end

#component_source_repositoriesObject



823
824
825
826
827
# File 'app/models/katello/repository.rb', line 823

def component_source_repositories
  #find other copies of this repositories, in the CV version's components, that are in the 'archive'
  Katello::Repository.where(:content_view_version_id => self.content_view_version.components, :environment_id => nil,
                            :root_id => self.root_id)
end

#content_countsObject



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'app/models/katello/repository.rb', line 331

def content_counts
  content_counts = {}
  RepositoryTypeManager.defined_repository_types[content_type].content_types_to_index.each do |content_type|
    if content_type&.model_class::CONTENT_TYPE == DockerTag::CONTENT_TYPE
      content_counts[DockerTag::CONTENT_TYPE] = docker_tags.count
    elsif content_type&.model_class::CONTENT_TYPE == GenericContentUnit::CONTENT_TYPE
      content_counts[content_type.content_type] = content_type&.model_class&.in_repositories(self)&.where(:content_type => content_type.content_type)&.count
    else
      content_counts[content_type.label] = content_type&.model_class&.in_repositories(self)&.count
    end
  end

  content_counts['module_stream'] = content_counts.delete('modulemd') if content_counts.key?('modulemd')
  content_counts
end

#content_viewObject



257
258
259
# File 'app/models/katello/repository.rb', line 257

def content_view
  self.content_view_version.content_view
end

#content_views_all(include_composite: false) ⇒ Object



763
764
765
766
767
768
769
770
# File 'app/models/katello/repository.rb', line 763

def content_views_all(include_composite: false)
  if include_composite
    cv_ids = library_instances_inverse&.joins(:content_view_version)&.map { |cvv| cvv&.content_view&.id }
    return ContentView.where(id: cv_ids.uniq)
  else
    return self.content_views
  end
end

#copy_indexed_data(source_repository) ⇒ Object



905
906
907
908
909
910
# File 'app/models/katello/repository.rb', line 905

def copy_indexed_data(source_repository)
  repository_type.content_types_to_index.each do |type|
    type.model_class.copy_repository_associations(source_repository, self)
    repository_type.index_additional_data_proc&.call(self, source_repository)
  end
end

#create_smart_proxy_sync_history(smart_proxy) ⇒ Object



611
612
613
614
615
616
617
618
619
620
621
# File 'app/models/katello/repository.rb', line 611

def create_smart_proxy_sync_history(smart_proxy)
  clear_smart_proxy_sync_histories(smart_proxy)
  sp_history_args = {
    :smart_proxy_id => smart_proxy.id,
    :repository_id => self.id,
    :started_at => Time.now
  }
  sp_history = ::Katello::SmartProxySyncHistory.create sp_history_args
  sp_history.save!
  sp_history.id
end

#custom_docker_repo_pathObject



897
898
899
900
901
902
903
# File 'app/models/katello/repository.rb', line 897

def custom_docker_repo_path
  if [environment, product, root.label].any?(&:nil?)
    return nil # can't generate valid path
  end
  parts = [environment.organization.label, product.label, root.label]
  parts.map { |x| x.gsub(/[^-\w]/, "_") }.join("-").downcase
end

#custom_repo_pathObject



888
889
890
891
892
893
894
895
# File 'app/models/katello/repository.rb', line 888

def custom_repo_path
  return custom_docker_repo_path if docker?
  if [environment, product, root.label].any?(&:nil?)
    return nil # can't generate valid path
  end
  prefix = [environment.organization.label, environment.label].map { |x| x.gsub(/[^-\w]/, "_") }.join("/")
  prefix + root.custom_content_path
end

#destroyable?(remove_from_content_view_versions = false) ⇒ Boolean

deleteable? is already taken by the authorization mixin

Returns:

  • (Boolean)


745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
# File 'app/models/katello/repository.rb', line 745

def destroyable?(remove_from_content_view_versions = false)
  if self.environment.try(:library?) && self.content_view.default?
    if self.environment.organization.being_deleted?
      return true
    elsif self.custom? && self.deletable?(remove_from_content_view_versions)
      return true
    elsif !self.custom? && self.redhat_deletable?(remove_from_content_view_versions)
      return true
    else
      errors.add(:base, _("Repository cannot be deleted since it has already been included in a published Content View. " \
                          "Please delete all Content View versions containing this repository before attempting to delete it."))

      return false
    end
  end
  return true
end

#distribution_informationObject



734
735
736
737
738
739
740
741
742
# File 'app/models/katello/repository.rb', line 734

def distribution_information
  {
    distribution_version: self.distribution_version,
    distribution_arch: self.distribution_arch,
    distribution_family: self.distribution_family,
    distribution_variant: self.distribution_variant,
    distribution_bootable: self.distribution_bootable
  }
end

#docker_meta_tag_countObject



787
788
789
# File 'app/models/katello/repository.rb', line 787

def docker_meta_tag_count
  DockerMetaTag.in_repositories(self.id).count
end

#dynflow_handled_last_sync?(pulp_task_id) ⇒ Boolean

Returns true if the pulp_task_id was triggered by the last synchronization action for the repository. Dynflow action handles the synchronization by it’s own so no need to synchronize it again in this callback. Since the callbacks are run just after synchronization is finished, it should be enough to check for the last synchronization task.

Returns:

  • (Boolean)


487
488
489
490
491
# File 'app/models/katello/repository.rb', line 487

def dynflow_handled_last_sync?(pulp_task_id)
  task = ForemanTasks::Task::DynflowTask.for_action(::Actions::Katello::Repository::Sync).
      for_resource(self).order(:started_at).last
  return task && task.main_action.pulp_task_id == pulp_task_id
end

#environmental_instances(view) ⇒ Object

returns other instances of this repo with the same library equivalent of repo



646
647
648
# File 'app/models/katello/repository.rb', line 646

def environmental_instances(view)
  self.all_instances.non_archived.in_content_views([view])
end

#errata_filenamesObject



554
555
556
557
# File 'app/models/katello/repository.rb', line 554

def errata_filenames
  Katello::ErratumPackage.joins(:erratum => :repository_errata).
      where("#{RepositoryErratum.table_name}.repository_id" => self.id).pluck("#{Katello::ErratumPackage.table_name}.filename")
end

#exist_for_environment?(environment, content_view, attribute = nil) ⇒ Boolean

Returns:

  • (Boolean)


680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
# File 'app/models/katello/repository.rb', line 680

def exist_for_environment?(environment, content_view, attribute = nil)
  if environment.present? && content_view.in_environment?(environment)
    repos = content_view.version(environment).repos(environment)

    repos.any? do |repo|
      not_self = (repo.id != self.id)
      same_product = (repo.product.id == self.product.id)

      repo_exists = same_product && not_self

      if repo_exists && attribute
        same_attribute = repo.send(attribute) == self.send(attribute)
        repo_exists = same_attribute
      end

      repo_exists
    end
  else
    false
  end
end

#fetch_module_errata_to_filterObject



395
396
397
398
399
400
401
402
403
404
# File 'app/models/katello/repository.rb', line 395

def fetch_module_errata_to_filter
  errata_counts = ::Katello::Repository.errata_with_module_stream_counts(self)
  errata_counts_in_library = ::Katello::Repository.errata_with_module_stream_counts(library_instance)
  if errata_counts_in_library.any?
    errata_counts_in_library.keep_if { |id| errata_counts[id] != errata_counts_in_library[id] }
    errata_counts_in_library.keys
  else
    []
  end
end

#fetch_package_errata_to_keepObject



384
385
386
387
388
389
390
391
392
393
# File 'app/models/katello/repository.rb', line 384

def fetch_package_errata_to_keep
  errata_counts = ::Katello::Repository.errata_with_package_counts(self)
  if errata_counts.any?
    errata_counts_in_library = ::Katello::Repository.errata_with_package_counts(library_instance)
    errata_counts.keep_if { |id| errata_counts[id] == errata_counts_in_library[id] }
    errata_counts.keys
  else
    []
  end
end

#full_path(smart_proxy = nil, force_http = false) ⇒ Object



442
443
444
445
446
447
448
449
450
451
452
# File 'app/models/katello/repository.rb', line 442

def full_path(smart_proxy = nil, force_http = false)
  pulp_uri = URI.parse(smart_proxy ? smart_proxy.url : ::SmartProxy.pulp_primary.url)
  scheme = force_http ? 'http' : 'https'
  if docker?
    "#{pulp_uri.host.downcase}/#{container_repository_name}"
  elsif ansible_collection?
    "#{scheme}://#{pulp_uri.host.downcase}/pulp_ansible/galaxy/#{relative_path}/api/"
  else
    "#{scheme}://#{pulp_uri.host.downcase}/pulp/content/#{relative_path}/"
  end
end

#generate_content_pathObject



493
494
495
496
497
498
499
# File 'app/models/katello/repository.rb', line 493

def generate_content_path
  path = content.content_url
  root.substitutions.each do |key, value|
    path = path.gsub("$#{key}", value) if value
  end
  path
end

#generate_docker_repo_pathObject



517
518
519
520
521
522
523
524
525
526
527
528
529
# File 'app/models/katello/repository.rb', line 517

def generate_docker_repo_path
  org = self.organization.label.downcase
  if self.environment
    cve = ContentViewEnvironment.where(:environment_id => self.environment,
                                       :content_view_id => self.content_view).first
    view = self.content_view.label
    product = self.product.label
    env = cve.label.split('/').first
    "#{org}-#{env.downcase}-#{view}-#{product}-#{self.root.label}"
  else
    "#{org}-#{self.content_view.label}-#{self.content_view_version.version}-#{self.root.product.label}-#{self.root.label}"
  end
end

#generate_repo_path(content_path = nil) ⇒ Object



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

def generate_repo_path(content_path = nil)
  _org, _content, content_path = library_instance_or_self.relative_path.split("/", 3) if content_path.blank?
  content_path = content_path.sub(%r|^/|, '')
  if self.environment
    cve = ContentViewEnvironment.where(:environment_id => self.environment,
                                       :content_view_id => self.content_view).first
    "#{organization.label}/#{cve.label}/#{content_path}"
  else
    "#{organization.label}/#{ContentView::CONTENT_DIR}/#{self.content_view.label}/#{self.content_view_version.version}/#{content_path}"
  end
end

#get_clone(env) ⇒ Object



471
472
473
474
475
476
477
478
479
480
# File 'app/models/katello/repository.rb', line 471

def get_clone(env)
  if self.content_view.default
    # this repo is part of a default content view
    Repository.in_environment(env).clones.
        joins(:content_view_version => :content_view).where("#{Katello::ContentView.table_name}.default" => true).first
  else
    # this repo is part of a content view that was published from a user created view
    self.content_view.get_repo_clone(env, self).first
  end
end

#groupObject



438
439
440
# File 'app/models/katello/repository.rb', line 438

def group
  all_instances
end

#immediate?Boolean

Returns:

  • (Boolean)


316
317
318
# File 'app/models/katello/repository.rb', line 316

def immediate?
  root.download_policy == ::Katello::RootRepository::DOWNLOAD_IMMEDIATE
end

#import_distribution_data(target_repo = nil) ⇒ Object



720
721
722
723
724
725
726
727
728
729
730
731
732
# File 'app/models/katello/repository.rb', line 720

def import_distribution_data(target_repo = nil)
  if target_repo
    self.update!(
      :distribution_version => target_repo.distribution_version,
      :distribution_arch => target_repo.distribution_arch,
      :distribution_family => target_repo.distribution_family,
      :distribution_variant => target_repo.distribution_variant,
      :distribution_bootable => target_repo.distribution_bootable
    )
  else
    self.backend_service(SmartProxy.pulp_primary).import_distribution_data
  end
end

#in_content_view?(content_view) ⇒ Boolean

Returns:

  • (Boolean)


945
946
947
# File 'app/models/katello/repository.rb', line 945

def in_content_view?(content_view)
  content_view.repositories.include? self
end

#in_default_view?Boolean

Returns:

  • (Boolean)


308
309
310
# File 'app/models/katello/repository.rb', line 308

def in_default_view?
  content_view_version&.default_content_view?
end

#index_content(options = {}) ⇒ Object



920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
# File 'app/models/katello/repository.rb', line 920

def index_content(options = {})
  # set full_index to true if you want to force fetch all data from pulp
  # This is automatically done for library instance repos
  # However for non-library instance as in those belonging to a version
  # by default we fetch only ids and match them with the library instance
  # some times we want to force fetch all data even for non-library repos.
  # Use the full_index for those times

  full_index = options.fetch(:full_index, false)
  source_repository = options.fetch(:source_repository, nil)
  if self.yum? && !self.primary?
    index_linked_repo
  elsif source_repository && !repository_type.unique_content_per_repo
    copy_indexed_data(source_repository)
  else
    repository_type.content_types_to_index.each do |type|
      Katello::Logging.time("CONTENT_INDEX", data: {type: type.model_class}) do
        Katello::ContentUnitIndexer.new(content_type: type, repository: self, optimized: !full_index).import_all
      end
    end
    repository_type.index_additional_data_proc&.call(self)
  end
  true
end

#index_linked_repoObject



912
913
914
915
916
917
918
# File 'app/models/katello/repository.rb', line 912

def index_linked_repo
  if (base_repo = self.target_repository)
    copy_indexed_data(base_repo)
  else
    Rails.logger.error("Cannot index #{self.id}, no target repository found.")
  end
end

#latest_dynflow_syncObject



639
640
641
642
# File 'app/models/katello/repository.rb', line 639

def latest_dynflow_sync
  @latest_dynflow_sync ||= ForemanTasks::Task::DynflowTask.where(:label => ::Actions::Katello::Repository::Sync.name).
                            for_resource(self).order(:started_at).last
end

#latest_sync_auditObject



623
624
625
# File 'app/models/katello/repository.rb', line 623

def latest_sync_audit
  self.audits.where(:action => AUDIT_SYNC_ACTION).order(:created_at).last
end

#library_instance?Boolean

Returns:

  • (Boolean)


261
262
263
# File 'app/models/katello/repository.rb', line 261

def library_instance?
  self.content_view.default?
end

#library_instance_or_selfObject



501
502
503
# File 'app/models/katello/repository.rb', line 501

def library_instance_or_self
  self.library_instance || self
end

#link?Boolean

a link repository has no content in the pulp repository and serves as a shell. It will always be empty. Only the YumCloneDistributor can be used to publish yum metadata, and it cannot be indexed from pulp, but must have its indexed associations copied from another repository (its target).

Returns:

  • (Boolean)


803
804
805
# File 'app/models/katello/repository.rb', line 803

def link?
  !primary?
end

#module_streams_without_errataObject



539
540
541
542
543
544
545
546
547
548
# File 'app/models/katello/repository.rb', line 539

def module_streams_without_errata
  module_stream_errata = Katello::ModuleStreamErratumPackage.joins(:erratum_package => {:erratum => :repository_errata})
                          .where("#{RepositoryErratum.table_name}.repository_id" => self.id)
                          .pluck("#{Katello::ModuleStreamErratumPackage.table_name}.module_stream_id")
  if module_stream_errata.any?
    self.module_streams.where("#{ModuleStream.table_name}.id NOT in (?)", module_stream_errata)
  else
    self.module_streams
  end
end

#node_syncable?Boolean

Returns:

  • (Boolean)


670
671
672
# File 'app/models/katello/repository.rb', line 670

def node_syncable?
  environment
end

#on_demand?Boolean

Returns:

  • (Boolean)


312
313
314
# File 'app/models/katello/repository.rb', line 312

def on_demand?
  root.download_policy == ::Katello::RootRepository::DOWNLOAD_ON_DEMAND
end

#organizationObject



222
223
224
225
226
227
228
# File 'app/models/katello/repository.rb', line 222

def organization
  if self.environment
    self.environment.organization
  else
    self.content_view.organization
  end
end

#organization_idObject



230
231
232
# File 'app/models/katello/repository.rb', line 230

def organization_id
  organization&.id
end

#packages_without_errataObject



531
532
533
534
535
536
537
# File 'app/models/katello/repository.rb', line 531

def packages_without_errata
  if errata_filenames.any?
    self.rpms.where("#{Rpm.table_name}.filename NOT in (?)", errata_filenames)
  else
    self.rpms
  end
end

#partial_errataObject



406
407
408
409
410
411
412
413
414
415
416
417
# File 'app/models/katello/repository.rb', line 406

def partial_errata
  return [] if library_instance?

  partial_errata = self.errata
  errata_to_keep = fetch_package_errata_to_keep - fetch_module_errata_to_filter

  if errata_to_keep.any?
    partial_errata = self.errata.where("#{Katello::Erratum.table_name}.id NOT IN (?)", errata_to_keep)
  end

  partial_errata
end

#primary?Boolean

a primary repository actually has content (rpms, errata, etc) in the pulp repository. For these repositories, we can use the YumDistributor to generate metadata and can index the content from pulp, or for the case of content view archives without filters, can also use the YumCloneDistributor

Returns:

  • (Boolean)


794
795
796
797
798
799
# File 'app/models/katello/repository.rb', line 794

def primary?
  !self.yum? || # non-yum repos
      self.in_default_view? || # default content view repos
      (self.archive? && !self.content_view.composite) || # non-composite content view archive repos
      (self.archive? && self.content_view.composite? && self.component_source_repositories.count > 1) # composite archive repo with more than 1 source repository
end

#product_typeObject



327
328
329
# File 'app/models/katello/repository.rb', line 327

def product_type
  redhat? ? "redhat" : "custom"
end

#promoted?Boolean

Returns:

  • (Boolean)


463
464
465
466
467
468
469
# File 'app/models/katello/repository.rb', line 463

def promoted?
  if environment&.library?
    self.clones.any?
  else
    false
  end
end

#published_in_versionsObject



347
348
349
350
# File 'app/models/katello/repository.rb', line 347

def published_in_versions
  Katello::ContentViewVersion.with_repositories(self.library_instances_inverse)
                             .where(content_view_id: Katello::ContentView.ignore_generated).distinct
end

#rabl_pathObject



779
780
781
# File 'app/models/katello/repository.rb', line 779

def rabl_path
  "katello/api/v2/#{self.class.to_s.demodulize.tableize}/show"
end


666
667
668
# File 'app/models/katello/repository.rb', line 666

def related_resources
  self.product
end

#remove_partial_errata! {|found| ... } ⇒ Object

Yields:

  • (found)


419
420
421
422
423
424
# File 'app/models/katello/repository.rb', line 419

def remove_partial_errata!
  found = partial_errata.to_a
  yield(found) if block_given?
  self.repository_errata.where(:erratum_id => found.map(&:id)).delete_all
  found
end

#requires_yum_clone_distributor?Boolean

Returns:

  • (Boolean)


658
659
660
# File 'app/models/katello/repository.rb', line 658

def requires_yum_clone_distributor?
  self.yum? && self.environment_id && !self.in_default_view?
end

#set_container_repository_nameObject



253
254
255
# File 'app/models/katello/repository.rb', line 253

def set_container_repository_name
  self.container_repository_name = Repository.safe_render_container_name(self)
end

#set_pulp_idObject



238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'app/models/katello/repository.rb', line 238

def set_pulp_id
  return if self.pulp_id

  if self.content_view.default?
    items = [SecureRandom.uuid]
  elsif self.environment
    items = [organization.id, content_view.label, environment.label, library_instance.pulp_id]
  else
    version = self.content_view_version.version.gsub('.', '_')
    items = [organization.id, content_view.label, "v#{version}", library_instance.pulp_id]
  end
  self.pulp_id = items.join('-')
  self.pulp_id = SecureRandom.uuid if self.pulp_id.length > PULP_ID_MAX_LENGTH
end

#siblingsObject



426
427
428
# File 'app/models/katello/repository.rb', line 426

def siblings
  content_view_version.archived_repos.where.not(:id => id)
end

#soft_copy_of_library?Boolean

Returns:

  • (Boolean)


295
296
297
298
# File 'app/models/katello/repository.rb', line 295

def soft_copy_of_library?
  return false if self.version_href.nil?
  self.version_href.starts_with?(self.library_instance.backend_service(SmartProxy.pulp_primary).repository_reference.repository_href)
end

#sync_hookObject



772
773
774
775
776
777
# File 'app/models/katello/repository.rb', line 772

def sync_hook
  run_callbacks :sync do
    logger.debug "custom hook after_sync on #{name} will be executed if defined."
    true
  end
end

#target_repositoryObject

A link (empty repo) points to a target (a repository that actually has units in pulp). Target repos are always archive repos of a content view version (a repo with no environment) But for composite view versions, an archive repo, usually won’t be a primary (but might be if multple components contain the same repo)



809
810
811
812
813
814
815
816
817
818
819
820
821
# File 'app/models/katello/repository.rb', line 809

def target_repository
  fail _("This is not a linked repository") if primary?
  return nil if self.archived_instance.nil?

  #this is an environment repo, and the archived_instance is a primary (not always true with composite)
  if self.environment_id? && self.archived_instance.primary?
    self.archived_instance
  elsif self.environment_id #this is an environment repo, but a composite who's archived_instance isn't a primary
    self.archived_instance.target_repository || self.archived_instance #to archived_instance if nil
  else #must be a composite archive repo, with only one component repo
    self.component_source_repositories.first
  end
end

#to_hash(content_source = nil, force_http = false) ⇒ Object



454
455
456
# File 'app/models/katello/repository.rb', line 454

def to_hash(content_source = nil, force_http = false)
  {id: id, name: label, url: full_path(content_source, force_http)}
end

#to_labelObject



204
205
206
# File 'app/models/katello/repository.rb', line 204

def to_label
  name
end

#units_for_removal(ids, type_class = nil) ⇒ Object



702
703
704
705
706
707
708
709
710
711
712
# File 'app/models/katello/repository.rb', line 702

def units_for_removal(ids, type_class = nil)
  removable_unit_association = unit_type_for_removal(type_class)
  table_name = removable_unit_association.table_name
  is_integer = Integer(ids.first) rescue false #assume all ids are either integers or not

  if is_integer
    removable_unit_association.where("#{table_name}.id in (?)", ids)
  else
    removable_unit_association.where("#{table_name}.pulp_id in (?)", ids)
  end
end

#url?Boolean

Returns:

  • (Boolean)


662
663
664
# File 'app/models/katello/repository.rb', line 662

def url?
  root.url.present?
end

#using_mirrored_metadata?Boolean

Returns:

  • (Boolean)


304
305
306
# File 'app/models/katello/repository.rb', line 304

def using_mirrored_metadata?
  self.yum? && self.library_instance? && self.root.mirroring_policy == Katello::RootRepository::MIRRORING_POLICY_COMPLETE
end

#yum_gpg_key_urlObject



320
321
322
323
324
325
# File 'app/models/katello/repository.rb', line 320

def yum_gpg_key_url
  # if the repo has a gpg key return a url to access it
  if self.root.gpg_key.try(:content).present?
    "../..#{gpg_key_content_api_repository_url(self, :only_path => true)}"
  end
end