Feat: vela cuex eval (#5562)

* Feat: vela cuex render

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

* feat: CLI command `vela cuex eval <file>`

Signed-off-by: Zhenghao Lou <rhzx3519@gmail.com>

* responsive writer

Signed-off-by: Somefive <yd219913@alibaba-inc.com>

---------

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
Signed-off-by: Zhenghao Lou <rhzx3519@gmail.com>
Co-authored-by: Zhenghao Lou <rhzx3519@gmail.com>
This commit is contained in:
Somefive
2023-04-23 10:21:11 +08:00
committed by GitHub
co-authored by Zhenghao Lou
parent 956eb31f29
commit 3de9e391ee
7 changed files with 228 additions and 3 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ require (
github.com/hashicorp/hcl/v2 v2.16.2
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
github.com/imdario/mergo v0.3.13
github.com/kubevela/pkg v1.8.1-0.20230410075324-9f0ba3b09495
github.com/kubevela/pkg v1.8.1-0.20230421100856-841accb6dd92
github.com/kubevela/workflow v0.5.1-0.20230412142834-be9e5a10baf0
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/magiconair/properties v1.8.7
+2 -2
View File
@@ -964,8 +964,8 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kubevela/pkg v1.8.1-0.20230410075324-9f0ba3b09495 h1:maT6E7JSrZgv4T1grgTBL69px7oUldc+tHIPxJ5SD9Y=
github.com/kubevela/pkg v1.8.1-0.20230410075324-9f0ba3b09495/go.mod h1:dGT23SGBw16frh5ReEYMFraxjppkX6jPCltBgTeLUhE=
github.com/kubevela/pkg v1.8.1-0.20230421100856-841accb6dd92 h1:wbsdJ6p6OhwUMRLpqCTFI1WxdjLxRrfWnNSHv/PVzsI=
github.com/kubevela/pkg v1.8.1-0.20230421100856-841accb6dd92/go.mod h1:dGT23SGBw16frh5ReEYMFraxjppkX6jPCltBgTeLUhE=
github.com/kubevela/workflow v0.5.1-0.20230412142834-be9e5a10baf0 h1:/ZPmjKpd/+fpCjJfNfUnE7jdESuCcZeP+fyTUAU9an0=
github.com/kubevela/workflow v0.5.1-0.20230412142834-be9e5a10baf0/go.mod h1:0GhIWFIPP+Zt31m4Aslx9mihoyNz3HrOvCV69ljMIBo=
github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
+1
View File
@@ -113,6 +113,7 @@ func NewCommandWithIOStreams(ioStream util.IOStreams) *cobra.Command {
NewProviderCommand(commandArgs, "10", ioStream),
AuthCommandGroup(f, ioStream),
KubeCommandGroup(f, ioStream),
CueXCommandGroup(f),
// Config management
ConfigCommandGroup(f, ioStream),
+116
View File
@@ -0,0 +1,116 @@
/*
Copyright 2023 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cli
import (
"fmt"
"os"
"github.com/kubevela/pkg/cue/cuex"
"github.com/kubevela/pkg/cue/util"
"github.com/spf13/cobra"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"github.com/oam-dev/kubevela/apis/types"
velacmd "github.com/oam-dev/kubevela/pkg/cmd"
)
// CueXCommandGroup commands for cuex management
func CueXCommandGroup(f velacmd.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "cuex",
Short: i18n.T("Manage CueX engine for compile."),
Annotations: map[string]string{
types.TagCommandType: types.TypeExtension,
},
}
cmd.AddCommand(NewCueXEvalCommand(f))
return cmd
}
// CueXEvalOption option for compile cuex
type CueXEvalOption struct {
Format string
Path string
File string
}
// Run compile cuex
func (in *CueXEvalOption) Run(cmd *cobra.Command) error {
if in.File == "" {
return fmt.Errorf("file must be provided for compile")
}
bs, err := os.ReadFile(in.File)
if err != nil {
return err
}
val, err := cuex.CompileString(cmd.Context(), string(bs))
if err != nil {
return err
}
bs, err = util.Print(val, util.WithFormat(in.Format), util.WithPath(in.Path))
if err != nil {
return err
}
cmd.Println(string(bs))
return nil
}
var (
cuexEvalLong = templates.LongDesc(i18n.T(`
Eval cue file with CueX engine.
Evaluate your cue file with the CueX engine. When your cue file does not
use KubeVela's extension, it will work similarly to the native CUE CLI.
When using KubeVela's extensions, this command will execute the extension
functions and resolve values, in addition to the native CUE compile process.
`))
cuexEvalExample = templates.Examples(i18n.T(`
# Evaluate a cue file
vela cuex eval -f my.cue
# Evaluate a cue file into json format
vela cuex eval -f my.cue -o json
# Evaluate a cue file and output the target path
vela cuex eval -f my.cue -p key.path
`))
)
// NewCueXEvalCommand `vela cuex eval` command
func NewCueXEvalCommand(f velacmd.Factory) *cobra.Command {
opt := &CueXEvalOption{
Format: string(util.PrintFormatCue),
}
cmd := &cobra.Command{
Use: "eval",
Short: i18n.T("Eval cue file with CueX engine."),
Long: cuexEvalLong,
Example: cuexEvalExample,
RunE: func(cmd *cobra.Command, args []string) error {
return opt.Run(cmd)
},
}
cmd.Flags().StringVarP(&opt.Format, "format", "o", opt.Format, "format of the output")
cmd.Flags().StringVarP(&opt.File, "file", "f", opt.File, "file for eval")
cmd.Flags().StringVarP(&opt.Path, "path", "p", opt.Path, "path for eval")
return velacmd.NewCommandBuilder(f, cmd).
WithResponsiveWriter().
Build()
}
+85
View File
@@ -0,0 +1,85 @@
/*
Copyright 2023 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cli
import (
"bytes"
"path/filepath"
"testing"
"github.com/kubevela/pkg/util/stringtools"
"github.com/stretchr/testify/require"
)
const (
testdataDir = "test-data/cuex"
)
func TestCueXEval(t *testing.T) {
buffer := bytes.NewBuffer(nil)
cmd := NewCueXEvalCommand(nil)
cmd.SetOut(buffer)
testCases := map[string]struct {
filepath string
path string
format string
expect string
}{
"normal evaluate": {
filepath.Join(testdataDir, "foo.cue"),
"S.name",
"",
"\"Postgres\"",
},
"json": {
filepath.Join(testdataDir, "foo.cue"),
"",
"json",
`{"label":"app","S":{"name":"Postgres","version":"13","label":"app","image":"docker.io/postgres:13"}}`,
},
"yaml": {
filepath.Join(testdataDir, "foo.cue"),
"",
"yaml",
`
S:
image: docker.io/postgres:13
label: app
name: Postgres
version: "13"
label: app`,
},
"http": {
filepath.Join(testdataDir, "httpget.cue"),
"statusCode",
"",
"200",
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
buffer.Truncate(0)
r := require.New(t)
cmd.SetArgs([]string{"-f", tc.filepath, "-p", tc.path, "-o", tc.format})
err := cmd.Execute()
r.NoError(err)
r.Equal(stringtools.TrimLeadingIndent(tc.expect), stringtools.TrimLeadingIndent(buffer.String()))
})
}
}
+13
View File
@@ -0,0 +1,13 @@
import "strings"
label: "app"
// alias for label
let L = label
S: {
name: "Postgres"
// intermediate value
let lower = strings.ToLower(name)
version: "13"
label: L
image: "docker.io/\(lower):\(version)"
}
+10
View File
@@ -0,0 +1,10 @@
import "vela/http"
req: http.#Get & {
$params: {
url: "https://cuelang.org"
}
}
body: req.$returns.body
statusCode: req.$returns.statusCode