Class: Katello::ContentView

Inherits:
Model
  • Object
show all
Includes:
Foreman::ObservableModel, ForemanTasks::Concerns::ActionSubject, Authorization::ContentView, Ext::LabelFromName
Defined in:
app/models/katello/content_view.rb

Overview

rubocop:disable Metrics/ClassLength

Defined Under Namespace

Classes: Jail

Constant Summary collapse

CONTENT_DIR =
"content_views".freeze
IMPORT_LIBRARY =
"Import-Library".freeze
EXPORT_LIBRARY =
"Export-Library".freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Authorization::ContentView

#deletable?, #editable?, #promotable_or_removable?, #publishable?, #readable?

Methods included from Ext::LabelFromName

included, #label_not_changed, #setup_label_from_name

Methods inherited from Model

#destroy!

Class Method Details

.completer_scope_options(search) ⇒ Object



144
145
146
147
148
149
150
151
# File 'app/models/katello/content_view.rb', line 144

def self.completer_scope_options(search)
  if search.include?('content_views')
    # Don't autocomplete CCV names when searching for components
    { :value_filter => { :composite => false } }
  else
    {}
  end
end

.find_components_by_cv_name(_key, operator, value) ⇒ Object



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

def self.find_components_by_cv_name(_key, operator, value)
  kcv = Katello::ContentView.table_name
  kcvc = Katello::ContentViewComponent.table_name
  { :conditions => "#{kcv}.composite = 't' AND #{kcv}.id IN (SELECT #{kcvc}.composite_content_view_id FROM #{kcvc} WHERE #{kcvc}.content_view_id IN (SELECT #{kcv}.id FROM #{kcv} WHERE #{kcv}.name #{operator} ?))",
    :parameter => [value],
  }
end

.humanize_class_name(_name = nil) ⇒ Object



765
766
767
# File 'app/models/katello/content_view.rb', line 765

def self.humanize_class_name(_name = nil)
  _("Content Views")
end

.in_environment(env) ⇒ Object



174
175
176
177
# File 'app/models/katello/content_view.rb', line 174

def self.in_environment(env)
  joins(:content_view_environments).
    where("#{Katello::ContentViewEnvironment.table_name}.environment_id = ?", env.id)
end

.in_organization(org) ⇒ Object



183
184
185
# File 'app/models/katello/content_view.rb', line 183

def self.in_organization(org)
  where(organization_id: org.id) unless org.nil?
end

.published_with_repositories(root_repository) ⇒ Object



179
180
181
# File 'app/models/katello/content_view.rb', line 179

def self.published_with_repositories(root_repository)
  joins(:content_view_versions => :repositories).where("katello_repositories.root_id" => root_repository.id).uniq
end

Instance Method Details

#add_components(components_to_add) ⇒ Object

Adds content view components based on the input

:latest=> false, :latest=> true ..


225
226
227
228
229
# File 'app/models/katello/content_view.rb', line 225

def add_components(components_to_add)
  components_to_add.each do |cvc|
    content_view_components.build(cvc)
  end
end

#add_environment(env, version) ⇒ Object

Associate an environment with this content view. This can occur whenever a version of the view is promoted to an environment. It is necessary for candlepin to become aware that the view is available for consumers.



588
589
590
591
592
593
594
595
596
597
598
599
# File 'app/models/katello/content_view.rb', line 588

def add_environment(env, version)
  if self.content_view_environments.where(:environment_id => env.id).empty?
    label = generate_cp_environment_label(env)
    ContentViewEnvironment.create!(:name => label,
                                   :label => label,
                                   :cp_id => generate_cp_environment_id(env),
                                   :environment_id => env.id,
                                   :content_view => self,
                                   :content_view_version => version
    )
  end
end

#all_version_library_instancesObject

get the library instances of all repos within this view



502
503
504
505
506
# File 'app/models/katello/content_view.rb', line 502

def all_version_library_instances
  all_repos = all_version_repos.where(:library_instance_id => nil).pluck("#{Katello::Repository.table_name}.id")
  all_repos += all_version_repos.pluck(:library_instance_id)
  Repository.where(:id => all_repos)
end

#all_version_reposObject



400
401
402
403
# File 'app/models/katello/content_view.rb', line 400

def all_version_repos
  Repository.joins(:content_view_version).
    where("#{Katello::ContentViewVersion.table_name}.content_view_id" => self.id)
end

#as_json(options = {}) ⇒ Object

NOTE: this function will most likely become obsolete once we drop api v1



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'app/models/katello/content_view.rb', line 308

def as_json(options = {})
  result = self.attributes
  result['organization'] = self.organization.try(:name)
  result['environments'] = environments.map { |e| e.try(:name) }
  result['versions'] = versions.map(&:version)
  result['versions_details'] = versions.map do |v|
    {
      :version => v.version,
      :published => v.created_at.to_s,
      :environments => v.environments.map { |e| e.name },
    }
  end

  if options && options[:environment].present?
    result['repositories'] = repos(options[:environment]).map(&:name)
  end

  result
end

#audited_changes_present?Boolean

Returns:

  • (Boolean)


870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
# File 'app/models/katello/content_view.rb', line 870

def audited_changes_present?
  latest_version_created_at = latest_version_object.created_at
  cv_repository_ids = repositories.pluck(:id)

  audited_changes_like = ->(param) {
    Arel.sql("#{Audit.table_name}.audited_changes ilike '%#{param}%'")
  }

  table = Audit.arel_table
  repository_condition = table[:auditable_id].eq(id)
                                             .and(table[:auditable_type].eq('Katello::ContentView'))
                                             .and(audited_changes_like.call("repository_ids"))

  cv_repository_condition = table[:auditable_id].in(cv_repository_ids)
                                                .and(table[:auditable_type].eq('Katello::Repository'))
                                                .and(Arel.sql("(#{audited_changes_like.call("publication_href")} OR #{audited_changes_like.call("version_href")})"))

  content_view_filter_condition = table[:auditable_type].eq('Katello::ContentViewFilter').and(table[:associated_id].eq(id))

  filter_rule_condition = table[:associated_id].eq(id).and(table[:auditable_type].matches('%FilterRule%'))

  base_query = table[:created_at].gt(latest_version_created_at)

  final_query = base_query.and(repository_condition.or(cv_repository_condition).or(content_view_filter_condition).or(filter_rule_condition))

  Audit.where(final_query).exists?
end

#auto_publish_componentsObject



450
451
452
# File 'app/models/katello/content_view.rb', line 450

def auto_publish_components
  component_composites.where(latest: true).joins(:composite_content_view).where(self.class.table_name => { auto_publish: true })
end

#blocking_taskObject



906
907
908
909
910
911
912
913
914
915
# File 'app/models/katello/content_view.rb', line 906

def blocking_task
  blocking_task_labels = [
    ::Actions::Katello::ContentView::Publish.name,
  ]
  ForemanTasks::Task::DynflowTask.where(:label => blocking_task_labels)
                                 .where.not(state: 'stopped')
                                 .for_resource(self)
                                 .order(:started_at)
                                 .last
end

#check_composite_action_allowed!(env) ⇒ Object



690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
# File 'app/models/katello/content_view.rb', line 690

def check_composite_action_allowed!(env)
  if composite? && Setting['restrict_composite_view']
    if components.size != content_view_components.size
      fail _("Make sure all the component content views are published before publishing/promoting the composite content view. "\
           "This restriction is optional and can be modified in the Administrator -> Settings -> Content "\
            "page using the restrict_composite_view flag.")
    end

    env_ids = env.try(:pluck, 'id') || []
    env_ids << env.id unless env_ids.size > 0
    components.each do |component|
      component_environment_ids = component.environments.pluck('id')
      unless (env_ids - component_environment_ids).empty?
        fail _("The action requested on this composite view cannot be performed until all of the "\
               "component content view versions have been promoted to the target environment: %{env}.  "\
               "This restriction is optional and can be modified in the Administrator -> Settings -> Content "\
               "page using the restrict_composite_view flag.") %
               { :env => env.try(:pluck, 'name') || env.name }
      end
    end
  end
  true
end

#check_default_label_nameObject



562
563
564
565
566
# File 'app/models/katello/content_view.rb', line 562

def check_default_label_name
  if default? && !(name == 'Default Organization View' && label == 'Default_Organization_View')
    errors.add(:base, _("Name and label of default content view should not be changed"))
  end
end

#check_docker_conflictsObject



568
569
570
571
572
573
# File 'app/models/katello/content_view.rb', line 568

def check_docker_conflicts
  duplicate_docker_repos.each do |repo|
    msg = _("Container Image repo '%{repo}' is present in multiple component content views.") % { repo: repo.name }
    errors.add(:base, msg)
  end
end

#check_docker_repository_names!(environments) ⇒ Object



673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
# File 'app/models/katello/content_view.rb', line 673

def check_docker_repository_names!(environments)
  environments.each do |environment|
    repositories = []
    publish_repositories do |all_repositories|
      repositories += all_repositories.keep_if { |repository| repository.content_type == Katello::Repository::DOCKER_TYPE }
    end
    next if repositories.empty?

    error_messages = ::Katello::Validators::EnvironmentDockerRepositoriesValidator.validate_repositories(environment.registry_name_pattern, repositories)
    unless error_messages.empty?
      error_messages << _("Consider changing the Lifecycle Environment's Registry Name Pattern to something more specific.")
      fail error_messages.join("  ")
    end
  end
  true
end

#check_non_composite_auto_publishObject



556
557
558
559
560
# File 'app/models/katello/content_view.rb', line 556

def check_non_composite_auto_publish
  if !composite? && auto_publish
    errors.add(:base, _("Cannot set auto publish to a non-composite content view"))
  end
end

#check_non_composite_componentsObject



550
551
552
553
554
# File 'app/models/katello/content_view.rb', line 550

def check_non_composite_components
  if !composite? && components.present?
    errors.add(:base, _("Cannot add component versions to a non-composite content view"))
  end
end

#check_orphaned_content_facets!(environments: []) ⇒ Object



714
715
716
717
718
719
720
721
722
723
724
# File 'app/models/katello/content_view.rb', line 714

def check_orphaned_content_facets!(environments: [])
  Location.no_taxonomy_scope do
    User.as_anonymous_admin do
      ::Katello::Host::ContentFacet.with_content_views(self).with_environments(environments).each do |facet|
        unless facet.host
          fail _("Orphaned content facets for deleted hosts exist for the content view and environment. Please run rake task : katello:clean_orphaned_facets and try again!")
        end
      end
    end
  end
end

#check_ready_to_destroy!Object



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

def check_ready_to_destroy!
  check_orphaned_content_facets!(environments: self.environments)
  errors = []

  dependencies = { environments: _("environments"),
                   hosts: _("hosts"),
                   activation_keys: _("activation keys"),
  }

  dependencies.each do |key, name|
    if (models = self.association(key).scope).any?
      errors << _("Cannot delete '%{view}' due to associated %{dependent}: %{names}.") %
        { view: self.name, dependent: name, names: models.map(&:name).join(", ") }
    end
  end

  fail errors.join(" ") if errors.any?
  return true
end

#check_ready_to_import!Object



640
641
642
643
644
# File 'app/models/katello/content_view.rb', line 640

def check_ready_to_import!
  fail _("Cannot import a composite content view") if composite?
  fail _("This Content View must be set to Import-only before performing an import") unless import_only?
  true
end

#check_ready_to_publish!(importing: false, syncable: false) ⇒ Object



646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
# File 'app/models/katello/content_view.rb', line 646

def check_ready_to_publish!(importing: false, syncable: false)
  fail _("User must be logged in.") if ::User.current.nil?
  fail _("Cannot publish default content view") if default?

  if importing
    check_ready_to_import!
  else
    fail _("Import-only content views can not be published directly") if import_only? && !syncable
    check_repositories_blocking_publish!
    check_composite_action_allowed!(organization.library)
    check_docker_repository_names!([organization.library])
    check_orphaned_content_facets!(environments: self.environments)
  end

  true
end

#check_remove_from_environment!(env) ⇒ Object



726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
# File 'app/models/katello/content_view.rb', line 726

def check_remove_from_environment!(env)
  check_orphaned_content_facets!(environments: [env])
  errors = []

  dependencies = { hosts: _("hosts"),
                   activation_keys: _("activation keys"),
  }

  dependencies.each do |key, name|
    if (models = self.association(key).scope.in_environments(env)).any?
      errors << _("Cannot remove '%{view}' from environment '%{env}' due to associated %{dependent}: %{names}.") %
        { view: self.name, env: env.name, dependent: name, names: models.map(&:name).join(", ") }
    end
  end

  fail errors.join(" ") if errors.any?
  return true
end

#check_repositories_blocking_publish!Object



663
664
665
666
667
668
669
670
671
# File 'app/models/katello/content_view.rb', line 663

def check_repositories_blocking_publish!
  blocking_tasks = repositories&.map { |repo| repo.blocking_task }&.compact

  if blocking_tasks&.any?
    errored_tasks = blocking_tasks.uniq.map { |task| "- #{Setting['foreman_url']}/foreman_tasks/tasks/#{task&.id}" }.join("\n")
    fail _("Pending tasks detected in repositories of this content view. Please wait for the tasks: " +
             errored_tasks + " before publishing.")
  end
end

#component_idsObject



211
212
213
# File 'app/models/katello/content_view.rb', line 211

def component_ids
  components.map(&:id)
end

#component_ids=(component_version_ids_to_set) ⇒ Object

Warning this call wipes out existing associations And replaces them with the component version ids passed in.



239
240
241
242
243
244
245
246
247
# File 'app/models/katello/content_view.rb', line 239

def component_ids=(component_version_ids_to_set)
  content_view_components.destroy_all
  component_version_ids_to_set.each do |content_view_version_id|
    cvv = ContentViewVersion.find(content_view_version_id)
    content_view_components.build(:content_view_version => cvv,
                                  :latest => false,
                                  :composite_content_view => self)
  end
end

#component_repositoriesObject



479
480
481
# File 'app/models/katello/content_view.rb', line 479

def component_repositories
  components.map(&:archived_repos).flatten
end

#component_repository_idsObject



483
484
485
# File 'app/models/katello/content_view.rb', line 483

def component_repository_ids
  component_repositories.map(&:id)
end

#componentsObject



215
216
217
# File 'app/models/katello/content_view.rb', line 215

def components
  content_view_components.map(&:latest_version).compact.freeze
end

#components_with_repo(library_instance) ⇒ Object



446
447
448
# File 'app/models/katello/content_view.rb', line 446

def components_with_repo(library_instance)
  components.select { |component| component.repositories.where(:library_instance => library_instance).any? }
end

#composite_cv_components_changed?Boolean

Returns:

  • (Boolean)


800
801
802
803
804
805
806
807
808
# File 'app/models/katello/content_view.rb', line 800

def composite_cv_components_changed?
  return true unless latest_version_object
  published_component_version_ids = latest_version_object.components.pluck(:id) || []
  unpublished_component_version_ids = content_view_components.where(latest: false).pluck(:content_view_version_id) || []
  content_view_components.where(latest: true).each do |latest_component|
    unpublished_component_version_ids << latest_component.content_view&.latest_version_object&.id
  end
  published_component_version_ids.compact.uniq.sort != unpublished_component_version_ids.compact.uniq.sort
end

#content_host_countObject



207
208
209
# File 'app/models/katello/content_view.rb', line 207

def content_host_count
  hosts.size
end

#content_view_environment(environment) ⇒ Object



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

def content_view_environment(environment)
  self.content_view_environments.where(:environment_id => environment.try(:id)).first
end

#copy(new_name) ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'app/models/katello/content_view.rb', line 284

def copy(new_name)
  new_view = ContentView.new
  new_view.name = new_name
  new_view.attributes = self.attributes.slice("description", "organization_id", "default", "composite", "solve_dependencies")
  new_view.save!
  new_view.repositories = self.repositories

  copy_components(new_view)

  copy_filters(new_view)
  new_view.save!
  new_view
end

#copy_components(new_view) ⇒ Object



249
250
251
252
253
254
255
# File 'app/models/katello/content_view.rb', line 249

def copy_components(new_view)
  self.content_view_components.each do |cvc|
    component = cvc.dup
    component.composite_content_view = new_view
    new_view.content_view_components << component
  end
end

#copy_filters(new_view) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'app/models/katello/content_view.rb', line 257

def copy_filters(new_view)
  self.filters.each do |filter|
    new_filter = filter.dup
    new_filter.repositories = filter.repositories
    new_view.filters << new_filter

    case filter.type
    when ContentViewDebFilter.name
      filter.deb_rules.each do |rule|
        new_filter.deb_rules << rule.dup
      end
    when ContentViewPackageFilter.name
      filter.package_rules.each do |rule|
        new_filter.package_rules << rule.dup
      end
    when ContentViewPackageGroupFilter.name
      filter.package_group_rules.each do |rule|
        new_filter.package_group_rules << rule.dup
      end
    when ContentViewErratumFilter.name
      filter.erratum_rules.each do |rule|
        new_filter.erratum_rules << rule.dup
      end
    end
  end
end

#cp_environment_id(env) ⇒ Object



617
618
619
# File 'app/models/katello/content_view.rb', line 617

def cp_environment_id(env)
  ContentViewEnvironment.where(:content_view_id => self, :environment_id => env).first.try(:cp_id)
end

#cp_environment_label(env) ⇒ Object



613
614
615
# File 'app/models/katello/content_view.rb', line 613

def cp_environment_label(env)
  ContentViewEnvironment.where(:content_view_id => self, :environment_id => env).first.try(:label)
end

#create_new_version(major = next_version, minor = 0, components = self.components) ⇒ Object



621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
# File 'app/models/katello/content_view.rb', line 621

def create_new_version(major = next_version, minor = 0, components = self.components)
  version = ContentViewVersion.create!(:major => major,
                                       :minor => minor,
                                       :content_view => self,
                                       :components => components
  )

  # TODO: If a controller creates a new version and then uses latest_version_object, the old data is displayed.
  #       To prevent this, a 'reload' would currently be necessary, but this is not very performant.
  #       However, this is currently not a problem because after your create_new_version there is no immediate
  #       access to latest_version_object, but the ContentView object is first completely reloaded.
  #
  #       In Rails 7.1, individual connections can be reloaded:
  #       https://www.shakacode.com/blog/rails-7-1-allows-resetting-singular-associations/

  update(:next_version => major.to_i + 1) unless major.to_i < next_version
  version
end

#cv_repo_indexed_after_last_published?Boolean

Returns:

  • (Boolean)


815
816
817
# File 'app/models/katello/content_view.rb', line 815

def cv_repo_indexed_after_last_published?
  repositories.any? { |repo| repo.last_indexed && repo.last_indexed > latest_version_object.created_at }
end

#delete(from_env) ⇒ Object



515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
# File 'app/models/katello/content_view.rb', line 515

def delete(from_env)
  if from_env.library? && in_non_library_environment?
    fail Errors::ChangesetContentException, _("Cannot delete view while it exists in environments")
  end

  version = self.version(from_env)
  if version.nil?
    fail Errors::ChangesetContentException, _("Cannot delete from %s, view does not exist there.") % from_env.name
  end
  version = ContentViewVersion.find(version.id)

  if (foreman_env = Environment.find_by_katello_id(self.organization, from_env, self))
    foreman_env.destroy
  end

  version.delete(from_env)
  self.destroy if self.versions.empty?
end

#dependency_solving_changed?Boolean

Returns:

  • (Boolean)


898
899
900
# File 'app/models/katello/content_view.rb', line 898

def dependency_solving_changed?
  latest_version_object.applied_filters && solve_dependencies != latest_version_object.applied_filters['dependency_solving']
end

#duplicate_docker_reposObject



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

def duplicate_docker_repos
  duplicate_repositories.docker_type
end

#duplicate_repositoriesObject



538
539
540
541
542
543
544
# File 'app/models/katello/content_view.rb', line 538

def duplicate_repositories
  counts = repositories_to_publish.each_with_object(Hash.new(0)) do |repo, h|
    h[repo.library_instance_id] += 1
  end
  ids = counts.select { |_k, v| v > 1 }.keys
  Repository.where(:id => ids)
end

#duplicate_repositories_to_publishObject



441
442
443
444
# File 'app/models/katello/content_view.rb', line 441

def duplicate_repositories_to_publish
  return [] unless composite?
  repositories_to_publish_by_library_instance.select { |key, val| val.count > 1 && key.present? }.keys
end

#filtered?Boolean

Returns:

  • (Boolean)


902
903
904
# File 'app/models/katello/content_view.rb', line 902

def filtered?
  filters.present?
end

#generated?Boolean

Returns:

  • (Boolean)


303
304
305
# File 'app/models/katello/content_view.rb', line 303

def generated?
  !generated_for_none?
end

#generated_for_library?Boolean

Returns:

  • (Boolean)


203
204
205
# File 'app/models/katello/content_view.rb', line 203

def generated_for_library?
  generated_for_library_export? || generated_for_library_import? || generated_for_library_export_syncable?
end

#generated_for_repository?Boolean

Returns:

  • (Boolean)


199
200
201
# File 'app/models/katello/content_view.rb', line 199

def generated_for_repository?
  generated_for_repository_export? || generated_for_repository_import? || generated_for_repository_export_syncable?
end

#get_repo_clone(env, repo) ⇒ Object



508
509
510
511
512
513
# File 'app/models/katello/content_view.rb', line 508

def get_repo_clone(env, repo)
  lib_id = repo.library_instance_id || repo.id
  Repository.in_environment(env).where(:library_instance_id => lib_id).
    joins(:content_view_version).
    where("#{Katello::ContentViewVersion.table_name}.content_view_id" => self.id)
end

#historyObject



368
369
370
371
# File 'app/models/katello/content_view.rb', line 368

def history
  Katello::ContentViewHistory.joins(:content_view_version).where(
    "#{Katello::ContentViewVersion.table_name}.content_view_id" => self.id)
end

#in_environment?(env) ⇒ Boolean

Returns:

  • (Boolean)


336
337
338
# File 'app/models/katello/content_view.rb', line 336

def in_environment?(env)
  environments.include?(env)
end

#in_non_library_environment?Boolean

Returns:

  • (Boolean)


534
535
536
# File 'app/models/katello/content_view.rb', line 534

def in_non_library_environment?
  environments.where(:library => false).length > 0
end

#last_publish_task_success?Boolean

Returns:

  • (Boolean)


810
811
812
813
# File 'app/models/katello/content_view.rb', line 810

def last_publish_task_success?
  last_publish_result = latest_version_object&.history&.publish&.first&.task&.result
  return last_publish_result.present? && last_publish_result == 'success'
end

#last_taskObject



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

def last_task
  last_task_id = history.order(:created_at)&.last&.task_id
  last_task_id ? ForemanTasks::Task.find_by(id: last_task_id) : nil
end

#latest_versionObject



349
350
351
# File 'app/models/katello/content_view.rb', line 349

def latest_version
  latest_version_object.try(:version)
end

#latest_version_envObject



357
358
359
360
361
# File 'app/models/katello/content_view.rb', line 357

def latest_version_env
  environments = organization.readable_promotion_paths.flatten
  environments.insert(0, organization.library)
  environments.intersection(latest_version_object.try(:environments) || [])
end

#latest_version_idObject



353
354
355
# File 'app/models/katello/content_view.rb', line 353

def latest_version_id
  latest_version_object.try(:id)
end

#library_export?Boolean

Returns:

  • (Boolean)


195
196
197
# File 'app/models/katello/content_view.rb', line 195

def library_export?
  name.start_with? EXPORT_LIBRARY
end

#library_import?Boolean

Returns:

  • (Boolean)


191
192
193
# File 'app/models/katello/content_view.rb', line 191

def library_import?
  name == IMPORT_LIBRARY
end

#library_repo_idsObject



396
397
398
# File 'app/models/katello/content_view.rb', line 396

def library_repo_ids
  repos(self.organization.library).map { |r| r.library_instance_id }
end

#library_reposObject



392
393
394
# File 'app/models/katello/content_view.rb', line 392

def library_repos
  Repository.where(:id => library_repo_ids)
end

#needs_publish?Boolean

Returns:

  • (Boolean)


823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
# File 'app/models/katello/content_view.rb', line 823

def needs_publish?
  #Returns
  # True:
  #     a) When content/repo/filter change audit records exist
  #     b) CV hasn't ever been published
  #     c) CV dependency_solving != latest_version.applied_filters.dependency_solving
  #     d) If repo was indexed after cv publish. This can happen under 3 cases:
  #       i) Index runs because last index(before publish) had failed and repo is picked up for index even if pulp publication hasn't changed.
  #       ii) Complete sync runs or sync adds/removes new content (Already true because new pulp publication/version gets created)
  #       iii) repo.index_content is run. (This doesn't necessarily indicate contents changed. Corner case where we play safe and return true)
  # nil:
  #     a) When CV version creation audit is missing(Indicating audit cleanup)
  #     b) Version doesn't have audited_filters set indicating
  #     it was published before 4.9 upgrade when we started auditing changes on the CV.
  #     c) Last publish task failed leaving us with no way of knowing if all content in the version is correct.
  # False:
  #     a) No changes were detected via audits *and*
  #        Audit for CV publish exists (Audits haven't been cleaned up)
  #        *and* applied_filters field is set(Published after upgrade)
  #     b) Default, import only and generated CVs can not be published, hence these will always return false.
  #
  return false if unpublishable?
  return true unless latest_version_object
  return nil unless last_publish_task_success?
  return composite_cv_components_changed? if composite?
  # return true if the audit records clearly show we have unpublished changes
  return true if audited_changes_present?
  # return true if the dependency solving changed for CV between last publish and now
  return true if dependency_solving_changed?
  # return true if any child repo's indexed_at > last_version.created_at
  return true if cv_repo_indexed_after_last_published?
  # if we didn't return `true` already, either the audit records show that we don't need to publish, or we may
  # have insufficient data to make the determination (either audits were cleaned, or never got created at all).
  # first, check for the `create` audit record; its absence indicates that audits were cleaned some time after
  # the cv version was created (i.e. the first indeterminate state) so we return `nil` in that case.
  return nil unless latest_version_object&.audits&.where(action: "create")&.exists?
  # even when the `create` audit exists, the other audits could still be absent due to the latest cv version
  # being created prior to the tracking of the other audits that were added in katello 4.9 (i.e. the second indeterminate state).
  # We determine that using the `applied_filters` field. This field was added in Katello 4.9 and is set to nil for
  # all versions published before that upgrade.
  # If `applied_filters` is nil we can not deterministically rule out changes before the upgrade
  # not captured by newer content change and filter change audits.
  # If that field is not nil, the version was published after upgrade, hence we have all the information to rule out
  # any audited changes to the CV and we can deterministically return false
  latest_version_object.applied_filters.nil? ? nil : false
end

#on_demand_repositoriesObject



773
774
775
# File 'app/models/katello/content_view.rb', line 773

def on_demand_repositories
  repositories.on_demand
end

#products(env = nil) ⇒ Object



496
497
498
499
# File 'app/models/katello/content_view.rb', line 496

def products(env = nil)
  repos = repos(env)
  Product.joins(:repositories).where("#{Katello::Repository.table_name}.id" => repos.map(&:id)).distinct
end

#promoted?Boolean

Returns:

  • (Boolean)


298
299
300
301
# File 'app/models/katello/content_view.rb', line 298

def promoted?
  # if the view exists in more than 1 environment, it has been promoted
  self.environments.many?
end

#publish_repositories(override_components = nil) ⇒ Object



454
455
456
457
458
459
460
461
462
463
# File 'app/models/katello/content_view.rb', line 454

def publish_repositories(override_components = nil)
  repositories = composite? ? repositories_to_publish_by_library_instance(override_components).values : repositories_to_publish
  repositories.each do |repos|
    if repos.is_a? Array
      yield repos
    else
      yield [repos]
    end
  end
end


785
786
787
788
789
790
791
792
793
794
795
796
797
798
# File 'app/models/katello/content_view.rb', line 785

def related_composite_cvs
  content_views = []
  component_composites.each do |cv|
    cv_id = cv.composite_content_view_id
    cv_name = ContentView.find(cv_id).name
    content_views.push(
      {
        id: cv_id,
        name: cv_name,
      }
    )
  end
  content_views
end


777
778
779
780
781
782
783
# File 'app/models/katello/content_view.rb', line 777

def related_cv_count
  if composite
    content_view_components.length
  else
    component_composites.length
  end
end

#remove_components(components_to_remove) ⇒ Object

Removes selected content view components

1,2,34

> content view component ids/



233
234
235
# File 'app/models/katello/content_view.rb', line 233

def remove_components(components_to_remove)
  content_view_components.where(:id => components_to_remove).destroy_all
end

#remove_environment(env) ⇒ Object

Unassociate an environment from this content view. This can occur whenever a view is deleted from an environment. It is necessary to make candlepin aware that the view is no longer available for consumers.



604
605
606
607
608
609
610
611
# File 'app/models/katello/content_view.rb', line 604

def remove_environment(env)
  # Do not remove the content view environment, if there is still a view
  # version in the environment.
  if self.versions.in_environment(env).blank?
    view_env = self.content_view_environments.where(:environment_id => env.id)
    view_env.first.destroy unless view_env.blank?
  end
end

#repos(env = nil) ⇒ Object



383
384
385
386
387
388
389
390
# File 'app/models/katello/content_view.rb', line 383

def repos(env = nil)
  if env
    repo_ids = versions.flat_map { |version| version.repositories.in_environment(env) }.map(&:id)
  else
    repo_ids = versions.flat_map { |version| version.repositories }.map(&:id)
  end
  Repository.where(:id => repo_ids)
end

#repos_in_product(env, product) ⇒ Object



487
488
489
490
491
492
493
494
# File 'app/models/katello/content_view.rb', line 487

def repos_in_product(env, product)
  version = version(env)
  if version
    version.repositories.in_environment(env).in_product(product)
  else
    []
  end
end

#repositories_to_publish(override_components = nil) ⇒ Object



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# File 'app/models/katello/content_view.rb', line 405

def repositories_to_publish(override_components = nil)
  if composite?
    components_to_publish = []
    components.each do |component|
      override_component = override_components&.detect do |override_cvv|
        override_cvv.content_view == component.content_view
      end

      if override_component
        components_to_publish << override_component
      else
        components_to_publish << component
      end
    end
    ids = components_to_publish.flat_map { |version| version.repositories.archived }.map(&:id)
    Repository.where(:id => ids)
  else
    repositories
  end
end

#repositories_to_publish_by_library_instance(override_components = nil) ⇒ Object



430
431
432
433
434
435
436
437
438
439
# File 'app/models/katello/content_view.rb', line 430

def repositories_to_publish_by_library_instance(override_components = nil)
  # retrieve the list of repositories in a hash, where the key
  # is the library instance id, and the value is an array
  # of the repositories for that instance.
  repositories_to_publish(override_components).inject({}) do |result, repo|
    result[repo.library_instance] ||= []
    result[repo.library_instance] << repo
    result
  end
end

#repositories_to_publish_idsObject



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

def repositories_to_publish_ids
  composite? ? repositories_to_publish.pluck(&:id) : repository_ids
end

#resulting_productsObject



379
380
381
# File 'app/models/katello/content_view.rb', line 379

def resulting_products
  (self.repositories.collect { |r| r.product }).uniq
end

#sorted_versionsObject



219
220
221
# File 'app/models/katello/content_view.rb', line 219

def sorted_versions
  versions.order('created_at DESC')
end

#to_sObject



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

def to_s
  name
end

#total_deb_package_count(env) ⇒ Object



332
333
334
# File 'app/models/katello/content_view.rb', line 332

def total_deb_package_count(env)
  Katello::Deb.in_repositories(self.repos(env)).count
end

#total_package_count(env) ⇒ Object



328
329
330
# File 'app/models/katello/content_view.rb', line 328

def total_package_count(env)
  Katello::Rpm.in_repositories(self.repos(env)).count
end

#unpublishable?Boolean

Returns:

  • (Boolean)


819
820
821
# File 'app/models/katello/content_view.rb', line 819

def unpublishable?
  default? || import_only? || generated? || rolling?
end

#update_cp_content(env) ⇒ Object



579
580
581
582
583
# File 'app/models/katello/content_view.rb', line 579

def update_cp_content(env)
  view_env = content_view_environment(env)

  view_env&.update_cp_content
end

#update_host_statuses(environment) ⇒ Object



465
466
467
468
469
470
471
472
473
474
475
476
477
# File 'app/models/katello/content_view.rb', line 465

def update_host_statuses(environment)
  # update errata applicability counts for all hosts in the CV & LE
  Location.no_taxonomy_scope do
    User.as_anonymous_admin do
      ::Katello::Host::ContentFacet.with_content_views(self).with_environments(environment).each do |facet|
        facet.update_applicability_counts
        facet.update_errata_status
      rescue NoMethodError
        Rails.logger.warn _('Errata statuses not updated for deleted content facet with UUID %s') % facet.uuid
      end
    end
  end
end

#version(env) ⇒ Object



345
346
347
# File 'app/models/katello/content_view.rb', line 345

def version(env)
  self.versions.in_environment(env).order("#{Katello::ContentViewVersion.table_name}.id ASC").readonly(false).last
end

#version_countObject



769
770
771
# File 'app/models/katello/content_view.rb', line 769

def version_count
  content_view_versions.size
end

#version_environment(env) ⇒ Object



373
374
375
376
377
# File 'app/models/katello/content_view.rb', line 373

def version_environment(env)
  # TODO: rewrite this into SQL or use content_view_environment when that
  # points to environment
  version(env).content_view_version_environments.select { |cvve| cvve.environment_id == env.id }
end