From f55801d9017b33095fc74a9a22c15a60b265b539 Mon Sep 17 00:00:00 2001 From: Jonatan Wallmander Date: Thu, 21 Nov 2024 09:42:21 +0100 Subject: [PATCH 1/4] fix: git daemon listens only when starting it This was inconsistent with the other servers. --- pkg/daemon/daemon.go | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go index ca821d26..de65cba7 100644 --- a/pkg/daemon/daemon.go +++ b/pkg/daemon/daemon.go @@ -67,16 +67,21 @@ func NewGitDaemon(ctx context.Context) (*GitDaemon, error) { conns: connections{m: make(map[net.Conn]struct{})}, logger: log.FromContext(ctx).WithPrefix("gitdaemon"), } - listener, err := net.Listen("tcp", d.addr) - if err != nil { - return nil, err - } - d.listener = listener return d, nil } // Start starts the Git TCP daemon. func (d *GitDaemon) Start() error { + // listen on the socket + { + listener, err := net.Listen("tcp", d.addr) + if err != nil { + return err + } + d.listener = listener + } + + // close eventual connections to the socket defer d.listener.Close() // nolint: errcheck d.wg.Add(1) @@ -308,6 +313,11 @@ func (d *GitDaemon) Close() error { // Shutdown gracefully shuts down the daemon. func (d *GitDaemon) Shutdown(ctx context.Context) error { + // in the case when git daemon was never started + if d.listener == nil { + return nil + } + d.once.Do(func() { close(d.finished) }) err := d.listener.Close() finished := make(chan struct{}, 1) From 45c22b9f47419ea0686d8003b0b15327459450fc Mon Sep 17 00:00:00 2001 From: Jonatan Wallmander Date: Thu, 21 Nov 2024 09:51:10 +0100 Subject: [PATCH 2/4] fix: test framework supports ensuring specific port is open The generic "waitforserver" has been renamed to "ensureserverrunning". This command now also takes an argument which denotes which environment variable to pick the port from. This is needed as the ports are randomized by the test. --- testscript/script_test.go | 44 ++++++++++++++--------- testscript/testdata/anon-access.txtar | 4 +-- testscript/testdata/help.txtar | 4 +-- testscript/testdata/http.txtar | 4 +-- testscript/testdata/jwt.txtar | 4 +-- testscript/testdata/mirror.txtar | 4 +-- testscript/testdata/repo-blob.txtar | 4 +-- testscript/testdata/repo-collab.txtar | 4 +-- testscript/testdata/repo-commit.txtar | 4 +-- testscript/testdata/repo-create.txtar | 4 +-- testscript/testdata/repo-delete.txtar | 4 +-- testscript/testdata/repo-import.txtar | 4 +-- testscript/testdata/repo-perms.txtar | 4 +-- testscript/testdata/repo-push.txtar | 4 +-- testscript/testdata/repo-tree.txtar | 4 +-- testscript/testdata/repo-webhooks.txtar | 4 +-- testscript/testdata/set-username.txtar | 4 +-- testscript/testdata/settings.txtar | 4 +-- testscript/testdata/ssh-lfs.txtar | 4 +-- testscript/testdata/ssh.txtar | 4 +-- testscript/testdata/token.txtar | 4 +-- testscript/testdata/ui-home.txtar | 4 +-- testscript/testdata/user_management.txtar | 4 +-- 23 files changed, 71 insertions(+), 61 deletions(-) diff --git a/testscript/script_test.go b/testscript/script_test.go index 43fdde90..56437280 100644 --- a/testscript/script_test.go +++ b/testscript/script_test.go @@ -79,20 +79,20 @@ func TestScript(t *testing.T) { UpdateScripts: *update, RequireExplicitExec: true, Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){ - "soft": cmdSoft("admin", admin1.Signer()), - "usoft": cmdSoft("user1", user1.Signer()), - "git": cmdGit(admin1Key), - "ugit": cmdGit(user1Key), - "curl": cmdCurl, - "mkfile": cmdMkfile, - "envfile": cmdEnvfile, - "readfile": cmdReadfile, - "dos2unix": cmdDos2Unix, - "new-webhook": cmdNewWebhook, - "waitforserver": cmdWaitforserver, - "stopserver": cmdStopserver, - "ui": cmdUI(admin1.Signer()), - "uui": cmdUI(user1.Signer()), + "soft": cmdSoft("admin", admin1.Signer()), + "usoft": cmdSoft("user1", user1.Signer()), + "git": cmdGit(admin1Key), + "ugit": cmdGit(user1Key), + "curl": cmdCurl, + "mkfile": cmdMkfile, + "envfile": cmdEnvfile, + "readfile": cmdReadfile, + "dos2unix": cmdDos2Unix, + "new-webhook": cmdNewWebhook, + "ensureserverrunning": cmdEnsureServerRunning, + "stopserver": cmdStopserver, + "ui": cmdUI(admin1.Signer()), + "uui": cmdUI(user1.Signer()), }, Setup: func(e *testscript.Env) error { // Add binPath to PATH @@ -470,9 +470,18 @@ func cmdCurl(ts *testscript.TestScript, neg bool, args []string) { check(ts, cmd.Execute(), neg) } -func cmdWaitforserver(ts *testscript.TestScript, neg bool, args []string) { - // wait until the server is up - addr := net.JoinHostPort("localhost", ts.Getenv("SSH_PORT")) +func cmdEnsureServerRunning(ts *testscript.TestScript, neg bool, args []string) { + if len(args) < 1 { + ts.Fatalf("Must supply a TCP port of one of the services to connect to. " + + "These are set as env vars as they are randomized. " + + "Example usage: \"cmdensureserverrunning SSH_PORT\"\n" + + "Valid values for the env var: SSH_PORT|HTTP_PORT|GIT_PORT|STATS_PORT") + } + + port := ts.Getenv(args[0]) + + // verify that the server is up + addr := net.JoinHostPort("localhost", port) for { conn, _ := net.DialTimeout( "tcp", @@ -480,6 +489,7 @@ func cmdWaitforserver(ts *testscript.TestScript, neg bool, args []string) { time.Second, ) if conn != nil { + ts.Logf("Server is running on port: %s", port) conn.Close() break } diff --git a/testscript/testdata/anon-access.txtar b/testscript/testdata/anon-access.txtar index 54958fa1..c43dc23c 100644 --- a/testscript/testdata/anon-access.txtar +++ b/testscript/testdata/anon-access.txtar @@ -2,8 +2,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # set settings soft settings allow-keyless true diff --git a/testscript/testdata/help.txtar b/testscript/testdata/help.txtar index d6756ca0..299e2950 100644 --- a/testscript/testdata/help.txtar +++ b/testscript/testdata/help.txtar @@ -3,8 +3,8 @@ # start soft serve exec soft serve --sync-hooks & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT soft --help cmpenv stdout help.txt diff --git a/testscript/testdata/http.txtar b/testscript/testdata/http.txtar index 98f6902a..796c6421 100644 --- a/testscript/testdata/http.txtar +++ b/testscript/testdata/http.txtar @@ -8,8 +8,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create user soft user create user1 --key "$USER1_AUTHORIZED_KEY" diff --git a/testscript/testdata/jwt.txtar b/testscript/testdata/jwt.txtar index 7a257044..667ec798 100644 --- a/testscript/testdata/jwt.txtar +++ b/testscript/testdata/jwt.txtar @@ -2,8 +2,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create user soft user create user1 --key "$USER1_AUTHORIZED_KEY" diff --git a/testscript/testdata/mirror.txtar b/testscript/testdata/mirror.txtar index d3cc1915..76feb782 100644 --- a/testscript/testdata/mirror.txtar +++ b/testscript/testdata/mirror.txtar @@ -5,8 +5,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # import a repo soft repo import --mirror charmbracelet/catwalk https://github.com/charmbracelet/catwalk.git diff --git a/testscript/testdata/repo-blob.txtar b/testscript/testdata/repo-blob.txtar index e2712acf..685c15d8 100644 --- a/testscript/testdata/repo-blob.txtar +++ b/testscript/testdata/repo-blob.txtar @@ -5,8 +5,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create a repo soft repo create repo1 diff --git a/testscript/testdata/repo-collab.txtar b/testscript/testdata/repo-collab.txtar index d2960693..ead5fdce 100644 --- a/testscript/testdata/repo-collab.txtar +++ b/testscript/testdata/repo-collab.txtar @@ -2,8 +2,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # setup soft repo import test https://github.com/charmbracelet/catwalk.git diff --git a/testscript/testdata/repo-commit.txtar b/testscript/testdata/repo-commit.txtar index 70ca3da1..a3b61e51 100644 --- a/testscript/testdata/repo-commit.txtar +++ b/testscript/testdata/repo-commit.txtar @@ -5,8 +5,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create a repo soft repo import basic1 https://github.com/git-fixtures/basic diff --git a/testscript/testdata/repo-create.txtar b/testscript/testdata/repo-create.txtar index 7b7f12d7..2b8cf452 100644 --- a/testscript/testdata/repo-create.txtar +++ b/testscript/testdata/repo-create.txtar @@ -5,8 +5,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create a repo soft repo create repo1 -d 'description' -H -p -n 'repo11' diff --git a/testscript/testdata/repo-delete.txtar b/testscript/testdata/repo-delete.txtar index ca513e78..b9197e17 100644 --- a/testscript/testdata/repo-delete.txtar +++ b/testscript/testdata/repo-delete.txtar @@ -2,8 +2,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT soft repo create repo1 soft repo create repo-to-delete diff --git a/testscript/testdata/repo-import.txtar b/testscript/testdata/repo-import.txtar index 84d4334b..e9bfa31e 100644 --- a/testscript/testdata/repo-import.txtar +++ b/testscript/testdata/repo-import.txtar @@ -5,8 +5,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # import private soft repo import --private repo1 https://github.com/charmbracelet/catwalk.git diff --git a/testscript/testdata/repo-perms.txtar b/testscript/testdata/repo-perms.txtar index 1cc371e9..a3e4515c 100644 --- a/testscript/testdata/repo-perms.txtar +++ b/testscript/testdata/repo-perms.txtar @@ -5,8 +5,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create a repo & user1 with admin soft repo create repo1 -p diff --git a/testscript/testdata/repo-push.txtar b/testscript/testdata/repo-push.txtar index cadb735b..d9f94753 100644 --- a/testscript/testdata/repo-push.txtar +++ b/testscript/testdata/repo-push.txtar @@ -2,8 +2,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create a repo soft repo create repo-empty -d 'description' -H -p -n 'repo-empty' diff --git a/testscript/testdata/repo-tree.txtar b/testscript/testdata/repo-tree.txtar index b3e6320d..75a9978a 100644 --- a/testscript/testdata/repo-tree.txtar +++ b/testscript/testdata/repo-tree.txtar @@ -5,8 +5,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create a repo soft repo create repo1 diff --git a/testscript/testdata/repo-webhooks.txtar b/testscript/testdata/repo-webhooks.txtar index fe393a5b..6b370d31 100644 --- a/testscript/testdata/repo-webhooks.txtar +++ b/testscript/testdata/repo-webhooks.txtar @@ -2,8 +2,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create a repo soft repo create repo-123 diff --git a/testscript/testdata/set-username.txtar b/testscript/testdata/set-username.txtar index 30f1a8e0..745134c7 100644 --- a/testscript/testdata/set-username.txtar +++ b/testscript/testdata/set-username.txtar @@ -5,8 +5,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # get original username soft info diff --git a/testscript/testdata/settings.txtar b/testscript/testdata/settings.txtar index 1ceaec57..fc6bdf46 100644 --- a/testscript/testdata/settings.txtar +++ b/testscript/testdata/settings.txtar @@ -2,8 +2,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # check default allow-keyless soft settings allow-keyless true diff --git a/testscript/testdata/ssh-lfs.txtar b/testscript/testdata/ssh-lfs.txtar index fbba49d3..a647dff9 100644 --- a/testscript/testdata/ssh-lfs.txtar +++ b/testscript/testdata/ssh-lfs.txtar @@ -8,8 +8,8 @@ skip 'breaks with git-lfs 3.5.1' env SOFT_SERVE_LFS_SSH_ENABLED=true # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create a user soft user create foo --key "$USER1_AUTHORIZED_KEY" diff --git a/testscript/testdata/ssh.txtar b/testscript/testdata/ssh.txtar index 3e652aeb..e968fa63 100644 --- a/testscript/testdata/ssh.txtar +++ b/testscript/testdata/ssh.txtar @@ -4,8 +4,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create a user soft user create foo --key "$USER1_AUTHORIZED_KEY" diff --git a/testscript/testdata/token.txtar b/testscript/testdata/token.txtar index 821cea84..7a88701c 100644 --- a/testscript/testdata/token.txtar +++ b/testscript/testdata/token.txtar @@ -2,8 +2,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # create user soft user create user1 --key "$USER1_AUTHORIZED_KEY" diff --git a/testscript/testdata/ui-home.txtar b/testscript/testdata/ui-home.txtar index 0a5c04ab..126b38e7 100644 --- a/testscript/testdata/ui-home.txtar +++ b/testscript/testdata/ui-home.txtar @@ -2,8 +2,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # test repositories tab ui '" q"' diff --git a/testscript/testdata/user_management.txtar b/testscript/testdata/user_management.txtar index f6539709..233e8fd5 100644 --- a/testscript/testdata/user_management.txtar +++ b/testscript/testdata/user_management.txtar @@ -5,8 +5,8 @@ # start soft serve exec soft serve & -# wait for server to start -waitforserver +# wait for SSH server to start +ensureserverrunning SSH_PORT # add key to admin soft user add-pubkey admin "$ADMIN2_AUTHORIZED_KEY" From 58f6da48ff141f7ca84ea63dab41d9085e18bd76 Mon Sep 17 00:00:00 2001 From: Jonatan Wallmander Date: Thu, 21 Nov 2024 10:05:14 +0100 Subject: [PATCH 3/4] feat: test framework supports turning off -race flag This is useful on Windows where gcc is not always available. --- testscript/script_test.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/testscript/script_test.go b/testscript/script_test.go index 56437280..4277122f 100644 --- a/testscript/script_test.go +++ b/testscript/script_test.go @@ -34,6 +34,15 @@ var ( binPath string ) +func PrepareBuildCommand(binPath string) *exec.Cmd { + _, disableRaceSet := os.LookupEnv("DISABLE_RACE_CHECKS") + if disableRaceSet { + // don't add the -race flag + return exec.Command("go", "build", "-cover", "-o", binPath, filepath.Join("..", "cmd", "soft")) + } + return exec.Command("go", "build", "-race", "-cover", "-o", binPath, filepath.Join("..", "cmd", "soft")) +} + func TestMain(m *testing.M) { tmp, err := os.MkdirTemp("", "soft-serve*") if err != nil { @@ -48,7 +57,7 @@ func TestMain(m *testing.M) { } // Build the soft binary with -cover flag. - cmd := exec.Command("go", "build", "-race", "-cover", "-o", binPath, filepath.Join("..", "cmd", "soft")) + cmd := PrepareBuildCommand(binPath) if err := cmd.Run(); err != nil { fmt.Fprintf(os.Stderr, "failed to build soft-serve binary: %s", err) os.Exit(1) From bdd80c21ca1baddd81ead3301c1ab22980de3f2b Mon Sep 17 00:00:00 2001 From: Jonatan Wallmander Date: Thu, 14 Nov 2024 15:49:04 +0100 Subject: [PATCH 4/4] feat: support toggling servers on/off in configuration (#594) To test this, tests added: `ensureservernotrunning [SERVICE_NAME]` --- cmd/soft/serve/server.go | 73 ++++++++++++------- pkg/config/config.go | 20 +++++ testscript/script_test.go | 57 +++++++++++---- .../config-servers-git_disabled.txtar | 18 +++++ .../config-servers-http_disabled.txtar | 19 +++++ .../config-servers-ssh_disabled.txtar | 18 +++++ .../config-servers-stats_disabled.txtar | 18 +++++ 7 files changed, 181 insertions(+), 42 deletions(-) create mode 100644 testscript/testdata/config-servers-git_disabled.txtar create mode 100644 testscript/testdata/config-servers-http_disabled.txtar create mode 100644 testscript/testdata/config-servers-ssh_disabled.txtar create mode 100644 testscript/testdata/config-servers-stats_disabled.txtar diff --git a/cmd/soft/serve/server.go b/cmd/soft/serve/server.go index 33679091..c1379340 100644 --- a/cmd/soft/serve/server.go +++ b/cmd/soft/serve/server.go @@ -93,34 +93,51 @@ func NewServer(ctx context.Context) (*Server, error) { // Start starts the SSH server. func (s *Server) Start() error { errg, _ := errgroup.WithContext(s.ctx) - errg.Go(func() error { - s.logger.Print("Starting Git daemon", "addr", s.Config.Git.ListenAddr) - if err := s.GitDaemon.Start(); !errors.Is(err, daemon.ErrServerClosed) { - return err - } - return nil - }) - errg.Go(func() error { - s.logger.Print("Starting HTTP server", "addr", s.Config.HTTP.ListenAddr) - if err := s.HTTPServer.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { - return err - } - return nil - }) - errg.Go(func() error { - s.logger.Print("Starting SSH server", "addr", s.Config.SSH.ListenAddr) - if err := s.SSHServer.ListenAndServe(); !errors.Is(err, ssh.ErrServerClosed) { - return err - } - return nil - }) - errg.Go(func() error { - s.logger.Print("Starting Stats server", "addr", s.Config.Stats.ListenAddr) - if err := s.StatsServer.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { - return err - } - return nil - }) + + // optionally start the SSH server + if s.Config.SSH.Enabled { + errg.Go(func() error { + s.logger.Print("Starting SSH server", "addr", s.Config.SSH.ListenAddr) + if err := s.SSHServer.ListenAndServe(); !errors.Is(err, ssh.ErrServerClosed) { + return err + } + return nil + }) + } + + // optionally start the git daemon + if s.Config.Git.Enabled { + errg.Go(func() error { + s.logger.Print("Starting Git daemon", "addr", s.Config.Git.ListenAddr) + if err := s.GitDaemon.Start(); !errors.Is(err, daemon.ErrServerClosed) { + return err + } + return nil + }) + } + + // optionally start the HTTP server + if s.Config.HTTP.Enabled { + errg.Go(func() error { + s.logger.Print("Starting HTTP server", "addr", s.Config.HTTP.ListenAddr) + if err := s.HTTPServer.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { + return err + } + return nil + }) + } + + // optionally start the Stats server + if s.Config.Stats.Enabled { + errg.Go(func() error { + s.logger.Print("Starting Stats server", "addr", s.Config.Stats.ListenAddr) + if err := s.StatsServer.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { + return err + } + return nil + }) + } + errg.Go(func() error { s.Cron.Start() return nil diff --git a/pkg/config/config.go b/pkg/config/config.go index 2b650984..9d8395d4 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -18,6 +18,9 @@ var binPath = "soft" // SSHConfig is the configuration for the SSH server. type SSHConfig struct { + // Enabled toggles the SSH server on/off + Enabled bool `env:"ENABLED" yaml:"enabled"` + // ListenAddr is the address on which the SSH server will listen. ListenAddr string `env:"LISTEN_ADDR" yaml:"listen_addr"` @@ -39,6 +42,9 @@ type SSHConfig struct { // GitConfig is the Git daemon configuration for the server. type GitConfig struct { + // Enabled toggles the Git daemon on/off + Enabled bool `env:"ENABLED" yaml:"enabled"` + // ListenAddr is the address on which the Git daemon will listen. ListenAddr string `env:"LISTEN_ADDR" yaml:"listen_addr"` @@ -57,6 +63,9 @@ type GitConfig struct { // HTTPConfig is the HTTP configuration for the server. type HTTPConfig struct { + // Enabled toggles the HTTP server on/off + Enabled bool `env:"ENABLED" yaml:"enabled"` + // ListenAddr is the address on which the HTTP server will listen. ListenAddr string `env:"LISTEN_ADDR" yaml:"listen_addr"` @@ -72,6 +81,9 @@ type HTTPConfig struct { // StatsConfig is the configuration for the stats server. type StatsConfig struct { + // Enabled toggles the Stats server on/off + Enabled bool `env:"ENABLED" yaml:"enabled"` + // ListenAddr is the address on which the stats server will listen. ListenAddr string `env:"LISTEN_ADDR" yaml:"listen_addr"` } @@ -165,21 +177,25 @@ func (c *Config) Environ() []string { fmt.Sprintf("SOFT_SERVE_DATA_PATH=%s", c.DataPath), fmt.Sprintf("SOFT_SERVE_NAME=%s", c.Name), fmt.Sprintf("SOFT_SERVE_INITIAL_ADMIN_KEYS=%s", strings.Join(c.InitialAdminKeys, "\n")), + fmt.Sprintf("SOFT_SERVE_SSH_ENABLED=%t", c.SSH.Enabled), fmt.Sprintf("SOFT_SERVE_SSH_LISTEN_ADDR=%s", c.SSH.ListenAddr), fmt.Sprintf("SOFT_SERVE_SSH_PUBLIC_URL=%s", c.SSH.PublicURL), fmt.Sprintf("SOFT_SERVE_SSH_KEY_PATH=%s", c.SSH.KeyPath), fmt.Sprintf("SOFT_SERVE_SSH_CLIENT_KEY_PATH=%s", c.SSH.ClientKeyPath), fmt.Sprintf("SOFT_SERVE_SSH_MAX_TIMEOUT=%d", c.SSH.MaxTimeout), fmt.Sprintf("SOFT_SERVE_SSH_IDLE_TIMEOUT=%d", c.SSH.IdleTimeout), + fmt.Sprintf("SOFT_SERVE_GIT_ENABLED=%t", c.Git.Enabled), fmt.Sprintf("SOFT_SERVE_GIT_LISTEN_ADDR=%s", c.Git.ListenAddr), fmt.Sprintf("SOFT_SERVE_GIT_PUBLIC_URL=%s", c.Git.PublicURL), fmt.Sprintf("SOFT_SERVE_GIT_MAX_TIMEOUT=%d", c.Git.MaxTimeout), fmt.Sprintf("SOFT_SERVE_GIT_IDLE_TIMEOUT=%d", c.Git.IdleTimeout), fmt.Sprintf("SOFT_SERVE_GIT_MAX_CONNECTIONS=%d", c.Git.MaxConnections), + fmt.Sprintf("SOFT_SERVE_HTTP_ENABLED=%t", c.HTTP.Enabled), fmt.Sprintf("SOFT_SERVE_HTTP_LISTEN_ADDR=%s", c.HTTP.ListenAddr), fmt.Sprintf("SOFT_SERVE_HTTP_TLS_KEY_PATH=%s", c.HTTP.TLSKeyPath), fmt.Sprintf("SOFT_SERVE_HTTP_TLS_CERT_PATH=%s", c.HTTP.TLSCertPath), fmt.Sprintf("SOFT_SERVE_HTTP_PUBLIC_URL=%s", c.HTTP.PublicURL), + fmt.Sprintf("SOFT_SERVE_STATS_ENABLED=%t", c.Stats.Enabled), fmt.Sprintf("SOFT_SERVE_STATS_LISTEN_ADDR=%s", c.Stats.ListenAddr), fmt.Sprintf("SOFT_SERVE_LOG_FORMAT=%s", c.Log.Format), fmt.Sprintf("SOFT_SERVE_LOG_TIME_FORMAT=%s", c.Log.TimeFormat), @@ -318,6 +334,7 @@ func DefaultConfig() *Config { Name: "Soft Serve", DataPath: DefaultDataPath(), SSH: SSHConfig{ + Enabled: true, ListenAddr: ":23231", PublicURL: "ssh://localhost:23231", KeyPath: filepath.Join("ssh", "soft_serve_host_ed25519"), @@ -326,6 +343,7 @@ func DefaultConfig() *Config { IdleTimeout: 10 * 60, // 10 minutes }, Git: GitConfig{ + Enabled: true, ListenAddr: ":9418", PublicURL: "git://localhost", MaxTimeout: 0, @@ -333,10 +351,12 @@ func DefaultConfig() *Config { MaxConnections: 32, }, HTTP: HTTPConfig{ + Enabled: true, ListenAddr: ":23232", PublicURL: "http://localhost:23232", }, Stats: StatsConfig{ + Enabled: true, ListenAddr: "localhost:23233", }, Log: LogConfig{ diff --git a/testscript/script_test.go b/testscript/script_test.go index 4277122f..ce45dec3 100644 --- a/testscript/script_test.go +++ b/testscript/script_test.go @@ -88,20 +88,21 @@ func TestScript(t *testing.T) { UpdateScripts: *update, RequireExplicitExec: true, Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){ - "soft": cmdSoft("admin", admin1.Signer()), - "usoft": cmdSoft("user1", user1.Signer()), - "git": cmdGit(admin1Key), - "ugit": cmdGit(user1Key), - "curl": cmdCurl, - "mkfile": cmdMkfile, - "envfile": cmdEnvfile, - "readfile": cmdReadfile, - "dos2unix": cmdDos2Unix, - "new-webhook": cmdNewWebhook, - "ensureserverrunning": cmdEnsureServerRunning, - "stopserver": cmdStopserver, - "ui": cmdUI(admin1.Signer()), - "uui": cmdUI(user1.Signer()), + "soft": cmdSoft("admin", admin1.Signer()), + "usoft": cmdSoft("user1", user1.Signer()), + "git": cmdGit(admin1Key), + "ugit": cmdGit(user1Key), + "curl": cmdCurl, + "mkfile": cmdMkfile, + "envfile": cmdEnvfile, + "readfile": cmdReadfile, + "dos2unix": cmdDos2Unix, + "new-webhook": cmdNewWebhook, + "ensureserverrunning": cmdEnsureServerRunning, + "ensureservernotrunning": cmdEnsureServerNotRunning, + "stopserver": cmdStopserver, + "ui": cmdUI(admin1.Signer()), + "uui": cmdUI(user1.Signer()), }, Setup: func(e *testscript.Env) error { // Add binPath to PATH @@ -121,6 +122,8 @@ func TestScript(t *testing.T) { e.Setenv("DATA_PATH", data) e.Setenv("SSH_PORT", fmt.Sprintf("%d", sshPort)) e.Setenv("HTTP_PORT", fmt.Sprintf("%d", httpPort)) + e.Setenv("STATS_PORT", fmt.Sprintf("%d", statsPort)) + e.Setenv("GIT_PORT", fmt.Sprintf("%d", gitPort)) e.Setenv("ADMIN1_AUTHORIZED_KEY", admin1.AuthorizedKey()) e.Setenv("ADMIN2_AUTHORIZED_KEY", admin2.AuthorizedKey()) e.Setenv("USER1_AUTHORIZED_KEY", user1.AuthorizedKey()) @@ -505,6 +508,32 @@ func cmdEnsureServerRunning(ts *testscript.TestScript, neg bool, args []string) } } +func cmdEnsureServerNotRunning(ts *testscript.TestScript, neg bool, args []string) { + if len(args) < 1 { + ts.Fatalf("Must supply a TCP port of one of the services to connect to. " + + "These are set as env vars as they are randomized. " + + "Example usage: \"cmdensureservernotrunning SSH_PORT\"\n" + + "Valid values for the env var: SSH_PORT|HTTP_PORT|GIT_PORT|STATS_PORT") + } + + port := ts.Getenv(args[0]) + + // verify that the server is not up + addr := net.JoinHostPort("localhost", port) + for { + conn, _ := net.DialTimeout( + "tcp", + addr, + time.Second, + ) + if conn != nil { + ts.Fatalf("server is running on port %s while it should not be running", port) + conn.Close() + } + break + } +} + func cmdStopserver(ts *testscript.TestScript, neg bool, args []string) { // stop the server resp, err := http.DefaultClient.Head(fmt.Sprintf("%s/__stop", ts.Getenv("SOFT_SERVE_HTTP_PUBLIC_URL"))) diff --git a/testscript/testdata/config-servers-git_disabled.txtar b/testscript/testdata/config-servers-git_disabled.txtar new file mode 100644 index 00000000..7fe34eda --- /dev/null +++ b/testscript/testdata/config-servers-git_disabled.txtar @@ -0,0 +1,18 @@ +# vi: set ft=conf + +# disable git listening +env SOFT_SERVE_SSH_ENABLED=true +env SOFT_SERVE_GIT_ENABLED=false +env SOFT_SERVE_HTTP_ENABLED=true +env SOFT_SERVE_STATS_ENABLED=true + +# start soft serve +exec soft serve --sync-hooks & + +# wait for the ssh + other servers to come up +ensureserverrunning SSH_PORT +ensureserverrunning HTTP_PORT +ensureserverrunning STATS_PORT + +# ensure that the disabled server is not running +ensureservernotrunning GIT_PORT diff --git a/testscript/testdata/config-servers-http_disabled.txtar b/testscript/testdata/config-servers-http_disabled.txtar new file mode 100644 index 00000000..7eee3ed5 --- /dev/null +++ b/testscript/testdata/config-servers-http_disabled.txtar @@ -0,0 +1,19 @@ +# vi: set ft=conf + +# disable http listening +env SOFT_SERVE_SSH_ENABLED=true +env SOFT_SERVE_GIT_ENABLED=true +env SOFT_SERVE_HTTP_ENABLED=false +env SOFT_SERVE_STATS_ENABLED=true + +# start soft serve +exec soft serve --sync-hooks & + +# wait for the ssh + other servers to come up +ensureserverrunning SSH_PORT +ensureserverrunning GIT_PORT +ensureserverrunning STATS_PORT + +# ensure that the disabled server is not running +ensureservernotrunning HTTP_PORT + diff --git a/testscript/testdata/config-servers-ssh_disabled.txtar b/testscript/testdata/config-servers-ssh_disabled.txtar new file mode 100644 index 00000000..30b7492d --- /dev/null +++ b/testscript/testdata/config-servers-ssh_disabled.txtar @@ -0,0 +1,18 @@ +# vi: set ft=conf + +# disable ssh listening +env SOFT_SERVE_SSH_ENABLED=false +env SOFT_SERVE_GIT_ENABLED=true +env SOFT_SERVE_HTTP_ENABLED=true +env SOFT_SERVE_STATS_ENABLED=true + +# start soft serve +exec soft serve --sync-hooks & + +# wait for the git + other servers to come up +ensureserverrunning GIT_PORT +ensureserverrunning HTTP_PORT +ensureserverrunning STATS_PORT + +# ensure that the disabled server is not running +ensureservernotrunning SSH_PORT diff --git a/testscript/testdata/config-servers-stats_disabled.txtar b/testscript/testdata/config-servers-stats_disabled.txtar new file mode 100644 index 00000000..2b803175 --- /dev/null +++ b/testscript/testdata/config-servers-stats_disabled.txtar @@ -0,0 +1,18 @@ +# vi: set ft=conf + +# disable stats listening +env SOFT_SERVE_SSH_ENABLED=true +env SOFT_SERVE_GIT_ENABLED=true +env SOFT_SERVE_HTTP_ENABLED=true +env SOFT_SERVE_STATS_ENABLED=false + +# start soft serve +exec soft serve --sync-hooks & + +# wait for the ssh + other servers to come up +ensureserverrunning SSH_PORT +ensureserverrunning GIT_PORT +ensureserverrunning HTTP_PORT + +# ensure that the disabled server is not running +ensureservernotrunning STATS_PORT