Last active
October 3, 2022 14:56
-
-
Save sdboyer/b55ada925904c8e61a543c36907d3284 to your computer and use it in GitHub Desktop.
rapidly prototyped demo of thema and codegen for loki config file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package lokicfg | |
import "github.com/grafana/thema" | |
// - MIGHT be helpful for them if there could be an init command that tries to start from Go structs | |
// - Probably need to generate YAML struct tags | |
thema.#Lineage | |
name: "lokicfg" | |
seqs: [ | |
{ | |
schemas: [ | |
// v0.0 | |
{ | |
server: { | |
port: int32 | |
} | |
}, | |
// v0.1 | |
{ | |
server: { | |
port: int32 | |
tlsVersion: int32 & (*1 | 2) | |
} | |
} | |
] | |
}, | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// WE'RE IMAGINING THIS FILE IS AUTOGENERATED | |
package lokicfg | |
import ( | |
"embed" | |
"sync" | |
"cuelang.org/go/cue/cuecontext" | |
"github.com/grafana/thema" | |
"github.com/grafana/thema/load" | |
"github.com/grafana/thema/vmux" | |
) | |
type Lokicfg struct { | |
Server struct { | |
Port int32 `json:"port"` | |
TlsVersion int32 `json:"tlsVersion"` | |
} `json:"server"` | |
} | |
// vars representing the state of the lineage cue file | |
var ( | |
//go:embed lokicfg.cue | |
cueFS embed.FS | |
currentVersion = thema.SV(0, 1) | |
) | |
// vars for handling caching of the lineage factory output | |
var ( | |
lineageOnce sync.Once | |
clin thema.ConvergentLineage[*Lokicfg] | |
clinerr error | |
) | |
var allctx = cuecontext.New() | |
var allrt = thema.NewRuntime(allctx) | |
// type guard | |
var _ thema.ConvergentLineageFactory[*Lokicfg] = Lineage | |
func init() { | |
// It's probably useful to trigger this on init, and panic right away if there's | |
// a problem, as the only possible fix is updating lokicfg.cue. | |
_, err := Lineage(allrt) | |
if err != nil { | |
panic(err) | |
} | |
} | |
func Lineage(rt *thema.Runtime, opt ...thema.BindOption) (thema.ConvergentLineage[*Lokicfg], error) { | |
if rt == nil || rt == allrt { | |
lineageOnce.Do(func() { | |
// This freezes the thema.BindOption set to whatever is passed in on the first | |
// call. That could be problematic in the future, but for now the set is really | |
// small. | |
clin, clinerr = doLineage(allrt, opt...) | |
}) | |
return clin, clinerr | |
} | |
return doLineage(rt, opt...) | |
} | |
func doLineage(rt *thema.Runtime, opt ...thema.BindOption) (thema.ConvergentLineage[*Lokicfg], error) { | |
linval, err := load.InstancesWithThema(cueFS, ".") | |
if err != nil { | |
return nil, err | |
} | |
// this returns a thema.Lineage | |
lin, err := thema.BindLineage(rt.Context().BuildInstance(linval), rt) | |
if err != nil { | |
// This would error out if you have a generally invalid lineage - | |
// e.g., schemas don't follow backwards compatibility rules, | |
// lenses are incomplete, etc.; all the general invariants Thema | |
// aims to provide over all lineages | |
return nil, err | |
} | |
sch, _ := lin.Schema(currentVersion) | |
tsch, err := thema.BindType[*Lokicfg](sch, &Lokicfg{}) | |
if err != nil { | |
// This would error out if the Lokicfg isn't assignable to the 0.1 schema. | |
// This should be unreachable, barring a critical bug in Thema's Go generator. | |
return nil, err | |
} | |
return tsch.ConvergentLineage(), nil | |
} | |
func GimmeValueMux(rt *thema.Runtime) vmux.ValueMux[*Lokicfg] { | |
lin, err := Lineage(rt) | |
if err != nil { | |
panic(err) | |
} | |
return vmux.NewValueMux(lin.TypedSchema(), vmux.NewYAMLEndec("conf.yaml")) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment