Enforce environment variable configuration for Docker entrypoint
CI / Go Tests (push) Successful in 12s
CI / Build (push) Successful in 11s
Format / gofmt (push) Successful in 6s
Release Artifacts / Validate release tag (push) Successful in 2s
Release Artifacts / Build and release executables (push) Successful in 16s
Release Artifacts / Build and release Docker image (push) Successful in 26s
CI / Go Tests (push) Successful in 12s
CI / Build (push) Successful in 11s
Format / gofmt (push) Successful in 6s
Release Artifacts / Validate release tag (push) Successful in 2s
Release Artifacts / Build and release executables (push) Successful in 16s
Release Artifacts / Build and release Docker image (push) Successful in 26s
- Updated `docker-entrypoint.sh` to disallow custom command-line arguments, requiring configuration through `SCRATCHBOX_*` environment variables. - Modified `README.md` to clarify that custom container commands are not supported and to reflect the new entrypoint behavior. - Enhanced `main_test.go` to validate failure when required environment variables are not set. - Added a function in `server.go` to print startup environment variables, ensuring visibility of configuration during server initialization.
This commit is contained in:
@@ -42,5 +42,4 @@ fmt:
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf web/static
|
rm -rf web/static
|
||||||
rm -rf $(CONFIG)
|
|
||||||
rm -rf $(BIN_DIR)
|
rm -rf $(BIN_DIR)
|
||||||
|
|||||||
@@ -51,14 +51,11 @@ Use the included Compose example:
|
|||||||
Inside the container, the default command is:
|
Inside the container, the default command is:
|
||||||
|
|
||||||
- `scratchbox server --env`
|
- `scratchbox server --env`
|
||||||
|
- Custom container command/args are not supported; configure behavior via `SCRATCHBOX_*` env vars.
|
||||||
- The image forces `SCRATCHBOX_STORAGE_DATA_DIR=/data`.
|
- The image forces `SCRATCHBOX_STORAGE_DATA_DIR=/data`.
|
||||||
- The image forces `SCRATCHBOX_SERVER_LISTEN_ADDR=:8080`.
|
- The image forces `SCRATCHBOX_SERVER_LISTEN_ADDR=:8080`.
|
||||||
- The image forces `SCRATCHBOX_SERVER_ACCESS_LOG_FILE_PATH` to empty.
|
- The image forces `SCRATCHBOX_SERVER_ACCESS_LOG_FILE_PATH` to empty.
|
||||||
|
|
||||||
To run with a YAML config instead, pass `--config` explicitly (mutually exclusive with `--env`):
|
|
||||||
|
|
||||||
- `docker run --rm -p 8080:8080 -v "$(pwd)/docker-data:/data" -v "$(pwd)/docker-config:/config" scratchbox:dev server --config /config/config.yaml`
|
|
||||||
|
|
||||||
Storage encryption key behavior:
|
Storage encryption key behavior:
|
||||||
|
|
||||||
- The key file is always stored at `storage.data_dir/metadata.key` (next to `metadata`).
|
- The key file is always stored at `storage.data_dir/metadata.key` (next to `metadata`).
|
||||||
|
|||||||
@@ -139,9 +139,30 @@ func TestMainProcessEnvSuccess(t *testing.T) {
|
|||||||
"SCRATCHBOX_STORAGE_DATA_DIR="+filepath.Join(tmp, "data"),
|
"SCRATCHBOX_STORAGE_DATA_DIR="+filepath.Join(tmp, "data"),
|
||||||
"SCRATCHBOX_SECURITY_ALLOWED_IPS=",
|
"SCRATCHBOX_SECURITY_ALLOWED_IPS=",
|
||||||
)
|
)
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
t.Fatalf("helper process failed: %v, output=%s", err, string(out))
|
t.Fatalf("helper process failed: %v, output=%s", err, string(out))
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(string(out), "[scratchbox] --env startup variables:") {
|
||||||
|
t.Fatalf("helper output missing env startup header, output=%q", string(out))
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(out), "SCRATCHBOX_SERVER_LISTEN_ADDR=127.0.0.1:0") {
|
||||||
|
t.Fatalf("helper output missing expected env var, output=%q", string(out))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMainProcessEnvWithoutScratchboxVarsFails(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
cmd := exec.Command(os.Args[0], "-test.run=TestMainHelperProcess")
|
||||||
|
cmd.Dir = repoRoot(t)
|
||||||
|
cmd.Env = []string{
|
||||||
|
"GO_WANT_MAIN_HELPER=1",
|
||||||
|
"MAIN_HELPER_MODE=env-no-vars",
|
||||||
|
}
|
||||||
|
if err := cmd.Run(); err == nil {
|
||||||
|
t.Fatalf("expected helper process failure when --env has no SCRATCHBOX_* vars")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServerConfigAndEnvMutuallyExclusive(t *testing.T) {
|
func TestServerConfigAndEnvMutuallyExclusive(t *testing.T) {
|
||||||
@@ -256,6 +277,10 @@ func TestMainHelperProcess(t *testing.T) {
|
|||||||
os.Args = []string{"scratchbox", "server", "--env"}
|
os.Args = []string{"scratchbox", "server", "--env"}
|
||||||
main()
|
main()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
case "env-no-vars":
|
||||||
|
os.Args = []string{"scratchbox", "server", "--env"}
|
||||||
|
main()
|
||||||
|
os.Exit(0)
|
||||||
case "storage-fail":
|
case "storage-fail":
|
||||||
cfgPath := os.Getenv("MAIN_HELPER_CONFIG")
|
cfgPath := os.Getenv("MAIN_HELPER_CONFIG")
|
||||||
os.Args = []string{"scratchbox", "server", "--config", cfgPath}
|
os.Args = []string{"scratchbox", "server", "--config", cfgPath}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@@ -45,6 +46,10 @@ func run(configPath string, useEnv bool) error {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if useEnv {
|
if useEnv {
|
||||||
|
envCount := printEnvStartup()
|
||||||
|
if envCount == 0 {
|
||||||
|
return errors.New("no SCRATCHBOX_* environment variables set for --env mode")
|
||||||
|
}
|
||||||
cfg, err = config.LoadFromEnv()
|
cfg, err = config.LoadFromEnv()
|
||||||
} else {
|
} else {
|
||||||
generated, err := ensureConfigFile(configPath)
|
generated, err := ensureConfigFile(configPath)
|
||||||
@@ -123,6 +128,26 @@ func run(configPath string, useEnv bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printEnvStartup() int {
|
||||||
|
entries := make([]string, 0)
|
||||||
|
for _, item := range os.Environ() {
|
||||||
|
if strings.HasPrefix(item, "SCRATCHBOX_") {
|
||||||
|
entries = append(entries, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(entries)
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, "[scratchbox] --env startup variables:")
|
||||||
|
if len(entries) == 0 {
|
||||||
|
fmt.Fprintln(os.Stdout, "[scratchbox] (no SCRATCHBOX_* variables set)")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
for _, item := range entries {
|
||||||
|
fmt.Fprintf(os.Stdout, "[scratchbox] %s\n", item)
|
||||||
|
}
|
||||||
|
return len(entries)
|
||||||
|
}
|
||||||
|
|
||||||
func ensureConfigFile(configPath string) (bool, error) {
|
func ensureConfigFile(configPath string) (bool, error) {
|
||||||
path := strings.TrimSpace(configPath)
|
path := strings.TrimSpace(configPath)
|
||||||
if path == "" {
|
if path == "" {
|
||||||
|
|||||||
@@ -13,12 +13,10 @@ export SCRATCHBOX_SERVER_LISTEN_ADDR
|
|||||||
SCRATCHBOX_SERVER_ACCESS_LOG_FILE_PATH=
|
SCRATCHBOX_SERVER_ACCESS_LOG_FILE_PATH=
|
||||||
export SCRATCHBOX_SERVER_ACCESS_LOG_FILE_PATH
|
export SCRATCHBOX_SERVER_ACCESS_LOG_FILE_PATH
|
||||||
|
|
||||||
# Default to running the server from SCRATCHBOX_* env vars.
|
# Entrypoint is fixed for Docker deployments; custom args are not supported.
|
||||||
if [ "$#" -eq 0 ]; then
|
if [ "$#" -ne 0 ]; then
|
||||||
set -- server --env
|
echo "custom entrypoint arguments are not supported; configure via SCRATCHBOX_* env vars" >&2
|
||||||
elif [ "${1#-}" != "$1" ]; then
|
exit 2
|
||||||
# Allow passing server flags directly, e.g. `docker run ... --env`.
|
|
||||||
set -- server --env "$@"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec scratchbox "$@"
|
exec scratchbox server --env
|
||||||
|
|||||||
Reference in New Issue
Block a user