summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Van Landuyt <bob@vanlanduyt.co>2018-12-19 17:43:17 +0100
committerBob Van Landuyt <bob@vanlanduyt.co>2018-12-20 17:58:44 +0100
commit9d5b20753967c88bd76f55ecbc37e854bd3a63ce (patch)
treeca18b287c1527d60adaea38d83d4b441cfa6d1fc
parentf8d74597781f9ac9bfe2dbe6b1feacb512a52ae8 (diff)
downloadgitlab-shell-bvl-port-gitlabnet-to-go.tar.gz
WIP: Parse commands & enable featuresbvl-port-gitlabnet-to-go
-rw-r--r--go/cmd/gitlab-shell/command/command.go92
-rw-r--r--go/cmd/gitlab-shell/main.go42
-rw-r--r--go/internal/config/config.go4
-rw-r--r--go/internal/gitlabclient/client.go14
-rw-r--r--spec/gitlab_shell_gitlab_shell_spec.rb132
5 files changed, 214 insertions, 70 deletions
diff --git a/go/cmd/gitlab-shell/command/command.go b/go/cmd/gitlab-shell/command/command.go
new file mode 100644
index 0000000..c35a685
--- /dev/null
+++ b/go/cmd/gitlab-shell/command/command.go
@@ -0,0 +1,92 @@
+package command
+
+import (
+ "os"
+ "regexp"
+ "strconv"
+)
+
+type CommandType string
+
+const (
+ Discover CommandType = "discover"
+)
+
+type Command struct {
+ GitlabUsername string
+ GitlabKeyId int
+ SshConnection bool
+ Command string
+ Type CommandType
+}
+
+func New(arguments []string) (*Command, error) {
+ _, sshConnection := os.LookupEnv("SSH_CONNECTION")
+
+ command := &Command{SshConnection: sshConnection}
+
+ if _, err := parseWho(arguments, command); err != nil {
+ return nil, err
+ }
+
+ originalCommand, _ := os.LookupEnv("SSH_ORIGINAL_COMMAND")
+ parseCommand(originalCommand, command)
+
+ return command, nil
+}
+
+func parseWho(arguments []string, command *Command) (*Command, error) {
+ var err error = nil
+
+ for _, argument := range arguments {
+ keyId, err := tryParseKeyId(argument)
+ if keyId > 0 && err != nil {
+ command.GitlabKeyId = keyId
+ break
+ }
+
+ username, err := tryParseUsername(argument)
+ if username != "" && err != nil {
+ command.GitlabUsername = username
+ break
+ }
+ }
+
+ return command, err
+}
+
+func tryParseKeyId(argument string) (int, error) {
+ whoKeyRegex, err := regexp.Compile(`\bkey-(?P<keyid>\d+)\b`)
+ if err != nil {
+ return 0, err
+ }
+
+ keyMatch := whoKeyRegex.FindString(argument)
+ if keyMatch != "" {
+ gitlabKeyId, err := strconv.Atoi(keyMatch)
+
+ return gitlabKeyId, err
+ }
+
+ return 0, nil
+}
+
+func tryParseUsername(argument string) (string, error) {
+ whoUsernameRegex, err := regexp.Compile(`\busername-(?P<username>\S+)\b`)
+ if err != nil {
+ return "", err
+ }
+
+ usernameMatch := whoUsernameRegex.FindString(argument)
+ return usernameMatch, nil
+}
+
+func parseCommand(commandString string, command *Command) *Command {
+ command.Command = commandString
+
+ if commandString == "" {
+ command.Type = Discover
+ }
+
+ return nil
+}
diff --git a/go/cmd/gitlab-shell/main.go b/go/cmd/gitlab-shell/main.go
index ae54151..331e93d 100644
--- a/go/cmd/gitlab-shell/main.go
+++ b/go/cmd/gitlab-shell/main.go
@@ -6,22 +6,36 @@ import (
"path/filepath"
"syscall"
+ "gitlab.com/gitlab-org/gitlab-shell/go/cmd/gitlab-shell/command"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
)
var (
- binDir string
- rootDir string
+ binDir string
+ rootDir string
+ features map[command.CommandType]bool
)
func init() {
binDir = filepath.Dir(os.Args[0])
rootDir = filepath.Dir(binDir)
+ features = map[command.CommandType]bool{}
}
-func migrate(*config.Config) (int, bool) {
- // TODO: Dispatch appropriate requests to Go handlers and return
- // <exitstatus, true> depending on how they fare
+func migrate(config *config.Config) (int, bool) {
+ if !config.Migration.Enabled {
+ return 0, false
+ }
+ command, err := command.New(os.Args)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to build command: %v\n", err)
+ return 0, false
+ }
+
+ if featureEnabled(config, command.Type) {
+
+ }
+
return 0, false
}
@@ -42,7 +56,7 @@ func main() {
// warning as this isn't something we can sustain indefinitely
config, err := config.NewFromDir(rootDir)
if err != nil {
- fmt.Fprintln(os.Stderr, "Failed to read config, falling back to gitlab-shell-ruby")
+ fmt.Fprintf(os.Stderr, "Failed to read config, falling back to gitlab-shell-ruby: %v", err)
execRuby()
}
@@ -54,3 +68,19 @@ func main() {
// Since a migration has not handled the command, fall back to Ruby to do so
execRuby()
}
+
+func featureEnabled(config *config.Config, commandType command.CommandType) bool {
+ if features[commandType] {
+ return true
+ }
+
+ fmt.Fprintf(os.Stderr, "Config: %v", config.Migration)
+
+ for _, featureName := range config.Migration.Features {
+ fmt.Fprintf(os.Stderr, "Setting feature: %v to %v", featureName, command.CommandType(featureName))
+
+ features[command.CommandType(featureName)] = true
+ }
+
+ return features[commandType]
+}
diff --git a/go/internal/config/config.go b/go/internal/config/config.go
index d325fd4..76ba07d 100644
--- a/go/internal/config/config.go
+++ b/go/internal/config/config.go
@@ -74,7 +74,9 @@ func parseConfig(configBytes []byte, cfg *Config) error {
cfg.LogFormat = "text"
}
- baseUrl, err := url.Parse(cfg.GitlabUrl)
+ unescapedUrl, err := url.PathUnescape(cfg.GitlabUrl)
+
+ baseUrl, err := url.Parse(unescapedUrl)
if err != nil {
return err
}
diff --git a/go/internal/gitlabclient/client.go b/go/internal/gitlabclient/client.go
index c186b6c..5a8dd9d 100644
--- a/go/internal/gitlabclient/client.go
+++ b/go/internal/gitlabclient/client.go
@@ -4,7 +4,7 @@ import (
"net/http"
"time"
- "gitlab.com/gitlab-org/go/internal/config"
+ "gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
)
type Client struct {
@@ -21,20 +21,12 @@ func New() (*Client, error) {
return nil, err
}
- tr = &http.Transport{
+ tr := &http.Transport{
MaxIdleConns: 10,
IdleConnTimeout: 30 * time.Second,
DisableCompression: true,
}
- httpClient = &http.Client{Transport: tr}
+ httpClient := &http.Client{Transport: tr}
return &Client{config: config, httpClient: httpClient}, nil
}
-
-func (c *Client) Discover(gitlabId string) {
-
-}
-
-func (c *Client) get(path string) (*Response, error) {
-
-}
diff --git a/spec/gitlab_shell_gitlab_shell_spec.rb b/spec/gitlab_shell_gitlab_shell_spec.rb
index 9afeac8..398b50f 100644
--- a/spec/gitlab_shell_gitlab_shell_spec.rb
+++ b/spec/gitlab_shell_gitlab_shell_spec.rb
@@ -43,11 +43,7 @@ describe 'bin/gitlab-shell' do
sleep(0.1) while @webrick_thread.alive? && @server.status != :Running
raise "Couldn't start stub GitlabNet server" unless @server.status == :Running
-
- File.open(config_path, 'w') do |f|
- f.write("---\ngitlab_url: http+unix://#{CGI.escape(tmp_socket_path)}\n")
- end
-
+ system(original_root_path, 'bin/compile')
copy_dirs = ['bin', 'lib']
FileUtils.rm_rf(copy_dirs.map { |d| File.join(tmp_root_path, d) })
FileUtils.cp_r(copy_dirs, tmp_root_path)
@@ -61,72 +57,98 @@ describe 'bin/gitlab-shell' do
let(:gitlab_shell_path) { File.join(tmp_root_path, 'bin', 'gitlab-shell') }
- # Basic valid input
- it 'succeeds and prints username when a valid known key id is given' do
- output, status = run!(["key-100"])
+ shared_examples 'results with keys' do
+ # Basic valid input
+ it 'succeeds and prints username when a valid known key id is given' do
+ output, status = run!(["key-100"])
- expect(output).to eq("Welcome to GitLab, @someuser!\n")
- expect(status).to be_success
- end
+ expect(output).to eq("Welcome to GitLab, @someuser!\n")
+ expect(status).to be_success
+ end
- it 'succeeds and prints username when a valid known username is given' do
- output, status = run!(["username-someuser"])
+ it 'succeeds and prints username when a valid known username is given' do
+ output, status = run!(["username-someuser"])
- expect(output).to eq("Welcome to GitLab, @someuser!\n")
- expect(status).to be_success
- end
+ expect(output).to eq("Welcome to GitLab, @someuser!\n")
+ expect(status).to be_success
+ end
- # Valid but unknown input
- it 'succeeds and prints Anonymous when a valid unknown key id is given' do
- output, status = run!(["key-12345"])
+ # Valid but unknown input
+ it 'succeeds and prints Anonymous when a valid unknown key id is given' do
+ output, status = run!(["key-12345"])
- expect(output).to eq("Welcome to GitLab, Anonymous!\n")
- expect(status).to be_success
- end
+ expect(output).to eq("Welcome to GitLab, Anonymous!\n")
+ expect(status).to be_success
+ end
- it 'succeeds and prints Anonymous when a valid unknown username is given' do
- output, status = run!(["username-unknown"])
+ it 'succeeds and prints Anonymous when a valid unknown username is given' do
+ output, status = run!(["username-unknown"])
- expect(output).to eq("Welcome to GitLab, Anonymous!\n")
- expect(status).to be_success
- end
+ expect(output).to eq("Welcome to GitLab, Anonymous!\n")
+ expect(status).to be_success
+ end
- # Invalid input. TODO: capture stderr & compare
- it 'gets an ArgumentError on invalid input (empty)' do
- output, status = run!([])
+ # Invalid input. TODO: capture stderr & compare
+ it 'gets an ArgumentError on invalid input (empty)' do
+ output, status = run!([])
- expect(output).to eq("")
- expect(status).not_to be_success
- end
+ expect(output).to eq("")
+ expect(status).not_to be_success
+ end
- it 'gets an ArgumentError on invalid input (unknown)' do
- output, status = run!(["whatever"])
+ it 'gets an ArgumentError on invalid input (unknown)' do
+ output, status = run!(["whatever"])
- expect(output).to eq("")
- expect(status).not_to be_success
- end
+ expect(output).to eq("")
+ expect(status).not_to be_success
+ end
- it 'gets an ArgumentError on invalid input (multiple unknown)' do
- output, status = run!(["this", "is", "all", "invalid"])
+ it 'gets an ArgumentError on invalid input (multiple unknown)' do
+ output, status = run!(["this", "is", "all", "invalid"])
- expect(output).to eq("")
- expect(status).not_to be_success
+ expect(output).to eq("")
+ expect(status).not_to be_success
+ end
+
+ # Not so basic valid input
+ # (https://gitlab.com/gitlab-org/gitlab-shell/issues/145)
+ it 'succeeds and prints username when a valid known key id is given in the middle of other input' do
+ output, status = run!(["-c/usr/share/webapps/gitlab-shell/bin/gitlab-shell", "key-100", "2foo"])
+
+ expect(output).to eq("Welcome to GitLab, @someuser!\n")
+ expect(status).to be_success
+ end
+
+ it 'succeeds and prints username when a valid known username is given in the middle of other input' do
+ output, status = run!(["-c/usr/share/webapps/gitlab-shell/bin/gitlab-shell", "username-someuser" ,"foo"])
+
+ expect(output).to eq("Welcome to GitLab, @someuser!\n")
+ expect(status).to be_success
+ end
end
- # Not so basic valid input
- # (https://gitlab.com/gitlab-org/gitlab-shell/issues/145)
- it 'succeeds and prints username when a valid known key id is given in the middle of other input' do
- output, status = run!(["-c/usr/share/webapps/gitlab-shell/bin/gitlab-shell", "key-100", "2foo"])
+ describe 'without go features' do
+ before(:context) do
+ write_config("gitlab_url" => "http+unix://#{CGI.escape(tmp_socket_path)}")
+ end
- expect(output).to eq("Welcome to GitLab, @someuser!\n")
- expect(status).to be_success
+ it_behaves_like 'results with keys'
end
- it 'succeeds and prints username when a valid known username is given in the middle of other input' do
- output, status = run!(["-c/usr/share/webapps/gitlab-shell/bin/gitlab-shell", "username-someuser" ,"foo"])
+ describe 'with the go discover feature' do
+ before(:context) do
+ write_config(
+ "gitlab_url" => "http+unix://#{CGI.escape(tmp_socket_path)}",
+ "migration" => { "enabled" => true,
+ "features" => ["discover"] }
+ )
+ end
+
+ it 'writes the correct config' do
+ puts File.read(config_path)
+ end
- expect(output).to eq("Welcome to GitLab, @someuser!\n")
- expect(status).to be_success
+ it_behaves_like 'results with keys'
end
def run!(args)
@@ -139,4 +161,10 @@ describe 'bin/gitlab-shell' do
[output, $?]
end
+
+ def write_config(config)
+ File.open(config_path, 'w') do |f|
+ f.write(config.to_yaml)
+ end
+ end
end