cue: close struct only after referencing

closeIfStruct type is used to communicate closedness
to children.

Change-Id: I3e27ce1bd246e0db2486428e483badea547e7eda
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3767
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/ast_test.go b/cue/ast_test.go
index 83e3b7d..09e9358 100644
--- a/cue/ast_test.go
+++ b/cue/ast_test.go
@@ -291,6 +291,25 @@
 		out: `<0>{` +
 			`a: (<1>{d: <2>{info :: <3>{...}, Y: <2>.info.X}, <0>.base} & <4>{<>: <5>(Name: string)-><6>{info :: <7>C{X: "foo"}}, }), ` +
 			`base :: <8>C{info :: <9>{...}}}`,
+	}, {
+		in: `
+		def :: {
+			Type: string
+			Text: string
+			Size: int
+		}
+
+		def :: {
+			Type: "B"
+			Size: 0
+		} | {
+			Type: "A"
+			Size: 1
+		}
+		`,
+		out: `<0>{` +
+			`def :: (<1>C{Size: int, Type: string, Text: string} & (<2>C{Size: 0, Type: "B"} | <3>C{Size: 1, Type: "A"}))` +
+			`}`,
 	}}
 	for _, tc := range testCases {
 		t.Run("", func(t *testing.T) {
diff --git a/cue/binop.go b/cue/binop.go
index 152b8ac..5a3ca19 100644
--- a/cue/binop.go
+++ b/cue/binop.go
@@ -590,7 +590,7 @@
 	return nil
 }
 
-func evalLambda(ctx *context, a value) (l *lambdaExpr, err evaluated) {
+func evalLambda(ctx *context, a value, finalize bool) (l *lambdaExpr, err evaluated) {
 	if a == nil {
 		return nil, nil
 	}
@@ -603,7 +603,11 @@
 	if !ok {
 		return nil, ctx.mkErr(a, "value must be lambda")
 	}
-	return ctx.deref(l).(*lambdaExpr), nil
+	lambda := ctx.deref(l).(*lambdaExpr)
+	if finalize {
+		lambda.value = wrapFinalize(lambda.value)
+	}
+	return lambda, nil
 }
 
 func (x *structLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
@@ -632,8 +636,8 @@
 	}
 	defer ctx.pushForwards(x, obj, y, obj).popForwards()
 
-	tx, ex := evalLambda(ctx, x.template)
-	ty, ey := evalLambda(ctx, y.template)
+	tx, ex := evalLambda(ctx, x.template, x.closeStatus.shouldFinalize())
+	ty, ey := evalLambda(ctx, y.template, y.closeStatus.shouldFinalize())
 
 	var t *lambdaExpr
 	switch {
@@ -699,7 +703,14 @@
 					return ctx.mkErr(src, "field %q declared as definition and regular field",
 						ctx.labelStr(a.feature))
 				}
-				v = mkBin(ctx, src.Pos(), op, b.v, v)
+				w := b.v
+				if x.closeStatus.shouldFinalize() {
+					w = wrapFinalize(w)
+				}
+				if y.closeStatus.shouldFinalize() {
+					v = wrapFinalize(v)
+				}
+				v = mkBin(ctx, src.Pos(), op, w, v)
 				obj.arcs[i].v = v
 				obj.arcs[i].cache = nil
 				obj.arcs[i].optional = a.optional && b.optional
@@ -725,7 +736,7 @@
 	sort.Stable(obj)
 
 	if unchecked && obj.template != nil {
-		obj.closeStatus = 0
+		obj.closeStatus.unclose()
 	}
 
 	return obj
diff --git a/cue/debug.go b/cue/debug.go
index ca3e970..1eb5bff 100644
--- a/cue/debug.go
+++ b/cue/debug.go
@@ -263,7 +263,18 @@
 		write("(")
 		p.str(x.params.arcs)
 		write(")->")
+		v := x.value
+		// strip one layer of closeIf wrapper. Evaluation may cause one
+		// layer to have not yet been evaluated. This is fine.
+		if w, ok := v.(*closeIfStruct); ok {
+			v = w.value
+		}
+		p.str(v)
+
+	case *closeIfStruct:
+		write("close(")
 		p.str(x.value)
+		write(")")
 
 	case *structLit:
 		if x == nil {
@@ -273,7 +284,7 @@
 		if p.showNodeRef {
 			p.writef("<%s>", p.ctx.ref(x))
 		}
-		if x.closeStatus != 0 {
+		if x.closeStatus.shouldClose() {
 			write("C")
 		}
 		write("{")
@@ -301,7 +312,7 @@
 				p.write(", ")
 			}
 		}
-		if topDefault && x.closeStatus == 0 {
+		if topDefault && !x.closeStatus.shouldClose() {
 			if len(x.arcs) > 0 {
 				p.write(", ")
 			}
diff --git a/cue/eval.go b/cue/eval.go
index 04a9c77..5950ef9 100644
--- a/cue/eval.go
+++ b/cue/eval.go
@@ -319,6 +319,12 @@
 	return st
 }
 
+func (x *closeIfStruct) evalPartial(ctx *context) evaluated {
+	v := x.value.evalPartial(ctx)
+	updateCloseStatus(v)
+	return v
+}
+
 func (x *structLit) evalPartial(ctx *context) (result evaluated) {
 	if ctx.trace {
 		defer uni(indent(ctx, "struct eval", x))
diff --git a/cue/export.go b/cue/export.go
index 86376c1..656b8ff 100644
--- a/cue/export.go
+++ b/cue/export.go
@@ -211,10 +211,14 @@
 	return false
 }
 
+func (p *exporter) showOptional() bool {
+	return !p.mode.omitOptional && !p.mode.concrete
+}
+
 func (p *exporter) closeOrOpen(s *ast.StructLit, isClosed bool) ast.Expr {
 	// Note, there is no point in printing close if we are dropping optional
 	// fields, as by this the meaning of close will change anyway.
-	if p.mode.omitOptional || p.mode.concrete {
+	if !p.showOptional() {
 		return s
 	}
 	if isClosed && !p.inDef {
@@ -236,6 +240,18 @@
 		return !all
 	case *bottom:
 		return !isIncomplete(x)
+	case *closeIfStruct:
+		return p.isComplete(x.value, all)
+	}
+	return false
+}
+
+func isDisjunction(v value) bool {
+	switch x := v.(type) {
+	case *disjunction:
+		return true
+	case *closeIfStruct:
+		return isDisjunction(x.value)
 	}
 	return false
 }
@@ -247,7 +263,7 @@
 		// This likely requires disjunctions to keep track of original
 		// values (so using arcs instead of values).
 		p := &exporter{p.ctx, options{concrete: true, raw: true}, p.stack, p.top, p.imports, p.inDef}
-		if _, ok := v.(*disjunction); ok || isBottom(e) {
+		if isDisjunction(v) || isBottom(e) {
 			return p.expr(v)
 		}
 		return p.expr(e)
@@ -255,6 +271,10 @@
 	return p.expr(e)
 }
 
+func (p *exporter) isClosed(x *structLit) bool {
+	return x.closeStatus.shouldClose()
+}
+
 func (p *exporter) expr(v value) ast.Expr {
 	// TODO: use the raw expression for convert incomplete errors downstream
 	// as well.
@@ -421,19 +441,30 @@
 		}
 		return bin
 
+	case *closeIfStruct:
+		return p.expr(x.value)
+
 	case *structLit:
-		st, err := p.structure(x, !x.isClosed())
+		st, err := p.structure(x, !p.isClosed(x))
 		if err != nil {
 			return p.expr(err)
 		}
-		expr := p.closeOrOpen(st, x.isClosed())
+		expr := p.closeOrOpen(st, p.isClosed(x))
 		switch {
-		case x.isClosed() && x.template != nil:
+		// If a template is non-nil, we only show it if printing of
+		// optional fields is requested. If a struct is not closed it was
+		// already generated before. Furthermore, if if we are in evaluation
+		// mode, the struct is already unified, so there is no need to print it.
+		case x.template != nil && p.showOptional() && p.isClosed(x) && !doEval(p.mode):
 			l, ok := x.template.evalPartial(p.ctx).(*lambdaExpr)
 			if !ok {
 				break
 			}
-			if _, ok := l.value.(*top); ok {
+			v := l.value
+			if c, ok := v.(*closeIfStruct); ok {
+				v = c.value
+			}
+			if _, ok := v.(*top); ok {
 				break
 			}
 			expr = &ast.BinaryExpr{X: expr, Op: token.AND, Y: &ast.StructLit{
@@ -629,10 +660,10 @@
 		obj.Elts = append(obj.Elts, &ast.EmbedDecl{Expr: p.expr(x.emit)})
 	}
 	switch {
-	case !doEval(p.mode) && x.template != nil && addTempl:
+	case x.template != nil && p.showOptional() && addTempl:
 		l, ok := x.template.evalPartial(p.ctx).(*lambdaExpr)
 		if ok {
-			if _, ok := l.value.(*top); ok && !x.isClosed() {
+			if _, ok := l.value.(*top); ok && !p.isClosed(x) {
 				break
 			}
 			obj.Elts = append(obj.Elts, &ast.Field{
@@ -735,7 +766,7 @@
 			break
 		}
 		s.Elts = append(s.Elts, st.Elts...)
-		return x.isClosed()
+		return p.isClosed(x)
 
 	case *binaryExpr:
 		if x.op != opUnifyUnchecked {
diff --git a/cue/export_test.go b/cue/export_test.go
index 507b345..eed802c 100644
--- a/cue/export_test.go
+++ b/cue/export_test.go
@@ -294,8 +294,9 @@
 			a b: 3
 		}`),
 	}, {
-		raw:  true,
-		eval: true,
+		raw:   true,
+		eval:  true,
+		noOpt: true,
 		in: `{
 			job <Name>: {
 				name:     Name
@@ -381,6 +382,10 @@
 					sub: reg
 				}
 				val: def
+				def2 :: {
+					a: { b: int }
+				}
+				val2: def2
 			}`,
 		out: unindent(`
 		{
@@ -402,6 +407,10 @@
 					bar baz: 3
 				}
 			}
+			def2 :: {
+				a b: int
+			}
+			val2 a b: int
 		}`),
 	}, {
 		raw:  true,
@@ -476,8 +485,9 @@
 				}
 				a: []
 			}`)}, {
-		raw:  true,
-		eval: true,
+		raw:   true,
+		eval:  true,
+		noOpt: true,
 		in: `{
 				And :: {
 					"Fn::And": [...(3 | And)]
@@ -494,8 +504,9 @@
 				Ands "Fn::And": [3 | And]
 			}`),
 	}, {
-		raw:  true,
-		eval: true,
+		raw:   true,
+		eval:  true,
+		noOpt: true,
 		in: `{
 			Foo :: {
 				sgl: Bar
@@ -557,7 +568,7 @@
 			n := root.(*structLit).arcs[0].v
 			v := newValueRoot(ctx, n)
 
-			opts := options{raw: !tc.eval, omitOptional: true}
+			opts := options{raw: !tc.eval, omitOptional: tc.noOpt}
 			node, _ := export(ctx, v.eval(ctx), opts)
 			b, err := format.Node(node, format.Simplify())
 			if err != nil {
@@ -574,6 +585,7 @@
 	testCases := []struct {
 		eval    bool // evaluate the full export
 		in, out string
+		opts    []Option
 	}{{
 		in: `
 		import "strings"
@@ -713,13 +725,9 @@
 			}
 			a: close({
 				b: <10
-			}) & {
-				<_>: <10
-			}
+			})
 			B :: {
 				b: <10
-			} & {
-				<_>: <10
 			}
 		}`),
 	}, {
@@ -758,6 +766,98 @@
 				}
 			})
 		}`),
+	}, {
+		eval: true,
+		in: `
+			T :: {
+				<_>: int64
+			}
+			X :: {
+				x: int
+			} & T
+			x: X
+			`,
+		out: unindent(`
+		{
+			T :: {
+				<_>: int64
+			}
+			X :: {
+				x: int64
+			}
+			x: close({
+				x: int64
+			})
+		}`),
+	}, {
+		eval: true,
+		opts: []Option{Optional(false)},
+		in: `
+		T :: {
+			<_>: int64
+		}
+		X :: {
+			x: int
+		} & T
+		x: X
+		`,
+		out: unindent(`
+		{
+			T :: {
+			}
+			X :: {
+				x: int64
+			}
+			x x: int64
+		}`),
+	}, {
+		eval: true,
+		in: `{
+				reg: { foo: 1, bar: { baz: 3 } }
+				def :: {
+					a: 1
+	
+					sub: reg
+				}
+				val: def
+				def2 :: {
+					a: { b: int }
+				}
+				val2: def2
+			}`,
+		out: unindent(`
+			{
+				reg: {
+					foo: 1
+					bar baz: 3
+				}
+				def :: {
+					a: 1
+					sub: {
+						foo: 1
+						bar: {
+							baz: 3
+							...
+						}
+						...
+					}
+				}
+				val: close({
+					a: 1
+					sub: {
+						foo: 1
+						bar baz: 3
+					}
+				})
+				def2 :: {
+					a b: int
+				}
+				val2: close({
+					a: close({
+						b: int
+					})
+				})
+			}`),
 	}}
 	for _, tc := range testCases {
 		t.Run("", func(t *testing.T) {
@@ -766,7 +866,7 @@
 			if err != nil {
 				t.Fatal(err)
 			}
-			opts := []Option{}
+			opts := tc.opts
 			if !tc.eval {
 				opts = []Option{Raw()}
 			}
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index 9582f78..689a75b 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -1228,14 +1228,55 @@
 					`,
 		out: `<0>{` +
 			`D1 :: <1>C{env: <2>C{a: "A", b: "B"}, def :: <3>C{a: "A", b: "B"}}, ` +
-			`d1: <4>C{env: <5>C{a: "A", b: "B", c: "C"}, def :: <6>C{a: "A", b: "B"}}, ` +
-			`D2 :: <7>C{a: int, b: int}, ` +
-			`D3 :: <8>C{env: <9>C{a: "A", b: "B"}}, ` +
-			`D4 :: <10>C{env: _|_(int:field "b" not allowed in closed struct)}, ` +
-			`DC :: <11>C{a: int}` +
+			`d1: <4>C{env: _|_("C":field "c" not allowed in closed struct), def :: <5>C{a: "A", b: "B"}}, ` +
+			`D2 :: <6>C{a: int, b: int}, ` +
+			`D3 :: <7>C{env: <8>C{a: "A", b: "B"}}, ` +
+			`D4 :: <9>C{env: _|_(int:field "b" not allowed in closed struct)}, ` +
+			`DC :: <10>C{a: int}` +
 			`}`,
 	}, {
-		desc: "definitions with oneofs",
+		desc: "recursive closing starting at non-definition",
+		in: `
+			z a: {
+				B:: {
+					c d: 1
+					c f: 1
+				}
+			}
+			A: z & { a: { B :: { c e: 2 } } }
+			`,
+		out: `<0>{z: <1>{a: <2>{B :: <3>C{c: <4>C{d: 1, f: 1}}}}, A: <5>{a: <6>{B :: <7>C{c: _|_(2:field "e" not allowed in closed struct)}}}}`,
+	}, {
+		desc: "non-closed definition carries over closedness to enclosed template",
+		in: `
+		S :: {
+			<_>: { a: int }
+		}
+		a: S & {
+			v: { b: int }
+		}
+		Q :: {
+			<_>: { a: int } | { b: int }
+		}
+		b: Q & {
+			w: { c: int }
+		}
+		R :: {
+			<_>: [{ a: int }, { b: int }]
+		}
+		c: R & {
+			w: [{ d: int }, ...]
+		}
+		`,
+		out: `<0>{` +
+			`S :: <1>{<>: <2>(_: string)-><3>C{a: int}, }, ` +
+			`a: <4>{<>: <5>(_: string)-><6>C{a: int}, v: _|_(<7>{<>: <5>(_: string)-><6>C{a: int}, v: <8>{b: int}}:field "b" not allowed in closed struct)}, ` +
+			`b: <9>{<>: <10>(_: string)->(<11>C{a: int} | <12>C{b: int}), w: _|_(<13>{<>: <10>(_: string)->(<11>C{a: int} | <12>C{b: int}), w: <14>{c: int}}:empty disjunction: field "c" not allowed in closed struct)}, ` +
+			`Q :: <15>{<>: <16>(_: string)->(<17>C{a: int} | <18>C{b: int}), }, ` +
+			`c: <19>{<>: <20>(_: string)->[<21>C{a: int},<22>C{b: int}], w: [_|_((<23>{d: int} & close(<24>C{a: int})):field "d" not allowed in closed struct),<25>C{b: int}]}, ` +
+			`R :: <26>{<>: <27>(_: string)->[<28>C{a: int},<29>C{b: int}], }}`,
+	}, {
+		desc: "definitions with disjunctions",
 		in: `
 			Foo :: {
 				field: int
@@ -1245,7 +1286,7 @@
 			}
 
 			foo: Foo
-			foo: { a: 2 }
+			foo: { a: 1 }
 
 			bar: Foo
 			bar: { c: 2 }
@@ -1255,10 +1296,26 @@
 			`,
 		out: `<0>{` +
 			`Foo :: (<1>C{field: int, a: 1} | <2>C{field: int, b: 2}), ` +
-			`foo: _|_((<3>.Foo & <4>{a: 2}):empty disjunction: C{field: int, a: (1 & 2)}), ` +
-			`bar: _|_((<3>.Foo & <5>{c: 2}):empty disjunction: field "c" not allowed in closed struct), ` +
+			`foo: <3>C{field: int, a: 1}, ` +
+			`bar: _|_((<4>.Foo & <5>{c: 2}):empty disjunction: field "c" not allowed in closed struct), ` +
 			`baz: <6>C{field: int, b: 2}}`,
 	}, {
+		desc: "definitions with disjunctions recurisive",
+		in: `
+			Foo :: {
+				x: {
+					field: int
+
+					{ a: 1 } |
+					{ b: 2 }
+				}
+				x c: 3
+			}
+					`,
+		out: `<0>{` +
+			`Foo :: <1>C{x: (<2>C{field: int, a: 1, c: 3} | <3>C{field: int, b: 2, c: 3})}` +
+			`}`,
+	}, {
 		desc: "definitions with embedding",
 		in: `
 		E :: {
@@ -1282,6 +1339,26 @@
 			`e1 :: <5>C{a: _|_(4:field "d" not allowed in closed struct), b: 3}, ` +
 			`v1 :: <6>C{a: <7>C{b: int, c: 4}, b: 3}}`,
 	}, {
+		desc: "top-level definition with struct and disjunction",
+		in: `
+		def :: {
+			Type: string
+			Text: string
+			Size: int
+		}
+
+		def :: {
+			Type: "B"
+			Size: 0
+		} | {
+			Type: "A"
+			Size: 1
+		}`,
+		out: `<0>{` +
+			`def :: (<1>C{Size: (0 & int), Type: ("B" & string), Text: string} | ` +
+			`<2>C{Size: (1 & int), Type: ("A" & string), Text: string})` +
+			`}`,
+	}, {
 		desc: "closing structs",
 		in: `
 		op: {x: int}             // {x: int}
@@ -1376,7 +1453,6 @@
 		in: `
 		A :: {f1: int, f2: int}
 
-		// Comprehension fields cannot be added like any other.
 		for k, v in {f3 : int} {
 			a: A & { "\(k)": v }
 		}
@@ -1409,6 +1485,25 @@
 			`D :: <5>{f1: int, ...}` +
 			`}`,
 	}, {
+		desc: "incomplete comprehensions",
+		in: `
+		A: {
+			for v in src {
+				"\(v)": v
+			}
+			src: _
+			if true {
+				baz: "baz"
+			}
+		}
+		B: A & {
+			src: ["foo", "bar"]
+		}
+		`,
+		out: `<0>{` +
+			`A: <1>{src: _, baz: "baz" <2>for _, v in <3>.src yield <4>{""+<2>.v+"": <2>.v}}, ` +
+			`B: <5>{src: ["foo","bar"], baz: "baz", foo: "foo", bar: "bar"}}`,
+	}, {
 		desc: "reference to root",
 		in: `
 			a: { b: int }
@@ -1996,7 +2091,9 @@
 				}
 			}
 		`,
-		out: `<0>{b: true, a: "foo", c: <1>{a: 3}, d: <2>{a: int if (<2>.a > 1) yield <3>{a: 3}}}`,
+		// NOTE: the node numbers are not correct here, but this is an artifact
+		// of the testing code.
+		out: `<0>{b: true, a: "foo", c: <1>{a: 3}, d: <2>{a: int if (<3>.a > 1) yield <4>{a: 3}}}`,
 	}, {
 		desc: "referencing field in field comprehension",
 		in: `
@@ -2287,7 +2384,9 @@
 			`fibRec: <1>{` +
 			`nn: int, ` +
 			`out: (<2>.fib & <3>{n: <4>.nn}).out}, ` +
-			`fib: <5>{n: int if (<5>.n >= 2) yield <6>{out: ((<2>.fibRec & <7>{nn: (<5>.n - 2)}).out + (<2>.fibRec & <8>{nn: (<5>.n - 1)}).out)},  if (<5>.n < 2) yield <9>{out: <5>.n}}, ` +
+			// NOTE: the node numbers are not correct here, but this is an artifact
+			// of the testing code.
+			`fib: <5>{n: int if (<6>.n >= 2) yield <7>{out: ((<2>.fibRec & <8>{nn: (<6>.n - 2)}).out + (<2>.fibRec & <9>{nn: (<6>.n - 1)}).out)},  if (<6>.n < 2) yield <10>{out: <6>.n}}, ` +
 			`fib2: 1, ` +
 			`fib7: 13, ` +
 			`fib12: 144}`,
diff --git a/cue/rewrite.go b/cue/rewrite.go
index 6d13eaa..3a2b477 100644
--- a/cue/rewrite.go
+++ b/cue/rewrite.go
@@ -34,6 +34,14 @@
 	return x
 }
 
+func (x *closeIfStruct) rewrite(ctx *context, fn rewriteFunc) value {
+	v := rewrite(ctx, x.value, fn)
+	if v == x.value {
+		return x
+	}
+	return wrapFinalize(v)
+}
+
 func (x *structLit) rewrite(ctx *context, fn rewriteFunc) value {
 	emit := x.emit
 	if emit != nil {
diff --git a/cue/subsume.go b/cue/subsume.go
index 1c928e0..83cd174 100644
--- a/cue/subsume.go
+++ b/cue/subsume.go
@@ -113,7 +113,7 @@
 			}
 		}
 		// For closed structs, all arcs in b must exist in a.
-		if x.isClosed() {
+		if x.closeStatus.shouldClose() {
 			for _, b := range o.arcs {
 				a := x.lookup(ctx, b.feature)
 				if a.val() == nil {
diff --git a/cue/types.go b/cue/types.go
index 34edee1..ac7412b 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -1151,7 +1151,7 @@
 			obj.baseValue,   // baseValue
 			obj.emit,        // emit
 			obj.template,    // template
-			obj.closeStatus, // isClosed
+			obj.closeStatus, // closeStatus
 			nil,             // comprehensions
 			arcs,            // arcs
 			nil,             // attributes
diff --git a/cue/value.go b/cue/value.go
index f3cf133..17ef829 100644
--- a/cue/value.go
+++ b/cue/value.go
@@ -640,7 +640,7 @@
 	// template must evaluated to a lambda and is applied to all concrete
 	// values in the struct, whether it be open or closed.
 	template    value
-	closeStatus byte
+	closeStatus closeMode
 
 	comprehensions []value
 
@@ -649,15 +649,34 @@
 	expanded evaluated
 }
 
-func (x *structLit) isClosed() bool {
-	return x.closeStatus != 0
-}
+type closeMode byte
 
 const (
-	toClose  = 1
-	isClosed = 2
+	shouldFinalize closeMode = 1 << iota
+	toClose
+	isClosed
 )
 
+func (m closeMode) shouldFinalize() bool {
+	return m&shouldFinalize != 0
+}
+
+func (m *closeMode) unclose() {
+	*m &^= (toClose | isClosed)
+}
+
+func (m closeMode) isClosed() bool {
+	return m&isClosed != 0
+}
+
+func (m closeMode) shouldClose() bool {
+	return m >= toClose
+}
+
+func (x *structLit) isClosed() bool {
+	return x.closeStatus.isClosed()
+}
+
 func (x *structLit) addTemplate(ctx *context, pos token.Pos, t value) {
 	if x.template == nil {
 		x.template = t
@@ -667,7 +686,7 @@
 }
 
 func (x *structLit) allows(f label) bool {
-	return x.closeStatus&isClosed == 0 || f&hidden != 0
+	return !x.closeStatus.isClosed() || f&hidden != 0
 }
 
 func newStruct(src source) *structLit {
@@ -762,6 +781,7 @@
 
 		var doc *ast.Field
 		v, doc = x.applyTemplate(ctx, i, v)
+		// only place to apply template?
 
 		if (len(ctx.evalStack) > 0 && ctx.cycleErr) || cycleError(v) != nil {
 			// Don't cache while we're in a evaluation cycle as it will cache
@@ -776,11 +796,7 @@
 		// it is safe to cache the result.
 		ctx.cycleErr = false
 
-		if s, ok := v.(*structLit); ok {
-			if s.closeStatus != 0 {
-				s.closeStatus = 2
-			}
-		}
+		updateCloseStatus(v)
 		x.arcs[i].cache = v
 		if doc != nil {
 			x.arcs[i].docs = &docNode{n: doc, left: x.arcs[i].docs}
@@ -802,10 +818,6 @@
 // should not be evaluated until the other fields of a struct are
 // fully evaluated.
 func (x *structLit) expandFields(ctx *context) (st *structLit, err *bottom) {
-	if x.closeStatus == toClose {
-		x.closeStatus = isClosed
-	}
-
 	switch v := x.expanded.(type) {
 	case nil:
 	case *structLit:
@@ -822,6 +834,8 @@
 
 	comprehensions := x.comprehensions
 
+	var incomplete []value
+
 	var n evaluated = &top{x.baseValue}
 	if x.emit != nil {
 		n = x.emit.evalPartial(ctx)
@@ -829,6 +843,14 @@
 
 	for _, x := range comprehensions {
 		v := x.evalPartial(ctx)
+		if v, ok := v.(*bottom); ok {
+			if isIncomplete(v) {
+				incomplete = append(incomplete, x)
+				continue
+			}
+
+			return nil, v
+		}
 		src := binSrc(x.Pos(), opUnify, x, v)
 		n = binOp(ctx, src, opUnifyUnchecked, n, v)
 	}
@@ -838,16 +860,19 @@
 	case *bottom:
 	case *structLit:
 		orig := *x
-		orig.comprehensions = nil
+		orig.comprehensions = incomplete
 		orig.emit = nil
 		n = binOp(ctx, src, opUnifyUnchecked, &orig, n)
 
 	default:
+		if len(comprehensions) == len(incomplete) {
+			return x, nil
+		}
 		if x.emit != nil {
 			v := x.emit.evalPartial(ctx)
 			n = binOp(ctx, src, opUnifyUnchecked, v, n)
 		}
-		return nil, ctx.mkErr(x, "invalid embedding")
+		return nil, ctx.mkErr(x, n, "invalid embedding")
 	}
 
 	switch v := n.(type) {
@@ -866,7 +891,7 @@
 
 func (x *structLit) applyTemplate(ctx *context, i int, v evaluated) (evaluated, *ast.Field) {
 	if x.template != nil {
-		fn, err := evalLambda(ctx, x.template)
+		fn, err := evalLambda(ctx, x.template, x.closeStatus != 0)
 		if err != nil {
 			return err, nil
 		}
@@ -955,6 +980,46 @@
 	a.cache = nil
 }
 
+type closeIfStruct struct {
+	value
+}
+
+func wrapFinalize(v value) value {
+	if v.kind().isAnyOf(structKind | listKind) {
+		switch x := v.(type) {
+		case *top:
+			return v
+		case *structLit, *list, *disjunction:
+			updateCloseStatus(v)
+		case *closeIfStruct:
+			return x
+		}
+		return &closeIfStruct{v}
+	}
+	return v
+}
+
+func updateCloseStatus(v value) {
+	switch x := v.(type) {
+	case *structLit:
+		if x.closeStatus.shouldClose() {
+			x.closeStatus = isClosed
+		}
+		x.closeStatus |= shouldFinalize
+
+	case *disjunction:
+		for _, d := range x.values {
+			d.val = wrapFinalize(d.val)
+		}
+
+	case *list:
+		wrapFinalize(x.elem)
+		if x.typ != nil {
+			wrapFinalize(x.typ)
+		}
+	}
+}
+
 // insertValue is used during initialization but never during evaluation.
 func (x *structLit) insertValue(ctx *context, f label, optional, isDef bool, value value, a *attributes, docs *docNode) {
 	for i, p := range x.arcs {
@@ -1510,6 +1575,6 @@
 		if k := source.kind(); k&(structKind|listKind) == bottomKind {
 			return ctx.mkErr(x, x.source, "feed source must be list or struct, found %s", k)
 		}
-		return ctx.mkErr(x, "feed source not fully evaluated to struct or list")
+		return ctx.mkErr(x, x.source, codeIncomplete, "incomplete feed source")
 	}
 }
diff --git a/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/apps/v1beta1/types_go_gen.cue b/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/apps/v1beta1/types_go_gen.cue
index fd4c052..f49b235 100644
--- a/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/apps/v1beta1/types_go_gen.cue
+++ b/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/apps/v1beta1/types_go_gen.cue
@@ -44,7 +44,6 @@
 // Scale represents a scaling request for a resource.
 Scale :: {
 	metav1.TypeMeta
-
 	// Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata.
 	// +optional
 	metadata?: metav1.ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt)
@@ -68,7 +67,6 @@
 // map to the same storage identity.
 StatefulSet :: {
 	metav1.TypeMeta
-
 	// +optional
 	metadata?: metav1.ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt)
 
@@ -270,7 +268,6 @@
 // StatefulSetList is a collection of StatefulSets.
 StatefulSetList :: {
 	metav1.TypeMeta
-
 	// +optional
 	metadata?: metav1.ListMeta @go(ListMeta) @protobuf(1,bytes,opt)
 	items: [...StatefulSet] @go(Items,[]StatefulSet) @protobuf(2,bytes,rep)
@@ -281,7 +278,6 @@
 // Deployment enables declarative updates for Pods and ReplicaSets.
 Deployment :: {
 	metav1.TypeMeta
-
 	// Standard object metadata.
 	// +optional
 	metadata?: metav1.ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt)
@@ -349,7 +345,6 @@
 // DeploymentRollback stores the information required to rollback a deployment.
 DeploymentRollback :: {
 	metav1.TypeMeta
-
 	// Required: This must match the Name of a deployment.
 	name: string @go(Name) @protobuf(1,bytes,opt)
 
@@ -515,7 +510,6 @@
 // DeploymentList is a list of Deployments.
 DeploymentList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// +optional
 	metadata?: metav1.ListMeta @go(ListMeta) @protobuf(1,bytes,opt)
@@ -537,7 +531,6 @@
 // depend on its stability. It is primarily for internal use by controllers.
 ControllerRevision :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -553,7 +546,6 @@
 // ControllerRevisionList is a resource containing a list of ControllerRevision objects.
 ControllerRevisionList :: {
 	metav1.TypeMeta
-
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
 	metadata?: metav1.ListMeta @go(ListMeta) @protobuf(1,bytes,opt)
diff --git a/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/core/v1/types_go_gen.cue b/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/core/v1/types_go_gen.cue
index 8aed250..fcd6299 100644
--- a/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/core/v1/types_go_gen.cue
+++ b/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/core/v1/types_go_gen.cue
@@ -28,7 +28,6 @@
 	name: string @go(Name) @protobuf(1,bytes,opt)
 
 	VolumeSource
-
 }
 
 // Represents the source of a volume to mount.
@@ -304,7 +303,6 @@
 // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes
 PersistentVolume :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -435,7 +433,6 @@
 // PersistentVolumeList is a list of PersistentVolume items.
 PersistentVolumeList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -449,7 +446,6 @@
 // PersistentVolumeClaim is a user's request for and claim to a persistent volume
 PersistentVolumeClaim :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -470,7 +466,6 @@
 // PersistentVolumeClaimList is a list of PersistentVolumeClaim items.
 PersistentVolumeClaimList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -1266,7 +1261,6 @@
 // mode.
 SecretProjection :: {
 	LocalObjectReference
-
 	// If unspecified, each key-value pair in the Data field of the referenced
 	// Secret will be projected into the volume as a file whose name is the
 	// key and content is the value. If specified, the listed keys will be
@@ -1735,7 +1729,6 @@
 // ConfigMap volumes support ownership management and SELinux relabeling.
 ConfigMapVolumeSource :: {
 	LocalObjectReference
-
 	// If unspecified, each key-value pair in the Data field of the referenced
 	// ConfigMap will be projected into the volume as a file whose name is the
 	// key and content is the value. If specified, the listed keys will be
@@ -1770,7 +1763,6 @@
 // mode.
 ConfigMapProjection :: {
 	LocalObjectReference
-
 	// If unspecified, each key-value pair in the Data field of the referenced
 	// ConfigMap will be projected into the volume as a file whose name is the
 	// key and content is the value. If specified, the listed keys will be
@@ -2030,7 +2022,6 @@
 	// Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
 	// Defaults to "" (volume's root).
 	// SubPathExpr and SubPath are mutually exclusive.
-	// This field is beta in 1.15.
 	// +optional
 	subPathExpr?: string @go(SubPathExpr) @protobuf(6,bytes,opt)
 }
@@ -2143,7 +2134,6 @@
 // Selects a key from a ConfigMap.
 ConfigMapKeySelector :: {
 	LocalObjectReference
-
 	// The key to select.
 	key: string @go(Key) @protobuf(2,bytes,opt)
 
@@ -2155,7 +2145,6 @@
 // SecretKeySelector selects a key of a Secret.
 SecretKeySelector :: {
 	LocalObjectReference
-
 	// The key of the secret to select from.  Must be a valid secret key.
 	key: string @go(Key) @protobuf(2,bytes,opt)
 
@@ -2186,7 +2175,6 @@
 // key-value pairs as environment variables.
 ConfigMapEnvSource :: {
 	LocalObjectReference
-
 	// Specify whether the ConfigMap must be defined
 	// +optional
 	optional?: null | bool @go(Optional,*bool) @protobuf(2,varint,opt)
@@ -2199,7 +2187,6 @@
 // key-value pairs as environment variables.
 SecretEnvSource :: {
 	LocalObjectReference
-
 	// Specify whether the Secret must be defined
 	// +optional
 	optional?: null | bool @go(Optional,*bool) @protobuf(2,varint,opt)
@@ -2280,7 +2267,6 @@
 // alive or ready to receive traffic.
 Probe :: {
 	Handler
-
 	// Number of seconds after the container has started before liveness probes are initiated.
 	// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
 	// +optional
@@ -3784,7 +3770,6 @@
 // This is an alpha feature enabled by the EphemeralContainers feature flag.
 EphemeralContainer :: {
 	EphemeralContainerCommon
-
 	// If set, the name of the container from PodSpec that this ephemeral container targets.
 	// The ephemeral container will be run in the namespaces (IPC, PID, etc) of this container.
 	// If not set then the ephemeral container is run in whatever namespaces are shared
@@ -3893,7 +3878,6 @@
 // PodStatusResult is a wrapper for PodStatus returned by kubelet that can be encode/decoded
 PodStatusResult :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -3912,7 +3896,6 @@
 // by clients and scheduled onto hosts.
 Pod :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -3935,7 +3918,6 @@
 // PodList is a list of Pods.
 PodList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -3962,7 +3944,6 @@
 // PodTemplate describes a template for creating copies of a predefined pod.
 PodTemplate :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -3977,7 +3958,6 @@
 // PodTemplateList is a list of PodTemplates.
 PodTemplateList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -4081,7 +4061,6 @@
 // ReplicationController represents the configuration of a replication controller.
 ReplicationController :: {
 	metav1.TypeMeta
-
 	// If the Labels of a ReplicationController are empty, they are defaulted to
 	// be the same as the Pod(s) that the replication controller manages.
 	// Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
@@ -4105,7 +4084,6 @@
 // ReplicationControllerList is a collection of replication controllers.
 ReplicationControllerList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -4402,7 +4380,6 @@
 // will answer requests sent through the proxy.
 Service :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -4428,7 +4405,6 @@
 // ServiceList holds a list of services.
 ServiceList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -4444,7 +4420,6 @@
 // * a set of secrets
 ServiceAccount :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -4473,7 +4448,6 @@
 // ServiceAccountList is a list of ServiceAccount objects
 ServiceAccountList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -4498,7 +4472,6 @@
 //  ]
 Endpoints :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -4587,7 +4560,6 @@
 // EndpointsList is a list of endpoints.
 EndpointsList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -5028,7 +5000,6 @@
 // Each node will have a unique identifier in the cache (i.e. in etcd).
 Node :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -5050,7 +5021,6 @@
 // NodeList is the whole list of all Nodes which have been registered with master.
 NodeList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -5148,7 +5118,6 @@
 // Use of multiple namespaces is optional.
 Namespace :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -5168,7 +5137,6 @@
 // NamespaceList is a list of Namespaces.
 NamespaceList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -5183,7 +5151,6 @@
 // Deprecated in 1.7, please use the bindings subresource of pods instead.
 Binding :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -5196,7 +5163,6 @@
 // A list of ephemeral containers used with the Pod ephemeralcontainers subresource.
 EphemeralContainers :: {
 	metav1.TypeMeta
-
 	// +optional
 	metadata?: metav1.ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt)
 
@@ -5219,7 +5185,6 @@
 // PodLogOptions is the query options for a Pod's logs REST call.
 PodLogOptions :: {
 	metav1.TypeMeta
-
 	// The container for which to stream logs. Defaults to only container if there is one container in the pod.
 	// +optional
 	container?: string @go(Container) @protobuf(1,bytes,opt)
@@ -5269,7 +5234,6 @@
 // and also when we cut V2, we should export a "StreamOptions" or somesuch that contains Stdin, Stdout, Stder and TTY
 PodAttachOptions :: {
 	metav1.TypeMeta
-
 	// Stdin if true, redirects the standard input stream of the pod for this call.
 	// Defaults to false.
 	// +optional
@@ -5304,7 +5268,6 @@
 // and also when we cut V2, we should export a "StreamOptions" or somesuch that contains Stdin, Stdout, Stder and TTY
 PodExecOptions :: {
 	metav1.TypeMeta
-
 	// Redirect the standard input stream of the pod for this call.
 	// Defaults to false.
 	// +optional
@@ -5342,7 +5305,6 @@
 // to be passed in the `port` header as part of request.
 PodPortForwardOptions :: {
 	metav1.TypeMeta
-
 	// List of ports to forward
 	// Required when using WebSockets
 	// +optional
@@ -5352,7 +5314,6 @@
 // PodProxyOptions is the query options to a Pod's proxy call.
 PodProxyOptions :: {
 	metav1.TypeMeta
-
 	// Path is the URL path to use for the current proxy request to pod.
 	// +optional
 	path?: string @go(Path) @protobuf(1,bytes,opt)
@@ -5361,7 +5322,6 @@
 // NodeProxyOptions is the query options to a Node's proxy call.
 NodeProxyOptions :: {
 	metav1.TypeMeta
-
 	// Path is the URL path to use for the current proxy request to node.
 	// +optional
 	path?: string @go(Path) @protobuf(1,bytes,opt)
@@ -5370,7 +5330,6 @@
 // ServiceProxyOptions is the query options to a Service's proxy call.
 ServiceProxyOptions :: {
 	metav1.TypeMeta
-
 	// Path is the part of URLs that include service endpoints, suffixes,
 	// and parameters to use for the current proxy request to service.
 	// For example, the whole request URL is
@@ -5453,7 +5412,6 @@
 // SerializedReference is a reference to serialized object.
 SerializedReference :: {
 	metav1.TypeMeta
-
 	// The reference to an object in the system.
 	// +optional
 	reference?: ObjectReference @go(Reference) @protobuf(1,bytes,opt)
@@ -5479,7 +5437,6 @@
 // Event is a report of an event somewhere in the cluster.
 Event :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	metadata: metav1.ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt)
@@ -5571,7 +5528,6 @@
 // EventList is a list of events.
 EventList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -5637,7 +5593,6 @@
 // LimitRange sets resource usage limits for each kind of resource in a Namespace.
 LimitRange :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -5652,7 +5607,6 @@
 // LimitRangeList is a list of LimitRange items.
 LimitRangeList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -5818,7 +5772,6 @@
 // ResourceQuota sets aggregate quota restrictions enforced per namespace
 ResourceQuota :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -5838,7 +5791,6 @@
 // ResourceQuotaList is a list of ResourceQuota items.
 ResourceQuotaList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -5853,7 +5805,6 @@
 // the Data field must be less than MaxSecretSize bytes.
 Secret :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -5986,7 +5937,6 @@
 // SecretList is a list of Secret.
 SecretList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -6000,7 +5950,6 @@
 // ConfigMap holds configuration data for pods to consume.
 ConfigMap :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -6028,7 +5977,6 @@
 // ConfigMapList is a resource containing a list of ConfigMap objects.
 ConfigMapList :: {
 	metav1.TypeMeta
-
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
 	metadata?: metav1.ListMeta @go(ListMeta) @protobuf(1,bytes,opt)
@@ -6069,7 +6017,6 @@
 // ComponentStatus (and ComponentStatusList) holds the cluster validation info.
 ComponentStatus :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -6085,7 +6032,6 @@
 // Status of all the conditions for the component as a list of ComponentStatus objects.
 ComponentStatusList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -6278,7 +6224,6 @@
 // RangeAllocation is not a public type.
 RangeAllocation :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
diff --git a/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/extensions/v1beta1/types_go_gen.cue b/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/extensions/v1beta1/types_go_gen.cue
index 83308fd..bcf4692 100644
--- a/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/extensions/v1beta1/types_go_gen.cue
+++ b/doc/tutorial/kubernetes/quick/pkg/k8s.io/api/extensions/v1beta1/types_go_gen.cue
@@ -39,7 +39,6 @@
 // represents a scaling request for a resource.
 Scale :: {
 	metav1.TypeMeta
-
 	// Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata.
 	// +optional
 	metadata?: metav1.ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt)
@@ -56,7 +55,6 @@
 // Dummy definition
 ReplicationControllerDummy :: {
 	metav1.TypeMeta
-
 }
 
 // DEPRECATED - This group version of Deployment is deprecated by apps/v1beta2/Deployment. See the release notes for
@@ -64,7 +62,6 @@
 // Deployment enables declarative updates for Pods and ReplicaSets.
 Deployment :: {
 	metav1.TypeMeta
-
 	// Standard object metadata.
 	// +optional
 	metadata?: metav1.ObjectMeta @go(ObjectMeta) @protobuf(1,bytes,opt)
@@ -135,7 +132,6 @@
 // DeploymentRollback stores the information required to rollback a deployment.
 DeploymentRollback :: {
 	metav1.TypeMeta
-
 	// Required: This must match the Name of a deployment.
 	name: string @go(Name) @protobuf(1,bytes,opt)
 
@@ -301,7 +297,6 @@
 // DeploymentList is a list of Deployments.
 DeploymentList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// +optional
 	metadata?: metav1.ListMeta @go(ListMeta) @protobuf(1,bytes,opt)
@@ -479,7 +474,6 @@
 // DaemonSet represents the configuration of a daemon set.
 DaemonSet :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -513,7 +507,6 @@
 // DaemonSetList is a collection of daemon sets.
 DaemonSetList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -530,7 +523,6 @@
 // DEPRECATED - This group version of Ingress is deprecated by networking.k8s.io/v1beta1 Ingress. See the release notes for more information.
 Ingress :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -550,7 +542,6 @@
 // IngressList is a collection of Ingress.
 IngressList :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -628,7 +619,6 @@
 	host?: string @go(Host) @protobuf(1,bytes,opt)
 
 	IngressRuleValue
-
 }
 
 // IngressRuleValue represents a rule to apply against incoming requests. If the
@@ -682,7 +672,6 @@
 // ReplicaSet ensures that a specified number of pod replicas are running at any given time.
 ReplicaSet :: {
 	metav1.TypeMeta
-
 	// If the Labels of a ReplicaSet are empty, they are defaulted to
 	// be the same as the Pod(s) that the ReplicaSet manages.
 	// Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
@@ -706,7 +695,6 @@
 // ReplicaSetList is a collection of ReplicaSets.
 ReplicaSetList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -811,7 +799,6 @@
 // Deprecated: use PodSecurityPolicy from policy API Group instead.
 PodSecurityPolicy :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -1237,7 +1224,6 @@
 // Deprecated: use PodSecurityPolicyList from policy API Group instead.
 PodSecurityPolicyList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -1251,7 +1237,6 @@
 // NetworkPolicy describes what network traffic is allowed for a set of Pods
 NetworkPolicy :: {
 	metav1.TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -1424,7 +1409,6 @@
 // Network Policy List is a list of NetworkPolicy objects.
 NetworkPolicyList :: {
 	metav1.TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
diff --git a/doc/tutorial/kubernetes/quick/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/types_go_gen.cue b/doc/tutorial/kubernetes/quick/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/types_go_gen.cue
index 9881cfa..07bd4d8 100644
--- a/doc/tutorial/kubernetes/quick/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/types_go_gen.cue
+++ b/doc/tutorial/kubernetes/quick/pkg/k8s.io/apimachinery/pkg/apis/meta/v1/types_go_gen.cue
@@ -314,7 +314,6 @@
 // ListOptions is the query options to a standard REST list call.
 ListOptions :: {
 	TypeMeta
-
 	// A selector to restrict the list of returned objects by their labels.
 	// Defaults to everything.
 	// +optional
@@ -397,7 +396,6 @@
 // Deprecated. Planned for removal in 1.18.
 ExportOptions :: {
 	TypeMeta
-
 	// Should this value be exported.  Export strips fields that a user can not specify.
 	// Deprecated. Planned for removal in 1.18.
 	export: bool @go(Export) @protobuf(1,varint,opt)
@@ -410,7 +408,6 @@
 // GetOptions is the standard query options to the standard REST get call.
 GetOptions :: {
 	TypeMeta
-
 	// When specified:
 	// - if unset, then the result is returned from remote storage based on quorum-read flag;
 	// - if it's 0, then we simply return what we currently have in cache, no guarantee;
@@ -448,7 +445,6 @@
 // DeleteOptions may be provided when deleting an API object.
 DeleteOptions :: {
 	TypeMeta
-
 	// The duration in seconds before the object should be deleted. Value must be non-negative integer.
 	// The value zero indicates delete immediately. If this value is nil, the default grace period for the
 	// specified type will be used.
@@ -491,7 +487,6 @@
 // CreateOptions may be provided when creating an API object.
 CreateOptions :: {
 	TypeMeta
-
 	// When present, indicates that modifications should not be
 	// persisted. An invalid or unrecognized dryRun directive will
 	// result in an error response and no further processing of the
@@ -512,7 +507,6 @@
 // PatchOptions is meant to be a superset of UpdateOptions.
 PatchOptions :: {
 	TypeMeta
-
 	// When present, indicates that modifications should not be
 	// persisted. An invalid or unrecognized dryRun directive will
 	// result in an error response and no further processing of the
@@ -542,7 +536,6 @@
 // All fields in UpdateOptions should also be present in PatchOptions.
 UpdateOptions :: {
 	TypeMeta
-
 	// When present, indicates that modifications should not be
 	// persisted. An invalid or unrecognized dryRun directive will
 	// result in an error response and no further processing of the
@@ -573,7 +566,6 @@
 // Status is a return value for calls that don't return other objects.
 Status :: {
 	TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -894,7 +886,6 @@
 // List holds a list of objects, which may not be known by the server.
 List :: {
 	TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -911,7 +902,6 @@
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 APIVersions :: {
 	TypeMeta
-
 	// versions are the api versions that are available.
 	versions: [...string] @go(Versions,[]string) @protobuf(1,bytes,rep)
 
@@ -929,7 +919,6 @@
 // /apis.
 APIGroupList :: {
 	TypeMeta
-
 	// groups is a list of APIGroup.
 	groups: [...APIGroup] @go(Groups,[]APIGroup) @protobuf(1,bytes,rep)
 }
@@ -938,7 +927,6 @@
 // of a group.
 APIGroup :: {
 	TypeMeta
-
 	// name is the name of the group.
 	name: string @go(Name) @protobuf(1,bytes,opt)
 
@@ -1038,7 +1026,6 @@
 // is namespaced.
 APIResourceList :: {
 	TypeMeta
-
 	// groupVersion is the group and version this APIResourceList is for.
 	groupVersion: string @go(GroupVersion) @protobuf(1,bytes,opt)
 
@@ -1164,7 +1151,6 @@
 // +protobuf=false
 Table :: {
 	TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
@@ -1292,7 +1278,6 @@
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 TableOptions :: {
 	TypeMeta
-
 	// includeObject decides whether to include each object along with its columnar information.
 	// Specifying "None" will return no object, specifying "Object" will return the full object contents, and
 	// specifying "Metadata" (the default) will return the object's metadata in the PartialObjectMetadata kind
@@ -1305,7 +1290,6 @@
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 PartialObjectMetadata :: {
 	TypeMeta
-
 	// Standard object's metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
 	// +optional
@@ -1316,7 +1300,6 @@
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 PartialObjectMetadataList :: {
 	TypeMeta
-
 	// Standard list metadata.
 	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
 	// +optional
diff --git a/doc/tutorial/kubernetes/testdata/manual.out b/doc/tutorial/kubernetes/testdata/manual.out
index 58b85a0..7f4563d 100644
--- a/doc/tutorial/kubernetes/testdata/manual.out
+++ b/doc/tutorial/kubernetes/testdata/manual.out
@@ -31,7 +31,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -81,7 +113,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -248,7 +312,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -417,7 +513,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -584,7 +712,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -751,7 +911,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -920,7 +1112,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -1087,7 +1311,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -1256,7 +1512,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -1306,7 +1594,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -1459,7 +1779,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -1785,7 +2137,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -1857,8 +2241,13 @@
                                 name:          "grpc"
                                 containerPort: 7788
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "secret-volume"
+                                mountPath: "/etc/ssl"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                         }]
                         volumes: [{
                             name: "secret-volume"
@@ -2007,7 +2396,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -2082,8 +2503,13 @@
                                 name:          "https"
                                 containerPort: 7443
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "secret-volume"
+                                mountPath: "/etc/ssl"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                         }]
                         volumes: [{
                             name: "secret-volume"
@@ -2204,7 +2630,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -2273,8 +2731,13 @@
                                 name:          "http"
                                 containerPort: 8080
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "secret-updater"
+                                mountPath: "/etc/certs"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                         }]
                         volumes: [{
                             name: "secret-updater"
@@ -2375,7 +2838,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -2449,8 +2944,13 @@
                                 name:          "https"
                                 containerPort: 7788
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "secret-volume"
+                                mountPath: "/etc/ssl"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                         }]
                         volumes: [{
                             name: "secret-volume"
@@ -2562,7 +3062,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -2612,7 +3144,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -2634,7 +3198,27 @@
         "event-server": "events:7788"
         logdir:         "/logs"
     }
-    volume: _|_ // incomplete
+    volume: {
+        "\(name)-disk": {
+            name:      string
+            mountPath: "/logs"
+            spec: {
+                gcePersistentDisk: {
+                    pdName: *name | string
+                    fsType: "ext4"
+                }
+            }
+        }
+        "secret-\(name)": {
+            mountPath: "/etc/certs"
+            readOnly:  true
+            spec: {
+                secret: {
+                    secretName: *"\(name)-secrets" | string
+                }
+            }
+        }
+    }
 }
 
 
@@ -2690,10 +3274,27 @@
                                 name:          "client"
                                 containerPort: 8080
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "ssd-caller"
+                                mountPath: "/logs"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "secret-ssh-key"
+                                mountPath: "/sslcerts"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "secret-caller"
+                                mountPath: "/etc/certs"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                             livenessProbe: {
                                 httpGet: {
                                     path: "/debug/health"
@@ -2864,7 +3465,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -2886,7 +3519,27 @@
         "event-server": "events:7788"
         logdir:         "/logs"
     }
-    volume: _|_ // incomplete
+    volume: {
+        "\(name)-disk": {
+            name:      string
+            mountPath: "/logs"
+            spec: {
+                gcePersistentDisk: {
+                    pdName: *name | string
+                    fsType: "ext4"
+                }
+            }
+        }
+        "secret-\(name)": {
+            mountPath: "/etc/certs"
+            readOnly:  true
+            spec: {
+                secret: {
+                    secretName: *"\(name)-secrets" | string
+                }
+            }
+        }
+    }
 }
 
 
@@ -2942,10 +3595,27 @@
                                 name:          "client"
                                 containerPort: 8080
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "secret-ssh-key"
+                                mountPath: "/sslcerts"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "dishwasher-disk"
+                                mountPath: "/logs"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "secret-dishwasher"
+                                mountPath: "/etc/certs"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                             livenessProbe: {
                                 httpGet: {
                                     path: "/debug/health"
@@ -3113,7 +3783,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -3135,7 +3837,27 @@
         "event-server": "events:7788"
         logdir:         "/logs"
     }
-    volume: _|_ // incomplete
+    volume: {
+        "\(name)-disk": {
+            name:      string
+            mountPath: "/logs"
+            spec: {
+                gcePersistentDisk: {
+                    pdName: *name | string
+                    fsType: "ext4"
+                }
+            }
+        }
+        "secret-\(name)": {
+            mountPath: "/etc/certs"
+            readOnly:  true
+            spec: {
+                secret: {
+                    secretName: *"\(name)-secrets" | string
+                }
+            }
+        }
+    }
 }
 
 
@@ -3191,9 +3913,20 @@
                                 name:          "client"
                                 containerPort: 8080
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "expiditer-disk"
+                                mountPath: "/logs"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "secret-expiditer"
+                                mountPath: "/etc/certs"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                             livenessProbe: {
                                 httpGet: {
                                     path: "/debug/health"
@@ -3346,7 +4079,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -3368,7 +4133,27 @@
         "event-server": "events:7788"
         logdir:         "/logs"
     }
-    volume: _|_ // incomplete
+    volume: {
+        "\(name)-disk": {
+            name:      string
+            mountPath: "/logs"
+            spec: {
+                gcePersistentDisk: {
+                    pdName: *name | string
+                    fsType: "ext4"
+                }
+            }
+        }
+        "secret-\(name)": {
+            mountPath: "/etc/certs"
+            readOnly:  true
+            spec: {
+                secret: {
+                    secretName: *"\(name)-secrets" | string
+                }
+            }
+        }
+    }
 }
 
 
@@ -3424,9 +4209,20 @@
                                 name:          "client"
                                 containerPort: 8080
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "secret-headchef"
+                                mountPath: "/sslcerts"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "headchef-disk"
+                                mountPath: "/logs"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                             livenessProbe: {
                                 httpGet: {
                                     path: "/debug/health"
@@ -3578,7 +4374,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -3600,7 +4428,27 @@
         "event-server": "events:7788"
         logdir:         "/logs"
     }
-    volume: _|_ // incomplete
+    volume: {
+        "\(name)-disk": {
+            name:      string
+            mountPath: "/logs"
+            spec: {
+                gcePersistentDisk: {
+                    pdName: *name | string
+                    fsType: "ext4"
+                }
+            }
+        }
+        "secret-\(name)": {
+            mountPath: "/etc/certs"
+            readOnly:  true
+            spec: {
+                secret: {
+                    secretName: *"\(name)-secrets" | string
+                }
+            }
+        }
+    }
 }
 
 
@@ -3656,9 +4504,20 @@
                                 name:          "client"
                                 containerPort: 8080
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "secret-kitchen"
+                                mountPath: "/etc/certs"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "linecook-disk"
+                                mountPath: "/logs"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                             livenessProbe: {
                                 httpGet: {
                                     path: "/debug/health"
@@ -3814,7 +4673,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -3836,7 +4727,27 @@
         "event-server": "events:7788"
         logdir:         "/logs"
     }
-    volume: _|_ // incomplete
+    volume: {
+        "\(name)-disk": {
+            name:      string
+            mountPath: "/logs"
+            spec: {
+                gcePersistentDisk: {
+                    pdName: *name | string
+                    fsType: "ext4"
+                }
+            }
+        }
+        "secret-\(name)": {
+            mountPath: "/etc/certs"
+            readOnly:  true
+            spec: {
+                secret: {
+                    secretName: *"\(name)-secrets" | string
+                }
+            }
+        }
+    }
 }
 
 
@@ -3892,9 +4803,20 @@
                                 name:          "client"
                                 containerPort: 8080
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "secret-ssh-key"
+                                mountPath: "/etc/certs"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "pastrychef-disk"
+                                mountPath: "/logs"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                             livenessProbe: {
                                 httpGet: {
                                     path: "/debug/health"
@@ -4050,7 +4972,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -4072,7 +5026,27 @@
         "event-server": "events:7788"
         logdir:         "/logs"
     }
-    volume: _|_ // incomplete
+    volume: {
+        "\(name)-disk": {
+            name:      string
+            mountPath: "/logs"
+            spec: {
+                gcePersistentDisk: {
+                    pdName: *name | string
+                    fsType: "ext4"
+                }
+            }
+        }
+        "secret-\(name)": {
+            mountPath: "/etc/certs"
+            readOnly:  true
+            spec: {
+                secret: {
+                    secretName: *"\(name)-secrets" | string
+                }
+            }
+        }
+    }
 }
 
 
@@ -4244,7 +5218,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -4266,7 +5272,27 @@
         "event-server": "events:7788"
         logdir:         "/logs"
     }
-    volume: _|_ // incomplete
+    volume: {
+        "\(name)-disk": {
+            name:      string
+            mountPath: "/logs"
+            spec: {
+                gcePersistentDisk: {
+                    pdName: *name | string
+                    fsType: "ext4"
+                }
+            }
+        }
+        "secret-\(name)": {
+            mountPath: "/etc/certs"
+            readOnly:  true
+            spec: {
+                secret: {
+                    secretName: *"\(name)-secrets" | string
+                }
+            }
+        }
+    }
 }
 
 
@@ -4303,7 +5329,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -4383,9 +5441,19 @@
                                 name:          "alertmanager"
                                 containerPort: 9093
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "alertmanager"
+                                mountPath: "/alertmanager"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "config-volume"
+                                mountPath: "/etc/alertmanager"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                         }]
                         volumes: [{
                             name: "alertmanager"
@@ -4560,7 +5628,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -4642,8 +5742,13 @@
                                 name:          "web"
                                 containerPort: 8080
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "grafana-volume"
+                                mountPath: "/var/lib/grafana"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                             resources: {
                                 requests: {
                                     cpu:    "100m"
@@ -4786,7 +5891,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -4864,9 +6001,21 @@
                                 containerPort: 9100
                                 hostPort:      9100
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                                                _|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "proc"
+                                mountPath: "/host/proc"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "sys"
+                                mountPath: "/host/sys"
+                                readOnly:  true
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                             resources: {
                                 requests: {
                                     cpu:    "100m"
@@ -5022,7 +6171,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -5103,8 +6284,13 @@
                                 name:          "web"
                                 containerPort: 9090
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "config-volume"
+                                mountPath: "/etc/prometheus"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                         }]
                         volumes: [{
                             name: "config-volume"
@@ -5714,7 +6900,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -5764,7 +6982,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -5833,8 +7083,13 @@
                                 name:          "client"
                                 containerPort: 4180
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "config-volume"
+                                mountPath: "/etc/authproxy"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                         }]
                         volumes: [{
                             name: "config-volume"
@@ -6055,7 +7310,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -6130,8 +7417,13 @@
                                 name:          "https"
                                 containerPort: 7443
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                            ]
+                            volumeMounts: [{
+                                name:      "secret-volume"
+                                mountPath: "/etc/ssl"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }]
                         }]
                         volumes: [{
                             name: "secret-volume"
@@ -6241,7 +7533,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }
@@ -6319,12 +7643,17 @@
                                 name:          "https"
                                 containerPort: 443
                             }]
-                            volumeMounts: [_|_, // non-concrete value bool
-                                                {
-                                    name:      "config-volume"
-                                    mountPath: "/etc/nginx/nginx.conf"
-                                    subPath:   "nginx.conf"
-                                }]
+                            volumeMounts: [{
+                                name:      "secret-volume"
+                                mountPath: "/etc/ssl"
+                                if false | true {
+                                    subPath: null
+                                }
+                            }, {
+                                name:      "config-volume"
+                                mountPath: "/etc/nginx/nginx.conf"
+                                subPath:   "nginx.conf"
+                            }]
                         }]
                         volumes: [{
                             name: "secret-volume"
@@ -6856,7 +8185,39 @@
         kubernetes: {
             spec: {
                 template: {
-                    spec: _|_ // undefined field "volume"
+                    spec: {
+                        containers: [{
+                            name:  X.name
+                            image: X.image
+                            args:  X.args
+                            ports: [ {
+                                name:          k
+                                containerPort: p
+                            } for k, p in X.expose.port & X.port ]
+                            if len(X.envSpec) > 0 {
+                                env: [ {
+                                    name: k
+                                } & v for k, v in X.envSpec ]
+                            }
+                            if len(X.volume) > 0 {
+                                volumeMounts: [ {
+                                    name:      v.name
+                                    mountPath: v.mountPath
+                                    if v.subPath != null | true {
+                                        subPath: v.subPath
+                                    }
+                                    if v.readOnly {
+                                        readOnly: v.readOnly
+                                    }
+                                } for v in X.volume ]
+                            }
+                        }]
+                        if len(X.volume) > 0 {
+                            volumes: [ v.kubernetes & {
+                                name: v.name
+                            } for v in X.volume ]
+                        }
+                    }
                     metadata: {
                         labels: X.label
                     }