Repository: zalando-incubator/kube-ingress-aws-controller
Pull request #614 (2023-06-14 15:01:16)

Add some more goldenfile tests
Follow up on https://github.com/zalando-incubator/kube-ingress-aws-controller/pull/587 for better coverage.

lucastt: So, when reading the expected CF templates I noticed something weird, they seem to reference values that would be received as parameters, but there is no place showing the values of these parameters. To confirm my theory I executed a vimdiff between both expected files: `testdata/ingress_rg_shared_alb/expected.cf` and `testdata/ingress_rg_notshared_alb/expected.cf` and they yield no diff, meaning they are exactly the same.

When I created the structure of these tests I didn't notice it because I just made two simple tests, on creating ALB and the other creating NLB, which yield different templates. But now I see there may be a problem in the way I built these golden file tests. 🤔 

Did I get something wrong?
lucastt: > So, when reading the expected CF templates I noticed something weird, they seem to reference values that would be received as parameters, but there is no place showing the values of these parameters. To confirm my theory I executed a vimdiff between both expected files: `testdata/ingress_rg_shared_alb/expected.cf` and `testdata/ingress_rg_notshared_alb/expected.cf` and they yield no diff, meaning they are exactly the same.
> 
> When I created the structure of these tests I didn't notice it because I just made two simple tests, on creating ALB and the other creating NLB, which yield different templates. But now I see there may be a problem in the way I built these golden file tests. 🤔
> 
> Did I get something wrong?

Created a new issue for this. https://github.com/zalando-incubator/kube-ingress-aws-controller/issues/626
lucastt: 👍 
szuecs: @MustafaSaber the changes are great progress for tests!
If you do nonshared / share, please keep routegroup in ingress with annotations in-sync.
You can change the .kube file (at least in skipper tests) to configure the defaults of the controller and then test defaults, too. From my pov, to merge the only thing to make sure is that the tests are consistent in their annotation use.
MustafaSaber: Thanks @lucastt for taking over 🙏!
lucastt: 👍 
szuecs: :+1: 

Patch:
diff --git a/aws/fake/cf.go b/aws/fake/cf.go
index 8c269de..48ed579 100644
--- a/aws/fake/cf.go
+++ b/aws/fake/cf.go
@@ -17,22 +17,28 @@ type CFOutputs struct {
 
 type CFClient struct {
 	cloudformationiface.CloudFormationAPI
-	lastStackTemplate string
-	lastStackParams   []*cloudformation.Parameter
-	lastStackTags     []*cloudformation.Tag
-	Outputs           CFOutputs
+	templateCreationHistory []string
+	paramCreationHistory    [][]*cloudformation.Parameter
+	tagCreationHistory      [][]*cloudformation.Tag
+	Outputs                 CFOutputs
 }
 
-func (m *CFClient) GetLastStackTemplate() string {
-	return m.lastStackTemplate
+func (m *CFClient) GetTemplateCreationHistory() []string {
+	return m.templateCreationHistory
 }
 
-func (m *CFClient) GetLastStackParams() []*cloudformation.Parameter {
-	return m.lastStackParams
+func (m *CFClient) GetParamCreationHistory() [][]*cloudformation.Parameter {
+	return m.paramCreationHistory
 }
 
-func (m *CFClient) GetLastStackTags() []*cloudformation.Tag {
-	return m.lastStackTags
+func (m *CFClient) GetTagCreationHistory() [][]*cloudformation.Tag {
+	return m.tagCreationHistory
+}
+
+func (m *CFClient) CleanCreationHistory() {
+	m.paramCreationHistory = [][]*cloudformation.Parameter{}
+	m.tagCreationHistory = [][]*cloudformation.Tag{}
+	m.templateCreationHistory = []string{}
 }
 
 func (m *CFClient) DescribeStacksPages(in *cloudformation.DescribeStacksInput, fn func(*cloudformation.DescribeStacksOutput, bool) bool) (err error) {
@@ -62,9 +68,9 @@ func (m *CFClient) DescribeStacks(in *cloudformation.DescribeStacksInput) (*clou
 }
 
 func (m *CFClient) CreateStack(params *cloudformation.CreateStackInput) (*cloudformation.CreateStackOutput, error) {
-	m.lastStackTags = params.Tags
-	m.lastStackParams = params.Parameters
-	m.lastStackTemplate = *params.TemplateBody
+	m.tagCreationHistory = append(m.tagCreationHistory, params.Tags)
+	m.paramCreationHistory = append(m.paramCreationHistory, params.Parameters)
+	m.templateCreationHistory = append(m.templateCreationHistory, *params.TemplateBody)
 
 	out, ok := m.Outputs.CreateStack.response.(*cloudformation.CreateStackOutput)
 	if !ok {
@@ -80,9 +86,9 @@ func MockCSOutput(stackId string) *cloudformation.CreateStackOutput {
 }
 
 func (m *CFClient) UpdateStack(params *cloudformation.UpdateStackInput) (*cloudformation.UpdateStackOutput, error) {
-	m.lastStackTags = params.Tags
-	m.lastStackParams = params.Parameters
-	m.lastStackTemplate = *params.TemplateBody
+	// TODO: https://github.com/zalando-incubator/kube-ingress-aws-controller/issues/653
+	// Update stack needs to use different variable to register change history,
+	// so createStack and updateStack mocks don't mess with each other states.
 
 	out, ok := m.Outputs.UpdateStack.response.(*cloudformation.UpdateStackOutput)
 	if !ok {


Test patch:
diff --git a/testdata/ing_shared_rg_notshared_alb/input/k8s/01-ing.yaml b/testdata/ing_shared_rg_notshared_alb/input/k8s/01-ing.yaml
new file mode 100644
index 0000000..ddd37ec
--- /dev/null
+++ b/testdata/ing_shared_rg_notshared_alb/input/k8s/01-ing.yaml
@@ -0,0 +1,18 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: myingress
+  annotations:
+    zalando.org/aws-load-balancer-shared: "true"
+spec:
+  rules:
+  - host: foo.bar.org
+    http:
+      paths:
+      - backend:
+          service:
+            name: foo-bar-service
+            port:
+              name: main-port
+        path: /
+        pathType: ImplementationSpecific
diff --git a/testdata/ing_shared_rg_notshared_alb/input/k8s/02-rg.yaml b/testdata/ing_shared_rg_notshared_alb/input/k8s/02-rg.yaml
new file mode 100644
index 0000000..432e0b4
--- /dev/null
+++ b/testdata/ing_shared_rg_notshared_alb/input/k8s/02-rg.yaml
@@ -0,0 +1,18 @@
+apiVersion: zalando.org/v1
+kind: RouteGroup
+metadata:
+  name: my-route-group
+  annotations:
+    zalando.org/aws-load-balancer-shared: "false"
+spec:
+  hosts:
+    - foo.bar.org
+  backends:
+  - name: my-backend
+    type: service
+    serviceName: my-service
+    servicePort: 80
+  routes:
+    - pathSubtree: /
+      backends:
+        - backendName: my-backend
diff --git a/testdata/simple_alb/params.json b/testdata/ing_shared_rg_notshared_alb/output/params/01-ing.json
similarity index 100%
rename from testdata/simple_alb/params.json
rename to testdata/ing_shared_rg_notshared_alb/output/params/01-ing.json
diff --git a/testdata/ing_shared_rg_notshared_alb/output/params/02-rg.json b/testdata/ing_shared_rg_notshared_alb/output/params/02-rg.json
new file mode 100644
index 0000000..c1ecf89
--- /dev/null
+++ b/testdata/ing_shared_rg_notshared_alb/output/params/02-rg.json
@@ -0,0 +1,54 @@
+[
+  {
+    "parameterKey": "LoadBalancerSchemeParameter",
+    "parameterValue": "internet-facing"
+  },
+  {
+    "parameterKey": "LoadBalancerSecurityGroupParameter",
+    "parameterValue": "42"
+  },
+  {
+    "parameterKey": "LoadBalancerSubnetsParameter",
+    "parameterValue": "foo1"
+  },
+  {
+    "parameterKey": "TargetGroupVPCIDParameter",
+    "parameterValue": "1"
+  },
+  {
+    "parameterKey": "TargetGroupTargetPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "ListenerSslPolicyParameter",
+    "parameterValue": "ELBSecurityPolicy-2016-08"
+  },
+  {
+    "parameterKey": "IpAddressType",
+    "parameterValue": "ipv4"
+  },
+  {
+    "parameterKey": "Type",
+    "parameterValue": "application"
+  },
+  {
+    "parameterKey": "HTTP2",
+    "parameterValue": "true"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPathParameter",
+    "parameterValue": ""
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckIntervalParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckTimeoutParameter",
+    "parameterValue": "0"
+  }
+]
diff --git a/testdata/simple_alb/tags.json b/testdata/ing_shared_rg_notshared_alb/output/tags/01-ing.json
similarity index 100%
rename from testdata/simple_alb/tags.json
rename to testdata/ing_shared_rg_notshared_alb/output/tags/01-ing.json
diff --git a/testdata/ing_shared_rg_notshared_alb/output/tags/02-rg.json b/testdata/ing_shared_rg_notshared_alb/output/tags/02-rg.json
new file mode 100644
index 0000000..04f7153
--- /dev/null
+++ b/testdata/ing_shared_rg_notshared_alb/output/tags/02-rg.json
@@ -0,0 +1,15 @@
+[
+  {
+    "key": "kubernetes:application",
+    "value": ""
+  },{
+    "key": "kubernetes.io/cluster/aws:123:eu-central-1:kube-1",
+    "value": "owned"
+  },{
+    "key": "ingress:certificate-arn/DUMMY",
+    "value": "0001-01-01T00:00:00Z"
+  },{
+    "key": "ingress:owner",
+    "value": "/my-route-group"
+  }
+]
diff --git a/testdata/simple_alb/template.cf b/testdata/ing_shared_rg_notshared_alb/output/templates/01-ing.cf
similarity index 100%
rename from testdata/simple_alb/template.cf
rename to testdata/ing_shared_rg_notshared_alb/output/templates/01-ing.cf
diff --git a/testdata/ing_shared_rg_notshared_alb/output/templates/02-rg.cf b/testdata/ing_shared_rg_notshared_alb/output/templates/02-rg.cf
new file mode 100644
index 0000000..7e9378d
--- /dev/null
+++ b/testdata/ing_shared_rg_notshared_alb/output/templates/02-rg.cf
@@ -0,0 +1,219 @@
+{
+    "AWSTemplateFormatVersion": "2010-09-09",
+    "Description": "Load Balancer for Kubernetes Ingress",
+    "Parameters": {
+        "HTTP2": {
+            "Type": "String",
+            "Default": "true",
+            "Description": "H2 Enabled"
+        },
+        "IpAddressType": {
+            "Type": "String",
+            "Default": "ipv4",
+            "Description": "IP Address Type, 'ipv4' or 'dualstack'"
+        },
+        "ListenerSslPolicyParameter": {
+            "Type": "String",
+            "Default": "ELBSecurityPolicy-2016-08",
+            "Description": "The HTTPS SSL Security Policy Name"
+        },
+        "LoadBalancerSchemeParameter": {
+            "Type": "String",
+            "Default": "internet-facing",
+            "Description": "The Load Balancer scheme - 'internal' or 'internet-facing'"
+        },
+        "LoadBalancerSecurityGroupParameter": {
+            "Type": "List\u003cAWS::EC2::SecurityGroup::Id\u003e",
+            "Description": "The security group ID for the Load Balancer"
+        },
+        "LoadBalancerSubnetsParameter": {
+            "Type": "List\u003cAWS::EC2::Subnet::Id\u003e",
+            "Description": "The list of subnets IDs for the Load Balancer"
+        },
+        "TargetGroupHealthCheckIntervalParameter": {
+            "Type": "Number",
+            "Default": "10",
+            "Description": "The healthcheck interval"
+        },
+        "TargetGroupHealthCheckPathParameter": {
+            "Type": "String",
+            "Default": "/kube-system/healthz",
+            "Description": "The healthcheck path"
+        },
+        "TargetGroupHealthCheckPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The healthcheck port"
+        },
+        "TargetGroupHealthCheckTimeoutParameter": {
+            "Type": "Number",
+            "Default": "5",
+            "Description": "The healthcheck timeout"
+        },
+        "TargetGroupTargetPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The target port"
+        },
+        "TargetGroupVPCIDParameter": {
+            "Type": "AWS::EC2::VPC::Id",
+            "Description": "The VPCID for the TargetGroup"
+        },
+        "Type": {
+            "Type": "String",
+            "Default": "application",
+            "Description": "Loadbalancer Type, 'application' or 'network'"
+        }
+    },
+    "Resources": {
+        "HTTPListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 80,
+                "Protocol": "HTTP"
+            }
+        },
+        "HTTPSListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 443,
+                "Protocol": "HTTPS",
+                "SslPolicy": {
+                    "Ref": "ListenerSslPolicyParameter"
+                }
+            }
+        },
+        "HTTPSListenerCertificatefc48082457b770e278fc0bd3d392d127869993166f76e8df57d19a0e662820ea": {
+            "Type": "AWS::ElasticLoadBalancingV2::ListenerCertificate",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "ListenerArn": {
+                    "Ref": "HTTPSListener"
+                }
+            }
+        },
+        "LB": {
+            "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
+            "Properties": {
+                "IpAddressType": {
+                    "Ref": "IpAddressType"
+                },
+                "LoadBalancerAttributes": [
+                    {
+                        "Key": "idle_timeout.timeout_seconds",
+                        "Value": "0"
+                    },
+                    {
+                        "Key": "routing.http2.enabled",
+                        "Value": "true"
+                    },
+                    {
+                        "Key": "access_logs.s3.enabled",
+                        "Value": "false"
+                    }
+                ],
+                "Scheme": {
+                    "Ref": "LoadBalancerSchemeParameter"
+                },
+                "SecurityGroups": {
+                    "Ref": "LoadBalancerSecurityGroupParameter"
+                },
+                "Subnets": {
+                    "Ref": "LoadBalancerSubnetsParameter"
+                },
+                "Tags": [
+                    {
+                        "Key": "StackName",
+                        "Value": {
+                            "Ref": "AWS::StackName"
+                        }
+                    }
+                ],
+                "Type": {
+                    "Ref": "Type"
+                }
+            }
+        },
+        "TG": {
+            "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
+            "Properties": {
+                "HealthCheckIntervalSeconds": {
+                    "Ref": "TargetGroupHealthCheckIntervalParameter"
+                },
+                "HealthCheckPath": {
+                    "Ref": "TargetGroupHealthCheckPathParameter"
+                },
+                "HealthCheckPort": {
+                    "Ref": "TargetGroupHealthCheckPortParameter"
+                },
+                "HealthCheckProtocol": "HTTP",
+                "HealthCheckTimeoutSeconds": {
+                    "Ref": "TargetGroupHealthCheckTimeoutParameter"
+                },
+                "HealthyThresholdCount": 0,
+                "Port": {
+                    "Ref": "TargetGroupTargetPortParameter"
+                },
+                "Protocol": "HTTP",
+                "TargetGroupAttributes": [
+                    {
+                        "Key": "deregistration_delay.timeout_seconds",
+                        "Value": "0"
+                    }
+                ],
+                "UnhealthyThresholdCount": 0,
+                "VpcId": {
+                    "Ref": "TargetGroupVPCIDParameter"
+                }
+            }
+        }
+    },
+    "Outputs": {
+        "LoadBalancerDNSName": {
+            "Description": "DNS name for the LoadBalancer",
+            "Value": {
+                "Fn::GetAtt": [
+                    "LB",
+                    "DNSName"
+                ]
+            }
+        },
+        "TargetGroupARN": {
+            "Description": "The ARN of the TargetGroup",
+            "Value": {
+                "Ref": "TG"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/testdata/simple_alb/ing.yaml b/testdata/ingress_alb/input/k8s/ing.yaml
similarity index 100%
rename from testdata/simple_alb/ing.yaml
rename to testdata/ingress_alb/input/k8s/ing.yaml
diff --git a/testdata/ingress_alb/output/params/ing.json b/testdata/ingress_alb/output/params/ing.json
new file mode 100644
index 0000000..c1ecf89
--- /dev/null
+++ b/testdata/ingress_alb/output/params/ing.json
@@ -0,0 +1,54 @@
+[
+  {
+    "parameterKey": "LoadBalancerSchemeParameter",
+    "parameterValue": "internet-facing"
+  },
+  {
+    "parameterKey": "LoadBalancerSecurityGroupParameter",
+    "parameterValue": "42"
+  },
+  {
+    "parameterKey": "LoadBalancerSubnetsParameter",
+    "parameterValue": "foo1"
+  },
+  {
+    "parameterKey": "TargetGroupVPCIDParameter",
+    "parameterValue": "1"
+  },
+  {
+    "parameterKey": "TargetGroupTargetPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "ListenerSslPolicyParameter",
+    "parameterValue": "ELBSecurityPolicy-2016-08"
+  },
+  {
+    "parameterKey": "IpAddressType",
+    "parameterValue": "ipv4"
+  },
+  {
+    "parameterKey": "Type",
+    "parameterValue": "application"
+  },
+  {
+    "parameterKey": "HTTP2",
+    "parameterValue": "true"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPathParameter",
+    "parameterValue": ""
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckIntervalParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckTimeoutParameter",
+    "parameterValue": "0"
+  }
+]
diff --git a/testdata/simple_nlb/tags.json b/testdata/ingress_alb/output/tags/ing.json
similarity index 100%
rename from testdata/simple_nlb/tags.json
rename to testdata/ingress_alb/output/tags/ing.json
diff --git a/testdata/ingress_alb/output/templates/ing.cf b/testdata/ingress_alb/output/templates/ing.cf
new file mode 100644
index 0000000..7e9378d
--- /dev/null
+++ b/testdata/ingress_alb/output/templates/ing.cf
@@ -0,0 +1,219 @@
+{
+    "AWSTemplateFormatVersion": "2010-09-09",
+    "Description": "Load Balancer for Kubernetes Ingress",
+    "Parameters": {
+        "HTTP2": {
+            "Type": "String",
+            "Default": "true",
+            "Description": "H2 Enabled"
+        },
+        "IpAddressType": {
+            "Type": "String",
+            "Default": "ipv4",
+            "Description": "IP Address Type, 'ipv4' or 'dualstack'"
+        },
+        "ListenerSslPolicyParameter": {
+            "Type": "String",
+            "Default": "ELBSecurityPolicy-2016-08",
+            "Description": "The HTTPS SSL Security Policy Name"
+        },
+        "LoadBalancerSchemeParameter": {
+            "Type": "String",
+            "Default": "internet-facing",
+            "Description": "The Load Balancer scheme - 'internal' or 'internet-facing'"
+        },
+        "LoadBalancerSecurityGroupParameter": {
+            "Type": "List\u003cAWS::EC2::SecurityGroup::Id\u003e",
+            "Description": "The security group ID for the Load Balancer"
+        },
+        "LoadBalancerSubnetsParameter": {
+            "Type": "List\u003cAWS::EC2::Subnet::Id\u003e",
+            "Description": "The list of subnets IDs for the Load Balancer"
+        },
+        "TargetGroupHealthCheckIntervalParameter": {
+            "Type": "Number",
+            "Default": "10",
+            "Description": "The healthcheck interval"
+        },
+        "TargetGroupHealthCheckPathParameter": {
+            "Type": "String",
+            "Default": "/kube-system/healthz",
+            "Description": "The healthcheck path"
+        },
+        "TargetGroupHealthCheckPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The healthcheck port"
+        },
+        "TargetGroupHealthCheckTimeoutParameter": {
+            "Type": "Number",
+            "Default": "5",
+            "Description": "The healthcheck timeout"
+        },
+        "TargetGroupTargetPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The target port"
+        },
+        "TargetGroupVPCIDParameter": {
+            "Type": "AWS::EC2::VPC::Id",
+            "Description": "The VPCID for the TargetGroup"
+        },
+        "Type": {
+            "Type": "String",
+            "Default": "application",
+            "Description": "Loadbalancer Type, 'application' or 'network'"
+        }
+    },
+    "Resources": {
+        "HTTPListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 80,
+                "Protocol": "HTTP"
+            }
+        },
+        "HTTPSListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 443,
+                "Protocol": "HTTPS",
+                "SslPolicy": {
+                    "Ref": "ListenerSslPolicyParameter"
+                }
+            }
+        },
+        "HTTPSListenerCertificatefc48082457b770e278fc0bd3d392d127869993166f76e8df57d19a0e662820ea": {
+            "Type": "AWS::ElasticLoadBalancingV2::ListenerCertificate",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "ListenerArn": {
+                    "Ref": "HTTPSListener"
+                }
+            }
+        },
+        "LB": {
+            "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
+            "Properties": {
+                "IpAddressType": {
+                    "Ref": "IpAddressType"
+                },
+                "LoadBalancerAttributes": [
+                    {
+                        "Key": "idle_timeout.timeout_seconds",
+                        "Value": "0"
+                    },
+                    {
+                        "Key": "routing.http2.enabled",
+                        "Value": "true"
+                    },
+                    {
+                        "Key": "access_logs.s3.enabled",
+                        "Value": "false"
+                    }
+                ],
+                "Scheme": {
+                    "Ref": "LoadBalancerSchemeParameter"
+                },
+                "SecurityGroups": {
+                    "Ref": "LoadBalancerSecurityGroupParameter"
+                },
+                "Subnets": {
+                    "Ref": "LoadBalancerSubnetsParameter"
+                },
+                "Tags": [
+                    {
+                        "Key": "StackName",
+                        "Value": {
+                            "Ref": "AWS::StackName"
+                        }
+                    }
+                ],
+                "Type": {
+                    "Ref": "Type"
+                }
+            }
+        },
+        "TG": {
+            "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
+            "Properties": {
+                "HealthCheckIntervalSeconds": {
+                    "Ref": "TargetGroupHealthCheckIntervalParameter"
+                },
+                "HealthCheckPath": {
+                    "Ref": "TargetGroupHealthCheckPathParameter"
+                },
+                "HealthCheckPort": {
+                    "Ref": "TargetGroupHealthCheckPortParameter"
+                },
+                "HealthCheckProtocol": "HTTP",
+                "HealthCheckTimeoutSeconds": {
+                    "Ref": "TargetGroupHealthCheckTimeoutParameter"
+                },
+                "HealthyThresholdCount": 0,
+                "Port": {
+                    "Ref": "TargetGroupTargetPortParameter"
+                },
+                "Protocol": "HTTP",
+                "TargetGroupAttributes": [
+                    {
+                        "Key": "deregistration_delay.timeout_seconds",
+                        "Value": "0"
+                    }
+                ],
+                "UnhealthyThresholdCount": 0,
+                "VpcId": {
+                    "Ref": "TargetGroupVPCIDParameter"
+                }
+            }
+        }
+    },
+    "Outputs": {
+        "LoadBalancerDNSName": {
+            "Description": "DNS name for the LoadBalancer",
+            "Value": {
+                "Fn::GetAtt": [
+                    "LB",
+                    "DNSName"
+                ]
+            }
+        },
+        "TargetGroupARN": {
+            "Description": "The ARN of the TargetGroup",
+            "Value": {
+                "Ref": "TG"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/testdata/simple_nlb/ing.yaml b/testdata/ingress_nlb/input/k8s/ing.yaml
similarity index 88%
rename from testdata/simple_nlb/ing.yaml
rename to testdata/ingress_nlb/input/k8s/ing.yaml
index 21b2e45..1f21110 100644
--- a/testdata/simple_nlb/ing.yaml
+++ b/testdata/ingress_nlb/input/k8s/ing.yaml
@@ -15,4 +15,4 @@ spec:
             port:
               name: main-port
         path: /
-        pathType: ImplementationSpecific
\ No newline at end of file
+        pathType: ImplementationSpecific
diff --git a/testdata/simple_nlb/params.json b/testdata/ingress_nlb/output/params/ing.json
similarity index 100%
rename from testdata/simple_nlb/params.json
rename to testdata/ingress_nlb/output/params/ing.json
diff --git a/testdata/ingress_nlb/output/tags/ing.json b/testdata/ingress_nlb/output/tags/ing.json
new file mode 100644
index 0000000..d64eed4
--- /dev/null
+++ b/testdata/ingress_nlb/output/tags/ing.json
@@ -0,0 +1,12 @@
+[
+  {
+    "key": "kubernetes:application",
+    "value": ""
+  },{
+    "key": "kubernetes.io/cluster/aws:123:eu-central-1:kube-1",
+    "value": "owned"
+  },{
+    "key": "ingress:certificate-arn/DUMMY",
+    "value": "0001-01-01T00:00:00Z"
+  }
+]
diff --git a/testdata/simple_nlb/template.cf b/testdata/ingress_nlb/output/templates/ing.cf
similarity index 100%
rename from testdata/simple_nlb/template.cf
rename to testdata/ingress_nlb/output/templates/ing.cf
diff --git a/testdata/ingress_rg_shared_alb/input/k8s/01-ing.yaml b/testdata/ingress_rg_shared_alb/input/k8s/01-ing.yaml
new file mode 100644
index 0000000..ddd37ec
--- /dev/null
+++ b/testdata/ingress_rg_shared_alb/input/k8s/01-ing.yaml
@@ -0,0 +1,18 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: myingress
+  annotations:
+    zalando.org/aws-load-balancer-shared: "true"
+spec:
+  rules:
+  - host: foo.bar.org
+    http:
+      paths:
+      - backend:
+          service:
+            name: foo-bar-service
+            port:
+              name: main-port
+        path: /
+        pathType: ImplementationSpecific
diff --git a/testdata/ingress_rg_shared_alb/input/k8s/02-rg.yaml b/testdata/ingress_rg_shared_alb/input/k8s/02-rg.yaml
new file mode 100644
index 0000000..01acc2e
--- /dev/null
+++ b/testdata/ingress_rg_shared_alb/input/k8s/02-rg.yaml
@@ -0,0 +1,18 @@
+apiVersion: zalando.org/v1
+kind: RouteGroup
+metadata:
+  name: my-route-group
+  annotations:
+    zalando.org/aws-load-balancer-shared: "true"
+spec:
+  hosts:
+    - foo.bar.org
+  backends:
+  - name: my-backend
+    type: service
+    serviceName: my-service
+    servicePort: 80
+  routes:
+    - pathSubtree: /
+      backends:
+        - backendName: my-backend
diff --git a/testdata/ingress_rg_shared_alb/output/params/shared.json b/testdata/ingress_rg_shared_alb/output/params/shared.json
new file mode 100644
index 0000000..c1ecf89
--- /dev/null
+++ b/testdata/ingress_rg_shared_alb/output/params/shared.json
@@ -0,0 +1,54 @@
+[
+  {
+    "parameterKey": "LoadBalancerSchemeParameter",
+    "parameterValue": "internet-facing"
+  },
+  {
+    "parameterKey": "LoadBalancerSecurityGroupParameter",
+    "parameterValue": "42"
+  },
+  {
+    "parameterKey": "LoadBalancerSubnetsParameter",
+    "parameterValue": "foo1"
+  },
+  {
+    "parameterKey": "TargetGroupVPCIDParameter",
+    "parameterValue": "1"
+  },
+  {
+    "parameterKey": "TargetGroupTargetPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "ListenerSslPolicyParameter",
+    "parameterValue": "ELBSecurityPolicy-2016-08"
+  },
+  {
+    "parameterKey": "IpAddressType",
+    "parameterValue": "ipv4"
+  },
+  {
+    "parameterKey": "Type",
+    "parameterValue": "application"
+  },
+  {
+    "parameterKey": "HTTP2",
+    "parameterValue": "true"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPathParameter",
+    "parameterValue": ""
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckIntervalParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckTimeoutParameter",
+    "parameterValue": "0"
+  }
+]
diff --git a/testdata/ingress_rg_shared_alb/output/tags/shared.json b/testdata/ingress_rg_shared_alb/output/tags/shared.json
new file mode 100644
index 0000000..d64eed4
--- /dev/null
+++ b/testdata/ingress_rg_shared_alb/output/tags/shared.json
@@ -0,0 +1,12 @@
+[
+  {
+    "key": "kubernetes:application",
+    "value": ""
+  },{
+    "key": "kubernetes.io/cluster/aws:123:eu-central-1:kube-1",
+    "value": "owned"
+  },{
+    "key": "ingress:certificate-arn/DUMMY",
+    "value": "0001-01-01T00:00:00Z"
+  }
+]
diff --git a/testdata/ingress_rg_shared_alb/output/templates/shared.cf b/testdata/ingress_rg_shared_alb/output/templates/shared.cf
new file mode 100644
index 0000000..7e9378d
--- /dev/null
+++ b/testdata/ingress_rg_shared_alb/output/templates/shared.cf
@@ -0,0 +1,219 @@
+{
+    "AWSTemplateFormatVersion": "2010-09-09",
+    "Description": "Load Balancer for Kubernetes Ingress",
+    "Parameters": {
+        "HTTP2": {
+            "Type": "String",
+            "Default": "true",
+            "Description": "H2 Enabled"
+        },
+        "IpAddressType": {
+            "Type": "String",
+            "Default": "ipv4",
+            "Description": "IP Address Type, 'ipv4' or 'dualstack'"
+        },
+        "ListenerSslPolicyParameter": {
+            "Type": "String",
+            "Default": "ELBSecurityPolicy-2016-08",
+            "Description": "The HTTPS SSL Security Policy Name"
+        },
+        "LoadBalancerSchemeParameter": {
+            "Type": "String",
+            "Default": "internet-facing",
+            "Description": "The Load Balancer scheme - 'internal' or 'internet-facing'"
+        },
+        "LoadBalancerSecurityGroupParameter": {
+            "Type": "List\u003cAWS::EC2::SecurityGroup::Id\u003e",
+            "Description": "The security group ID for the Load Balancer"
+        },
+        "LoadBalancerSubnetsParameter": {
+            "Type": "List\u003cAWS::EC2::Subnet::Id\u003e",
+            "Description": "The list of subnets IDs for the Load Balancer"
+        },
+        "TargetGroupHealthCheckIntervalParameter": {
+            "Type": "Number",
+            "Default": "10",
+            "Description": "The healthcheck interval"
+        },
+        "TargetGroupHealthCheckPathParameter": {
+            "Type": "String",
+            "Default": "/kube-system/healthz",
+            "Description": "The healthcheck path"
+        },
+        "TargetGroupHealthCheckPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The healthcheck port"
+        },
+        "TargetGroupHealthCheckTimeoutParameter": {
+            "Type": "Number",
+            "Default": "5",
+            "Description": "The healthcheck timeout"
+        },
+        "TargetGroupTargetPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The target port"
+        },
+        "TargetGroupVPCIDParameter": {
+            "Type": "AWS::EC2::VPC::Id",
+            "Description": "The VPCID for the TargetGroup"
+        },
+        "Type": {
+            "Type": "String",
+            "Default": "application",
+            "Description": "Loadbalancer Type, 'application' or 'network'"
+        }
+    },
+    "Resources": {
+        "HTTPListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 80,
+                "Protocol": "HTTP"
+            }
+        },
+        "HTTPSListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 443,
+                "Protocol": "HTTPS",
+                "SslPolicy": {
+                    "Ref": "ListenerSslPolicyParameter"
+                }
+            }
+        },
+        "HTTPSListenerCertificatefc48082457b770e278fc0bd3d392d127869993166f76e8df57d19a0e662820ea": {
+            "Type": "AWS::ElasticLoadBalancingV2::ListenerCertificate",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "ListenerArn": {
+                    "Ref": "HTTPSListener"
+                }
+            }
+        },
+        "LB": {
+            "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
+            "Properties": {
+                "IpAddressType": {
+                    "Ref": "IpAddressType"
+                },
+                "LoadBalancerAttributes": [
+                    {
+                        "Key": "idle_timeout.timeout_seconds",
+                        "Value": "0"
+                    },
+                    {
+                        "Key": "routing.http2.enabled",
+                        "Value": "true"
+                    },
+                    {
+                        "Key": "access_logs.s3.enabled",
+                        "Value": "false"
+                    }
+                ],
+                "Scheme": {
+                    "Ref": "LoadBalancerSchemeParameter"
+                },
+                "SecurityGroups": {
+                    "Ref": "LoadBalancerSecurityGroupParameter"
+                },
+                "Subnets": {
+                    "Ref": "LoadBalancerSubnetsParameter"
+                },
+                "Tags": [
+                    {
+                        "Key": "StackName",
+                        "Value": {
+                            "Ref": "AWS::StackName"
+                        }
+                    }
+                ],
+                "Type": {
+                    "Ref": "Type"
+                }
+            }
+        },
+        "TG": {
+            "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
+            "Properties": {
+                "HealthCheckIntervalSeconds": {
+                    "Ref": "TargetGroupHealthCheckIntervalParameter"
+                },
+                "HealthCheckPath": {
+                    "Ref": "TargetGroupHealthCheckPathParameter"
+                },
+                "HealthCheckPort": {
+                    "Ref": "TargetGroupHealthCheckPortParameter"
+                },
+                "HealthCheckProtocol": "HTTP",
+                "HealthCheckTimeoutSeconds": {
+                    "Ref": "TargetGroupHealthCheckTimeoutParameter"
+                },
+                "HealthyThresholdCount": 0,
+                "Port": {
+                    "Ref": "TargetGroupTargetPortParameter"
+                },
+                "Protocol": "HTTP",
+                "TargetGroupAttributes": [
+                    {
+                        "Key": "deregistration_delay.timeout_seconds",
+                        "Value": "0"
+                    }
+                ],
+                "UnhealthyThresholdCount": 0,
+                "VpcId": {
+                    "Ref": "TargetGroupVPCIDParameter"
+                }
+            }
+        }
+    },
+    "Outputs": {
+        "LoadBalancerDNSName": {
+            "Description": "DNS name for the LoadBalancer",
+            "Value": {
+                "Fn::GetAtt": [
+                    "LB",
+                    "DNSName"
+                ]
+            }
+        },
+        "TargetGroupARN": {
+            "Description": "The ARN of the TargetGroup",
+            "Value": {
+                "Ref": "TG"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/testdata/ingress_rg_shared_nlb/input/k8s/01-ing.yaml b/testdata/ingress_rg_shared_nlb/input/k8s/01-ing.yaml
new file mode 100644
index 0000000..ddd37ec
--- /dev/null
+++ b/testdata/ingress_rg_shared_nlb/input/k8s/01-ing.yaml
@@ -0,0 +1,18 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: myingress
+  annotations:
+    zalando.org/aws-load-balancer-shared: "true"
+spec:
+  rules:
+  - host: foo.bar.org
+    http:
+      paths:
+      - backend:
+          service:
+            name: foo-bar-service
+            port:
+              name: main-port
+        path: /
+        pathType: ImplementationSpecific
diff --git a/testdata/ingress_rg_shared_nlb/input/k8s/02-rg.yaml b/testdata/ingress_rg_shared_nlb/input/k8s/02-rg.yaml
new file mode 100644
index 0000000..01acc2e
--- /dev/null
+++ b/testdata/ingress_rg_shared_nlb/input/k8s/02-rg.yaml
@@ -0,0 +1,18 @@
+apiVersion: zalando.org/v1
+kind: RouteGroup
+metadata:
+  name: my-route-group
+  annotations:
+    zalando.org/aws-load-balancer-shared: "true"
+spec:
+  hosts:
+    - foo.bar.org
+  backends:
+  - name: my-backend
+    type: service
+    serviceName: my-service
+    servicePort: 80
+  routes:
+    - pathSubtree: /
+      backends:
+        - backendName: my-backend
diff --git a/testdata/ingress_rg_shared_nlb/output/params/shared.json b/testdata/ingress_rg_shared_nlb/output/params/shared.json
new file mode 100644
index 0000000..adec04c
--- /dev/null
+++ b/testdata/ingress_rg_shared_nlb/output/params/shared.json
@@ -0,0 +1,54 @@
+[
+  {
+    "parameterKey": "LoadBalancerSchemeParameter",
+    "parameterValue": "internet-facing"
+  },
+  {
+    "parameterKey": "LoadBalancerSecurityGroupParameter",
+    "parameterValue": "42"
+  },
+  {
+    "parameterKey": "LoadBalancerSubnetsParameter",
+    "parameterValue": "foo1"
+  },
+  {
+    "parameterKey": "TargetGroupVPCIDParameter",
+    "parameterValue": "1"
+  },
+  {
+    "parameterKey": "TargetGroupTargetPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "ListenerSslPolicyParameter",
+    "parameterValue": "ELBSecurityPolicy-2016-08"
+  },
+  {
+    "parameterKey": "IpAddressType",
+    "parameterValue": "ipv4"
+  },
+  {
+    "parameterKey": "Type",
+    "parameterValue": "network"
+  },
+  {
+    "parameterKey": "HTTP2",
+    "parameterValue": "true"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPathParameter",
+    "parameterValue": ""
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckIntervalParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckTimeoutParameter",
+    "parameterValue": "0"
+  }
+]
diff --git a/testdata/ingress_rg_shared_nlb/output/tags/shared.json b/testdata/ingress_rg_shared_nlb/output/tags/shared.json
new file mode 100644
index 0000000..d64eed4
--- /dev/null
+++ b/testdata/ingress_rg_shared_nlb/output/tags/shared.json
@@ -0,0 +1,12 @@
+[
+  {
+    "key": "kubernetes:application",
+    "value": ""
+  },{
+    "key": "kubernetes.io/cluster/aws:123:eu-central-1:kube-1",
+    "value": "owned"
+  },{
+    "key": "ingress:certificate-arn/DUMMY",
+    "value": "0001-01-01T00:00:00Z"
+  }
+]
diff --git a/testdata/ingress_rg_shared_nlb/output/templates/shared.cf b/testdata/ingress_rg_shared_nlb/output/templates/shared.cf
new file mode 100644
index 0000000..ac57a01
--- /dev/null
+++ b/testdata/ingress_rg_shared_nlb/output/templates/shared.cf
@@ -0,0 +1,187 @@
+{
+    "AWSTemplateFormatVersion": "2010-09-09",
+    "Description": "Load Balancer for Kubernetes Ingress",
+    "Parameters": {
+        "HTTP2": {
+            "Type": "String",
+            "Default": "true",
+            "Description": "H2 Enabled"
+        },
+        "IpAddressType": {
+            "Type": "String",
+            "Default": "ipv4",
+            "Description": "IP Address Type, 'ipv4' or 'dualstack'"
+        },
+        "ListenerSslPolicyParameter": {
+            "Type": "String",
+            "Default": "ELBSecurityPolicy-2016-08",
+            "Description": "The HTTPS SSL Security Policy Name"
+        },
+        "LoadBalancerSchemeParameter": {
+            "Type": "String",
+            "Default": "internet-facing",
+            "Description": "The Load Balancer scheme - 'internal' or 'internet-facing'"
+        },
+        "LoadBalancerSecurityGroupParameter": {
+            "Type": "List\u003cAWS::EC2::SecurityGroup::Id\u003e",
+            "Description": "The security group ID for the Load Balancer"
+        },
+        "LoadBalancerSubnetsParameter": {
+            "Type": "List\u003cAWS::EC2::Subnet::Id\u003e",
+            "Description": "The list of subnets IDs for the Load Balancer"
+        },
+        "TargetGroupHealthCheckIntervalParameter": {
+            "Type": "Number",
+            "Default": "10",
+            "Description": "The healthcheck interval"
+        },
+        "TargetGroupHealthCheckPathParameter": {
+            "Type": "String",
+            "Default": "/kube-system/healthz",
+            "Description": "The healthcheck path"
+        },
+        "TargetGroupHealthCheckPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The healthcheck port"
+        },
+        "TargetGroupHealthCheckTimeoutParameter": {
+            "Type": "Number",
+            "Default": "5",
+            "Description": "The healthcheck timeout"
+        },
+        "TargetGroupTargetPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The target port"
+        },
+        "TargetGroupVPCIDParameter": {
+            "Type": "AWS::EC2::VPC::Id",
+            "Description": "The VPCID for the TargetGroup"
+        },
+        "Type": {
+            "Type": "String",
+            "Default": "application",
+            "Description": "Loadbalancer Type, 'application' or 'network'"
+        }
+    },
+    "Resources": {
+        "HTTPSListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 443,
+                "Protocol": "TLS",
+                "SslPolicy": {
+                    "Ref": "ListenerSslPolicyParameter"
+                }
+            }
+        },
+        "HTTPSListenerCertificatefc48082457b770e278fc0bd3d392d127869993166f76e8df57d19a0e662820ea": {
+            "Type": "AWS::ElasticLoadBalancingV2::ListenerCertificate",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "ListenerArn": {
+                    "Ref": "HTTPSListener"
+                }
+            }
+        },
+        "LB": {
+            "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
+            "Properties": {
+                "IpAddressType": {
+                    "Ref": "IpAddressType"
+                },
+                "LoadBalancerAttributes": [
+                    {
+                        "Key": "access_logs.s3.enabled",
+                        "Value": "false"
+                    }
+                ],
+                "Scheme": {
+                    "Ref": "LoadBalancerSchemeParameter"
+                },
+                "Subnets": {
+                    "Ref": "LoadBalancerSubnetsParameter"
+                },
+                "Tags": [
+                    {
+                        "Key": "StackName",
+                        "Value": {
+                            "Ref": "AWS::StackName"
+                        }
+                    }
+                ],
+                "Type": {
+                    "Ref": "Type"
+                }
+            }
+        },
+        "TG": {
+            "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
+            "Properties": {
+                "HealthCheckIntervalSeconds": {
+                    "Ref": "TargetGroupHealthCheckIntervalParameter"
+                },
+                "HealthCheckPath": {
+                    "Ref": "TargetGroupHealthCheckPathParameter"
+                },
+                "HealthCheckPort": {
+                    "Ref": "TargetGroupHealthCheckPortParameter"
+                },
+                "HealthCheckProtocol": "HTTP",
+                "HealthyThresholdCount": 0,
+                "Port": {
+                    "Ref": "TargetGroupTargetPortParameter"
+                },
+                "Protocol": "TCP",
+                "TargetGroupAttributes": [
+                    {
+                        "Key": "deregistration_delay.timeout_seconds",
+                        "Value": "0"
+                    }
+                ],
+                "UnhealthyThresholdCount": 0,
+                "VpcId": {
+                    "Ref": "TargetGroupVPCIDParameter"
+                }
+            }
+        }
+    },
+    "Outputs": {
+        "LoadBalancerDNSName": {
+            "Description": "DNS name for the LoadBalancer",
+            "Value": {
+                "Fn::GetAtt": [
+                    "LB",
+                    "DNSName"
+                ]
+            }
+        },
+        "TargetGroupARN": {
+            "Description": "The ARN of the TargetGroup",
+            "Value": {
+                "Ref": "TG"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/testdata/rg_alb/input/k8s/rg.yaml b/testdata/rg_alb/input/k8s/rg.yaml
new file mode 100644
index 0000000..ed9a90f
--- /dev/null
+++ b/testdata/rg_alb/input/k8s/rg.yaml
@@ -0,0 +1,16 @@
+apiVersion: zalando.org/v1
+kind: RouteGroup
+metadata:
+  name: my-route-group
+spec:
+  hosts:
+    - foo.bar.org
+  backends:
+  - name: my-backend
+    type: service
+    serviceName: my-service
+    servicePort: 80
+  routes:
+    - pathSubtree: /
+      backends:
+        - backendName: my-backend
diff --git a/testdata/rg_alb/output/params/rg.json b/testdata/rg_alb/output/params/rg.json
new file mode 100644
index 0000000..c1ecf89
--- /dev/null
+++ b/testdata/rg_alb/output/params/rg.json
@@ -0,0 +1,54 @@
+[
+  {
+    "parameterKey": "LoadBalancerSchemeParameter",
+    "parameterValue": "internet-facing"
+  },
+  {
+    "parameterKey": "LoadBalancerSecurityGroupParameter",
+    "parameterValue": "42"
+  },
+  {
+    "parameterKey": "LoadBalancerSubnetsParameter",
+    "parameterValue": "foo1"
+  },
+  {
+    "parameterKey": "TargetGroupVPCIDParameter",
+    "parameterValue": "1"
+  },
+  {
+    "parameterKey": "TargetGroupTargetPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "ListenerSslPolicyParameter",
+    "parameterValue": "ELBSecurityPolicy-2016-08"
+  },
+  {
+    "parameterKey": "IpAddressType",
+    "parameterValue": "ipv4"
+  },
+  {
+    "parameterKey": "Type",
+    "parameterValue": "application"
+  },
+  {
+    "parameterKey": "HTTP2",
+    "parameterValue": "true"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPathParameter",
+    "parameterValue": ""
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckIntervalParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckTimeoutParameter",
+    "parameterValue": "0"
+  }
+]
diff --git a/testdata/rg_alb/output/tags/rg.json b/testdata/rg_alb/output/tags/rg.json
new file mode 100644
index 0000000..d64eed4
--- /dev/null
+++ b/testdata/rg_alb/output/tags/rg.json
@@ -0,0 +1,12 @@
+[
+  {
+    "key": "kubernetes:application",
+    "value": ""
+  },{
+    "key": "kubernetes.io/cluster/aws:123:eu-central-1:kube-1",
+    "value": "owned"
+  },{
+    "key": "ingress:certificate-arn/DUMMY",
+    "value": "0001-01-01T00:00:00Z"
+  }
+]
diff --git a/testdata/rg_alb/output/templates/rg.cf b/testdata/rg_alb/output/templates/rg.cf
new file mode 100644
index 0000000..7e9378d
--- /dev/null
+++ b/testdata/rg_alb/output/templates/rg.cf
@@ -0,0 +1,219 @@
+{
+    "AWSTemplateFormatVersion": "2010-09-09",
+    "Description": "Load Balancer for Kubernetes Ingress",
+    "Parameters": {
+        "HTTP2": {
+            "Type": "String",
+            "Default": "true",
+            "Description": "H2 Enabled"
+        },
+        "IpAddressType": {
+            "Type": "String",
+            "Default": "ipv4",
+            "Description": "IP Address Type, 'ipv4' or 'dualstack'"
+        },
+        "ListenerSslPolicyParameter": {
+            "Type": "String",
+            "Default": "ELBSecurityPolicy-2016-08",
+            "Description": "The HTTPS SSL Security Policy Name"
+        },
+        "LoadBalancerSchemeParameter": {
+            "Type": "String",
+            "Default": "internet-facing",
+            "Description": "The Load Balancer scheme - 'internal' or 'internet-facing'"
+        },
+        "LoadBalancerSecurityGroupParameter": {
+            "Type": "List\u003cAWS::EC2::SecurityGroup::Id\u003e",
+            "Description": "The security group ID for the Load Balancer"
+        },
+        "LoadBalancerSubnetsParameter": {
+            "Type": "List\u003cAWS::EC2::Subnet::Id\u003e",
+            "Description": "The list of subnets IDs for the Load Balancer"
+        },
+        "TargetGroupHealthCheckIntervalParameter": {
+            "Type": "Number",
+            "Default": "10",
+            "Description": "The healthcheck interval"
+        },
+        "TargetGroupHealthCheckPathParameter": {
+            "Type": "String",
+            "Default": "/kube-system/healthz",
+            "Description": "The healthcheck path"
+        },
+        "TargetGroupHealthCheckPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The healthcheck port"
+        },
+        "TargetGroupHealthCheckTimeoutParameter": {
+            "Type": "Number",
+            "Default": "5",
+            "Description": "The healthcheck timeout"
+        },
+        "TargetGroupTargetPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The target port"
+        },
+        "TargetGroupVPCIDParameter": {
+            "Type": "AWS::EC2::VPC::Id",
+            "Description": "The VPCID for the TargetGroup"
+        },
+        "Type": {
+            "Type": "String",
+            "Default": "application",
+            "Description": "Loadbalancer Type, 'application' or 'network'"
+        }
+    },
+    "Resources": {
+        "HTTPListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 80,
+                "Protocol": "HTTP"
+            }
+        },
+        "HTTPSListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 443,
+                "Protocol": "HTTPS",
+                "SslPolicy": {
+                    "Ref": "ListenerSslPolicyParameter"
+                }
+            }
+        },
+        "HTTPSListenerCertificatefc48082457b770e278fc0bd3d392d127869993166f76e8df57d19a0e662820ea": {
+            "Type": "AWS::ElasticLoadBalancingV2::ListenerCertificate",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "ListenerArn": {
+                    "Ref": "HTTPSListener"
+                }
+            }
+        },
+        "LB": {
+            "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
+            "Properties": {
+                "IpAddressType": {
+                    "Ref": "IpAddressType"
+                },
+                "LoadBalancerAttributes": [
+                    {
+                        "Key": "idle_timeout.timeout_seconds",
+                        "Value": "0"
+                    },
+                    {
+                        "Key": "routing.http2.enabled",
+                        "Value": "true"
+                    },
+                    {
+                        "Key": "access_logs.s3.enabled",
+                        "Value": "false"
+                    }
+                ],
+                "Scheme": {
+                    "Ref": "LoadBalancerSchemeParameter"
+                },
+                "SecurityGroups": {
+                    "Ref": "LoadBalancerSecurityGroupParameter"
+                },
+                "Subnets": {
+                    "Ref": "LoadBalancerSubnetsParameter"
+                },
+                "Tags": [
+                    {
+                        "Key": "StackName",
+                        "Value": {
+                            "Ref": "AWS::StackName"
+                        }
+                    }
+                ],
+                "Type": {
+                    "Ref": "Type"
+                }
+            }
+        },
+        "TG": {
+            "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
+            "Properties": {
+                "HealthCheckIntervalSeconds": {
+                    "Ref": "TargetGroupHealthCheckIntervalParameter"
+                },
+                "HealthCheckPath": {
+                    "Ref": "TargetGroupHealthCheckPathParameter"
+                },
+                "HealthCheckPort": {
+                    "Ref": "TargetGroupHealthCheckPortParameter"
+                },
+                "HealthCheckProtocol": "HTTP",
+                "HealthCheckTimeoutSeconds": {
+                    "Ref": "TargetGroupHealthCheckTimeoutParameter"
+                },
+                "HealthyThresholdCount": 0,
+                "Port": {
+                    "Ref": "TargetGroupTargetPortParameter"
+                },
+                "Protocol": "HTTP",
+                "TargetGroupAttributes": [
+                    {
+                        "Key": "deregistration_delay.timeout_seconds",
+                        "Value": "0"
+                    }
+                ],
+                "UnhealthyThresholdCount": 0,
+                "VpcId": {
+                    "Ref": "TargetGroupVPCIDParameter"
+                }
+            }
+        }
+    },
+    "Outputs": {
+        "LoadBalancerDNSName": {
+            "Description": "DNS name for the LoadBalancer",
+            "Value": {
+                "Fn::GetAtt": [
+                    "LB",
+                    "DNSName"
+                ]
+            }
+        },
+        "TargetGroupARN": {
+            "Description": "The ARN of the TargetGroup",
+            "Value": {
+                "Ref": "TG"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/testdata/rg_nlb/input/k8s/rg.yaml b/testdata/rg_nlb/input/k8s/rg.yaml
new file mode 100644
index 0000000..ed9a90f
--- /dev/null
+++ b/testdata/rg_nlb/input/k8s/rg.yaml
@@ -0,0 +1,16 @@
+apiVersion: zalando.org/v1
+kind: RouteGroup
+metadata:
+  name: my-route-group
+spec:
+  hosts:
+    - foo.bar.org
+  backends:
+  - name: my-backend
+    type: service
+    serviceName: my-service
+    servicePort: 80
+  routes:
+    - pathSubtree: /
+      backends:
+        - backendName: my-backend
diff --git a/testdata/rg_nlb/output/params/rg.json b/testdata/rg_nlb/output/params/rg.json
new file mode 100644
index 0000000..adec04c
--- /dev/null
+++ b/testdata/rg_nlb/output/params/rg.json
@@ -0,0 +1,54 @@
+[
+  {
+    "parameterKey": "LoadBalancerSchemeParameter",
+    "parameterValue": "internet-facing"
+  },
+  {
+    "parameterKey": "LoadBalancerSecurityGroupParameter",
+    "parameterValue": "42"
+  },
+  {
+    "parameterKey": "LoadBalancerSubnetsParameter",
+    "parameterValue": "foo1"
+  },
+  {
+    "parameterKey": "TargetGroupVPCIDParameter",
+    "parameterValue": "1"
+  },
+  {
+    "parameterKey": "TargetGroupTargetPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "ListenerSslPolicyParameter",
+    "parameterValue": "ELBSecurityPolicy-2016-08"
+  },
+  {
+    "parameterKey": "IpAddressType",
+    "parameterValue": "ipv4"
+  },
+  {
+    "parameterKey": "Type",
+    "parameterValue": "network"
+  },
+  {
+    "parameterKey": "HTTP2",
+    "parameterValue": "true"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPathParameter",
+    "parameterValue": ""
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckPortParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckIntervalParameter",
+    "parameterValue": "0"
+  },
+  {
+    "parameterKey": "TargetGroupHealthCheckTimeoutParameter",
+    "parameterValue": "0"
+  }
+]
diff --git a/testdata/rg_nlb/output/tags/rg.json b/testdata/rg_nlb/output/tags/rg.json
new file mode 100644
index 0000000..d64eed4
--- /dev/null
+++ b/testdata/rg_nlb/output/tags/rg.json
@@ -0,0 +1,12 @@
+[
+  {
+    "key": "kubernetes:application",
+    "value": ""
+  },{
+    "key": "kubernetes.io/cluster/aws:123:eu-central-1:kube-1",
+    "value": "owned"
+  },{
+    "key": "ingress:certificate-arn/DUMMY",
+    "value": "0001-01-01T00:00:00Z"
+  }
+]
diff --git a/testdata/rg_nlb/output/templates/rg.cf b/testdata/rg_nlb/output/templates/rg.cf
new file mode 100644
index 0000000..ac57a01
--- /dev/null
+++ b/testdata/rg_nlb/output/templates/rg.cf
@@ -0,0 +1,187 @@
+{
+    "AWSTemplateFormatVersion": "2010-09-09",
+    "Description": "Load Balancer for Kubernetes Ingress",
+    "Parameters": {
+        "HTTP2": {
+            "Type": "String",
+            "Default": "true",
+            "Description": "H2 Enabled"
+        },
+        "IpAddressType": {
+            "Type": "String",
+            "Default": "ipv4",
+            "Description": "IP Address Type, 'ipv4' or 'dualstack'"
+        },
+        "ListenerSslPolicyParameter": {
+            "Type": "String",
+            "Default": "ELBSecurityPolicy-2016-08",
+            "Description": "The HTTPS SSL Security Policy Name"
+        },
+        "LoadBalancerSchemeParameter": {
+            "Type": "String",
+            "Default": "internet-facing",
+            "Description": "The Load Balancer scheme - 'internal' or 'internet-facing'"
+        },
+        "LoadBalancerSecurityGroupParameter": {
+            "Type": "List\u003cAWS::EC2::SecurityGroup::Id\u003e",
+            "Description": "The security group ID for the Load Balancer"
+        },
+        "LoadBalancerSubnetsParameter": {
+            "Type": "List\u003cAWS::EC2::Subnet::Id\u003e",
+            "Description": "The list of subnets IDs for the Load Balancer"
+        },
+        "TargetGroupHealthCheckIntervalParameter": {
+            "Type": "Number",
+            "Default": "10",
+            "Description": "The healthcheck interval"
+        },
+        "TargetGroupHealthCheckPathParameter": {
+            "Type": "String",
+            "Default": "/kube-system/healthz",
+            "Description": "The healthcheck path"
+        },
+        "TargetGroupHealthCheckPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The healthcheck port"
+        },
+        "TargetGroupHealthCheckTimeoutParameter": {
+            "Type": "Number",
+            "Default": "5",
+            "Description": "The healthcheck timeout"
+        },
+        "TargetGroupTargetPortParameter": {
+            "Type": "Number",
+            "Default": "9999",
+            "Description": "The target port"
+        },
+        "TargetGroupVPCIDParameter": {
+            "Type": "AWS::EC2::VPC::Id",
+            "Description": "The VPCID for the TargetGroup"
+        },
+        "Type": {
+            "Type": "String",
+            "Default": "application",
+            "Description": "Loadbalancer Type, 'application' or 'network'"
+        }
+    },
+    "Resources": {
+        "HTTPSListener": {
+            "Type": "AWS::ElasticLoadBalancingV2::Listener",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "DefaultActions": [
+                    {
+                        "TargetGroupArn": {
+                            "Ref": "TG"
+                        },
+                        "Type": "forward"
+                    }
+                ],
+                "LoadBalancerArn": {
+                    "Ref": "LB"
+                },
+                "Port": 443,
+                "Protocol": "TLS",
+                "SslPolicy": {
+                    "Ref": "ListenerSslPolicyParameter"
+                }
+            }
+        },
+        "HTTPSListenerCertificatefc48082457b770e278fc0bd3d392d127869993166f76e8df57d19a0e662820ea": {
+            "Type": "AWS::ElasticLoadBalancingV2::ListenerCertificate",
+            "Properties": {
+                "Certificates": [
+                    {
+                        "CertificateArn": "DUMMY"
+                    }
+                ],
+                "ListenerArn": {
+                    "Ref": "HTTPSListener"
+                }
+            }
+        },
+        "LB": {
+            "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
+            "Properties": {
+                "IpAddressType": {
+                    "Ref": "IpAddressType"
+                },
+                "LoadBalancerAttributes": [
+                    {
+                        "Key": "access_logs.s3.enabled",
+                        "Value": "false"
+                    }
+                ],
+                "Scheme": {
+                    "Ref": "LoadBalancerSchemeParameter"
+                },
+                "Subnets": {
+                    "Ref": "LoadBalancerSubnetsParameter"
+                },
+                "Tags": [
+                    {
+                        "Key": "StackName",
+                        "Value": {
+                            "Ref": "AWS::StackName"
+                        }
+                    }
+                ],
+                "Type": {
+                    "Ref": "Type"
+                }
+            }
+        },
+        "TG": {
+            "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
+            "Properties": {
+                "HealthCheckIntervalSeconds": {
+                    "Ref": "TargetGroupHealthCheckIntervalParameter"
+                },
+                "HealthCheckPath": {
+                    "Ref": "TargetGroupHealthCheckPathParameter"
+                },
+                "HealthCheckPort": {
+                    "Ref": "TargetGroupHealthCheckPortParameter"
+                },
+                "HealthCheckProtocol": "HTTP",
+                "HealthyThresholdCount": 0,
+                "Port": {
+                    "Ref": "TargetGroupTargetPortParameter"
+                },
+                "Protocol": "TCP",
+                "TargetGroupAttributes": [
+                    {
+                        "Key": "deregistration_delay.timeout_seconds",
+                        "Value": "0"
+                    }
+                ],
+                "UnhealthyThresholdCount": 0,
+                "VpcId": {
+                    "Ref": "TargetGroupVPCIDParameter"
+                }
+            }
+        }
+    },
+    "Outputs": {
+        "LoadBalancerDNSName": {
+            "Description": "DNS name for the LoadBalancer",
+            "Value": {
+                "Fn::GetAtt": [
+                    "LB",
+                    "DNSName"
+                ]
+            }
+        },
+        "TargetGroupARN": {
+            "Description": "The ARN of the TargetGroup",
+            "Value": {
+                "Ref": "TG"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/worker_test.go b/worker_test.go
index d4cf4ef..91e9ebb 100644
--- a/worker_test.go
+++ b/worker_test.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"crypto/x509"
 	"encoding/json"
+	"io"
 	"net/http/httptest"
 	"os"
 	"reflect"
@@ -27,7 +28,7 @@ import (
 	certsfake "github.com/zalando-incubator/kube-ingress-aws-controller/certs/fake"
 )
 
-func TestResourceConversion(tt *testing.T) {
+func TestResourceConversionOneToOne(tt *testing.T) {
 	clusterIDTagPrefix := "kubernetes.io/cluster/"
 	clusterID := "aws:123:eu-central-1:kube-1"
 	vpcID := "1"
@@ -43,7 +44,7 @@ func TestResourceConversion(tt *testing.T) {
 		typeLB         string
 	}{
 		{
-			name: "simple_alb",
+			name: "ingress_alb",
 			responsesEC2: fake.EC2Outputs{DescribeInstancesPages: fake.MockDescribeInstancesPagesOutput(
 				nil,
 				fake.TestInstance{
@@ -96,7 +97,267 @@ func TestResourceConversion(tt *testing.T) {
 			typeLB: awsAdapter.LoadBalancerTypeApplication,
 		},
 		{
-			name: "simple_nlb",
+			name: "ingress_nlb",
+			responsesEC2: fake.EC2Outputs{DescribeInstancesPages: fake.MockDescribeInstancesPagesOutput(
+				nil,
+				fake.TestInstance{
+					Id:        "i0",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.3",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i1",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.4",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i2",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.5",
+					VpcId:     vpcID,
+					State:     running,
+				}),
+				DescribeSecurityGroups: fake.R(fake.MockDescribeSecurityGroupsOutput(map[string]string{"id": securityGroupID}), nil),
+				DescribeSubnets: fake.R(fake.MockDescribeSubnetsOutput(
+					fake.TestSubnet{Id: "foo1", Name: "bar1", Az: "baz1", Tags: map[string]string{"kubernetes.io/role/elb": ""}}), nil),
+				DescribeRouteTables: fake.R(fake.MockDescribeRouteTableOutput(
+					fake.TestRouteTable{SubnetID: "foo1", GatewayIds: []string{"igw-foo1"}},
+					fake.TestRouteTable{SubnetID: "mismatch", GatewayIds: []string{"igw-foo2"}, Main: true},
+				), nil),
+			},
+			responsesASG: fake.ASGOutputs{
+				DescribeAutoScalingGroups: fake.R(fake.MockDescribeAutoScalingGroupOutput(map[string]fake.ASGtags{"asg1": {
+					clusterIDTagPrefix + clusterID: "owned",
+				}}), nil),
+				DescribeLoadBalancerTargetGroups: fake.R(&autoscaling.DescribeLoadBalancerTargetGroupsOutput{
+					LoadBalancerTargetGroups: []*autoscaling.LoadBalancerTargetGroupState{},
+				}, nil),
+				AttachLoadBalancerTargetGroups: fake.R(nil, nil),
+			},
+			responsesELBv2: fake.ELBv2Outputs{
+				DescribeTargetGroups: fake.R(nil, nil),
+				DescribeTags:         fake.R(nil, nil),
+			},
+			responsesCF: fake.CFOutputs{
+				DescribeStackPages: fake.R(nil, nil),
+				DescribeStacks:     fake.R(nil, nil),
+				CreateStack:        fake.R(fake.MockCSOutput("42"), nil),
+			},
+			typeLB: awsAdapter.LoadBalancerTypeNetwork,
+		}, {
+			name: "rg_alb",
+			responsesEC2: fake.EC2Outputs{DescribeInstancesPages: fake.MockDescribeInstancesPagesOutput(
+				nil,
+				fake.TestInstance{
+					Id:        "i0",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.3",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i1",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.4",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i2",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.5",
+					VpcId:     vpcID,
+					State:     running,
+				}),
+				DescribeSecurityGroups: fake.R(fake.MockDescribeSecurityGroupsOutput(map[string]string{"id": securityGroupID}), nil),
+				DescribeSubnets: fake.R(fake.MockDescribeSubnetsOutput(
+					fake.TestSubnet{Id: "foo1", Name: "bar1", Az: "baz1", Tags: map[string]string{"kubernetes.io/role/elb": ""}}), nil),
+				DescribeRouteTables: fake.R(fake.MockDescribeRouteTableOutput(
+					fake.TestRouteTable{SubnetID: "foo1", GatewayIds: []string{"igw-foo1"}},
+					fake.TestRouteTable{SubnetID: "mismatch", GatewayIds: []string{"igw-foo2"}, Main: true},
+				), nil),
+			},
+			responsesASG: fake.ASGOutputs{
+				DescribeAutoScalingGroups: fake.R(fake.MockDescribeAutoScalingGroupOutput(map[string]fake.ASGtags{"asg1": {
+					clusterIDTagPrefix + clusterID: "owned",
+				}}), nil),
+				DescribeLoadBalancerTargetGroups: fake.R(&autoscaling.DescribeLoadBalancerTargetGroupsOutput{
+					LoadBalancerTargetGroups: []*autoscaling.LoadBalancerTargetGroupState{},
+				}, nil),
+				AttachLoadBalancerTargetGroups: fake.R(nil, nil),
+			},
+			responsesELBv2: fake.ELBv2Outputs{
+				DescribeTargetGroups: fake.R(nil, nil),
+				DescribeTags:         fake.R(nil, nil),
+			},
+			responsesCF: fake.CFOutputs{
+				DescribeStackPages: fake.R(nil, nil),
+				DescribeStacks:     fake.R(nil, nil),
+				CreateStack:        fake.R(fake.MockCSOutput("42"), nil),
+			},
+			typeLB: awsAdapter.LoadBalancerTypeApplication,
+		}, {
+			name: "rg_nlb",
+			responsesEC2: fake.EC2Outputs{DescribeInstancesPages: fake.MockDescribeInstancesPagesOutput(
+				nil,
+				fake.TestInstance{
+					Id:        "i0",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.3",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i1",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.4",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i2",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.5",
+					VpcId:     vpcID,
+					State:     running,
+				}),
+				DescribeSecurityGroups: fake.R(fake.MockDescribeSecurityGroupsOutput(map[string]string{"id": securityGroupID}), nil),
+				DescribeSubnets: fake.R(fake.MockDescribeSubnetsOutput(
+					fake.TestSubnet{Id: "foo1", Name: "bar1", Az: "baz1", Tags: map[string]string{"kubernetes.io/role/elb": ""}}), nil),
+				DescribeRouteTables: fake.R(fake.MockDescribeRouteTableOutput(
+					fake.TestRouteTable{SubnetID: "foo1", GatewayIds: []string{"igw-foo1"}},
+					fake.TestRouteTable{SubnetID: "mismatch", GatewayIds: []string{"igw-foo2"}, Main: true},
+				), nil),
+			},
+			responsesASG: fake.ASGOutputs{
+				DescribeAutoScalingGroups: fake.R(fake.MockDescribeAutoScalingGroupOutput(map[string]fake.ASGtags{"asg1": {
+					clusterIDTagPrefix + clusterID: "owned",
+				}}), nil),
+				DescribeLoadBalancerTargetGroups: fake.R(&autoscaling.DescribeLoadBalancerTargetGroupsOutput{
+					LoadBalancerTargetGroups: []*autoscaling.LoadBalancerTargetGroupState{},
+				}, nil),
+				AttachLoadBalancerTargetGroups: fake.R(nil, nil),
+			},
+			responsesELBv2: fake.ELBv2Outputs{
+				DescribeTargetGroups: fake.R(nil, nil),
+				DescribeTags:         fake.R(nil, nil),
+			},
+			responsesCF: fake.CFOutputs{
+				DescribeStackPages: fake.R(nil, nil),
+				DescribeStacks:     fake.R(nil, nil),
+				CreateStack:        fake.R(fake.MockCSOutput("42"), nil),
+			},
+			typeLB: awsAdapter.LoadBalancerTypeNetwork,
+		}, {
+			name: "ing_shared_rg_notshared_alb",
+			responsesEC2: fake.EC2Outputs{DescribeInstancesPages: fake.MockDescribeInstancesPagesOutput(
+				nil,
+				fake.TestInstance{
+					Id:        "i0",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.3",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i1",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.4",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i2",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.5",
+					VpcId:     vpcID,
+					State:     running,
+				}),
+				DescribeSecurityGroups: fake.R(fake.MockDescribeSecurityGroupsOutput(map[string]string{"id": securityGroupID}), nil),
+				DescribeSubnets: fake.R(fake.MockDescribeSubnetsOutput(
+					fake.TestSubnet{Id: "foo1", Name: "bar1", Az: "baz1", Tags: map[string]string{"kubernetes.io/role/elb": ""}}), nil),
+				DescribeRouteTables: fake.R(fake.MockDescribeRouteTableOutput(
+					fake.TestRouteTable{SubnetID: "foo1", GatewayIds: []string{"igw-foo1"}},
+					fake.TestRouteTable{SubnetID: "mismatch", GatewayIds: []string{"igw-foo2"}, Main: true},
+				), nil),
+			},
+			responsesASG: fake.ASGOutputs{
+				DescribeAutoScalingGroups: fake.R(fake.MockDescribeAutoScalingGroupOutput(map[string]fake.ASGtags{"asg1": {
+					clusterIDTagPrefix + clusterID: "owned",
+				}}), nil),
+				DescribeLoadBalancerTargetGroups: fake.R(&autoscaling.DescribeLoadBalancerTargetGroupsOutput{
+					LoadBalancerTargetGroups: []*autoscaling.LoadBalancerTargetGroupState{},
+				}, nil),
+				AttachLoadBalancerTargetGroups: fake.R(nil, nil),
+			},
+			responsesELBv2: fake.ELBv2Outputs{
+				DescribeTargetGroups: fake.R(nil, nil),
+				DescribeTags:         fake.R(nil, nil),
+			},
+			responsesCF: fake.CFOutputs{
+				DescribeStackPages: fake.R(nil, nil),
+				DescribeStacks:     fake.R(nil, nil),
+				CreateStack:        fake.R(fake.MockCSOutput("42"), nil),
+			},
+			typeLB: awsAdapter.LoadBalancerTypeApplication,
+		}, {
+			name: "ingress_rg_shared_alb",
+			responsesEC2: fake.EC2Outputs{DescribeInstancesPages: fake.MockDescribeInstancesPagesOutput(
+				nil,
+				fake.TestInstance{
+					Id:        "i0",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.3",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i1",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.4",
+					VpcId:     vpcID,
+					State:     running,
+				},
+				fake.TestInstance{
+					Id:        "i2",
+					Tags:      fake.Tags{"aws:autoscaling:groupName": "asg1", clusterIDTagPrefix + clusterID: "owned"},
+					PrivateIp: "1.2.3.5",
+					VpcId:     vpcID,
+					State:     running,
+				}),
+				DescribeSecurityGroups: fake.R(fake.MockDescribeSecurityGroupsOutput(map[string]string{"id": securityGroupID}), nil),
+				DescribeSubnets: fake.R(fake.MockDescribeSubnetsOutput(
+					fake.TestSubnet{Id: "foo1", Name: "bar1", Az: "baz1", Tags: map[string]string{"kubernetes.io/role/elb": ""}}), nil),
+				DescribeRouteTables: fake.R(fake.MockDescribeRouteTableOutput(
+					fake.TestRouteTable{SubnetID: "foo1", GatewayIds: []string{"igw-foo1"}},
+					fake.TestRouteTable{SubnetID: "mismatch", GatewayIds: []string{"igw-foo2"}, Main: true},
+				), nil),
+			},
+			responsesASG: fake.ASGOutputs{
+				DescribeAutoScalingGroups: fake.R(fake.MockDescribeAutoScalingGroupOutput(map[string]fake.ASGtags{"asg1": {
+					clusterIDTagPrefix + clusterID: "owned",
+				}}), nil),
+				DescribeLoadBalancerTargetGroups: fake.R(&autoscaling.DescribeLoadBalancerTargetGroupsOutput{
+					LoadBalancerTargetGroups: []*autoscaling.LoadBalancerTargetGroupState{},
+				}, nil),
+				AttachLoadBalancerTargetGroups: fake.R(nil, nil),
+			},
+			responsesELBv2: fake.ELBv2Outputs{
+				DescribeTargetGroups: fake.R(nil, nil),
+				DescribeTags:         fake.R(nil, nil),
+			},
+			responsesCF: fake.CFOutputs{
+				DescribeStackPages: fake.R(nil, nil),
+				DescribeStacks:     fake.R(nil, nil),
+				CreateStack:        fake.R(fake.MockCSOutput("42"), nil),
+			},
+			typeLB: awsAdapter.LoadBalancerTypeApplication,
+		}, {
+			name: "ingress_rg_shared_nlb",
 			responsesEC2: fake.EC2Outputs{DescribeInstancesPages: fake.MockDescribeInstancesPagesOutput(
 				nil,
 				fake.TestInstance{
@@ -151,7 +412,7 @@ func TestResourceConversion(tt *testing.T) {
 	} {
 		tt.Run(scenario.name, func(t *testing.T) {
 			readFile := func(fileName string) []byte {
-				b, err := os.ReadFile("./testdata/" + scenario.name + "/" + fileName)
+				b, err := os.ReadFile("./testdata/" + scenario.name + "/output/" + fileName)
 				if err != nil {
 					t.Fatal(err)
 				}
@@ -159,20 +420,46 @@ func TestResourceConversion(tt *testing.T) {
 				return b
 			}
 
-			template := string(readFile("template.cf"))
+			var templates []string
+			templateFiles, err := os.ReadDir("./testdata/" + scenario.name + "/output/templates/")
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			for _, file := range templateFiles {
+				templates = append(templates, string(readFile("templates/"+file.Name())))
+			}
 
-			var tags []*cf.Tag
-			err := json.Unmarshal(readFile("tags.json"), &tags)
+			paramFiles, err := os.ReadDir("./testdata/" + scenario.name + "/output/params/")
 			if err != nil {
 				t.Fatal(err)
 			}
 
-			var params []*cf.Parameter
-			err = json.Unmarshal(readFile("params.json"), &params)
+			var params [][]*cf.Parameter
+			for _, file := range paramFiles {
+				var content []*cf.Parameter
+				err := json.Unmarshal(readFile("params/"+file.Name()), &content)
+				if err != nil {
+					t.Fatal(err)
+				}
+				params = append(params, content)
+			}
+
+			tagFiles, err := os.ReadDir("./testdata/" + scenario.name + "/output/tags/")
 			if err != nil {
 				t.Fatal(err)
 			}
 
+			var tags [][]*cf.Tag
+			for _, file := range tagFiles {
+				var content []*cf.Tag
+				err := json.Unmarshal(readFile("tags/"+file.Name()), &content)
+				if err != nil {
+					t.Fatal(err)
+				}
+				tags = append(tags, content)
+			}
+
 			clientEC2 := &fake.EC2Client{Outputs: scenario.responsesEC2}
 			clientASG := &fake.ASGClient{Outputs: scenario.responsesASG}
 			clientELBv2 := &fake.ELBv2Client{Outputs: scenario.responsesELBv2}
@@ -188,15 +475,25 @@ func TestResourceConversion(tt *testing.T) {
 
 			a, err = a.UpdateManifest(clusterID, vpcID)
 			if err != nil {
-				t.Error(err)
+				t.Fatal(err)
 			}
 
-			f, err := os.Open("./testdata/" + scenario.name + "/ing.yaml")
+			readers := make([]io.Reader, 0)
+			files, err := os.ReadDir("./testdata/" + scenario.name + "/input/k8s/")
 			if err != nil {
 				t.Fatal(err)
 			}
 
-			api, err := kubernetestest.NewAPI(kubernetestest.TestAPIOptions{}, f)
+			for _, file := range files {
+				f, err := os.Open("./testdata/" + scenario.name + "/input/k8s/" + file.Name())
+				if err != nil {
+					t.Fatal(err)
+				}
+				readers = append(readers, f)
+				defer f.Close()
+			}
+
+			api, err := kubernetestest.NewAPI(kubernetestest.TestAPIOptions{}, readers...)
 			if err != nil {
 				t.Fatal(err)
 			}
@@ -223,36 +520,48 @@ func TestResourceConversion(tt *testing.T) {
 			if err != nil {
 				t.Fatal(err)
 			}
+
 			log.SetLevel(log.DebugLevel)
 			problems := doWork(&certsfake.CertificateProvider{}, 10, time.Hour, a, k, "")
 			if len(problems.Errors()) > 0 {
 				t.Error(problems.Errors())
 			}
 
-			// When a stack is created using cloud formation API the stack information is sent in a split way.
-			// There is a template with the description of the stack, but this template references parameters
-			// and tags that are not defined in this template. These parameters and tags are sent as different
-			// fields in the request.
-			// That is why when we validate the content of the template we also need to check the parameters
-			// and tags and this is why this check is split in three parts, we check the template,
-			// the parameters and tags generated by the ingress controller and not only the template.
-			assert.Equal(
-				t,
-				template,
-				clientCF.GetLastStackTemplate(),
-			)
-
-			assert.ElementsMatch(
-				t,
-				tags,
-				clientCF.GetLastStackTags(),
-			)
-
-			assert.ElementsMatch(
-				t,
-				params,
-				clientCF.GetLastStackParams(),
-			)
+			assert.Equal(t, len(clientCF.GetTagCreationHistory()), len(tags))
+			assert.Equal(t, len(clientCF.GetParamCreationHistory()), len(params))
+			assert.Equal(t, len(clientCF.GetTemplateCreationHistory()), len(templates))
+
+			// This loop is necessary because assert.ElementsMatch only do set-style comparison
+			// for the first level of the array. So for nested arrays it would not behave like expected.
+			// The order is important when loading the files, because of this its necessary to use numbers
+			// before the file name to make them in the order you want.
+			for i := range templates {
+				// When a stack is created using cloud formation API the stack information is sent in a split way.
+				// There is a template with the description of the stack, but this template references parameters
+				// and tags that are not defined in this template. These parameters and tags are sent as different
+				// fields in the request.
+				// That is why when we validate the content of the template we also need to check the parameters
+				// and tags and this is why this check is split in three parts, we check the template,
+				// the parameters and tags generated by the ingress controller and not only the template.
+				assert.Equal(
+					t,
+					templates[i],
+					clientCF.GetTemplateCreationHistory()[i],
+				)
+
+				assert.ElementsMatch(
+					t,
+					tags[i],
+					clientCF.GetTagCreationHistory()[i],
+				)
+
+				assert.ElementsMatch(
+					t,
+					params[i],
+					clientCF.GetParamCreationHistory()[i],
+				)
+			}
+			clientCF.CleanCreationHistory()
 		})
 	}
 }