app/controllers/katello/api/v2/repositories_controller.rb in katello-4.6.2.1 vs app/controllers/katello/api/v2/repositories_controller.rb in katello-4.7.0.rc1

- old
+ new

@@ -79,11 +79,11 @@ end def_param_group :repo_create do param :label, String, :required => false param :product_id, :number, :required => true, :desc => N_("Product the repository belongs to") - param :content_type, RepositoryTypeManager.creatable_repository_types(false).keys, :required => true, :desc => N_("type of repo") + param :content_type, String, :required => true, :desc => N_("Type of repository. Available types endpoint: /katello/api/repositories/repository_types") end api :GET, "/repositories", N_("List of enabled repositories") api :GET, "/content_views/:id/repositories", N_("List of repositories for a content view") api :GET, "/organizations/:organization_id/repositories", N_("List of repositories in an organization") @@ -100,22 +100,32 @@ param :rpm_id, String, :desc => N_("Id of a rpm package to find repositories that contain the rpm") param :file_id, String, :desc => N_("Id of a file to find repositories that contain the file") param :ansible_collection_id, String, :desc => N_("Id of an ansible collection to find repositories that contain the ansible collection") param :library, :bool, :desc => N_("show repositories in Library and the default content view") param :archived, :bool, :desc => N_("show archived repositories") - param :content_type, RepositoryTypeManager.defined_repository_types.keys, :desc => N_("limit to only repositories of this type") + param :content_type, String, :desc => N_("Limit the repository type. Available types endpoint: /katello/api/repositories/repository_types") param :name, String, :desc => N_("name of the repository"), :required => false param :label, String, :desc => N_("label of the repository"), :required => false param :description, String, :desc => N_("description of the repository") param :available_for, String, :desc => N_("interpret specified object to return only Repositories that can be associated with specified object. Only 'content_view' & 'content_view_version' are supported."), :required => false - param :with_content, RepositoryTypeManager.enabled_content_types(false), :desc => N_("only repositories having at least one of the specified content type ex: rpm , erratum") + param :with_content, String, :desc => N_("Filter repositories by content unit type (erratum, docker_tag, etc.). Check the \"Indexed?\" types here: /katello/api/repositories/repository_types") param :download_policy, ::Katello::RootRepository::DOWNLOAD_POLICIES, :desc => N_("limit to only repositories with this download policy") param :username, String, :desc => N_("only show the repositories readable by this user with this username") param_group :search, Api::V2::ApiController add_scoped_search_description_for(Repository) def index + unless params[:content_type].empty? || RepositoryTypeManager.find(params[:content_type]) + msg = _("Invalid params provided - content_type must be one of %s") % + RepositoryTypeManager.enabled_repository_types.keys.sort.join(",") + fail HttpErrors::UnprocessableEntity, msg + end + unless params[:with_content].empty? || RepositoryTypeManager.find_content_type(params[:with_content], true) + msg = _("Invalid params provided - with_content must be one of %s") % + RepositoryTypeManager.indexable_content_types.map(&:label).sort.join(",") + fail HttpErrors::UnprocessableEntity, msg + end base_args = [index_relation.distinct, :name, :asc] options = {:includes => [:environment, {:root => [:gpg_key, :product]}]} respond_to do |format| format.csv do @@ -222,20 +232,65 @@ end query end + api :GET, "/repositories/compare/", N_("List :resource") + param :content_view_version_ids, Array, :desc => N_("content view versions to compare") + param :repository_id, :number, :desc => N_("Library repository id to restrict comparisons to") + param :restrict_comparison, String, :desc => N_("Return same, different or all results") + + def compare + fail _("No content_view_version_ids provided") if params[:content_view_version_ids].empty? + @versions = ContentViewVersion.readable.where(:id => params[:content_view_version_ids]) + if @versions.count != params[:content_view_version_ids].uniq.length + missing = params[:content_view_version_ids] - @versions.pluck(:id) + fail HttpErrors::NotFound, _("Couldn't find content view versions '%s'") % missing.join(',') + end + + archived_version_repos = Katello::Repository.where(:content_view_version_id => @versions&.pluck(:id))&.archived + repos = Katello::Repository.where(id: archived_version_repos&.pluck(:library_instance_id)) + repos = repos.where(:root_id => @repo.root_id) if @repo + repositories = restrict_comparison(repos, @versions, params[:restrict_comparison]) + collection = scoped_search(repositories.distinct, :name, :asc) + collection[:results] = collection[:results].map { |item| ContentViewVersionComparePresenter.new(item, @versions, @repo) } + respond_for_index(:collection => collection) + end + + def restrict_comparison(collection, content_view_versions = nil, compare = 'all') + case compare + when 'same' + same_repo_ids = compare_same(collection, content_view_versions) + collection.where(id: same_repo_ids) + when 'different' + same_repo_ids = compare_same(collection, content_view_versions) + collection.where.not(id: same_repo_ids) + else + collection + end + end + + def compare_same(collection, content_view_versions = nil) + same_repo_ids = [] + collection.each do |repo| + if (content_view_versions&.pluck(:id)&.- repo.published_in_versions&.pluck(:id))&.empty? + same_repo_ids << repo.id + end + end + same_repo_ids + end + api :POST, "/repositories", N_("Create a custom repository") param :name, String, :desc => N_("Name of the repository"), :required => true param :description, String, :desc => N_("Description of the repository"), :required => false param_group :repo_create param_group :repo def create repo_params = repository_params unless RepositoryTypeManager.creatable_by_user?(repo_params[:content_type], false) msg = _("Invalid params provided - content_type must be one of %s") % - RepositoryTypeManager.creatable_repository_types(false).keys.join(",") + RepositoryTypeManager.creatable_repository_types.keys.sort.join(",") fail HttpErrors::UnprocessableEntity, msg end if !repo_params[:url].nil? && URI(repo_params[:url]).userinfo fail "Do not include the username/password in the URL. Use the username/password settings instead." @@ -372,22 +427,27 @@ api :PUT, "/repositories/:id/remove_docker_manifests" api :PUT, "/repositories/:id/remove_content" desc "Remove content from a repository" param :id, :number, :required => true, :desc => "repository ID" param 'ids', Array, :required => true, :desc => "Array of content ids to remove" - param :content_type, RepositoryTypeManager.removable_content_types(false).map(&:label), :required => false, :desc => N_("content type ('deb', 'docker_manifest', 'file', 'ostree', 'rpm', 'srpm')") + param :content_type, String, :required => false, :desc => N_("The type of content to remove (srpm, docker_manifest, etc.). Check removable types here: /katello/api/repositories/repository_types") param 'sync_capsule', :bool, :desc => N_("Whether or not to sync an external capsule after upload. Default: true") def remove_content + unless params[:content_type].empty? || RepositoryTypeManager.removable_content_types.map(&:label).include?(params[:content_type]) + msg = _("Invalid params provided - content_type must be one of %s") % + RepositoryTypeManager.removable_content_types.map(&:label).sort.join(",") + fail HttpErrors::UnprocessableEntity, msg + end sync_capsule = ::Foreman::Cast.to_bool(params.fetch(:sync_capsule, true)) fail _("No content ids provided") if @content.blank? respond_for_async :resource => sync_task(::Actions::Katello::Repository::RemoveContent, @repository, @content, content_type: params[:content_type], sync_capsule: sync_capsule) end api :POST, "/repositories/:id/upload_content", N_("Upload content into the repository") param :id, :number, :required => true, :desc => N_("repository ID") param :content, File, :required => true, :desc => N_("Content files to upload. Can be a single file or array of files.") - param :content_type, RepositoryTypeManager.uploadable_content_types(false).map(&:label), :required => false, :desc => N_("content type ('deb', 'docker_manifest', 'file', 'ostree', 'rpm', 'srpm')") + param :content_type, String, :required => false, :desc => N_("The type of content to upload (srpm, file, etc.). Check uploadable types here: /katello/api/repositories/repository_types") def upload_content fail Katello::Errors::InvalidRepositoryContent, _("Cannot upload Container Image content.") if @repository.docker? fail Katello::Errors::InvalidRepositoryContent, _("Cannot upload Ansible collections.") if @repository.ansible_collection? unless params[:content_type].empty? || RepositoryTypeManager.uploadable_content_types.map(&:label).include?(params[:content_type]) msg = _("Invalid params provided - content_type must be one of %s") % @@ -424,11 +484,11 @@ param :uploads, Array, :desc => N_("Array of uploads to import") do param 'id', String, :required => true param 'content_unit_id', String param 'size', String param 'checksum', String - param 'name', String, :desc => N_("Needs to only be set for file repositories or docker tags") + param 'name', String, :desc => N_("Needs to only be set for file repositories or docker tags"), :required => true param 'digest', String, :desc => N_("Needs to only be set for docker tags") end Katello::RepositoryTypeManager.generic_repository_types.each_pair do |_, repo_type| repo_type.import_attributes.each do |import_attribute| param import_attribute.api_param, import_attribute.type, @@ -445,10 +505,18 @@ uploads = (params[:uploads] || []).map do |upload| upload.permit(:id, :content_unit_id, :size, :checksum, :name, :digest).to_h end + if @repository.content_type != 'docker' && uploads.first['checksum'].nil? + fail HttpErrors::BadRequest, _('Checksum is a required parameter.') + end + + if uploads.first['name'].nil? + fail HttpErrors::BadRequest, _('Name is a required parameter.') + end + begin upload_args = { content_type: params[:content_type], generate_metadata: generate_metadata, sync_capsule: sync_capsule @@ -596,11 +664,11 @@ end # rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength def handle_mirror_on_sync(repo_params) if !repo_params.key?(:mirroring_policy) && repo_params.key?(:mirror_on_sync) - ::Foreman::Deprecation.api_deprecation_warning("mirror_on_sync is deprecated in favor of mirroring_policy. It will be removed in Katello 4.6.") + ::Foreman::Deprecation.api_deprecation_warning("mirror_on_sync is deprecated in favor of mirroring_policy. It will be removed in Katello 4.8.") if ::Foreman::Cast.to_bool(repo_params[:mirror_on_sync]) repo_params[:mirroring_policy] = Katello::RootRepository::MIRRORING_POLICY_CONTENT else repo_params[:mirroring_policy] = Katello::RootRepository::MIRRORING_POLICY_ADDITIVE end @@ -662,15 +730,13 @@ end query end def generic_remote_options_hash(repo_params) - generic_remote_options = {} content_type = @repository&.content_type || repo_params[:content_type] - RepositoryTypeManager.generic_remote_options(content_type: content_type).each do |option| - generic_remote_options[option.name] = repo_params[option.name] + RepositoryTypeManager.generic_remote_options(content_type: content_type).to_h do |option| + [option.name, repo_params[option.name].nil? ? option&.default : repo_params[option.name]] end - generic_remote_options end def generic_content_type_import_upload_args args = {} @repository.repository_type&.import_attributes&.collect do |import_attribute|