Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add overrides for aws_sns_topic and other problematic conversions #112

Open
jignesh1995 opened this issue Feb 21, 2023 · 1 comment
Open
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed

Comments

@jignesh1995
Copy link

This is an excellent python app for translating Cloudformation Stack to Terraform scripts

Some modules could however use an improvement while translating to terraform scripts:

  • aws_autoscaling_notification
  • aws_autoscaling_groups
  • aws_acmpca_policy
  • aws_cloudwatch_composite_alarm
  • aws_sns_topic

The generated script has terraform blocks such as the following:

resource "aws_sns_topic" "some_topic" {
  name = "${var.environment_name}-some-topic"
  // CF Property(Subscription) = [
  //   {
  //     Endpoint = aws_lambda_function.lambda_function_name.arn
  //     Protocol = "lambda"
  //   }
  // ]
}

When in ideal scenario, there should have been 2 resources (1 for SNS Topic, 1 for SNS Subscription):

resource "aws_sns_topic" "some_topic" {
  name = "${var.environment_name}-some-topic"
}

resource "aws_sns_topic_subscription" some_sqs_target" {
  topic_arn = aws_sns_topic.some_topic.arn
  protocol  = "lambda"
  endpoint  = "aws_lambda_function.lambda_function_name.arn"
}

I think the primary reason for this is that my Cloudformation script is creating the resources within the same module(CF block Type: "AWS::SNS::Topic"), however terraform based on its API documentation requires multiple modules to replicate the same resource structure.

PS: Props to the idea of not failing the conversion for such scenarios and instead adding a comment block at the appropriate locations//CF Property.... so that developers can resolve them manually.

@shadycuz
Copy link
Member

@jignesh1995 That is exactly what is happening. The converter tries to convery the Cloudformation property "Subscription" into a Terraform attribute for aws_sns_topic but it doesn't exist, so it gives up.

This is something could be fixed. I added an override system to the tool in a previous release. This override functionality allows you to inspect the Cloudformation properties ahead of time and then manually do things.

The logic for performing the overrides is here:

cf2tf/src/cf2tf/convert.py

Lines 610 to 625 in a0ad1ea

def perform_resource_overrides(
tf_type: str, params: Dict[str, TerraformType], tc: TemplateConverter
):
log.debug("Overiding params for {tf_type}")
if tf_type not in OVERRIDE_DISPATCH:
return params
param_overrides = OVERRIDE_DISPATCH[tf_type]
for param, override in param_overrides.items():
if param in params:
params = override(tc, params)
return params

The actual overrides are stored here:
from typing import TYPE_CHECKING, Callable, Dict
from cf2tf.terraform.hcl2.custom import LiteralType
from cf2tf.terraform.hcl2.primitive import NullType, StringType, TerraformType
if TYPE_CHECKING:
from cf2tf.convert import TemplateConverter
CFParams = Dict[str, TerraformType]
Override = Callable[["TemplateConverter", CFParams], CFParams]
ParamOverride = Dict[str, Override]
ResourceOverride = Dict[str, ParamOverride]
def s3_bucket_acl(_tc: "TemplateConverter", params: CFParams) -> CFParams:
access_controls: CFParams = {
"Private": StringType("private"),
"PublicRead": StringType("public-read"),
"PublicReadWrite": StringType("public-read-write"),
"AuthenticatedRead": StringType("authenticated-read"),
"LogDeliveryWrite": StringType("log-delivery-write"),
"BucketOwnerRead": NullType(),
"BucketOwnerFullControl": NullType(),
"AwsExecRead": StringType("aws-exec-read"),
}
orig_value = params["AccessControl"]
new_value = access_controls[orig_value] # type: ignore
del params["AccessControl"]
params["acl"] = new_value
return params
def s3_bucket_policy(_tc: "TemplateConverter", params: CFParams) -> CFParams:
policy_value = params["PolicyDocument"]
params["PolicyDocument"] = LiteralType(f"jsonencode({policy_value.render(4)}\n )")
return params
OVERRIDE_DISPATCH: ResourceOverride = {
"aws_s3_bucket": {"AccessControl": s3_bucket_acl},
"aws_s3_bucket_policy": {"PolicyDocument": s3_bucket_policy},
}

I will take a look at fixing the topic subscription with an override soon. Thanks for opening the issue with a clear example.

@shadycuz shadycuz changed the title Improvement for AWS Auto Scaling Group and other modules Add overrides for aws_sns_topic and other problematic conversions Mar 16, 2023
@shadycuz shadycuz added enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed labels Mar 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants