Class: Katello::ContentViewVersion

Inherits:
Model
  • Object
show all
Includes:
ForemanTasks::Concerns::ActionSubject, Authorization::ContentViewVersion, Katello::Concerns::SearchByRepositoryName
Defined in:
app/models/katello/content_view_version.rb

Overview

rubocop:disable Metrics/ClassLength

Defined Under Namespace

Classes: Jail

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Authorization::ContentViewVersion

#all_hosts_editable?

Methods inherited from Model

#destroy!

Class Method Details

.component_of(versions) ⇒ Object



91
92
93
# File 'app/models/katello/content_view_version.rb', line 91

def self.component_of(versions)
  joins(:content_view_version_composites).where("#{Katello::ContentViewVersionComponent.table_name}.composite_version_id" => versions)
end

.find_by_version(_key, operator, value) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'app/models/katello/content_view_version.rb', line 73

def self.find_by_version(_key, operator, value)
  conditions = ""
  if ['>', '<', '=', '<=', '>=', "<>", "!=", 'IN', 'NOT IN'].include?(operator) && value.to_f >= 0
    major, minor = value.split(".")
    case
    when /[<>]/ =~ operator
      minor ||= 0
      query = where("major #{operator} :major OR (major = :major AND minor #{operator} :minor)", :major => major, :minor => minor)
    when minor.nil?
      query = where("major #{operator} (:major)", :major => major)
    else
      query = where("major #{operator} (:major) and minor #{operator} (:minor)", :major => major, :minor => minor)
    end
    _, conditions = query.to_sql.split("WHERE")
  end
  { :conditions => conditions }
end

.for_version(version) ⇒ Object



99
100
101
102
103
# File 'app/models/katello/content_view_version.rb', line 99

def self.for_version(version)
  major, minor = version.to_s.split('.')
  minor ||= 0
  where(:major => major, :minor => minor)
end

.in_environment(env) ⇒ Object



209
210
211
# File 'app/models/katello/content_view_version.rb', line 209

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

.with_library_repo(repo) ⇒ Object



95
96
97
# File 'app/models/katello/content_view_version.rb', line 95

def self.with_library_repo(repo)
  joins(:repositories).where("#{Katello::Repository.table_name}.library_instance_id" => repo)
end

Instance Method Details

#active_historyObject



115
116
117
# File 'app/models/katello/content_view_version.rb', line 115

def active_history
  self.history.select { |history| history.task.try(:pending) }
end

#after_promote_hooksObject



424
425
426
427
428
429
# File 'app/models/katello/content_view_version.rb', line 424

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

#ansible_collectionsObject



109
110
111
# File 'app/models/katello/content_view_version.rb', line 109

def ansible_collections
  AnsibleCollection.in_repositories(archived_repos)
end

#archived_reposObject



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

def archived_repos
  self.default? ? self.repositories : self.repos(nil)
end

#auto_publish_composites!Object



351
352
353
354
355
356
357
358
359
360
361
# File 'app/models/katello/content_view_version.rb', line 351

def auto_publish_composites!
   = {
    description: _("Auto Publish - Triggered by '%s'") % self.name,
    triggered_by: self.id
  }
  self.content_view.auto_publish_components.pluck(:composite_content_view_id).each do |composite_id|
    ::Katello::EventQueue.push_event(::Katello::Events::AutoPublishCompositeView::EVENT_TYPE, composite_id) do |attrs|
      attrs[:metadata] = 
    end
  end
end

#available_debsObject



290
291
292
# File 'app/models/katello/content_view_version.rb', line 290

def available_debs
  library_packages.where.not(:id => debs)
end

#available_errataObject



304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'app/models/katello/content_view_version.rb', line 304

def available_errata
  # The simple/obvious solution is:
  #   library_errata.where.not(:id => errata)
  # However, when the list of exclusions is large, the SQL "NOT IN" clause
  # is extremely inefficient, and it is much better to use a
  # "LEFT OUTER JOIN" with a subquery.
  # ActiveRecord .joins() only supports subqueries by supplying raw SQL.  We
  # use .to_sql to avoid hard-coding raw SQL for self.errata, although
  # .to_sql may also be somewhat brittle.  For example, see:
  # https://github.com/rails/rails/issues/18379
  library_errata.joins(
    "LEFT OUTER JOIN (#{errata.select('id').to_sql}) AS exclude_errata ON " \
    'katello_errata.id = exclude_errata.id'
  ).where('exclude_errata.id IS NULL')
end

#available_packagesObject



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'app/models/katello/content_view_version.rb', line 253

def available_packages
  # The simple/obvious solution is:
  #   library_packages.where.not(:id => packages)
  # However, when the list of exclusions is large, the SQL "NOT IN" clause
  # is extremely inefficient, and it is much better to use a
  # "LEFT OUTER JOIN" with a subquery.
  # ActiveRecord .joins() only supports subqueries by supplying raw SQL.  We
  # use .to_sql to avoid hard-coding raw SQL for self.packages, although
  # .to_sql may also be somewhat brittle.  For example, see:
  # https://github.com/rails/rails/issues/18379
  library_packages.joins(
    "LEFT OUTER JOIN (#{packages.select('id').to_sql}) AS exclude_rpms ON " \
    'katello_rpms.id = exclude_rpms.id'
  ).where('exclude_rpms.id IS NULL')
end

#available_releasesObject



155
156
157
# File 'app/models/katello/content_view_version.rb', line 155

def available_releases
  Katello::RootRepository.where(:id => self.repositories.select(:root_id)).pluck(:minor).compact.uniq.sort
end

#before_promote_hooksObject



417
418
419
420
421
422
# File 'app/models/katello/content_view_version.rb', line 417

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

#check_ready_to_promote!(to_env) ⇒ Object



379
380
381
382
383
384
# File 'app/models/katello/content_view_version.rb', line 379

def check_ready_to_promote!(to_env)
  fail _("Default content view versions cannot be promoted") if default?
  content_view.check_composite_action_allowed!(to_env)
  content_view.check_docker_repository_names!(to_env)
  content_view.check_orphaned_content_facets!(environments: [to_env])
end

#components_needing_errata(errata) ⇒ Object



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

def components_needing_errata(errata)
  component_repos = Repository.where(:content_view_version_id => self.components)
  library_repos = Repository.where(:id => component_repos.pluck(:library_instance_id)).with_errata(errata)
  component_repos -= component_repos.with_errata(errata) #find component repos without the errata
  component_repos.select { |repo| library_repos.include?(repo.library_instance) }.map(&:content_view_version).uniq
end

#content_counts_mapObject



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

def content_counts_map
  # if its empty, calculate it on demand
  update_content_counts! if content_counts.blank?
  counts = Hash[content_counts.map { |key, value| ["#{key}_count", value] }]
  counts.merge("module_stream_count" => counts["modulemd_count"],
               "package_count" => counts["rpm_count"])
end

#debsObject



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

def debs
  Katello::Deb.in_repositories(self.repositories.archived)
end

#default_content_view?Boolean

Returns:

  • (Boolean)


135
136
137
# File 'app/models/katello/content_view_version.rb', line 135

def default_content_view?
  default?
end

#deletable?(from_env) ⇒ Boolean

Returns:

  • (Boolean)


221
222
223
224
# File 'app/models/katello/content_view_version.rb', line 221

def deletable?(from_env)
  ::Host.in_content_view_environment(self.content_view, from_env).empty? ||
      self.content_view.versions.in_environment(from_env).count > 1
end

#descriptionObject



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

def description
  history.publish.first.try(:notes)
end

#docker_manifest_listsObject



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

def docker_manifest_lists
  DockerManifestList.in_repositories(archived_repos)
end

#docker_manifestsObject



324
325
326
# File 'app/models/katello/content_view_version.rb', line 324

def docker_manifests
  DockerManifest.in_repositories(archived_repos)
end

#docker_tagsObject



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

def docker_tags
  # Don't count tags from non-archived repos; this causes count errors
  ::Katello::DockerMetaTag.where(:id => RepositoryDockerMetaTag.where(:repository_id => repositories.archived.docker_type).select(:docker_meta_tag_id))
end

#env_promote_date(env) ⇒ Object



123
124
125
# File 'app/models/katello/content_view_version.rb', line 123

def env_promote_date(env)
  Katello::ContentViewEnvironment.where(:environment_id => env.id, :content_view_version_id => self.id).pluck(:updated_at).try(:first)
end

#errata(errata_type = nil) ⇒ Object



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

def errata(errata_type = nil)
  errata = Erratum.in_repositories(archived_repos)
  errata = errata.of_type(errata_type) if errata_type
  errata
end

#file_unitsObject



320
321
322
# File 'app/models/katello/content_view_version.rb', line 320

def file_units
  FileUnit.in_repositories(archived_repos)
end

#generic_content_units(content_type) ⇒ Object



245
246
247
# File 'app/models/katello/content_view_version.rb', line 245

def generic_content_units(content_type)
  GenericContentUnit.in_repositories(archived_repos).where(content_type: content_type)
end

#get_repo_clone(env, repo) ⇒ Object



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

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

#importable_repositoriesObject



409
410
411
412
413
414
415
# File 'app/models/katello/content_view_version.rb', line 409

def importable_repositories
  if default?
    repositories.exportable
  else
    archived_repos.exportable
  end
end

#in_composite?Boolean

Returns:

  • (Boolean)


143
144
145
# File 'app/models/katello/content_view_version.rb', line 143

def in_composite?
  composite_content_views.any?
end

#in_environment?Boolean

Returns:

  • (Boolean)


151
152
153
# File 'app/models/katello/content_view_version.rb', line 151

def in_environment?
  environments.any?
end

#incrementally_updated?Boolean

Returns:

  • (Boolean)


167
168
169
# File 'app/models/katello/content_view_version.rb', line 167

def incrementally_updated?
  minor != 0
end

#last_eventObject



119
120
121
# File 'app/models/katello/content_view_version.rb', line 119

def last_event
  self.history.order(:created_at).last
end

#latest?Boolean

Returns:

  • (Boolean)


139
140
141
# File 'app/models/katello/content_view_version.rb', line 139

def latest?
  content_view.latest_version_id == self.id
end

#library_debsObject



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

def library_debs
  Katello::Deb.in_repositories(library_repos)
end

#library_errataObject



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

def library_errata
  Erratum.in_repositories(library_repos)
end

#library_packagesObject



249
250
251
# File 'app/models/katello/content_view_version.rb', line 249

def library_packages
  Rpm.in_repositories(library_repos)
end

#library_reposObject



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

def library_repos
  archived_repos.includes(:library_instance).map(&:library_instance)
end

#module_streamsObject



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

def module_streams
  ModuleStream.in_repositories(archived_repos)
end

#nameObject



127
128
129
# File 'app/models/katello/content_view_version.rb', line 127

def name
  "#{content_view} #{version}"
end

#next_incremental_versionObject



159
160
161
# File 'app/models/katello/content_view_version.rb', line 159

def next_incremental_version
  "#{major}.#{minor + 1}"
end

#non_archive_reposObject



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

def non_archive_repos
  self.repositories.non_archived
end

#package_groupsObject



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

def package_groups
  PackageGroup.in_repositories(archived_repos)
end

#packagesObject



241
242
243
# File 'app/models/katello/content_view_version.rb', line 241

def packages
  Rpm.in_repositories(archived_repos)
end

#products(env = nil) ⇒ Object



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

def products(env = nil)
  if env
    repos(env).map(&:product).uniq(&:id)
  else
    self.repositories.map(&:product).uniq(&:id)
  end
end

#promotable?(target_envs) ⇒ Boolean

Returns:

  • (Boolean)


226
227
228
229
230
231
232
# File 'app/models/katello/content_view_version.rb', line 226

def promotable?(target_envs)
  target_envs = Array.wrap(target_envs)
  all_environments = target_envs + environments
  target_envs.all? do |environment|
    all_environments.include?(environment.prior) || environments.empty? && environment == organization.library
  end
end

#published_in_composite?Boolean

Returns:

  • (Boolean)


147
148
149
# File 'app/models/katello/content_view_version.rb', line 147

def published_in_composite?
  content_view_version_composites.any?
end

#rabl_pathObject



431
432
433
# File 'app/models/katello/content_view_version.rb', line 431

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

#removable?Boolean

Returns:

  • (Boolean)


213
214
215
216
217
218
219
# File 'app/models/katello/content_view_version.rb', line 213

def removable?
  if environments.blank?
    content_view.promotable_or_removable?
  else
    content_view.promotable_or_removable? && KTEnvironment.where(:id => environments).any_promotable?
  end
end

#repos(env) ⇒ Object



171
172
173
# File 'app/models/katello/content_view_version.rb', line 171

def repos(env)
  self.repositories.in_environment(env)
end

#repos_ordered_by_product(env) ⇒ Object



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

def repos_ordered_by_product(env)
  # The repository model has a default scope that orders repositories by name;
  # however, for content views, it is desirable to order the repositories
  # based on the name of the product the repository is part of.
  Repository.send(:with_exclusive_scope) do
    self.repositories.joins(:product).in_environment(env).order("#{Katello::Product.table_name}.name asc")
  end
end

#repository_type_counts_mapObject



363
364
365
366
367
368
369
# File 'app/models/katello/content_view_version.rb', line 363

def repository_type_counts_map
  counts = {}
  Katello::RepositoryTypeManager.enabled_repository_types.keys.each do |repo_type|
    counts["#{repo_type}_repository_count"] = archived_repos.with_type(repo_type).count
  end
  counts
end

#srpmsObject



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

def srpms
  Katello::Srpm.in_repositories(self.repositories)
end

#to_sObject



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

def to_s
  name
end

#update_content_counts!Object



336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'app/models/katello/content_view_version.rb', line 336

def update_content_counts!
  self.content_counts = {}
  RepositoryTypeManager.indexable_content_types.each do |content_type|
    case content_type&.model_class::CONTENT_TYPE
    when DockerTag::CONTENT_TYPE
      content_counts[DockerTag::CONTENT_TYPE] = docker_tags.count
    when GenericContentUnit::CONTENT_TYPE
      content_counts[content_type.content_type] = content_type&.model_class&.in_repositories(self.repositories.archived)&.where(:content_type => content_type.content_type)&.count
    else
      content_counts[content_type&.model_class::CONTENT_TYPE] = content_type&.model_class&.in_repositories(self.repositories.archived)&.count
    end
  end
  save!
end

#validate_destroyable!(skip_environment_check: false) ⇒ Object



386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
# File 'app/models/katello/content_view_version.rb', line 386

def validate_destroyable!(skip_environment_check: false)
  unless organization.being_deleted?
    if !skip_environment_check && in_environment?
      fail _("Cannot delete version while it is in environments: %s") %
               environments.map(&:name).join(",")
    end

    if in_composite?
      fail _("Cannot delete version while it is in use by composite content views: %s") %
               composite_content_views.map(&:name).join(",")
    end

    if published_in_composite?
      list = composites.map do |version|
        "#{version.content_view.name} Version #{version.version}"
      end
      fail _("Cannot delete version while it is in use by composite content views: %s") %
               list.join(",")
    end
  end
  true
end

#versionObject



163
164
165
# File 'app/models/katello/content_view_version.rb', line 163

def version
  "#{major}.#{minor}"
end