Commit 9dacf17d authored by Steve Abrams's avatar Steve Abrams Committed by Thong Kuah

Conan download_urls endpoints

Endpoints that return the file download urls for
conan package files to the conan client.
parent a48a780d
# frozen_string_literal: true
# Conan Package Manager Client API
#
# These API endpoints are not consumed directly by users, so there is no documentation for the
# individual endpoints. They are called by the Conan package manager client when users run commands
# like `conan install` or `conan upload`. The usage of the GitLab Conan repository is documented here:
# https://docs.gitlab.com/ee/user/packages/conan_repository/#installing-a-package
#
# Technical debt: https://gitlab.com/gitlab-org/gitlab/issues/35798
module API
class ConanPackages < Grape::API
helpers ::API::Helpers::PackagesHelpers
......@@ -108,26 +116,34 @@ module API
detail 'This feature was introduced in GitLab 12.5'
end
get 'packages/:conan_package_reference/digest' do
authorize!(:read_package, project)
presenter = ConanPackagePresenter.new(recipe, current_user, project)
render_api_error!("No recipe manifest found", 404) if presenter.package_urls.empty?
present presenter, with: EE::API::Entities::ConanPackage::ConanPackageManifest
present_package_download_urls
end
desc 'Recipe Digest' do
detail 'This feature was introduced in GitLab 12.5'
end
get 'digest' do
authorize!(:read_package, project)
presenter = ConanPackagePresenter.new(recipe, current_user, project)
present_recipe_download_urls
end
render_api_error!("No recipe manifest found", 404) if presenter.recipe_urls.empty?
# Get the download urls
#
# returns the download urls for the existing recipe or package in the registry
#
# the manifest is a hash of { filename: url }
# where the url is the download url for the file
desc 'Package Download Urls' do
detail 'This feature was introduced in GitLab 12.5'
end
get 'packages/:conan_package_reference/download_urls' do
present_package_download_urls
end
present presenter, with: EE::API::Entities::ConanPackage::ConanRecipeManifest
desc 'Recipe Download Urls' do
detail 'This feature was introduced in GitLab 12.5'
end
get 'download_urls' do
present_recipe_download_urls
end
# Get the upload urls
......@@ -205,6 +221,26 @@ module API
include Gitlab::Utils::StrongMemoize
include ::API::Helpers::RelatedResourcesHelpers
def present_package_download_urls
authorize!(:read_package, project)
presenter = ConanPackagePresenter.new(recipe, current_user, project)
render_api_error!("No recipe manifest found", 404) if presenter.package_urls.empty?
present presenter, with: EE::API::Entities::ConanPackage::ConanPackageManifest
end
def present_recipe_download_urls
authorize!(:read_package, project)
presenter = ConanPackagePresenter.new(recipe, current_user, project)
render_api_error!("No recipe manifest found", 404) if presenter.recipe_urls.empty?
present presenter, with: EE::API::Entities::ConanPackage::ConanRecipeManifest
end
def recipe_upload_urls(file_names)
{ upload_urls: Hash[
file_names.collect do |file_name|
......
......@@ -234,10 +234,45 @@ describe API::ConanPackages do
end
end
shared_examples 'recipe download_urls' do
let(:recipe_path) { package.conan_recipe_path }
it 'returns the download_urls for the recipe files' do
expected_response = {
'conanfile.py' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanfile.py",
'conanmanifest.txt' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
}
allow(presenter).to receive(:recipe_urls) { expected_response }
subject
expect(json_response).to eq(expected_response)
end
end
shared_examples 'package download_urls' do
let(:recipe_path) { package.conan_recipe_path }
it 'returns the download_urls for the package files' do
expected_response = {
'conaninfo.txt' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conaninfo.txt",
'conanmanifest.txt' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conanmanifest.txt",
'conan_package.tgz' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conan_package.tgz"
}
allow(presenter).to receive(:package_urls) { expected_response }
subject
expect(json_response).to eq(expected_response)
end
end
context 'recipe endpoints' do
let(:jwt) { build_jwt(personal_access_token) }
let(:headers) { build_auth_headers(jwt.encoded) }
let(:package_id) { '123456789' }
let(:conan_package_reference) { '123456789' }
let(:presenter) { double('ConanPackagePresenter') }
before do
......@@ -271,10 +306,10 @@ describe API::ConanPackages do
end
end
describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:package_id' do
describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference' do
let(:recipe_path) { package.conan_recipe_path }
subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{package_id}"), headers: headers }
subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}"), headers: headers }
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects recipe for invalid project'
......@@ -302,48 +337,31 @@ describe API::ConanPackages do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects recipe for invalid project'
context 'with existing package' do
let(:recipe_path) { package.conan_recipe_path }
it 'returns the download urls for each package file' do
expected_response = {
'conanfile.py' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanfile.py",
'conanmanifest.txt' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
}
allow(presenter).to receive(:recipe_urls) { expected_response }
subject
expect(json_response).to eq(expected_response)
end
end
it_behaves_like 'recipe download_urls'
end
describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:package_id/digest' do
subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{package_id}/digest"), headers: headers }
describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/download_urls' do
subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}/download_urls"), headers: headers }
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects recipe for invalid project'
it_behaves_like 'package download_urls'
end
context 'with existing package' do
let(:recipe_path) { package.conan_recipe_path }
it 'returns the download urls for the files' do
expected_response = {
'conaninfo.txt' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conaninfo.txt",
'conanmanifest.txt' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conanmanifest.txt",
'conan_package.tgz' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conan_package.tgz"
}
describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/download_urls' do
subject { get api("/packages/conan/v1/conans/#{recipe_path}/download_urls"), headers: headers }
allow(presenter).to receive(:package_urls) { expected_response }
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects recipe for invalid project'
it_behaves_like 'recipe download_urls'
end
subject
describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/digest' do
subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}/digest"), headers: headers }
expect(json_response).to eq(expected_response)
end
end
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects recipe for invalid project'
it_behaves_like 'package download_urls'
end
describe 'POST /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/upload_urls' do
......@@ -370,7 +388,7 @@ describe API::ConanPackages do
end
end
describe 'POST /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:package_id/upload_urls' do
describe 'POST /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/upload_urls' do
let(:recipe_path) { package.conan_recipe_path }
let(:params) do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment