Fix: use value instead of instance in openapi.gen (#4739)

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
This commit is contained in:
Tianxin Dong
2022-09-20 15:18:31 +08:00
committed by GitHub
parent 99d25a3657
commit d98016aa3d
8 changed files with 47 additions and 88 deletions
+3 -5
View File
@@ -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
}
+2 -2
View File
@@ -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
}
+4 -6
View File
@@ -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")
}
+5 -22
View File
@@ -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
+1 -2
View File
@@ -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
+14 -33
View File
@@ -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
+16 -17
View File
@@ -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)
}
+2 -1
View File
@@ -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")