Skip to content

Commit

Permalink
WIP: kubernetes#7052 TF 12 feature flagged - update output support
Browse files Browse the repository at this point in the history
  • Loading branch information
fred-vogt committed Nov 16, 2019
1 parent 07adf0c commit 8380412
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 21 deletions.
1 change: 1 addition & 0 deletions docs/advanced/experimental.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The following experimental features are currently available:
* `+EnableExternalDNS` - Enable external-dns with default settings (ingress sources only).
* `+VPCSkipEnableDNSSupport` - Enables creation of a VPC that does not need DNSSupport enabled.
* `+SkipTerraformFormat` - Do not `terraform fmt` the generated terraform files.
* `+Terraform012` - Use HCL2 output for terraform versions 0.12+.
* `+EnableExternalCloudController` - Enables the use of cloud-controller-manager introduced in v1.7.
* `+EnableSeparateConfigBase` - Allow a config-base that is different from the state store.
* `+SpecOverrideFlag` - Allow setting spec values on `kops create`.
Expand Down
2 changes: 2 additions & 0 deletions pkg/featureflag/featureflag.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ var (
// In particular, this is the only (?) way to grant the bucket.list permission
// It allows for experiments with alternative DNS configurations - in particular local proxies.
SkipTerraformFormat = New("SkipTerraformFormat", Bool(false))
// Enable TF 0.12.x update -target=terraform output
Terraform012 = New("Terraform012", Bool(false))
// SpecOverrideFlag allows setting spec values on create
SpecOverrideFlag = New("SpecOverrideFlag", Bool(false))
// Spotinst toggles the use of Spotinst integration.
Expand Down
33 changes: 17 additions & 16 deletions upup/pkg/fi/cloudup/terraform/hcl_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,25 @@ import (
"fmt"
"strings"

"github.com/hashicorp/hcl/hcl/ast"
hcl_printer "github.com/hashicorp/hcl/hcl/printer"
hcl1_ast "github.com/hashicorp/hcl/hcl/ast"
hcl1_printer "github.com/hashicorp/hcl/hcl/printer"

"k8s.io/klog"
"k8s.io/kops/pkg/featureflag"
)

const safeChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"

// sanitizer fixes up an invalid HCL AST, as produced by the HCL parser for JSON
type astSanitizer struct {
type hcl1_astSanitizer struct {
}

// output prints creates b printable HCL output and returns it.
func (v *astSanitizer) visit(n interface{}) {
func (v *hcl1_astSanitizer) visit(n interface{}) {
switch t := n.(type) {
case *ast.File:
case *hcl1_ast.File:
v.visit(t.Node)
case *ast.ObjectList:
case *hcl1_ast.ObjectList:
var index int
for {
if index == len(t.Items) {
Expand All @@ -48,20 +49,20 @@ func (v *astSanitizer) visit(n interface{}) {
v.visit(t.Items[index])
index++
}
case *ast.ObjectKey:
case *ast.ObjectItem:
case *hcl1_ast.ObjectKey:
case *hcl1_ast.ObjectItem:
v.visitObjectItem(t)
case *ast.LiteralType:
case *ast.ListType:
case *ast.ObjectType:
case *hcl1_ast.LiteralType:
case *hcl1_ast.ListType:
case *hcl1_ast.ObjectType:
v.visit(t.List)
default:
klog.Warningf(" unknown type: %T\n", n)
}

}

func (v *astSanitizer) visitObjectItem(o *ast.ObjectItem) {
func (v *hcl1_astSanitizer) visitObjectItem(o *hcl1_ast.ObjectItem) {
for i, k := range o.Keys {
if i == 0 {
text := k.Token.Text
Expand All @@ -88,12 +89,12 @@ func (v *astSanitizer) visitObjectItem(o *ast.ObjectItem) {
v.visit(o.Val)
}

func hclPrint(node ast.Node) ([]byte, error) {
var sanitizer astSanitizer
func hcl1Print(node hcl1_ast.Node) ([]byte, error) {
var sanitizer hcl1_astSanitizer
sanitizer.visit(node)

var b bytes.Buffer
err := hcl_printer.Fprint(&b, node)
err := hcl1_printer.Fprint(&b, node)
if err != nil {
return nil, fmt.Errorf("error writing HCL: %v", err)
}
Expand All @@ -120,7 +121,7 @@ func hclPrint(node ast.Node) ([]byte, error) {
}

// Apply Terraform style (alignment etc.)
formatted, err := hcl_printer.Format([]byte(s))
formatted, err := hcl1_printer.Format([]byte(s))
if err != nil {
klog.Errorf("Invalid HCL follows:")
for i, line := range strings.Split(s, "\n") {
Expand Down
18 changes: 13 additions & 5 deletions upup/pkg/fi/cloudup/terraform/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ import (
"strings"
"sync"

hcl_parser "github.com/hashicorp/hcl/json/parser"
hcl1_parser "github.com/hashicorp/hcl/json/parser"

"k8s.io/klog"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/pkg/featureflag"
)

type TerraformTarget struct {
Expand Down Expand Up @@ -255,9 +257,15 @@ func (t *TerraformTarget) Finish(taskMap map[string]fi.Task) error {
}
}

// See https://github.com/kubernetes/kops/pull/2424 for why we require 0.9.3
terraformConfiguration := make(map[string]interface{})
terraformConfiguration["required_version"] = ">= 0.9.3"
if featureflag.Terraform012.Enabled() {
// TF 12 / HCL2 is not the default yet
klog.Infof("feature-flag Terraform012 was set; terraform required_version >= 0.12.0")
terraformConfiguration["required_version"] = ">= 0.12.0"
} else {
// See https://github.com/kubernetes/kops/pull/2424 for why we require 0.9.3
terraformConfiguration["required_version"] = ">= 0.9.3"
}

data := make(map[string]interface{})
data["terraform"] = terraformConfiguration
Expand All @@ -282,12 +290,12 @@ func (t *TerraformTarget) Finish(taskMap map[string]fi.Task) error {
if useJson {
t.files["kubernetes.tf"] = jsonBytes
} else {
f, err := hcl_parser.Parse(jsonBytes)
ast, err := hcl1_parser.Parse(jsonBytes)
if err != nil {
return fmt.Errorf("error parsing terraform json: %v", err)
}

b, err := hclPrint(f)
b, err := hcl1Print(ast)
if err != nil {
return fmt.Errorf("error writing terraform data to output: %v", err)
}
Expand Down

0 comments on commit 8380412

Please sign in to comment.