Extend envoy to support resource translations

This commit is contained in:
Tomaž Jerman
2021-09-22 11:26:14 +02:00
parent a33856b66c
commit 895b40da36
38 changed files with 1891 additions and 57 deletions
@@ -0,0 +1,31 @@
package {{ .Package }}
{{ template "header-gentext.tpl" }}
{{ template "header-definitions.tpl" . }}
import (
systemTypes "github.com/cortezaproject/corteza-server/system/types"
{{- range .Imports }}
{{ . }}
{{- end }}
)
{{- range .Def }}
{{ $Component := .Component }}
{{ $Resource := .Resource }}
{{ $GoType := printf "types.%s" .Resource }}
func (r *{{export $Component}}{{$Resource}}) EncodeTranslations() ([]*ResourceTranslation, error) {
out := make([]*ResourceTranslation, 0, 10)
rr := r.Res.EncodeTranslations()
rr.SetLanguage(defaultLanguage)
res, ref, pp := r.ResourceTranslationParts()
out = append(out, NewResourceTranslation(systemTypes.FromLocale(rr), res, ref, pp...))
{{ if .Locale.Extended }}
tmp, err := r.encodeTranslations()
return append(out, tmp...), err
{{ else }}
return out, nil
{{- end }}
}
{{- end }}
@@ -0,0 +1,73 @@
package {{ .Package }}
{{ template "header-gentext.tpl" }}
{{ template "header-definitions.tpl" . }}
import (
"fmt"
"strings"
{{- range .Imports }}
{{ . }}
{{- end }}
)
// Parse generates resource setting logic for each resource
//
// Resources with "envoy: false" are skipped
//
// This function is auto-generated
func ParseResourceTranslation(res string) (string, *Ref, []*Ref, error) {
if res == "" {
return "", nil, nil, fmt.Errorf("empty resource")
}
sp := "/"
if strings.Index(res, "corteza::") == 0 {
res = res[9:]
}
res = strings.TrimSpace(res)
res = strings.TrimRight(res, sp)
rr := strings.Split(res, sp)
// only service defined (corteza::system, corteza::compose, ...)
if len(rr) == 1 {
return "", nil, nil, fmt.Errorf("only service defined: %s", res)
}
// full thing
resourceType, path := rr[0], rr[1:]
for p := 1; p < len(path); p++ {
if path[p] == "*" {
return "", nil, nil, fmt.Errorf("path wildcard not allowed for locale resources: '%s'", res)
}
}
// make the resource provide the slice of parent resources we should nest under
switch resourceType {
{{- range .Def }}
case {{ unexport .Component "types" }}.{{ export .Resource }}ResourceTranslationType:
if len(path) != {{ len .Locale.Resource.References }} {
return "", nil, nil, fmt.Errorf("expecting {{ len .Locale.Resource.References }} reference components in path, got %d", len(path))
}
{{- if gt (len .Locale.Resource.References) 0 }}
ref, pp, err := {{ export .Component .Resource }}ResourceTranslationReferences(
{{- range $i, $r := .Locale.Resource.References }}
// {{ unexport $r.Resource }}
path[{{ $i }}],
{{ end }}
)
return {{ unexport .Component "types" }}.{{ export .Resource }}ResourceTranslationType, ref, pp, err
{{ else }}
// Component resource, no path
return {{ unexport .Component "types" }}.{{ export .Resource }}ResourceTranslationType, nil, nil, nil
{{- end }}
{{- end}}
}
// return unhandled resource as-is
return resourceType, nil, nil, nil
}
@@ -0,0 +1,33 @@
package {{ .Package }}
{{ template "header-gentext.tpl" }}
{{ template "header-definitions.tpl" . }}
import (
{{- range .Imports }}
{{ . }}
{{- end }}
)
{{- range .Def }}
{{- if .Locale }}
{{- if gt (len .Locale.Resource.References) 0 }}
// {{ export .Component .Resource }}ResourceTranslationReferences generates Locale references
//
// Resources with "envoy: false" are skipped
//
// This function is auto-generated
func {{ export .Component .Resource }}ResourceTranslationReferences({{- range .Locale.Resource.References }}{{ unexport .Resource }} string, {{- end }}) (res *Ref, pp []*Ref, err error) {
{{- range .Locale.Resource.References }}
{{- if eq .Field "ID" }}
res = &Ref{ResourceType: types.{{ export .Resource }}ResourceType, Identifiers: MakeIdentifiers({{ unexport .Resource }})}
{{- else }}
pp = append(pp, &Ref{ResourceType: types.{{ export .Resource }}ResourceType, Identifiers: MakeIdentifiers({{ unexport .Resource }})})
{{- end }}
{{- end }}
return
}
{{- end }}
{{- end }}
{{- end }}
+86
View File
@@ -13,6 +13,10 @@ func Envoy(t *template.Template, dd []*def.Document) error {
return List{
"resource rbac parse": envoyResourceRbacUnmarshal,
"resource rbac references": envoyResourceRbacReferences,
"resource translation": envoyResourceTranslation,
"resource translation parse": envoyResourceTranslationUnmarshal,
"resource translation references": envoyResourceTranslationReferences,
}.Generate(t, dd)
}
@@ -80,3 +84,85 @@ func envoyResourceRbacReferences(t *template.Template, dd []*def.Document) (err
return
}
func envoyResourceTranslation(t *template.Template, dd []*def.Document) (err error) {
const (
templateName = "envoy/resource-resource_translation.go.tpl"
outputPathTpl = "pkg/envoy/resource/resource_translation.gen.go"
)
dd = filter(dd, func(d *def.Document) bool { return d.Envoy && d.Locale != nil })
// build list of component type imports
ctImports := make([]string, 0)
w := tpl.Wrap{
Package: "resource",
Def: dd,
Imports: append(collectImports(dd...), ctImports...),
}
err = tpl.GoTemplate(outputPathTpl, t.Lookup(templateName), w)
if err != nil {
return
}
return
}
func envoyResourceTranslationUnmarshal(t *template.Template, dd []*def.Document) (err error) {
const (
templateName = "envoy/resource-resource_translation_parse.go.tpl"
outputPathTpl = "pkg/envoy/resource/resource_translation_parse.gen.go"
)
dd = filter(dd, func(d *def.Document) bool { return d.Envoy && d.Locale != nil })
// build list of component type imports
ctImports := make([]string, 0)
for _, d := range dd {
imp := d.Component + "Types " + cImport(d.Component, "types")
if !slice.HasString(ctImports, imp) {
ctImports = append(ctImports, imp)
}
}
w := tpl.Wrap{
Package: "resource",
Def: dd,
Imports: append(collectImports(dd...), ctImports...),
}
err = tpl.GoTemplate(outputPathTpl, t.Lookup(templateName), w)
if err != nil {
return
}
return
}
func envoyResourceTranslationReferences(t *template.Template, dd []*def.Document) (err error) {
const (
templateName = "envoy/resource-resource_translation_references.go.tpl"
outputPathTpl = "pkg/envoy/resource/resource_translation_references_%s.gen.go"
)
dd = filter(dd, func(d *def.Document) bool { return d.Envoy && d.Locale != nil })
for component, perComponent := range partByComponent(dd) {
w := tpl.Wrap{
Package: "resource",
Component: component,
Def: perComponent,
Imports: append(collectImports(perComponent...), cImport(component, "types")),
}
err = tpl.GoTemplate(fmt.Sprintf(outputPathTpl, component), t.Lookup(templateName), w)
if err != nil {
return
}
}
return
}