awslabs/aws-cfn-template-flip

to_yaml converts entire template, including json values

daschi opened this issue ยท 8 comments

Hello and thank you so much for this package!

I was wondering if anyone had come across the issue of trying to convert a json template to yaml that includes some JSON values. For example, the AWS::StepFunctions::StateMachine resource has a property DefinitionString which requires the Amazon States Language JSON-based syntax. Currently the converter will convert the value of DefinitionString from JSON to yaml format, which is invalid syntax for that CloudFormation resource.

I was considering a potential solution would be to convert the entire template to yaml, and then load the yaml file as an object and iterate each of the CloudFormation Resources and use the to_json method on the values that should remain JSON (like the DefinitionString for AWS::StepFunctions::StateMachine). Would love to hear of any other solutions you've used or thought of or if you have any feedback on this approach! Thanks!

Hi @daschi and thanks for the bug report. Do you have an example template that I could work from to see if I can find a nice way around this?

It's a interesting topic as normally when I build a YAML template some payloads/values are acceptable in yaml or json and are interpreted correctly by Cloudformation.
A sample template with the issue will be good to know how to handle the parser and maybe add some pre-processor function to keep some data as-is.

@stilvoid Here's an example json template, the yaml output, and then the valid yaml template that AWS StateMachine resource expects:

# input json template
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Transform": "AWS::Serverless-2016-10-31",
    "Resources": {
        "ExampleStateMachineResource": {
            "Type": "AWS::StepFunctions::StateMachine",
            "Properties": {
                "DefinitionString": {
                  "StartAt": "First State",
                  "States": {
                    "First State": {
                      "Type": "Task",
                      "Resource": "FunctionARN",
                      "Next": "Second State"
                    },
                    "Second State": {
                      "Type": "Task",
                      "Resource": "FunctionARN",
                      "End": true
                    }
                  }
                }
            }
        }
    }
} 
# output yaml template 
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  ExampleStateMachineResource:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      DefinitionString:
        StartAt: First State
        States:
          First State:
            Type: Task
            Resource: FunctionARN
            Next: Second State
          Second State:
            Type: Task
            Resource: FunctionARN
            End: true
# Valid yaml template for StateMachine resource
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  ExampleStateMachineResource:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      DefinitionString: |-
        {
          "StartAt": "First State",
          "States": {
            "First State": {
              "Type": "Task",
              "Resource": "FunctionARN",
              "Next": "Second State"
            },
            "Second State": {
              "Type": "Task",
              "Resource": "FunctionARN",
              "End": true
            }
          }
        }

Let me know if I can help with any more examples!

I got the problem and will try to add some configuration to the tool to keep parts of the value as-is based on the resource type.

@daschi DefinitionString must be a string according to docs, not a JSON document.

I'm working in this issue and will get back soon with the feature.

Fixed and send PR: #80

Fixed in #80