Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #38048 - Add rolling content views #11240

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def show_all
CAST (#{kcc}.composite_content_view_id as BOOLEAN) ASC, #{kc}.name
SQL
query = Katello::ContentView.readable.in_organization(@organization)
query = query&.non_composite&.non_default&.generated_for_none
query = query&.non_composite&.non_default&.non_rolling&.generated_for_none
component_cv_ids = Katello::ContentViewComponent.where(composite_content_view_id: @view.id).select(:content_view_id)
query = case params[:status]
when "Not added"
Expand Down Expand Up @@ -145,23 +145,23 @@ def update
def get_total(status)
case status
when 'All'
return Katello::ContentView.non_default.non_composite.in_organization(@organization).count
return Katello::ContentView.non_default.non_composite.non_rolling.in_organization(@organization).count
when 'Added'
return Katello::ContentViewComponent.where(composite_content_view_id: @view.id).count
when 'Not added'
return Katello::ContentView.non_default.non_composite.in_organization(@organization).count - Katello::ContentViewComponent.where(composite_content_view_id: @view.id).count
return Katello::ContentView.non_default.non_composite.non_rolling.in_organization(@organization).count - Katello::ContentViewComponent.where(composite_content_view_id: @view.id).count
else
return Katello::ContentView.non_default.non_composite.in_organization(@organization).count
return Katello::ContentView.non_default.non_composite.non_rolling.in_organization(@organization).count
end
end

def find_composite_content_view
@view = ContentView.composite.non_default.readable.find_by(id: params[:composite_content_view_id])
@view = ContentView.composite.non_default.non_rolling.readable.find_by(id: params[:composite_content_view_id])
throw_resource_not_found(name: 'composite content view', id: params[:composite_content_view_id]) if @view.nil?
end

def find_composite_content_view_for_edit
@view = ContentView.composite.non_default.editable.find_by(id: params[:composite_content_view_id])
@view = ContentView.composite.non_default.non_rolling.editable.find_by(id: params[:composite_content_view_id])
throw_resource_not_found(name: 'composite content view', id: params[:composite_content_view_id]) if @view.nil?
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ def index_relation
param :repository_ids, Array, :desc => N_("list of repository ids")
param :description, String, :desc => N_("description of the filter")
def create
if @view.rolling?
fail HttpErrors::BadRequest, _("It's not possible to create a filter for a rolling content view.")
end
params[:type] = "erratum" if (params[:type] == "erratum_date" || params[:type] == "erratum_id")
filter = ContentViewFilter.create_for(params[:type], filter_params.merge(:content_view => @view))
respond :resource => filter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ def show
param :environment_ids, Array, :desc => N_("Identifiers for Lifecycle Environment")
param :description, String, :desc => N_("The description for the content view version promotion")
def promote
if @view.rolling?
fail HttpErrors::BadRequest, _("It's not possible to promote a rolling content view.")
end
is_force = ::Foreman::Cast.to_bool(params[:force])
task = async_task(::Actions::Katello::ContentView::Promote,
@content_view_version, @environments, is_force, params[:description])
Expand Down Expand Up @@ -97,6 +100,9 @@ def republish_repositories
api :DELETE, "/content_view_versions/:id", N_("Remove content view version")
param :id, :number, :desc => N_("Content view version identifier"), :required => true
def destroy
if @view.rolling?
fail HttpErrors::BadRequest, _("It's not possible to destroy a version of a rolling content view.")
end
task = async_task(::Actions::Katello::ContentViewVersion::Destroy, @content_view_version)
respond_for_async :resource => task
end
Expand Down
24 changes: 22 additions & 2 deletions app/controllers/katello/api/v2/content_views_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Api::V2::ContentViewsController < Api::V2::ApiController

wrap_parameters :include => (ContentView.attribute_names + %w(repository_ids component_ids))

around_action :add_to_environment, :only => [:create]
resource_description do
api_version "v2"
end
Expand Down Expand Up @@ -84,6 +85,7 @@ def index_relation
param :name, String, :desc => N_("Name of the content view"), :required => true
param :label, String, :desc => N_("Content view label")
param :composite, :bool, :desc => N_("Composite content view")
param :rolling, :bool, :desc => N_("Rolling content view")
param_group :content_view
def create
@content_view = ContentView.create!(view_params) do |view|
Expand Down Expand Up @@ -192,6 +194,9 @@ def remove
param :key_content_view_id, :number, :desc => N_("content view to reassign orphaned activation keys to")
param :key_environment_id, :number, :desc => N_("environment to reassign orphaned activation keys to")
def bulk_delete_versions
if @content_view.rolling?
fail HttpErrors::BadRequest, _("It's not possible to bulk remove versions from a rolling content view.")
end
params[:bulk_content_view_version_ids] ||= {}

versions = find_bulk_items(bulk_params: params[:bulk_content_view_version_ids],
Expand Down Expand Up @@ -237,6 +242,9 @@ def destroy
param :name, String, :required => true, :desc => N_("New content view name")
def copy
@content_view = Katello::ContentView.readable.find_by(:id => params[:id])
if @content_view.rolling?
fail HttpErrors::BadRequest, _("It's not possible to copy a rolling content view.")
end
throw_resource_not_found(name: 'content_view', id: params[:id]) if @content_view.blank?
ensure_non_default
new_content_view = @content_view.copy(params[:content_view][:name])
Expand All @@ -246,6 +254,9 @@ def copy
private

def validate_publish_params!
if @content_view.rolling?
fail HttpErrors::BadRequest, _("It's not possible to publish a rolling content view.")
end
if params[:repos_units].present? && @content_view.composite?
fail HttpErrors::BadRequest, _("Directly setting package lists on composite content views is not allowed. Please " \
"update the components, then re-publish the composite.")
Expand Down Expand Up @@ -284,11 +295,14 @@ def ensure_non_generated
def view_params
attrs = [:name, :description, :auto_publish, :solve_dependencies, :import_only,
:default, :created_at, :updated_at, :next_version, {:component_ids => []}]
attrs.push(:label, :composite) if action_name == "create"
attrs.push(:label, :composite, :rolling) if action_name == "create"
if (!@content_view || !@content_view.composite?)
attrs.push({:repository_ids => []}, :repository_ids)
end
params.require(:content_view).permit(*attrs).to_h
result = params.require(:content_view).permit(*attrs).to_h
# sanitize repository_ids to be a list of integers
result[:repository_ids] = result[:repository_ids].map(&:to_i) if result[:repository_ids].present?
result
end

def find_environment
Expand All @@ -307,5 +321,11 @@ def add_use_latest_records(module_records, selected_latest_versions)
end
module_records
end

def add_to_environment
yield
return unless params[:rolling]
async_task(::Actions::Katello::ContentView::AddToEnvironment, @content_view.create_new_version, @content_view.organization.library)
end
end
end
3 changes: 3 additions & 0 deletions app/controllers/katello/api/v2/exports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ def find_exportable_content_view_version
@version = ContentViewVersion.exportable.find_by_id(params[:id])
throw_resource_not_found(name: 'content view version', id: params[:id]) if @version.blank?
@view = @version.content_view
if @view.rolling?
fail HttpErrors::BadRequest, _("It's not possible to export a rolling content view.")
end
end

def find_history
Expand Down
17 changes: 17 additions & 0 deletions app/lib/actions/helpers/rolling_cv_repos.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Actions
module Helpers
module RollingCVRepos
def update_rolling_content_views(repo)
concurrence do
repos = repo.root.repositories.in_environment(repo.environment).where(
content_view_version: ::Katello::ContentViewVersion.where(content_view: ::Katello::ContentView.rolling)
)

repos.each do |rolling_repo|
plan_action(::Actions::Katello::ContentView::RefreshRollingRepo, rolling_repo)
end
end
end
end
end
end
28 changes: 28 additions & 0 deletions app/lib/actions/katello/content_view/add_rolling_repo_clone.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Actions
module Katello
module ContentView
class AddRollingRepoClone < Actions::EntryAction
def plan(content_view, repository_ids)
library = content_view.organization.library

concurrence do
::Katello::Repository.where(id: repository_ids).each do |repository|
sequence do
clone = content_view.get_repo_clone(library, repository).first
if clone.nil?
clone = repository.build_clone(content_view: content_view, environment: library)
clone.save!
end
plan_action(RefreshRollingRepo, clone)

view_env_cp_id = content_view.content_view_environment(library).cp_id
content_id = repository.content_id
plan_action(Actions::Candlepin::Environment::AddContentToEnvironment, :view_env_cp_id => view_env_cp_id, :content_id => content_id)
end
end
end
end
end
end
end
end
30 changes: 30 additions & 0 deletions app/lib/actions/katello/content_view/refresh_rolling_repo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Actions
module Katello
module ContentView
class RefreshRollingRepo < Actions::EntryAction
def plan(repository)
action_subject repository
sequence do
plan_self(repository_id: repository.id)
plan_action(Pulp3::Repository::RefreshDistribution, repository, SmartProxy.pulp_primary)
plan_action(Repository::IndexContent, id: repository.id, source_repository_id: repository.library_instance.id)
end
end

def run
repository = ::Katello::Repository.find(input[:repository_id])
library_instance = repository.library_instance
# ensure IndexContent is not skipped!
repository.last_contents_changed = DateTime.now if repository.version_href != library_instance.version_href

repository.version_href = library_instance.version_href
repository.publication_href = library_instance.publication_href
if repository.deb_using_structured_apt?
repository.content_id = library_instance.content_id
end
repository.save!
end
end
end
end
end
28 changes: 28 additions & 0 deletions app/lib/actions/katello/content_view/remove_rolling_repo_clone.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Actions
module Katello
module ContentView
class RemoveRollingRepoClone < Actions::EntryAction
def plan(content_view, repository_ids)
library = content_view.organization.library

clone_repo_ids = []
concurrence do
::Katello::Repository.where(id: repository_ids).each do |repository|
clone_repo = content_view.get_repo_clone(library, repository).first
next if clone_repo.nil?

clone_repo_ids << clone_repo.id
plan_action(Actions::Pulp3::Repository::DeleteDistributions, clone_repo.id, SmartProxy.pulp_primary)
end
plan_action(Candlepin::Environment::SetContent, content_view, library, content_view.content_view_environment(library))
end
plan_self(repository_ids: clone_repo_ids)
end

def run
::Katello::Repository.where(id: input[:repository_ids]).destroy_all
end
end
end
end
end
8 changes: 8 additions & 0 deletions app/lib/actions/katello/content_view/update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ def plan(content_view, content_view_params)
end
end

if content_view.rolling? && content_view_params.key?(:repository_ids)
repo_ids_to_add = content_view_params[:repository_ids] - content_view.repository_ids
repo_ids_to_remove = content_view.repository_ids - content_view_params[:repository_ids]

plan_action(AddRollingRepoClone, content_view, repo_ids_to_add) if repo_ids_to_add.any?
plan_action(RemoveRollingRepoClone, content_view, repo_ids_to_remove) if repo_ids_to_remove.any?
end

content_view.update!(content_view_params)
end
end
Expand Down
5 changes: 5 additions & 0 deletions app/lib/actions/katello/repository/import_upload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module Actions
module Katello
module Repository
class ImportUpload < Actions::EntryAction
include Helpers::RollingCVRepos

# rubocop:disable Metrics/MethodLength
def plan(repository, uploads, options = {})
action_subject(repository)
Expand Down Expand Up @@ -52,6 +54,9 @@ def plan(repository, uploads, options = {})
plan_action(Katello::Repository::MetadataGenerate, repository, force_publication: true) if generate_metadata
plan_action(Actions::Katello::Applicability::Repository::Regenerate, :repo_ids => [repository.id]) if generate_applicability
plan_self(repository_id: repository.id, sync_capsule: sync_capsule, upload_results: upload_results)

# Refresh rolling CVs that have this repository
update_rolling_content_views(repository)
end
end
# rubocop:enable Metrics/MethodLength
Expand Down
2 changes: 2 additions & 0 deletions app/lib/actions/katello/repository/sync.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Repository
class Sync < Actions::EntryAction
extend ApipieDSL::Class
include Helpers::Presenter
include Helpers::RollingCVRepos
include ::Actions::ObservableAction
middleware.use Actions::Middleware::ExecuteIfContentsChanged

Expand Down Expand Up @@ -56,6 +57,7 @@ def plan(repo, options = {})
end
plan_self(:id => repo.id, :sync_result => output, :skip_metadata_check => skip_metadata_check, :validate_contents => validate_contents,
:contents_changed => output[:contents_changed])
update_rolling_content_views(repo)
plan_action(Katello::Repository::SyncHook, :id => repo.id)
end
end
Expand Down
8 changes: 7 additions & 1 deletion app/lib/actions/katello/repository/upload_files.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ module Actions
module Katello
module Repository
class UploadFiles < Actions::EntryAction
include Helpers::RollingCVRepos

def plan(repository, files, content_type = nil, options = {})
action_subject(repository)
repository.check_ready_to_act!
Expand Down Expand Up @@ -38,6 +40,9 @@ def plan(repository, files, content_type = nil, options = {})
plan_action(FinishUpload, repository, content_type: content_type, upload_actions: upload_actions)
plan_self(tmp_files: tmp_files)
plan_action(Actions::Katello::Applicability::Repository::Regenerate, :repo_ids => [repository.id]) if generate_applicability

# Refresh rolling CVs that have this repository
update_rolling_content_views(repository)
end
ensure
# Delete tmp files when some exception occurred. Would be
Expand All @@ -46,7 +51,8 @@ def plan(repository, files, content_type = nil, options = {})
end

def run
ForemanTasks.async_task(Repository::CapsuleSync, ::Katello::Repository.find(input[:repository][:id])) if Setting[:foreman_proxy_content_auto_sync]
repository = ::Katello::Repository.find(input[:repository][:id])
ForemanTasks.async_task(Repository::CapsuleSync, repository) if Setting[:foreman_proxy_content_auto_sync]
rescue ::Katello::Errors::CapsuleCannotBeReached # skip any capsules that cannot be connected to
end

Expand Down
15 changes: 14 additions & 1 deletion app/models/katello/content_view.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ class ContentView < Katello::Model
validates :composite,
inclusion: { in: [false], message: "Composite Content Views can not solve dependencies" },
if: :solve_dependencies
validates :rolling, :inclusion => [true, false]
validates :rolling,
inclusion: { in: [false], message: "Rolling content views can not solve dependencies" },
if: :solve_dependencies
validates :rolling,
inclusion: { in: [false], message: "Rolling content views can not be composite" },
if: :composite
validates :rolling,
inclusion: { in: [false], message: "Rolling content views can not be import only" },
if: :import_only
validates :import_only, :inclusion => [true, false]
validates :import_only,
inclusion: { in: [false], message: "Import-only Content Views can not be Composite" },
Expand All @@ -93,6 +103,8 @@ class ContentView < Katello::Model
scope :non_default, -> { where(:default => false) }
scope :composite, -> { where(:composite => true) }
scope :non_composite, -> { where(:composite => [nil, false]) }
scope :rolling, -> { where(:rolling => true) }
scope :non_rolling, -> { where(:rolling => [nil, false]) }
scope :generated, -> { where.not(:generated_for => :none) }
scope :generated_for_repository, -> {
where(:generated_for => [:repository_export,
Expand All @@ -113,6 +125,7 @@ class ContentView < Katello::Model
scoped_search :on => :organization_id, :complete_value => true, :only_explicit => true, :validator => ScopedSearch::Validators::INTEGER
scoped_search :on => :label, :complete_value => true
scoped_search :on => :composite, :complete_value => { :true => true, :false => false }
scoped_search :on => :rolling, :complete_value => { :true => true, :false => false }
scoped_search :on => :generated_for, :complete_value => true
scoped_search :on => :default # just for ordering
scoped_search :on => :name, :complete_value => true,
Expand Down Expand Up @@ -802,7 +815,7 @@ def cv_repo_indexed_after_last_published?
end

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

def needs_publish?
Expand Down
4 changes: 4 additions & 0 deletions app/models/katello/content_view_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ def ensure_valid_content_view
errors.add(:base, _("Cannot add default content view to composite content view"))
end

if view.rolling?
errors.add(:base, _("Cannot add rolling content view to composite content view"))
end

if attached_content_view_ids.include?(view.id)
errors.add(:base, _("Another component already includes content view with ID %s" % view.id))
end
Expand Down
Loading
Loading