seperate def and module modifier

Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
This commit is contained in:
Qiaozp
2023-03-20 15:27:18 +08:00
parent 91f9e49d21
commit 8f4ef2f62a
5 changed files with 262 additions and 115 deletions
@@ -4,11 +4,16 @@ go 1.19
require (
github.com/oam-dev/kubevela-core-api v1.5.8
// for main module
github.com/pkg/errors v0.9.1
k8s.io/apimachinery v0.23.6
k8s.io/client-go v0.23.6
sigs.k8s.io/controller-runtime v0.11.2
sigs.k8s.io/yaml v1.3.0
// for sub-module
github.com/kubevela/vela-go-sdk v0.0.0-20230310062146-e5d4070da6b4
)
require (
+58 -31
View File
@@ -34,6 +34,7 @@ import (
"github.com/kubevela/pkg/util/slices"
"github.com/kubevela/workflow/pkg/cue/model/value"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
@@ -56,6 +57,8 @@ var (
// GenMeta stores the metadata for generator.
type GenMeta struct {
config *rest.Config
name string
kind string
Output string
APIDirectory string
@@ -66,6 +69,7 @@ type GenMeta struct {
File []string
InitSDK bool
Verbose bool
GoArgs GoArgs
cuePaths []string
templatePath string
@@ -75,11 +79,12 @@ type GenMeta struct {
// Generator is used to generate SDK code from CUE template for one language.
type Generator struct {
meta *GenMeta
name string
kind string
def definition.Definition
openapiSchema []byte
modifiers []Modifier
// defModifiers are the modifiers for each definition.
defModifiers []Modifier
// moduleModifiers are the modifiers for the whole module. It will be executed after generating all definitions.
moduleModifiers []Modifier
}
// Modifier is used to modify the generated code.
@@ -90,7 +95,7 @@ type Modifier interface {
// Init initializes the generator.
// It will validate the param, analyze the CUE files, read them to memory, mkdir for output.
func (meta *GenMeta) Init(c common.Args) (err error) {
func (meta *GenMeta) Init(c common.Args, flags *pflag.FlagSet) (err error) {
meta.config, err = c.GetConfig()
if err != nil {
klog.Info("No kubeconfig found, skipping")
@@ -107,9 +112,19 @@ func (meta *GenMeta) Init(c common.Args) (err error) {
if meta.APIDirectory == "" {
meta.APIDirectory = defaultAPIDir[meta.Lang]
}
if flags != nil {
switch meta.Lang {
case "go":
if goargs, err := flags.GetStringSlice("go-args"); err != nil {
return err
} else {
meta.GoArgs.parse(goargs)
}
}
}
packageFuncs := map[string]byteHandler{
"go": func(b []byte) []byte {
return bytes.ReplaceAll(b, []byte("github.com/kubevela/vela-go-sdk"), []byte(meta.Package))
return bytes.ReplaceAll(b, []byte(DefaultPackage), []byte(meta.Package))
},
}
@@ -248,18 +263,20 @@ func (meta *GenMeta) PrepareGeneratorAndTemplate() error {
// 1. Generate OpenAPI schema from cue files
// 2. Generate code from OpenAPI schema
func (meta *GenMeta) Run() error {
g := NewModifiableGenerator(meta)
for _, cuePath := range meta.cuePaths {
klog.Infof("Generating SDK for %s", cuePath)
g := NewModifiableGenerator(meta)
// nolint:gosec
cueBytes, err := os.ReadFile(cuePath)
if err != nil {
return errors.Wrapf(err, "failed to read %s", cuePath)
}
template, err := g.GetDefinitionValue(cueBytes)
template, defName, defKind, err := g.GetDefinitionValue(cueBytes)
if err != nil {
return err
}
g.meta.SetDefinition(defName, defKind)
err = g.GenOpenAPISchema(template)
if err != nil {
if strings.Contains(err.Error(), "unsupported node string (*ast.Ident)") {
@@ -269,32 +286,43 @@ func (meta *GenMeta) Run() error {
}
return errors.Wrapf(err, "generate OpenAPI schema")
}
err = g.GenerateCode()
if err != nil {
return err
}
}
for _, m := range g.moduleModifiers {
err := m.Modify()
if err != nil {
return err
}
}
return nil
}
// GetDefinitionValue returns a value.Value from cue bytes
func (g *Generator) GetDefinitionValue(cueBytes []byte) (*value.Value, error) {
func (meta *GenMeta) SetDefinition(defName, defKind string) {
meta.name = defName
meta.kind = defKind
}
// GetDefinitionValue returns a value.Value definition name, definition kind from cue bytes
func (g *Generator) GetDefinitionValue(cueBytes []byte) (*value.Value, string, string, error) {
g.def = definition.Definition{Unstructured: unstructured.Unstructured{}}
if err := g.def.FromCUEString(string(cueBytes), g.meta.config); err != nil {
return nil, errors.Wrapf(err, "failed to parse CUE")
return nil, "", "", errors.Wrapf(err, "failed to parse CUE")
}
g.name = g.def.GetName()
g.kind = g.def.GetKind()
templateString, _, err := unstructured.NestedString(g.def.Object, definition.DefinitionTemplateKeys...)
if err != nil {
return nil, err
return nil, "", "", err
}
template, err := value.NewValue(templateString+velacue.BaseTemplate, nil, "")
if err != nil {
return nil, err
return nil, "", "", err
}
return template, nil
return template, g.def.GetName(), g.def.GetKind(), nil
}
// GenOpenAPISchema generates OpenAPI json schema from cue.Instance
@@ -349,13 +377,13 @@ func (g *Generator) completeOpenAPISchema(doc *openapi3.T) {
for key, schema := range doc.Components.Schemas {
switch key {
case "parameter":
spec := g.name + "-spec"
spec := g.meta.name + "-spec"
schema.Value.Title = spec
completeFreeFormSchema(schema)
completeSchema(key, schema)
doc.Components.Schemas[spec] = schema
delete(doc.Components.Schemas, key)
case g.name + "-spec":
case g.meta.name + "-spec":
continue
default:
completeSchema(key, schema)
@@ -365,7 +393,7 @@ func (g *Generator) completeOpenAPISchema(doc *openapi3.T) {
// GenerateCode will call openapi-generator to generate code and modify it
func (g *Generator) GenerateCode() (err error) {
tmpFile, err := os.CreateTemp("", g.name+"-*.json")
tmpFile, err := os.CreateTemp("", g.meta.name+"-*.json")
_, err = tmpFile.Write(g.openapiSchema)
if err != nil {
return errors.Wrap(err, "write openapi schema to temporary file")
@@ -380,7 +408,7 @@ func (g *Generator) GenerateCode() (err error) {
if err != nil {
return errors.Wrapf(err, "get absolute path of %s", apiDir)
}
err = os.MkdirAll(path.Join(apiDir, definition.DefinitionKindToType[g.kind]), 0750)
err = os.MkdirAll(path.Join(apiDir, definition.DefinitionKindToType[g.meta.kind]), 0750)
if err != nil {
return errors.Wrapf(err, "create directory %s", apiDir)
}
@@ -396,13 +424,13 @@ func (g *Generator) GenerateCode() (err error) {
"generate",
"-i", "/local/input/"+filepath.Base(tmpFile.Name()),
"-g", g.meta.Lang,
"-o", fmt.Sprintf("/local/output/%s/%s", definition.DefinitionKindToType[g.kind], g.name),
"-o", fmt.Sprintf("/local/output/%s/%s", definition.DefinitionKindToType[g.meta.kind], g.meta.name),
"-t", "/local/template",
"--skip-validate-spec",
"--enable-post-process-file",
"--generate-alias-as-model",
"--inline-schema-name-defaults", "arrayItemSuffix=,mapItemSuffix=",
"--additional-properties", fmt.Sprintf("packageName=%s", strings.ReplaceAll(g.name, "-", "_")),
"--additional-properties", fmt.Sprintf("packageName=%s", strings.ReplaceAll(g.meta.name, "-", "_")),
"--global-property", "modelDocs=false,models,supportingFiles=utils.go",
)
if g.meta.Verbose {
@@ -417,7 +445,7 @@ func (g *Generator) GenerateCode() (err error) {
}
// Adjust the generated files and code
for _, m := range g.modifiers {
for _, m := range g.defModifiers {
err := m.Modify()
if err != nil {
return errors.Wrapf(err, "modify fail by %s", m.Name())
@@ -543,20 +571,19 @@ func completeSchemas(schemas openapi3.Schemas) {
// NewModifiableGenerator returns a new Generator with modifiers
func NewModifiableGenerator(meta *GenMeta) *Generator {
g := &Generator{
meta: meta,
modifiers: []Modifier{},
meta: meta,
defModifiers: []Modifier{},
moduleModifiers: []Modifier{},
}
mo := newModifierOnLanguage(meta.Lang, g)
g.modifiers = append(g.modifiers, mo)
appendModifiersByLanguage(g, meta)
return g
}
func newModifierOnLanguage(lang string, generator *Generator) Modifier {
switch lang {
func appendModifiersByLanguage(g *Generator, meta *GenMeta) {
switch meta.Lang {
case "go":
return &GoModifier{g: generator}
default:
panic("unsupported language: " + lang)
g.defModifiers = append(g.defModifiers, &GoDefModifier{GenMeta: meta})
g.moduleModifiers = append(g.moduleModifiers, &GoModuleModifier{GenMeta: meta})
}
}
+1 -1
View File
@@ -44,7 +44,7 @@ var _ = Describe("Test Generating SDK", func() {
Expect(err).Should(BeNil())
}
genWithMeta := func(meta GenMeta) {
err = meta.Init(common.Args{})
err = meta.Init(common.Args{}, nil)
Expect(err).Should(BeNil())
err = meta.CreateScaffold()
Expect(err).Should(BeNil())
+190 -81
View File
@@ -23,6 +23,7 @@ import (
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
@@ -36,6 +37,20 @@ import (
pkgdef "github.com/oam-dev/kubevela/pkg/definition"
)
type GoArgs struct {
// MainModuleVersion is version of main module, it will be used in go get command. For example, tag, commit id, branch name
// if set, vela will run a go get command in docker
MainModuleVersion string
// GoProxy is the proxy for go get/go mod tidy command
GoProxy string
}
const (
DefaultMainModuleHash = "cd431bb25a9a"
DefaultGoProxy = "https://goproxy.cn,direct"
DefaultPackage = "github.com/kubevela/vela-go-sdk"
)
var (
// DefinitionKindToPascal is the map of definition kind to pascal case
DefinitionKindToPascal = map[string]string{
@@ -60,14 +75,20 @@ var (
}
)
// GoModifier is the Modifier for golang
type GoModifier struct {
g *Generator
// GoDefModifier is the Modifier for golang, modify code for each definition
type GoDefModifier struct {
*GenMeta
*goArgs
defName string
defKind string
verbose bool
defStructPointer *j.Statement
}
type GoModuleModifier struct {
*GenMeta
*goArgs
}
type goArgs struct {
apiDir string
defDir string
utilsDir string
@@ -78,25 +99,29 @@ type GoModifier struct {
typeVarName string
defStructName string
defFuncReceiver string
defStructPointer *j.Statement
}
// Name the name of modifier
func (m *GoModifier) Name() string {
return "GoModifier"
func (a *goArgs) init(m *GenMeta) error {
var err error
a.apiDir, err = filepath.Abs(path.Join(m.Output, m.APIDirectory))
if err != nil {
return err
}
a.defDir = path.Join(a.apiDir, pkgdef.DefinitionKindToType[m.kind], m.name)
a.utilsDir = path.Join(m.Output, "pkg", "apis", "utils")
a.nameInSnakeCase = strcase.ToSnake(m.name)
a.nameInPascalCase = strcase.ToPascal(m.name)
a.typeVarName = a.nameInPascalCase + "Type"
a.specNameInPascalCase = a.nameInPascalCase + "Spec"
a.defStructName = strcase.ToGoPascal(m.name + "-" + pkgdef.DefinitionKindToType[m.kind])
a.defFuncReceiver = m.name[:1]
return nil
}
// Modify the modification of generated code
func (m *GoModifier) Modify() error {
func (m *GoModuleModifier) Modify() error {
for _, fn := range []func() error{
m.init,
m.clean,
m.addSubGoMod,
m.moveUtils,
m.modifyDefs,
m.addDefAPI,
m.addValidateTraits,
m.exportMethods,
m.format,
} {
if err := fn(); err != nil {
@@ -106,26 +131,56 @@ func (m *GoModifier) Modify() error {
return nil
}
func (m *GoModifier) init() error {
m.defName = m.g.name
m.defKind = m.g.kind
m.verbose = m.g.meta.Verbose
func (m *GoModuleModifier) init() error {
m.goArgs = &goArgs{}
err := m.goArgs.init(m.GenMeta)
if err != nil {
return err
}
return nil
}
func (m *GoModuleModifier) Name() string {
return "goModuleModifier"
}
// Name the name of modifier
func (m *GoDefModifier) Name() string {
return "GoDefModifier"
}
// Modify the modification of generated code
func (m *GoDefModifier) Modify() error {
for _, fn := range []func() error{
m.init,
m.clean,
m.moveUtils,
m.modifyDefs,
m.addDefAPI,
m.addValidateTraits,
m.exportMethods,
} {
if err := fn(); err != nil {
return err
}
}
return nil
}
func (m *GoDefModifier) init() error {
m.goArgs = &goArgs{}
err := m.goArgs.init(m.GenMeta)
if err != nil {
return err
}
m.apiDir = path.Join(m.g.meta.Output, m.g.meta.APIDirectory)
m.defDir = path.Join(m.apiDir, pkgdef.DefinitionKindToType[m.defKind], m.defName)
m.utilsDir = path.Join(m.g.meta.Output, "pkg", "apis", "utils")
m.nameInSnakeCase = strcase.ToSnake(m.defName)
m.nameInPascalCase = strcase.ToPascal(m.defName)
m.typeVarName = m.nameInPascalCase + "Type"
m.specNameInPascalCase = m.nameInPascalCase + "Spec"
m.defStructName = strcase.ToGoPascal(m.defName + "-" + pkgdef.DefinitionKindToType[m.defKind])
m.defStructPointer = j.Op("*").Id(m.defStructName)
m.defFuncReceiver = m.defName[:1]
err := os.MkdirAll(m.utilsDir, 0750)
err = os.MkdirAll(m.utilsDir, 0750)
return err
}
func (m *GoModifier) clean() error {
func (m *GoDefModifier) clean() error {
err := os.RemoveAll(path.Join(m.defDir, ".openapi-generator"))
if err != nil {
return err
@@ -150,9 +205,9 @@ func (m *GoModifier) clean() error {
}
// addSubGoMod will add a go.mod and go.sum in the api directory if user mark that the api is a sub module
func (m *GoModifier) addSubGoMod() error {
if !m.g.meta.IsSubModule {
// addSubGoMod will add a go.mod and go.sum in the api directory if user mark that the api is a submodule
func (m *GoModuleModifier) addSubGoMod() error {
if !m.IsSubModule {
return nil
}
copyFiles := map[string]string{
@@ -164,25 +219,59 @@ func (m *GoModifier) addSubGoMod() error {
if err != nil {
return errors.Wrap(err, "read "+src)
}
subModuleName := strings.TrimSuffix(fmt.Sprintf("%s/%s", m.Package, m.APIDirectory), "/")
srcContent = bytes.ReplaceAll(srcContent, []byte(DefaultPackage), []byte(subModuleName))
err = os.WriteFile(path.Join(m.apiDir, dst), srcContent, 0644)
if err != nil {
return errors.Wrap(err, "write "+dst)
}
}
cmds := make([]*exec.Cmd, 0)
if m.GoArgs.MainModuleVersion != DefaultMainModuleHash {
cmds = append(cmds, exec.Command("docker", "run",
"--rm",
"-v", m.apiDir+":/api",
"-w", "/api",
"golang:1.19-alpine",
"go", "get", fmt.Sprintf("%s@%s", m.Package, m.GoArgs.MainModuleVersion),
))
}
cmds = append(cmds, exec.Command("docker", "run",
"--rm",
"-v", m.apiDir+":/api",
"-w", "/api",
"golang:1.19-alpine",
"go", "mod", "tidy",
))
for _, cmd := range cmds {
if m.Verbose {
fmt.Println(cmd.String())
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
}
cmd.Env = append(cmd.Env, "GOPROXY="+m.GoArgs.GoProxy)
err := cmd.Run()
if err != nil {
return errors.Wrapf(err, "fail to run command %s", cmd.String())
}
}
return nil
}
// read all files in definition directory,
// 1. replace the Nullable* Struct
// 2. replace the package name
func (m *GoModifier) modifyDefs() error {
func (m *GoDefModifier) modifyDefs() error {
changeNullableType := func(b []byte) []byte {
return regexp.MustCompile("Nullable(String|(Float|Int)(32|64)|Bool)").ReplaceAll(b, []byte("utils.Nullable$1"))
}
files, err := os.ReadDir(m.defDir)
defHandleFunc := []byteHandler{
m.g.meta.packageFunc,
m.packageFunc,
changeNullableType,
}
if err != nil {
@@ -204,7 +293,7 @@ func (m *GoModifier) modifyDefs() error {
return nil
}
func (m *GoModifier) moveUtils() error {
func (m *GoDefModifier) moveUtils() error {
// Adjust the generated files and code
err := os.Rename(path.Join(m.defDir, "utils.go"), path.Join(m.utilsDir, "utils.go"))
if err != nil {
@@ -217,7 +306,7 @@ func (m *GoModifier) moveUtils() error {
if err != nil {
return err
}
utilsBytes = bytes.Replace(utilsBytes, []byte(fmt.Sprintf("package %s", strcase.ToSnake(m.defName))), []byte("package utils"), 1)
utilsBytes = bytes.Replace(utilsBytes, []byte(fmt.Sprintf("package %s", strcase.ToSnake(m.name))), []byte("package utils"), 1)
utilsBytes = bytes.ReplaceAll(utilsBytes, []byte("isNil"), []byte("IsNil"))
err = os.WriteFile(utilsFile, utilsBytes, 0600)
if err != nil {
@@ -227,7 +316,7 @@ func (m *GoModifier) moveUtils() error {
}
// addDefAPI will add component/trait/workflowstep/policy Object to the api
func (m *GoModifier) addDefAPI() error {
func (m *GoDefModifier) addDefAPI() error {
file, err := os.OpenFile(path.Join(m.defDir, m.nameInSnakeCase+".go"), os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
return err
@@ -260,11 +349,11 @@ func (m *GoModifier) addDefAPI() error {
return nil
}
func (m *GoModifier) genCommonFunc() []*j.Statement {
kind := m.defKind
func (m *GoDefModifier) genCommonFunc() []*j.Statement {
kind := m.kind
typeName := j.Id(m.nameInPascalCase + "Type")
typeConst := j.Const().Add(typeName).Op("=").Lit(m.defName)
j.Op("=").Lit(m.defName)
typeConst := j.Const().Add(typeName).Op("=").Lit(m.name)
j.Op("=").Lit(m.name)
defStruct := j.Type().Id(m.defStructName).Struct(
j.Id("Base").Id("apis").Dot(DefinitionKindToBaseType[kind]),
j.Id("Properties").Id(m.specNameInPascalCase),
@@ -352,8 +441,8 @@ func (m *GoModifier) genCommonFunc() []*j.Statement {
return []*j.Statement{typeConst, initFunc, defStruct, defStructConstructor, buildFunc}
}
func (m *GoModifier) genFromFunc() []*j.Statement {
kind := m.g.kind
func (m *GoDefModifier) genFromFunc() []*j.Statement {
kind := m.kind
kindBaseProperties := map[string][]string{
v1beta1.ComponentDefinitionKind: {"Name", "DependsOn", "Inputs", "Outputs"},
v1beta1.WorkflowStepDefinitionKind: {"Name", "DependsOn", "Inputs", "Outputs", "If", "Timeout", "Meta"},
@@ -364,7 +453,7 @@ func (m *GoModifier) genFromFunc() []*j.Statement {
// fromFuncRsv means build from a part of K8s Object (e.g. v1beta1.Application.spec.component[*] to internal presentation (e.g. Component)
// fromFuncRsv will have a function receiver
getSubSteps := func(sub bool) func(g *j.Group) {
if m.defKind != v1beta1.WorkflowStepDefinitionKind || sub {
if m.kind != v1beta1.WorkflowStepDefinitionKind || sub {
return func(g *j.Group) {}
}
return func(g *j.Group) {
@@ -382,7 +471,7 @@ func (m *GoModifier) genFromFunc() []*j.Statement {
}
}
assignSubSteps := func(sub bool) func(g *j.Group) {
if m.defKind != v1beta1.WorkflowStepDefinitionKind || sub {
if m.kind != v1beta1.WorkflowStepDefinitionKind || sub {
return func(g *j.Group) {}
}
return func(g *j.Group) {
@@ -449,15 +538,15 @@ func (m *GoModifier) genFromFunc() []*j.Statement {
)
res := []*j.Statement{fromFuncRsv(false), fromFunc}
if m.defKind == v1beta1.WorkflowStepDefinitionKind {
if m.kind == v1beta1.WorkflowStepDefinitionKind {
res = append(res, fromFuncRsv(true), fromSubFunc)
}
return res
}
// genDedicatedFunc generate functions for definition kinds
func (m *GoModifier) genDedicatedFunc() []*j.Statement {
switch m.defKind {
func (m *GoDefModifier) genDedicatedFunc() []*j.Statement {
switch m.kind {
case v1beta1.ComponentDefinitionKind:
setTraitFunc := j.Func().
Params(j.Id(m.defFuncReceiver).Add(m.defStructPointer)).
@@ -508,14 +597,14 @@ func (m *GoModifier) genDedicatedFunc() []*j.Statement {
return nil
}
func (m *GoModifier) genNameTypeFunc() []*j.Statement {
nameFunc := j.Func().Params(j.Id(m.defFuncReceiver).Add(m.defStructPointer)).Id(DefinitionKindToPascal[m.defKind] + "Name").Params().String().Block(
func (m *GoDefModifier) genNameTypeFunc() []*j.Statement {
nameFunc := j.Func().Params(j.Id(m.defFuncReceiver).Add(m.defStructPointer)).Id(DefinitionKindToPascal[m.kind] + "Name").Params().String().Block(
j.Return(j.Id(m.defFuncReceiver).Dot("Base").Dot("Name")),
)
typeFunc := j.Func().Params(j.Id(m.defFuncReceiver).Add(m.defStructPointer)).Id("DefType").Params().String().Block(
j.Return(j.Id(m.typeVarName)),
)
switch m.defKind {
switch m.kind {
case v1beta1.ComponentDefinitionKind, v1beta1.WorkflowStepDefinitionKind, v1beta1.PolicyDefinitionKind:
return []*j.Statement{nameFunc, typeFunc}
case v1beta1.TraitDefinitionKind:
@@ -524,11 +613,11 @@ func (m *GoModifier) genNameTypeFunc() []*j.Statement {
return nil
}
func (m *GoModifier) genUnmarshalFunc() []*j.Statement {
func (m *GoDefModifier) genUnmarshalFunc() []*j.Statement {
return []*j.Statement{j.Null()}
}
func (m *GoModifier) genBaseSetterFunc() []*j.Statement {
func (m *GoDefModifier) genBaseSetterFunc() []*j.Statement {
baseFuncArgs := map[string][]struct {
funcName string
argName string
@@ -557,7 +646,7 @@ func (m *GoModifier) genBaseSetterFunc() []*j.Statement {
},
}
baseFuncs := make([]*j.Statement, 0)
for _, fn := range baseFuncArgs[m.defKind] {
for _, fn := range baseFuncArgs[m.kind] {
if fn.dst == nil {
fn.dst = j.Dot(fn.funcName)
}
@@ -580,8 +669,8 @@ func (m *GoModifier) genBaseSetterFunc() []*j.Statement {
return baseFuncs
}
func (m *GoModifier) genAddSubStepFunc() *j.Statement {
if m.defName != "step-group" || m.defKind != v1beta1.WorkflowStepDefinitionKind {
func (m *GoDefModifier) genAddSubStepFunc() *j.Statement {
if m.name != "step-group" || m.kind != v1beta1.WorkflowStepDefinitionKind {
return j.Null()
}
subList := j.Id(m.defFuncReceiver).Dot("Base").Dot("SubSteps")
@@ -597,7 +686,7 @@ func (m *GoModifier) genAddSubStepFunc() *j.Statement {
}
// exportMethods will export methods from definition spec struct to definition struct
func (m *GoModifier) exportMethods() error {
func (m *GoDefModifier) exportMethods() error {
fileLoc := path.Join(m.defDir, m.nameInSnakeCase+".go")
// nolint:gosec
file, err := os.ReadFile(fileLoc)
@@ -628,8 +717,8 @@ func (m *GoModifier) exportMethods() error {
return os.WriteFile(fileLoc, []byte(fileStr), 0600)
}
func (m *GoModifier) addValidateTraits() error {
if m.defKind != v1beta1.ComponentDefinitionKind {
func (m *GoDefModifier) addValidateTraits() error {
if m.kind != v1beta1.ComponentDefinitionKind {
return nil
}
fileLoc := path.Join(m.defDir, m.nameInSnakeCase+".go")
@@ -656,7 +745,7 @@ func (m *GoModifier) addValidateTraits() error {
return os.WriteFile(fileLoc, []byte(fileStr), 0600)
}
func (m *GoModifier) format() error {
func (m *GoModuleModifier) format() error {
// check if gofmt is installed
// todo (chivalryq): support go mod tidy for sub-module
@@ -673,11 +762,11 @@ func (m *GoModifier) format() error {
}
if allFormattersInstalled {
for _, fmter := range formatterPaths {
if m.verbose {
if m.Verbose {
fmt.Printf("Use %s to format code\n", fmter)
}
// nolint:gosec
cmd := exec.Command(fmter, "-w", m.defDir)
cmd := exec.Command(fmter, "-w", m.apiDir)
output, err := cmd.CombinedOutput()
if err != nil {
return errors.Wrap(err, string(output))
@@ -686,31 +775,51 @@ func (m *GoModifier) format() error {
return nil
}
// fallback to use go lib
if m.verbose {
if m.Verbose {
fmt.Println("At least one of linters is not installed, use go/format lib to format code")
}
files, err := os.ReadDir(m.defDir)
if err != nil {
return errors.Wrap(err, "read dir")
}
for _, f := range files {
if !strings.HasSuffix(f.Name(), ".go") {
continue
// format all .go files
return filepath.Walk(m.apiDir, func(path string, info os.FileInfo, err error) error {
if !strings.HasSuffix(path, ".go") {
return nil
}
filePath := path.Join(m.defDir, f.Name())
// nolint:gosec
content, err := os.ReadFile(filePath)
content, err := os.ReadFile(path)
if err != nil {
return errors.Wrapf(err, "read file %s", filePath)
return errors.Wrapf(err, "read file %s", path)
}
formatted, err := format.Source(content)
if err != nil {
return errors.Wrapf(err, "format file %s", filePath)
return errors.Wrapf(err, "format file %s", path)
}
err = os.WriteFile(filePath, formatted, 0600)
err = os.WriteFile(path, formatted, 0600)
if err != nil {
return errors.Wrapf(err, "write file %s", filePath)
return errors.Wrapf(err, "write file %s", path)
}
return nil
})
}
// parse parses the args and set the value to GoArgs
// todo(chivalryq): generalize the args parsing
func (args *GoArgs) parse(stringArgs []string) {
for _, arg := range stringArgs {
parts := strings.Split(arg, "=")
if len(parts) != 2 {
continue
}
switch parts[0] {
case "MainModuleVersion":
args.MainModuleVersion = parts[1]
case "GoProxy":
args.GoProxy = parts[1]
}
}
return nil
if args.GoProxy == "" {
args.GoProxy = DefaultGoProxy
}
if args.MainModuleVersion == "" {
args.MainModuleVersion = DefaultMainModuleHash
}
}
+8 -2
View File
@@ -1077,7 +1077,7 @@ func NewDefinitionGenAPICommand(c common.Args) *cobra.Command {
"# Generate incremental definition files to existing sdk directory\n" +
"> vela def gen-api --lang go -f /path/to/def -o /path/to/sdk",
RunE: func(cmd *cobra.Command, args []string) error {
err := meta.Init(c)
err := meta.Init(c, cmd.Flags())
if err != nil {
return err
}
@@ -1100,12 +1100,18 @@ func NewDefinitionGenAPICommand(c common.Args) *cobra.Command {
cmd.Flags().StringVarP(&meta.Output, "output", "o", "./apis", "Output directory path")
cmd.Flags().StringVar(&meta.APIDirectory, "api-dir", "", "API directory path to put definition API files, relative to output directory. Default value: go: pkg/apis")
cmd.Flags().BoolVar(&meta.IsSubModule, "submodule", false, "Whether the generated code is a submodule of the project. If set, the directory specified by `api-dir` will be treated as a submodule of the project")
cmd.Flags().StringVarP(&meta.Package, "package", "p", "github.com/kubevela/vela-go-sdk", "Package name of generated code")
cmd.Flags().StringVarP(&meta.Package, "package", "p", gen_sdk.DefaultPackage, "Package name of generated code")
cmd.Flags().StringVarP(&meta.Lang, "lang", "g", "go", "Language to generate code. Valid languages: go")
cmd.Flags().StringVarP(&meta.Template, "template", "t", "", "Template file path, if not specified, the default template will be used")
cmd.Flags().StringSliceVarP(&meta.File, "file", "f", nil, "File name of definitions, can be specified multiple times, or use comma to separate multiple files. If directory specified, all files found recursively in the directory will be used")
cmd.Flags().BoolVar(&meta.InitSDK, "init", false, "Init the whole SDK project, if not set, only the API file will be generated")
cmd.Flags().BoolVarP(&meta.Verbose, "verbose", "v", false, "Print verbose logs")
cmd.Flags().StringSlice("go-args", []string{},
fmt.Sprintf("Additional arguments to pass to the go generator, available options: "+
"MainModuleVersion(specify the version of the main module in submodule, used when set --submodule, default: cd431bb25a9a), "+
"GoProxy(specify the GOPROXY environment variable, default: https://goproxy.cn,direct)",
),
)
return cmd
}