2021-09-04 01:27:46 +05:30
# 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-07-16 23:28:13 +05:30
urgency :low
2021-09-04 01:27:46 +05:30
2021-09-30 23:02:18 +05:30
PACKAGE_FILENAME = 'package.tgz'
2021-11-18 22:05:49 +05:30
HELM_REQUIREMENTS = {
channel : API :: NO_SLASH_URL_PART_REGEX ,
2021-09-04 01:27:46 +05:30
file_name : API :: NO_SLASH_URL_PART_REGEX
} . freeze
content_type :binary , 'application/octet-stream'
2021-09-30 23:02:18 +05:30
content_type :yaml , 'text/yaml'
formatter :yaml , - > ( object , _ ) { object . serializable_hash . stringify_keys . to_yaml }
2021-09-04 01:27:46 +05:30
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-11-18 22:05:49 +05:30
namespace ':id/packages/helm' , requirements : HELM_REQUIREMENTS do
2021-09-30 23:02:18 +05:30
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-11-25 23:54:43 +05:30
project = authorized_user_project ( action : :read_package )
authorize_read_package! ( project )
2021-09-30 23:02:18 +05:30
2022-11-25 23:54:43 +05:30
packages = Packages :: Helm :: PackagesFinder . new ( project , params [ :channel ] ) . execute
2021-09-30 23:02:18 +05:30
env [ 'api.format' ] = :yaml
2021-11-11 11:23:49 +05:30
present :: Packages :: Helm :: IndexPresenter . new ( params [ :id ] , params [ :channel ] , packages ) ,
2021-09-30 23:02:18 +05:30
with : :: API :: Entities :: Helm :: Index
end
2021-09-04 01:27:46 +05:30
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-11-18 22:05:49 +05:30
get " :channel/charts/:file_name.tgz " do
2022-11-25 23:54:43 +05:30
project = authorized_user_project ( action : :read_package )
authorize_read_package! ( project )
2021-09-04 01:27:46 +05:30
2022-11-25 23:54:43 +05:30
package_file = Packages :: Helm :: PackageFilesFinder . new ( project , params [ :channel ] , file_name : " #{ params [ :file_name ] } .tgz " ) . most_recent!
2021-09-04 01:27:46 +05:30
2022-11-25 23:54:43 +05:30
track_package_event ( 'pull_package' , :helm , project : project , namespace : project . namespace )
2021-09-04 01:27:46 +05:30
2022-10-11 01:57:18 +05:30
present_package_file! ( package_file )
2021-09-04 01:27:46 +05:30
end
2021-09-30 23:02:18 +05:30
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-11-25 23:54:43 +05:30
requires :chart , type : :: API :: Validations :: Types :: WorkhorseFile , desc : 'The chart file to be published (generated by Multipart middleware)' , documentation : { type : 'file' }
2021-09-30 23:02:18 +05:30
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-27 11:52:29 +05:30
file : params [ :chart ] ,
2021-09-30 23:02:18 +05:30
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-09-04 01:27:46 +05:30
end
end
end
end