3
0

Split & move codegen tasks to codegen/Makefile

This commit is contained in:
Denis Arh
2022-03-12 17:38:53 +01:00
parent 1931534c52
commit 9b5586719e
21 changed files with 574 additions and 483 deletions

View File

@@ -27,7 +27,7 @@ jobs:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- run: make test.codegen test.all
- run: make test.all
snapshot-docker:
runs-on: ubuntu-latest

View File

@@ -133,11 +133,8 @@ watch.test.%: $(FSWATCH)
watch.test: watch.test.unit
# See codegen/README.md for details
codegen: $(CUE) $(JSONTPLEXEC)
$(CUE) eval codegen/*.cue --out json -e platform | $(JSONTPLEXEC) -v
test.codegen: $(CUE) $(JSONTPLEXEC)
$(CUE) eval codegen/*.cue --out json -e platform > /dev/null
codegen:
@ make -C codegen all
cue.fmt: $(CUE)
$(CUE) fmt -v codegen/*.cue

View File

@@ -2,6 +2,8 @@ GO = go
GOINSTALL = $(GO) install
GOFLAGS ?= -trimpath
GOPATH ?= $(HOME)/go
ROOT_DIR = $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
CGO_ENABLED = 1
@@ -20,14 +22,17 @@ GIN = $(GOPATH)/bin/gin
STATIK = $(GOPATH)/bin/statik
MODOUTDATED = $(GOPATH)/bin/go-mod-outdated
CUE = $(GOPATH)/bin/cue
CODEGEN = build/codegen
JSONTPLEXEC = build/json-tpl-exec
CODEGEN = $(GOPATH)/bin/corteza-codegen
JSONTPLEXEC = $(GOPATH)/bin/corteza-json-tpl-exec
PROTOC = /usr/local/bin/protoc
FSWATCH = /usr/local/bin/fswatch
# fswatch is intentionally left out...
BINS = $(GOCRITIC) $(MOCKGEN) $(GOTEST) $(STATICCHECK) $(PROTOGEN) $(GIN) $(STATIK) $(CODEGEN)
BINS = $(GOCRITIC) $(MOCKGEN) $(GOTEST) $(STATICCHECK) $(PROTOGEN) $(GIN) $(STATIK)
# Corteza's tools
CORTEZA_BINS = $(CODEGEN) $(JSONTPLEXEC)
########################################################################################################################
@@ -59,16 +64,27 @@ $(STATIK):
$(MODOUTDATED):
$(GOINSTALL) github.com/psampaz/go-mod-outdated@latest
$(CODEGEN):
$(GO) build -o $@ cmd/codegen/main.go
$(CUE):
$(GOINSTALL) cuelang.org/go/cmd/cue@latest
$(CODEGEN):
$(GO) build -o $@ $(ROOT_DIR)/cmd/codegen/main.go
$(JSONTPLEXEC):
$(GO) build -o $@ ./codegen/tool
$(GO) build -o $@ $(ROOT_DIR)/codegen/tool
clean-tools:
rm -f $(BINS)
clean-corteza-tools:
rm -f $(CORTEZA_BINS)
########################################################################################################################
COLOUR_GREEN=\033[0;32m
COLOUR_RED=\033[0;31m
COLOUR_BLUE=\033[0;34m
COLOUR_END=\033[0m
#

1
codegen/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

18
codegen/Makefile Normal file
View File

@@ -0,0 +1,18 @@
.PHONY: *.cue
DEF_ALL = *.cue
DEF_SERVER = server.*.cue
DEF_DOCS = docs.*.cue
all: $(DEF_ALL)
server: $(DEF_SERVER)
docs: $(DEF_DOCS)
include ../Makefile.inc
$(DEF_ALL): $(CUE) $(JSONTPLEXEC)
@ echo "$(COLOUR_GREEN)Generating from $@$(COLOUR_END)"
@ $(CUE) eval $@ --out json | $(JSONTPLEXEC) -v -p ../codegen/assets/templates -b ../
gen:
@ rm $(JSONTPLEXEC)

View File

@@ -34,18 +34,36 @@ Platform, component and resource definitions (.cue files) can be found in:
When a definitions or templates are changed all outputs need to be regenerated
This can be done with the following command
```
This can be done with the following command (the root of the project)
```shell
make codegen
```
Please note that
Inside `/codegen` you can run codegen with different options
```shell
# generate all
make
# generate only server files (golang code, .env.example, ...)
make server
# generate only docs (asciidoc files)
make docs
# generate for only one specific codegen definition
make server.options.cue
make docs.options.cue
# or more of them at once
make server.options.cue docs.options.cue
```
## How does it work?
### High-level overview
See [Makefile's `codegen-cue` task](../Makefile)
See [Makefile's `codegen` task](../Makefile)
1. evaluate codegen instructions (see [platform.cue](./platform.cue))
2. output instructions as JSON
@@ -57,28 +75,8 @@ See [Makefile's `codegen-cue` task](../Makefile)
#### Codegen instructions
Collection of `#codegen` structs with template + payload + output instructions. Template exec tool iterates over collection and creates output from each one.
endpoints (unrelated to specific component)
#### Platform
Main entry point that combines all components
- options (see [options.cue](./options.cue))
- @todo REST endpoints (unrelated to specific component)
#### Component
Defines component, it's behaviour, RBAC operations and resources
- @todo REST endpoints (unrelated to specific resources)
#### Resource
Defines resource, it's behaviour, types, RBAC operations, translatable keys
- @todo events
- @todo actions
- @todo errors
- @todo automation functions
- @todo expression types
- @todo REST endpoints
# Troubleshooting
1. Make sure you have the latest version of cue (0.4.2 or newer)

82
codegen/docs.options.cue Normal file
View File

@@ -0,0 +1,82 @@
package codegen
import (
"strings"
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
)
[...schema.#codegen] &
[
{
template: "gocode/options/options.go.tpl"
output: "pkg/options/options.gen.go"
payload: {
package: "options"
// make unique list of packages we'll import
imports: [ for i in {for g in app.corteza.options for i in g.imports {"\(i)": i}} {i}]
groups: [
for g in app.corteza.options {
func: g.expIdent
struct: g.expIdent + "Opt"
options: [
for o in g.options {
o
default?: string
if (o.defaultGoExpr != _|_) {
default: o.defaultGoExpr
}
if (o.defaultGoExpr == _|_ && o.defaultValue != _|_) {
default: "\"" + o.defaultValue + "\""
}
},
]
},
]
}
},
]+
[
{
template: "docs/.env.example.tpl"
output: ".env.example"
syntax: ".env"
payload: {
groups: [
for g in app.corteza.options {
title: "# " + strings.Join(strings.Split(g.title, "\n"), "\n# ")
if (g.intro != _|_) {
intro: "# " + strings.Join(strings.Split(g.intro, "\n"), "\n# ")
}
options: [
for o in g.options {
handle: o.handle
env: o.env
type: o.type
defaultGoExpr?: string
if (o.defaultGoExpr != _|_) {
defaultGoExpr: o.defaultGoExpr
}
defaultValue?: string
if (o.defaultValue != _|_) {
defaultValue: o.defaultValue
}
if (o.description != _|_) {
description: "# " + strings.Join(strings.Split(o.description, "\n"), "\n# ")
}
},
]
},
]
}
},
]

View File

@@ -1,134 +0,0 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
// "strings"
)
envoyRBAC:
[...schema.#codegen] &
[
for cmp in app.corteza.components {
template: "gocode/envoy/rbac_references_$component.go.tpl"
output: "pkg/envoy/resource/rbac_references_\(cmp.ident).gen.go"
payload: {
package: "resource"
imports: [
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
]
resources: [
for res in cmp.resources {
rbacRefFunc: "\(cmp.expIdent)\(res.expIdent)RbacReferences"
references: [
for p in res.parents {p},
{param: res.ident, refField: "ID", expIdent: res.expIdent},
]
},
]
}
},
]+
[
{
template: "gocode/envoy/rbac_rules_parse.go.tpl"
output: "pkg/envoy/resource/rbac_rules_parse.gen.go"
payload: {
package: "resource"
imports: [
for cmp in app.corteza.components {
"\(cmp.ident)Types \"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\""
},
]
resources: [
for cmp in app.corteza.components for res in cmp.resources {
importAlias: "\(cmp.ident)Types"
expIdent: res.expIdent
typeConst: "\(importAlias).\(expIdent)ResourceType"
rbacRefFunc: "\(cmp.expIdent)\(res.expIdent)RbacReferences"
references: [
for p in res.parents {p},
{param: res.ident, refField: "ID", expIdent: res.expIdent},
]
},
for cmp in app.corteza.components {
importAlias: "\(cmp.ident)Types"
expIdent: cmp.expIdent
typeConst: "\(importAlias).ComponentResourceType"
references: []
},
]
}
},
]+
[
{
template: "gocode/envoy/resource_translation.go.tpl"
output: "pkg/envoy/resource/resource_translation.gen.go"
payload: {
package: "resource"
resources: [
for cmp in app.corteza.components for res in cmp.resources if res.locale != _|_ {
expIdent: "\(cmp.expIdent)\(res.expIdent)"
extended: res.locale.extended
},
]
}
},
]+
[
{
template: "gocode/envoy/resource_translation_parse.go.tpl"
output: "pkg/envoy/resource/resource_translation_parse.gen.go"
payload: {
package: "resource"
imports: [
for cmp in app.corteza.components for res in cmp.resources if res.locale != _|_ {
"\(cmp.ident)Types \"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\""
},
]
resources: [
for cmp in app.corteza.components for res in cmp.resources if res.locale != _|_ {
importAlias: "\(cmp.ident)Types"
typeConst: "\(importAlias).\(res.expIdent)ResourceTranslationType"
resTrRefFunc: "\(cmp.expIdent)\(res.expIdent)ResourceTranslationReferences"
references: [
for p in res.parents {p},
{param: res.ident, refField: "ID", expIdent: res.expIdent},
]
},
]
}
},
]+
[
// wrapped with additional for loop to trim out templates with empty types list
for tpl in [
for cmp in app.corteza.components {
template: "gocode/envoy/resource_translation_references_$component.go.tpl"
output: "pkg/envoy/resource/resource_translation_references_\(cmp.ident).gen.go"
payload: {
package: "resource"
imports: [
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
]
resources: [
for res in cmp.resources if res.locale != _|_ {
resTrRefFunc: "\(cmp.expIdent)\(res.expIdent)ResourceTranslationReferences"
expIdent: res.expIdent
references: [
for p in res.parents {p},
]
},
]
}
},
] if len(tpl.payload.resources) > 0 {tpl}]+
[]

View File

@@ -1,43 +0,0 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
)
localeService:
[...schema.#codegen] &
[
// wrapped with additional for loop to trim out templates with empty types list
for tpl in [
for cmp in app.corteza.components {
template: "gocode/locale/$component_service.go.tpl"
output: "\(cmp.ident)/service/locale.gen.go"
payload: {
package: "service"
imports: [
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
]
resources: [
for res in cmp.resources if (res.locale != _|_) if (!res.locale.skipSvc) {
expIdent: res.expIdent
ident: res.ident
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
extended: res.locale.extended
keys: [ for key in res.locale.keys if key.handlerFunc == _|_ {
struct: key.struct
"extended": extended
customHandler: key.customHandler
if key.serviceFunc != _|_ {serviceFunc: key.serviceFunc}
}]
},
]
}
},
// skip empty type lists
] if len(tpl.payload.resources) > 0 {tpl}]

View File

@@ -1,55 +0,0 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
"strings"
)
localeTypes:
[...schema.#codegen] &
[
// wrapped with additional for loop to trim out templates with empty types list
for tpl in [
for cmp in app.corteza.components {
template: "gocode/locale/$component_types.go.tpl"
output: "\(cmp.ident)/types/locale.gen.go"
payload: {
package: "types"
resources: [
for res in cmp.resources if res.locale != _|_ {
expIdent: res.expIdent
const: res.locale.resource.const
type: res.locale.resource.type
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
extended: res.locale.extended
keys: [ for key in res.locale.keys if key.handlerFunc == _|_ {
struct: key.struct
field: strings.ToTitle(key.name)
path: strings.Join([ for p in key.expandedPath {
if p.var {"{{\(p.part)}}"}
if !p.var {p.part}
}], ".")
if !key.customHandler {
fieldPath: strings.Join([ for p in key.expandedPath {
strings.ToTitle(p.part)
}], ".")
}
"extended": extended
if key.decodeFunc != _|_ {decodeFunc: key.decodeFunc}
if key.encodeFunc != _|_ {encodeFunc: key.encodeFunc}
}]
},
]
}
},
// skip empty type lists
] if len(tpl.payload.resources) > 0 {tpl}]

View File

@@ -1,85 +0,0 @@
package codegen
import (
"strings"
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
)
options:
[...schema.#codegen] &
[
{
template: "gocode/options/options.go.tpl"
output: "pkg/options/options.gen.go"
payload: {
package: "options"
// make unique list of packages we'll import
imports: [ for i in {for g in app.corteza.options for i in g.imports {"\(i)": i}} {i}]
groups: [
for g in app.corteza.options {
func: g.expIdent
struct: g.expIdent + "Opt"
options: [
for o in g.options {
o
default?: string
if (o.defaultGoExpr != _|_) {
default: o.defaultGoExpr
}
if (o.defaultGoExpr == _|_ && o.defaultValue != _|_) {
default: "\"" + o.defaultValue + "\""
}
},
]
},
]
}
},
]+
[
{
template: "docs/.env.example.tpl"
output: ".env.example"
syntax: ".env"
payload: {
groups: [
for g in app.corteza.options {
title: "# " + strings.Join(strings.Split(g.title, "\n"), "\n# ")
if (g.intro != _|_) {
intro: "# " + strings.Join(strings.Split(g.intro, "\n"), "\n# ")
}
options: [
for o in g.options {
handle: o.handle
env: o.env
type: o.type
defaultGoExpr?: string
if (o.defaultGoExpr != _|_) {
defaultGoExpr: o.defaultGoExpr
}
defaultValue?: string
if (o.defaultValue != _|_) {
defaultValue: o.defaultValue
}
if (o.description != _|_) {
description: "# " + strings.Join(strings.Split(o.description, "\n"), "\n# ")
}
},
]
},
]
}
},
]+
[]

View File

@@ -1,19 +0,0 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/codegen/schema"
)
// List of all codegen jobs for the entire platform
//
// How to run it?
// @todo when this gets into
// cue eval codegen/*.cue --out json -e platform | go run codegen/tool/*.go -v
platform: [...schema.#codegen] &
rbacAccessControl+
rbacTypes+
localeTypes+
localeService+
envoyRBAC+
options+
[] // placeholder

View File

@@ -1,62 +0,0 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/codegen/schema"
"github.com/cortezaproject/corteza-server/app"
)
rbacAccessControl:
[...schema.#codegen] &
[
for cmp in app.corteza.components {
template: "gocode/rbac/$component_access_control.go.tpl"
output: "\(cmp.ident)/service/access_control.gen.go"
payload: {
package: "service"
imports: [
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
]
// All possible RBAC operations on component and resources
// flattened
operations: [
for res in cmp.resources for op in res.rbac.operations {
"op": op.handle
const: "types.\(res.expIdent)ResourceType"
resFunc: "types.\(res.expIdent)RbacResource"
goType: "types.\(res.expIdent)"
description: op.description
checkFuncName: op.checkFuncName
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
},
for op in cmp.rbac.operations {
"op": op.handle
const: "types.ComponentResourceType"
resFunc: "types.ComponentRbacResource"
goType: "types.Component"
description: op.description
checkFuncName: op.checkFuncName
component: true
},
]
// Operation/resource validators, grouped by resource
validation: [
for res in cmp.resources {
label: res.ident
const: "types.\(res.expIdent)ResourceType"
funcName: "rbac\(res.expIdent)ResourceValidator"
references: [ for p in res.parents {p.refField}, "ID"]
operations: [ for op in res.rbac.operations {op.handle}]
},
{
label: "\(cmp.ident) component"
const: "types.ComponentResourceType"
funcName: "rbacComponentResourceValidator"
operations: [ for op in cmp.rbac.operations {op.handle}]
},
]
}
},
]

View File

@@ -1,42 +0,0 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
)
rbacTypes:
[...schema.#codegen] &
[
for cmp in app.corteza.components {
template: "gocode/rbac/$component_types.go.tpl"
output: "\(cmp.ident)/types/rbac.gen.go"
payload: {
package: "types"
cmpIdent: cmp.ident
// Operation/resource validators, grouped by resource
types: [
for res in cmp.resources {
const: "\(res.expIdent)ResourceType"
type: res.fqrn
resFunc: "\(res.expIdent)RbacResource"
tplFunc: "\(res.expIdent)RbacResourceTpl"
attFunc: "\(res.expIdent)RbacAttributes"
goType: res.expIdent
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
},
{
const: "ComponentResourceType"
type: cmp.fqrn
resFunc: "ComponentRbacResource"
tplFunc: "ComponentRbacResourceTpl"
attFunc: "ComponentRbacAttributes"
goType: "Component"
component: true
},
]
}
},
]

View File

@@ -0,0 +1,133 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
// "strings"
)
[...schema.#codegen] &
[
for cmp in app.corteza.components {
template: "gocode/envoy/rbac_references_$component.go.tpl"
output: "pkg/envoy/resource/rbac_references_\(cmp.ident).gen.go"
payload: {
package: "resource"
imports: [
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
]
resources: [
for res in cmp.resources {
rbacRefFunc: "\(cmp.expIdent)\(res.expIdent)RbacReferences"
references: [
for p in res.parents {p},
{param: res.ident, refField: "ID", expIdent: res.expIdent},
]
},
]
}
},
]+
[
{
template: "gocode/envoy/rbac_rules_parse.go.tpl"
output: "pkg/envoy/resource/rbac_rules_parse.gen.go"
payload: {
package: "resource"
imports: [
for cmp in app.corteza.components {
"\(cmp.ident)Types \"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\""
},
]
resources: [
for cmp in app.corteza.components for res in cmp.resources {
importAlias: "\(cmp.ident)Types"
expIdent: res.expIdent
typeConst: "\(importAlias).\(expIdent)ResourceType"
rbacRefFunc: "\(cmp.expIdent)\(res.expIdent)RbacReferences"
references: [
for p in res.parents {p},
{param: res.ident, refField: "ID", expIdent: res.expIdent},
]
},
for cmp in app.corteza.components {
importAlias: "\(cmp.ident)Types"
expIdent: cmp.expIdent
typeConst: "\(importAlias).ComponentResourceType"
references: []
},
]
}
},
]+
[
{
template: "gocode/envoy/resource_translation.go.tpl"
output: "pkg/envoy/resource/resource_translation.gen.go"
payload: {
package: "resource"
resources: [
for cmp in app.corteza.components for res in cmp.resources if res.locale != _|_ {
expIdent: "\(cmp.expIdent)\(res.expIdent)"
extended: res.locale.extended
},
]
}
},
]+
[
{
template: "gocode/envoy/resource_translation_parse.go.tpl"
output: "pkg/envoy/resource/resource_translation_parse.gen.go"
payload: {
package: "resource"
imports: [
for cmp in app.corteza.components for res in cmp.resources if res.locale != _|_ {
"\(cmp.ident)Types \"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\""
},
]
resources: [
for cmp in app.corteza.components for res in cmp.resources if res.locale != _|_ {
importAlias: "\(cmp.ident)Types"
typeConst: "\(importAlias).\(res.expIdent)ResourceTranslationType"
resTrRefFunc: "\(cmp.expIdent)\(res.expIdent)ResourceTranslationReferences"
references: [
for p in res.parents {p},
{param: res.ident, refField: "ID", expIdent: res.expIdent},
]
},
]
}
},
]+
[
// wrapped with additional for loop to trim out templates with empty types list
for tpl in [
for cmp in app.corteza.components {
template: "gocode/envoy/resource_translation_references_$component.go.tpl"
output: "pkg/envoy/resource/resource_translation_references_\(cmp.ident).gen.go"
payload: {
package: "resource"
imports: [
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
]
resources: [
for res in cmp.resources if res.locale != _|_ {
resTrRefFunc: "\(cmp.expIdent)\(res.expIdent)ResourceTranslationReferences"
expIdent: res.expIdent
references: [
for p in res.parents {p},
]
},
]
}
},
] if len(tpl.payload.resources) > 0 {tpl}
]

View File

@@ -0,0 +1,43 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
)
[...schema.#codegen] &
[
// wrapped with additional for loop to trim out templates with empty types list
for tpl in [
for cmp in app.corteza.components {
template: "gocode/locale/$component_service.go.tpl"
output: "\(cmp.ident)/service/locale.gen.go"
payload: {
package: "service"
imports: [
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
]
resources: [
for res in cmp.resources if (res.locale != _|_) if (!res.locale.skipSvc) {
expIdent: res.expIdent
ident: res.ident
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
extended: res.locale.extended
keys: [ for key in res.locale.keys if key.handlerFunc == _|_ {
struct: key.struct
"extended": extended
customHandler: key.customHandler
if key.serviceFunc != _|_ {serviceFunc: key.serviceFunc}
}]
},
]
}
},
// skip empty type lists
] if len(tpl.payload.resources) > 0 {tpl}
]

View File

@@ -0,0 +1,55 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
"strings"
)
[...schema.#codegen] &
[
// wrapped with additional for loop to trim out templates with empty types list
for tpl in [
for cmp in app.corteza.components {
template: "gocode/locale/$component_types.go.tpl"
output: "\(cmp.ident)/types/locale.gen.go"
payload: {
package: "types"
resources: [
for res in cmp.resources if res.locale != _|_ {
expIdent: res.expIdent
const: res.locale.resource.const
type: res.locale.resource.type
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
extended: res.locale.extended
keys: [ for key in res.locale.keys if key.handlerFunc == _|_ {
struct: key.struct
field: strings.ToTitle(key.name)
path: strings.Join([ for p in key.expandedPath {
if p.var {"{{\(p.part)}}"}
if !p.var {p.part}
}], ".")
if !key.customHandler {
fieldPath: strings.Join([ for p in key.expandedPath {
strings.ToTitle(p.part)
}], ".")
}
"extended": extended
if key.decodeFunc != _|_ {decodeFunc: key.decodeFunc}
if key.encodeFunc != _|_ {encodeFunc: key.encodeFunc}
}]
},
]
}
},
// skip empty type lists
] if len(tpl.payload.resources) > 0 {tpl}
]

View File

@@ -0,0 +1,82 @@
package codegen
import (
"strings"
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
)
[...schema.#codegen] &
[
{
template: "gocode/options/options.go.tpl"
output: "pkg/options/options.gen.go"
payload: {
package: "options"
// make unique list of packages we'll import
imports: [ for i in {for g in app.corteza.options for i in g.imports {"\(i)": i}} {i}]
groups: [
for g in app.corteza.options {
func: g.expIdent
struct: g.expIdent + "Opt"
options: [
for o in g.options {
o
default?: string
if (o.defaultGoExpr != _|_) {
default: o.defaultGoExpr
}
if (o.defaultGoExpr == _|_ && o.defaultValue != _|_) {
default: "\"" + o.defaultValue + "\""
}
},
]
},
]
}
},
]+
[
{
template: "docs/.env.example.tpl"
output: ".env.example"
syntax: ".env"
payload: {
groups: [
for g in app.corteza.options {
title: "# " + strings.Join(strings.Split(g.title, "\n"), "\n# ")
if (g.intro != _|_) {
intro: "# " + strings.Join(strings.Split(g.intro, "\n"), "\n# ")
}
options: [
for o in g.options {
handle: o.handle
env: o.env
type: o.type
defaultGoExpr?: string
if (o.defaultGoExpr != _|_) {
defaultGoExpr: o.defaultGoExpr
}
defaultValue?: string
if (o.defaultValue != _|_) {
defaultValue: o.defaultValue
}
if (o.description != _|_) {
description: "# " + strings.Join(strings.Split(o.description, "\n"), "\n# ")
}
},
]
},
]
}
},
]

View File

@@ -0,0 +1,61 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/codegen/schema"
"github.com/cortezaproject/corteza-server/app"
)
[...schema.#codegen] &
[
for cmp in app.corteza.components {
template: "gocode/rbac/$component_access_control.go.tpl"
output: "\(cmp.ident)/service/access_control.gen.go"
payload: {
package: "service"
imports: [
"\"github.com/cortezaproject/corteza-server/\(cmp.ident)/types\"",
]
// All possible RBAC operations on component and resources
// flattened
operations: [
for res in cmp.resources for op in res.rbac.operations {
"op": op.handle
const: "types.\(res.expIdent)ResourceType"
resFunc: "types.\(res.expIdent)RbacResource"
goType: "types.\(res.expIdent)"
description: op.description
checkFuncName: op.checkFuncName
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
},
for op in cmp.rbac.operations {
"op": op.handle
const: "types.ComponentResourceType"
resFunc: "types.ComponentRbacResource"
goType: "types.Component"
description: op.description
checkFuncName: op.checkFuncName
component: true
},
]
// Operation/resource validators, grouped by resource
validation: [
for res in cmp.resources {
label: res.ident
const: "types.\(res.expIdent)ResourceType"
funcName: "rbac\(res.expIdent)ResourceValidator"
references: [ for p in res.parents {p.refField}, "ID"]
operations: [ for op in res.rbac.operations {op.handle}]
},
{
label: "\(cmp.ident) component"
const: "types.ComponentResourceType"
funcName: "rbacComponentResourceValidator"
operations: [ for op in cmp.rbac.operations {op.handle}]
},
]
}
},
]

View File

@@ -0,0 +1,41 @@
package codegen
import (
"github.com/cortezaproject/corteza-server/app"
"github.com/cortezaproject/corteza-server/codegen/schema"
)
[...schema.#codegen] &
[
for cmp in app.corteza.components {
template: "gocode/rbac/$component_types.go.tpl"
output: "\(cmp.ident)/types/rbac.gen.go"
payload: {
package: "types"
cmpIdent: cmp.ident
// Operation/resource validators, grouped by resource
types: [
for res in cmp.resources {
const: "\(res.expIdent)ResourceType"
type: res.fqrn
resFunc: "\(res.expIdent)RbacResource"
tplFunc: "\(res.expIdent)RbacResourceTpl"
attFunc: "\(res.expIdent)RbacAttributes"
goType: res.expIdent
references: [ for p in res.parents {p}, {param: "id", refField: "ID"}]
},
{
const: "ComponentResourceType"
type: cmp.fqrn
resFunc: "ComponentRbacResource"
tplFunc: "ComponentRbacResourceTpl"
attFunc: "ComponentRbacAttributes"
goType: "Component"
component: true
},
]
}
},
]

View File

@@ -5,6 +5,7 @@ import (
"flag"
"fmt"
"os"
"path"
"text/template"
"github.com/cortezaproject/corteza-server/pkg/cli"
@@ -23,12 +24,14 @@ var (
verbose bool
showHelp bool
tplRootPath string
outputBase string
)
func init() {
flag.BoolVar(&showHelp, "h", false, "show help")
flag.BoolVar(&verbose, "v", false, "be verbose")
flag.StringVar(&tplRootPath, "p", "codegen/assets/templates", "location of the template files")
flag.StringVar(&outputBase, "b", ".", "base dir for output")
flag.Parse()
}
@@ -56,13 +59,14 @@ func main() {
}
for _, j := range tasks {
print(fmt.Sprintf("generating %s (from %s) ...", j.Output, j.Template))
output := path.Join(outputBase, j.Output)
print(fmt.Sprintf("generating %s (from %s) ...", output, j.Template))
switch j.Syntax {
case "go":
err = writeFormattedGo(j.Output, tpl.Lookup(j.Template), j.Payload)
err = writeFormattedGo(output, tpl.Lookup(j.Template), j.Payload)
default:
err = write(j.Output, tpl.Lookup(j.Template), j.Payload)
err = write(output, tpl.Lookup(j.Template), j.Payload)
}
if err != nil {