fetch_ml/cmd/configlint/main.go
Jeremie Fraeys 803677be57 feat: implement Go backend with comprehensive API and internal packages
- Add API server with WebSocket support and REST endpoints
- Implement authentication system with API keys and permissions
- Add task queue system with Redis backend and error handling
- Include storage layer with database migrations and schemas
- Add comprehensive logging, metrics, and telemetry
- Implement security middleware and network utilities
- Add experiment management and container orchestration
- Include configuration management with smart defaults
2025-12-04 16:53:53 -05:00

116 lines
2.4 KiB
Go

package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"github.com/xeipuuv/gojsonschema"
"gopkg.in/yaml.v3"
)
func main() {
var (
schemaPath string
failFast bool
)
flag.StringVar(&schemaPath, "schema", "configs/schema.yaml", "Path to JSON schema in YAML format")
flag.BoolVar(&failFast, "fail-fast", false, "Stop on first error")
flag.Parse()
if flag.NArg() == 0 {
log.Fatalf("usage: configlint [--schema path] [--fail-fast] <config files...>")
}
schemaLoader, err := loadSchema(schemaPath)
if err != nil {
log.Fatalf("failed to load schema: %v", err)
}
var hadError bool
for _, configPath := range flag.Args() {
if err := validateConfig(schemaLoader, configPath); err != nil {
hadError = true
fmt.Fprintf(os.Stderr, "configlint: %s: %v\n", configPath, err)
if failFast {
os.Exit(1)
}
}
}
if hadError {
os.Exit(1)
}
fmt.Println("All configuration files are valid.")
}
func loadSchema(schemaPath string) (gojsonschema.JSONLoader, error) {
data, err := os.ReadFile(schemaPath)
if err != nil {
return nil, err
}
var schemaYAML interface{}
if err := yaml.Unmarshal(data, &schemaYAML); err != nil {
return nil, err
}
schemaJSON, err := json.Marshal(schemaYAML)
if err != nil {
return nil, err
}
tmpFile, err := os.CreateTemp("", "fetchml-schema-*.json")
if err != nil {
return nil, err
}
defer tmpFile.Close()
if _, err := tmpFile.Write(schemaJSON); err != nil {
return nil, err
}
return gojsonschema.NewReferenceLoader("file://" + filepath.ToSlash(tmpFile.Name())), nil
}
func validateConfig(schemaLoader gojsonschema.JSONLoader, configPath string) error {
data, err := os.ReadFile(configPath)
if err != nil {
return err
}
var configYAML interface{}
if err := yaml.Unmarshal(data, &configYAML); err != nil {
return fmt.Errorf("failed to parse YAML: %w", err)
}
configJSON, err := json.Marshal(configYAML)
if err != nil {
return err
}
result, err := gojsonschema.Validate(schemaLoader, gojsonschema.NewBytesLoader(configJSON))
if err != nil {
return err
}
if result.Valid() {
fmt.Printf("%s: valid\n", configPath)
return nil
}
var builder strings.Builder
for _, issue := range result.Errors() {
builder.WriteString("- ")
builder.WriteString(issue.String())
builder.WriteByte('\n')
}
return fmt.Errorf("validation failed:\n%s", builder.String())
}