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 SAM templating capability #42

Open
EliaBoschiero opened this issue Aug 1, 2022 · 7 comments
Open

Add SAM templating capability #42

EliaBoschiero opened this issue Aug 1, 2022 · 7 comments
Labels
enhancement New feature or request

Comments

@EliaBoschiero
Copy link

EliaBoschiero commented Aug 1, 2022

Some resources are created automatically by cloudformation (Ex. Lambda Role https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) but the cloudformation/functions/ref function can't find the explicit value in the template, this is not the only case of non explicit resource creation by cloudformation, off the top of my head there's also the FunctionAlias

@shadycuz
Copy link
Member

shadycuz commented Aug 1, 2022

@EliaBoschiero Can you provide a Cloudformation template that works correctly but fails for cf2tf?

As far as I know, you can only reference parameters and resources in the current template. Here is the Cloudformation documentation for Ref where it says:

The intrinsic function Ref returns the value of the specified parameter or resource.

I understand that certain resources like SAM create more than one resource, but that doesn't mean Cloudformation allows you to reference them.

@EliaBoschiero
Copy link
Author

EliaBoschiero commented Aug 1, 2022

Can't upload yml files but this should work, it just creates the lambda, but I can reference both the Role and the live alias

If a role isn't specified, one is created for you with a logical ID of Role

With the resource having a logical ID I can reference it even if it's not explicitly declared

Transform: AWS::Serverless-2016-10-31

Description: Test Stack for cf2tf

Resources:
  TestFn:
    Type: AWS::Serverless::Function
    Properties:
      InlineCode: |
        def handler(event, context):
          print("Hello, world!")
      Handler: index.handler
      Runtime: nodejs14.x
      AutoPublishAlias: live
      Description: Function to test cf2tf
      ReservedConcurrentExecutions: 5
      Tracing: PassThrough

Outputs:
  TestFnRoleArn:
    Value: !Ref TestFnRole
  TestFnAlias:
    Value: !Ref TestFnAliaslive

@shadycuz
Copy link
Member

shadycuz commented Aug 1, 2022

@EliaBoschiero I will have to deploy this and test it, but if it works, it's some bizarre undocumented feature in Cloudformation.

I'm not sure how I will be able to fix this in cf2tf. But I will try. 😊

Thanks for opening this bug report 👍

@EliaBoschiero
Copy link
Author

EliaBoschiero commented Aug 2, 2022

@shadycuz I did some research and this is actually a SAM feature (Note the transform in the first line of my template. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-aws-serverless.html), so basically an AWS hosted macro (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-macros.html), the best way would be to look for the transform before starting the conversion, execute aws cloudformation package on the original template and use the generated template (already .json so skipping this conversion) to generate the tf files, the only issue is I can't seem to find an official way to get the transformed template on a local dir, only s3 bucket :/
(https://aws.amazon.com/blogs/compute/introducing-simplified-serverless-application-deplyoment-and-management/)

@shadycuz
Copy link
Member

shadycuz commented Aug 2, 2022

@EliaBoschiero ahh I missed that Transform key as I have never used it before. Currently cf2tf doesn't support the Transform section or the transform intrinsic function.

I dont think actually transforming the template is the correct way to implement this feature because it would require working AWS credentials.

Instead, we should inject the required additional terraform resources whenever we see a SAM function. This is not currently possible but the ability to override the default behavior for a specific resource is on the roadmap. So hopefully we will be able to fix this in the future.

For now, perhaps you could try transforming the template and then converting it with cf2tf?

@EliaBoschiero
Copy link
Author

@shadycuz Yes that's right I didn't think about the credentials.
Unless you can find the actual code of the AWS transform macro (will look into that) injecting the resources seem to be the only solution, but unless you modify the cf template it would need a rework for the return values functions (Ex. Ref, Sub, GetAtt) as they now search for the resource name in the json template.

Yes that's what I ended up doing in the end! I think a quick mention of this in the README would be useful for many people seeing as a serverless template is not actually considered compliant

(https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-aws-serverless.html)

The AWS::Serverless transform, which is a macro hosted by CloudFormation, takes an entire template written in the AWS Serverless Application Model (AWS SAM) syntax and transforms and expands it into a compliant CloudFormation template.

@shadycuz
Copy link
Member

shadycuz commented Aug 2, 2022

@EliaBoschiero If you want to submit a PR to add SAM templates to the roadmap in the README that would be great. If not I will get to it eventually.

I actually don't think we need to rework the return values functions. The way it works right now should work once we "inject" the missing resources into Terraform.

When cf2tf does a !Ref TestFnRole, it doesn't use the Cloudformation template, it instead uses the generated terraform configuration. This is for a variety of reasons but mainly because !Ref TestFnRole will be converted to aws_iam_role.test_fn_role.arn. So most of that context belongs to terraform. So as long as we have a Terraform resource called test_fn_role then everything will work.

Basically, on the first pass, we convert all the Cloudformation resources to Terraform resources but we keep all the Cloudformation expesssions. Then on the second pass, we convert the expressions to terraform equivalent.

Edit: Thanks so much for all your help digging into this issue. I do think it will be fixed one day.

@shadycuz shadycuz added the enhancement New feature or request label Sep 6, 2022
@shadycuz shadycuz changed the title Ref of a non declared resource fails Add SAM templating capability Nov 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants