From d98016aa3dcee9b517175c45f762ed6e606dac75 Mon Sep 17 00:00:00 2001 From: Tianxin Dong Date: Tue, 20 Sep 2022 15:18:31 +0800 Subject: [PATCH] Fix: use value instead of instance in openapi.gen (#4739) Signed-off-by: FogDong Signed-off-by: FogDong --- pkg/addon/addon.go | 8 ++--- pkg/addon/init.go | 4 +-- pkg/appfile/helm/schema.go | 10 +++---- pkg/controller/utils/capability.go | 27 ++++------------- pkg/definition/definition.go | 3 +- pkg/utils/common/common.go | 47 +++++++++--------------------- pkg/utils/common/common_test.go | 33 ++++++++++----------- references/cli/def.go | 3 +- 8 files changed, 47 insertions(+), 88 deletions(-) diff --git a/pkg/addon/addon.go b/pkg/addon/addon.go index 0899dade4..9d8ba1fbe 100644 --- a/pkg/addon/addon.go +++ b/pkg/addon/addon.go @@ -32,7 +32,7 @@ import ( "text/template" "time" - "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" "github.com/Masterminds/semver/v3" "github.com/google/go-github/v32/github" "github.com/imdario/mergo" @@ -589,18 +589,16 @@ func unmarshalToContent(content []byte) (fileContent *github.RepositoryContent, return nil, nil, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %w", fileUnmarshalError, directoryUnmarshalError) } -// nolint:staticcheck func genAddonAPISchema(addonRes *UIData) error { param, err := utils2.PrepareParameterCue(addonRes.Name, addonRes.Parameters) if err != nil { return err } - var r cue.Runtime - cueInst, err := r.Compile("-", param) + val := cuecontext.New().CompileString(param) if err != nil { return err } - data, err := common.GenOpenAPI(cueInst) + data, err := common.GenOpenAPI(val) if err != nil { return err } diff --git a/pkg/addon/init.go b/pkg/addon/init.go index f86dc3bb4..435c87eee 100644 --- a/pkg/addon/init.go +++ b/pkg/addon/init.go @@ -25,6 +25,7 @@ import ( "strings" "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/format" "cuelang.org/go/encoding/gocode/gocodec" "github.com/fatih/color" @@ -240,8 +241,7 @@ func (cmd *InitCmd) createURLComponent() error { // toCUEResourceString formats object to CUE string used in addons // nolint:staticcheck func toCUEResourceString(obj interface{}) (string, error) { - r := cue.Runtime{} - v, err := gocodec.New(&r, nil).Decode(obj) + v, err := gocodec.New((*cue.Runtime)(cuecontext.New()), nil).Decode(obj) if err != nil { return "", err } diff --git a/pkg/appfile/helm/schema.go b/pkg/appfile/helm/schema.go index 903ba3568..d9dc74c0d 100644 --- a/pkg/appfile/helm/schema.go +++ b/pkg/appfile/helm/schema.go @@ -84,7 +84,6 @@ func GetChartValuesJSONSchema(ctx context.Context, h *common.Helm) ([]byte, erro // generateSchemaFromValues generate OpenAPIv3 schema based on Chart Values // file. -// nolint:staticcheck func generateSchemaFromValues(values []byte) ([]byte, error) { valuesIdentifier := "values" cuectx := cuecontext.New() @@ -104,13 +103,12 @@ func generateSchemaFromValues(values []byte) ([]byte, error) { // an identifier manually valuesStr := fmt.Sprintf("#%s:{\n%s\n}", valuesIdentifier, string(c)) - r := cue.Runtime{} - inst, err := r.Compile("-", valuesStr) - if err != nil { - return nil, errors.Wrap(err, "cannot compile CUE generated from Values.yaml") + val := cuecontext.New().CompileString(valuesStr) + if val.Err() != nil { + return nil, errors.Wrap(val.Err(), "cannot compile CUE generated from Values.yaml") } // generate OpenAPIv3 schema through cue openapi encoder - rawSchema, err := openapi.Gen(inst, &openapi.Config{}) + rawSchema, err := openapi.Gen(val, &openapi.Config{}) if err != nil { return nil, errors.Wrap(err, "cannot generate OpenAPIv3 schema") } diff --git a/pkg/controller/utils/capability.go b/pkg/controller/utils/capability.go index b95058ed2..42d988d31 100644 --- a/pkg/controller/utils/capability.go +++ b/pkg/controller/utils/capability.go @@ -26,8 +26,7 @@ import ( "regexp" "strings" - "cuelang.org/go/cue" - "cuelang.org/go/cue/build" + "cuelang.org/go/cue/cuecontext" "github.com/getkin/kin-openapi/openapi3" "github.com/pkg/errors" "gopkg.in/src-d/go-git.v4" @@ -715,39 +714,23 @@ func getOpenAPISchema(capability types.Capability, pd *packages.PackageDiscover) } // generateOpenAPISchemaFromCapabilityParameter returns the parameter of a definition in cue.Value format -// nolint:staticcheck func generateOpenAPISchemaFromCapabilityParameter(capability types.Capability, pd *packages.PackageDiscover) ([]byte, error) { + ctx := cuecontext.New() template, err := PrepareParameterCue(capability.Name, capability.CueTemplate) if err != nil { if errors.As(err, &ErrNoSectionParameterInCue{}) { // return OpenAPI with empty object parameter, making it possible to generate ConfigMap - var r cue.Runtime - cueInst, _ := r.Compile("-", "") - return common.GenOpenAPI(cueInst) + return common.GenOpenAPI(ctx.CompileString("")) } return nil, err } template += velacue.BaseTemplate - if pd == nil { - var r cue.Runtime - cueInst, err := r.Compile("-", template) - if err != nil { - return nil, err - } - return common.GenOpenAPI(cueInst) - } - bi := build.NewContext().NewInstance("", nil) - err = value.AddFile(bi, "-", template) + val, err := value.NewValue(template, pd, "") if err != nil { return nil, err } - - cueInst, err := pd.ImportPackagesAndBuildInstance(bi) - if err != nil { - return nil, err - } - return common.GenOpenAPI(cueInst) + return common.GenOpenAPI(val.CueValue()) } // GenerateOpenAPISchemaFromDefinition returns the parameter of a definition diff --git a/pkg/definition/definition.go b/pkg/definition/definition.go index eb52db1d4..2cf998df4 100644 --- a/pkg/definition/definition.go +++ b/pkg/definition/definition.go @@ -164,8 +164,7 @@ func (def *Definition) ToCUE() (*cue.Value, string, error) { "attributes": spec, }, } - r := &cue.Runtime{} - codec := gocodec.New(r, &gocodec.Config{}) + codec := gocodec.New((*cue.Runtime)(cuecontext.New()), &gocodec.Config{}) val, err := codec.Decode(obj) if err != nil { return nil, "", err diff --git a/pkg/utils/common/common.go b/pkg/utils/common/common.go index 7a58a993a..281a6a9d2 100644 --- a/pkg/utils/common/common.go +++ b/pkg/utils/common/common.go @@ -31,7 +31,7 @@ import ( "path/filepath" "cuelang.org/go/cue" - "cuelang.org/go/cue/ast" + "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/format" "cuelang.org/go/encoding/openapi" "github.com/AlecAivazis/survey/v2" @@ -263,22 +263,22 @@ func GetCUEParameterValue(cueStr string, pd *packages.PackageDiscover) (cue.Valu } // GenOpenAPI generates OpenAPI json schema from cue.Instance -func GenOpenAPI(inst *cue.Instance) (b []byte, err error) { +func GenOpenAPI(val cue.Value) (b []byte, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("invalid cue definition to generate open api: %v", r) return } }() - if inst.Err != nil { - return nil, inst.Err + if val.Err() != nil { + return nil, val.Err() } - paramOnlyIns, err := RefineParameterInstance(inst) + paramOnlyVal, err := RefineParameterValue(val) if err != nil { return nil, err } defaultConfig := &openapi.Config{ExpandReferences: true} - b, err = openapi.Gen(paramOnlyIns, defaultConfig) + b, err = openapi.Gen(paramOnlyVal, defaultConfig) if err != nil { return nil, err } @@ -287,29 +287,10 @@ func GenOpenAPI(inst *cue.Instance) (b []byte, err error) { return out.Bytes(), nil } -// extractParameterDefinitionNodeFromInstance extracts the `#parameter` ast.Node from root instance, if failed fall back to `parameter` by LookUpDef +// RefineParameterValue refines cue value to merely include `parameter` identifier // nolint:staticcheck -func extractParameterDefinitionNodeFromInstance(inst *cue.Instance) ast.Node { - opts := []cue.Option{cue.Docs(true), cue.InlineImports(true)} - node := inst.Value().Syntax(opts...) - if fileNode, ok := node.(*ast.File); ok { - for _, decl := range fileNode.Decls { - if field, ok := decl.(*ast.Field); ok { - if label, ok := field.Label.(*ast.Ident); ok && label.Name == "#"+process.ParameterFieldName { - return decl.(*ast.Field).Value - } - } - } - } - paramVal := inst.LookupDef(process.ParameterFieldName) - return paramVal.Syntax(opts...) -} - -// RefineParameterInstance refines cue instance to merely include `parameter` identifier -// nolint:staticcheck -func RefineParameterInstance(inst *cue.Instance) (*cue.Instance, error) { - r := cue.Runtime{} - paramVal := inst.Lookup(process.ParameterFieldName) +func RefineParameterValue(val cue.Value) (cue.Value, error) { + paramVal := val.Lookup(process.ParameterFieldName) var paramOnlyStr string switch k := paramVal.IncompleteKind(); k { case cue.StructKind, cue.ListKind: @@ -320,13 +301,13 @@ func RefineParameterInstance(inst *cue.Instance) (*cue.Instance, error) { case cue.BottomKind: paramOnlyStr = fmt.Sprintf("#%s: {}", process.ParameterFieldName) default: - return nil, fmt.Errorf("unsupport parameter kind: %s", k.String()) + return cue.Value{}, fmt.Errorf("unsupport parameter kind: %s", k.String()) } - paramOnlyIns, err := r.Compile("-", paramOnlyStr) - if err != nil { - return nil, err + paramOnlyVal := cuecontext.New().CompileString(paramOnlyStr) + if paramOnlyVal.Err() != nil { + return cue.Value{}, paramOnlyVal.Err() } - return paramOnlyIns, nil + return paramOnlyVal, nil } // RealtimePrintCommandOutput prints command output in real time diff --git a/pkg/utils/common/common_test.go b/pkg/utils/common/common_test.go index 894e2d506..ead16b2d7 100644 --- a/pkg/utils/common/common_test.go +++ b/pkg/utils/common/common_test.go @@ -29,7 +29,7 @@ import ( "testing" "time" - "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" "cuelang.org/go/cue/load" "github.com/crossplane/crossplane-runtime/pkg/test" "github.com/google/go-cmp/cmp" @@ -305,7 +305,6 @@ name } } -// nolint:staticcheck func TestGenOpenAPI(t *testing.T) { type want struct { targetSchemaFile string @@ -337,10 +336,12 @@ func TestGenOpenAPI(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { - inst := cue.Build(load.Instances([]string{filepath.FromSlash(tc.fileName)}, &load.Config{ + vals, err := cuecontext.New().BuildInstances(load.Instances([]string{filepath.FromSlash(tc.fileName)}, &load.Config{ Dir: "testdata", - }))[0] - got, err := GenOpenAPI(inst) + })) + assert.NoError(t, err) + val := vals[0] + got, err := GenOpenAPI(val) if tc.want.err != nil { if diff := cmp.Diff(tc.want.err, errors.New(err.Error()), test.EquateErrors()); diff != "" { t.Errorf("\n%s\nGenOpenAPIFromFile(...): -want error, +got error:\n%s", tc.reason, diff) @@ -446,7 +447,6 @@ variable "mapVar" { assert.True(t, intVarExisted) } -// nolint:staticcheck func TestRefineParameterInstance(t *testing.T) { // test #parameter exists: mock issues in #1939 & #2062 s := `parameter: #parameter @@ -461,10 +461,10 @@ patch: { label: parameter.x } }` - r := cue.Runtime{} - inst, err := r.Compile("-", s) - assert.NoError(t, err) - _, err = RefineParameterInstance(inst) + cuectx := cuecontext.New() + val := cuectx.CompileString(s) + assert.NoError(t, val.Err()) + _, err := RefineParameterValue(val) assert.NoError(t, err) // test #parameter not exist but parameter exists s = `parameter: { @@ -473,24 +473,23 @@ patch: { y: string } }` - inst, err = r.Compile("-", s) + val = cuectx.CompileString(s) assert.NoError(t, err) - _ = extractParameterDefinitionNodeFromInstance(inst) - _, err = RefineParameterInstance(inst) + _, err = RefineParameterValue(val) assert.NoError(t, err) // test #parameter as int s = `parameter: #parameter #parameter: int` - inst, err = r.Compile("-", s) + val = cuectx.CompileString(s) assert.NoError(t, err) - _, err = RefineParameterInstance(inst) + _, err = RefineParameterValue(val) assert.NoError(t, err) // test invalid parameter kind s = `parameter: #parameter #parameter: '\x03abc'` - inst, err = r.Compile("-", s) + val = cuectx.CompileString(s) assert.NoError(t, err) - _, err = RefineParameterInstance(inst) + _, err = RefineParameterValue(val) assert.NotNil(t, err) } diff --git a/references/cli/def.go b/references/cli/def.go index bd79932de..f19eeb0dc 100644 --- a/references/cli/def.go +++ b/references/cli/def.go @@ -33,6 +33,7 @@ import ( "time" "cuelang.org/go/cue" + "cuelang.org/go/cue/cuecontext" "cuelang.org/go/encoding/gocode/gocodec" crossplane "github.com/oam-dev/terraform-controller/api/types/crossplane-runtime" "github.com/pkg/errors" @@ -142,7 +143,7 @@ func buildTemplateFromYAML(templateYAML string, def *pkgdef.Definition) error { templateObject[process.OutputsFieldName].(map[string]interface{})[name] = yamlObject } } - codec := gocodec.New(&cue.Runtime{}, &gocodec.Config{}) + codec := gocodec.New((*cue.Runtime)(cuecontext.New()), &gocodec.Config{}) val, err := codec.Decode(templateObject) if err != nil { return errors.Wrapf(err, "failed to decode template into cue")