Skip to content

Commit

Permalink
Merge pull request #1426 from suttod/test-envfile
Browse files Browse the repository at this point in the history
Load config from spicedb.env
  • Loading branch information
jzelinskie authored Aug 23, 2023
2 parents e4bb3ad + 368da03 commit 0f89d30
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 4 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ require (
github.com/jackc/pgx-zerolog v0.0.0-20230315001418-f978528409eb
github.com/jackc/pgx/v5 v5.4.2
github.com/johannesboyne/gofakes3 v0.0.0-20230506070712-04da935ef877
github.com/jzelinskie/cobrautil/v2 v2.0.0-20230714172849-80717639cec5
github.com/jzelinskie/cobrautil/v2 v2.0.0-20230814170201-d023222f49a5
github.com/jzelinskie/stringz v0.0.2
github.com/lthibault/jitterbug v2.0.0+incompatible
github.com/magefile/mage v1.15.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -903,8 +903,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY=
github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0=
github.com/jzelinskie/cobrautil/v2 v2.0.0-20230714172849-80717639cec5 h1:X7vo4fEmuKLS4YQ+WkQ9xEtnR93tqkcYnH4rDDkfzhI=
github.com/jzelinskie/cobrautil/v2 v2.0.0-20230714172849-80717639cec5/go.mod h1:954benQgK9Oi403yRaIot4TgRM0dDLKrBj48K7J8NZg=
github.com/jzelinskie/cobrautil/v2 v2.0.0-20230814170201-d023222f49a5 h1:Bs9es44WBUDfuCFiHYSJLYc97ZaQyMlWoxCHmsAC0fM=
github.com/jzelinskie/cobrautil/v2 v2.0.0-20230814170201-d023222f49a5/go.mod h1:954benQgK9Oi403yRaIot4TgRM0dDLKrBj48K7J8NZg=
github.com/jzelinskie/stringz v0.0.2 h1:OSjMEYvz8tjhovgZ/6cGcPID736ubeukr35mu6RYAmg=
github.com/jzelinskie/stringz v0.0.2/go.mod h1:hHYbgxJuNLRw91CmpuFsYEOyQqpDVFg8pvEh23vy4P0=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
Expand Down
207 changes: 207 additions & 0 deletions pkg/cmd/serve_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package cmd

import (
"os"
"path/filepath"
"strings"
"testing"

"github.com/spf13/cobra"
"github.com/stretchr/testify/require"

"github.com/authzed/spicedb/pkg/cmd/server"
)

// Run a serve command with specified command line args
// and call `assertConfig` with the merged configuration.
func RunServeTest(t *testing.T, args []string, assertConfig func(t *testing.T, mergedConfig *server.Config)) {
config := server.NewConfigWithOptionsAndDefaults()
cmd := NewServeCommand("spicedb", config)
RegisterRootFlags(cmd)
require.Nil(t, RegisterServeFlags(cmd, config))
// Disable all metrics as they are singletons
config.DispatchClusterMetricsEnabled = false
config.DispatchClientMetricsEnabled = false
config.DatastoreConfig.EnableDatastoreMetrics = false
config.DispatchCacheConfig.Metrics = false
config.ClusterDispatchCacheConfig.Metrics = false
config.NamespaceCacheConfig.Metrics = false

cmd.SetArgs(args)

cmd.RunE = func(cmd *cobra.Command, args []string) error {
_, err := config.Complete(cmd.Context())
t.Cleanup(func() {
// TODO: RunnableServer.closeFunc should be called on Cleanup, but it is private.
})
if err != nil {
return err
}
assertConfig(t, config)
return nil
}
require.Nil(t, cmd.Execute())
}

func prepareTempConfigDir(t *testing.T) string {
workdir, err := os.Getwd()
require.Nil(t, err)

testdir := t.TempDir()
require.Nil(t, os.Chdir(testdir))

t.Cleanup(func() {
err = os.Chdir(workdir)
require.Nil(t, err)
})

return testdir
}

func prepareTempConfigFile(t *testing.T, config string) {
confdir := prepareTempConfigDir(t)
confFile, err := os.Create(filepath.Join(confdir, "spicedb.env"))
require.Nil(t, err)
_, err = confFile.WriteString(config)
require.Nil(t, err)
require.Nil(t, confFile.Close())
prevEnv := os.Environ()
restore := func() {
restoreEnv(prevEnv)
}
t.Cleanup(restore)
}

func restoreEnv(prevEnv []string) {
os.Clearenv()
for _, line := range prevEnv {
envvar := strings.SplitN(line, "=", 2)
os.Setenv(envvar[0], envvar[1])
}
}

func TestDefaultConfig(t *testing.T) {
flags := []string{
"--grpc-preshared-key", "some_key",
}
RunServeTest(t, flags, func(t *testing.T, mergedConfig *server.Config) {
require.Equal(t, true, mergedConfig.GRPCServer.Enabled)
require.Equal(t, ":50051", mergedConfig.GRPCServer.Address)
require.Equal(t, false, mergedConfig.HTTPGateway.HTTPEnabled)
require.Equal(t, ":8443", mergedConfig.HTTPGateway.HTTPAddress)
require.Equal(t, "memory", mergedConfig.DatastoreConfig.Engine)
require.Equal(t, uint16(1024), mergedConfig.DatastoreConfig.WatchBufferLength)
})
}

func TestFlagsAreParsed(t *testing.T) {
flags := []string{
"--grpc-preshared-key", "some_key",
"--grpc-addr", "127.0.0.1:9051",
"--http-enabled",
"--http-addr", "127.0.0.1:9443",
"--datastore-engine", "memory",
"--datastore-watch-buffer-length", "9000",
}
RunServeTest(t, flags, func(t *testing.T, mergedConfig *server.Config) {
require.Equal(t, true, mergedConfig.GRPCServer.Enabled)
require.Equal(t, "127.0.0.1:9051", mergedConfig.GRPCServer.Address)
require.Equal(t, true, mergedConfig.HTTPGateway.HTTPEnabled)
require.Equal(t, "127.0.0.1:9443", mergedConfig.HTTPGateway.HTTPAddress)
require.Equal(t, "memory", mergedConfig.DatastoreConfig.Engine)
require.Equal(t, uint16(9000), mergedConfig.DatastoreConfig.WatchBufferLength)
})
}

func TestEnvVarsAreParsed(t *testing.T) {
t.Setenv("SPICEDB_GRPC_PRESHARED_KEY", "some_key")
t.Setenv("SPICEDB_GRPC_ADDR", "127.0.0.1:10051")
t.Setenv("SPICEDB_HTTP_ENABLED", "1")
t.Setenv("SPICEDB_HTTP_ADDR", "127.0.0.1:10443")
t.Setenv("SPICEDB_DATASTORE_ENGINE", "memory")
t.Setenv("SPICEDB_DATASTORE_WATCH_BUFFER_LENGTH", "10000")
flags := []string{}
RunServeTest(t, flags, func(t *testing.T, mergedConfig *server.Config) {
require.Equal(t, true, mergedConfig.GRPCServer.Enabled)
require.Equal(t, "127.0.0.1:10051", mergedConfig.GRPCServer.Address)
require.Equal(t, true, mergedConfig.HTTPGateway.HTTPEnabled)
require.Equal(t, "127.0.0.1:10443", mergedConfig.HTTPGateway.HTTPAddress)
require.Equal(t, "memory", mergedConfig.DatastoreConfig.Engine)
require.Equal(t, uint16(10000), mergedConfig.DatastoreConfig.WatchBufferLength)
})
}

func TestConfigFileValuesAreParsed(t *testing.T) {
config := `
SPICEDB_GRPC_PRESHARED_KEY=some_key
SPICEDB_GRPC_ADDR=127.0.0.1:11051
SPICEDB_HTTP_ENABLED=1
SPICEDB_HTTP_ADDR=127.0.0.1:11443
SPICEDB_DATASTORE_ENGINE=memory
SPICEDB_DATASTORE_WATCH_BUFFER_LENGTH=11000`
prepareTempConfigFile(t, config)
flags := []string{}
RunServeTest(t, flags, func(t *testing.T, mergedConfig *server.Config) {
require.Equal(t, true, mergedConfig.GRPCServer.Enabled)
require.Equal(t, "127.0.0.1:11051", mergedConfig.GRPCServer.Address)
require.Equal(t, true, mergedConfig.HTTPGateway.HTTPEnabled)
require.Equal(t, "127.0.0.1:11443", mergedConfig.HTTPGateway.HTTPAddress)
require.Equal(t, "memory", mergedConfig.DatastoreConfig.Engine)
require.Equal(t, uint16(11000), mergedConfig.DatastoreConfig.WatchBufferLength)
})
}

func TestConfigsAreMerged(t *testing.T) {
config := `
SPICEDB_GRPC_PRESHARED_KEY=some_key
SPICEDB_GRPC_ADDR=127.0.0.1:12051`
prepareTempConfigFile(t, config)

t.Setenv("SPICEDB_HTTP_ENABLED", "1")
t.Setenv("SPICEDB_HTTP_ADDR", "127.0.0.1:12443")

flags := []string{
"--datastore-engine", "memory",
"--datastore-watch-buffer-length", "12000",
}
RunServeTest(t, flags, func(t *testing.T, mergedConfig *server.Config) {
require.Equal(t, true, mergedConfig.GRPCServer.Enabled)
require.Equal(t, "127.0.0.1:12051", mergedConfig.GRPCServer.Address)
require.Equal(t, true, mergedConfig.HTTPGateway.HTTPEnabled)
require.Equal(t, "127.0.0.1:12443", mergedConfig.HTTPGateway.HTTPAddress)
require.Equal(t, "memory", mergedConfig.DatastoreConfig.Engine)
require.Equal(t, uint16(12000), mergedConfig.DatastoreConfig.WatchBufferLength)
})
}

func TestConfigPrecedence(t *testing.T) {
// Config file has lowest precedence (over default values)
config := `
SPICEDB_GRPC_PRESHARED_KEY=some_key
SPICEDB_GRPC_ADDR=127.0.0.1:21051
SPICEDB_HTTP_ENABLED=1
SPICEDB_HTTP_ADDR=127.0.0.1:21443
SPICEDB_DATASTORE_ENGINE=memory
SPICEDB_DATASTORE_WATCH_BUFFER_LENGTH=21000`
prepareTempConfigFile(t, config)

// Env variables override config file
t.Setenv("SPICEDB_HTTP_ENABLED", "1")
t.Setenv("SPICEDB_HTTP_ADDR", "127.0.0.1:22443")
t.Setenv("SPICEDB_DATASTORE_ENGINE", "memory")
t.Setenv("SPICEDB_DATASTORE_WATCH_BUFFER_LENGTH", "22000")

// command line flags override everything
flags := []string{
"--datastore-engine", "memory",
"--datastore-watch-buffer-length", "23000",
}
RunServeTest(t, flags, func(t *testing.T, mergedConfig *server.Config) {
require.Equal(t, true, mergedConfig.GRPCServer.Enabled)
require.Equal(t, "127.0.0.1:21051", mergedConfig.GRPCServer.Address)
require.Equal(t, true, mergedConfig.HTTPGateway.HTTPEnabled)
require.Equal(t, "127.0.0.1:22443", mergedConfig.HTTPGateway.HTTPAddress)
require.Equal(t, "memory", mergedConfig.DatastoreConfig.Engine)
require.Equal(t, uint16(23000), mergedConfig.DatastoreConfig.WatchBufferLength)
})
}
2 changes: 1 addition & 1 deletion pkg/cmd/server/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func ServeExample(programName string) string {
// command.
func DefaultPreRunE(programName string) cobrautil.CobraRunFunc {
return cobrautil.CommandStack(
cobrautil.SyncViperPreRunE(programName),
cobrautil.SyncViperDotEnvPreRunE(programName, "spicedb.env", zerologr.New(&logging.Logger)),
cobrazerolog.New(
cobrazerolog.WithTarget(func(logger zerolog.Logger) {
logging.SetGlobalLogger(logger)
Expand Down

0 comments on commit 0f89d30

Please sign in to comment.