129 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| require_dependency 'api/validations/validators/limit'
 | |
| 
 | |
| module API
 | |
|   module Terraform
 | |
|     class State < Grape::API::Instance
 | |
|       include ::Gitlab::Utils::StrongMemoize
 | |
| 
 | |
|       default_format :json
 | |
| 
 | |
|       before do
 | |
|         authenticate!
 | |
|         authorize! :read_terraform_state, user_project
 | |
|       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'
 | |
|           route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
 | |
|           get do
 | |
|             remote_state_handler.find_with_lock do |state|
 | |
|               no_content! unless state.file.exists?
 | |
| 
 | |
|               env['api.format'] = :binary # this bypasses json serialization
 | |
|               body state.file.read
 | |
|               status :ok
 | |
|             end
 | |
|           end
 | |
| 
 | |
|           desc 'Add a new terraform state or update an existing one'
 | |
|           route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
 | |
|           post do
 | |
|             authorize! :admin_terraform_state, user_project
 | |
| 
 | |
|             data = request.body.read
 | |
|             no_content! if data.empty?
 | |
| 
 | |
|             remote_state_handler.handle_with_lock do |state|
 | |
|               state.file = CarrierWaveStringFile.new(data)
 | |
|               state.save!
 | |
|               status :ok
 | |
|             end
 | |
|           end
 | |
| 
 | |
|           desc 'Delete a terraform state of a certain name'
 | |
|           route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
 | |
|           delete do
 | |
|             authorize! :admin_terraform_state, user_project
 | |
| 
 | |
|             remote_state_handler.handle_with_lock do |state|
 | |
|               state.destroy!
 | |
|               status :ok
 | |
|             end
 | |
|           end
 | |
| 
 | |
|           desc 'Lock a terraform state of a certain name'
 | |
|           route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
 | |
|           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
 | |
|             authorize! :admin_terraform_state, user_project
 | |
| 
 | |
|             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'
 | |
|           route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
 | |
|           params do
 | |
|             optional :ID, type: String, limit: 255, desc: 'Terraform state lock ID'
 | |
|           end
 | |
|           delete '/lock' do
 | |
|             authorize! :admin_terraform_state, user_project
 | |
| 
 | |
|             remote_state_handler.unlock!
 | |
|             status :ok
 | |
|           rescue ::Terraform::RemoteStateHandler::StateLockedError
 | |
|             status :conflict
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end
 |