mirror of
https://github.com/hanzoai/o11y-foundry.git
synced 2026-10-30 18:26:45 +00:00
## Summary - Wires schema-based validation of `casting.yaml` at config load time. Schema is generated from the Go types via `swaggest/jsonschema-go`, embedded as `api/v1alpha1/schema.json`, and validated post-merge with `google/jsonschema-go`. - Adds field-level rules: `required`, `enum`, `pattern` (DNS-1123 name, JSON Pointer paths, OCI image), `minimum`/`minLength`/`minItems` on the relevant fields. `additionalProperties:false` is set on every nested type for the published schema. - Replaces the loose string `Platform` / `Mode` / `Flavor` on `TypeDeployment` with typed enums following the existing `*Kind` pattern. Bad values now fail at unmarshal with a clear "invalid deployment …" message. - Drops `InfrastructureProvider` in favor of `Platform` — the cloud subset (aws, gcp, azure) drives the Terraform IaC pipeline directly. `ResolveProvider` collapses `PlatformECS → PlatformAWS`. - Side cleanups bundled here: typed errors in `internal/errors` with stacktrace capture (used by yamlconfig to wrap validation failures as `TypeInvalidInput`), and removal of the custom pretty slog handler in `internal/instrumentation` in favor of `slog.NewJSONHandler`. ## Test plan - [ ] `make gen-schemas` is idempotent (CI's `schemas` job stays green). - [ ] `go test ./...` passes locally. - [ ] Every committed example casting (`docs/examples/**/casting.yaml`, `docs/standalone/casting.yaml`) loads without error. - [ ] Negative cases at config load: bad `apiVersion`, missing required fields, unknown enum values for `kind` / `mode` / `flavor` / `platform` / patch `op`, non-JSON-Pointer patch paths, negative `replicas`, `shards: 0`, malformed image refs — each fails with a `TypeInvalidInput` error pointing at the offending location. - [ ] `foundryctl forge` against `docs/examples/docker/compose/casting.yaml` still produces the expected pours.
102 lines
2.1 KiB
Go
102 lines
2.1 KiB
Go
package v1alpha1
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/swaggest/jsonschema-go"
|
|
"go.yaml.in/yaml/v3"
|
|
)
|
|
|
|
var _ yaml.Marshaler = (*Flavor)(nil)
|
|
var _ yaml.Unmarshaler = (*Flavor)(nil)
|
|
var _ json.Marshaler = (*Flavor)(nil)
|
|
var _ json.Unmarshaler = (*Flavor)(nil)
|
|
var _ fmt.Stringer = (*Flavor)(nil)
|
|
var _ jsonschema.Enum = (*Flavor)(nil)
|
|
|
|
var (
|
|
FlavorCompose Flavor = Flavor{s: "compose"}
|
|
FlavorSwarm Flavor = Flavor{s: "swarm"}
|
|
FlavorBinary Flavor = Flavor{s: "binary"}
|
|
FlavorKustomize Flavor = Flavor{s: "kustomize"}
|
|
FlavorHelm Flavor = Flavor{s: "helm"}
|
|
FlavorBlueprint Flavor = Flavor{s: "blueprint"}
|
|
FlavorStack Flavor = Flavor{s: "stack"}
|
|
FlavorTemplate Flavor = Flavor{s: "template"}
|
|
FlavorTerraform Flavor = Flavor{s: "terraform"}
|
|
)
|
|
|
|
type Flavor struct {
|
|
s string
|
|
}
|
|
|
|
func (flavor Flavor) String() string {
|
|
return flavor.s
|
|
}
|
|
|
|
func Flavors() []Flavor {
|
|
return []Flavor{
|
|
FlavorCompose,
|
|
FlavorSwarm,
|
|
FlavorBinary,
|
|
FlavorKustomize,
|
|
FlavorHelm,
|
|
FlavorBlueprint,
|
|
FlavorStack,
|
|
FlavorTemplate,
|
|
FlavorTerraform,
|
|
}
|
|
}
|
|
|
|
func (flavor Flavor) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(flavor.String())
|
|
}
|
|
|
|
func (flavor *Flavor) UnmarshalJSON(text []byte) error {
|
|
var str string
|
|
if err := json.Unmarshal(text, &str); err != nil {
|
|
return err
|
|
}
|
|
|
|
return flavor.UnmarshalText([]byte(str))
|
|
}
|
|
|
|
func (flavor *Flavor) UnmarshalText(text []byte) error {
|
|
for _, available := range Flavors() {
|
|
if available.String() == string(text) {
|
|
*flavor = available
|
|
return nil
|
|
}
|
|
}
|
|
|
|
if len(text) == 0 {
|
|
*flavor = Flavor{s: ""}
|
|
return nil
|
|
}
|
|
|
|
return errors.New("invalid deployment flavor: " + string(text))
|
|
}
|
|
|
|
func (flavor Flavor) MarshalText() ([]byte, error) {
|
|
return []byte(flavor.String()), nil
|
|
}
|
|
|
|
func (flavor *Flavor) UnmarshalYAML(node *yaml.Node) error {
|
|
return flavor.UnmarshalText([]byte(node.Value))
|
|
}
|
|
|
|
func (flavor Flavor) MarshalYAML() (any, error) {
|
|
return flavor.String(), nil
|
|
}
|
|
|
|
func (flavor Flavor) Enum() []any {
|
|
flavors := []any{}
|
|
for _, flavor := range Flavors() {
|
|
flavors = append(flavors, flavor.String())
|
|
}
|
|
|
|
return flavors
|
|
}
|