From 2a48c70ea8599c44cd6fc8a4aa9ab96cac51d597 Mon Sep 17 00:00:00 2001 From: Peter Rifel Date: Wed, 8 Apr 2020 21:18:50 -0500 Subject: [PATCH 1/4] Copy GCE instance fields into both Instance and InstanceTemplate The hcl2 library doesn't handle embedded types well, so rather than trying to detect it with reflection I figured it was easier to just get rid of the one case of it. This copies the fields from the embedded type into both Instance and InstanceTemplate, updating the receiver functions to instead return the value for the field that was being modified. --- upup/pkg/fi/cloudup/gcetasks/instance.go | 39 ++++++-- .../fi/cloudup/gcetasks/instancetemplate.go | 91 ++++++++----------- 2 files changed, 73 insertions(+), 57 deletions(-) diff --git a/upup/pkg/fi/cloudup/gcetasks/instance.go b/upup/pkg/fi/cloudup/gcetasks/instance.go index 2e5c9ca2e9..663c64e4af 100644 --- a/upup/pkg/fi/cloudup/gcetasks/instance.go +++ b/upup/pkg/fi/cloudup/gcetasks/instance.go @@ -394,9 +394,32 @@ func ShortenImageURL(defaultProject string, imageURL string) (string, error) { } type terraformInstance struct { - terraformInstanceCommon + 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"` + +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"` + Disk string `json:"disk,omitempty" cty:"disk"` + Image string `json:"image,omitempty" cty:"image"` + Scratch bool `json:"scratch,omitempty" cty:"scratch"` + Size int64 `json:"size,omitempty" cty:"size"` } func (_ *Instance) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *Instance) error { @@ -426,10 +449,10 @@ func (_ *Instance) RenderTerraform(t *terraform.TerraformTarget, a, e, changes * tf.Zone = *e.Zone } - tf.AddServiceAccounts(i.ServiceAccounts) + tf.ServiceAccount = addServiceAccounts(i.ServiceAccounts) for _, d := range i.Disks { - tfd := &terraformAttachedDisk{ + tfd := &terraformInstanceAttachedDisk{ AutoDelete: d.AutoDelete, Scratch: d.Type == "SCRATCH", DeviceName: d.DeviceName, @@ -446,9 +469,13 @@ func (_ *Instance) RenderTerraform(t *terraform.TerraformTarget, a, e, changes * tf.Disks = append(tf.Disks, tfd) } - tf.AddNetworks(e.Network, e.Subnet, i.NetworkInterfaces) + tf.NetworkInterfaces = addNetworks(e.Network, e.Subnet, i.NetworkInterfaces) - tf.AddMetadata(t, i.Name, i.Metadata) + metadata, err := addMetadata(t, i.Name, i.Metadata) + if err != nil { + return err + } + tf.Metadata = metadata // Using metadata_startup_script is now mandatory (?) { diff --git a/upup/pkg/fi/cloudup/gcetasks/instancetemplate.go b/upup/pkg/fi/cloudup/gcetasks/instancetemplate.go index bbbb0622c7..e8014bcdb3 100644 --- a/upup/pkg/fi/cloudup/gcetasks/instancetemplate.go +++ b/upup/pkg/fi/cloudup/gcetasks/instancetemplate.go @@ -417,23 +417,16 @@ func (_ *InstanceTemplate) RenderGCE(t *gce.GCEAPITarget, a, e, changes *Instanc } type terraformInstanceTemplate struct { - terraformInstanceCommon - NamePrefix string `json:"name_prefix" cty:"name_prefix"` -} - -type terraformInstanceCommon 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 []*terraformAttachedDisk `json:"disk,omitempty" cty:"disk"` + 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"` - - // Only for instances: - Zone string `json:"zone,omitempty" cty:"zone"` } type terraformServiceAccount struct { @@ -447,8 +440,7 @@ type terraformScheduling struct { Preemptible bool `json:"preemptible" cty:"preemptible"` } -type terraformAttachedDisk struct { - // These values are common +type terraformInstanceTemplateAttachedDisk struct { AutoDelete bool `json:"auto_delete,omitempty" cty:"auto_delete"` DeviceName string `json:"device_name,omitempty" cty:"device_name"` @@ -466,12 +458,6 @@ type terraformAttachedDisk struct { Mode string `json:"mode,omitempty" cty:"mode"` DiskType string `json:"disk_type,omitempty" cty:"disk_type"` DiskSizeGB int64 `json:"disk_size_gb,omitempty" cty:"disk_size_gb"` - - // These values are only for instances: - Disk string `json:"disk,omitempty" cty:"disk"` - Image string `json:"image,omitempty" cty:"image"` - Scratch bool `json:"scratch,omitempty" cty:"scratch"` - Size int64 `json:"size,omitempty" cty:"size"` } type terraformNetworkInterface struct { @@ -484,8 +470,9 @@ type terraformAccessConfig struct { NatIP *terraform.Literal `json:"nat_ip,omitempty" cty:"nat_ip"` } -func (t *terraformInstanceCommon) AddNetworks(network *Network, subnet *Subnet, networkInterfacs []*compute.NetworkInterface) { - for _, g := range networkInterfacs { +func addNetworks(network *Network, subnet *Subnet, networkInterfaces []*compute.NetworkInterface) []*terraformNetworkInterface { + ni := make([]*terraformNetworkInterface, 0) + for _, g := range networkInterfaces { tf := &terraformNetworkInterface{} if network != nil { tf.Network = network.TerraformName() @@ -505,46 +492,44 @@ func (t *terraformInstanceCommon) AddNetworks(network *Network, subnet *Subnet, tf.AccessConfig = append(tf.AccessConfig, tac) } - t.NetworkInterfaces = append(t.NetworkInterfaces, tf) + ni = append(ni, tf) } + return ni } -func (t *terraformInstanceCommon) AddMetadata(target *terraform.TerraformTarget, name string, metadata *compute.Metadata) error { - if metadata != nil { - if t.Metadata == nil { - t.Metadata = make(map[string]*terraform.Literal) - } - for _, g := range metadata.Items { - v := fi.NewStringResource(fi.StringValue(g.Value)) - tfResource, err := target.AddFile("google_compute_instance_template", name, "metadata_"+g.Key, v) - if err != nil { - return err - } - - t.Metadata[g.Key] = tfResource - } +func addMetadata(target *terraform.TerraformTarget, name string, metadata *compute.Metadata) (map[string]*terraform.Literal, error) { + if metadata == nil { + return nil, nil } + m := make(map[string]*terraform.Literal) + for _, g := range metadata.Items { + v := fi.NewStringResource(fi.StringValue(g.Value)) + tfResource, err := target.AddFile("google_compute_instance_template", name, "metadata_"+g.Key, v) + if err != nil { + return nil, err + } - return nil + m[g.Key] = tfResource + } + return m, nil } -func (t *terraformInstanceCommon) AddServiceAccounts(serviceAccounts []*compute.ServiceAccount) { +func addServiceAccounts(serviceAccounts []*compute.ServiceAccount) *terraformServiceAccount { // there's an inconsistency here- GCP only lets you have one service account per VM // terraform gets it right, but the golang api doesn't. womp womp :( if len(serviceAccounts) != 1 { klog.Fatal("Instances can only have 1 service account assigned.") - } else { - klog.Infof("adding csa: %v", serviceAccounts[0].Email) - csa := serviceAccounts[0] - tsa := &terraformServiceAccount{ - Email: csa.Email, - Scopes: csa.Scopes, - } - // for _, scope := range csa.Scopes { - // tsa.Scopes = append(tsa.Scopes, scope) - // } - t.ServiceAccount = tsa } + klog.Infof("adding csa: %v", serviceAccounts[0].Email) + csa := serviceAccounts[0] + tsa := &terraformServiceAccount{ + Email: csa.Email, + Scopes: csa.Scopes, + } + // for _, scope := range csa.Scopes { + // tsa.Scopes = append(tsa.Scopes, scope) + // } + return tsa } func (_ *InstanceTemplate) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *InstanceTemplate) error { project := t.Project @@ -565,10 +550,10 @@ func (_ *InstanceTemplate) RenderTerraform(t *terraform.TerraformTarget, a, e, c //tf.Zone = i.Properties.Zone tf.Tags = i.Properties.Tags.Items - tf.AddServiceAccounts(i.Properties.ServiceAccounts) + tf.ServiceAccount = addServiceAccounts(i.Properties.ServiceAccounts) for _, d := range i.Properties.Disks { - tfd := &terraformAttachedDisk{ + tfd := &terraformInstanceTemplateAttachedDisk{ AutoDelete: d.AutoDelete, Boot: d.Boot, DeviceName: d.DeviceName, @@ -584,9 +569,13 @@ func (_ *InstanceTemplate) RenderTerraform(t *terraform.TerraformTarget, a, e, c tf.Disks = append(tf.Disks, tfd) } - tf.AddNetworks(e.Network, e.Subnet, i.Properties.NetworkInterfaces) + tf.NetworkInterfaces = addNetworks(e.Network, e.Subnet, i.Properties.NetworkInterfaces) - tf.AddMetadata(t, name, i.Properties.Metadata) + metadata, err := addMetadata(t, name, i.Properties.Metadata) + if err != nil { + return err + } + tf.Metadata = metadata if i.Properties.Scheduling != nil { tf.Scheduling = &terraformScheduling{ From ef76409046015cb064ae8f2cd3d5e32b84d81130 Mon Sep 17 00:00:00 2001 From: Peter Rifel Date: Wed, 8 Apr 2020 21:19:06 -0500 Subject: [PATCH 2/4] Add support for writing maps of literals, used by gce metadata --- upup/pkg/fi/cloudup/gcetasks/instance.go | 29 +++++------ .../fi/cloudup/gcetasks/instancetemplate.go | 28 +++++----- upup/pkg/fi/cloudup/terraform/BUILD.bazel | 1 + upup/pkg/fi/cloudup/terraform/hcl2.go | 25 +++++++-- upup/pkg/fi/cloudup/terraform/hcl2_test.go | 51 +++++++++++++++++++ 5 files changed, 97 insertions(+), 37 deletions(-) diff --git a/upup/pkg/fi/cloudup/gcetasks/instance.go b/upup/pkg/fi/cloudup/gcetasks/instance.go index 663c64e4af..e0134b0200 100644 --- a/upup/pkg/fi/cloudup/gcetasks/instance.go +++ b/upup/pkg/fi/cloudup/gcetasks/instance.go @@ -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"` diff --git a/upup/pkg/fi/cloudup/gcetasks/instancetemplate.go b/upup/pkg/fi/cloudup/gcetasks/instancetemplate.go index e8014bcdb3..2105c22331 100644 --- a/upup/pkg/fi/cloudup/gcetasks/instancetemplate.go +++ b/upup/pkg/fi/cloudup/gcetasks/instancetemplate.go @@ -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"` diff --git a/upup/pkg/fi/cloudup/terraform/BUILD.bazel b/upup/pkg/fi/cloudup/terraform/BUILD.bazel index 01d54cd0a2..dcca1f3b06 100644 --- a/upup/pkg/fi/cloudup/terraform/BUILD.bazel +++ b/upup/pkg/fi/cloudup/terraform/BUILD.bazel @@ -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", ], ) diff --git a/upup/pkg/fi/cloudup/terraform/hcl2.go b/upup/pkg/fi/cloudup/terraform/hcl2.go index 959b193b03..bf06bbd49b 100644 --- a/upup/pkg/fi/cloudup/terraform/hcl2.go +++ b/upup/pkg/fi/cloudup/terraform/hcl2.go @@ -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("}")}, diff --git a/upup/pkg/fi/cloudup/terraform/hcl2_test.go b/upup/pkg/fi/cloudup/terraform/hcl2_test.go index 726f463ec0..648eba60a6 100644 --- a/upup/pkg/fi/cloudup/terraform/hcl2_test.go +++ b/upup/pkg/fi/cloudup/terraform/hcl2_test.go @@ -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) + } + }) + } +} From fb7fba01523be2b188c792ccdf8827eef5ef6241 Mon Sep 17 00:00:00 2001 From: Peter Rifel Date: Wed, 8 Apr 2020 21:19:18 -0500 Subject: [PATCH 3/4] Update GCE integration test output --- .../update_cluster/ha_gce/kubernetes.tf | 144 ++++++++++++++++++ .../update_cluster/minimal_gce/kubernetes.tf | 72 +++++++++ 2 files changed, 216 insertions(+) diff --git a/tests/integration/update_cluster/ha_gce/kubernetes.tf b/tests/integration/update_cluster/ha_gce/kubernetes.tf index 9bd73e5bec..bfbcb9a7a4 100644 --- a/tests/integration/update_cluster/ha_gce/kubernetes.tf +++ b/tests/integration/update_cluster/ha_gce/kubernetes.tf @@ -332,19 +332,163 @@ resource "google_compute_instance_group_manager" "c-nodes-ha-gce-example-com" { } resource "google_compute_instance_template" "master-us-test1-a-ha-gce-example-com" { + can_ip_forward = true + disk { + auto_delete = true + boot = true + device_name = "persistent-disks-0" + disk_name = "" + disk_size_gb = 64 + disk_type = "pd-standard" + interface = "" + mode = "READ_WRITE" + source = "" + source_image = "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-stable-57-9202-64-0" + type = "PERSISTENT" + } + machine_type = "n1-standard-1" + metadata = { + "cluster-name" = file("${path.module}/data/google_compute_instance_template_master-us-test1-a-ha-gce-example-com_metadata_cluster-name") + "kops-k8s-io-instance-group-name" = file("${path.module}/data/google_compute_instance_template_master-us-test1-a-ha-gce-example-com_metadata_kops-k8s-io-instance-group-name") + "ssh-keys" = file("${path.module}/data/google_compute_instance_template_master-us-test1-a-ha-gce-example-com_metadata_ssh-keys") + "startup-script" = file("${path.module}/data/google_compute_instance_template_master-us-test1-a-ha-gce-example-com_metadata_startup-script") + } name_prefix = "master-us-test1-a-ha-gce--ke5ah6-" + network_interface { + access_config { + } + network = google_compute_network.default.name + } + scheduling { + automatic_restart = true + on_host_maintenance = "MIGRATE" + preemptible = false + } + service_account { + email = "default" + scopes = ["https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/monitoring", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/devstorage.read_write", "https://www.googleapis.com/auth/ndev.clouddns.readwrite"] + } + tags = ["ha-gce-example-com-k8s-io-role-master"] } resource "google_compute_instance_template" "master-us-test1-b-ha-gce-example-com" { + can_ip_forward = true + disk { + auto_delete = true + boot = true + device_name = "persistent-disks-0" + disk_name = "" + disk_size_gb = 64 + disk_type = "pd-standard" + interface = "" + mode = "READ_WRITE" + source = "" + source_image = "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-stable-57-9202-64-0" + type = "PERSISTENT" + } + machine_type = "n1-standard-1" + metadata = { + "cluster-name" = file("${path.module}/data/google_compute_instance_template_master-us-test1-b-ha-gce-example-com_metadata_cluster-name") + "kops-k8s-io-instance-group-name" = file("${path.module}/data/google_compute_instance_template_master-us-test1-b-ha-gce-example-com_metadata_kops-k8s-io-instance-group-name") + "ssh-keys" = file("${path.module}/data/google_compute_instance_template_master-us-test1-b-ha-gce-example-com_metadata_ssh-keys") + "startup-script" = file("${path.module}/data/google_compute_instance_template_master-us-test1-b-ha-gce-example-com_metadata_startup-script") + } name_prefix = "master-us-test1-b-ha-gce--c8u7qq-" + network_interface { + access_config { + } + network = google_compute_network.default.name + } + scheduling { + automatic_restart = true + on_host_maintenance = "MIGRATE" + preemptible = false + } + service_account { + email = "default" + scopes = ["https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/monitoring", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/devstorage.read_write", "https://www.googleapis.com/auth/ndev.clouddns.readwrite"] + } + tags = ["ha-gce-example-com-k8s-io-role-master"] } resource "google_compute_instance_template" "master-us-test1-c-ha-gce-example-com" { + can_ip_forward = true + disk { + auto_delete = true + boot = true + device_name = "persistent-disks-0" + disk_name = "" + disk_size_gb = 64 + disk_type = "pd-standard" + interface = "" + mode = "READ_WRITE" + source = "" + source_image = "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-stable-57-9202-64-0" + type = "PERSISTENT" + } + machine_type = "n1-standard-1" + metadata = { + "cluster-name" = file("${path.module}/data/google_compute_instance_template_master-us-test1-c-ha-gce-example-com_metadata_cluster-name") + "kops-k8s-io-instance-group-name" = file("${path.module}/data/google_compute_instance_template_master-us-test1-c-ha-gce-example-com_metadata_kops-k8s-io-instance-group-name") + "ssh-keys" = file("${path.module}/data/google_compute_instance_template_master-us-test1-c-ha-gce-example-com_metadata_ssh-keys") + "startup-script" = file("${path.module}/data/google_compute_instance_template_master-us-test1-c-ha-gce-example-com_metadata_startup-script") + } name_prefix = "master-us-test1-c-ha-gce--3unp7l-" + network_interface { + access_config { + } + network = google_compute_network.default.name + } + scheduling { + automatic_restart = true + on_host_maintenance = "MIGRATE" + preemptible = false + } + service_account { + email = "default" + scopes = ["https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/monitoring", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/devstorage.read_write", "https://www.googleapis.com/auth/ndev.clouddns.readwrite"] + } + tags = ["ha-gce-example-com-k8s-io-role-master"] } resource "google_compute_instance_template" "nodes-ha-gce-example-com" { + can_ip_forward = true + disk { + auto_delete = true + boot = true + device_name = "persistent-disks-0" + disk_name = "" + disk_size_gb = 128 + disk_type = "pd-standard" + interface = "" + mode = "READ_WRITE" + source = "" + source_image = "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-stable-57-9202-64-0" + type = "PERSISTENT" + } + machine_type = "n1-standard-2" + metadata = { + "cluster-name" = file("${path.module}/data/google_compute_instance_template_nodes-ha-gce-example-com_metadata_cluster-name") + "kops-k8s-io-instance-group-name" = file("${path.module}/data/google_compute_instance_template_nodes-ha-gce-example-com_metadata_kops-k8s-io-instance-group-name") + "ssh-keys" = file("${path.module}/data/google_compute_instance_template_nodes-ha-gce-example-com_metadata_ssh-keys") + "startup-script" = file("${path.module}/data/google_compute_instance_template_nodes-ha-gce-example-com_metadata_startup-script") + } name_prefix = "nodes-ha-gce-example-com-" + network_interface { + access_config { + } + network = google_compute_network.default.name + } + scheduling { + automatic_restart = true + on_host_maintenance = "MIGRATE" + preemptible = false + } + service_account { + email = "default" + scopes = ["https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/monitoring", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/devstorage.read_only"] + } + tags = ["ha-gce-example-com-k8s-io-role-node"] } resource "google_compute_network" "default" { diff --git a/tests/integration/update_cluster/minimal_gce/kubernetes.tf b/tests/integration/update_cluster/minimal_gce/kubernetes.tf index 75306e3912..480a890d75 100644 --- a/tests/integration/update_cluster/minimal_gce/kubernetes.tf +++ b/tests/integration/update_cluster/minimal_gce/kubernetes.tf @@ -244,11 +244,83 @@ resource "google_compute_instance_group_manager" "a-nodes-minimal-gce-example-co } resource "google_compute_instance_template" "master-us-test1-a-minimal-gce-example-com" { + can_ip_forward = true + disk { + auto_delete = true + boot = true + device_name = "persistent-disks-0" + disk_name = "" + disk_size_gb = 64 + disk_type = "pd-standard" + interface = "" + mode = "READ_WRITE" + source = "" + source_image = "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-stable-57-9202-64-0" + type = "PERSISTENT" + } + machine_type = "n1-standard-1" + metadata = { + "cluster-name" = file("${path.module}/data/google_compute_instance_template_master-us-test1-a-minimal-gce-example-com_metadata_cluster-name") + "kops-k8s-io-instance-group-name" = file("${path.module}/data/google_compute_instance_template_master-us-test1-a-minimal-gce-example-com_metadata_kops-k8s-io-instance-group-name") + "ssh-keys" = file("${path.module}/data/google_compute_instance_template_master-us-test1-a-minimal-gce-example-com_metadata_ssh-keys") + "startup-script" = file("${path.module}/data/google_compute_instance_template_master-us-test1-a-minimal-gce-example-com_metadata_startup-script") + } name_prefix = "master-us-test1-a-minimal-do16cp-" + network_interface { + access_config { + } + network = google_compute_network.default.name + } + scheduling { + automatic_restart = true + on_host_maintenance = "MIGRATE" + preemptible = false + } + service_account { + email = "default" + scopes = ["https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/monitoring", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/devstorage.read_write", "https://www.googleapis.com/auth/ndev.clouddns.readwrite"] + } + tags = ["minimal-gce-example-com-k8s-io-role-master"] } resource "google_compute_instance_template" "nodes-minimal-gce-example-com" { + can_ip_forward = true + disk { + auto_delete = true + boot = true + device_name = "persistent-disks-0" + disk_name = "" + disk_size_gb = 128 + disk_type = "pd-standard" + interface = "" + mode = "READ_WRITE" + source = "" + source_image = "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-stable-57-9202-64-0" + type = "PERSISTENT" + } + machine_type = "n1-standard-2" + metadata = { + "cluster-name" = file("${path.module}/data/google_compute_instance_template_nodes-minimal-gce-example-com_metadata_cluster-name") + "kops-k8s-io-instance-group-name" = file("${path.module}/data/google_compute_instance_template_nodes-minimal-gce-example-com_metadata_kops-k8s-io-instance-group-name") + "ssh-keys" = file("${path.module}/data/google_compute_instance_template_nodes-minimal-gce-example-com_metadata_ssh-keys") + "startup-script" = file("${path.module}/data/google_compute_instance_template_nodes-minimal-gce-example-com_metadata_startup-script") + } name_prefix = "nodes-minimal-gce-example-com-" + network_interface { + access_config { + } + network = google_compute_network.default.name + } + scheduling { + automatic_restart = true + on_host_maintenance = "MIGRATE" + preemptible = false + } + service_account { + email = "default" + scopes = ["https://www.googleapis.com/auth/compute", "https://www.googleapis.com/auth/monitoring", "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/devstorage.read_only"] + } + tags = ["minimal-gce-example-com-k8s-io-role-node"] } resource "google_compute_network" "default" { From 2f098b3ac3568a65c42cf9485355398ed2edc130 Mon Sep 17 00:00:00 2001 From: Peter Rifel Date: Wed, 8 Apr 2020 21:19:31 -0500 Subject: [PATCH 4/4] Make verify-terraform script blocking now that it passes --- hack/verify-terraform.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hack/verify-terraform.sh b/hack/verify-terraform.sh index be3ea0e605..d53f5c2a15 100755 --- a/hack/verify-terraform.sh +++ b/hack/verify-terraform.sh @@ -41,9 +41,7 @@ done 3< <(find "${KOPS_ROOT}/tests/integration/update_cluster" -type d -maxdepth if [ $RC != 0 ]; then echo -e "\nTerraform validation failed\n" - # TODO(rifelpet): make this script blocking in PRs by exiting non-zero on failure - # exit $RC - exit 0 + exit $RC else echo -e "\nTerraform validation succeeded\n" fi