Add generate-config command to output default configuration in YAML format

This commit is contained in:
2026-05-31 17:46:02 -05:00
parent 900b1a0165
commit 9e398957a9
3 changed files with 109 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
package main
import (
"fmt"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
"scratchbox/internal/config"
)
func newGenerateConfigCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "generate-config",
Short: "Print a default config YAML to stdout",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) error {
return writeDefaultConfig(cmd)
},
}
return cmd
}
func writeDefaultConfig(cmd *cobra.Command) error {
cfg := config.Config{
Server: config.ServerConfig{
ListenAddr: ":8080",
},
Limits: config.LimitsConfig{
MaxUploadSize: "100MB",
DefaultTTL: "1h",
},
Storage: config.StorageConfig{
DataDir: "./data",
CleanupInterval: "1m",
},
Security: config.SecurityConfig{
AllowedIPs: []string{},
TrustProxyHeaders: false,
RateLimit: config.RateLimitConfig{
Enabled: true,
RequestsPerMinute: 30,
Burst: 10,
},
},
}
b, err := yaml.Marshal(cfg)
if err != nil {
return fmt.Errorf("marshal default config: %w", err)
}
if _, err := cmd.OutOrStdout().Write(b); err != nil {
return fmt.Errorf("write default config: %w", err)
}
return nil
}
+1
View File
@@ -26,5 +26,6 @@ func newRootCmd() *cobra.Command {
},
}
cmd.AddCommand(newServerCmd())
cmd.AddCommand(newGenerateConfigCmd())
return cmd
}
+50
View File
@@ -19,6 +19,7 @@ import (
"scratchbox/internal/config"
httpapi "scratchbox/internal/http"
"scratchbox/internal/storage"
"gopkg.in/yaml.v3"
)
func repoRoot(t *testing.T) string {
@@ -205,6 +206,55 @@ func TestMainHelperProcess(t *testing.T) {
}
}
func TestGenerateConfigCommandWritesDefaultYAML(t *testing.T) {
t.Parallel()
cmd := newRootCmd()
var out bytes.Buffer
cmd.SetOut(&out)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"generate-config"})
if err := cmd.Execute(); err != nil {
t.Fatalf("Execute() error = %v", err)
}
if out.Len() == 0 {
t.Fatalf("generate-config output is empty")
}
var cfg config.Config
if err := yaml.Unmarshal(out.Bytes(), &cfg); err != nil {
t.Fatalf("yaml.Unmarshal() error = %v", err)
}
if cfg.Server.ListenAddr != ":8080" {
t.Fatalf("server.listen_addr = %q, want %q", cfg.Server.ListenAddr, ":8080")
}
if cfg.Limits.MaxUploadSize != "100MB" {
t.Fatalf("limits.max_upload_size = %q, want %q", cfg.Limits.MaxUploadSize, "100MB")
}
if cfg.Storage.DataDir != "./data" {
t.Fatalf("storage.data_dir = %q, want %q", cfg.Storage.DataDir, "./data")
}
if cfg.Security.RateLimit.RequestsPerMinute != 30 {
t.Fatalf("security.rate_limit.requests_per_minute = %d, want %d", cfg.Security.RateLimit.RequestsPerMinute, 30)
}
}
func TestGenerateConfigCommandRejectsUnexpectedArgs(t *testing.T) {
t.Parallel()
cmd := newRootCmd()
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"generate-config", "extra"})
if err := cmd.Execute(); err == nil {
t.Fatalf("expected error for unexpected args")
}
}
func TestLiveServerEndToEndHTTP(t *testing.T) {
tmp := t.TempDir()
cfgPath := filepath.Join(tmp, "config.yaml")