Add Promptkit configuration and inspection seams
This commit is contained in:
@@ -28,6 +28,7 @@ type Config struct {
|
||||
Notify NotifyConfig `yaml:"notify"`
|
||||
MissingSource MissingSourceConfig `yaml:"missing_source"`
|
||||
Scriptorium ScriptoriumConfig `yaml:"scriptorium"`
|
||||
Promptkit PromptkitConfig `yaml:"promptkit"`
|
||||
Workspace WorkspaceConfig `yaml:"workspace"`
|
||||
Dayparts []DaypartConfig `yaml:"dayparts"`
|
||||
RecentChange RecentChangeConfig `yaml:"recent_change"`
|
||||
@@ -89,6 +90,19 @@ type ScriptoriumConfig struct {
|
||||
ExtraArgs []string `yaml:"extra_args"`
|
||||
}
|
||||
|
||||
type PromptkitConfig struct {
|
||||
Profile string `yaml:"profile"`
|
||||
ProfileFile string `yaml:"profile_file"`
|
||||
ProfileDir string `yaml:"profile_dir"`
|
||||
Timeout time.Duration `yaml:"timeout"`
|
||||
Local PromptkitLocalConfig `yaml:"local"`
|
||||
}
|
||||
|
||||
type PromptkitLocalConfig struct {
|
||||
Endpoint string `yaml:"endpoint"`
|
||||
ConcurrencyLimit int `yaml:"concurrency_limit"`
|
||||
}
|
||||
|
||||
type WorkspaceConfig struct {
|
||||
Root string `yaml:"root"`
|
||||
SnapshotsDir string `yaml:"snapshots_dir"`
|
||||
|
||||
@@ -47,6 +47,12 @@ func Defaults() Config {
|
||||
Binary: "scriptorium",
|
||||
Timeout: 2 * time.Minute,
|
||||
},
|
||||
Promptkit: PromptkitConfig{
|
||||
Timeout: 2 * time.Minute,
|
||||
Local: PromptkitLocalConfig{
|
||||
ConcurrencyLimit: 1,
|
||||
},
|
||||
},
|
||||
Workspace: WorkspaceConfig{
|
||||
Root: "workspace",
|
||||
SnapshotsDir: "snapshots",
|
||||
|
||||
101
internal/config/promptkit_test.go
Normal file
101
internal/config/promptkit_test.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func TestPromptkitDefaultsAndYAML(t *testing.T) {
|
||||
cfg := Defaults()
|
||||
if cfg.Promptkit.Timeout != 2*time.Minute || cfg.Promptkit.Local.ConcurrencyLimit != 1 {
|
||||
t.Fatalf("Promptkit defaults = %#v", cfg.Promptkit)
|
||||
}
|
||||
if err := yaml.Unmarshal([]byte(`
|
||||
promptkit:
|
||||
profile: selected
|
||||
profile_file: /etc/weatherreporter/profile.yml
|
||||
timeout: 45s
|
||||
local:
|
||||
endpoint: http://127.0.0.1:8080
|
||||
concurrency_limit: 0
|
||||
`), &cfg); err != nil {
|
||||
t.Fatalf("Unmarshal() error = %v", err)
|
||||
}
|
||||
if cfg.Promptkit.Profile != "selected" || cfg.Promptkit.ProfileFile != "/etc/weatherreporter/profile.yml" || cfg.Promptkit.Timeout != 45*time.Second || cfg.Promptkit.Local.Endpoint != "http://127.0.0.1:8080" || cfg.Promptkit.Local.ConcurrencyLimit != 0 {
|
||||
t.Fatalf("Promptkit YAML = %#v", cfg.Promptkit)
|
||||
}
|
||||
if err := Validate(cfg); err != nil {
|
||||
t.Fatalf("Validate() error = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidatePromptkit(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*PromptkitConfig)
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "profile sources conflict",
|
||||
mutate: func(cfg *PromptkitConfig) {
|
||||
cfg.ProfileFile = "profile.yml"
|
||||
cfg.ProfileDir = "profiles"
|
||||
},
|
||||
wantErr: "profile_file",
|
||||
},
|
||||
{
|
||||
name: "nonpositive timeout",
|
||||
mutate: func(cfg *PromptkitConfig) {
|
||||
cfg.Timeout = 0
|
||||
},
|
||||
wantErr: "timeout",
|
||||
},
|
||||
{
|
||||
name: "invalid local endpoint",
|
||||
mutate: func(cfg *PromptkitConfig) {
|
||||
cfg.Local.Endpoint = "not a URL"
|
||||
},
|
||||
wantErr: "local.endpoint",
|
||||
},
|
||||
{
|
||||
name: "negative local concurrency",
|
||||
mutate: func(cfg *PromptkitConfig) {
|
||||
cfg.Local.ConcurrencyLimit = -1
|
||||
},
|
||||
wantErr: "concurrency_limit",
|
||||
},
|
||||
{
|
||||
name: "unlimited local concurrency",
|
||||
mutate: func(cfg *PromptkitConfig) {
|
||||
cfg.Local.Endpoint = "http://127.0.0.1:8080"
|
||||
cfg.Local.ConcurrencyLimit = 0
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "unregistered local backend",
|
||||
mutate: func(cfg *PromptkitConfig) {
|
||||
cfg.Local.Endpoint = ""
|
||||
cfg.Local.ConcurrencyLimit = 1
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
cfg := Defaults()
|
||||
test.mutate(&cfg.Promptkit)
|
||||
err := Validate(cfg)
|
||||
if test.wantErr == "" {
|
||||
if err != nil {
|
||||
t.Fatalf("Validate() error = %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err == nil || !strings.Contains(err.Error(), test.wantErr) {
|
||||
t.Fatalf("Validate() error = %v, want %q", err, test.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,9 @@ func Validate(cfg Config) error {
|
||||
if cfg.Scriptorium.Timeout <= 0 {
|
||||
return fmt.Errorf("scriptorium.timeout must be greater than zero")
|
||||
}
|
||||
if err := validatePromptkit(cfg.Promptkit); err != nil {
|
||||
return err
|
||||
}
|
||||
if cfg.Workspace.Root == "" {
|
||||
return fmt.Errorf("workspace.root is required")
|
||||
}
|
||||
@@ -85,6 +88,25 @@ func Validate(cfg Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validatePromptkit(cfg PromptkitConfig) error {
|
||||
if cfg.ProfileFile != "" && cfg.ProfileDir != "" {
|
||||
return fmt.Errorf("promptkit.profile_file and promptkit.profile_dir cannot both be configured")
|
||||
}
|
||||
if cfg.Timeout <= 0 {
|
||||
return fmt.Errorf("promptkit.timeout must be greater than zero")
|
||||
}
|
||||
if cfg.Local.Endpoint != "" {
|
||||
parsed, err := url.Parse(cfg.Local.Endpoint)
|
||||
if err != nil || parsed.Scheme == "" || parsed.Host == "" {
|
||||
return fmt.Errorf("promptkit.local.endpoint must be an absolute URL when configured")
|
||||
}
|
||||
}
|
||||
if cfg.Local.ConcurrencyLimit < 0 {
|
||||
return fmt.Errorf("promptkit.local.concurrency_limit must be zero or greater")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateDistributorNotify(cfg DistributorNotifyConfig) error {
|
||||
if !cfg.Enabled {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user