summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsh McKenzie <amckenzie@gitlab.com>2018-07-25 14:15:07 +1000
committerAsh McKenzie <amckenzie@gitlab.com>2018-07-25 14:34:21 +1000
commite7a4f669e54bc097ab0ba5bcb9032a9c30978514 (patch)
treea40b531e737d0c91dbe7a60d30db8c7161e558c9
parent634a519a38784372f729b51e006f260f7143531d (diff)
downloadgitlab-shell-e7a4f669e54bc097ab0ba5bcb9032a9c30978514.tar.gz
New Action module and Action::Gitaly class
-rw-r--r--lib/action.rb5
-rw-r--r--lib/action/base.rb21
-rw-r--r--lib/action/gitaly.rb129
3 files changed, 155 insertions, 0 deletions
diff --git a/lib/action.rb b/lib/action.rb
new file mode 100644
index 0000000..cb76372
--- /dev/null
+++ b/lib/action.rb
@@ -0,0 +1,5 @@
+require_relative 'action/base'
+require_relative 'action/gitaly'
+
+module Action
+end
diff --git a/lib/action/base.rb b/lib/action/base.rb
new file mode 100644
index 0000000..5e5a2b2
--- /dev/null
+++ b/lib/action/base.rb
@@ -0,0 +1,21 @@
+require 'json'
+require_relative '../gitlab_config'
+require_relative '../current_user_helper'
+
+module Action
+ class Base
+ include CurrentUserHelper
+
+ def self.create_from_json(_)
+ raise NotImplementedError
+ end
+
+ def config
+ @config ||= GitlabConfig.new
+ end
+
+ private
+
+ attr_reader :key_id
+ end
+end
diff --git a/lib/action/gitaly.rb b/lib/action/gitaly.rb
new file mode 100644
index 0000000..a87583b
--- /dev/null
+++ b/lib/action/gitaly.rb
@@ -0,0 +1,129 @@
+require_relative 'base'
+require_relative '../gitlab_logger'
+require_relative '../gitlab_net'
+require_relative '../log_helper'
+
+module Action
+ class Gitaly < Base
+ include LogHelper
+
+ MIGRATED_COMMANDS = {
+ 'git-upload-pack' => File.join(ROOT_PATH, 'bin', 'gitaly-upload-pack'),
+ 'git-upload-archive' => File.join(ROOT_PATH, 'bin', 'gitaly-upload-archive'),
+ 'git-receive-pack' => File.join(ROOT_PATH, 'bin', 'gitaly-receive-pack')
+ }.freeze
+
+ def initialize(key_id, gl_repository, gl_username, repository_path, gitaly)
+ @key_id = key_id
+ @gl_repository = gl_repository
+ @gl_username = gl_username
+ @repository_path = repository_path
+ @gitaly = gitaly
+
+ self.repo_path = repository_path # FIXME: WTF IS THIS?
+ end
+
+ def self.create_from_json(key_id, json)
+ values = JSON.parse(json)
+ new(key_id,
+ values["gl_repository"],
+ values["gl_username"],
+ values["repository_path"],
+ values["gitaly"])
+ end
+
+ def execute(command, args)
+ process(command, args)
+ end
+
+ private
+
+ attr_reader :gl_repository, :gl_username, :repository_path, :gitaly, :repo_path
+
+ # FIXME: WTF IS THIS?
+ def repo_path=(repo_path)
+ raise ArgumentError, "Repository path not provided. Please make sure you're using GitLab v8.10 or later." unless repo_path
+ raise InvalidRepositoryPathError if File.absolute_path(repo_path) != repo_path
+
+ @repo_path = repo_path
+ end
+
+ def process(command, args)
+ executable = command
+ args = [repo_path]
+
+ if MIGRATED_COMMANDS.key?(executable) && gitaly
+ executable = MIGRATED_COMMANDS[executable]
+ gitaly_address = gitaly['address']
+
+ # The entire gitaly_request hash should be built in gitlab-ce and passed
+ # on as-is. For now we build a fake one on the spot.
+ gitaly_request = {
+ 'repository' => gitaly['repository'],
+ 'gl_repository' => gl_repository,
+ 'gl_id' => key_id,
+ 'gl_username' => gl_username
+ }
+
+ args = [gitaly_address, JSON.dump(gitaly_request)]
+ end
+
+ args_string = [File.basename(executable), *args].join(' ')
+ $logger.info('executing git command', command: args_string, user: log_username)
+
+ exec_cmd(executable, *args)
+ end
+
+ def exec_cmd(*args)
+ # If you want to call a command without arguments, use
+ # exec_cmd(['my_command', 'my_command']) . Otherwise use
+ # exec_cmd('my_command', 'my_argument', ...).
+ if args.count == 1 && !args.first.is_a?(Array)
+ raise GitlabShell::DisallowedCommandError
+ end
+
+ env = {
+ 'HOME' => ENV['HOME'],
+ 'PATH' => ENV['PATH'],
+ 'LD_LIBRARY_PATH' => ENV['LD_LIBRARY_PATH'],
+ 'LANG' => ENV['LANG'],
+ 'GL_ID' => key_id,
+ 'GL_PROTOCOL' => GitlabNet::GL_PROTOCOL,
+ 'GL_REPOSITORY' => gl_repository,
+ 'GL_USERNAME' => gl_username
+ }
+
+ if gitaly && gitaly.include?('token')
+ env['GITALY_TOKEN'] = gitaly['token']
+ end
+
+ if git_trace_available?
+ env.merge!(
+ 'GIT_TRACE' => config.git_trace_log_file,
+ 'GIT_TRACE_PACKET' => config.git_trace_log_file,
+ 'GIT_TRACE_PERFORMANCE' => config.git_trace_log_file
+ )
+ end
+
+ # We use 'chdir: ROOT_PATH' to let the next executable know where config.yml is.
+ Kernel.exec(env, *args, unsetenv_others: true, chdir: ROOT_PATH)
+ end
+
+ def git_trace_available?
+ return false unless config.git_trace_log_file
+
+ if Pathname(config.git_trace_log_file).relative?
+ $logger.warn('git trace log path must be absolute, ignoring', git_trace_log_file: config.git_trace_log_file)
+ return false
+ end
+
+ begin
+ File.open(config.git_trace_log_file, 'a') { nil }
+ return true
+ rescue => ex
+ $logger.warn('Failed to open git trace log file', git_trace_log_file: config.git_trace_log_file, error: ex.to_s)
+ return false
+ end
+ end
+ end
+end