Skip to content

Commit

Permalink
Adds logic for writing out k8s object as heredoc in contentssection o…
Browse files Browse the repository at this point in the history
…f resource block
  • Loading branch information
sebradloff committed Apr 21, 2020
1 parent 663e21e commit c423f92
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 34 deletions.
83 changes: 52 additions & 31 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
"path/filepath"
"strings"

"github.com/hashicorp/hcl2/gohcl"
yaml2 "github.com/ghodss/yaml"
"github.com/hashicorp/hcl2/hcl/hclsyntax"
"github.com/hashicorp/hcl2/hclwrite"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -48,64 +49,84 @@ var rootCmd = &cobra.Command{
filesToTransform = append(filesToTransform, k8sFile)
}

type resource struct {
K8sManifest string `hcl:"k8s_manifest,label"`
Name string `hcl:"name,label"`
Content string `hcl:"content"`
}
type tfStruct struct {
Resources []resource `hcl:"resource,block"`
}

var tfRes tfStruct
tfFile := hclwrite.NewEmptyFile()
rootBody := tfFile.Body()
// write hcl to tf file
defer tfFile.Body().Clear()

for _, f := range filesToTransform {
fmt.Println("****" + f)

data, err := ioutil.ReadFile(f)
if err != nil {
return fmt.Errorf("could not ioutil.ReadFile(%s); err = %v", f, err)
}

var objects []*unstructured.Unstructured
decoder := yaml.NewYAMLOrJSONDecoder(strings.NewReader(string(data)), 4096)

// allows us to capture yaml streams
for {
var object *unstructured.Unstructured

err = decoder.Decode(&object)
var o *unstructured.Unstructured
// decode one yaml strem into a k8s object
err = decoder.Decode(&o)
if err != nil && err != io.EOF {
return fmt.Errorf("Failed to unmarshal manifest: %s", err)
return fmt.Errorf("Failed to unmarshal manifest: %v", err)
}
if err == io.EOF {
break
}

objects = append(objects, object)
}

for _, v := range objects {
res := resource{
K8sManifest: "k8s_manifest",
Name: v.GetName(),
Content: "cool2",
objectJSON, err := o.MarshalJSON()
if err != nil {
return fmt.Errorf("Failed to marshall one object into json: %v", err)
}
objectYaml, err := yaml2.JSONToYAML(objectJSON)
if err != nil {
return fmt.Errorf("Failed to marshall one object json into yaml: %v", err)
}

tfRes.Resources = append(tfRes.Resources, res)
ns := o.GetNamespace()
if ns == "" {
ns = "default"
}
groupVersion := strings.Replace(o.GroupVersionKind().GroupVersion().String(), "/", "_", -1)
resourceName := strings.Join([]string{ns, groupVersion, o.GetKind(), o.GetName()}, "-")

contentBytes := []byte("<<EOT\n")
contentBytes = append(contentBytes, objectYaml...)
contentBytes = append(contentBytes, []byte("EOT\n")...)

// create tf resource block
resourceBlock := rootBody.AppendNewBlock("resource", []string{"k8s_manifest", resourceName})

tokens := hclwrite.Tokens{

{
Type: hclsyntax.TokenTabs,
},
{
Type: hclsyntax.TokenCQuote,
Bytes: []byte("content = "),
},
{
Type: hclsyntax.TokenOHeredoc,
Bytes: contentBytes,
},
{
Type: hclsyntax.TokenNewline,
},
}
resourceBlock.Body().BuildTokens(tokens)
resourceBlock.Body().AppendUnstructuredTokens(tokens)
rootBody.AppendNewline()
}
}

f := hclwrite.NewEmptyFile()
gohcl.EncodeIntoBody(&tfRes, f.Body())
defer f.Body().Clear()

oF, err := os.Create(outputFile)
if err != nil {
return fmt.Errorf("could not os.Create(%s); err = %v", outputFile, err)
}
defer oF.Close()
_, err = f.WriteTo(oF)
_, err = tfFile.WriteTo(oF)
if err != nil {
return fmt.Errorf("could not write to file %s; err = %v", oF.Name(), err)
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ func TestRoot(t *testing.T) {
"One file with one kubernetes object": {
k8sFileName: "one-obj",
},
"One file with multiple kubernetes objects": {
k8sFileName: "multiple-objs",
},
}

for name, tc := range tests {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.14

require (
github.com/agext/levenshtein v1.2.2 // indirect
github.com/ghodss/yaml v1.0.0
github.com/hashicorp/hcl2 v0.0.0-20191002203319-fb75b3253c80
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
Expand Down
46 changes: 46 additions & 0 deletions testdata/golden/multiple-objs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
resource "k8s_manifest" "default-apps_v1-Deployment-nginx-deployment" {
content = <<EOT
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.7.9
name: nginx
ports:
- containerPort: 80
EOT
}

resource "k8s_manifest" "default-v1-Service-nginx" {
content = <<EOT
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
spec:
clusterIP: ""
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app: nginx
EOT
}

28 changes: 25 additions & 3 deletions testdata/golden/one-obj.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@

resource "k8s_manifest" "nginx-deployment" {
content = "cool2"
resource "k8s_manifest" "default-apps_v1-Deployment-nginx-deployment" {
content = <<EOT
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.7.9
name: nginx
ports:
- containerPort: 80
EOT
}

37 changes: 37 additions & 0 deletions testdata/k8s-files/multiple-objs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx
spec:
clusterIP: ""
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app: nginx

0 comments on commit c423f92

Please sign in to comment.