mirror of https://github.com/kubernetes/kops.git
Add support for writing maps of literals, used by gce metadata
This commit is contained in:
parent
2a48c70ea8
commit
ef76409046
|
|
@ -394,28 +394,25 @@ func ShortenImageURL(defaultProject string, imageURL string) (string, error) {
|
|||
}
|
||||
|
||||
type terraformInstance struct {
|
||||
Name string `json:"name" cty:"name"`
|
||||
CanIPForward bool `json:"can_ip_forward" cty:"can_ip_forward"`
|
||||
MachineType string `json:"machine_type,omitempty" cty:"machine_type"`
|
||||
ServiceAccount *terraformServiceAccount `json:"service_account,omitempty" cty:"service_account"`
|
||||
Scheduling *terraformScheduling `json:"scheduling,omitempty" cty:"scheduling"`
|
||||
Disks []*terraformInstanceAttachedDisk `json:"disk,omitempty" cty:"disk"`
|
||||
NetworkInterfaces []*terraformNetworkInterface `json:"network_interface,omitempty" cty:"network_interface"`
|
||||
Metadata map[string]*terraform.Literal `json:"metadata,omitempty" cty:"metadata"`
|
||||
MetadataStartupScript *terraform.Literal `json:"metadata_startup_script,omitempty" cty:"metadata_startup_script"`
|
||||
Tags []string `json:"tags,omitempty" cty:"tags"`
|
||||
Zone string `json:"zone,omitempty" cty:"zone"`
|
||||
Name string `json:"name" cty:"name"`
|
||||
CanIPForward bool `json:"can_ip_forward" cty:"can_ip_forward"`
|
||||
MachineType string `json:"machine_type,omitempty" cty:"machine_type"`
|
||||
ServiceAccount *terraformServiceAccount `json:"service_account,omitempty" cty:"service_account"`
|
||||
Scheduling *terraformScheduling `json:"scheduling,omitempty" cty:"scheduling"`
|
||||
Disks []*terraformInstanceAttachedDisk `json:"disk,omitempty" cty:"disk"`
|
||||
NetworkInterfaces []*terraformNetworkInterface `json:"network_interface,omitempty" cty:"network_interface"`
|
||||
Metadata map[string]*terraform.Literal `json:"metadata,omitempty" cty:"metadata"`
|
||||
MetadataStartupScript *terraform.Literal `json:"metadata_startup_script,omitempty" cty:"metadata_startup_script"`
|
||||
Tags []string `json:"tags,omitempty" cty:"tags"`
|
||||
Zone string `json:"zone,omitempty" cty:"zone"`
|
||||
}
|
||||
|
||||
|
||||
type terraformInstanceAttachedDisk struct {
|
||||
AutoDelete bool `json:"auto_delete,omitempty" cty:"auto_delete"`
|
||||
DeviceName string `json:"device_name,omitempty" cty:"device_name"`
|
||||
|
||||
// DANGER - common but different meaning:
|
||||
// for an instance template this is scratch vs persistent
|
||||
// for an instance this is 'pd-standard', 'pd-ssd', 'local-ssd' etc
|
||||
Type string `json:"type,omitempty" cty:"type"`
|
||||
// 'pd-standard', 'pd-ssd', 'local-ssd' etc
|
||||
Type string `json:"type,omitempty" cty:"type"`
|
||||
Disk string `json:"disk,omitempty" cty:"disk"`
|
||||
Image string `json:"image,omitempty" cty:"image"`
|
||||
Scratch bool `json:"scratch,omitempty" cty:"scratch"`
|
||||
|
|
|
|||
|
|
@ -417,16 +417,16 @@ func (_ *InstanceTemplate) RenderGCE(t *gce.GCEAPITarget, a, e, changes *Instanc
|
|||
}
|
||||
|
||||
type terraformInstanceTemplate struct {
|
||||
NamePrefix string `json:"name_prefix" cty:"name_prefix"`
|
||||
CanIPForward bool `json:"can_ip_forward" cty:"can_ip_forward"`
|
||||
MachineType string `json:"machine_type,omitempty" cty:"machine_type"`
|
||||
ServiceAccount *terraformServiceAccount `json:"service_account,omitempty" cty:"service_account"`
|
||||
Scheduling *terraformScheduling `json:"scheduling,omitempty" cty:"scheduling"`
|
||||
Disks []*terraformInstanceTemplateAttachedDisk `json:"disk,omitempty" cty:"disk"`
|
||||
NetworkInterfaces []*terraformNetworkInterface `json:"network_interface,omitempty" cty:"network_interface"`
|
||||
Metadata map[string]*terraform.Literal `json:"metadata,omitempty" cty:"metadata"`
|
||||
MetadataStartupScript *terraform.Literal `json:"metadata_startup_script,omitempty" cty:"metadata_startup_script"`
|
||||
Tags []string `json:"tags,omitempty" cty:"tags"`
|
||||
NamePrefix string `json:"name_prefix" cty:"name_prefix"`
|
||||
CanIPForward bool `json:"can_ip_forward" cty:"can_ip_forward"`
|
||||
MachineType string `json:"machine_type,omitempty" cty:"machine_type"`
|
||||
ServiceAccount *terraformServiceAccount `json:"service_account,omitempty" cty:"service_account"`
|
||||
Scheduling *terraformScheduling `json:"scheduling,omitempty" cty:"scheduling"`
|
||||
Disks []*terraformInstanceTemplateAttachedDisk `json:"disk,omitempty" cty:"disk"`
|
||||
NetworkInterfaces []*terraformNetworkInterface `json:"network_interface,omitempty" cty:"network_interface"`
|
||||
Metadata map[string]*terraform.Literal `json:"metadata,omitempty" cty:"metadata"`
|
||||
MetadataStartupScript *terraform.Literal `json:"metadata_startup_script,omitempty" cty:"metadata_startup_script"`
|
||||
Tags []string `json:"tags,omitempty" cty:"tags"`
|
||||
}
|
||||
|
||||
type terraformServiceAccount struct {
|
||||
|
|
@ -444,12 +444,8 @@ type terraformInstanceTemplateAttachedDisk struct {
|
|||
AutoDelete bool `json:"auto_delete,omitempty" cty:"auto_delete"`
|
||||
DeviceName string `json:"device_name,omitempty" cty:"device_name"`
|
||||
|
||||
// DANGER - common but different meaning:
|
||||
// for an instance template this is scratch vs persistent
|
||||
// for an instance this is 'pd-standard', 'pd-ssd', 'local-ssd' etc
|
||||
Type string `json:"type,omitempty" cty:"type"`
|
||||
|
||||
// These values are only for instance templates:
|
||||
// scratch vs persistent
|
||||
Type string `json:"type,omitempty" cty:"type"`
|
||||
Boot bool `json:"boot,omitempty" cty:"boot"`
|
||||
DiskName string `json:"disk_name,omitempty" cty:"disk_name"`
|
||||
SourceImage string `json:"source_image,omitempty" cty:"source_image"`
|
||||
|
|
|
|||
|
|
@ -40,5 +40,6 @@ go_test(
|
|||
"//pkg/diff:go_default_library",
|
||||
"//vendor/github.com/hashicorp/hcl/v2/hclwrite:go_default_library",
|
||||
"//vendor/github.com/zclconf/go-cty/cty:go_default_library",
|
||||
"//vendor/github.com/zclconf/go-cty/cty/gocty:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -177,17 +177,32 @@ func writeMap(body *hclwrite.Body, key string, values map[string]cty.Value) {
|
|||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
v := values[k]
|
||||
tokens = append(tokens, []*hclwrite.Token{
|
||||
{Type: hclsyntax.TokenOQuote, Bytes: []byte{'"'}, SpacesBefore: 1},
|
||||
{Type: hclsyntax.TokenQuotedLit, Bytes: []byte(k)},
|
||||
{Type: hclsyntax.TokenCQuote, Bytes: []byte{'"'}, SpacesBefore: 1},
|
||||
{Type: hclsyntax.TokenEqual, Bytes: []byte("="), SpacesBefore: 1},
|
||||
{Type: hclsyntax.TokenOQuote, Bytes: []byte{'"'}, SpacesBefore: 1},
|
||||
{Type: hclsyntax.TokenQuotedLit, Bytes: []byte(v.AsString())},
|
||||
{Type: hclsyntax.TokenCQuote, Bytes: []byte{'"'}, SpacesBefore: 1},
|
||||
{Type: hclsyntax.TokenNewline, Bytes: []byte("\n")},
|
||||
}...)
|
||||
|
||||
v := values[k]
|
||||
|
||||
refLiteral := reflect.New(reflect.TypeOf(Literal{}))
|
||||
err := gocty.FromCtyValue(v, refLiteral.Interface())
|
||||
// If this is a map of literals then do not surround the value with quotes
|
||||
if literal, ok := refLiteral.Interface().(*Literal); err == nil && ok {
|
||||
// For maps of literals we currently only support file references
|
||||
// If we ever need to support a map of strings to resource property references that can be added here
|
||||
if literal.FilePath != "" {
|
||||
tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenIdent, Bytes: []byte(fmt.Sprintf("file(%q)", literal.FilePath))})
|
||||
}
|
||||
} else {
|
||||
tokens = append(tokens, []*hclwrite.Token{
|
||||
{Type: hclsyntax.TokenOQuote, Bytes: []byte{'"'}, SpacesBefore: 1},
|
||||
{Type: hclsyntax.TokenQuotedLit, Bytes: []byte(v.AsString())},
|
||||
{Type: hclsyntax.TokenOQuote, Bytes: []byte{'"'}, SpacesBefore: 1},
|
||||
}...)
|
||||
}
|
||||
tokens = append(tokens, &hclwrite.Token{Type: hclsyntax.TokenNewline, Bytes: []byte("\n")})
|
||||
}
|
||||
tokens = append(tokens,
|
||||
&hclwrite.Token{Type: hclsyntax.TokenCBrace, Bytes: []byte("}")},
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/hcl/v2/hclwrite"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/gocty"
|
||||
"k8s.io/kops/pkg/diff"
|
||||
)
|
||||
|
||||
|
|
@ -262,3 +263,53 @@ tags = {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteMapLiterals(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
values map[string]Literal
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "literal values",
|
||||
values: map[string]Literal{
|
||||
"key1": {FilePath: "${module.path}/path/to/value1"},
|
||||
"key2": {FilePath: "${module.path}/path/to/value2"},
|
||||
},
|
||||
expected: `
|
||||
metadata = {
|
||||
"key1" = file("${module.path}/path/to/value1")
|
||||
"key2" = file("${module.path}/path/to/value2")
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
literalMap := make(map[string]cty.Value)
|
||||
for k, v := range tc.values {
|
||||
literalType, err := gocty.ImpliedType(v)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
}
|
||||
literalVal, err := gocty.ToCtyValue(v, literalType)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
}
|
||||
literalMap[k] = literalVal
|
||||
}
|
||||
|
||||
f := hclwrite.NewEmptyFile()
|
||||
root := f.Body()
|
||||
writeMap(root, "metadata", literalMap)
|
||||
actual := strings.TrimSpace(string(f.Bytes()))
|
||||
expected := strings.TrimSpace(tc.expected)
|
||||
if actual != expected {
|
||||
diffString := diff.FormatDiff(expected, string(actual))
|
||||
t.Logf("diff:\n%s\n", diffString)
|
||||
t.Errorf("expected: '%s', got: '%s'\n", expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue