Abort startup on an unknown PIXA_ environment variable (closes #133) #136
@@ -3,10 +3,14 @@ package config
|
|||||||
import (
|
import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"sneak.berlin/go/pixa/internal/globals"
|
||||||
|
"sneak.berlin/go/pixa/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestMain unsets PORT and every PIXA_ environment variable before the
|
// TestMain unsets PORT and every PIXA_ environment variable before the
|
||||||
@@ -95,6 +99,114 @@ func TestEnvironmentSetsEveryKey(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestUnknownPixaVariableAbortsStartup checks that a PIXA_ variable that
|
||||||
|
// is not a setting's variable, such as a misspelled one, aborts startup
|
||||||
|
// naming it, as an unknown config key does, instead of being ignored.
|
||||||
|
func TestUnknownPixaVariableAbortsStartup(t *testing.T) {
|
||||||
|
t.Setenv("PIXA_TRUSTED_PROXY", "192.0.2.0/24")
|
||||||
|
t.Setenv("PIXA_SIGNINGKEY", validTestSigningKey)
|
||||||
|
|
||||||
|
err := validateKnownEnvVars()
|
||||||
|
wantStartupError(t, err, "PIXA_TRUSTED_PROXY", "PIXA_SIGNINGKEY")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestPixaPortAbortsStartupPointingToPort checks that PIXA_PORT aborts
|
||||||
|
// startup with a message saying to use PORT, which sets the port.
|
||||||
|
func TestPixaPortAbortsStartupPointingToPort(t *testing.T) {
|
||||||
|
t.Setenv("PIXA_PORT", "9090")
|
||||||
|
|
||||||
|
err := validateKnownEnvVars()
|
||||||
|
wantStartupError(t, err, "PIXA_PORT", "use PORT")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSettingVariablesAndConfigPathAreAccepted checks that every
|
||||||
|
// setting's variable and PIXA_CONFIG_PATH pass the check for unknown
|
||||||
|
// PIXA_ variables. TestEnvironmentSetsEveryKey pins the names in the list.
|
||||||
|
func TestSettingVariablesAndConfigPathAreAccepted(t *testing.T) {
|
||||||
|
// A config file's env section loaded by another test can leave a
|
||||||
|
// PIXA_ variable set for the whole process, so every one is unset
|
||||||
|
// here first; t.Setenv restores each when the test ends.
|
||||||
|
for _, entry := range os.Environ() {
|
||||||
|
name, _, _ := strings.Cut(entry, "=")
|
||||||
|
if !strings.HasPrefix(name, "PIXA_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Setenv(name, "")
|
||||||
|
|
||||||
|
err := os.Unsetenv(name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to unset %s: %v", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Setenv("PIXA_CONFIG_PATH", "/etc/pixa/config.yml")
|
||||||
|
|
||||||
|
for _, name := range envVarNames() {
|
||||||
|
t.Setenv(name, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
err := validateKnownEnvVars()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("PIXA_CONFIG_PATH and every setting's variable "+
|
||||||
|
"must be accepted: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// configFromNew writes yamlContent to a temporary config file, points
|
||||||
|
// PIXA_CONFIG_PATH at it, and runs New, as the server does at startup.
|
||||||
|
// The state directory is a temporary one and the disk cache is off, so
|
||||||
|
// New succeeds unless something in the test is wrong.
|
||||||
|
func configFromNew(t *testing.T, yamlContent string) (*Config, error) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
configPath := filepath.Join(tmpDir, "config.yml")
|
||||||
|
|
||||||
|
err := os.WriteFile(configPath, []byte(yamlContent), 0o600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to write test config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Setenv("PIXA_CONFIG_PATH", configPath)
|
||||||
|
t.Setenv("PIXA_STATE_DIR", filepath.Join(tmpDir, "state"))
|
||||||
|
t.Setenv("PIXA_CACHE_MAX_BYTES", "0")
|
||||||
|
|
||||||
|
testLogger, err := logger.New(nil, logger.Params{Globals: &globals.Globals{}})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create logger: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return New(nil, Params{Logger: testLogger})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestUnknownPixaVariableAbortsNew checks that New, which the server
|
||||||
|
// calls at startup, aborts on a misspelled PIXA_ variable.
|
||||||
|
func TestUnknownPixaVariableAbortsNew(t *testing.T) {
|
||||||
|
t.Setenv("PIXA_TRUSTED_PROXY", "192.0.2.0/24")
|
||||||
|
|
||||||
|
_, err := configFromNew(t, signingKeyLine)
|
||||||
|
wantStartupError(t, err, "PIXA_TRUSTED_PROXY")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestUnknownPixaVariableInEnvSectionAbortsNew checks that New aborts
|
||||||
|
// on a misspelled PIXA_ name in the config file's env section, which
|
||||||
|
// loading the file sets as an environment variable.
|
||||||
|
func TestUnknownPixaVariableInEnvSectionAbortsNew(t *testing.T) {
|
||||||
|
// The variable must be absent until the file loads. t.Setenv makes
|
||||||
|
// sure the one the file sets is removed when the test ends.
|
||||||
|
t.Setenv("PIXA_TRUSTED_PROXY", "")
|
||||||
|
|
||||||
|
err := os.Unsetenv("PIXA_TRUSTED_PROXY")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to unset PIXA_TRUSTED_PROXY: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = configFromNew(t, signingKeyLine+
|
||||||
|
"env:\n PIXA_TRUSTED_PROXY: 192.0.2.0/24\n")
|
||||||
|
wantStartupError(t, err, "PIXA_TRUSTED_PROXY")
|
||||||
|
}
|
||||||
|
|
||||||
// TestPortFromEnvironmentOverridesConfigFile checks that PORT wins over
|
// TestPortFromEnvironmentOverridesConfigFile checks that PORT wins over
|
||||||
// the port in the config file.
|
// the port in the config file.
|
||||||
func TestPortFromEnvironmentOverridesConfigFile(t *testing.T) {
|
func TestPortFromEnvironmentOverridesConfigFile(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user