Last active
April 16, 2019 14:29
-
-
Save owulveryck/fb0a64f92ccc18cf1b250e824f7c5d9e to your computer and use it in GitHub Desktop.
terraform tfvars diff: do a diff against two tfvars and returns an error if they do not contain the same variables.
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
package main | |
import ( | |
"flag" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"os" | |
"github.com/hashicorp/hcl" | |
) | |
var ( | |
file1 string | |
file2 string | |
) | |
func main() { | |
silent := flag.Bool("s", false, "silent mode") | |
flag.Parse() | |
args := flag.Args() | |
if len(args) != 2 { | |
usage() | |
return | |
} | |
file1 = args[0] | |
file2 = args[1] | |
content1, err := ioutil.ReadFile(file1) | |
if err != nil { | |
log.Fatal(err) | |
} | |
content2, err := ioutil.ReadFile(file2) | |
if err != nil { | |
log.Fatal(err) | |
} | |
receiver1, err := parseContent(content1) | |
if err != nil { | |
log.Fatal(err) | |
} | |
receiver2, err := parseContent(content2) | |
if err != nil { | |
log.Fatal(err) | |
} | |
err = diffKeys(receiver1, receiver2, false) | |
if err != nil { | |
if *silent { | |
os.Exit(1) | |
} | |
log.Fatal(err) | |
} | |
} | |
func usage() { | |
fmt.Printf("usage: %v [-s] file1 file2", os.Args[0]) | |
} | |
func parseContent(b []byte) (map[string]interface{}, error) { | |
var output map[string]interface{} | |
err := hcl.Unmarshal(b, &output) | |
if err != nil { | |
return nil, fmt.Errorf("cannot parse content: %v", err) | |
} | |
return output, nil | |
} | |
func diffKeys(receiver1, receiver2 map[string]interface{}, stop bool) error { | |
for k, v1 := range receiver1 { | |
var v2 interface{} | |
var ok bool | |
if v2, ok = receiver2[k]; !ok { | |
return fmt.Errorf("variable %v is defined in one file but not the other", k) | |
} | |
if reflect.ValueOf(v1).Kind() != reflect.ValueOf(v2).Kind() { | |
return fmt.Errorf("%v is of type %v in one file and %v in the other", k, reflect.ValueOf(v1).Kind(), reflect.ValueOf(v2).Kind()) | |
} | |
val1, ok1 := v1.([]map[string]interface{}) | |
val2, ok2 := v2.([]map[string]interface{}) | |
switch { | |
case ok1 && ok2: | |
if len(val1) != len(val2) { | |
return fmt.Errorf("array's size differs") | |
} | |
for i := 0; i < len(val1); i++ { | |
return diffKeys(val1[i], val2[i], false) | |
} | |
case ok1 != ok2: | |
return fmt.Errorf("different types") | |
} | |
} | |
if stop { | |
return nil | |
} | |
return diffKeys(receiver2, receiver1, true) | |
} | |
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
package main | |
import "testing" | |
func TestDivKeys_ok(t *testing.T) { | |
valid1 := []byte(` | |
b = 1 | |
c = { | |
bla = "truc" | |
d = { | |
aha = "b" | |
} | |
} | |
`) | |
valid2 := []byte(` | |
b = 4 | |
c = { | |
bla = "blo" | |
d = { | |
aha = "b" | |
} | |
} | |
`) | |
receiver1, err := parseContent(valid1) | |
if err != nil { | |
t.Fatal(err) | |
} | |
receiver2, err := parseContent(valid2) | |
if err != nil { | |
t.Fatal(err) | |
} | |
err = diffKeys(receiver1, receiver2, false) | |
if err != nil { | |
t.Fatal(err) | |
} | |
} | |
func TestDivKeys_koType(t *testing.T) { | |
valid1 := []byte(` | |
b = 1 | |
c = { | |
bla = "truc" | |
d = { | |
aha = "b" | |
} | |
} | |
`) | |
valid2 := []byte(` | |
b = 4 | |
c = { | |
bla = true | |
d = { | |
aha = "b" | |
} | |
} | |
`) | |
receiver1, err := parseContent(valid1) | |
if err != nil { | |
t.Fatal(err) | |
} | |
receiver2, err := parseContent(valid2) | |
if err != nil { | |
t.Fatal(err) | |
} | |
err = diffKeys(receiver1, receiver2, false) | |
if err == nil { | |
t.Fatal("should have failed because types defers") | |
} | |
} | |
func TestDivKeys_ko1(t *testing.T) { | |
valid1 := []byte(` | |
b = 1 | |
c = { | |
bla = "truc" | |
d = "aha" | |
} | |
`) | |
valid2 := []byte(` | |
b = 4 | |
c = { | |
bla = true | |
d = { | |
aha = "b" | |
} | |
} | |
`) | |
receiver1, err := parseContent(valid1) | |
if err != nil { | |
t.Fatal(err) | |
} | |
receiver2, err := parseContent(valid2) | |
if err != nil { | |
t.Fatal(err) | |
} | |
err = diffKeys(receiver2, receiver1, false) | |
if err == nil { | |
t.Fatalf("%v should be different from %v and return an error", receiver1, receiver2) | |
} | |
} | |
func TestDivKeys_ko2(t *testing.T) { | |
valid1 := []byte(` | |
c = { | |
bla = "truc" | |
d = "aha" | |
} | |
f = ["a","b"] | |
`) | |
valid2 := []byte(` | |
c = "bla" | |
`) | |
receiver1, err := parseContent(valid1) | |
if err != nil { | |
t.Fatal(err) | |
} | |
receiver2, err := parseContent(valid2) | |
if err != nil { | |
t.Fatal(err) | |
} | |
err = diffKeys(receiver1, receiver2, false) | |
if err == nil { | |
t.Fatalf("%v should be different from %v and return an error", receiver1, receiver2) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment