Commit 40728a8b authored by Yann Hodique's avatar Yann Hodique Committed by GitHub

fix(kurtosis-devnet): make main tests self-contained (#13605)

parent 3d577f8e
...@@ -54,16 +54,21 @@ type staticServer struct { ...@@ -54,16 +54,21 @@ type staticServer struct {
*serve.Server *serve.Server
} }
func launchStaticServer(ctx context.Context, cfg *config) (*staticServer, func(), error) { type Main struct {
cfg *config
newDeployer func(opts ...kurtosis.KurtosisDeployerOptions) (deployer, error)
}
func (m *Main) launchStaticServer(ctx context.Context) (*staticServer, func(), error) {
// we will serve content from this tmpDir for the duration of the devnet creation // we will serve content from this tmpDir for the duration of the devnet creation
tmpDir, err := os.MkdirTemp("", cfg.enclave) tmpDir, err := os.MkdirTemp("", m.cfg.enclave)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("error creating temporary directory: %w", err) return nil, nil, fmt.Errorf("error creating temporary directory: %w", err)
} }
server := serve.NewServer( server := serve.NewServer(
serve.WithStaticDir(tmpDir), serve.WithStaticDir(tmpDir),
serve.WithHostname(cfg.localHostName), serve.WithHostname(m.cfg.localHostName),
) )
if err := server.Start(ctx); err != nil { if err := server.Start(ctx); err != nil {
return nil, nil, fmt.Errorf("error starting server: %w", err) return nil, nil, fmt.Errorf("error starting server: %w", err)
...@@ -82,14 +87,14 @@ func launchStaticServer(ctx context.Context, cfg *config) (*staticServer, func() ...@@ -82,14 +87,14 @@ func launchStaticServer(ctx context.Context, cfg *config) (*staticServer, func()
}, nil }, nil
} }
func localDockerImageOption(cfg *config) tmpl.TemplateContextOptions { func (m *Main) localDockerImageOption() tmpl.TemplateContextOptions {
dockerBuilder := build.NewDockerBuilder( dockerBuilder := build.NewDockerBuilder(
build.WithDockerBaseDir(cfg.baseDir), build.WithDockerBaseDir(m.cfg.baseDir),
build.WithDockerDryRun(cfg.dryRun), build.WithDockerDryRun(m.cfg.dryRun),
) )
imageTag := func(projectName string) string { imageTag := func(projectName string) string {
return fmt.Sprintf("%s:%s", projectName, cfg.enclave) return fmt.Sprintf("%s:%s", projectName, m.cfg.enclave)
} }
return tmpl.WithFunction("localDockerImage", func(projectName string) (string, error) { return tmpl.WithFunction("localDockerImage", func(projectName string) (string, error) {
...@@ -97,15 +102,15 @@ func localDockerImageOption(cfg *config) tmpl.TemplateContextOptions { ...@@ -97,15 +102,15 @@ func localDockerImageOption(cfg *config) tmpl.TemplateContextOptions {
}) })
} }
func localContractArtifactsOption(cfg *config, server *staticServer) tmpl.TemplateContextOptions { func (m *Main) localContractArtifactsOption(server *staticServer) tmpl.TemplateContextOptions {
contractsBundle := fmt.Sprintf("contracts-bundle-%s.tar.gz", cfg.enclave) contractsBundle := fmt.Sprintf("contracts-bundle-%s.tar.gz", m.cfg.enclave)
contractsBundlePath := func(_ string) string { contractsBundlePath := func(_ string) string {
return filepath.Join(server.dir, contractsBundle) return filepath.Join(server.dir, contractsBundle)
} }
contractBuilder := build.NewContractBuilder( contractBuilder := build.NewContractBuilder(
build.WithContractBaseDir(cfg.baseDir), build.WithContractBaseDir(m.cfg.baseDir),
build.WithContractDryRun(cfg.dryRun), build.WithContractDryRun(m.cfg.dryRun),
) )
return tmpl.WithFunction("localContractArtifacts", func(layer string) (string, error) { return tmpl.WithFunction("localContractArtifacts", func(layer string) (string, error) {
...@@ -125,10 +130,10 @@ func localContractArtifactsOption(cfg *config, server *staticServer) tmpl.Templa ...@@ -125,10 +130,10 @@ func localContractArtifactsOption(cfg *config, server *staticServer) tmpl.Templa
}) })
} }
func localPrestateOption(cfg *config, server *staticServer) tmpl.TemplateContextOptions { func (m *Main) localPrestateOption(server *staticServer) tmpl.TemplateContextOptions {
prestateBuilder := build.NewPrestateBuilder( prestateBuilder := build.NewPrestateBuilder(
build.WithPrestateBaseDir(cfg.baseDir), build.WithPrestateBaseDir(m.cfg.baseDir),
build.WithPrestateDryRun(cfg.dryRun), build.WithPrestateDryRun(m.cfg.dryRun),
) )
return tmpl.WithFunction("localPrestate", func() (string, error) { return tmpl.WithFunction("localPrestate", func() (string, error) {
...@@ -146,7 +151,7 @@ func localPrestateOption(cfg *config, server *staticServer) tmpl.TemplateContext ...@@ -146,7 +151,7 @@ func localPrestateOption(cfg *config, server *staticServer) tmpl.TemplateContext
url := fmt.Sprintf("%s/%s", server.URL(), relPath) url := fmt.Sprintf("%s/%s", server.URL(), relPath)
if cfg.dryRun { if m.cfg.dryRun {
return url, nil return url, nil
} }
...@@ -194,16 +199,16 @@ func localPrestateOption(cfg *config, server *staticServer) tmpl.TemplateContext ...@@ -194,16 +199,16 @@ func localPrestateOption(cfg *config, server *staticServer) tmpl.TemplateContext
}) })
} }
func renderTemplate(cfg *config, server *staticServer) (*bytes.Buffer, error) { func (m *Main) renderTemplate(server *staticServer) (*bytes.Buffer, error) {
opts := []tmpl.TemplateContextOptions{ opts := []tmpl.TemplateContextOptions{
localDockerImageOption(cfg), m.localDockerImageOption(),
localContractArtifactsOption(cfg, server), m.localContractArtifactsOption(server),
localPrestateOption(cfg, server), m.localPrestateOption(server),
} }
// Read and parse the data file if provided // Read and parse the data file if provided
if cfg.dataFile != "" { if m.cfg.dataFile != "" {
data, err := os.ReadFile(cfg.dataFile) data, err := os.ReadFile(m.cfg.dataFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("error reading data file: %w", err) return nil, fmt.Errorf("error reading data file: %w", err)
} }
...@@ -217,7 +222,7 @@ func renderTemplate(cfg *config, server *staticServer) (*bytes.Buffer, error) { ...@@ -217,7 +222,7 @@ func renderTemplate(cfg *config, server *staticServer) (*bytes.Buffer, error) {
} }
// Open template file // Open template file
tmplFile, err := os.Open(cfg.templateFile) tmplFile, err := os.Open(m.cfg.templateFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("error opening template file: %w", err) return nil, fmt.Errorf("error opening template file: %w", err)
} }
...@@ -235,7 +240,7 @@ func renderTemplate(cfg *config, server *staticServer) (*bytes.Buffer, error) { ...@@ -235,7 +240,7 @@ func renderTemplate(cfg *config, server *staticServer) (*bytes.Buffer, error) {
return buf, nil return buf, nil
} }
func deploy(ctx context.Context, cfg *config, r io.Reader) error { func (m *Main) deploy(ctx context.Context, r io.Reader) error {
// Create a multi reader to output deployment input to stdout // Create a multi reader to output deployment input to stdout
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
tee := io.TeeReader(r, buf) tee := io.TeeReader(r, buf)
...@@ -246,33 +251,46 @@ func deploy(ctx context.Context, cfg *config, r io.Reader) error { ...@@ -246,33 +251,46 @@ func deploy(ctx context.Context, cfg *config, r io.Reader) error {
return fmt.Errorf("error copying deployment input: %w", err) return fmt.Errorf("error copying deployment input: %w", err)
} }
kurtosisDeployer, err := kurtosis.NewKurtosisDeployer( opts := []kurtosis.KurtosisDeployerOptions{
kurtosis.WithKurtosisBaseDir(cfg.baseDir), kurtosis.WithKurtosisBaseDir(m.cfg.baseDir),
kurtosis.WithKurtosisDryRun(cfg.dryRun), kurtosis.WithKurtosisDryRun(m.cfg.dryRun),
kurtosis.WithKurtosisPackageName(cfg.kurtosisPackage), kurtosis.WithKurtosisPackageName(m.cfg.kurtosisPackage),
kurtosis.WithKurtosisEnclave(cfg.enclave), kurtosis.WithKurtosisEnclave(m.cfg.enclave),
) }
d, err := m.newDeployer(opts...)
if err != nil { if err != nil {
return fmt.Errorf("error creating kurtosis deployer: %w", err) return fmt.Errorf("error creating kurtosis deployer: %w", err)
} }
env, err := kurtosisDeployer.Deploy(ctx, buf) env, err := d.Deploy(ctx, buf)
if err != nil { if err != nil {
return fmt.Errorf("error deploying kurtosis: %w", err) return fmt.Errorf("error deploying kurtosis package: %w", err)
}
if err := writeEnvironment(m.cfg.environment, env); err != nil {
return fmt.Errorf("error writing environment: %w", err)
} }
envOutput := os.Stdout return nil
if cfg.environment != "" { }
envOutput, err = os.Create(cfg.environment)
type deployer interface {
Deploy(ctx context.Context, input io.Reader) (*kurtosis.KurtosisEnvironment, error)
}
func writeEnvironment(path string, env *kurtosis.KurtosisEnvironment) error {
out := os.Stdout
if path != "" {
var err error
out, err = os.Create(path)
if err != nil { if err != nil {
return fmt.Errorf("error creating environment file: %w", err) return fmt.Errorf("error creating environment file: %w", err)
} }
defer envOutput.Close() defer out.Close()
} else {
log.Println("\nEnvironment description:")
} }
enc := json.NewEncoder(envOutput) enc := json.NewEncoder(out)
enc.SetIndent("", " ") enc.SetIndent("", " ")
if err := enc.Encode(env); err != nil { if err := enc.Encode(env); err != nil {
return fmt.Errorf("error encoding environment: %w", err) return fmt.Errorf("error encoding environment: %w", err)
...@@ -281,22 +299,22 @@ func deploy(ctx context.Context, cfg *config, r io.Reader) error { ...@@ -281,22 +299,22 @@ func deploy(ctx context.Context, cfg *config, r io.Reader) error {
return nil return nil
} }
func mainFunc(cfg *config) error { func (m *Main) run() error {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
server, cleanup, err := launchStaticServer(ctx, cfg) server, cleanup, err := m.launchStaticServer(ctx)
if err != nil { if err != nil {
return fmt.Errorf("error launching static server: %w", err) return fmt.Errorf("error launching static server: %w", err)
} }
defer cleanup() defer cleanup()
buf, err := renderTemplate(cfg, server) buf, err := m.renderTemplate(server)
if err != nil { if err != nil {
return fmt.Errorf("error rendering template: %w", err) return fmt.Errorf("error rendering template: %w", err)
} }
return deploy(ctx, cfg, buf) return m.deploy(ctx, buf)
} }
func mainAction(c *cli.Context) error { func mainAction(c *cli.Context) error {
...@@ -304,7 +322,13 @@ func mainAction(c *cli.Context) error { ...@@ -304,7 +322,13 @@ func mainAction(c *cli.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("error parsing config: %w", err) return fmt.Errorf("error parsing config: %w", err)
} }
return mainFunc(cfg) m := &Main{
cfg: cfg,
newDeployer: func(opts ...kurtosis.KurtosisDeployerOptions) (deployer, error) {
return kurtosis.NewKurtosisDeployer(opts...)
},
}
return m.run()
} }
func getFlags() []cli.Flag { func getFlags() []cli.Flag {
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/json" "encoding/json"
"io"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
...@@ -15,6 +16,18 @@ import ( ...@@ -15,6 +16,18 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
type mockDeployer struct {
dryRun bool
}
func (m *mockDeployer) Deploy(ctx context.Context, input io.Reader) (*kurtosis.KurtosisEnvironment, error) {
return &kurtosis.KurtosisEnvironment{}, nil
}
func newMockDeployer(...kurtosis.KurtosisDeployerOptions) (deployer, error) {
return &mockDeployer{dryRun: true}, nil
}
func TestParseFlags(t *testing.T) { func TestParseFlags(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
...@@ -93,13 +106,23 @@ func TestParseFlags(t *testing.T) { ...@@ -93,13 +106,23 @@ func TestParseFlags(t *testing.T) {
} }
} }
func newTestMain(cfg *config) *Main {
return &Main{
cfg: cfg,
newDeployer: func(opts ...kurtosis.KurtosisDeployerOptions) (deployer, error) {
return newMockDeployer(opts...)
},
}
}
func TestLaunchStaticServer(t *testing.T) { func TestLaunchStaticServer(t *testing.T) {
cfg := &config{ cfg := &config{
localHostName: "test.local", localHostName: "test.local",
} }
m := newTestMain(cfg)
ctx := context.Background() ctx := context.Background()
server, cleanup, err := launchStaticServer(ctx, cfg) server, cleanup, err := m.launchStaticServer(ctx)
require.NoError(t, err) require.NoError(t, err)
defer cleanup() defer cleanup()
...@@ -142,12 +165,13 @@ artifacts: {{localContractArtifacts "l1"}}` ...@@ -142,12 +165,13 @@ artifacts: {{localContractArtifacts "l1"}}`
dryRun: true, // Important for tests dryRun: true, // Important for tests
} }
m := newTestMain(cfg)
ctx := context.Background() ctx := context.Background()
server, cleanup, err := launchStaticServer(ctx, cfg) server, cleanup, err := m.launchStaticServer(ctx)
require.NoError(t, err) require.NoError(t, err)
defer cleanup() defer cleanup()
buf, err := renderTemplate(cfg, server) buf, err := m.renderTemplate(server)
require.NoError(t, err) require.NoError(t, err)
// Verify template rendering // Verify template rendering
...@@ -174,7 +198,8 @@ func TestDeploy(t *testing.T) { ...@@ -174,7 +198,8 @@ func TestDeploy(t *testing.T) {
// Create a simple deployment configuration // Create a simple deployment configuration
deployConfig := bytes.NewBufferString(`{"test": "config"}`) deployConfig := bytes.NewBufferString(`{"test": "config"}`)
err = deploy(ctx, cfg, deployConfig) m := newTestMain(cfg)
err = m.deploy(ctx, deployConfig)
require.NoError(t, err) require.NoError(t, err)
// Verify the environment file was created // Verify the environment file was created
...@@ -189,7 +214,6 @@ func TestDeploy(t *testing.T) { ...@@ -189,7 +214,6 @@ func TestDeploy(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
} }
// TestMainFunc performs an integration test of the main function
func TestMainFunc(t *testing.T) { func TestMainFunc(t *testing.T) {
// Create a temporary directory for test files // Create a temporary directory for test files
tmpDir, err := os.MkdirTemp("", "main-test") tmpDir, err := os.MkdirTemp("", "main-test")
...@@ -210,7 +234,8 @@ func TestMainFunc(t *testing.T) { ...@@ -210,7 +234,8 @@ func TestMainFunc(t *testing.T) {
dryRun: true, dryRun: true,
} }
err = mainFunc(cfg) m := newTestMain(cfg)
err = m.run()
require.NoError(t, err) require.NoError(t, err)
// Verify the environment file was created // Verify the environment file was created
...@@ -254,13 +279,14 @@ _prestate-build target: ...@@ -254,13 +279,14 @@ _prestate-build target:
dryRun: tt.dryRun, dryRun: tt.dryRun,
} }
m := newTestMain(cfg)
ctx := context.Background() ctx := context.Background()
server, cleanup, err := launchStaticServer(ctx, cfg) server, cleanup, err := m.launchStaticServer(ctx)
require.NoError(t, err) require.NoError(t, err)
defer cleanup() defer cleanup()
// Create template context with just the prestate function // Create template context with just the prestate function
tmplCtx := tmpl.NewTemplateContext(localPrestateOption(cfg, server)) tmplCtx := tmpl.NewTemplateContext(m.localPrestateOption(server))
// Test template // Test template
template := `{"prestate": "{{localPrestate}}"}` template := `{"prestate": "{{localPrestate}}"}`
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment