debian-mirror-gitlab/lib/api/terraform/state.rb

149 lines
5.3 KiB
Ruby
Raw Normal View History

2020-04-22 19:07:51 +05:30
# frozen_string_literal: true
require_dependency 'api/validations/validators/limit'
module API
module Terraform
2021-01-03 14:25:43 +05:30
class State < ::API::Base
2020-04-22 19:07:51 +05:30
include ::Gitlab::Utils::StrongMemoize
2021-01-29 00:20:46 +05:30
feature_category :infrastructure_as_code
2022-07-16 23:28:13 +05:30
urgency :low
2021-01-29 00:20:46 +05:30
2020-04-22 19:07:51 +05:30
default_format :json
2022-01-26 12:08:38 +05:30
rescue_from(
2022-07-23 23:45:48 +05:30
::Terraform::RemoteStateHandler::StateDeletedError,
2022-01-26 12:08:38 +05:30
::ActiveRecord::RecordNotUnique,
::PG::UniqueViolation
) do |e|
render_api_error!(e.message, 422)
end
2020-04-22 19:07:51 +05:30
before do
authenticate!
2020-07-28 23:09:34 +05:30
authorize! :read_terraform_state, user_project
2021-03-08 18:12:59 +05:30
increment_unique_values('p_terraform_state_api_unique_users', current_user.id)
2022-07-23 23:45:48 +05:30
if Feature.enabled?(:route_hll_to_snowplow_phase2, user_project&.namespace)
Gitlab::Tracking.event('API::Terraform::State', 'p_terraform_state_api_unique_users',
namespace: user_project&.namespace, user: current_user)
end
2020-04-22 19:07:51 +05:30
end
params do
requires :id, type: String, desc: 'The ID of a project'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
namespace ':id/terraform/state/:name' do
params do
requires :name, type: String, desc: 'The name of a Terraform state'
optional :ID, type: String, limit: 255, desc: 'Terraform state lock ID'
end
helpers do
def remote_state_handler
::Terraform::RemoteStateHandler.new(user_project, current_user, name: params[:name], lock_id: params[:ID])
end
end
desc 'Get a terraform state by its name'
2020-06-23 00:09:42 +05:30
route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
2020-04-22 19:07:51 +05:30
get do
remote_state_handler.find_with_lock do |state|
2020-11-24 15:15:51 +05:30
no_content! unless state.latest_file && state.latest_file.exists?
2020-04-22 19:07:51 +05:30
env['api.format'] = :binary # this bypasses json serialization
2020-11-24 15:15:51 +05:30
body state.latest_file.read
2020-04-22 19:07:51 +05:30
end
end
desc 'Add a new terraform state or update an existing one'
2020-06-23 00:09:42 +05:30
route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
2020-04-22 19:07:51 +05:30
post do
2020-07-28 23:09:34 +05:30
authorize! :admin_terraform_state, user_project
2020-05-05 14:28:15 +05:30
data = request.body.read
2020-04-22 19:07:51 +05:30
no_content! if data.empty?
remote_state_handler.handle_with_lock do |state|
2021-01-29 00:20:46 +05:30
state.update_file!(CarrierWaveStringFile.new(data), version: params[:serial], build: current_authenticated_job)
2020-04-22 19:07:51 +05:30
end
2020-11-05 12:06:23 +05:30
body false
status :ok
2020-04-22 19:07:51 +05:30
end
desc 'Delete a terraform state of a certain name'
2020-06-23 00:09:42 +05:30
route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
2020-04-22 19:07:51 +05:30
delete do
2020-07-28 23:09:34 +05:30
authorize! :admin_terraform_state, user_project
2020-04-22 19:07:51 +05:30
remote_state_handler.handle_with_lock do |state|
2022-07-23 23:45:48 +05:30
::Terraform::States::TriggerDestroyService.new(state, current_user: current_user).execute
2020-04-22 19:07:51 +05:30
end
2020-11-05 12:06:23 +05:30
body false
status :ok
2020-04-22 19:07:51 +05:30
end
desc 'Lock a terraform state of a certain name'
2020-06-23 00:09:42 +05:30
route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
2020-04-22 19:07:51 +05:30
params do
requires :ID, type: String, limit: 255, desc: 'Terraform state lock ID'
requires :Operation, type: String, desc: 'Terraform operation'
requires :Info, type: String, desc: 'Terraform info'
requires :Who, type: String, desc: 'Terraform state lock owner'
requires :Version, type: String, desc: 'Terraform version'
requires :Created, type: String, desc: 'Terraform state lock timestamp'
requires :Path, type: String, desc: 'Terraform path'
end
post '/lock' do
2020-07-28 23:09:34 +05:30
authorize! :admin_terraform_state, user_project
2020-04-22 19:07:51 +05:30
status_code = :ok
lock_info = {
'Operation' => params[:Operation],
'Info' => params[:Info],
'Version' => params[:Version],
'Path' => params[:Path]
}
begin
remote_state_handler.lock!
rescue ::Terraform::RemoteStateHandler::StateLockedError
status_code = :conflict
end
remote_state_handler.find_with_lock do |state|
lock_info['ID'] = state.lock_xid
lock_info['Who'] = state.locked_by_user.username
lock_info['Created'] = state.locked_at
env['api.format'] = :binary # this bypasses json serialization
body lock_info.to_json
status status_code
end
end
desc 'Unlock a terraform state of a certain name'
2020-06-23 00:09:42 +05:30
route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
2020-04-22 19:07:51 +05:30
params do
optional :ID, type: String, limit: 255, desc: 'Terraform state lock ID'
end
delete '/lock' do
2020-07-28 23:09:34 +05:30
authorize! :admin_terraform_state, user_project
2020-04-22 19:07:51 +05:30
remote_state_handler.unlock!
status :ok
rescue ::Terraform::RemoteStateHandler::StateLockedError
status :conflict
end
end
end
end
end
end