-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrites hcl transformation logic into another package
- Loading branch information
1 parent
c423f92
commit ee6bb03
Showing
4 changed files
with
270 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package hcl | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/ghodss/yaml" | ||
"github.com/hashicorp/hcl/v2/hclsyntax" | ||
"github.com/hashicorp/hcl/v2/hclwrite" | ||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
) | ||
|
||
type HCLFile struct { | ||
file *hclwrite.File | ||
rootBody *hclwrite.Body | ||
} | ||
|
||
func NewHCLFile() *HCLFile { | ||
f := hclwrite.NewEmptyFile() | ||
return &HCLFile{ | ||
file: f, | ||
rootBody: f.Body(), | ||
} | ||
} | ||
|
||
func (f *HCLFile) GetFileBytes() []byte { | ||
return f.file.Bytes() | ||
} | ||
|
||
func (f *HCLFile) GetFileRootBody() *hclwrite.Body { | ||
return f.rootBody | ||
} | ||
|
||
func (f *HCLFile) K8sObjectToResourceBlock(o *unstructured.Unstructured) error { | ||
oJSON, err := o.MarshalJSON() | ||
if err != nil { | ||
return fmt.Errorf("Failed to marshall one object into json: %v", err) | ||
} | ||
oYaml, err := yaml.JSONToYAML(oJSON) | ||
if err != nil { | ||
return fmt.Errorf("Failed to marshall one object json into yaml: %v", err) | ||
} | ||
|
||
ns := o.GetNamespace() | ||
if ns == "" { | ||
ns = "default" | ||
} | ||
groupVersion := strings.Replace(o.GetAPIVersion(), "/", "_", -1) | ||
resourceName := strings.Join([]string{ns, groupVersion, o.GetKind(), o.GetName()}, "-") | ||
|
||
contentBytes := []byte("<<EOT\n") | ||
contentBytes = append(contentBytes, oYaml...) | ||
contentBytes = append(contentBytes, []byte("EOT\n")...) | ||
|
||
// create tf resource block | ||
resourceBlock := f.rootBody.AppendNewBlock("resource", []string{"k8s_manifest", resourceName}) | ||
|
||
tokens := hclwrite.Tokens{ | ||
{ | ||
Type: hclsyntax.TokenOHeredoc, | ||
Bytes: contentBytes, | ||
}, | ||
} | ||
|
||
bT := resourceBlock.Body().BuildTokens(tokens) | ||
resourceBlock.Body().SetAttributeRaw("content", bT) | ||
f.rootBody.AppendNewline() | ||
|
||
return nil | ||
} | ||
|
||
func (hF *HCLFile) WriteToFile(path string) error { | ||
f, err := os.Create(path) | ||
if err != nil { | ||
return fmt.Errorf("could not os.Create(%s); err = %v", path, err) | ||
} | ||
defer f.Close() | ||
|
||
_, err = hF.file.WriteTo(f) | ||
if err != nil { | ||
return fmt.Errorf("could not write to file %s; err = %v", f.Name(), err) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package hcl_test | ||
|
||
import ( | ||
"bytes" | ||
"flag" | ||
"fmt" | ||
"io/ioutil" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/hashicorp/hcl/v2" | ||
"github.com/hashicorp/hcl/v2/hclwrite" | ||
h "github.com/sebradloff/rawk8stfc/pkg/hcl" | ||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
) | ||
|
||
var ( | ||
updateFlag bool | ||
) | ||
|
||
func init() { | ||
flag.BoolVar(&updateFlag, "update", false, "Set this flag to update the golden files.") | ||
} | ||
|
||
func TestHCLFile_K8sObjectToResourceBlock(t *testing.T) { | ||
// given | ||
f := h.NewHCLFile() | ||
var o unstructured.Unstructured | ||
o.SetAPIVersion("apps/v1") | ||
o.SetKind("Deployment") | ||
o.SetName("test-1") | ||
o.SetNamespace("test-1") | ||
//when | ||
err := f.K8sObjectToResourceBlock(&o) | ||
if err != nil { | ||
t.Fatalf("asdfsdf %v", err) | ||
} | ||
|
||
//then | ||
goldenFile := filepath.Join("test-fixtures", fmt.Sprintf("%s.hcl", "test-1")) | ||
if updateFlag { | ||
err := f.WriteToFile(goldenFile) | ||
if err != nil { | ||
t.Fatalf("could not update golden file %s; err = %v", goldenFile, err) | ||
} | ||
} | ||
|
||
wantBytes, err := ioutil.ReadFile(goldenFile) | ||
if err != nil { | ||
t.Fatalf("failed to read the goldenFile file: %s. err = %v", goldenFile, err) | ||
} | ||
|
||
wF, diags := hclwrite.ParseConfig(wantBytes, goldenFile, hcl.InitialPos) | ||
if diags.HasErrors() { | ||
for _, diag := range diags { | ||
if diag.Subject != nil { | ||
fmt.Printf("[%s:%d] %s: %s", diag.Subject.Filename, diag.Subject.Start.Line, diag.Summary, diag.Detail) | ||
} else { | ||
fmt.Printf("%s: %s", diag.Summary, diag.Detail) | ||
} | ||
} | ||
} | ||
|
||
f.GetFileRootBody() | ||
|
||
if len(f.GetFileRootBody().Blocks()) != 1 { | ||
t.Fatalf("got more than one block %d; want %d", len(f.GetFileRootBody().Blocks()), 1) | ||
} | ||
|
||
for _, block := range f.GetFileRootBody().Blocks() { | ||
wantType := "resource" | ||
if block.Type() != wantType { | ||
t.Errorf("block type = %s; want %s", block.Type(), wantType) | ||
} | ||
|
||
if len(block.Labels()) != 2 { | ||
t.Fatalf("block labels len(%d); want 2", len(block.Labels())) | ||
} | ||
wantFirstLabel := "k8s_manifest" | ||
if block.Labels()[0] != wantFirstLabel { | ||
t.Errorf("first block label = %s; want %s", block.Labels()[0], wantFirstLabel) | ||
} | ||
|
||
wantAttr := "content" | ||
attr := block.Body().GetAttribute(wantAttr) | ||
if attr == nil { | ||
t.Errorf("got no body attribue; want attribute %s", wantAttr) | ||
} | ||
} | ||
|
||
if !bytes.Equal(f.GetFileBytes(), wF.Bytes()) { | ||
t.Errorf("the file bytes do not match the golden file bytes (%s)", goldenFile) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package hcl | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/hashicorp/hcl/v2/hclwrite" | ||
) | ||
|
||
func Test_HCLFile_WriteToFile(t *testing.T) { | ||
type checkFn func(*testing.T, *HCLFile, string, error) | ||
check := func(fns ...checkFn) []checkFn { return fns } | ||
|
||
hasNoErr := func() checkFn { | ||
return func(t *testing.T, f *HCLFile, outputFilePath string, err error) { | ||
if err != nil { | ||
t.Fatalf("err = %v; want nil", err) | ||
} | ||
} | ||
} | ||
|
||
fileExistsWithRightNumOfBytes := func() checkFn { | ||
return func(t *testing.T, f *HCLFile, outputFilePath string, err error) { | ||
oF, err := os.Stat(outputFilePath) | ||
if err != nil { | ||
t.Fatalf("error checking on file %s; err = %v", outputFilePath, oF) | ||
} | ||
|
||
if !oF.Mode().IsRegular() { | ||
t.Fatalf("%s is not a file", outputFilePath) | ||
} | ||
|
||
if int64(len(f.GetFileBytes())) != oF.Size() { | ||
t.Errorf("the created file (%s) does not have the same number of bytes as the HCLFile", outputFilePath) | ||
} | ||
} | ||
} | ||
|
||
tests := map[string]struct { | ||
numOfResources int | ||
checks []checkFn | ||
}{ | ||
"one resource": { | ||
numOfResources: 1, | ||
checks: check(hasNoErr(), fileExistsWithRightNumOfBytes()), | ||
}, | ||
"two resources": { | ||
numOfResources: 2, | ||
checks: check(hasNoErr(), fileExistsWithRightNumOfBytes()), | ||
}, | ||
"zero resources": { | ||
numOfResources: 0, | ||
checks: check(hasNoErr(), fileExistsWithRightNumOfBytes()), | ||
}, | ||
} | ||
|
||
for name, tc := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
hf := hclwrite.NewEmptyFile() | ||
f := &HCLFile{ | ||
file: hf, | ||
rootBody: hf.Body(), | ||
} | ||
|
||
for i := 0; i < tc.numOfResources; i++ { | ||
f.file.Body().AppendNewBlock("test", []string{"t1", strconv.Itoa(i)}) | ||
} | ||
|
||
outputFilePath := filepath.Join(os.TempDir(), fmt.Sprintf("%s.hcl", name)) | ||
|
||
err := f.WriteToFile(outputFilePath) | ||
for _, check := range tc.checks { | ||
check(t, f, outputFilePath, err) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
resource "k8s_manifest" "test-1-apps_v1-Deployment-test-1" { | ||
content = <<EOT | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: test-1 | ||
namespace: test-1 | ||
EOT | ||
|
||
} | ||
|