Repository: klothoplatform/klotho
Pull request #815 (2023-12-08 19:57:10)

updating reconciler to understand how to delete resources in groups based on iac dependencies
makes the reconciliation check iac dependencies of namespaced resources to see if we need to clean up more than just the namespaced resources

### Standard checks

- **Unit tests**: Any special considerations?
- **Docs**: Do we need to update any docs, internal or public?
- **Backwards compatibility**: Will this break existing apps? If so, what would be the extra work required to keep them working?



Patch:
diff --git a/pkg/engine2/reconciler/reconciler.go b/pkg/engine2/reconciler/reconciler.go
index ad406dd3..06aa11fc 100644
--- a/pkg/engine2/reconciler/reconciler.go
+++ b/pkg/engine2/reconciler/reconciler.go
@@ -3,7 +3,9 @@ package reconciler
 import (
 	"errors"
 	"fmt"
+	"reflect"
 
+	"github.com/klothoplatform/klotho/pkg/collectionutil"
 	construct "github.com/klothoplatform/klotho/pkg/construct2"
 	"github.com/klothoplatform/klotho/pkg/engine2/solution_context"
 	knowledgebase "github.com/klothoplatform/klotho/pkg/knowledge_base2"
@@ -11,57 +13,187 @@ import (
 	"go.uber.org/zap"
 )
 
-func RemoveResource(c solution_context.SolutionContext, resource construct.ResourceId, explicit bool) error {
-	zap.S().Debugf("reconciling removal of resource %s ", resource)
-	upstreams, downstreams, err := construct.Neighbors(c.DataflowGraph(), resource)
-	if err != nil {
-		return err
+type (
+	deleteRequest struct {
+		resource construct.ResourceId
+		explicit bool
 	}
+)
 
-	template, err := c.KnowledgeBase().GetResourceTemplate(resource)
-	if err != nil {
-		return fmt.Errorf("unable to remove resource: error getting resource template for %s: %v", resource, err)
-	}
-	canDelete, err := canDeleteResource(c, resource, explicit, template, upstreams, downstreams)
-	if err != nil {
-		return err
-	}
-	if !canDelete {
-		return nil
-	}
+func RemoveResource(c solution_context.SolutionContext, resource construct.ResourceId, explicit bool) error {
+	zap.S().Debugf("reconciling removal of resource %s ", resource)
 
-	op := c.OperationalView()
+	queue := []deleteRequest{{
+		resource: resource,
+		explicit: explicit,
+	}}
 
 	var errs error
-	// We must remove all edges before removing the vertex
-	for res := range upstreams {
-		errs = errors.Join(errs, op.RemoveEdge(res, resource))
-	}
-	for res := range downstreams {
-		errs = errors.Join(errs, op.RemoveEdge(resource, res))
-	}
-	if errs != nil {
-		return errs
+
+	for len(queue) > 0 {
+		request := queue[0]
+		queue = queue[1:]
+		resource := request.resource
+		explicit := request.explicit
+
+		upstreams, downstreams, err := construct.Neighbors(c.DataflowGraph(), resource)
+		if err != nil {
+			errs = errors.Join(errs, err)
+			continue
+		}
+
+		template, err := c.KnowledgeBase().GetResourceTemplate(resource)
+		if err != nil {
+			errs = errors.Join(errs, fmt.Errorf("unable to remove resource: error getting resource template for %s: %v", resource, err))
+			continue
+		}
+		canDelete, err := canDeleteResource(c, resource, explicit, template, upstreams, downstreams)
+		if err != nil {
+			errs = errors.Join(errs, err)
+			continue
+		}
+		if !canDelete {
+			continue
+		}
+		// find all namespaced resources before removing edges and the initial resource, otherwise certain resources may
+		// be moved out of their original namespace
+		namespacedResources, err := findAllResourcesInNamespace(c, resource)
+		if err != nil {
+			errs = errors.Join(errs, err)
+			continue
+		}
+
+		op := c.OperationalView()
+
+		// We must remove all edges before removing the vertex
+		for res := range upstreams {
+			errs = errors.Join(errs, op.RemoveEdge(res, resource))
+		}
+		for res := range downstreams {
+			errs = errors.Join(errs, op.RemoveEdge(resource, res))
+		}
+
+		err = construct.RemoveResource(op, resource)
+		if err != nil {
+			errs = errors.Join(errs, err)
+			continue
+		}
+
+		for res := range namespacedResources {
+
+			// Since we may be explicitly deleting the namespace resource,
+			// we will forward the same explicit flag to the namespace resource
+			queue = appendToQueue(deleteRequest{resource: res, explicit: explicit}, queue)
+			// find deployment dependencies to ensure the resource wont get recreated
+			queue, err = addAllDeploymentDependencies(c, res, explicit, queue)
+			if err != nil {
+				errs = errors.Join(errs, err)
+			}
+
+		}
+		// try to cleanup, if the resource is removable
+		for res := range upstreams.Union(downstreams) {
+			queue = appendToQueue(deleteRequest{resource: res, explicit: false}, queue)
+		}
 	}
+	return errs
+}
 
-	err = construct.RemoveResource(op, resource)
-	if err != nil {
-		return err
+func appendToQueue(request deleteRequest, queue []deleteRequest) []deleteRequest {
+	for i, req := range queue {
+		if req.resource == request.resource && req.explicit == request.explicit {
+			return queue
+			// only update if it wasnt explicit previously and now it is
+		} else if req.resource == request.resource && !req.explicit {
+			queue[i] = request
+			return queue
+		} else if req.resource == request.resource && req.explicit {
+			return queue
+		}
 	}
+	return append(queue, request)
+}
+
+func addAllDeploymentDependencies(
+	ctx solution_context.SolutionContext,
+	resource construct.ResourceId,
+	explicit bool,
+	queue []deleteRequest,
+) ([]deleteRequest, error) {
 
-	namespacedResources, err := findAllResourcesInNamespace(c, resource)
+	deploymentDeps, err := knowledgebase.Upstream(
+		ctx.DeploymentGraph(),
+		ctx.KnowledgeBase(),
+		resource,
+		knowledgebase.ResourceDirectLayer,
+	)
 	if err != nil {
-		return err
-	}
-	for _, res := range namespacedResources.ToSlice() {
-		// Since we are explicitly deleting the namespace resource, we will explicitly delete the resources namespaced to it
-		errs = errors.Join(errs, RemoveResource(c, res, explicit))
+		return nil, err
 	}
-	// try to cleanup, if the resource is removable
-	for res := range upstreams.Union(downstreams) {
-		errs = errors.Join(errs, RemoveResource(c, res, false))
+
+	for _, dep := range deploymentDeps {
+		res, err := ctx.RawView().Vertex(dep)
+		if err != nil {
+			return nil, err
+		}
+		rt, err := ctx.KnowledgeBase().GetResourceTemplate(dep)
+		if err != nil {
+			return nil, err
+		}
+		if collectionutil.Contains(queue, deleteRequest{resource: dep, explicit: explicit}) {
+			continue
+		}
+
+		shouldDelete := false
+
+		// check if the dep exists as a property on the resource
+		err = rt.LoopProperties(res, func(p knowledgebase.Property) error {
+			propVal, err := res.GetProperty(p.Details().Path)
+			if err != nil {
+				return err
+			}
+			found := false
+			switch val := propVal.(type) {
+			case construct.ResourceId:
+				if val == resource {
+					found = true
+				}
+			case construct.PropertyRef:
+				if val.Resource == resource {
+					found = true
+				}
+			default:
+				if reflect.ValueOf(val).Kind() == reflect.Slice || reflect.ValueOf(val).Kind() == reflect.Array {
+					for i := 0; i < reflect.ValueOf(val).Len(); i++ {
+						idVal := reflect.ValueOf(val).Index(i).Interface()
+						if id, ok := idVal.(construct.ResourceId); ok && id == resource {
+							found = true
+						} else if pref, ok := idVal.(construct.PropertyRef); ok && pref.Resource == resource {
+							found = true
+						}
+					}
+				}
+			}
+			if found {
+				if p.Details().OperationalRule != nil || p.Details().Required {
+					shouldDelete = true
+				}
+			}
+			return nil
+		})
+		if err != nil {
+			return nil, err
+		}
+
+		if shouldDelete {
+			queue = appendToQueue(deleteRequest{resource: dep, explicit: explicit}, queue)
+			queue, err = addAllDeploymentDependencies(ctx, dep, explicit, queue)
+			if err != nil {
+				return nil, err
+			}
+		}
 	}
-	return nil
+	return queue, nil
 }
 
 func canDeleteResource(
diff --git a/pkg/templates/aws/resources/api_integration.yaml b/pkg/templates/aws/resources/api_integration.yaml
index b11c3158..5b6d601b 100644
--- a/pkg/templates/aws/resources/api_integration.yaml
+++ b/pkg/templates/aws/resources/api_integration.yaml
@@ -103,7 +103,7 @@ classification:
     - api_integration
 
 delete_context:
-  requires_no_upstream_or_downstream: true
+  requires_no_upstream: true
 
 views:
   dataflow: big
diff --git a/pkg/templates/aws/resources/route_table.yaml b/pkg/templates/aws/resources/route_table.yaml
index 7d7346b5..0c880ef8 100644
--- a/pkg/templates/aws/resources/route_table.yaml
+++ b/pkg/templates/aws/resources/route_table.yaml
@@ -4,6 +4,8 @@ display_name: Route Table
 properties:
   Vpc:
     type: resource(aws:vpc)
+    required: true
+    namespace: true
     operational_rule:
       step:
         direction: downstream


Test patch:
diff --git a/pkg/engine2/reconciler/reconciler_test.go b/pkg/engine2/reconciler/reconciler_test.go
index 8fdd312d..e6c3bd24 100644
--- a/pkg/engine2/reconciler/reconciler_test.go
+++ b/pkg/engine2/reconciler/reconciler_test.go
@@ -12,6 +12,381 @@ import (
 	"github.com/stretchr/testify/mock"
 )
 
+func Test_appendToQueue(t *testing.T) {
+	type args struct {
+		queue []deleteRequest
+		req   deleteRequest
+	}
+	tests := []struct {
+		name string
+		args args
+		want []deleteRequest
+	}{
+		{
+			name: "append to empty queue",
+			args: args{
+				queue: []deleteRequest{},
+				req: deleteRequest{
+					resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+					explicit: true,
+				},
+			},
+			want: []deleteRequest{
+				{
+					resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+					explicit: true,
+				},
+			},
+		},
+		{
+			name: "append to non empty queue",
+			args: args{
+				queue: []deleteRequest{
+					{
+						resource: construct.ResourceId{Provider: "one", Type: "one", Name: "two"},
+						explicit: true,
+					},
+				},
+				req: deleteRequest{
+					resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+					explicit: true,
+				},
+			},
+			want: []deleteRequest{
+				{
+					resource: construct.ResourceId{Provider: "one", Type: "one", Name: "two"},
+					explicit: true,
+				},
+				{
+					resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+					explicit: true,
+				},
+			},
+		},
+		{
+			name: "append explicit overwrites non explicit",
+			args: args{
+				queue: []deleteRequest{
+					{
+						resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+						explicit: false,
+					},
+				},
+				req: deleteRequest{
+					resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+					explicit: true,
+				},
+			},
+			want: []deleteRequest{
+				{
+					resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+					explicit: true,
+				},
+			},
+		},
+		{
+			name: "append non-explicit does not overwrites non explicit",
+			args: args{
+				queue: []deleteRequest{
+					{
+						resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+						explicit: true,
+					},
+				},
+				req: deleteRequest{
+					resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+					explicit: false,
+				},
+			},
+			want: []deleteRequest{
+				{
+					resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+					explicit: true,
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert := assert.New(t)
+			got := appendToQueue(tt.args.req, tt.args.queue)
+			assert.Equal(tt.want, got)
+		})
+	}
+}
+
+func Test_addAllDeploymentDependencies(t *testing.T) {
+	type args struct {
+		resource construct.ResourceId
+		explicit bool
+	}
+	tests := []struct {
+		name              string
+		args              args
+		upstreamResources []*construct.Resource
+		mockKBCalls       []mock.Call
+		want              []deleteRequest
+		wantErr           bool
+	}{
+		{
+			name: "no dependencies",
+			args: args{
+				resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+				explicit: true,
+			},
+		},
+		{
+			name: "single iac dependency with property that has op rule",
+			args: args{
+				resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+				explicit: true,
+			},
+			upstreamResources: []*construct.Resource{
+				{
+					ID: construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					Properties: construct.Properties{
+						"one": construct.PropertyRef{
+							Resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+							Property: "name",
+						},
+					},
+				},
+			},
+			mockKBCalls: []mock.Call{
+				{
+					Method: "GetResourceTemplate",
+					Arguments: mock.Arguments{
+						construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					},
+					ReturnArguments: mock.Arguments{
+						&knowledgebase.ResourceTemplate{
+							Properties: knowledgebase.Properties{
+								"one": &properties.StringProperty{
+									PropertyDetails: knowledgebase.PropertyDetails{
+										Path:            "one",
+										Name:            "one",
+										OperationalRule: &knowledgebase.PropertyRule{},
+									},
+								},
+							},
+						},
+						nil,
+					},
+				},
+			},
+			want: []deleteRequest{
+				{
+					resource: construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					explicit: true,
+				},
+			},
+		},
+		{
+			name: "single iac dependency with property that is required",
+			args: args{
+				resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+				explicit: true,
+			},
+			upstreamResources: []*construct.Resource{
+				{
+					ID: construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					Properties: construct.Properties{
+						"one": construct.PropertyRef{
+							Resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+							Property: "name",
+						},
+					},
+				},
+			},
+			mockKBCalls: []mock.Call{
+				{
+					Method: "GetResourceTemplate",
+					Arguments: mock.Arguments{
+						construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					},
+					ReturnArguments: mock.Arguments{
+						&knowledgebase.ResourceTemplate{
+							Properties: knowledgebase.Properties{
+								"one": &properties.StringProperty{
+									PropertyDetails: knowledgebase.PropertyDetails{
+										Path:     "one",
+										Name:     "one",
+										Required: true,
+									},
+								},
+							},
+						},
+						nil,
+					},
+				},
+			},
+			want: []deleteRequest{
+				{
+					resource: construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					explicit: true,
+				},
+			},
+		},
+		{
+			name: "single iac dependency as resource with property that is required",
+			args: args{
+				resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+				explicit: true,
+			},
+			upstreamResources: []*construct.Resource{
+				{
+					ID: construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					Properties: construct.Properties{
+						"one": construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+					},
+				},
+			},
+			mockKBCalls: []mock.Call{
+				{
+					Method: "GetResourceTemplate",
+					Arguments: mock.Arguments{
+						construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					},
+					ReturnArguments: mock.Arguments{
+						&knowledgebase.ResourceTemplate{
+							Properties: knowledgebase.Properties{
+								"one": &properties.StringProperty{
+									PropertyDetails: knowledgebase.PropertyDetails{
+										Path:     "one",
+										Name:     "one",
+										Required: true,
+									},
+								},
+							},
+						},
+						nil,
+					},
+				},
+			},
+			want: []deleteRequest{
+				{
+					resource: construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					explicit: true,
+				},
+			},
+		},
+		{
+			name: "single iac dependency as array with property that is required",
+			args: args{
+				resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+				explicit: true,
+			},
+			upstreamResources: []*construct.Resource{
+				{
+					ID: construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					Properties: construct.Properties{
+						"one": []construct.ResourceId{{Provider: "one", Type: "one", Name: "one"}},
+					},
+				},
+			},
+			mockKBCalls: []mock.Call{
+				{
+					Method: "GetResourceTemplate",
+					Arguments: mock.Arguments{
+						construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					},
+					ReturnArguments: mock.Arguments{
+						&knowledgebase.ResourceTemplate{
+							Properties: knowledgebase.Properties{
+								"one": &properties.StringProperty{
+									PropertyDetails: knowledgebase.PropertyDetails{
+										Path:     "one",
+										Name:     "one",
+										Required: true,
+									},
+								},
+							},
+						},
+						nil,
+					},
+				},
+			},
+			want: []deleteRequest{
+				{
+					resource: construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					explicit: true,
+				},
+			},
+		},
+		{
+			name: "single iac dependency not added with property that is not required and no op rule",
+			args: args{
+				resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+				explicit: true,
+			},
+			upstreamResources: []*construct.Resource{
+				{
+					ID: construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					Properties: construct.Properties{
+						"one": construct.PropertyRef{
+							Resource: construct.ResourceId{Provider: "one", Type: "one", Name: "one"},
+							Property: "name",
+						},
+					},
+				},
+			},
+			mockKBCalls: []mock.Call{
+				{
+					Method: "GetResourceTemplate",
+					Arguments: mock.Arguments{
+						construct.ResourceId{Provider: "one", Type: "two", Name: "two"},
+					},
+					ReturnArguments: mock.Arguments{
+						&knowledgebase.ResourceTemplate{
+							Properties: knowledgebase.Properties{
+								"one": &properties.StringProperty{
+									PropertyDetails: knowledgebase.PropertyDetails{
+										Path: "one",
+										Name: "one",
+									},
+								},
+							},
+						},
+						nil,
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert := assert.New(t)
+			sol := enginetesting.NewTestSolution()
+			sol.KB.On("GetResourceTemplate", mock.Anything).Return(&knowledgebase.ResourceTemplate{}, nil)
+			sol.KB.On("GetEdgeTemplate", mock.Anything, mock.Anything).Return(&knowledgebase.EdgeTemplate{}, nil)
+			sol.LoadState(t, tt.args.resource.String())
+			for _, resource := range tt.upstreamResources {
+				err := sol.RawView().AddVertex(resource)
+				if !assert.NoError(err) {
+					return
+				}
+				err = sol.RawView().AddEdge(resource.ID, tt.args.resource)
+				if !assert.NoError(err) {
+					return
+				}
+			}
+			sol.KB.On("GetResourceTemplate", mock.Anything).Unset()
+			for _, call := range tt.mockKBCalls {
+				sol.KB.On(call.Method, call.Arguments...).Return(call.ReturnArguments...)
+			}
+			got, err := addAllDeploymentDependencies(sol, tt.args.resource, tt.args.explicit, []deleteRequest{})
+			if tt.wantErr {
+				assert.Error(err)
+				return
+			}
+			if !assert.NoError(err) {
+				return
+			}
+			assert.ElementsMatch(tt.want, got)
+		})
+	}
+}
+
 func Test_canDeleteResource(t *testing.T) {
 	type args struct {
 		resource    construct.ResourceId
diff --git a/pkg/engine2/testdata/delete_namespace_resource.dataflow-viz.yaml b/pkg/engine2/testdata/delete_namespace_resource.dataflow-viz.yaml
new file mode 100644
index 00000000..d1ee6387
--- /dev/null
+++ b/pkg/engine2/testdata/delete_namespace_resource.dataflow-viz.yaml
@@ -0,0 +1,6 @@
+provider: aws
+resources:
+  lambda_function/lambda_function_2:
+    children: aws:ecr_image:lambda_function_2-image,aws:iam_role:lambda_function_2-ExecutionRole,aws:log_group:lambda_function_2-log-group
+
+
diff --git a/pkg/engine2/testdata/delete_namespace_resource.expect.yaml b/pkg/engine2/testdata/delete_namespace_resource.expect.yaml
new file mode 100644
index 00000000..00532531
--- /dev/null
+++ b/pkg/engine2/testdata/delete_namespace_resource.expect.yaml
@@ -0,0 +1,36 @@
+resources:
+    aws:lambda_function:lambda_function_2:
+        ExecutionRole: aws:iam_role:lambda_function_2-ExecutionRole
+        Image: aws:ecr_image:lambda_function_2-image
+        LogGroup: aws:log_group:lambda_function_2-log-group
+        MemorySize: 512
+        Timeout: 180
+    aws:SERVICE_API:lambda_function_2-lambda_function_2-log-group:
+    aws:ecr_image:lambda_function_2-image:
+        Context: .
+        Dockerfile: lambda_function_2-image.Dockerfile
+        Repo: aws:ecr_repo:ecr_repo-0
+    aws:iam_role:lambda_function_2-ExecutionRole:
+        AssumeRolePolicyDoc:
+            Statement:
+                - Action:
+                    - sts:AssumeRole
+                  Effect: Allow
+                  Principal:
+                    Service:
+                        - lambda.amazonaws.com
+            Version: "2012-10-17"
+        ManagedPolicies:
+            - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
+    aws:ecr_repo:ecr_repo-0:
+        ForceDelete: true
+    aws:log_group:lambda_function_2-log-group:
+        LogGroupName: /aws/lambda/lambda_function_2
+        RetentionInDays: 5
+edges:
+    aws:lambda_function:lambda_function_2 -> aws:SERVICE_API:lambda_function_2-lambda_function_2-log-group:
+    aws:lambda_function:lambda_function_2 -> aws:ecr_image:lambda_function_2-image:
+    aws:lambda_function:lambda_function_2 -> aws:iam_role:lambda_function_2-ExecutionRole:
+    aws:SERVICE_API:lambda_function_2-lambda_function_2-log-group -> aws:log_group:lambda_function_2-log-group:
+    aws:ecr_image:lambda_function_2-image -> aws:ecr_repo:ecr_repo-0:
+    aws:iam_role:lambda_function_2-ExecutionRole -> aws:log_group:lambda_function_2-log-group:
diff --git a/pkg/engine2/testdata/delete_namespace_resource.iac-viz.yaml b/pkg/engine2/testdata/delete_namespace_resource.iac-viz.yaml
new file mode 100644
index 00000000..ac822a52
--- /dev/null
+++ b/pkg/engine2/testdata/delete_namespace_resource.iac-viz.yaml
@@ -0,0 +1,16 @@
+provider: aws
+resources:
+  ecr_repo/ecr_repo-0:
+
+  log_group/lambda_function_2-log-group:
+
+  ecr_image/lambda_function_2-image:
+  ecr_image/lambda_function_2-image -> ecr_repo/ecr_repo-0:
+
+  iam_role/lambda_function_2-executionrole:
+  iam_role/lambda_function_2-executionrole -> log_group/lambda_function_2-log-group:
+
+  lambda_function/lambda_function_2:
+  lambda_function/lambda_function_2 -> ecr_image/lambda_function_2-image:
+  lambda_function/lambda_function_2 -> iam_role/lambda_function_2-executionrole:
+
diff --git a/pkg/engine2/testdata/delete_namespace_resource.input.yaml b/pkg/engine2/testdata/delete_namespace_resource.input.yaml
new file mode 100644
index 00000000..aa3bc708
--- /dev/null
+++ b/pkg/engine2/testdata/delete_namespace_resource.input.yaml
@@ -0,0 +1,85 @@
+constraints:
+- node: aws:rest_api:rest_api_0
+  operator: remove
+  scope: application
+resources:
+    aws:api_stage:rest_api_0:api_stage-0:
+        Deployment: aws:api_deployment:rest_api_0:api_deployment-0
+        RestApi: aws:rest_api:rest_api_0
+        StageName: stage
+    aws:lambda_function:lambda_function_2:
+        ExecutionRole: aws:iam_role:lambda_function_2-ExecutionRole
+        Image: aws:ecr_image:lambda_function_2-image
+        LogGroup: aws:log_group:lambda_function_2-log-group
+        MemorySize: 512
+        Timeout: 180
+    aws:api_deployment:rest_api_0:api_deployment-0:
+        RestApi: aws:rest_api:rest_api_0
+        Triggers:
+            rest_api_0_integration_0: rest_api_0_integration_0
+            rest_api_0_integration_0_method: rest_api_0_integration_0_method
+    aws:SERVICE_API:lambda_function_2-lambda_function_2-log-group:
+    aws:ecr_image:lambda_function_2-image:
+        Context: .
+        Dockerfile: lambda_function_2-image.Dockerfile
+        Repo: aws:ecr_repo:ecr_repo-0
+    aws:iam_role:lambda_function_2-ExecutionRole:
+        AssumeRolePolicyDoc:
+            Statement:
+                - Action:
+                    - sts:AssumeRole
+                  Effect: Allow
+                  Principal:
+                    Service:
+                        - lambda.amazonaws.com
+            Version: "2012-10-17"
+        ManagedPolicies:
+            - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
+    aws:rest_api:rest_api_0:
+        BinaryMediaTypes:
+            - application/octet-stream
+            - image/*
+        Stages:
+            - aws:api_stage:rest_api_0:api_stage-0
+    aws:ecr_repo:ecr_repo-0:
+        ForceDelete: true
+    aws:log_group:lambda_function_2-log-group:
+        LogGroupName: /aws/lambda/lambda_function_2
+        RetentionInDays: 5
+    aws:api_resource:rest_api_0:api_resource-0:
+        FullPath: /{proxy+}
+        PathPart: '{proxy+}'
+        RestApi: aws:rest_api:rest_api_0
+    aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+        Authorization: NONE
+        HttpMethod: ANY
+        RequestParameters:
+            method.request.path.proxy: true
+        Resource: aws:api_resource:rest_api_0:api_resource-0
+        RestApi: aws:rest_api:rest_api_0
+    aws:api_integration:rest_api_0:rest_api_0_integration_0:
+        IntegrationHttpMethod: ANY
+        Method: aws:api_method:rest_api_0:rest_api_0_integration_0_method
+        RequestParameters:
+            integration.request.path.proxy: method.request.path.proxy
+        Resource: aws:api_resource:rest_api_0:api_resource-0
+        RestApi: aws:rest_api:rest_api_0
+        Route: /{proxy+}
+edges:
+    aws:api_stage:rest_api_0:api_stage-0 -> aws:api_deployment:rest_api_0:api_deployment-0:
+    aws:api_stage:rest_api_0:api_stage-0 -> aws:rest_api:rest_api_0:
+    aws:lambda_function:lambda_function_2 -> aws:SERVICE_API:lambda_function_2-lambda_function_2-log-group:
+    aws:lambda_function:lambda_function_2 -> aws:ecr_image:lambda_function_2-image:
+    aws:lambda_function:lambda_function_2 -> aws:iam_role:lambda_function_2-ExecutionRole:
+    aws:api_deployment:rest_api_0:api_deployment-0 -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:api_deployment:rest_api_0:api_deployment-0 -> aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+    aws:api_deployment:rest_api_0:api_deployment-0 -> aws:rest_api:rest_api_0:
+    aws:SERVICE_API:lambda_function_2-lambda_function_2-log-group -> aws:log_group:lambda_function_2-log-group:
+    aws:ecr_image:lambda_function_2-image -> aws:ecr_repo:ecr_repo-0:
+    aws:iam_role:lambda_function_2-ExecutionRole -> aws:log_group:lambda_function_2-log-group:
+    aws:rest_api:rest_api_0 -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:rest_api:rest_api_0 -> aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+    aws:rest_api:rest_api_0 -> aws:api_resource:rest_api_0:api_resource-0:
+    aws:api_resource:rest_api_0:api_resource-0 -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:api_resource:rest_api_0:api_resource-0 -> aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+    aws:api_method:rest_api_0:rest_api_0_integration_0_method -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
diff --git a/pkg/engine2/testdata/delete_resource_and_iacdeps.dataflow-viz.yaml b/pkg/engine2/testdata/delete_resource_and_iacdeps.dataflow-viz.yaml
new file mode 100644
index 00000000..694483be
--- /dev/null
+++ b/pkg/engine2/testdata/delete_resource_and_iacdeps.dataflow-viz.yaml
@@ -0,0 +1,8 @@
+provider: aws
+resources:
+  rest_api/rest_api_0:
+
+  aws:api_integration:rest_api_0/rest_api_0_integration_0:
+    parent: rest_api/rest_api_0
+
+
diff --git a/pkg/engine2/testdata/delete_resource_and_iacdeps.expect.yaml b/pkg/engine2/testdata/delete_resource_and_iacdeps.expect.yaml
new file mode 100644
index 00000000..55134a9a
--- /dev/null
+++ b/pkg/engine2/testdata/delete_resource_and_iacdeps.expect.yaml
@@ -0,0 +1,51 @@
+resources:
+    aws:api_stage:rest_api_0:api_stage-0:
+        Deployment: aws:api_deployment:rest_api_0:api_deployment-0
+        RestApi: aws:rest_api:rest_api_0
+        StageName: stage
+    aws:ecs_cluster:ecs_cluster-0:
+    aws:api_deployment:rest_api_0:api_deployment-0:
+        RestApi: aws:rest_api:rest_api_0
+        Triggers:
+            rest_api_0_integration_0: rest_api_0_integration_0
+            rest_api_0_integration_0_method: rest_api_0_integration_0_method
+    aws:rest_api:rest_api_0:
+        BinaryMediaTypes:
+            - application/octet-stream
+            - image/*
+        Stages:
+            - aws:api_stage:rest_api_0:api_stage-0
+    aws:api_resource:rest_api_0:api_resource-0:
+        FullPath: /{proxy+}
+        PathPart: '{proxy+}'
+        RestApi: aws:rest_api:rest_api_0
+    aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+        Authorization: NONE
+        HttpMethod: ANY
+        RequestParameters:
+            method.request.path.proxy: true
+        Resource: aws:api_resource:rest_api_0:api_resource-0
+        RestApi: aws:rest_api:rest_api_0
+    aws:api_integration:rest_api_0:rest_api_0_integration_0:
+        ConnectionType: VPC_LINK
+        IntegrationHttpMethod: ANY
+        Method: aws:api_method:rest_api_0:rest_api_0_integration_0_method
+        RequestParameters:
+            integration.request.path.proxy: method.request.path.proxy
+        Resource: aws:api_resource:rest_api_0:api_resource-0
+        RestApi: aws:rest_api:rest_api_0
+        Route: /{proxy+}
+        Type: HTTP_PROXY
+        Uri: aws:api_integration:rest_api_0:rest_api_0_integration_0#LbUri
+edges:
+    aws:api_stage:rest_api_0:api_stage-0 -> aws:api_deployment:rest_api_0:api_deployment-0:
+    aws:api_stage:rest_api_0:api_stage-0 -> aws:rest_api:rest_api_0:
+    aws:api_deployment:rest_api_0:api_deployment-0 -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:api_deployment:rest_api_0:api_deployment-0 -> aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+    aws:api_deployment:rest_api_0:api_deployment-0 -> aws:rest_api:rest_api_0:
+    aws:rest_api:rest_api_0 -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:rest_api:rest_api_0 -> aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+    aws:rest_api:rest_api_0 -> aws:api_resource:rest_api_0:api_resource-0:
+    aws:api_resource:rest_api_0:api_resource-0 -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:api_resource:rest_api_0:api_resource-0 -> aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+    aws:api_method:rest_api_0:rest_api_0_integration_0_method -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
diff --git a/pkg/engine2/testdata/delete_resource_and_iacdeps.iac-viz.yaml b/pkg/engine2/testdata/delete_resource_and_iacdeps.iac-viz.yaml
new file mode 100644
index 00000000..23606bb1
--- /dev/null
+++ b/pkg/engine2/testdata/delete_resource_and_iacdeps.iac-viz.yaml
@@ -0,0 +1,27 @@
+provider: aws
+resources:
+  rest_api/rest_api_0:
+
+  aws:api_resource:rest_api_0/api_resource-0:
+  aws:api_resource:rest_api_0/api_resource-0 -> rest_api/rest_api_0:
+
+  aws:api_method:rest_api_0/rest_api_0_integration_0_method:
+  aws:api_method:rest_api_0/rest_api_0_integration_0_method -> aws:api_resource:rest_api_0/api_resource-0:
+  aws:api_method:rest_api_0/rest_api_0_integration_0_method -> rest_api/rest_api_0:
+
+  aws:api_integration:rest_api_0/rest_api_0_integration_0:
+  aws:api_integration:rest_api_0/rest_api_0_integration_0 -> aws:api_method:rest_api_0/rest_api_0_integration_0_method:
+  aws:api_integration:rest_api_0/rest_api_0_integration_0 -> aws:api_resource:rest_api_0/api_resource-0:
+  aws:api_integration:rest_api_0/rest_api_0_integration_0 -> rest_api/rest_api_0:
+
+  aws:api_deployment:rest_api_0/api_deployment-0:
+  aws:api_deployment:rest_api_0/api_deployment-0 -> aws:api_integration:rest_api_0/rest_api_0_integration_0:
+  aws:api_deployment:rest_api_0/api_deployment-0 -> aws:api_method:rest_api_0/rest_api_0_integration_0_method:
+  aws:api_deployment:rest_api_0/api_deployment-0 -> rest_api/rest_api_0:
+
+  ecs_cluster/ecs_cluster-0:
+
+  aws:api_stage:rest_api_0/api_stage-0:
+  aws:api_stage:rest_api_0/api_stage-0 -> aws:api_deployment:rest_api_0/api_deployment-0:
+  aws:api_stage:rest_api_0/api_stage-0 -> rest_api/rest_api_0:
+
diff --git a/pkg/engine2/testdata/delete_resource_and_iacdeps.input.yaml b/pkg/engine2/testdata/delete_resource_and_iacdeps.input.yaml
new file mode 100644
index 00000000..63788be8
--- /dev/null
+++ b/pkg/engine2/testdata/delete_resource_and_iacdeps.input.yaml
@@ -0,0 +1,360 @@
+constraints:
+- node: aws:vpc:vpc-0
+  operator: remove
+  scope: application
+resources:
+    aws:api_stage:rest_api_0:api_stage-0:
+        Deployment: aws:api_deployment:rest_api_0:api_deployment-0
+        RestApi: aws:rest_api:rest_api_0
+        StageName: stage
+    aws:api_deployment:rest_api_0:api_deployment-0:
+        RestApi: aws:rest_api:rest_api_0
+        Triggers:
+            rest_api_0_integration_0: rest_api_0_integration_0
+            rest_api_0_integration_0_method: rest_api_0_integration_0_method
+    aws:rest_api:rest_api_0:
+        BinaryMediaTypes:
+            - application/octet-stream
+            - image/*
+        Stages:
+            - aws:api_stage:rest_api_0:api_stage-0
+    aws:api_resource:rest_api_0:api_resource-0:
+        FullPath: /{proxy+}
+        PathPart: '{proxy+}'
+        RestApi: aws:rest_api:rest_api_0
+    aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+        Authorization: NONE
+        HttpMethod: ANY
+        RequestParameters:
+            method.request.path.proxy: true
+        Resource: aws:api_resource:rest_api_0:api_resource-0
+        RestApi: aws:rest_api:rest_api_0
+    aws:api_integration:rest_api_0:rest_api_0_integration_0:
+        ConnectionType: VPC_LINK
+        IntegrationHttpMethod: ANY
+        Method: aws:api_method:rest_api_0:rest_api_0_integration_0_method
+        RequestParameters:
+            integration.request.path.proxy: method.request.path.proxy
+        Resource: aws:api_resource:rest_api_0:api_resource-0
+        RestApi: aws:rest_api:rest_api_0
+        Route: /{proxy+}
+        Target: aws:load_balancer:rest-api-0-integc0d8489a
+        Type: HTTP_PROXY
+        Uri: aws:api_integration:rest_api_0:rest_api_0_integration_0#LbUri
+        VpcLink: aws:vpc_link:rest_api_0_integration_0-ecs_service_2
+    aws:vpc_link:rest_api_0_integration_0-ecs_service_2:
+        Target: aws:load_balancer:rest-api-0-integc0d8489a
+    aws:load_balancer:rest-api-0-integc0d8489a:
+        Scheme: internal
+        Subnets:
+            - aws:subnet:vpc-0:subnet-0
+            - aws:subnet:vpc-0:subnet-1
+        Type: network
+    aws:load_balancer_listener:rest_api_0_integration_0-ecs_service_2:
+        DefaultActions:
+            - TargetGroup: aws:target_group:rest-api-0-integc0d8489a
+              Type: forward
+        LoadBalancer: aws:load_balancer:rest-api-0-integc0d8489a
+        Port: 80
+        Protocol: TCP
+    aws:target_group:rest-api-0-integc0d8489a:
+        HealthCheck:
+            Enabled: true
+            HealthyThreshold: 5
+            Interval: 30
+            Matcher: 200-299
+            Protocol: TCP
+            Timeout: 5
+            UnhealthyThreshold: 2
+        Port: 80
+        Protocol: TCP
+        TargetType: ip
+        Vpc: aws:vpc:vpc-0
+    aws:ecr_image:ecs_service_2-image:
+        Context: .
+        Dockerfile: ecs_service_2-image.Dockerfile
+        Repo: aws:ecr_repo:ecr_repo-0
+    aws:ecr_repo:ecr_repo-0:
+        ForceDelete: true
+    aws:ecs_cluster:ecs_cluster-0:
+    aws:ecs_service:ecs_service_2:
+        AssignPublicIp: false
+        Cluster: aws:ecs_cluster:ecs_cluster-0
+        DesiredCount: 1
+        ForceNewDeployment: true
+        LaunchType: FARGATE
+        LoadBalancers:
+            - ContainerName: ecs_service_2
+              TargetGroup: aws:target_group:rest-api-0-integc0d8489a
+        SecurityGroups:
+            - aws:security_group:vpc-0:ecs_service_2-security_group
+        Subnets:
+            - aws:subnet:vpc-0:subnet-0
+            - aws:subnet:vpc-0:subnet-1
+        TaskDefinition: aws:ecs_task_definition:ecs_service_2
+    aws:ecs_task_definition:ecs_service_2:
+        Cpu: "256"
+        EnvironmentVariables:
+            rds-instance-4_RDS_CONNECTION_ARN: aws:rds_instance:rds-instance-4#RdsConnectionArn
+            rds-instance-4_RDS_ENDPOINT: aws:rds_instance:rds-instance-4#Endpoint
+            rds-instance-4_RDS_PASSWORD: aws:rds_instance:rds-instance-4#Password
+            rds-instance-4_RDS_USERNAME: aws:rds_instance:rds-instance-4#Username
+        ExecutionRole: aws:iam_role:ecs_service_2-execution-role
+        Image: aws:ecr_image:ecs_service_2-image
+        LogGroup: aws:log_group:ecs_service_2-log-group
+        Memory: "512"
+        NetworkMode: awsvpc
+        PortMappings:
+            - ContainerPort: 80
+              HostPort: 80
+              Protocol: TCP
+        Region: aws:region:region-0
+        RequiresCompatibilities:
+            - FARGATE
+        TaskRole: aws:iam_role:ecs_service_2-execution-role
+    aws:iam_role:ecs_service_2-execution-role:
+        AssumeRolePolicyDoc:
+            Statement:
+                - Action:
+                    - sts:AssumeRole
+                  Effect: Allow
+                  Principal:
+                    Service:
+                        - ecs-tasks.amazonaws.com
+            Version: "2012-10-17"
+        InlinePolicies:
+            - Name: rds-instance-4-policy
+              Policy:
+                Statement:
+                    - Action:
+                        - rds-db:connect
+                      Effect: Allow
+                      Resource:
+                        - aws:rds_instance:rds-instance-4#RdsConnectionArn
+                Version: "2012-10-17"
+        ManagedPolicies:
+            - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
+    aws:log_group:ecs_service_2-log-group:
+        LogGroupName: /aws/ecs/ecs_service_2
+        RetentionInDays: 5
+    aws:elastic_ip:subnet-0-route_table-nat_gateway-elastic_ip:
+    aws:elastic_ip:subnet-1-route_table-nat_gateway-elastic_ip:
+    aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway:
+        ElasticIp: aws:elastic_ip:subnet-0-route_table-nat_gateway-elastic_ip
+        Subnet: aws:subnet:vpc-0:subnet-2
+    aws:subnet:vpc-0:subnet-2:
+        AvailabilityZone: aws:availability_zone:region-0:availability_zone-0
+        CidrBlock: 10.0.0.0/18
+        MapPublicIpOnLaunch: false
+        RouteTable: aws:route_table:vpc-0:subnet-2-route_table
+        Type: public
+        Vpc: aws:vpc:vpc-0
+    aws:route_table_association:subnet-2-subnet-2-route_table:
+        RouteTable: aws:route_table:vpc-0:subnet-2-route_table
+        Subnet: aws:subnet:vpc-0:subnet-2
+    aws:route_table:vpc-0:subnet-2-route_table:
+        Routes:
+            - CidrBlock: 0.0.0.0/0
+              Gateway: aws:internet_gateway:vpc-0:internet_gateway-0
+        Vpc: aws:vpc:vpc-0
+    aws:availability_zone:region-0:availability_zone-0:
+        Index: 0
+        Region: aws:region:region-0
+    aws:internet_gateway:vpc-0:internet_gateway-0:
+        Vpc: aws:vpc:vpc-0
+    aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway:
+        ElasticIp: aws:elastic_ip:subnet-1-route_table-nat_gateway-elastic_ip
+        Subnet: aws:subnet:vpc-0:subnet-3
+    aws:subnet:vpc-0:subnet-3:
+        AvailabilityZone: aws:availability_zone:region-0:availability_zone-1
+        CidrBlock: 10.0.64.0/18
+        MapPublicIpOnLaunch: false
+        RouteTable: aws:route_table:vpc-0:subnet-3-route_table
+        Type: public
+        Vpc: aws:vpc:vpc-0
+    aws:route_table_association:subnet-3-subnet-3-route_table:
+        RouteTable: aws:route_table:vpc-0:subnet-3-route_table
+        Subnet: aws:subnet:vpc-0:subnet-3
+    aws:route_table:vpc-0:subnet-3-route_table:
+        Routes:
+            - CidrBlock: 0.0.0.0/0
+              Gateway: aws:internet_gateway:vpc-0:internet_gateway-0
+        Vpc: aws:vpc:vpc-0
+    aws:availability_zone:region-0:availability_zone-1:
+        Index: 1
+        Region: aws:region:region-0
+    aws:region:region-0:
+    aws:rds_instance:rds-instance-4:
+        AllocatedStorage: 20
+        DatabaseName: main
+        Engine: postgres
+        EngineVersion: "13.7"
+        IamDatabaseAuthenticationEnabled: true
+        InstanceClass: db.t3.micro
+        SecurityGroups:
+            - aws:security_group:vpc-0:rds-instance-4-security_group
+        SkipFinalSnapshot: true
+        SubnetGroup: aws:rds_subnet_group:rds_subnet_group-0
+    aws:rds_subnet_group:rds_subnet_group-0:
+        Subnets:
+            - aws:subnet:vpc-0:subnet-0
+            - aws:subnet:vpc-0:subnet-1
+    aws:subnet:vpc-0:subnet-0:
+        AvailabilityZone: aws:availability_zone:region-0:availability_zone-0
+        CidrBlock: 10.0.128.0/18
+        MapPublicIpOnLaunch: false
+        RouteTable: aws:route_table:vpc-0:subnet-0-route_table
+        Type: private
+        Vpc: aws:vpc:vpc-0
+    aws:subnet:vpc-0:subnet-1:
+        AvailabilityZone: aws:availability_zone:region-0:availability_zone-1
+        CidrBlock: 10.0.192.0/18
+        MapPublicIpOnLaunch: false
+        RouteTable: aws:route_table:vpc-0:subnet-1-route_table
+        Type: private
+        Vpc: aws:vpc:vpc-0
+    aws:route_table_association:subnet-0-subnet-0-route_table:
+        RouteTable: aws:route_table:vpc-0:subnet-0-route_table
+        Subnet: aws:subnet:vpc-0:subnet-0
+    aws:route_table_association:subnet-1-subnet-1-route_table:
+        RouteTable: aws:route_table:vpc-0:subnet-1-route_table
+        Subnet: aws:subnet:vpc-0:subnet-1
+    aws:security_group:vpc-0:ecs_service_2-security_group:
+        EgressRules:
+            - CidrBlocks:
+                - 0.0.0.0/0
+              Description: Allows all outbound IPv4 traffic
+              FromPort: 0
+              Protocol: "-1"
+              ToPort: 0
+        IngressRules:
+            - Description: Allow ingress traffic from within the same security group
+              FromPort: 0
+              Protocol: "-1"
+              Self: true
+              ToPort: 0
+            - CidrBlocks:
+                - 10.0.192.0/18
+              Description: Allow ingress traffic from ip addresses within the subnet subnet-1
+              FromPort: 0
+              Protocol: "-1"
+              ToPort: 0
+            - CidrBlocks:
+                - 10.0.128.0/18
+              Description: Allow ingress traffic from ip addresses within the subnet subnet-0
+              FromPort: 0
+              Protocol: "-1"
+              ToPort: 0
+        Vpc: aws:vpc:vpc-0
+    aws:security_group:vpc-0:rds-instance-4-security_group:
+        EgressRules:
+            - CidrBlocks:
+                - 0.0.0.0/0
+              Description: Allows all outbound IPv4 traffic
+              FromPort: 0
+              Protocol: "-1"
+              ToPort: 0
+        IngressRules:
+            - Description: Allow ingress traffic from within the same security group
+              FromPort: 0
+              Protocol: "-1"
+              Self: true
+              ToPort: 0
+            - CidrBlocks:
+                - 10.0.128.0/18
+              Description: Allow ingress traffic from ip addresses within the subnet subnet-0
+              FromPort: 0
+              Protocol: "-1"
+              ToPort: 0
+            - CidrBlocks:
+                - 10.0.192.0/18
+              Description: Allow ingress traffic from ip addresses within the subnet subnet-1
+              FromPort: 0
+              Protocol: "-1"
+              ToPort: 0
+        Vpc: aws:vpc:vpc-0
+    aws:route_table:vpc-0:subnet-0-route_table:
+        Routes:
+            - CidrBlock: 0.0.0.0/0
+              NatGateway: aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway
+        Vpc: aws:vpc:vpc-0
+    aws:route_table:vpc-0:subnet-1-route_table:
+        Routes:
+            - CidrBlock: 0.0.0.0/0
+              NatGateway: aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway
+        Vpc: aws:vpc:vpc-0
+    aws:vpc:vpc-0:
+        CidrBlock: 10.0.0.0/16
+        EnableDnsHostnames: true
+        EnableDnsSupport: true
+edges:
+    aws:api_stage:rest_api_0:api_stage-0 -> aws:api_deployment:rest_api_0:api_deployment-0:
+    aws:api_stage:rest_api_0:api_stage-0 -> aws:rest_api:rest_api_0:
+    aws:api_deployment:rest_api_0:api_deployment-0 -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:api_deployment:rest_api_0:api_deployment-0 -> aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+    aws:api_deployment:rest_api_0:api_deployment-0 -> aws:rest_api:rest_api_0:
+    aws:rest_api:rest_api_0 -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:rest_api:rest_api_0 -> aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+    aws:rest_api:rest_api_0 -> aws:api_resource:rest_api_0:api_resource-0:
+    aws:api_resource:rest_api_0:api_resource-0 -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:api_resource:rest_api_0:api_resource-0 -> aws:api_method:rest_api_0:rest_api_0_integration_0_method:
+    aws:api_method:rest_api_0:rest_api_0_integration_0_method -> aws:api_integration:rest_api_0:rest_api_0_integration_0:
+    aws:api_integration:rest_api_0:rest_api_0_integration_0 -> aws:vpc_link:rest_api_0_integration_0-ecs_service_2:
+    aws:vpc_link:rest_api_0_integration_0-ecs_service_2 -> aws:load_balancer:rest-api-0-integc0d8489a:
+    aws:load_balancer:rest-api-0-integc0d8489a -> aws:load_balancer_listener:rest_api_0_integration_0-ecs_service_2:
+    aws:load_balancer:rest-api-0-integc0d8489a -> aws:subnet:vpc-0:subnet-0:
+    aws:load_balancer:rest-api-0-integc0d8489a -> aws:subnet:vpc-0:subnet-1:
+    aws:load_balancer_listener:rest_api_0_integration_0-ecs_service_2 -> aws:target_group:rest-api-0-integc0d8489a:
+    aws:target_group:rest-api-0-integc0d8489a -> aws:ecs_service:ecs_service_2:
+    aws:ecr_image:ecs_service_2-image -> aws:ecr_repo:ecr_repo-0:
+    aws:ecs_service:ecs_service_2 -> aws:ecs_cluster:ecs_cluster-0:
+    aws:ecs_service:ecs_service_2 -> aws:ecs_task_definition:ecs_service_2:
+    aws:ecs_service:ecs_service_2 -> aws:subnet:vpc-0:subnet-0:
+    aws:ecs_service:ecs_service_2 -> aws:subnet:vpc-0:subnet-1:
+    aws:ecs_task_definition:ecs_service_2 -> aws:ecr_image:ecs_service_2-image:
+    aws:ecs_task_definition:ecs_service_2 -> aws:iam_role:ecs_service_2-execution-role:
+    aws:ecs_task_definition:ecs_service_2 -> aws:log_group:ecs_service_2-log-group:
+    aws:ecs_task_definition:ecs_service_2 -> aws:region:region-0:
+    aws:iam_role:ecs_service_2-execution-role -> aws:rds_instance:rds-instance-4:
+    aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway -> aws:elastic_ip:subnet-0-route_table-nat_gateway-elastic_ip:
+    aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway -> aws:subnet:vpc-0:subnet-2:
+    aws:subnet:vpc-0:subnet-2 -> aws:availability_zone:region-0:availability_zone-0:
+    aws:subnet:vpc-0:subnet-2 -> aws:route_table_association:subnet-2-subnet-2-route_table:
+    aws:subnet:vpc-0:subnet-2 -> aws:vpc:vpc-0:
+    aws:route_table_association:subnet-2-subnet-2-route_table -> aws:route_table:vpc-0:subnet-2-route_table:
+    aws:route_table:vpc-0:subnet-2-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
+    aws:route_table:vpc-0:subnet-2-route_table -> aws:vpc:vpc-0:
+    aws:availability_zone:region-0:availability_zone-0 -> aws:region:region-0:
+    aws:internet_gateway:vpc-0:internet_gateway-0 -> aws:vpc:vpc-0:
+    aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway -> aws:elastic_ip:subnet-1-route_table-nat_gateway-elastic_ip:
+    aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway -> aws:subnet:vpc-0:subnet-3:
+    aws:subnet:vpc-0:subnet-3 -> aws:availability_zone:region-0:availability_zone-1:
+    aws:subnet:vpc-0:subnet-3 -> aws:route_table_association:subnet-3-subnet-3-route_table:
+    aws:subnet:vpc-0:subnet-3 -> aws:vpc:vpc-0:
+    aws:route_table_association:subnet-3-subnet-3-route_table -> aws:route_table:vpc-0:subnet-3-route_table:
+    aws:route_table:vpc-0:subnet-3-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
+    aws:route_table:vpc-0:subnet-3-route_table -> aws:vpc:vpc-0:
+    aws:availability_zone:region-0:availability_zone-1 -> aws:region:region-0:
+    aws:rds_instance:rds-instance-4 -> aws:rds_subnet_group:rds_subnet_group-0:
+    aws:rds_subnet_group:rds_subnet_group-0 -> aws:subnet:vpc-0:subnet-0:
+    aws:rds_subnet_group:rds_subnet_group-0 -> aws:subnet:vpc-0:subnet-1:
+    aws:subnet:vpc-0:subnet-0 -> aws:availability_zone:region-0:availability_zone-0:
+    aws:subnet:vpc-0:subnet-0 -> aws:route_table_association:subnet-0-subnet-0-route_table:
+    aws:subnet:vpc-0:subnet-0 -> aws:security_group:vpc-0:ecs_service_2-security_group:
+    aws:subnet:vpc-0:subnet-0 -> aws:security_group:vpc-0:rds-instance-4-security_group:
+    aws:subnet:vpc-0:subnet-0 -> aws:vpc:vpc-0:
+    aws:subnet:vpc-0:subnet-1 -> aws:availability_zone:region-0:availability_zone-1:
+    aws:subnet:vpc-0:subnet-1 -> aws:route_table_association:subnet-1-subnet-1-route_table:
+    aws:subnet:vpc-0:subnet-1 -> aws:security_group:vpc-0:ecs_service_2-security_group:
+    aws:subnet:vpc-0:subnet-1 -> aws:security_group:vpc-0:rds-instance-4-security_group:
+    aws:subnet:vpc-0:subnet-1 -> aws:vpc:vpc-0:
+    aws:route_table_association:subnet-0-subnet-0-route_table -> aws:route_table:vpc-0:subnet-0-route_table:
+    aws:route_table_association:subnet-1-subnet-1-route_table -> aws:route_table:vpc-0:subnet-1-route_table:
+    aws:security_group:vpc-0:ecs_service_2-security_group -> aws:ecs_service:ecs_service_2:
+    aws:security_group:vpc-0:ecs_service_2-security_group -> aws:vpc:vpc-0:
+    aws:security_group:vpc-0:rds-instance-4-security_group -> aws:rds_instance:rds-instance-4:
+    aws:security_group:vpc-0:rds-instance-4-security_group -> aws:vpc:vpc-0:
+    aws:route_table:vpc-0:subnet-0-route_table -> aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway:
+    aws:route_table:vpc-0:subnet-0-route_table -> aws:vpc:vpc-0:
+    aws:route_table:vpc-0:subnet-1-route_table -> aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway:
+    aws:route_table:vpc-0:subnet-1-route_table -> aws:vpc:vpc-0:
diff --git a/pkg/engine2/testdata/ecs_rds.expect.yaml b/pkg/engine2/testdata/ecs_rds.expect.yaml
index 608fb38a..ff4d63c2 100755
--- a/pkg/engine2/testdata/ecs_rds.expect.yaml
+++ b/pkg/engine2/testdata/ecs_rds.expect.yaml
@@ -87,13 +87,13 @@ resources:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-0
         CidrBlock: 10.0.0.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-2-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-2-route_table
         Type: public
         Vpc: aws:vpc:vpc-0
     aws:route_table_association:subnet-2-subnet-2-route_table:
-        RouteTable: aws:route_table:subnet-2-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-2-route_table
         Subnet: aws:subnet:vpc-0:subnet-2
-    aws:route_table:subnet-2-route_table:
+    aws:route_table:vpc-0:subnet-2-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               Gateway: aws:internet_gateway:vpc-0:internet_gateway-0
@@ -110,13 +110,13 @@ resources:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-1
         CidrBlock: 10.0.64.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-3-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-3-route_table
         Type: public
         Vpc: aws:vpc:vpc-0
     aws:route_table_association:subnet-3-subnet-3-route_table:
-        RouteTable: aws:route_table:subnet-3-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-3-route_table
         Subnet: aws:subnet:vpc-0:subnet-3
-    aws:route_table:subnet-3-route_table:
+    aws:route_table:vpc-0:subnet-3-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               Gateway: aws:internet_gateway:vpc-0:internet_gateway-0
@@ -144,21 +144,21 @@ resources:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-0
         CidrBlock: 10.0.128.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-0-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-0-route_table
         Type: private
         Vpc: aws:vpc:vpc-0
     aws:subnet:vpc-0:subnet-1:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-1
         CidrBlock: 10.0.192.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-1-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-1-route_table
         Type: private
         Vpc: aws:vpc:vpc-0
     aws:route_table_association:subnet-0-subnet-0-route_table:
-        RouteTable: aws:route_table:subnet-0-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-0-route_table
         Subnet: aws:subnet:vpc-0:subnet-0
     aws:route_table_association:subnet-1-subnet-1-route_table:
-        RouteTable: aws:route_table:subnet-1-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-1-route_table
         Subnet: aws:subnet:vpc-0:subnet-1
     aws:security_group:vpc-0:rds-instance-2-security_group:
         EgressRules:
@@ -187,12 +187,12 @@ resources:
               Protocol: "-1"
               ToPort: 0
         Vpc: aws:vpc:vpc-0
-    aws:route_table:subnet-0-route_table:
+    aws:route_table:vpc-0:subnet-0-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               NatGateway: aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway
         Vpc: aws:vpc:vpc-0
-    aws:route_table:subnet-1-route_table:
+    aws:route_table:vpc-0:subnet-1-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               NatGateway: aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway
@@ -219,9 +219,9 @@ edges:
     aws:subnet:vpc-0:subnet-2 -> aws:availability_zone:region-0:availability_zone-0:
     aws:subnet:vpc-0:subnet-2 -> aws:route_table_association:subnet-2-subnet-2-route_table:
     aws:subnet:vpc-0:subnet-2 -> aws:vpc:vpc-0:
-    aws:route_table_association:subnet-2-subnet-2-route_table -> aws:route_table:subnet-2-route_table:
-    aws:route_table:subnet-2-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
-    aws:route_table:subnet-2-route_table -> aws:vpc:vpc-0:
+    aws:route_table_association:subnet-2-subnet-2-route_table -> aws:route_table:vpc-0:subnet-2-route_table:
+    aws:route_table:vpc-0:subnet-2-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
+    aws:route_table:vpc-0:subnet-2-route_table -> aws:vpc:vpc-0:
     aws:availability_zone:region-0:availability_zone-0 -> aws:region:region-0:
     aws:internet_gateway:vpc-0:internet_gateway-0 -> aws:vpc:vpc-0:
     aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway -> aws:elastic_ip:subnet-1-route_table-nat_gateway-elastic_ip:
@@ -229,9 +229,9 @@ edges:
     aws:subnet:vpc-0:subnet-3 -> aws:availability_zone:region-0:availability_zone-1:
     aws:subnet:vpc-0:subnet-3 -> aws:route_table_association:subnet-3-subnet-3-route_table:
     aws:subnet:vpc-0:subnet-3 -> aws:vpc:vpc-0:
-    aws:route_table_association:subnet-3-subnet-3-route_table -> aws:route_table:subnet-3-route_table:
-    aws:route_table:subnet-3-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
-    aws:route_table:subnet-3-route_table -> aws:vpc:vpc-0:
+    aws:route_table_association:subnet-3-subnet-3-route_table -> aws:route_table:vpc-0:subnet-3-route_table:
+    aws:route_table:vpc-0:subnet-3-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
+    aws:route_table:vpc-0:subnet-3-route_table -> aws:vpc:vpc-0:
     aws:availability_zone:region-0:availability_zone-1 -> aws:region:region-0:
     aws:rds_instance:rds-instance-2 -> aws:rds_subnet_group:rds_subnet_group-0:
     aws:rds_subnet_group:rds_subnet_group-0 -> aws:subnet:vpc-0:subnet-0:
@@ -244,11 +244,11 @@ edges:
     aws:subnet:vpc-0:subnet-1 -> aws:route_table_association:subnet-1-subnet-1-route_table:
     aws:subnet:vpc-0:subnet-1 -> aws:security_group:vpc-0:rds-instance-2-security_group:
     aws:subnet:vpc-0:subnet-1 -> aws:vpc:vpc-0:
-    aws:route_table_association:subnet-0-subnet-0-route_table -> aws:route_table:subnet-0-route_table:
-    aws:route_table_association:subnet-1-subnet-1-route_table -> aws:route_table:subnet-1-route_table:
+    aws:route_table_association:subnet-0-subnet-0-route_table -> aws:route_table:vpc-0:subnet-0-route_table:
+    aws:route_table_association:subnet-1-subnet-1-route_table -> aws:route_table:vpc-0:subnet-1-route_table:
     aws:security_group:vpc-0:rds-instance-2-security_group -> aws:rds_instance:rds-instance-2:
     aws:security_group:vpc-0:rds-instance-2-security_group -> aws:vpc:vpc-0:
-    aws:route_table:subnet-0-route_table -> aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway:
-    aws:route_table:subnet-0-route_table -> aws:vpc:vpc-0:
-    aws:route_table:subnet-1-route_table -> aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway:
-    aws:route_table:subnet-1-route_table -> aws:vpc:vpc-0:
+    aws:route_table:vpc-0:subnet-0-route_table -> aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway:
+    aws:route_table:vpc-0:subnet-0-route_table -> aws:vpc:vpc-0:
+    aws:route_table:vpc-0:subnet-1-route_table -> aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway:
+    aws:route_table:vpc-0:subnet-1-route_table -> aws:vpc:vpc-0:
diff --git a/pkg/engine2/testdata/ecs_rds.iac-viz.yaml b/pkg/engine2/testdata/ecs_rds.iac-viz.yaml
index f29d858b..99f22352 100755
--- a/pkg/engine2/testdata/ecs_rds.iac-viz.yaml
+++ b/pkg/engine2/testdata/ecs_rds.iac-viz.yaml
@@ -64,21 +64,21 @@ resources:
 
   log_group/ecs_service_0-log-group:
 
-  route_table/subnet-3-route_table:
-  route_table/subnet-3-route_table -> aws:internet_gateway:vpc-0/internet_gateway-0:
-  route_table/subnet-3-route_table -> vpc/vpc-0:
+  aws:route_table:vpc-0/subnet-3-route_table:
+  aws:route_table:vpc-0/subnet-3-route_table -> aws:internet_gateway:vpc-0/internet_gateway-0:
+  aws:route_table:vpc-0/subnet-3-route_table -> vpc/vpc-0:
 
-  route_table/subnet-2-route_table:
-  route_table/subnet-2-route_table -> aws:internet_gateway:vpc-0/internet_gateway-0:
-  route_table/subnet-2-route_table -> vpc/vpc-0:
+  aws:route_table:vpc-0/subnet-2-route_table:
+  aws:route_table:vpc-0/subnet-2-route_table -> aws:internet_gateway:vpc-0/internet_gateway-0:
+  aws:route_table:vpc-0/subnet-2-route_table -> vpc/vpc-0:
 
-  route_table/subnet-1-route_table:
-  route_table/subnet-1-route_table -> aws:nat_gateway:subnet-3/subnet-1-route_table-nat_gateway:
-  route_table/subnet-1-route_table -> vpc/vpc-0:
+  aws:route_table:vpc-0/subnet-1-route_table:
+  aws:route_table:vpc-0/subnet-1-route_table -> aws:nat_gateway:subnet-3/subnet-1-route_table-nat_gateway:
+  aws:route_table:vpc-0/subnet-1-route_table -> vpc/vpc-0:
 
-  route_table/subnet-0-route_table:
-  route_table/subnet-0-route_table -> aws:nat_gateway:subnet-2/subnet-0-route_table-nat_gateway:
-  route_table/subnet-0-route_table -> vpc/vpc-0:
+  aws:route_table:vpc-0/subnet-0-route_table:
+  aws:route_table:vpc-0/subnet-0-route_table -> aws:nat_gateway:subnet-2/subnet-0-route_table-nat_gateway:
+  aws:route_table:vpc-0/subnet-0-route_table -> vpc/vpc-0:
 
   ecs_cluster/ecs_cluster-0:
 
@@ -92,19 +92,19 @@ resources:
   aws:security_group:vpc-0/ecs_service_0-security_group -> vpc/vpc-0:
 
   route_table_association/subnet-3-subnet-3-route_table:
-  route_table_association/subnet-3-subnet-3-route_table -> route_table/subnet-3-route_table:
+  route_table_association/subnet-3-subnet-3-route_table -> aws:route_table:vpc-0/subnet-3-route_table:
   route_table_association/subnet-3-subnet-3-route_table -> aws:subnet:vpc-0/subnet-3:
 
   route_table_association/subnet-2-subnet-2-route_table:
-  route_table_association/subnet-2-subnet-2-route_table -> route_table/subnet-2-route_table:
+  route_table_association/subnet-2-subnet-2-route_table -> aws:route_table:vpc-0/subnet-2-route_table:
   route_table_association/subnet-2-subnet-2-route_table -> aws:subnet:vpc-0/subnet-2:
 
   route_table_association/subnet-1-subnet-1-route_table:
-  route_table_association/subnet-1-subnet-1-route_table -> route_table/subnet-1-route_table:
+  route_table_association/subnet-1-subnet-1-route_table -> aws:route_table:vpc-0/subnet-1-route_table:
   route_table_association/subnet-1-subnet-1-route_table -> aws:subnet:vpc-0/subnet-1:
 
   route_table_association/subnet-0-subnet-0-route_table:
-  route_table_association/subnet-0-subnet-0-route_table -> route_table/subnet-0-route_table:
+  route_table_association/subnet-0-subnet-0-route_table -> aws:route_table:vpc-0/subnet-0-route_table:
   route_table_association/subnet-0-subnet-0-route_table -> aws:subnet:vpc-0/subnet-0:
 
   ecs_service/ecs_service_0:
diff --git a/pkg/engine2/testdata/k8s_api.expect.yaml b/pkg/engine2/testdata/k8s_api.expect.yaml
index 8578e946..1c2ec5fb 100755
--- a/pkg/engine2/testdata/k8s_api.expect.yaml
+++ b/pkg/engine2/testdata/k8s_api.expect.yaml
@@ -285,12 +285,12 @@ resources:
                         - ec2.amazonaws.com
             Version: "2012-10-17"
         ManagedPolicies:
-            - arn:aws:iam::aws:policy/AWSCloudMapFullAccess
-            - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
             - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
             - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
             - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
             - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
+            - arn:aws:iam::aws:policy/AWSCloudMapFullAccess
+            - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
     aws:iam_role:pod2:
         AssumeRolePolicyDoc:
             Statement:
@@ -477,21 +477,21 @@ resources:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-0
         CidrBlock: 10.0.128.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-0-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-0-route_table
         Type: private
         Vpc: aws:vpc:vpc-0
     aws:subnet:vpc-0:subnet-1:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-1
         CidrBlock: 10.0.192.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-1-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-1-route_table
         Type: private
         Vpc: aws:vpc:vpc-0
     aws:route_table_association:subnet-0-subnet-0-route_table:
-        RouteTable: aws:route_table:subnet-0-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-0-route_table
         Subnet: aws:subnet:vpc-0:subnet-0
     aws:route_table_association:subnet-1-subnet-1-route_table:
-        RouteTable: aws:route_table:subnet-1-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-1-route_table
         Subnet: aws:subnet:vpc-0:subnet-1
     aws:security_group:vpc-0:eks_cluster-0-security_group:
         EgressRules:
@@ -502,11 +502,6 @@ resources:
               Protocol: "-1"
               ToPort: 0
         IngressRules:
-            - Description: Allow ingress traffic from within the same security group
-              FromPort: 0
-              Protocol: "-1"
-              Self: true
-              ToPort: 0
             - CidrBlocks:
                 - 10.0.128.0/18
               Description: Allow ingress traffic from ip addresses within the subnet subnet-0
@@ -525,13 +520,18 @@ resources:
               FromPort: 9443
               Protocol: TCP
               ToPort: 9443
+            - Description: Allow ingress traffic from within the same security group
+              FromPort: 0
+              Protocol: "-1"
+              Self: true
+              ToPort: 0
         Vpc: aws:vpc:vpc-0
-    aws:route_table:subnet-0-route_table:
+    aws:route_table:vpc-0:subnet-0-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               NatGateway: aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway
         Vpc: aws:vpc:vpc-0
-    aws:route_table:subnet-1-route_table:
+    aws:route_table:vpc-0:subnet-1-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               NatGateway: aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway
@@ -547,7 +547,7 @@ resources:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-0
         CidrBlock: 10.0.0.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-2-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-2-route_table
         Type: public
         Vpc: aws:vpc:vpc-0
     aws:elastic_ip:subnet-1-route_table-nat_gateway-elastic_ip:
@@ -555,28 +555,28 @@ resources:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-1
         CidrBlock: 10.0.64.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-3-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-3-route_table
         Type: public
         Vpc: aws:vpc:vpc-0
     aws:availability_zone:region-0:availability_zone-0:
         Index: 0
         Region: aws:region:region-0
     aws:route_table_association:subnet-2-subnet-2-route_table:
-        RouteTable: aws:route_table:subnet-2-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-2-route_table
         Subnet: aws:subnet:vpc-0:subnet-2
     aws:availability_zone:region-0:availability_zone-1:
         Index: 1
         Region: aws:region:region-0
     aws:route_table_association:subnet-3-subnet-3-route_table:
-        RouteTable: aws:route_table:subnet-3-route_table
+        RouteTable: aws:route_table:vpc-0:subnet-3-route_table
         Subnet: aws:subnet:vpc-0:subnet-3
-    aws:route_table:subnet-2-route_table:
+    aws:route_table:vpc-0:subnet-2-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               Gateway: aws:internet_gateway:vpc-0:internet_gateway-0
         Vpc: aws:vpc:vpc-0
     aws:region:region-0:
-    aws:route_table:subnet-3-route_table:
+    aws:route_table:vpc-0:subnet-3-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               Gateway: aws:internet_gateway:vpc-0:internet_gateway-0
@@ -656,14 +656,14 @@ edges:
     aws:subnet:vpc-0:subnet-1 -> aws:route_table_association:subnet-1-subnet-1-route_table:
     aws:subnet:vpc-0:subnet-1 -> aws:security_group:vpc-0:eks_cluster-0-security_group:
     aws:subnet:vpc-0:subnet-1 -> aws:vpc:vpc-0:
-    aws:route_table_association:subnet-0-subnet-0-route_table -> aws:route_table:subnet-0-route_table:
-    aws:route_table_association:subnet-1-subnet-1-route_table -> aws:route_table:subnet-1-route_table:
+    aws:route_table_association:subnet-0-subnet-0-route_table -> aws:route_table:vpc-0:subnet-0-route_table:
+    aws:route_table_association:subnet-1-subnet-1-route_table -> aws:route_table:vpc-0:subnet-1-route_table:
     aws:security_group:vpc-0:eks_cluster-0-security_group -> aws:eks_cluster:eks_cluster-0:
     aws:security_group:vpc-0:eks_cluster-0-security_group -> aws:vpc:vpc-0:
-    aws:route_table:subnet-0-route_table -> aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway:
-    aws:route_table:subnet-0-route_table -> aws:vpc:vpc-0:
-    aws:route_table:subnet-1-route_table -> aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway:
-    aws:route_table:subnet-1-route_table -> aws:vpc:vpc-0:
+    aws:route_table:vpc-0:subnet-0-route_table -> aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway:
+    aws:route_table:vpc-0:subnet-0-route_table -> aws:vpc:vpc-0:
+    aws:route_table:vpc-0:subnet-1-route_table -> aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway:
+    aws:route_table:vpc-0:subnet-1-route_table -> aws:vpc:vpc-0:
     aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway -> aws:elastic_ip:subnet-0-route_table-nat_gateway-elastic_ip:
     aws:nat_gateway:subnet-2:subnet-0-route_table-nat_gateway -> aws:subnet:vpc-0:subnet-2:
     aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway -> aws:elastic_ip:subnet-1-route_table-nat_gateway-elastic_ip:
@@ -675,11 +675,11 @@ edges:
     aws:subnet:vpc-0:subnet-3 -> aws:route_table_association:subnet-3-subnet-3-route_table:
     aws:subnet:vpc-0:subnet-3 -> aws:vpc:vpc-0:
     aws:availability_zone:region-0:availability_zone-0 -> aws:region:region-0:
-    aws:route_table_association:subnet-2-subnet-2-route_table -> aws:route_table:subnet-2-route_table:
+    aws:route_table_association:subnet-2-subnet-2-route_table -> aws:route_table:vpc-0:subnet-2-route_table:
     aws:availability_zone:region-0:availability_zone-1 -> aws:region:region-0:
-    aws:route_table_association:subnet-3-subnet-3-route_table -> aws:route_table:subnet-3-route_table:
-    aws:route_table:subnet-2-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
-    aws:route_table:subnet-2-route_table -> aws:vpc:vpc-0:
-    aws:route_table:subnet-3-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
-    aws:route_table:subnet-3-route_table -> aws:vpc:vpc-0:
+    aws:route_table_association:subnet-3-subnet-3-route_table -> aws:route_table:vpc-0:subnet-3-route_table:
+    aws:route_table:vpc-0:subnet-2-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
+    aws:route_table:vpc-0:subnet-2-route_table -> aws:vpc:vpc-0:
+    aws:route_table:vpc-0:subnet-3-route_table -> aws:internet_gateway:vpc-0:internet_gateway-0:
+    aws:route_table:vpc-0:subnet-3-route_table -> aws:vpc:vpc-0:
     aws:internet_gateway:vpc-0:internet_gateway-0 -> aws:vpc:vpc-0:
diff --git a/pkg/engine2/testdata/k8s_api.iac-viz.yaml b/pkg/engine2/testdata/k8s_api.iac-viz.yaml
index 30e80855..fbd7a86f 100755
--- a/pkg/engine2/testdata/k8s_api.iac-viz.yaml
+++ b/pkg/engine2/testdata/k8s_api.iac-viz.yaml
@@ -132,21 +132,21 @@ resources:
   kubernetes:config_map/fluent-bit-cluster-info -> eks_cluster/eks_cluster-0:
   kubernetes:config_map/fluent-bit-cluster-info -> kubernetes:namespace/amazon-cloudwatch:
 
-  route_table/subnet-3-route_table:
-  route_table/subnet-3-route_table -> aws:internet_gateway:vpc-0/internet_gateway-0:
-  route_table/subnet-3-route_table -> vpc/vpc-0:
+  aws:route_table:vpc-0/subnet-3-route_table:
+  aws:route_table:vpc-0/subnet-3-route_table -> aws:internet_gateway:vpc-0/internet_gateway-0:
+  aws:route_table:vpc-0/subnet-3-route_table -> vpc/vpc-0:
 
-  route_table/subnet-2-route_table:
-  route_table/subnet-2-route_table -> aws:internet_gateway:vpc-0/internet_gateway-0:
-  route_table/subnet-2-route_table -> vpc/vpc-0:
+  aws:route_table:vpc-0/subnet-2-route_table:
+  aws:route_table:vpc-0/subnet-2-route_table -> aws:internet_gateway:vpc-0/internet_gateway-0:
+  aws:route_table:vpc-0/subnet-2-route_table -> vpc/vpc-0:
 
-  route_table/subnet-1-route_table:
-  route_table/subnet-1-route_table -> aws:nat_gateway:subnet-3/subnet-1-route_table-nat_gateway:
-  route_table/subnet-1-route_table -> vpc/vpc-0:
+  aws:route_table:vpc-0/subnet-1-route_table:
+  aws:route_table:vpc-0/subnet-1-route_table -> aws:nat_gateway:subnet-3/subnet-1-route_table-nat_gateway:
+  aws:route_table:vpc-0/subnet-1-route_table -> vpc/vpc-0:
 
-  route_table/subnet-0-route_table:
-  route_table/subnet-0-route_table -> aws:nat_gateway:subnet-2/subnet-0-route_table-nat_gateway:
-  route_table/subnet-0-route_table -> vpc/vpc-0:
+  aws:route_table:vpc-0/subnet-0-route_table:
+  aws:route_table:vpc-0/subnet-0-route_table -> aws:nat_gateway:subnet-2/subnet-0-route_table-nat_gateway:
+  aws:route_table:vpc-0/subnet-0-route_table -> vpc/vpc-0:
 
   iam_policy/iam_policy-0:
 
@@ -176,19 +176,19 @@ resources:
   security_group_rule/security_group_rule-0 -> vpc/vpc-0:
 
   route_table_association/subnet-3-subnet-3-route_table:
-  route_table_association/subnet-3-subnet-3-route_table -> route_table/subnet-3-route_table:
+  route_table_association/subnet-3-subnet-3-route_table -> aws:route_table:vpc-0/subnet-3-route_table:
   route_table_association/subnet-3-subnet-3-route_table -> aws:subnet:vpc-0/subnet-3:
 
   route_table_association/subnet-2-subnet-2-route_table:
-  route_table_association/subnet-2-subnet-2-route_table -> route_table/subnet-2-route_table:
+  route_table_association/subnet-2-subnet-2-route_table -> aws:route_table:vpc-0/subnet-2-route_table:
   route_table_association/subnet-2-subnet-2-route_table -> aws:subnet:vpc-0/subnet-2:
 
   route_table_association/subnet-1-subnet-1-route_table:
-  route_table_association/subnet-1-subnet-1-route_table -> route_table/subnet-1-route_table:
+  route_table_association/subnet-1-subnet-1-route_table -> aws:route_table:vpc-0/subnet-1-route_table:
   route_table_association/subnet-1-subnet-1-route_table -> aws:subnet:vpc-0/subnet-1:
 
   route_table_association/subnet-0-subnet-0-route_table:
-  route_table_association/subnet-0-subnet-0-route_table -> route_table/subnet-0-route_table:
+  route_table_association/subnet-0-subnet-0-route_table -> aws:route_table:vpc-0/subnet-0-route_table:
   route_table_association/subnet-0-subnet-0-route_table -> aws:subnet:vpc-0/subnet-0:
 
   load_balancer_listener/rest_api_4_integration_0-pod2:
diff --git a/pkg/engine2/testdata/namespace_pathselect.expect.yaml b/pkg/engine2/testdata/namespace_pathselect.expect.yaml
index 34c856b7..d86c6736 100755
--- a/pkg/engine2/testdata/namespace_pathselect.expect.yaml
+++ b/pkg/engine2/testdata/namespace_pathselect.expect.yaml
@@ -68,26 +68,26 @@ resources:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-0
         CidrBlock: 10.0.128.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:lambda_function_2-vpc_1-route_table
+        RouteTable: aws:route_table:vpc_1:lambda_function_2-vpc_1-route_table
         Type: private
         Vpc: aws:vpc:vpc_1
     aws:subnet:vpc_1:subnet-1:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-1
         CidrBlock: 10.0.192.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-1-route_table
+        RouteTable: aws:route_table:vpc_1:subnet-1-route_table
         Type: private
         Vpc: aws:vpc:vpc_1
     aws:ecr_repo:ecr_repo-0:
         ForceDelete: true
     aws:route_table_association:lambda_function_2-vpc_1-lambda_function_2-vpc_1-route_table:
-        RouteTable: aws:route_table:lambda_function_2-vpc_1-route_table
+        RouteTable: aws:route_table:vpc_1:lambda_function_2-vpc_1-route_table
         Subnet: aws:subnet:vpc_1:lambda_function_2-vpc_1
     aws:SERVICE_API:lambda_function_0-lambda_function_0-log-group:
     aws:route_table_association:subnet-1-subnet-1-route_table:
-        RouteTable: aws:route_table:subnet-1-route_table
+        RouteTable: aws:route_table:vpc_1:subnet-1-route_table
         Subnet: aws:subnet:vpc_1:subnet-1
-    aws:route_table:lambda_function_2-vpc_1-route_table:
+    aws:route_table:vpc_1:lambda_function_2-vpc_1-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               NatGateway: aws:nat_gateway:subnet-2:lambda_function_2-vpc_1-route_table-nat_gateway
@@ -98,7 +98,7 @@ resources:
     aws:log_group:lambda_function_2-log-group:
         LogGroupName: /aws/lambda/lambda_function_2
         RetentionInDays: 5
-    aws:route_table:subnet-1-route_table:
+    aws:route_table:vpc_1:subnet-1-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               NatGateway: aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway
@@ -114,7 +114,7 @@ resources:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-0
         CidrBlock: 10.0.0.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-2-route_table
+        RouteTable: aws:route_table:vpc_1:subnet-2-route_table
         Type: public
         Vpc: aws:vpc:vpc_1
     aws:elastic_ip:subnet-1-route_table-nat_gateway-elastic_ip:
@@ -122,28 +122,28 @@ resources:
         AvailabilityZone: aws:availability_zone:region-0:availability_zone-1
         CidrBlock: 10.0.64.0/18
         MapPublicIpOnLaunch: false
-        RouteTable: aws:route_table:subnet-3-route_table
+        RouteTable: aws:route_table:vpc_1:subnet-3-route_table
         Type: public
         Vpc: aws:vpc:vpc_1
     aws:availability_zone:region-0:availability_zone-0:
         Index: 0
         Region: aws:region:region-0
     aws:route_table_association:subnet-2-subnet-2-route_table:
-        RouteTable: aws:route_table:subnet-2-route_table
+        RouteTable: aws:route_table:vpc_1:subnet-2-route_table
         Subnet: aws:subnet:vpc_1:subnet-2
     aws:availability_zone:region-0:availability_zone-1:
         Index: 1
         Region: aws:region:region-0
     aws:route_table_association:subnet-3-subnet-3-route_table:
-        RouteTable: aws:route_table:subnet-3-route_table
+        RouteTable: aws:route_table:vpc_1:subnet-3-route_table
         Subnet: aws:subnet:vpc_1:subnet-3
-    aws:route_table:subnet-2-route_table:
+    aws:route_table:vpc_1:subnet-2-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               Gateway: aws:internet_gateway:vpc_1:internet_gateway-0
         Vpc: aws:vpc:vpc_1
     aws:region:region-0:
-    aws:route_table:subnet-3-route_table:
+    aws:route_table:vpc_1:subnet-3-route_table:
         Routes:
             - CidrBlock: 0.0.0.0/0
               Gateway: aws:internet_gateway:vpc_1:internet_gateway-0
@@ -178,15 +178,16 @@ edges:
     aws:subnet:vpc_1:subnet-1 -> aws:availability_zone:region-0:availability_zone-1:
     aws:subnet:vpc_1:subnet-1 -> aws:route_table_association:subnet-1-subnet-1-route_table:
     aws:subnet:vpc_1:subnet-1 -> aws:vpc:vpc_1:
-    ? aws:route_table_association:lambda_function_2-vpc_1-lambda_function_2-vpc_1-route_table -> aws:route_table:lambda_function_2-vpc_1-route_table
+    ? aws:route_table_association:lambda_function_2-vpc_1-lambda_function_2-vpc_1-route_table -> aws:route_table:vpc_1:lambda_function_2-vpc_1-route_table
     :
     aws:SERVICE_API:lambda_function_0-lambda_function_0-log-group -> aws:log_group:lambda_function_0-log-group:
     aws:SERVICE_API:lambda_function_0-lambda_function_0-log-group -> aws:log_group:lambda_function_2-log-group:
-    aws:route_table_association:subnet-1-subnet-1-route_table -> aws:route_table:subnet-1-route_table:
-    aws:route_table:lambda_function_2-vpc_1-route_table -> aws:nat_gateway:subnet-2:lambda_function_2-vpc_1-route_table-nat_gateway:
-    aws:route_table:lambda_function_2-vpc_1-route_table -> aws:vpc:vpc_1:
-    aws:route_table:subnet-1-route_table -> aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway:
-    aws:route_table:subnet-1-route_table -> aws:vpc:vpc_1:
+    aws:route_table_association:subnet-1-subnet-1-route_table -> aws:route_table:vpc_1:subnet-1-route_table:
+    ? aws:route_table:vpc_1:lambda_function_2-vpc_1-route_table -> aws:nat_gateway:subnet-2:lambda_function_2-vpc_1-route_table-nat_gateway
+    :
+    aws:route_table:vpc_1:lambda_function_2-vpc_1-route_table -> aws:vpc:vpc_1:
+    aws:route_table:vpc_1:subnet-1-route_table -> aws:nat_gateway:subnet-3:subnet-1-route_table-nat_gateway:
+    aws:route_table:vpc_1:subnet-1-route_table -> aws:vpc:vpc_1:
     ? aws:nat_gateway:subnet-2:lambda_function_2-vpc_1-route_table-nat_gateway -> aws:elastic_ip:lambda_function_2-vpc_1-route_table-nat_gateway-elastic_ip
     :
     aws:nat_gateway:subnet-2:lambda_function_2-vpc_1-route_table-nat_gateway -> aws:subnet:vpc_1:subnet-2:
@@ -199,11 +200,11 @@ edges:
     aws:subnet:vpc_1:subnet-3 -> aws:route_table_association:subnet-3-subnet-3-route_table:
     aws:subnet:vpc_1:subnet-3 -> aws:vpc:vpc_1:
     aws:availability_zone:region-0:availability_zone-0 -> aws:region:region-0:
-    aws:route_table_association:subnet-2-subnet-2-route_table -> aws:route_table:subnet-2-route_table:
+    aws:route_table_association:subnet-2-subnet-2-route_table -> aws:route_table:vpc_1:subnet-2-route_table:
     aws:availability_zone:region-0:availability_zone-1 -> aws:region:region-0:
-    aws:route_table_association:subnet-3-subnet-3-route_table -> aws:route_table:subnet-3-route_table:
-    aws:route_table:subnet-2-route_table -> aws:internet_gateway:vpc_1:internet_gateway-0:
-    aws:route_table:subnet-2-route_table -> aws:vpc:vpc_1:
-    aws:route_table:subnet-3-route_table -> aws:internet_gateway:vpc_1:internet_gateway-0:
-    aws:route_table:subnet-3-route_table -> aws:vpc:vpc_1:
+    aws:route_table_association:subnet-3-subnet-3-route_table -> aws:route_table:vpc_1:subnet-3-route_table:
+    aws:route_table:vpc_1:subnet-2-route_table -> aws:internet_gateway:vpc_1:internet_gateway-0:
+    aws:route_table:vpc_1:subnet-2-route_table -> aws:vpc:vpc_1:
+    aws:route_table:vpc_1:subnet-3-route_table -> aws:internet_gateway:vpc_1:internet_gateway-0:
+    aws:route_table:vpc_1:subnet-3-route_table -> aws:vpc:vpc_1:
     aws:internet_gateway:vpc_1:internet_gateway-0 -> aws:vpc:vpc_1:
diff --git a/pkg/engine2/testdata/namespace_pathselect.iac-viz.yaml b/pkg/engine2/testdata/namespace_pathselect.iac-viz.yaml
index a736bff8..6f1e7555 100755
--- a/pkg/engine2/testdata/namespace_pathselect.iac-viz.yaml
+++ b/pkg/engine2/testdata/namespace_pathselect.iac-viz.yaml
@@ -39,25 +39,25 @@ resources:
 
   log_group/lambda_function_0-log-group:
 
-  route_table/subnet-3-route_table:
-  route_table/subnet-3-route_table -> aws:internet_gateway:vpc_1/internet_gateway-0:
-  route_table/subnet-3-route_table -> vpc/vpc_1:
+  aws:route_table:vpc_1/subnet-3-route_table:
+  aws:route_table:vpc_1/subnet-3-route_table -> aws:internet_gateway:vpc_1/internet_gateway-0:
+  aws:route_table:vpc_1/subnet-3-route_table -> vpc/vpc_1:
 
-  route_table/subnet-2-route_table:
-  route_table/subnet-2-route_table -> aws:internet_gateway:vpc_1/internet_gateway-0:
-  route_table/subnet-2-route_table -> vpc/vpc_1:
+  aws:route_table:vpc_1/subnet-2-route_table:
+  aws:route_table:vpc_1/subnet-2-route_table -> aws:internet_gateway:vpc_1/internet_gateway-0:
+  aws:route_table:vpc_1/subnet-2-route_table -> vpc/vpc_1:
 
-  route_table/subnet-1-route_table:
-  route_table/subnet-1-route_table -> aws:nat_gateway:subnet-3/subnet-1-route_table-nat_gateway:
-  route_table/subnet-1-route_table -> vpc/vpc_1:
+  aws:route_table:vpc_1/subnet-1-route_table:
+  aws:route_table:vpc_1/subnet-1-route_table -> aws:nat_gateway:subnet-3/subnet-1-route_table-nat_gateway:
+  aws:route_table:vpc_1/subnet-1-route_table -> vpc/vpc_1:
 
   aws:subnet:vpc_1/subnet-1:
   aws:subnet:vpc_1/subnet-1 -> aws:availability_zone:region-0/availability_zone-1:
   aws:subnet:vpc_1/subnet-1 -> vpc/vpc_1:
 
-  route_table/lambda_function_2-vpc_1-route_table:
-  route_table/lambda_function_2-vpc_1-route_table -> aws:nat_gateway:subnet-2/lambda_function_2-vpc_1-route_table-nat_gateway:
-  route_table/lambda_function_2-vpc_1-route_table -> vpc/vpc_1:
+  aws:route_table:vpc_1/lambda_function_2-vpc_1-route_table:
+  aws:route_table:vpc_1/lambda_function_2-vpc_1-route_table -> aws:nat_gateway:subnet-2/lambda_function_2-vpc_1-route_table-nat_gateway:
+  aws:route_table:vpc_1/lambda_function_2-vpc_1-route_table -> vpc/vpc_1:
 
   aws:subnet:vpc_1/lambda_function_2-vpc_1:
   aws:subnet:vpc_1/lambda_function_2-vpc_1 -> aws:availability_zone:region-0/availability_zone-0:
@@ -79,19 +79,19 @@ resources:
   iam_role/lambda_function_0-executionrole -> log_group/lambda_function_0-log-group:
 
   route_table_association/subnet-3-subnet-3-route_table:
-  route_table_association/subnet-3-subnet-3-route_table -> route_table/subnet-3-route_table:
+  route_table_association/subnet-3-subnet-3-route_table -> aws:route_table:vpc_1/subnet-3-route_table:
   route_table_association/subnet-3-subnet-3-route_table -> aws:subnet:vpc_1/subnet-3:
 
   route_table_association/subnet-2-subnet-2-route_table:
-  route_table_association/subnet-2-subnet-2-route_table -> route_table/subnet-2-route_table:
+  route_table_association/subnet-2-subnet-2-route_table -> aws:route_table:vpc_1/subnet-2-route_table:
   route_table_association/subnet-2-subnet-2-route_table -> aws:subnet:vpc_1/subnet-2:
 
   route_table_association/subnet-1-subnet-1-route_table:
-  route_table_association/subnet-1-subnet-1-route_table -> route_table/subnet-1-route_table:
+  route_table_association/subnet-1-subnet-1-route_table -> aws:route_table:vpc_1/subnet-1-route_table:
   route_table_association/subnet-1-subnet-1-route_table -> aws:subnet:vpc_1/subnet-1:
 
   route_table_association/lambda_function_2-vpc_1-lambda_function_2-vpc_1-route_table:
-  route_table_association/lambda_function_2-vpc_1-lambda_function_2-vpc_1-route_table -> route_table/lambda_function_2-vpc_1-route_table:
+  route_table_association/lambda_function_2-vpc_1-lambda_function_2-vpc_1-route_table -> aws:route_table:vpc_1/lambda_function_2-vpc_1-route_table:
   route_table_association/lambda_function_2-vpc_1-lambda_function_2-vpc_1-route_table -> aws:subnet:vpc_1/lambda_function_2-vpc_1:
 
   lambda_function/lambda_function_2: