Skip to content

Commit

Permalink
Merge branch 'master' into issue-38116
Browse files Browse the repository at this point in the history
  • Loading branch information
pavanshekar authored Jan 20, 2025
2 parents fef992a + 4b9bac9 commit fcced92
Show file tree
Hide file tree
Showing 77 changed files with 1,088 additions and 354 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:

angular:
name: Angular ${{ matrix.engine }} - NodeJS ${{ matrix.node }}
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ locale/*/*.po.time_stamp
locale/.cache/*
locale/*/*.pox
locale/*/LC_MESSAGES
locale/action_names.rb
.yardoc
yardoc
doc/apidoc*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Api::Registry::RegistryProxiesController < Api::V2::ApiController
before_action :confirm_settings
skip_before_action :authorize
before_action :optional_authorize, only: [:token, :catalog]
before_action :registry_authorize, except: [:token, :v1_search, :catalog]
before_action :registry_authorize, except: [:token, :v1_search, :catalog, :static_index]
before_action :authorize_repository_read, only: [:pull_manifest, :tags_list, :check_blob, :pull_blob]
before_action :container_push_prop_validation, only: [:start_upload_blob, :upload_blob, :finish_upload_blob, :push_manifest]
before_action :create_container_repo_if_needed, only: [:start_upload_blob, :upload_blob, :finish_upload_blob, :push_manifest]
Expand Down Expand Up @@ -806,5 +806,25 @@ def render_podman_error(code, message, status = :bad_request)
def item_not_found(item)
render_podman_error("NAME_UNKNOWN", _("%s was not found!") % item, :not_found)
end

def static_index
host_ip = request.remote_ip
host = ::Host.joins(:primary_interface).where("nics.ip = :host_ip OR nics.ip6 = :host_ip", host_ip: host_ip)&.first
flatpak_index = (redirect_client { Resources::Registry::Proxy.get(@_request.fullpath, headers) })
flatpak_index_json = JSON.parse(flatpak_index)
# Filter out repositories if it's a registered host
if host&.content_view_environments&.any?
# host.update(flatpak_index: flatpak_index) Will this help??
repos = host.content_view_environments.flat_map do |cve|
cve.content_view_version.repositories
end
available_container_repo_names = repos.map(&:container_repository_name)
flatpak_index_json['Results'] = flatpak_index_json['Results'].select do |result|
available_container_repo_names.include?(result['Name'])
end
end
# Otherwise just return unfiltered pulp flatpak index
render json: flatpak_index_json
end
end
end
3 changes: 2 additions & 1 deletion app/controllers/katello/api/v2/content_uploads_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ class Api::V2::ContentUploadsController < Api::V2::ApiController
param :repository_id, :number, :required => true, :desc => N_("repository id")
param :size, :number, :required => true, :desc => N_("Size of file to upload")
param :checksum, String, :required => false, :desc => N_("Checksum of file to upload")
param :content_type, RepositoryTypeManager.uploadable_content_types(false).map(&:label), :required => false, :desc => N_("content type ('deb', 'docker_manifest', 'file', 'ostree_ref', 'rpm', 'srpm')")
param :content_type, RepositoryTypeManager.uploadable_content_types(false).map(&:label), :required => false, :desc => N_("content type ('deb', 'file', 'ostree_ref', 'rpm', 'srpm')")
def create
fail Katello::Errors::InvalidRepositoryContent, _("Cannot upload Ansible collections.") if @repository.ansible_collection?
fail Katello::Errors::InvalidRepositoryContent, _("Cannot upload container content via Hammer/API. Use podman push instead.") if @repository.docker?
content_type = params[:content_type] || ::Katello::RepositoryTypeManager.find(@repository.content_type)&.default_managed_content_type&.label
RepositoryTypeManager.check_content_matches_repo_type!(@repository, content_type)
if ::Katello::RepositoryTypeManager.generic_content_type?(content_type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def resource_class
param :types, Array, :desc => N_("erratum: types (enhancement, bugfix, security)")
param :date_type, String, :desc => N_("erratum: search using the 'Issued On' or 'Updated On' column of the errata. Values are 'issued'/'updated'")
param :module_stream_ids, Array, :desc => N_("module stream ids")
param :allow_other_types, :bool, :desc => N_("erratum: allow types not matching a valid errata type")
def create
rule_clazz = ContentViewFilter.rule_class_for(@filter)

Expand Down Expand Up @@ -89,6 +90,7 @@ def show
param :start_date, String, :desc => N_("erratum: start date (YYYY-MM-DD)")
param :end_date, String, :desc => N_("erratum: end date (YYYY-MM-DD)")
param :types, Array, :desc => N_("erratum: types (enhancement, bugfix, security)")
param :allow_other_types, :bool, :desc => N_("erratum: allow types not matching a valid errata type")
def update
update_params = rule_params
update_params[:name] = update_params[:name].first if update_params[:name]
Expand Down Expand Up @@ -136,7 +138,7 @@ def rule_params

@rule_params ||= params.fetch(:content_view_filter_rule, {}).
permit(:uuid, :version, :min_version, :max_version, :architecture,
:errata_id, :start_date, :end_date, :date_type,
:errata_id, :start_date, :end_date, :date_type, :allow_other_types,
:types => [], :module_stream_ids => [], :errata_ids => [], name: [])
end

Expand Down
5 changes: 4 additions & 1 deletion app/controllers/katello/api/v2/content_views_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,10 @@ def view_params
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].compact.map(&:to_i) if result[:repository_ids].present?
result
end

def find_environment
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/katello/api/v2/environments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ def show
ID of an environment that is prior to the new environment in the chain. It has to be
either the ID of Library or the ID of an environment at the end of a chain.
DESC
param :path_id, Integer, :desc => <<-DESC
If you are adding an environment to an existing path after Library, pass the ID of the environment that is the current successor of Library in the path.
It has to be the id of the old environment following library in this path.
DESC
def create
create_params = environment_params
create_params[:label] = labelize_params(create_params)
Expand Down
13 changes: 12 additions & 1 deletion app/controllers/katello/api/v2/errata_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,20 @@ def custom_index_relation(collection)
fail HttpErrors::UnprocessableEntity, msg
end

custom_index_relation_handle_type_and_time(collection)
end

def custom_index_relation_handle_type_and_time(collection)
collection = collection.where("#{date_type} >= ?", params[:start_date]) if params[:start_date]
collection = collection.where("#{date_type} <= ?", params[:end_date]) if params[:end_date]
collection = collection.of_type(params[:types]) if params[:types]
if params[:types]
include_other = params[:types]&.include?('other')
params[:types]&.delete('other')
collection = collection.of_type(
params[:types],
include_other
)
end
collection
end

Expand Down
71 changes: 71 additions & 0 deletions app/controllers/katello/api/v2/host_bootc_images_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
module Katello
class Api::V2::HostBootcImagesController < Api::V2::ApiController
include Katello::Concerns::FilteredAutoCompleteSearch

resource_description do
api_version 'v2'
api_base_url "/api"
end

api :GET, "/hosts/bootc_images", N_("List booted bootc container images for hosts")
param_group :search, Api::V2::ApiController
def bootc_images
params[:sort_by] ||= 'bootc_booted_image'
params[:sort_order] ||= 'asc'
if params[:order]
params[:order] = "#{params[:order].split(' ')[0]} #{sanitize_sort_order(params[:order].split(' ')[1])}"
else
params[:order] = "#{params[:sort_by]} #{sanitize_sort_order(params[:sort_order])}"
end
per_page = params[:per_page].present? ? params[:per_page].to_i : Setting[:entries_per_page]
page = params[:page].present? ? params[:page].to_i : 1

bootc_image_map = bootc_host_image_map
paged_images = bootc_image_map.to_a.paginate(page: page, per_page: per_page)
results = paged_images.collect { |image| { bootc_booted_image: image[0], digests: image[1] } }
render json: {
total: bootc_image_map.size,
page: page,
per_page: per_page,
subtotal: bootc_image_map.size,
sort: {
by: params[:sort_by],
order: params[:sort_order],
},
results: results,
}
end

private

def sanitize_sort_order(sort_order)
if sort_order.present? && ['asc', 'desc'].include?(sort_order.downcase)
sort_order.downcase
else
'asc'
end
end

def index_relation
query = resource_class.authorized(:view_hosts).distinct
query.joins(:content_facet).where.not(bootc_booted_image: nil, bootc_booted_digest: nil)
query
end

def resource_class
::Host::Managed
end

def bootc_host_image_map
content_facets = ::Katello::Host::ContentFacet.where(host_id: ::Host::Managed.joins(:content_facet).search_for(params[:search]).pluck(:id))
aggregate_bootc_data = content_facets.where.not(bootc_booted_image: nil, bootc_booted_digest: nil).
select(:bootc_booted_image, :bootc_booted_digest, 'COUNT(hosts.id) as host_count').
joins(:host).group(:bootc_booted_image, :bootc_booted_digest).order(params[:order])
bootc_image_map = Hash.new { |h, k| h[k] = [] }
aggregate_bootc_data.each do |host_image|
bootc_image_map[host_image.bootc_booted_image] << { bootc_booted_digest: host_image.bootc_booted_digest, host_count: host_image.host_count.to_i }
end
bootc_image_map
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def content_override
validate_content_overrides_enabled(override_params)
end
sync_task(::Actions::Katello::Host::UpdateContentOverrides, @host, content_override_values, false)
fetch_product_content
fetch_product_content(!params.dig(:content_overrides_search, :search).nil? && Foreman::Cast.to_bool(params.dig(:content_overrides_search, :limit_to_env)))
end

api :GET, "/hosts/:host_id/subscriptions/available_release_versions", N_("Show releases available for the content host")
Expand All @@ -203,8 +203,8 @@ def enabled_repositories

private

def fetch_product_content
content_finder = ProductContentFinder.new(:consumable => @host.subscription_facet)
def fetch_product_content(limit_to_env = false)
content_finder = ProductContentFinder.new(:match_environment => limit_to_env, :consumable => @host.subscription_facet)
content = content_finder.presenter_with_overrides(@host.subscription_facet.candlepin_consumer.content_overrides)
respond_with_template_collection("index", 'repository_sets', :collection => full_result_response(content))
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ module V2
module HttpProxiesControllerExtensions
extend ::Apipie::DSL::Concern

update_api(:create) do
update_api(:create, :show) do
param :http_proxy, Hash do
param :default_content_proxy, :bool, :required => false, :desc => N_('Set this HTTP proxy as the default content HTTP proxy')
param :content_default_http_proxy, :bool, :required => false, :desc => N_('Set this HTTP proxy as the default content HTTP proxy')
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module HttpProxiesControllerExtensions

def update_content_default_http_proxy
return unless @http_proxy.persisted?
return unless ActiveRecord::Type::Boolean.new.deserialize(params.dig('http_proxy', 'default_content'))
return unless ActiveRecord::Type::Boolean.new.deserialize(params.dig('http_proxy', 'content_default_http_proxy'))

Setting[:content_default_http_proxy] = @http_proxy.name
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ def plan(content_view_environment, options)
end

content_view_environment.activation_keys.each do |key|
plan_action(ActivationKey::Reassign, key, options[:key_content_view_id], options[:key_environment_id])
if key.multi_content_view_environment?
key.content_view_environments = key.content_view_environments - [content_view_environment]
else
plan_action(ActivationKey::Reassign, key, options[:key_content_view_id], options[:key_environment_id])
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ module Katello
module Validators
class ContentViewErratumFilterRuleValidator < ActiveModel::Validator
def validate(record)
if record.errata_id.blank? && record.start_date.blank? && record.end_date.blank? && record.types.blank?
if record.errata_id.blank? && record.start_date.blank? && record.end_date.blank? && record.types.blank? && record.allow_other_types == false
invalid_parameters = _("Invalid erratum filter rule specified, Must specify at least one of the following:" \
" 'errata_id', 'start_date', 'end_date' or 'types'")
" 'errata_id', 'start_date', 'end_date', 'types', or 'allow_other_types'")
record.errors.add(:base, invalid_parameters)
return
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/katello/activation_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def self.in_environments(envs)
def content_view_environments=(new_cves)
if new_cves.length > 1 && !Setting['allow_multiple_content_views']
fail ::Katello::Errors::MultiEnvironmentNotSupportedError,
_("Assigning an activation key to multiple content view environments is not enabled.")
_("Assigning an activation key to multiple content view environments is not enabled. To enable, set the allow_multiple_content_views setting.")
end
super(new_cves)
Katello::ContentViewEnvironmentActivationKey.reprioritize_for_activation_key(self, new_cves)
Expand Down
4 changes: 4 additions & 0 deletions app/models/katello/concerns/http_proxy_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ def name_and_url
uri.user = nil
"#{name} (#{uri})"
end

def content_default_http_proxy?
Setting[:content_default_http_proxy] == name
end
end
end
end
14 changes: 14 additions & 0 deletions app/models/katello/concerns/smart_proxy_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def refresh
before_create :associate_default_locations
before_create :associate_lifecycle_environments
before_validation :set_default_download_policy
after_update :refresh_smart_proxy_sync_histories

lazy_accessor :pulp_repositories, :initializer => lambda { |_s| pulp_node.extensions.repository.retrieve_all }

Expand Down Expand Up @@ -471,6 +472,9 @@ def add_lifecycle_environment(environment)
end

def remove_lifecycle_environment(environment)
smart_proxy_helper = ::Katello::SmartProxyHelper.new(self)
repos = smart_proxy_helper.repositories_available_to_capsule(environment)
smart_proxy_helper.clear_smart_proxy_sync_histories(repos) unless repos.empty?
self.lifecycle_environments.find(environment.id)
unless self.lifecycle_environments.destroy(environment)
fail _("Could not remove the lifecycle environment from the smart proxy")
Expand All @@ -479,6 +483,16 @@ def remove_lifecycle_environment(environment)
raise _("Lifecycle environment was not attached to the smart proxy; therefore, no changes were made.")
end

def refresh_smart_proxy_sync_histories
smart_proxy_helper = ::Katello::SmartProxyHelper.new(self)
repos = smart_proxy_helper.repositories_available_to_capsule.select(:id)
if repos.size == 0
self.smart_proxy_sync_histories.delete_all
else
self.smart_proxy_sync_histories.where.not(repository_id: repos).delete_all
end
end

def available_lifecycle_environments(organization_id = nil)
scope = Katello::KTEnvironment.not_in_capsule(self)
scope = scope.where(organization_id: organization_id) if organization_id
Expand Down
20 changes: 18 additions & 2 deletions app/models/katello/content_view_erratum_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,21 @@ def erratum_arel
end

def types_clause
# Create an array to store output clauses for quick type filtering later
conditions = []

# Add clauses for types in the filter
types = erratum_rules.first.types
return if types.blank?
errata_types_in(types)
conditions << errata_types_in(types) unless types.blank?

# Add clauses for 'other' types
conditions << errata_types_not_in(Erratum::TYPES) if erratum_rules.first.allow_other_types?

# Reduce the array of clauses to a single clause and return
return if conditions.empty?
conditions.reduce(nil) do |combined_clause, condition|
combined_clause ? combined_clause.or(condition) : condition
end
end

def filter_by_id?
Expand All @@ -105,6 +117,10 @@ def errata_types_in(types)
erratum_arel[:errata_type].in(types)
end

def errata_types_not_in(types)
erratum_arel[:errata_type].not_in(types)
end

def errata_in(ids)
erratum_arel[:errata_id].in(ids)
end
Expand Down
10 changes: 8 additions & 2 deletions app/models/katello/erratum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,14 @@ class Erratum < Katello::Model
:validator => ->(value) { ['true', 'false'].include?(value.downcase) },
:operators => ["="]

def self.of_type(type)
where(:errata_type => type)
def self.of_type(type, include_other = false)
if include_other
where.not(
:errata_type => [Erratum::SECURITY, Erratum::BUGZILLA, Erratum::ENHANCEMENT].flatten
).or(where(:errata_type => type))
else
where(:errata_type => type)
end
end

scope :security, -> { of_type(Erratum::SECURITY) }
Expand Down
4 changes: 2 additions & 2 deletions app/models/katello/host/content_facet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class ContentFacet < Katello::Model
validates_associated :content_view_environment_content_facets, :message => _("invalid: The content source must sync the lifecycle environment assigned to the host. See the logs for more information.")
validates :host, :presence => true, :allow_blank => false
validates :bootc_booted_digest, :bootc_available_digest, :bootc_staged_digest, :bootc_rollback_digest,
format: { with: /\Asha256:[A-Fa-f0-9]{64}\z/, message: "must be a valid sha256 digest", allow_nil: true }
format: { with: /\Asha256:[A-Fa-f0-9]{64}\z/, message: "must be a valid sha256 digest", allow_blank: true }

scope :with_environments, ->(lifecycle_environments) do
joins(:content_view_environment_content_facets => :content_view_environment).
Expand Down Expand Up @@ -136,7 +136,7 @@ def single_lifecycle_environment
def content_view_environments=(new_cves)
if new_cves.length > 1 && !Setting['allow_multiple_content_views']
fail ::Katello::Errors::MultiEnvironmentNotSupportedError,
_("Assigning a host to multiple content view environments is not enabled.")
_("Assigning a host to multiple content view environments is not enabled. To enable, set the allow_multiple_content_views setting.")
end
super(new_cves)
Katello::ContentViewEnvironmentContentFacet.reprioritize_for_content_facet(self, new_cves)
Expand Down
Loading

0 comments on commit fcced92

Please sign in to comment.