As we reevaluate how to best support and maintain Staging Ref in the future, we encourage development teams using this environment to highlight their use cases in the following issue: https://gitlab.com/gitlab-com/gl-infra/software-delivery/framework/software-delivery-framework-issue-tracker/-/issues/36.

Skip to content
Snippets Groups Projects
Commit 9d5b2075 authored by Bob Van Landuyt's avatar Bob Van Landuyt
Browse files

WIP: Parse commands & enable features

parent f8d74597
No related branches found
No related tags found
No related merge requests found
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
}
Loading
Loading
@@ -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
}
Loading
Loading
@@ -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()
}
Loading
Loading
@@ -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]
}
Loading
Loading
@@ -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
}
Loading
Loading
Loading
Loading
@@ -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 {
Loading
Loading
@@ -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) {
}
Loading
Loading
@@ -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)
Loading
Loading
@@ -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)
Loading
Loading
@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment