Repository: aws-cloudformation/rain (go)

Issue:
Format bug with Fn::GetAZs empty string
```yaml
  PrivateSubnet1Subnet:
    Type: AWS::EC2::Subnet
    Properties:
    AvailabilityZone: !Select [0, Fn::GetAZs: ""]
    CidrBlock: 10.0.128.0/18
    MapPublicIpOnLaunch: false
    VpcId: !Ref VPC
```

The empty string (which means the same as AWS::Region) is converted to null

```
(|) Resources:
(|)   PrivateSubnet1Subnet:
(|)     Properties:
(|)       AvailabilityZone:
(|)         Fn::Select:
(|)           [1]:
(>)             Fn::GetAZs: null
```

Pull request description:
Fix format bug with empty string and null
Fixes #273

Patch:
diff --git a/cft/diff/compare.go b/cft/diff/compare.go
index 9526947f..3e3b16ec 100644
--- a/cft/diff/compare.go
+++ b/cft/diff/compare.go
@@ -14,6 +14,12 @@ func New(a, b cft.Template) Diff {
 
 func compareValues(old, new interface{}) Diff {
 	if reflect.TypeOf(old) != reflect.TypeOf(new) {
+
+		// In YAML there is no difference between "" and null
+		if old == "" && new == nil {
+			return value{new, Unchanged}
+		}
+
 		return value{new, Changed}
 	}
 
diff --git a/cft/format/format.go b/cft/format/format.go
index 213ca644..4b045ef9 100644
--- a/cft/format/format.go
+++ b/cft/format/format.go
@@ -33,8 +33,6 @@ func CheckMultilineBegin(s string) bool {
 func String(t cft.Template, opt Options) string {
 	node := t.Node
 
-	// config.Debugf("%v", rnode.ToSJson(node))
-
 	buf := strings.Builder{}
 	enc := yaml.NewEncoder(&buf)
 	enc.SetIndent(2)
diff --git a/cft/format/transform.go b/cft/format/transform.go
index 433b32f1..9bc5cb15 100644
--- a/cft/format/transform.go
+++ b/cft/format/transform.go
@@ -28,6 +28,7 @@ func formatNode(n *yaml.Node) *yaml.Node {
 	if n.Kind == yaml.MappingNode {
 		// Does it have just one key/value pair?
 		if len(n.Content) == 2 {
+
 			// Is the key relevant?
 			for tag, funcName := range cft.Tags {
 				if n.Content[0].Value == funcName {
@@ -85,6 +86,7 @@ func formatNode(n *yaml.Node) *yaml.Node {
 					n.Style = newNode.Content[0].Style
 				}
 			}
+
 		}
 	}
 


Test patch:
diff --git a/cft/format/format_test.go b/cft/format/format_test.go
index c59d1919..ef15537a 100644
--- a/cft/format/format_test.go
+++ b/cft/format/format_test.go
@@ -717,3 +717,46 @@ Parameters:
 	}
 
 }
+
+func TestFnGetAZs(t *testing.T) {
+	input := `
+Resources:
+  PrivateSubnet1Subnet:
+    Type: AWS::EC2::Subnet
+    Properties:
+      AvailabilityZone: !Select
+        - 0
+        - !GetAZs ""
+`
+
+	// Parse the template
+	source, err := parse.String(string(input))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	output := format.String(source, format.Options{
+		JSON:     false,
+		Unsorted: true,
+	})
+
+	// Verify the output is valid
+	if err = parse.Verify(source, output); err != nil {
+		t.Fatal(err)
+	}
+
+	expected := `
+Resources:
+  PrivateSubnet1Subnet:
+    Type: AWS::EC2::Subnet
+    Properties:
+      AvailabilityZone: !Select
+        - 0
+        - !GetAZs 
+`
+
+	if strings.TrimSpace(output) != strings.TrimSpace(expected) {
+		t.Fatalf("Got:\n%s\n\nExpected:\n%s", output, expected)
+	}
+
+}
diff --git a/test/templates/getazs-null.yaml b/test/templates/getazs-null.yaml
new file mode 100644
index 00000000..76f7c781
--- /dev/null
+++ b/test/templates/getazs-null.yaml
@@ -0,0 +1,13 @@
+Parameters:
+  VpcId:
+    Type: String
+
+Resources:
+
+  PrivateSubnet1Subnet:
+    Type: AWS::EC2::Subnet
+    Properties:
+      AvailabilityZone: !Select
+        - 0
+        - !GetAZs ""
+      VpcId: !Ref VpcId