cue: introduce colon-separated labels
- parser: parse old and new style.
- format: format new style
- update generated examples and tutorial
Issue #60
Change-Id: I52e0d64932cc850281c96d6ad8d1eafca59f50b0
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3550
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/script_test.go b/cmd/cue/cmd/script_test.go
index 13f23ea..e3bae80 100644
--- a/cmd/cue/cmd/script_test.go
+++ b/cmd/cue/cmd/script_test.go
@@ -1,12 +1,56 @@
package cmd
import (
+ "bytes"
+ "fmt"
"os"
+ "path"
+ "path/filepath"
+ "strings"
"testing"
+ "cuelang.org/go/cue/errors"
+ "cuelang.org/go/cue/parser"
"github.com/rogpeppe/testscript"
+ "github.com/rogpeppe/testscript/txtar"
)
+// TestLatest checks that the examples match the latest language standard,
+// even if still valid in backwards compatibility mode.
+func TestLatest(t *testing.T) {
+ filepath.Walk("testdata/script", func(fullpath string, info os.FileInfo, err error) error {
+ if !strings.HasSuffix(fullpath, ".txt") {
+ return nil
+ }
+
+ a, err := txtar.ParseFile(fullpath)
+ if err != nil {
+ t.Error(err)
+ return nil
+ }
+ if bytes.HasPrefix(a.Comment, []byte("!")) {
+ return nil
+ }
+
+ for _, f := range a.Files {
+ t.Run(path.Join(fullpath, f.Name), func(t *testing.T) {
+ if !strings.HasSuffix(f.Name, ".cue") {
+ return
+ }
+ v := parser.FromVersion(parser.Latest)
+ _, err := parser.ParseFile(f.Name, f.Data, v)
+ if err != nil {
+ w := &bytes.Buffer{}
+ fmt.Fprintf(w, "\n%s:\n", fullpath)
+ errors.Print(w, err, nil)
+ t.Error(w.String())
+ }
+ })
+ }
+ return nil
+ })
+}
+
func TestScript(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testdata/script",
diff --git a/cmd/cue/cmd/testdata/script/cmd_baddisplay.txt b/cmd/cue/cmd/testdata/script/cmd_baddisplay.txt
index 3302f7e..a41547b 100644
--- a/cmd/cue/cmd/testdata/script/cmd_baddisplay.txt
+++ b/cmd/cue/cmd/testdata/script/cmd_baddisplay.txt
@@ -13,8 +13,8 @@
-- task_tool.cue --
package home
-command baddisplay: {
- task display: {
+command: baddisplay: {
+ task: display: {
kind: "print"
text: 42
}
diff --git a/cmd/cue/cmd/testdata/script/cmd_echo.txt b/cmd/cue/cmd/testdata/script/cmd_echo.txt
index 9f76b2e..a626358 100644
--- a/cmd/cue/cmd/testdata/script/cmd_echo.txt
+++ b/cmd/cue/cmd/testdata/script/cmd_echo.txt
@@ -12,14 +12,14 @@
-- hello_tool.cue --
package hello
-command echo: {
- task echo: {
+command: echo: {
+ task: echo: {
kind: "exec"
cmd: "echo \(message)"
stdout: string
}
- task display: {
+ task: display: {
kind: "print"
text: task.echo.stdout
}
diff --git a/cmd/cue/cmd/testdata/script/cmd_errcode.txt b/cmd/cue/cmd/testdata/script/cmd_errcode.txt
index e8ff6d1..633f94b 100644
--- a/cmd/cue/cmd/testdata/script/cmd_errcode.txt
+++ b/cmd/cue/cmd/testdata/script/cmd_errcode.txt
@@ -9,8 +9,8 @@
-- task_tool.cue --
package home
-command errcode: {
- task bad: exec.Run & {
+command: errcode: {
+ task: bad: exec.Run & {
kind: "exec"
cmd: "ls --badflags"
stderr: string // suppress error message
diff --git a/cmd/cue/cmd/testdata/script/cmd_http.txt b/cmd/cue/cmd/testdata/script/cmd_http.txt
index 2ce28ee..4c240b1 100644
--- a/cmd/cue/cmd/testdata/script/cmd_http.txt
+++ b/cmd/cue/cmd/testdata/script/cmd_http.txt
@@ -7,20 +7,20 @@
package home
-command http: {
- task testserver: {
+command: http: {
+ task: testserver: {
kind: "testserver"
url: string
}
- task http: {
+ task: http: {
kind: "http"
method: "POST"
url: task.testserver.url
- request body: "I'll be back!"
- response body: string // TODO: allow this to be a struct, parsing the body.
+ request: body: "I'll be back!"
+ response: body: string // TODO: allow this to be a struct, parsing the body.
}
- task print: {
+ task: print: {
kind: "print"
text: task.http.response.body
}
diff --git a/cmd/cue/cmd/testdata/script/cmd_print.txt b/cmd/cue/cmd/testdata/script/cmd_print.txt
index 5ebf1c0..a42de26 100644
--- a/cmd/cue/cmd/testdata/script/cmd_print.txt
+++ b/cmd/cue/cmd/testdata/script/cmd_print.txt
@@ -13,7 +13,7 @@
"strings"
)
-command print: {
+command: print: {
task: {
t1: exec.Run & {
cmd: ["sh", "-c", "sleep 1; echo t1"]
diff --git a/cmd/cue/cmd/testdata/script/cmd_run.txt b/cmd/cue/cmd/testdata/script/cmd_run.txt
index 1da20f1..821fcf6 100644
--- a/cmd/cue/cmd/testdata/script/cmd_run.txt
+++ b/cmd/cue/cmd/testdata/script/cmd_run.txt
@@ -8,8 +8,8 @@
-- task_tool.cue --
package home
-command run: runBase & {
- task echo cmd: "echo \(message)"
+command: run: runBase & {
+ task: echo: cmd: "echo \(message)"
}
-- base_tool.cue --
@@ -18,12 +18,12 @@
// deliberately put in another file to test resolving top-level identifiers
// in different files.
runBase: {
- task echo: {
+ task: echo: {
kind: "exec"
stdout: string
}
- task display: {
+ task: display: {
kind: "print"
text: task.echo.stdout
}
diff --git a/cmd/cue/cmd/testdata/script/cmd_run_list.txt b/cmd/cue/cmd/testdata/script/cmd_run_list.txt
index 16a5b1c..4fbbfed 100644
--- a/cmd/cue/cmd/testdata/script/cmd_run_list.txt
+++ b/cmd/cue/cmd/testdata/script/cmd_run_list.txt
@@ -8,8 +8,8 @@
-- task_tool.cue --
package home
-command run_list: runBase & {
- task echo cmd: ["echo", message]
+command: run_list: runBase & {
+ task: echo: cmd: ["echo", message]
}
-- base_tool.cue --
@@ -18,12 +18,12 @@
// deliberately put in another file to test resolving top-level identifiers
// in different files.
runBase: {
- task echo: {
+ task: echo: {
kind: "exec"
stdout: string
}
- task display: {
+ task: display: {
kind: "print"
text: task.echo.stdout
}
diff --git a/cmd/cue/cmd/testdata/script/eval_expr.txt b/cmd/cue/cmd/testdata/script/eval_expr.txt
index 4d7b08e..69a60f4 100644
--- a/cmd/cue/cmd/testdata/script/eval_expr.txt
+++ b/cmd/cue/cmd/testdata/script/eval_expr.txt
@@ -20,7 +20,7 @@
idx: a[str] // should resolve to top-level `a`
str: string
}
-b a b: 4
+b: a: b: 4
a: {
b: 3
c: 4
diff --git a/cmd/cue/cmd/testdata/script/eval_tool.txt b/cmd/cue/cmd/testdata/script/eval_tool.txt
index 43aa9d6..e8a06e4 100644
--- a/cmd/cue/cmd/testdata/script/eval_tool.txt
+++ b/cmd/cue/cmd/testdata/script/eval_tool.txt
@@ -10,6 +10,6 @@
-- task_tool.cue --
package home
-command run_list: runBase & {
- task echo cmd: ["echo", message]
+command: run_list: runBase & {
+ task: echo: cmd: ["echo", message]
}
diff --git a/cmd/cue/cmd/testdata/script/import_hoiststr.txt b/cmd/cue/cmd/testdata/script/import_hoiststr.txt
index e821f07..e8fda16 100644
--- a/cmd/cue/cmd/testdata/script/import_hoiststr.txt
+++ b/cmd/cue/cmd/testdata/script/import_hoiststr.txt
@@ -18,7 +18,7 @@
_cue_json = [1, 2]
}]
}
-deployment booster: [{
+deployment: booster: [{
kind: "Deployment"
name: "booster"
replicas: 1
diff --git a/cmd/cue/cmd/testdata/script/import_path.txt b/cmd/cue/cmd/testdata/script/import_path.txt
index 80618e2..64a4f32 100644
--- a/cmd/cue/cmd/testdata/script/import_path.txt
+++ b/cmd/cue/cmd/testdata/script/import_path.txt
@@ -2,16 +2,16 @@
cmp stdout expect-stdout
-- expect-stdout --
-service booster: {
+service: booster: {
kind: "Service"
name: "booster"
}
-deployment booster: {
+deployment: booster: {
kind: "Deployment"
name: "booster"
replicas: 1
}
-service "supplement\nfoo": {
+service: "supplement\nfoo": {
kind: "Service"
name: """
supplement
diff --git a/cmd/cue/cmd/testdata/script/toolonly.txt b/cmd/cue/cmd/testdata/script/toolonly.txt
index be535bc..735de03 100644
--- a/cmd/cue/cmd/testdata/script/toolonly.txt
+++ b/cmd/cue/cmd/testdata/script/toolonly.txt
@@ -8,7 +8,7 @@
import "tool/cli"
-command foo task: {
+command: foo: task: {
foo: cli.Print & {
text: "foo"
}
diff --git a/cmd/cue/cmd/testdata/script/trim.txt b/cmd/cue/cmd/testdata/script/trim.txt
index b437ddf..df4bd4f 100644
--- a/cmd/cue/cmd/testdata/script/trim.txt
+++ b/cmd/cue/cmd/testdata/script/trim.txt
@@ -3,7 +3,7 @@
-- expect-stdout --
package trim
-foo <Name>: {
+foo: <Name>: {
_value: string
a: 4
@@ -21,12 +21,12 @@
rList: [{a: "a"}]
rcList: [{a: "a", c: b}]
- t <Name>: {
+ t: <Name>: {
x: >=0 & <=5
}
}
-foo bar: {
+foo: bar: {
_value: "here"
b: "foo"
c: 45
@@ -34,33 +34,33 @@
sList: [{b: "foo"}, {}]
}
-foo baz: {}
+foo: baz: {}
-foo multipath: {
- t <Name>: {
+foo: multipath: {
+ t: <Name>: {
// Combined with the other template, we know the value must be 5 and
// thus the entry below can be eliminated.
x: >=5 & <=8
}
- t u: {
+ t: u: {
}
}
// TODO: top-level fields are currently not removed.
group: {
for k, v in foo {
- comp "\(k)": v
+ comp: "\(k)": v
}
- comp bar: {
+ comp: bar: {
aa: 8 // new value
}
}
-- trim/trim.cue --
package trim
-foo <Name>: {
+foo: <Name>: {
_value: string
a: 4
@@ -78,12 +78,12 @@
rList: [{a: "a"}]
rcList: [{a: "a", c: b}]
- t <Name>: {
+ t: <Name>: {
x: >=0 & <=5
}
}
-foo bar: {
+foo: bar: {
_value: "here"
b: "foo"
c: 45
@@ -91,26 +91,26 @@
sList: [{b: "foo"}, {}]
}
-foo baz: {}
+foo: baz: {}
-foo multipath: {
- t <Name>: {
+foo: multipath: {
+ t: <Name>: {
// Combined with the other template, we know the value must be 5 and
// thus the entry below can be eliminated.
x: >=5 & <=8
}
- t u: {
+ t: u: {
}
}
// TODO: top-level fields are currently not removed.
group: {
for k, v in foo {
- comp "\(k)": v
+ comp: "\(k)": v
}
- comp bar: {
+ comp: bar: {
aa: 8 // new value
}
}
diff --git a/cmd/cue/cmd/testdata/script/vet_concrete.txt b/cmd/cue/cmd/testdata/script/vet_concrete.txt
index 2aa0108..aefae51 100644
--- a/cmd/cue/cmd/testdata/script/vet_concrete.txt
+++ b/cmd/cue/cmd/testdata/script/vet_concrete.txt
@@ -18,7 +18,7 @@
idx: a[str] // should resolve to top-level `a`
str: string
}
-b a b: 4
+b: a: b: 4
a: {
b: 3
c: 4
diff --git a/cmd/cue/cmd/testdata/script/vet_file.txt b/cmd/cue/cmd/testdata/script/vet_file.txt
index b000daf..672192b 100644
--- a/cmd/cue/cmd/testdata/script/vet_file.txt
+++ b/cmd/cue/cmd/testdata/script/vet_file.txt
@@ -3,13 +3,13 @@
-- expect-stderr --
translations.hello.lang: incomplete value (string):
- ./vet.cue:2:24
+ ./vet.cue:2:26
translations.hello.lang: conflicting values false and string (mismatched types bool and string):
./data.yaml:13:11
- ./vet.cue:2:24
+ ./vet.cue:2:26
-- vet.cue --
-translations <_> lang: string
+translations: <_>: lang: string
File :: {
translations: {...}
diff --git a/cue/ast/astutil/apply_test.go b/cue/ast/astutil/apply_test.go
index 7c981bf..57b15c4 100644
--- a/cue/ast/astutil/apply_test.go
+++ b/cue/ast/astutil/apply_test.go
@@ -140,12 +140,12 @@
name: "templates",
in: `
foo: {
- a <b> c: 3
+ a: <b>: c: 3
}
`,
out: `
foo: {
- a <b>: {
+ a: <b>: {
c: 3
iam: new
}
diff --git a/cue/export_test.go b/cue/export_test.go
index 3bf8181..a42f84e 100644
--- a/cue/export_test.go
+++ b/cue/export_test.go
@@ -160,7 +160,7 @@
in: `{ a: { b: [] }, c: a.b, d: a["b"] }`,
out: unindent(`
{
- a b: []
+ a: b: []
c: a.b
d: a["b"]
}`),
@@ -288,10 +288,10 @@
A = a
b: {
idx: A[str]
- a b: 4
+ a: b: 4
str: string
}
- a b: 3
+ a: b: 3
}`),
}, {
raw: true,
@@ -355,7 +355,7 @@
{
emb :: {
a: 1
- sub f: 3
+ sub: f: 3
}
f :: {
a: 10
@@ -391,26 +391,26 @@
{
reg: {
foo: 1
- bar baz: 3
+ bar: baz: 3
}
def :: {
a: 1
sub: {
foo: 1
- bar baz: 3
+ bar: baz: 3
}
}
val: {
a: 1
sub: {
foo: 1
- bar baz: 3
+ bar: baz: 3
}
}
def2 :: {
- a b: int
+ a: b: int
}
- val2 a b: int
+ val2: a: b: int
}`),
}, {
raw: true,
@@ -501,7 +501,7 @@
And :: {
"Fn::And": []
}
- Ands "Fn::And": [3 | And]
+ Ands: "Fn::And": [3 | And]
}`),
}, {
raw: true,
@@ -664,7 +664,7 @@
import "strings"
STRINGS = strings
- a strings: STRINGS.ContainsAny("c")`),
+ a: strings: STRINGS.ContainsAny("c")`),
}, {
in: `
a: b - 100
@@ -745,7 +745,7 @@
{
reg: {
foo: 1
- bar baz: 3
+ bar: baz: 3
}
def :: {
a: 1
@@ -762,7 +762,7 @@
a: 1
sub: {
foo: 1
- bar baz: 3
+ bar: baz: 3
}
})
}`),
@@ -808,7 +808,7 @@
X :: {
x: int64
}
- x x: int64
+ x: x: int64
}`),
}, {
eval: true,
@@ -829,7 +829,7 @@
{
reg: {
foo: 1
- bar baz: 3
+ bar: baz: 3
}
def :: {
a: 1
@@ -846,11 +846,11 @@
a: 1
sub: {
foo: 1
- bar baz: 3
+ bar: baz: 3
}
})
def2 :: {
- a b: int
+ a: b: int
}
val2: close({
a: close({
diff --git a/cue/format/format.go b/cue/format/format.go
index e83a98c..6b2c6e2 100644
--- a/cue/format/format.go
+++ b/cue/format/format.go
@@ -179,6 +179,7 @@
type labelEntry struct {
label ast.Label
+ typ token.Token
optional bool
}
diff --git a/cue/format/format_test.go b/cue/format/format_test.go
index d3de3fe..0bd6104 100644
--- a/cue/format/format_test.go
+++ b/cue/format/format_test.go
@@ -18,7 +18,6 @@
import (
"bytes"
- "errors"
"flag"
"fmt"
"io/ioutil"
@@ -27,6 +26,7 @@
"time"
"cuelang.org/go/cue/ast"
+ "cuelang.org/go/cue/errors"
"cuelang.org/go/cue/parser"
"cuelang.org/go/cue/token"
)
@@ -71,7 +71,8 @@
// make sure formatted output is syntactically correct
if _, err := parser.ParseFile("", res, parser.AllErrors); err != nil {
- return nil, fmt.Errorf("re-parse: %s\n%s", err, res)
+ return nil, errors.Append(err.(errors.Error),
+ errors.Newf(token.NoPos, "re-parse failed: %s", res))
}
return res, nil
@@ -127,7 +128,9 @@
res, err := format(src, mode)
if err != nil {
- t.Error(err)
+ b := &bytes.Buffer{}
+ errors.Print(b, err, nil)
+ t.Error(b.String())
return
}
diff --git a/cue/format/node.go b/cue/format/node.go
index 44c6fe9..8524431 100644
--- a/cue/format/node.go
+++ b/cue/format/node.go
@@ -138,11 +138,11 @@
lastSize := len(f.labelBuf)
f.labelBuf = f.labelBuf[:0]
regular := isRegularField(n.Token)
- first, opt := n.Label, n.Optional != token.NoPos
+ first, typ, opt := n.Label, n.Token, n.Optional != token.NoPos
// If the label has a valid position, we assume that an unspecified
// Lbrace signals the intend to collapse fields.
- for (n.Label.Pos().IsValid() || f.printer.cfg.simplify) && regular {
+ for n.Label.Pos().IsValid() || (f.printer.cfg.simplify && regular) {
obj, ok := n.Value.(*ast.StructLit)
if !ok || len(obj.Elts) != 1 || (obj.Lbrace.IsValid() && !f.printer.cfg.simplify) || len(n.Attrs) > 0 {
break
@@ -164,10 +164,7 @@
if !ok || len(mem.Attrs) > 0 {
break
}
- if !isRegularField(mem.Token) {
- break
- }
- entry := labelEntry{mem.Label, mem.Optional != token.NoPos}
+ entry := labelEntry{mem.Label, mem.Token, mem.Optional != token.NoPos}
f.labelBuf = append(f.labelBuf, entry)
n = mem
}
@@ -175,15 +172,18 @@
if lastSize != len(f.labelBuf) {
f.print(formfeed)
}
- if !regular && first.Pos().RelPos() < token.Newline && len(f.output) > 0 {
- f.print(newline, nooverride)
- }
f.before(nil)
f.label(first, opt)
for _, x := range f.labelBuf {
+ if isRegularField(typ) {
+ f.print(n.TokenPos, token.COLON)
+ } else {
+ f.print(blank, nooverride, typ)
+ }
f.print(blank, nooverride)
f.label(x.label, x.optional)
+ typ = x.typ
}
f.after(nil)
diff --git a/cue/format/node_test.go b/cue/format/node_test.go
index ae358b6..6a5fe3e 100644
--- a/cue/format/node_test.go
+++ b/cue/format/node_test.go
@@ -15,7 +15,6 @@
package format
import (
- "strings"
"testing"
"cuelang.org/go/cue/ast"
@@ -42,9 +41,8 @@
}},
}},
// Force a new struct.
- out: `foo: {
- bar :: {
- }
+ out: `
+foo: bar :: {
}`,
}}
for _, tc := range testCases {
@@ -54,7 +52,7 @@
t.Fatal(err)
}
got := string(b)
- want := strings.TrimSpace(tc.out)
+ want := tc.out
if got != want {
t.Errorf("\ngot %v;\nwant %v", got, want)
}
diff --git a/cue/format/testdata/expressions.golden b/cue/format/testdata/expressions.golden
index ae7d8bd..cbd4ab3 100644
--- a/cue/format/testdata/expressions.golden
+++ b/cue/format/testdata/expressions.golden
@@ -6,9 +6,9 @@
b: 3
- c b a: 4
- c? bb? aaa?: 5
- c b <Name> a: int
+ c: b: a: 4
+ c?: bb?: aaa?: 5
+ c: b: <Name>: a: int
alias = 3.14
"g\("en")"?: 4
diff --git a/cue/format/testdata/simplify.golden b/cue/format/testdata/simplify.golden
index edb8b27..c6682e0 100644
--- a/cue/format/testdata/simplify.golden
+++ b/cue/format/testdata/simplify.golden
@@ -1,6 +1,6 @@
-foo bar: "str"
+foo: bar: "str"
-a B: 42
+a: B: 42
-"a.b" "foo-" cc_dd: x
+"a.b": "foo-": cc_dd: x
diff --git a/cue/parser/parser.go b/cue/parser/parser.go
index 894e2a7..46e2344 100644
--- a/cue/parser/parser.go
+++ b/cue/parser/parser.go
@@ -757,7 +757,8 @@
for i := 0; ; i++ {
tok := p.tok
- expr, ok := p.parseLabel(m)
+ label, expr, ok := p.parseLabel(false)
+ m.Label = label
if !ok {
if expr == nil {
@@ -805,6 +806,7 @@
switch p.tok {
case token.IDENT, token.STRING, token.LSS, token.INTERPOLATION, token.LBRACK:
+ p.assertV0(0, 12, "space-separated labels")
field := &ast.Field{}
m.Value = &ast.StructLit{Elts: []ast.Decl{field}}
m = field
@@ -835,7 +837,38 @@
p.errorExpected(pos, "':' or '::'")
}
p.next() // : or ::
- m.Value = p.parseRHS()
+
+ for {
+ tok := p.tok
+ label, expr, ok := p.parseLabel(true)
+ if !ok || (p.tok != token.COLON && p.tok != token.ISA && p.tok != token.OPTION) {
+ if expr == nil {
+ expr = p.parseRHS()
+ }
+ m.Value = expr
+ break
+ }
+ field := &ast.Field{Label: label}
+ m.Value = &ast.StructLit{Elts: []ast.Decl{field}}
+ m = field
+
+ if tok != token.LSS && p.tok == token.OPTION {
+ m.Optional = p.pos
+ p.next()
+ }
+
+ m.TokenPos = p.pos
+ m.Token = p.tok
+ if p.tok != token.COLON && p.tok != token.ISA {
+ if p.tok.IsLiteral() {
+ p.errf(p.pos, "expected ':' or '::'; found %s", p.lit)
+ } else {
+ p.errf(p.pos, "expected ':' or '::'; found %s", p.tok)
+ }
+ break
+ }
+ p.next()
+ }
if attrs := p.parseAttributes(); attrs != nil {
allowComprehension = false
@@ -894,7 +927,7 @@
return attrs
}
-func (p *parser) parseLabel(f *ast.Field) (expr ast.Expr, ok bool) {
+func (p *parser) parseLabel(rhs bool) (label ast.Label, expr ast.Expr, ok bool) {
tok := p.tok
switch tok {
case token.IDENT, token.STRING, token.INTERPOLATION,
@@ -911,16 +944,16 @@
// generating good errors: any keyword can only appear on the RHS of a
// field (after a ':'), whereas labels always appear on the LHS.
- f.Label, ok = x, true
+ label, ok = x, true
}
case ast.Label:
- f.Label, ok = x, true
+ label, ok = x, true
}
case token.IF, token.FOR, token.IN, token.LET:
// Keywords representing clauses.
- f.Label = &ast.Ident{
+ label = &ast.Ident{
NamePos: p.pos,
Name: p.lit,
}
@@ -928,20 +961,69 @@
ok = true
case token.LSS:
+ p.openList()
+ defer p.closeList()
+
pos := p.pos
c := p.openComments()
p.next()
- ident := p.parseIdent()
- gtr := p.pos
- if p.tok != token.GTR {
- p.expect(token.GTR)
+ var ident *ast.Ident
+ var gtr token.Pos
+ switch {
+ case rhs:
+ // TODO: remove this code once the <X> notation is out.
+ if p.tok != token.IDENT {
+ // parse RHS and continue binary Expression
+ expr = p.parseUnaryExpr()
+ expr = &ast.UnaryExpr{OpPos: pos, Op: token.LSS, X: expr}
+ expr = c.closeExpr(p, expr)
+ return nil, p.parseBinaryExprTail(false, token.LowestPrec+1, expr), false
+ }
+
+ ident = p.parseIdent()
+ if p.tok != token.GTR {
+ expr = p.parsePrimaryExprTail(ident)
+ expr = &ast.UnaryExpr{OpPos: pos, Op: token.LSS, X: expr}
+ expr = c.closeExpr(p, expr)
+ return nil, p.parseBinaryExprTail(false, token.LowestPrec+1, expr), false
+ }
+ gtr = p.pos
+ p.next()
+
+ // NOTE: at this point, even if there still a syntactically valid
+ // expression, it will always yield bottom, as '>' does not take
+ // boolean arguments.
+ // This code does not allow for `<X>[string]:` and so on. So a
+ // new way to alias labels should be introduced at the time
+ // such constructs are introduced. For instance `(X,Y)=[string]:`.
+ if p.tok != token.COLON && p.tok != token.ISA {
+ expr = &ast.UnaryExpr{OpPos: pos, Op: token.LSS, X: ident}
+ expr = c.closeExpr(p, expr)
+ c := p.openComments()
+ prec := token.GTR.Precedence()
+ expr = c.closeExpr(p, &ast.BinaryExpr{
+ X: expr,
+ OpPos: gtr,
+ Op: token.GTR,
+ Y: p.checkExpr(p.parseBinaryExpr(false, prec)),
+ })
+ return nil, expr, false
+ }
+
+ default:
+ ident = p.parseIdent()
+ gtr = p.pos
+ if p.tok != token.GTR {
+ p.expect(token.GTR)
+ }
+ p.next()
}
- p.next()
- label := &ast.TemplateLabel{Langle: pos, Ident: ident, Rangle: gtr}
+
+ label = &ast.TemplateLabel{Langle: pos, Ident: ident, Rangle: gtr}
c.closeNode(p, label)
- f.Label, ok = label, true
+ ok = true
}
- return expr, ok
+ return label, expr, ok
}
func (p *parser) parseStruct() (expr ast.Expr) {
@@ -1177,8 +1259,11 @@
defer un(trace(p, "PrimaryExpr"))
}
- x := p.parseOperand()
+ return p.parsePrimaryExprTail(p.parseOperand())
+}
+func (p *parser) parsePrimaryExprTail(operand ast.Expr) ast.Expr {
+ x := operand
L:
for {
switch p.tok {
@@ -1261,12 +1346,15 @@
p.openList()
defer p.closeList()
- x := p.parseUnaryExpr()
+ return p.parseBinaryExprTail(lhs, prec1, p.parseUnaryExpr())
+}
+func (p *parser) parseBinaryExprTail(lhs bool, prec1 int, x ast.Expr) ast.Expr {
for {
op, prec := p.tokPrec()
if lhs && op == token.LSS {
// Eagerly interpret this as a template label.
+ // TODO: remove once <X> is deprecated.
if _, ok := x.(ast.Label); ok {
return x
}
diff --git a/cue/parser/parser_test.go b/cue/parser/parser_test.go
index 85e56c9..51821d9 100644
--- a/cue/parser/parser_test.go
+++ b/cue/parser/parser_test.go
@@ -146,11 +146,12 @@
`package k8s, import a "foo", import "bar/baz"`,
}, {
"collapsed fields",
- `a b c: 1
+ `a: b:: c?: <Name>: d: 1
+ "g\("en")"?: 4
// job foo { bar: 1 } // TODO error after foo
- job "foo": { bar: 1 }
+ job "foo" <X>: { bar: 1 }
`,
- `a: {b: {c: 1}}, job: {"foo": {bar: 1}}`,
+ `a: {b :: {c?: {<Name>: {d: 1}}}}, "g\("en")"?: 4, job: {"foo": {<X>: {bar: 1}}}`,
}, {
"identifiers",
`// $_: 1,
@@ -412,6 +413,8 @@
testCases := []struct{ desc, in string }{
{"block comments",
`a: 1 /* a */`},
+ {"space separator",
+ `a b c: 2`},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
@@ -572,7 +575,7 @@
func TestX(t *testing.T) {
t.Skip()
- f, err := ParseFile("input", ``)
+ f, err := ParseFile("input", `a: b:: c?: <Name>: d: 1`)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
diff --git a/doc/tutorial/basics/0_intro/55_fold.txt b/doc/tutorial/basics/0_intro/55_fold.txt
index a6bd0a9..fc950e1 100644
--- a/doc/tutorial/basics/0_intro/55_fold.txt
+++ b/doc/tutorial/basics/0_intro/55_fold.txt
@@ -23,11 +23,11 @@
-- fold.cue --
// path-value pairs
-outer middle1 inner: 3
-outer middle2 inner: 7
+outer: middle1: inner: 3
+outer: middle2: inner: 7
// collection-constraint pair
-outer <Any> inner: int
+outer: <Any>: inner: int
-- expect-stdout-cue --
{
diff --git a/doc/tutorial/basics/2_types/05_types.txt b/doc/tutorial/basics/2_types/05_types.txt
index ef85665..c56e99f 100644
--- a/doc/tutorial/basics/2_types/05_types.txt
+++ b/doc/tutorial/basics/2_types/05_types.txt
@@ -43,10 +43,10 @@
}
xaxis: point
-xaxis x: 0
+xaxis: x: 0
yaxis: point
-yaxis y: 0
+yaxis: y: 0
origin: xaxis & yaxis
diff --git a/doc/tutorial/basics/2_types/90_templates.txt b/doc/tutorial/basics/2_types/90_templates.txt
index 779854b..b08f49b 100644
--- a/doc/tutorial/basics/2_types/90_templates.txt
+++ b/doc/tutorial/basics/2_types/90_templates.txt
@@ -18,15 +18,15 @@
-- templates.cue --
// The following struct is unified with all elements in job.
// The name of each element is bound to Name and visible in the struct.
-job <Name>: {
+job: <Name>: {
name: Name
replicas: uint | *1
command: string
}
-job list command: "ls"
+job: list: command: "ls"
-job nginx: {
+job: nginx: {
command: "nginx"
replicas: 2
}
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/bartender/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/bartender/kube.cue
index 24164fc..8570398 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/bartender/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/bartender/kube.cue
@@ -1,6 +1,6 @@
package kube
-deployment bartender spec template spec containers: [{
+deployment: bartender: spec: template: spec: containers: [{
image: "gcr.io/myproj/bartender:v0.1.34"
args: [
]
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/breaddispatcher/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/breaddispatcher/kube.cue
index 16af218..6e06a6a 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/breaddispatcher/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/breaddispatcher/kube.cue
@@ -1,6 +1,6 @@
package kube
-deployment breaddispatcher spec template spec containers: [{
+deployment: breaddispatcher: spec: template: spec: containers: [{
image: "gcr.io/myproj/breaddispatcher:v0.3.24"
args: [
"-etcd=etcd:2379",
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/host/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/host/kube.cue
index 97f1fe6..e58c822 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/host/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/host/kube.cue
@@ -1,8 +1,8 @@
package kube
-deployment host spec: {
+deployment: host: spec: {
replicas: 2
- template spec containers: [{
+ template: spec: containers: [{
image: "gcr.io/myproj/host:v0.1.10"
args: [
]
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/kube.cue
index b2a3007..d896430 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/kube.cue
@@ -2,12 +2,12 @@
Component :: "frontend"
-deployment <X> spec template: {
- metadata annotations: {
+deployment: <X>: spec: template: {
+ metadata: annotations: {
"prometheus.io.scrape": "true"
"prometheus.io.port": "\(spec.containers[0].ports[0].containerPort)"
}
- spec containers: [{
+ spec: containers: [{
ports: [{containerPort: *7080 | int}] // 7080 is the default
}]
}
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/maitred/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/maitred/kube.cue
index 00a213c..4829e95 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/maitred/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/maitred/kube.cue
@@ -1,6 +1,6 @@
package kube
-deployment maitred spec template spec containers: [{
+deployment: maitred: spec: template: spec: containers: [{
image: "gcr.io/myproj/maitred:v0.0.4"
args: [
]
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/valeter/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/valeter/kube.cue
index da37ea9..3f0963e 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/valeter/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/valeter/kube.cue
@@ -1,9 +1,9 @@
package kube
-service valeter spec ports: [{
+service: valeter: spec: ports: [{
name: "http"
}]
-deployment valeter spec template spec containers: [{
+deployment: valeter: spec: template: spec: containers: [{
image: "gcr.io/myproj/valeter:v0.0.4"
ports: [{
containerPort: 8080
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/waiter/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/waiter/kube.cue
index 3fcda5b..7a2c1de 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/waiter/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/waiter/kube.cue
@@ -1,8 +1,8 @@
package kube
-deployment waiter spec: {
+deployment: waiter: spec: {
replicas: 5
- template spec containers: [{
+ template: spec: containers: [{
image: "gcr.io/myproj/waiter:v0.3.0"
}]
}
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/waterdispatcher/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/waterdispatcher/kube.cue
index 66e9e56..058f185 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/waterdispatcher/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/waterdispatcher/kube.cue
@@ -1,9 +1,9 @@
package kube
-service waterdispatcher spec ports: [{
+service: waterdispatcher: spec: ports: [{
name: "http"
}]
-deployment waterdispatcher spec template spec containers: [{
+deployment: waterdispatcher: spec: template: spec: containers: [{
image: "gcr.io/myproj/waterdispatcher:v0.0.48"
args: [
"-http=:8080",
diff --git a/doc/tutorial/kubernetes/quick/services/infra/download/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/download/kube.cue
index 7a56c6f..a7860ae 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/download/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/download/kube.cue
@@ -1,6 +1,6 @@
package kube
-deployment download spec template spec containers: [{
+deployment: download: spec: template: spec: containers: [{
image: "gcr.io/myproj/download:v0.0.2"
ports: [{
containerPort: 7080
diff --git a/doc/tutorial/kubernetes/quick/services/infra/etcd/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/etcd/kube.cue
index 7a0e915..ae2f756 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/etcd/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/etcd/kube.cue
@@ -1,23 +1,23 @@
package kube
-service etcd spec: {
+service: etcd: spec: {
clusterIP: "None"
ports: [{
}, {
name: "peer"
}]
}
-statefulSet etcd spec: {
+statefulSet: etcd: spec: {
serviceName: "etcd"
replicas: 3
template: {
- metadata annotations: {
+ metadata: annotations: {
"prometheus.io.scrape": "true"
"prometheus.io.port": "2379"
}
spec: {
- affinity podAntiAffinity requiredDuringSchedulingIgnoredDuringExecution: [{
- labelSelector matchExpressions: [{
+ affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: [{
+ labelSelector: matchExpressions: [{
key: "app"
operator: "In"
values: [
@@ -55,10 +55,10 @@
value: "4"
}, {
name: "NAME"
- valueFrom fieldRef fieldPath: "metadata.name"
+ valueFrom: fieldRef: fieldPath: "metadata.name"
}, {
name: "IP"
- valueFrom fieldRef fieldPath: "status.podIP"
+ valueFrom: fieldRef: fieldPath: "status.podIP"
}]
command: ["/usr/local/bin/etcd"]
args: [
@@ -86,11 +86,11 @@
volumeClaimTemplates: [{
metadata: {
name: "etcd3"
- annotations "volume.alpha.kubernetes.io/storage-class": "default"
+ annotations: "volume.alpha.kubernetes.io/storage-class": "default"
}
spec: {
accessModes: ["ReadWriteOnce"]
- resources requests storage: "10Gi"
+ resources: requests: storage: "10Gi"
}
}]
}
diff --git a/doc/tutorial/kubernetes/quick/services/infra/events/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/events/kube.cue
index 5bfb6a3..d55ceb7 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/events/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/events/kube.cue
@@ -1,18 +1,18 @@
package kube
-service events spec ports: [{
+service: events: spec: ports: [{
name: "grpc"
}]
-deployment events spec: {
+deployment: events: spec: {
replicas: 2
template: {
- metadata annotations: {
+ metadata: annotations: {
"prometheus.io.scrape": "true"
"prometheus.io.port": "7080"
}
spec: {
- affinity podAntiAffinity requiredDuringSchedulingIgnoredDuringExecution: [{
- labelSelector matchExpressions: [{
+ affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: [{
+ labelSelector: matchExpressions: [{
key: "app"
operator: "In"
values: [
@@ -23,7 +23,7 @@
}]
volumes: [{
name: "secret-volume"
- secret secretName: "biz-secrets"
+ secret: secretName: "biz-secrets"
}]
containers: [{
image: "gcr.io/myproj/events:v0.1.31"
@@ -47,4 +47,4 @@
}
}
-deployment events spec template spec containers: [{ports: [{_export: false}, _]}]
+deployment: events: spec: template: spec: containers: [{ports: [{_export: false}, _]}]
diff --git a/doc/tutorial/kubernetes/quick/services/infra/tasks/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/tasks/kube.cue
index d478917..7181560 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/tasks/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/tasks/kube.cue
@@ -1,17 +1,17 @@
package kube
-deployment tasks spec: {
+deployment: tasks: spec: {
// podTemplate defines the 'cookie cutter' used for creating
// new pods when necessary
template: {
- metadata annotations: {
+ metadata: annotations: {
"prometheus.io.scrape": "true"
"prometheus.io.port": "7080"
}
spec: {
volumes: [{
name: "secret-volume"
- secret secretName: "star-example-com-secrets"
+ secret: secretName: "star-example-com-secrets"
}]
containers: [{
image: "gcr.io/myproj/tasks:v0.2.6"
@@ -29,4 +29,4 @@
}
}
-deployment tasks spec template spec containers: [{ports: [{_export: false}, _]}]
+deployment: tasks: spec: template: spec: containers: [{ports: [{_export: false}, _]}]
diff --git a/doc/tutorial/kubernetes/quick/services/infra/tasks/service.cue b/doc/tutorial/kubernetes/quick/services/infra/tasks/service.cue
index 4cab0f4..ce4b3b3 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/tasks/service.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/tasks/service.cue
@@ -1,6 +1,6 @@
package kube
-service tasks spec: {
+service: tasks: spec: {
type: "LoadBalancer"
loadBalancerIP: "1.2.3.4" // static ip
ports: [{
diff --git a/doc/tutorial/kubernetes/quick/services/infra/updater/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/updater/kube.cue
index 480d013..ca7b848 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/updater/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/updater/kube.cue
@@ -1,9 +1,9 @@
package kube
-deployment updater spec template spec: {
+deployment: updater: spec: template: spec: {
volumes: [{
name: "secret-updater"
- secret secretName: "updater-secrets"
+ secret: secretName: "updater-secrets"
}]
containers: [{
image: "gcr.io/myproj/updater:v0.1.0"
diff --git a/doc/tutorial/kubernetes/quick/services/infra/watcher/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/watcher/kube.cue
index 951b967..516a5cc 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/watcher/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/watcher/kube.cue
@@ -1,12 +1,12 @@
package kube
-deployment watcher spec: {
+deployment: watcher: spec: {
// podTemplate defines the 'cookie cutter' used for creating
// new pods when necessary
- template spec: {
+ template: spec: {
volumes: [{
name: "secret-volume"
- secret secretName: "star-example-com-secrets"
+ secret: secretName: "star-example-com-secrets"
}]
containers: [{
image: "gcr.io/myproj/watcher:v0.1.0"
@@ -23,4 +23,4 @@
}
}
-deployment watcher spec template spec containers: [{ports: [{_export: false}, _]}]
+deployment: watcher: spec: template: spec: containers: [{ports: [{_export: false}, _]}]
diff --git a/doc/tutorial/kubernetes/quick/services/infra/watcher/service.cue b/doc/tutorial/kubernetes/quick/services/infra/watcher/service.cue
index 0b8b6d9..3d0e60a 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/watcher/service.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/watcher/service.cue
@@ -1,6 +1,6 @@
package kube
-service watcher spec: {
+service: watcher: spec: {
type: "LoadBalancer"
loadBalancerIP: "1.2.3.4." // static ip
ports: [{
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/caller/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/caller/kube.cue
index 6315001..ddd728b 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/caller/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/caller/kube.cue
@@ -1,8 +1,8 @@
package kube
-deployment caller spec: {
+deployment: caller: spec: {
replicas: 3
- template spec: {
+ template: spec: {
volumes: [{
name: "ssd-caller"
gcePersistentDisk: {
@@ -12,7 +12,7 @@
}, {
}, {
name: "secret-ssh-key"
- secret secretName: "secrets"
+ secret: secretName: "secrets"
}]
containers: [{
image: "gcr.io/myproj/caller:v0.20.14"
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/dishwasher/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/dishwasher/kube.cue
index fe2019d..49430a4 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/dishwasher/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/dishwasher/kube.cue
@@ -1,13 +1,13 @@
package kube
-deployment dishwasher spec: {
+deployment: dishwasher: spec: {
replicas: 5
- template spec: {
+ template: spec: {
volumes: [{
}, {
}, {
name: "secret-ssh-key"
- secret secretName: "dishwasher-secrets"
+ secret: secretName: "dishwasher-secrets"
}]
containers: [{
image: "gcr.io/myproj/dishwasher:v0.2.13"
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/expiditer/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/expiditer/kube.cue
index 8370582..c152000 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/expiditer/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/expiditer/kube.cue
@@ -1,6 +1,6 @@
package kube
-deployment expiditer spec template spec containers: [{
+deployment: expiditer: spec: template: spec: containers: [{
image: "gcr.io/myproj/expiditer:v0.5.34"
args: [
"-env=prod",
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/headchef/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/headchef/kube.cue
index 68657ea..983d689 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/headchef/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/headchef/kube.cue
@@ -1,6 +1,6 @@
package kube
-deployment headchef spec template spec containers: [{
+deployment: headchef: spec: template: spec: containers: [{
image: "gcr.io/myproj/headchef:v0.2.16"
volumeMounts: [{
}, {
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/kube.cue
index 71450a1..02fa1f9 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/kube.cue
@@ -2,9 +2,9 @@
Component :: "kitchen"
-deployment <Name> spec template: {
- metadata annotations "prometheus.io.scrape": "true"
- spec containers: [{
+deployment: <Name>: spec: template: {
+ metadata: annotations: "prometheus.io.scrape": "true"
+ spec: containers: [{
ports: [{
containerPort: 8080
}]
@@ -19,18 +19,18 @@
}]
}
-deployment <ID> spec template spec: {
+deployment: <ID>: spec: template: spec: {
hasDisks :: *true | bool
// field comprehension using just "if"
if hasDisks {
volumes: [{
name: *"\(ID)-disk" | string
- gcePersistentDisk pdName: *"\(ID)-disk" | string
- gcePersistentDisk fsType: "ext4"
+ gcePersistentDisk: pdName: *"\(ID)-disk" | string
+ gcePersistentDisk: fsType: "ext4"
}, {
name: *"secret-\(ID)" | string
- secret secretName: *"\(ID)-secrets" | string
+ secret: secretName: *"\(ID)-secrets" | string
}, ...]
containers: [{
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/linecook/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/linecook/kube.cue
index fbe3a2e..179b993 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/linecook/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/linecook/kube.cue
@@ -1,10 +1,10 @@
package kube
-deployment linecook spec template spec: {
+deployment: linecook: spec: template: spec: {
volumes: [{
}, {
name: "secret-kitchen"
- secret secretName: "secrets"
+ secret: secretName: "secrets"
}]
containers: [{
image: "gcr.io/myproj/linecook:v0.1.42"
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/pastrychef/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/pastrychef/kube.cue
index f8ac1a4..3810eda 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/pastrychef/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/pastrychef/kube.cue
@@ -1,10 +1,10 @@
package kube
-deployment pastrychef spec template spec: {
+deployment: pastrychef: spec: template: spec: {
volumes: [{
}, {
name: "secret-ssh-key"
- secret secretName: "secrets"
+ secret: secretName: "secrets"
}]
containers: [{
image: "gcr.io/myproj/pastrychef:v0.1.15"
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/souschef/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/souschef/kube.cue
index 82e6533..11d9a94 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/souschef/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/souschef/kube.cue
@@ -1,9 +1,7 @@
package kube
-deployment souschef spec template spec containers: [{
+deployment: souschef: spec: template: spec: containers: [{
image: "gcr.io/myproj/souschef:v0.5.3"
}]
-deployment souschef spec template spec: {
- hasDisks :: false
-}
+deployment : souschef : spec : template : spec : hasDisks :: false
diff --git a/doc/tutorial/kubernetes/quick/services/kube.cue b/doc/tutorial/kubernetes/quick/services/kube.cue
index 90c0e93..40aa035 100644
--- a/doc/tutorial/kubernetes/quick/services/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kube.cue
@@ -1,6 +1,6 @@
package kube
-service <ID>: {
+service: <ID>: {
apiVersion: "v1"
kind: "Service"
metadata: {
@@ -22,79 +22,79 @@
}
}
-deployment <ID>: {
+deployment: <ID>: {
apiVersion: "extensions/v1beta1"
kind: "Deployment"
- metadata name: ID
+ metadata: name: ID
spec: {
// 1 is the default, but we allow any number
replicas: *1 | int
template: {
- metadata labels: {
+ metadata: labels: {
app: ID
domain: "prod"
component: Component
}
// we always have one namesake container
- spec containers: [{name: ID}]
+ spec: containers: [{name: ID}]
}
}
}
Component :: string
-daemonSet <ID>: _spec & {
+daemonSet: <ID>: _spec & {
apiVersion: "extensions/v1beta1"
kind: "DaemonSet"
Name :: ID
}
-statefulSet <ID>: _spec & {
+statefulSet: <ID>: _spec & {
apiVersion: "apps/v1beta1"
kind: "StatefulSet"
Name :: ID
}
-deployment <ID>: _spec & {
+deployment: <ID>: _spec & {
apiVersion: "extensions/v1beta1"
kind: "Deployment"
Name :: ID
- spec replicas: *1 | int
+ spec: replicas: *1 | int
}
-configMap <ID>: {
- metadata name: ID
- metadata labels component: Component
+configMap: <ID>: {
+ metadata: name: ID
+ metadata: labels: component: Component
}
_spec: {
Name :: string
- metadata name: Name
- metadata labels component: Component
- spec template: {
- metadata labels: {
+ metadata: name: Name
+ metadata: labels: component: Component
+ spec: template: {
+ metadata: labels: {
app: Name
component: Component
domain: "prod"
}
- spec containers: [{name: Name}]
+ spec: containers: [{name: Name}]
}
}
// Define the _export option and set the default to true
// for all ports defined in all containers.
-_spec spec template spec containers: [...{
+_spec: spec: template: spec: containers: [...{
ports: [...{
_export: *true | false // include the port in the service
}]
}]
for x in [deployment, daemonSet, statefulSet] for k, v in x {
- service "\(k)": {
- spec selector: v.spec.template.metadata.labels
+ service: "\(k)": {
+ spec: selector: v.spec.template.metadata.labels
- spec ports: [ {
+ spec: ports: [ {
Port = p.containerPort // Port is an alias
port: *Port | int
targetPort: *Port | int
diff --git a/doc/tutorial/kubernetes/quick/services/mon/alertmanager/configmap.cue b/doc/tutorial/kubernetes/quick/services/mon/alertmanager/configmap.cue
index e641eed..ad04bc9 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/alertmanager/configmap.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/alertmanager/configmap.cue
@@ -2,7 +2,7 @@
import yaml656e63 "encoding/yaml"
-configMap alertmanager: {
+configMap: alertmanager: {
apiVersion: "v1"
kind: "ConfigMap"
data: {
diff --git a/doc/tutorial/kubernetes/quick/services/mon/alertmanager/kube.cue b/doc/tutorial/kubernetes/quick/services/mon/alertmanager/kube.cue
index 76d2a8f..3af8c40 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/alertmanager/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/alertmanager/kube.cue
@@ -1,12 +1,12 @@
package kube
-service alertmanager: {
+service: alertmanager: {
metadata: {
annotations: {
"prometheus.io/scrape": "true"
"prometheus.io/path": "/metrics"
}
- labels name: "alertmanager"
+ labels: name: "alertmanager"
}
spec: {
// type: ClusterIP
@@ -15,10 +15,10 @@
}]
}
}
-deployment alertmanager spec: {
- selector matchLabels app: "alertmanager"
+deployment: alertmanager: spec: {
+ selector: matchLabels: app: "alertmanager"
template: {
- metadata name: "alertmanager"
+ metadata: name: "alertmanager"
spec: {
containers: [{
image: "prom/alertmanager:v0.15.2"
@@ -41,7 +41,7 @@
}]
volumes: [{
name: "config-volume"
- configMap name: "alertmanager"
+ configMap: name: "alertmanager"
}, {
name: "alertmanager"
emptyDir: {}
diff --git a/doc/tutorial/kubernetes/quick/services/mon/grafana/kube.cue b/doc/tutorial/kubernetes/quick/services/mon/grafana/kube.cue
index 6efff35..dd8463c 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/grafana/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/grafana/kube.cue
@@ -1,8 +1,8 @@
package kube
-deployment grafana: {
- metadata labels app: "grafana"
- spec template spec: {
+deployment: grafana: {
+ metadata: labels: app: "grafana"
+ spec: template: spec: {
volumes: [{
name: "grafana-volume"
gcePersistentDisk: {
@@ -49,7 +49,7 @@
}]
}
}
-service grafana spec ports: [{
+service: grafana: spec: ports: [{
name: "grafana"
port: 3000
targetPort: 3000
diff --git a/doc/tutorial/kubernetes/quick/services/mon/nodeexporter/kube.cue b/doc/tutorial/kubernetes/quick/services/mon/nodeexporter/kube.cue
index 8c46401..4ac3b8c 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/nodeexporter/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/nodeexporter/kube.cue
@@ -1,7 +1,7 @@
package kube
-service "node-exporter": {
- metadata annotations "prometheus.io/scrape": "true"
+service: "node-exporter": {
+ metadata: annotations: "prometheus.io/scrape": "true"
spec: {
type: "ClusterIP"
clusterIP: "None"
@@ -10,8 +10,8 @@
}]
}
}
-daemonSet "node-exporter" spec template: {
- metadata name: "node-exporter"
+daemonSet: "node-exporter": spec: template: {
+ metadata: name: "node-exporter"
spec: {
hostNetwork: true
hostPID: true
@@ -48,10 +48,10 @@
}]
volumes: [{
name: "proc"
- hostPath path: "/proc"
+ hostPath: path: "/proc"
}, {
name: "sys"
- hostPath path: "/sys"
+ hostPath: path: "/sys"
}]
}
}
diff --git a/doc/tutorial/kubernetes/quick/services/mon/prometheus/configmap.cue b/doc/tutorial/kubernetes/quick/services/mon/prometheus/configmap.cue
index c73acf7..7c58f18 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/prometheus/configmap.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/prometheus/configmap.cue
@@ -2,7 +2,7 @@
import yaml656e63 "encoding/yaml"
-configMap prometheus: {
+configMap: prometheus: {
apiVersion: "v1"
kind: "ConfigMap"
data: {
@@ -14,7 +14,7 @@
alert: "InstanceDown"
expr: "up == 0"
for: "30s"
- labels severity: "page"
+ labels: severity: "page"
annotations: {
description: "{{$labels.app}} of job {{ $labels.job }} has been down for more than 30 seconds."
@@ -24,7 +24,7 @@
alert: "InsufficientPeers"
expr: "count(up{job=\"etcd\"} == 0) > (count(up{job=\"etcd\"}) / 2 - 1)"
for: "3m"
- labels severity: "page"
+ labels: severity: "page"
annotations: {
description: "If one more etcd peer goes down the cluster will be unavailable"
summary: "etcd cluster small"
@@ -33,13 +33,13 @@
alert: "EtcdNoMaster"
expr: "sum(etcd_server_has_leader{app=\"etcd\"}) == 0"
for: "1s"
- labels severity: "page"
- annotations summary: "No ETCD master elected."
+ labels: severity: "page"
+ annotations: summary: "No ETCD master elected."
}, {
alert: "PodRestart"
expr: "(max_over_time(pod_container_status_restarts_total[5m]) - min_over_time(pod_container_status_restarts_total[5m])) > 2"
for: "1m"
- labels severity: "page"
+ labels: severity: "page"
annotations: {
description: "{{$labels.app}} {{ $labels.container }} resturted {{ $value }} times in 5m."
summary: "Pod for {{$labels.container}} restarts too often"
@@ -50,11 +50,11 @@
"prometheus.yml": yaml656e63.Marshal(_cue_prometheus_yml)
_cue_prometheus_yml = {
- global scrape_interval: "15s"
+ global: scrape_interval: "15s"
rule_files: [
"/etc/prometheus/alert.rules",
]
- alerting alertmanagers: [{
+ alerting: alertmanagers: [{
scheme: "http"
static_configs: [{
targets: [
@@ -79,7 +79,7 @@
// Prometheus. The discovery auth config is automatic if Prometheus runs inside
// the cluster. Otherwise, more config options have to be provided within the
// <kubernetes_sd_config>.
- tls_config ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
+ tls_config: ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
// If your node certificates are self-signed or use a different CA to the
// master CA, then disable certificate verification below. Note that
// certificate verification is an integral part of a secure infrastructure
@@ -116,7 +116,7 @@
// Prometheus. The discovery auth config is automatic if Prometheus runs inside
// the cluster. Otherwise, more config options have to be provided within the
// <kubernetes_sd_config>.
- tls_config ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
+ tls_config: ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
kubernetes_sd_configs: [{
@@ -162,7 +162,7 @@
// Prometheus. The discovery auth config is automatic if Prometheus runs inside
// the cluster. Otherwise, more config options have to be provided within the
// <kubernetes_sd_config>.
- tls_config ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
+ tls_config: ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
kubernetes_sd_configs: [{
@@ -241,7 +241,7 @@
job_name: "kubernetes-services"
metrics_path: "/probe"
- params module: ["http_2xx"]
+ params: module: ["http_2xx"]
kubernetes_sd_configs: [{
role: "service"
@@ -280,7 +280,7 @@
job_name: "kubernetes-ingresses"
metrics_path: "/probe"
- params module: ["http_2xx"]
+ params: module: ["http_2xx"]
kubernetes_sd_configs: [{
role: "ingress"
diff --git a/doc/tutorial/kubernetes/quick/services/mon/prometheus/kube.cue b/doc/tutorial/kubernetes/quick/services/mon/prometheus/kube.cue
index c24e39c..096a89d 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/prometheus/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/prometheus/kube.cue
@@ -1,9 +1,9 @@
package kube
-service prometheus: {
+service: prometheus: {
metadata: {
- annotations "prometheus.io/scrape": "true"
- labels name: "prometheus"
+ annotations: "prometheus.io/scrape": "true"
+ labels: name: "prometheus"
}
spec: {
type: "NodePort"
@@ -13,7 +13,7 @@
}]
}
}
-deployment prometheus spec: {
+deployment: prometheus: spec: {
strategy: {
rollingUpdate: {
maxSurge: 0
@@ -21,11 +21,11 @@
}
type: "RollingUpdate"
}
- selector matchLabels app: "prometheus"
+ selector: matchLabels: app: "prometheus"
template: {
metadata: {
name: "prometheus"
- annotations "prometheus.io.scrape": "true"
+ annotations: "prometheus.io.scrape": "true"
}
spec: {
containers: [{
@@ -45,7 +45,7 @@
}]
volumes: [{
name: "config-volume"
- configMap name: "prometheus"
+ configMap: name: "prometheus"
}]
}
}
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/authproxy/configmap.cue b/doc/tutorial/kubernetes/quick/services/proxy/authproxy/configmap.cue
index c38c6e3..f105c88 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/authproxy/configmap.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/authproxy/configmap.cue
@@ -1,6 +1,6 @@
package kube
-configMap authproxy: {
+configMap: authproxy: {
// To update run:
// kubectl apply -f configmap.yaml
// kubectl scale --replicas=0 deployment/proxy
@@ -8,7 +8,7 @@
apiVersion: "v1"
kind: "ConfigMap"
- data "authproxy.cfg": """
+ data: "authproxy.cfg": """
# Google Auth Proxy Config File
## https://github.com/bitly/google_auth_proxy
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/authproxy/kube.cue b/doc/tutorial/kubernetes/quick/services/proxy/authproxy/kube.cue
index 487f005..7f2556c 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/authproxy/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/authproxy/kube.cue
@@ -1,9 +1,9 @@
package kube
-deployment authproxy spec: {
+deployment: authproxy: spec: {
// podTemplate defines the 'cookie cutter' used for creating
// new pods when necessary
- template spec: {
+ template: spec: {
containers: [{
image: "skippy/oauth2_proxy:2.0.1"
ports: [{
@@ -20,7 +20,7 @@
}]
volumes: [{
name: "config-volume"
- configMap name: "authproxy"
+ configMap: name: "authproxy"
}]
}
}
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/goget/kube.cue b/doc/tutorial/kubernetes/quick/services/proxy/goget/kube.cue
index 33bc990..bdbbdcc 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/goget/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/goget/kube.cue
@@ -1,12 +1,12 @@
package kube
-deployment goget spec: {
+deployment: goget: spec: {
// podTemplate defines the 'cookie cutter' used for creating
// new pods when necessary
- template spec: {
+ template: spec: {
volumes: [{
name: "secret-volume"
- secret secretName: "goget-secrets"
+ secret: secretName: "goget-secrets"
}]
containers: [{
image: "gcr.io/myproj/goget:v0.5.1"
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/goget/service.cue b/doc/tutorial/kubernetes/quick/services/proxy/goget/service.cue
index 15465d2..70529cf 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/goget/service.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/goget/service.cue
@@ -1,6 +1,6 @@
package kube
-service goget spec: {
+service: goget: spec: {
type: "LoadBalancer"
loadBalancerIP: "1.3.5.7" // static ip
ports: [{
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/nginx/configmap.cue b/doc/tutorial/kubernetes/quick/services/proxy/nginx/configmap.cue
index a35ec2b..661ec92 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/nginx/configmap.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/nginx/configmap.cue
@@ -1,9 +1,9 @@
package kube
-configMap nginx: {
+configMap: nginx: {
apiVersion: "v1"
kind: "ConfigMap"
- data "nginx.conf": """
+ data: "nginx.conf": """
events {
worker_connections 768;
}
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/nginx/kube.cue b/doc/tutorial/kubernetes/quick/services/proxy/nginx/kube.cue
index 3486fef..fd1a1f6 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/nginx/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/nginx/kube.cue
@@ -1,15 +1,15 @@
package kube
-deployment nginx spec: {
+deployment: nginx: spec: {
// podTemplate defines the 'cookie cutter' used for creating
// new pods when necessary
- template spec: {
+ template: spec: {
volumes: [{
name: "secret-volume"
- secret secretName: "proxy-secrets"
+ secret: secretName: "proxy-secrets"
}, {
name: "config-volume"
- configMap name: "nginx"
+ configMap: name: "nginx"
}]
containers: [{
image: "nginx:1.11.10-alpine"
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/nginx/service.cue b/doc/tutorial/kubernetes/quick/services/proxy/nginx/service.cue
index 7c715e5..b310cb9 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/nginx/service.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/nginx/service.cue
@@ -1,6 +1,6 @@
package kube
-service nginx spec: {
+service: nginx: spec: {
type: "LoadBalancer"
loadBalancerIP: "1.3.4.5"
ports: [{
diff --git a/encoding/protobuf/testdata/client_config.proto.out.cue b/encoding/protobuf/testdata/client_config.proto.out.cue
index 3f9cb25..b9c5c3a 100644
--- a/encoding/protobuf/testdata/client_config.proto.out.cue
+++ b/encoding/protobuf/testdata/client_config.proto.out.cue
@@ -47,7 +47,7 @@
// service.
"FAIL_OPEN"
-NetworkFailPolicy_FailPolicy_value FAIL_OPEN: 0
+NetworkFailPolicy_FailPolicy_value: FAIL_OPEN: 0
// Defines the per-service client configuration.
ServiceConfig: {
diff --git a/encoding/protobuf/testdata/gateway.proto.out.cue b/encoding/protobuf/testdata/gateway.proto.out.cue
index f3503d2..1a7ed21 100644
--- a/encoding/protobuf/testdata/gateway.proto.out.cue
+++ b/encoding/protobuf/testdata/gateway.proto.out.cue
@@ -216,7 +216,7 @@
selector?: {
<_>: string
} @protobuf(2,type=map<string,string>)
- selector? <name>: name
+ selector?: <name>: name
}
// `Server` describes the properties of the proxy on a given load balancer
diff --git a/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/client_config_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/client_config_proto_gen.cue
index 1397a5a..4762234 100644
--- a/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/client_config_proto_gen.cue
+++ b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/client_config_proto_gen.cue
@@ -46,7 +46,7 @@
// service.
"FAIL_OPEN"
-NetworkFailPolicy_FailPolicy_value "FAIL_OPEN": 0
+NetworkFailPolicy_FailPolicy_value: "FAIL_OPEN": 0
// Defines the per-service client configuration.
ServiceConfig: {