2021-05-28 09:10:41 +00:00
# frozen_string_literal: true
###
# API endpoints for the Helm package registry
module API
class HelmPackages < :: API :: Base
helpers :: API :: Helpers :: PackagesHelpers
helpers :: API :: Helpers :: Packages :: BasicAuthHelpers
include :: API :: Helpers :: Authentication
feature_category :package_registry
2022-05-06 21:08:35 +00:00
urgency :low
2021-05-28 09:10:41 +00:00
2021-07-07 21:08:10 +00:00
PACKAGE_FILENAME = 'package.tgz'
2021-10-05 09:12:23 +00:00
HELM_REQUIREMENTS = {
channel : API :: NO_SLASH_URL_PART_REGEX ,
2021-05-28 09:10:41 +00:00
file_name : API :: NO_SLASH_URL_PART_REGEX
} . freeze
content_type :binary , 'application/octet-stream'
2021-06-25 12:07:44 +00:00
content_type :yaml , 'text/yaml'
formatter :yaml , - > ( object , _ ) { object . serializable_hash . stringify_keys . to_yaml }
2021-05-28 09:10:41 +00:00
authenticate_with do | accept |
accept . token_types ( :personal_access_token , :deploy_token , :job_token )
. sent_through ( :http_basic_auth )
end
before do
require_packages_enabled!
end
params do
requires :id , type : String , desc : 'The ID or full path of a project'
end
resource :projects , requirements : API :: NAMESPACE_OR_PROJECT_REQUIREMENTS do
2021-10-05 09:12:23 +00:00
namespace ':id/packages/helm' , requirements : HELM_REQUIREMENTS do
2021-06-25 12:07:44 +00:00
desc 'Download a chart index' do
detail 'This feature was introduced in GitLab 14.0'
end
params do
requires :channel , type : String , desc : 'Helm channel' , regexp : Gitlab :: Regex . helm_channel_regex
end
get " :channel/index.yaml " do
2022-10-17 12:10:08 +00:00
project = authorized_user_project ( action : :read_package )
authorize_read_package! ( project )
2021-06-25 12:07:44 +00:00
2022-10-17 12:10:08 +00:00
packages = Packages :: Helm :: PackagesFinder . new ( project , params [ :channel ] ) . execute
2021-06-25 12:07:44 +00:00
env [ 'api.format' ] = :yaml
2021-09-14 12:10:35 +00:00
present :: Packages :: Helm :: IndexPresenter . new ( params [ :id ] , params [ :channel ] , packages ) ,
2021-06-25 12:07:44 +00:00
with : :: API :: Entities :: Helm :: Index
end
2021-05-28 09:10:41 +00:00
desc 'Download a chart' do
detail 'This feature was introduced in GitLab 14.0'
end
params do
requires :channel , type : String , desc : 'Helm channel' , regexp : Gitlab :: Regex . helm_channel_regex
requires :file_name , type : String , desc : 'Helm package file name'
end
2021-10-05 09:12:23 +00:00
get " :channel/charts/:file_name.tgz " do
2022-10-17 12:10:08 +00:00
project = authorized_user_project ( action : :read_package )
authorize_read_package! ( project )
2021-05-28 09:10:41 +00:00
2022-10-17 12:10:08 +00:00
package_file = Packages :: Helm :: PackageFilesFinder . new ( project , params [ :channel ] , file_name : " #{ params [ :file_name ] } .tgz " ) . most_recent!
2021-05-28 09:10:41 +00:00
2022-10-17 12:10:08 +00:00
track_package_event ( 'pull_package' , :helm , project : project , namespace : project . namespace )
2021-05-28 09:10:41 +00:00
2022-09-14 18:12:48 +00:00
present_package_file! ( package_file )
2021-05-28 09:10:41 +00:00
end
2021-07-07 21:08:10 +00:00
desc 'Authorize a chart upload from workhorse' do
detail 'This feature was introduced in GitLab 14.0'
end
params do
requires :channel , type : String , desc : 'Helm channel' , regexp : Gitlab :: Regex . helm_channel_regex
end
post " api/:channel/charts/authorize " do
authorize_workhorse! (
subject : authorized_user_project ,
has_length : false ,
maximum_size : authorized_user_project . actual_limits . helm_max_file_size
)
end
desc 'Upload a chart' do
detail 'This feature was introduced in GitLab 14.0'
end
params do
requires :channel , type : String , desc : 'Helm channel' , regexp : Gitlab :: Regex . helm_channel_regex
2022-10-18 18:09:22 +00:00
requires :chart , type : :: API :: Validations :: Types :: WorkhorseFile , desc : 'The chart file to be published (generated by Multipart middleware)' , documentation : { type : 'file' }
2021-07-07 21:08:10 +00:00
end
post " api/:channel/charts " do
authorize_upload! ( authorized_user_project )
bad_request! ( 'File is too large' ) if authorized_user_project . actual_limits . exceeded? ( :helm_max_file_size , params [ :chart ] . size )
package = :: Packages :: CreateTemporaryPackageService . new (
authorized_user_project , current_user , declared_params . merge ( build : current_authenticated_job )
) . execute ( :helm , name : :: Packages :: Helm :: TEMPORARY_PACKAGE_NAME )
chart_params = {
2022-08-11 00:09:45 +00:00
file : params [ :chart ] ,
2021-07-07 21:08:10 +00:00
file_name : PACKAGE_FILENAME
}
chart_package_file = :: Packages :: CreatePackageFileService . new (
package , chart_params . merge ( build : current_authenticated_job )
) . execute
track_package_event ( 'push_package' , :helm , project : authorized_user_project , namespace : authorized_user_project . namespace )
:: Packages :: Helm :: ExtractionWorker . perform_async ( params [ :channel ] , chart_package_file . id ) # rubocop:disable CodeReuse/Worker
created!
rescue ObjectStorage :: RemoteStoreError = > e
Gitlab :: ErrorTracking . track_exception ( e , extra : { channel : params [ :channel ] , project_id : authorized_user_project . id } )
forbidden!
end
2021-05-28 09:10:41 +00:00
end
end
end
end