Fix: open basic lit fails lookup path (#4632)

* Fix: open basic lit fails lookup path

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

* Fix: test

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

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

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
Somefive
2022-08-19 16:51:11 +08:00
committed by GitHub
parent 309eb2e702
commit afb0466bcc
4 changed files with 95 additions and 5 deletions

View File

@@ -23,6 +23,7 @@ import (
"cuelang.org/go/cue"
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/parser"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
)
@@ -356,8 +357,7 @@ func jsonMergePatch(base cue.Value, patch cue.Value) (cue.Value, error) {
if err != nil {
return cue.Value{}, errors.Wrapf(err, "failed to merge base value and patch value by JsonMergePatch")
}
val := ctx.CompileBytes(merged)
output, err := OpenBaiscLit(val)
output, err := openJSON(string(merged))
if err != nil {
return cue.Value{}, errors.Wrapf(err, "failed to parse open basic lit for merged result")
}
@@ -383,10 +383,46 @@ func jsonPatch(base cue.Value, patch cue.Value) (cue.Value, error) {
if err != nil {
return cue.Value{}, errors.Wrapf(err, "failed to apply json patch")
}
val := ctx.CompileBytes(merged)
output, err := OpenBaiscLit(val)
output, err := openJSON(string(merged))
if err != nil {
return cue.Value{}, errors.Wrapf(err, "failed to parse open basic lit for merged result")
}
return ctx.BuildFile(output), nil
}
func isEllipsis(elt ast.Node) bool {
_, ok := elt.(*ast.Ellipsis)
return ok
}
func openJSON(data string) (*ast.File, error) {
f, err := parser.ParseFile("-", data, parser.ParseComments)
if err != nil {
return nil, err
}
ast.Walk(f, func(node ast.Node) bool {
field, ok := node.(*ast.Field)
if ok {
v := field.Value
switch lit := v.(type) {
case *ast.StructLit:
if len(lit.Elts) == 0 || !isEllipsis(lit.Elts[len(lit.Elts)-1]) {
lit.Elts = append(lit.Elts, &ast.Ellipsis{})
}
case *ast.ListLit:
if len(lit.Elts) == 0 || !isEllipsis(lit.Elts[len(lit.Elts)-1]) {
lit.Elts = append(lit.Elts, &ast.Ellipsis{})
}
}
}
return true
}, nil)
if len(f.Decls) > 0 {
if emb, ok := f.Decls[0].(*ast.EmbedDecl); ok {
if s, _ok := emb.Expr.(*ast.StructLit); _ok {
f.Decls = s.Elts
}
}
}
return f, nil
}

View File

@@ -186,7 +186,8 @@ func peelCloseExpr(node ast.Node) ast.Node {
func lookField(node ast.Node, key string) ast.Node {
if field, ok := node.(*ast.Field); ok {
if labelStr(field.Label) == key {
// Note: the trim here has side effect: "\(v)" will be trimmed to \(v), only used for comparing fields
if strings.Trim(labelStr(field.Label), `"`) == strings.Trim(key, `"`) {
return field.Value
}
}

View File

@@ -605,5 +605,23 @@ var _ = Describe("Test multicluster scenario", func() {
g.Expect(k8sClient.Get(hubCtx, types.NamespacedName{Namespace: testNamespace, Name: "another"}, &corev1.ConfigMap{})).Should(Satisfy(kerrors.IsNotFound))
})
})
It("Test Application with env in webservice and labels & storage trait", func() {
bs, err := ioutil.ReadFile("./testdata/app/app-with-env-labels-storage.yaml")
Expect(err).Should(Succeed())
app := &v1beta1.Application{}
Expect(yaml.Unmarshal(bs, app)).Should(Succeed())
app.SetNamespace(namespace)
Expect(k8sClient.Create(hubCtx, app)).Should(Succeed())
deploy := &appsv1.Deployment{}
Eventually(func(g Gomega) {
g.Expect(k8sClient.Get(hubCtx, types.NamespacedName{Namespace: namespace, Name: "test"}, deploy)).Should(Succeed())
}, 15*time.Second).Should(Succeed())
Expect(deploy.GetLabels()["key"]).Should(Equal("val"))
Expect(len(deploy.Spec.Template.Spec.Containers[0].Env)).Should(Equal(1))
Expect(deploy.Spec.Template.Spec.Containers[0].Env[0].Name).Should(Equal("testKey"))
Expect(deploy.Spec.Template.Spec.Containers[0].Env[0].Value).Should(Equal("testValue"))
Expect(len(deploy.Spec.Template.Spec.Volumes)).Should(Equal(1))
})
})
})

View File

@@ -0,0 +1,35 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: test
spec:
components:
- name: test
properties:
cmd:
- sleep
- -c
- "86400"
env:
- name: testKey
value: testValue
image: busybox
imagePullPolicy: IfNotPresent
traits:
- properties:
key: val
type: labels
- properties:
pvc:
- accessModes:
- ReadWriteOnce
mountOnly: false
mountPath: /data
name: lvhyca
resources:
requests:
storage: 4096Mi
storageClassName: default
volumeMode: Filesystem
type: storage
type: webservice