Add generate-config command to output default configuration in YAML format
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -26,5 +26,6 @@ func newRootCmd() *cobra.Command {
|
||||
},
|
||||
}
|
||||
cmd.AddCommand(newServerCmd())
|
||||
cmd.AddCommand(newGenerateConfigCmd())
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user