Show types during variable list operation
If a type was explicitly provided, it will be displayed in the variable listing. Inferred type names are not displayed, as they likely would not match the user's intent. Previously only `string` and `bool` default values were displayed in the listing. All default values, regardless of type, are now displayed. Signed-off-by: Roberto Villarreal <rrjjvv@yahoo.com>
This commit is contained in:
@@ -38,6 +38,9 @@ type variable struct {
|
||||
Validations []*variableValidation `json:"validation,omitempty" hcl:"validation,block"`
|
||||
Body hcl.Body `json:"-" hcl:",body"`
|
||||
Remain hcl.Body `json:"-" hcl:",remain"`
|
||||
|
||||
// the type described by Type if it was specified
|
||||
constraint *cty.Type
|
||||
}
|
||||
|
||||
type variableValidation struct {
|
||||
@@ -296,6 +299,9 @@ func (p *parser) resolveValue(ectx *hcl.EvalContext, name string) (err error) {
|
||||
return diags
|
||||
}
|
||||
typeSpecified = !varType.Equals(cty.DynamicPseudoType) || hcl.ExprAsKeyword(vr.Type) == "any"
|
||||
if typeSpecified {
|
||||
vr.constraint = &varType
|
||||
}
|
||||
}
|
||||
|
||||
if def == nil {
|
||||
@@ -674,6 +680,7 @@ func (p *parser) validateVariables(vars map[string]*variable, ectx *hcl.EvalCont
|
||||
type Variable struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Value *string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
@@ -803,13 +810,31 @@ func Parse(b hcl.Body, opt Opt, val any) (*ParseMeta, hcl.Diagnostics) {
|
||||
Name: p.vars[k].Name,
|
||||
Description: p.vars[k].Description,
|
||||
}
|
||||
tc := p.vars[k].constraint
|
||||
if tc != nil {
|
||||
v.Type = tc.FriendlyNameForConstraint()
|
||||
}
|
||||
if vv := p.ectx.Variables[k]; !vv.IsNull() {
|
||||
var s string
|
||||
switch vv.Type() {
|
||||
case cty.String:
|
||||
s = vv.AsString()
|
||||
case cty.Bool:
|
||||
s = strconv.FormatBool(vv.True())
|
||||
switch {
|
||||
case tc != nil:
|
||||
if bs, err := ctyjson.Marshal(vv, *tc); err == nil {
|
||||
s = string(bs)
|
||||
// untyped strings were always unquoted, so be consistent with typed strings as well
|
||||
if tc.Equals(cty.String) {
|
||||
s = strings.Trim(s, "\"")
|
||||
}
|
||||
}
|
||||
case vv.Type().IsPrimitiveType():
|
||||
// all primitives can convert to string, so error should never occur
|
||||
if val, err := convert.Convert(vv, cty.String); err == nil {
|
||||
s = val.AsString()
|
||||
}
|
||||
default:
|
||||
// must be an (inferred) tuple or object
|
||||
if bs, err := ctyjson.Marshal(vv, vv.Type()); err == nil {
|
||||
s = string(bs)
|
||||
}
|
||||
}
|
||||
v.Value = &s
|
||||
}
|
||||
|
||||
+2
-2
@@ -663,7 +663,7 @@ func printVars(w io.Writer, format string, vars []*hclparser.Variable) error {
|
||||
tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
|
||||
defer tw.Flush()
|
||||
|
||||
tw.Write([]byte("VARIABLE\tVALUE\tDESCRIPTION\n"))
|
||||
tw.Write([]byte("VARIABLE\tTYPE\tVALUE\tDESCRIPTION\n"))
|
||||
|
||||
for _, v := range vars {
|
||||
var value string
|
||||
@@ -672,7 +672,7 @@ func printVars(w io.Writer, format string, vars []*hclparser.Variable) error {
|
||||
} else {
|
||||
value = "<null>"
|
||||
}
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\n", v.Name, value, v.Description)
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", v.Name, v.Type, value, v.Description)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -198,12 +198,15 @@ To list variables:
|
||||
|
||||
```console
|
||||
$ docker buildx bake --list=variables
|
||||
VARIABLE VALUE DESCRIPTION
|
||||
REGISTRY docker.io/username Registry and namespace
|
||||
IMAGE_NAME my-app Image name
|
||||
VARIABLE TYPE VALUE DESCRIPTION
|
||||
REGISTRY string docker.io/username Registry and namespace
|
||||
IMAGE_NAME string my-app Image name
|
||||
GO_VERSION <null>
|
||||
DEBUG bool false Add debug symbols
|
||||
```
|
||||
|
||||
Variable types will be shown when set using the `type` property in the Bake file.
|
||||
|
||||
By default, the output of `docker buildx bake --list` is presented in a table
|
||||
format. Alternatively, you can use a long-form CSV syntax and specify a
|
||||
`format` attribute to output the list in JSON.
|
||||
|
||||
+88
-1
@@ -74,6 +74,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
|
||||
testBakeLoadPush,
|
||||
testListTargets,
|
||||
testListVariables,
|
||||
testListTypedVariables,
|
||||
testBakeCallCheck,
|
||||
testBakeCallCheckFlag,
|
||||
testBakeCallMetadata,
|
||||
@@ -1737,7 +1738,93 @@ target "default" {
|
||||
)
|
||||
require.NoError(t, err, out)
|
||||
|
||||
require.Equal(t, "VARIABLE\tVALUE\tDESCRIPTION\nabc\t\t<null>\t\ndef\t\t\t\nfoo\t\tbar\tThis is foo", strings.TrimSpace(out))
|
||||
require.Equal(t, "VARIABLE\tTYPE\tVALUE\tDESCRIPTION\nabc\t\t\t<null>\t\ndef\t\t\t\t\nfoo\t\t\tbar\tThis is foo", strings.TrimSpace(out))
|
||||
}
|
||||
|
||||
func testListTypedVariables(t *testing.T, sb integration.Sandbox) {
|
||||
bakefile := []byte(`
|
||||
variable "abc" {
|
||||
type = string
|
||||
default = "bar"
|
||||
description = "This is abc"
|
||||
}
|
||||
variable "def" {
|
||||
type = string
|
||||
description = "simple type, no default"
|
||||
}
|
||||
variable "ghi" {
|
||||
type = number
|
||||
default = 99
|
||||
description = "simple type w/ default"
|
||||
}
|
||||
variable "jkl" {
|
||||
type = list(string)
|
||||
default = ["hello"]
|
||||
description = "collection with quoted strings"
|
||||
}
|
||||
variable "mno" {
|
||||
type = list(number)
|
||||
description = "collection, no default"
|
||||
}
|
||||
variable "pqr" {
|
||||
type = tuple([number, string, bool])
|
||||
default = [99, "99", true]
|
||||
}
|
||||
variable "stu" {
|
||||
type = map(string)
|
||||
default = {"foo": "bar"}
|
||||
}
|
||||
variable "vwx" {
|
||||
type = set(bool)
|
||||
default = null
|
||||
description = "collection, null default"
|
||||
}
|
||||
|
||||
// untyped, but previously didn't have its value output
|
||||
variable "wxy" {
|
||||
default = ["foo"]
|
||||
description = "inferred tuple"
|
||||
}
|
||||
// untyped, but previously didn't have its value output
|
||||
variable "xyz" {
|
||||
default = {"foo": "bar"}
|
||||
description = "inferred object"
|
||||
}
|
||||
// untyped, but previously didn't have its value output
|
||||
variable "yza" {
|
||||
default = true
|
||||
description = "inferred bool"
|
||||
}
|
||||
target "default" {
|
||||
}
|
||||
`)
|
||||
dir := tmpdir(
|
||||
t,
|
||||
fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
|
||||
)
|
||||
|
||||
out, err := bakeCmd(
|
||||
sb,
|
||||
withDir(dir),
|
||||
withArgs("--list=variables"),
|
||||
)
|
||||
require.NoError(t, err, out)
|
||||
require.Equal(t,
|
||||
"VARIABLE\tTYPE\t\tVALUE\t\tDESCRIPTION\n"+
|
||||
"abc\t\tstring\t\tbar\t\tThis is abc\n"+
|
||||
"def\t\tstring\t\t<null>\t\tsimple type, no default\n"+
|
||||
"ghi\t\tnumber\t\t99\t\tsimple type w/ default\n"+
|
||||
"jkl\t\tlist of string\t[\"hello\"]\tcollection with quoted strings\n"+
|
||||
"mno\t\tlist of number\t<null>\t\tcollection, no default\n"+
|
||||
// the implementation for tuple's 'friendly name' is very basic
|
||||
// and marked as TODO, so this may change/break at some point
|
||||
"pqr\t\ttuple\t\t[99,\"99\",true]\t\n"+
|
||||
"stu\t\tmap of string\t{\"foo\":\"bar\"}\t\n"+
|
||||
"vwx\t\tset of bool\t<null>\t\tcollection, null default\n"+
|
||||
"wxy\t\t\t\t[\"foo\"]\t\tinferred tuple\n"+
|
||||
"xyz\t\t\t\t{\"foo\":\"bar\"}\tinferred object\n"+
|
||||
"yza\t\t\t\ttrue\t\tinferred bool",
|
||||
strings.TrimSpace(out))
|
||||
}
|
||||
|
||||
func testBakeCallCheck(t *testing.T, sb integration.Sandbox) {
|
||||
|
||||
Reference in New Issue
Block a user