summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Thomas <nick@gitlab.com>2018-09-28 14:50:26 +0100
committerNick Thomas <nick@gitlab.com>2018-09-28 14:50:26 +0100
commit7f1098a1d9fd79b394b53b0c43fcc4741349d43a (patch)
treec31273b3b1a49c73c6c19ab2c008230e2d488b5a
parentc37020bb5ae66bfb7596e2b1b4f7b5c79203ecf3 (diff)
downloadgitlab-shell-7f1098a1d9fd79b394b53b0c43fcc4741349d43a.tar.gz
Specify a richer scheme to run the migration with
-rw-r--r--config.yml.example8
-rw-r--r--go/cmd/gitlab-shell/main.go43
-rw-r--r--go/internal/config/config.go13
-rw-r--r--go/internal/config/config_test.go24
4 files changed, 60 insertions, 28 deletions
diff --git a/config.yml.example b/config.yml.example
index 49f5d78..3d3e580 100644
--- a/config.yml.example
+++ b/config.yml.example
@@ -50,5 +50,9 @@ log_level: INFO
# incurs an extra API call on every gitlab-shell command.
audit_usernames: false
-# Feature flag: go or ruby
-experimental: false
+# Migration to Go: anything listed here has two implementations. Use these flags
+# to try the new implementations out, or to revert to the old behaviour if there
+# problems arise.
+migration:
+ enabled: false
+ features: []
diff --git a/go/cmd/gitlab-shell/main.go b/go/cmd/gitlab-shell/main.go
index 53632a1..44384ab 100644
--- a/go/cmd/gitlab-shell/main.go
+++ b/go/cmd/gitlab-shell/main.go
@@ -9,28 +9,41 @@ import (
"gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
)
-func experiment() {
- fmt.Println("Experiment! nothing works!")
- os.Exit(1)
+func migrate(_cfg *config.Config, _args []string) (int, bool) {
+ // TODO: decide whether to handle the request in Go or not
+ return 0, false
}
-func main() {
+// rubyExec will never return. It either replaces the current process with a
+// Ruby interpreter, or outputs an error and kills the process.
+func execRuby() {
root := filepath.Dir(os.Args[0])
- ruby := filepath.Join(root, "gitlab-shell-ruby")
+ rubyCmd := filepath.Join(root, "gitlab-shell-ruby")
+ rubyArgs := os.Args[1:]
+ rubyEnv := os.Environ()
+
+ execErr := syscall.Exec(rubyCmd, rubyArgs, rubyEnv)
+ if execErr != nil {
+ fmt.Fprintf(os.Stderr, "Failed to exec(%q): %v\n", rubyCmd, execErr)
+ os.Exit(1)
+ }
+}
+
+func main() {
+ // Fall back to Ruby in case of problems reading the config, but issue a
+ // warning as this isn't something we can sustain indefinitely
config, err := config.New()
if err != nil {
- fmt.Println(err)
- os.Exit(1)
+ fmt.Fprintln(os.Stderr, "Failed to read config, falling back to gitlab-shell-ruby")
+ execRuby()
}
- if config.Experimental {
- experiment()
- } else {
- execErr := syscall.Exec(ruby, os.Args, os.Environ())
- if execErr != nil {
- fmt.Fprintf(os.Stderr, "Failed to exec(%q): %v\n", ruby, execErr)
- os.Exit(1)
- }
+ // Try to handle the command with the Go implementation
+ if exitCode, done := migrate(config, os.Args[1:]); done {
+ os.Exit(exitCode)
}
+
+ // Since a migration has not handled the command, fall back to Ruby to do so
+ execRuby()
}
diff --git a/go/internal/config/config.go b/go/internal/config/config.go
index 64822c7..4069851 100644
--- a/go/internal/config/config.go
+++ b/go/internal/config/config.go
@@ -13,11 +13,16 @@ const (
logFile = "gitlab-shell.log"
)
+type MigrationConfig struct {
+ Enabled bool `yaml:"enabled"`
+ Features []string `yaml:"features"`
+}
+
type Config struct {
- RootDir string
- LogFile string `yaml:"log_file"`
- LogFormat string `yaml:"log_format"`
- Experimental bool `yaml:"experimental"`
+ RootDir string
+ LogFile string `yaml:"log_file"`
+ LogFormat string `yaml:"log_format"`
+ Migration MigrationConfig `yaml:"migration"`
}
func New() (*Config, error) {
diff --git a/go/internal/config/config_test.go b/go/internal/config/config_test.go
index 552a600..368ab29 100644
--- a/go/internal/config/config_test.go
+++ b/go/internal/config/config_test.go
@@ -2,22 +2,28 @@ package config
import (
"fmt"
+ "strings"
"testing"
)
func TestConfigLogFile(t *testing.T) {
testRoot := "/foo/bar"
testCases := []struct {
- yaml string
- path string
- format string
- experimental bool
+ yaml string
+ path string
+ format string
+ migration MigrationConfig
}{
{path: "/foo/bar/gitlab-shell.log", format: "text"},
{yaml: "log_file: my-log.log", path: "/foo/bar/my-log.log", format: "text"},
{yaml: "log_file: /qux/my-log.log", path: "/qux/my-log.log", format: "text"},
{yaml: "log_format: json", path: "/foo/bar/gitlab-shell.log", format: "json"},
- {yaml: "experimental: true", path: "/foo/bar/gitlab-shell.log", format: "text", experimental: true},
+ {
+ yaml: "migration:\n enabled: true\n features:\n - foo\n - bar",
+ path: "/foo/bar/gitlab-shell.log",
+ format: "text",
+ migration: MigrationConfig{Enabled: true, Features: []string{"foo", "bar"}},
+ },
}
for _, tc := range testCases {
@@ -27,8 +33,12 @@ func TestConfigLogFile(t *testing.T) {
t.Fatal(err)
}
- if cfg.Experimental != tc.experimental {
- t.Fatalf("expected %v, got %v", tc.experimental, cfg.Experimental)
+ if cfg.Migration.Enabled != tc.migration.Enabled {
+ t.Fatalf("migration.enabled: expected %v, got %v", tc.migration.Enabled, cfg.Migration.Enabled)
+ }
+
+ if strings.Join(cfg.Migration.Features, ":") != strings.Join(tc.migration.Features, ":") {
+ t.Fatalf("migration.features: expected %#v, got %#v", tc.migration.Features, cfg.Migration.Features)
}
if cfg.LogFile != tc.path {