server_test.go

  1package server
  2
  3import (
  4	"fmt"
  5	"net"
  6	"path/filepath"
  7	"strconv"
  8	"strings"
  9	"testing"
 10
 11	"github.com/charmbracelet/keygen"
 12	"github.com/charmbracelet/soft-serve/server/config"
 13	"github.com/gliderlabs/ssh"
 14	"github.com/go-git/go-billy/v5/memfs"
 15	"github.com/go-git/go-git/v5"
 16	gconfig "github.com/go-git/go-git/v5/config"
 17	"github.com/go-git/go-git/v5/plumbing/object"
 18	gssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
 19	"github.com/go-git/go-git/v5/storage/memory"
 20	"github.com/matryer/is"
 21	gossh "golang.org/x/crypto/ssh"
 22)
 23
 24func TestPushRepo(t *testing.T) {
 25	is := is.New(t)
 26	_, cfg, pkPath := setupServer(t)
 27	rp := t.TempDir()
 28	r, err := git.PlainInit(rp, false)
 29	is.NoErr(err)
 30	wt, err := r.Worktree()
 31	is.NoErr(err)
 32	_, err = wt.Filesystem.Create("testfile")
 33	is.NoErr(err)
 34	_, err = wt.Add("testfile")
 35	is.NoErr(err)
 36	author := &object.Signature{
 37		Name:  "test",
 38		Email: "",
 39	}
 40	_, err = wt.Commit("test commit", &git.CommitOptions{
 41		All:       true,
 42		Author:    author,
 43		Committer: author,
 44	})
 45	is.NoErr(err)
 46	_, err = r.CreateRemote(&gconfig.RemoteConfig{
 47		Name: "origin",
 48		URLs: []string{fmt.Sprintf("ssh://localhost:%d/%s", cfg.SSH.Port, "testrepo")},
 49	})
 50	auth, err := gssh.NewPublicKeysFromFile("git", pkPath, "")
 51	is.NoErr(err)
 52	auth.HostKeyCallbackHelper = gssh.HostKeyCallbackHelper{
 53		HostKeyCallback: gossh.InsecureIgnoreHostKey(),
 54	}
 55	t.Logf("pushing to ssh://localhost:%d/%s", cfg.SSH.Port, "testrepo")
 56	err = r.Push(&git.PushOptions{
 57		RemoteName: "origin",
 58		Auth:       auth,
 59	})
 60	is.NoErr(err)
 61}
 62
 63func TestCloneRepo(t *testing.T) {
 64	is := is.New(t)
 65	_, cfg, pkPath := setupServer(t)
 66	url := fmt.Sprintf("ssh://localhost:%d/config", cfg.SSH.Port)
 67	t.Log("cloning repo", url)
 68	pk, err := gssh.NewPublicKeysFromFile("git", pkPath, "")
 69	is.NoErr(err)
 70	pk.HostKeyCallbackHelper = gssh.HostKeyCallbackHelper{
 71		HostKeyCallback: gossh.InsecureIgnoreHostKey(),
 72	}
 73	_, err = git.Clone(memory.NewStorage(), memfs.New(), &git.CloneOptions{
 74		URL:  url,
 75		Auth: pk,
 76	})
 77	is.NoErr(err)
 78}
 79
 80func randomPort() int {
 81	addr, _ := net.Listen("tcp", ":0") //nolint:gosec
 82	_ = addr.Close()
 83	return addr.Addr().(*net.TCPAddr).Port
 84}
 85
 86func setupServer(tb testing.TB) (*Server, *config.Config, string) {
 87	tb.Helper()
 88	pub, pkPath := createKeyPair(tb)
 89	dp := tb.TempDir()
 90	tb.Setenv("SOFT_SERVE_DATA_PATH", dp)
 91	tb.Setenv("SOFT_SERVE_INITIAL_ADMIN_KEY", authorizedKey(pub))
 92	tb.Setenv("SOFT_SERVE_GIT_ENABLED", "false")
 93	tb.Setenv("SOFT_SERVE_SSH_PORT", strconv.Itoa(randomPort()))
 94	// tb.Setenv("SOFT_SERVE_DB_DRIVER", "fake")
 95	cfg := config.DefaultConfig() //.WithDB(&fakedb.FakeDB{})
 96	s := NewServer(cfg)
 97	go func() {
 98		tb.Log("starting server")
 99		s.Start()
100	}()
101	tb.Cleanup(func() {
102		s.Close()
103	})
104	return s, cfg, pkPath
105}
106
107func createKeyPair(tb testing.TB) (ssh.PublicKey, string) {
108	tb.Helper()
109	is := is.New(tb)
110	keyDir := tb.TempDir()
111	kp, err := keygen.NewWithWrite(filepath.Join(keyDir, "id"), nil, keygen.Ed25519)
112	is.NoErr(err)
113	pubkey, _, _, _, err := ssh.ParseAuthorizedKey(kp.PublicKey())
114	is.NoErr(err)
115	return pubkey, filepath.Join(keyDir, "id_ed25519")
116}
117
118func authorizedKey(pk ssh.PublicKey) string {
119	return strings.TrimSpace(string(gossh.MarshalAuthorizedKey(pk)))
120}