redhat-developer / vscode-yaml

YAML support for VS Code with built-in kubernetes syntax support
MIT License
648 stars 219 forks source link

Cloudformation template: result of !Join fails validation for string #177

Open jrnail23 opened 5 years ago

jrnail23 commented 5 years ago

Given the below setup, my cloudformation template is failing validation, as it's (correctly) stating the Name property below should be a string, but I'm otherwise properly using the !Join function, which should return a string.

Here's a simplified version of my cloudformation template, to demonstrate failure mytemplate.cf.yml

AWSTemplateFormatVersion: 2010-09-09

Resources:
  MyWebAppUrl:
    Type: "AWS::Route53::RecordSet"
    Properties:
      Type: A
      Name: !Join [".", ["StringA", "StringB"]]
      HostedZoneId: "FAKE_ZONE_ID"

my settings.json

{
    "yaml.customTags": [
        "!Join sequence"
    ],
    "yaml.format.enable": true
}

validation failure

        {
            "severity": 1,
            "range": {
                "start": {
                    "line": 22,
                    "character": 18
                },
                "end": {
                    "line": 22,
                    "character": 47
                }
            },
            "message": "Incorrect type. Expected \"string\"."
        }

here's what I suspect is the AST:

[
    {
        "name": "AWSTemplateFormatVersion",
        "kind": 15,
        "location": {
            "uri": "file:///Users/myname/dev/myproject/ops/.cfn/mytemplate.cf.yml",
            "range": {
                "start": {
                    "line": 0,
                    "character": 0
                },
                "end": {
                    "line": 0,
                    "character": 36
                }
            }
        }
    },
    {
        "name": "Resources",
        "kind": 2,
        "location": {
            "uri": "file:///Users/myname/dev/myproject/ops/.cfn/mytemplate.cf.yml",
            "range": {
                "start": {
                    "line": 2,
                    "character": 0
                },
                "end": {
                    "line": 8,
                    "character": 34
                }
            }
        }
    },
    {
        "name": "MyWebAppUrl",
        "kind": 2,
        "location": {
            "uri": "file:///Users/myname/dev/myproject/ops/.cfn/mytemplate.cf.yml",
            "range": {
                "start": {
                    "line": 3,
                    "character": 2
                },
                "end": {
                    "line": 8,
                    "character": 34
                }
            }
        },
        "containerName": "Resources"
    },
    {
        "name": "Type",
        "kind": 15,
        "location": {
            "uri": "file:///Users/myname/dev/myproject/ops/.cfn/mytemplate.cf.yml",
            "range": {
                "start": {
                    "line": 4,
                    "character": 4
                },
                "end": {
                    "line": 4,
                    "character": 35
                }
            }
        },
        "containerName": "Resources.MyWebAppUrl"
    },
    {
        "name": "Properties",
        "kind": 2,
        "location": {
            "uri": "file:///Users/myname/dev/myproject/ops/.cfn/mytemplate.cf.yml",
            "range": {
                "start": {
                    "line": 5,
                    "character": 4
                },
                "end": {
                    "line": 8,
                    "character": 34
                }
            }
        },
        "containerName": "Resources.MyWebAppUrl"
    },
    {
        "name": "Type",
        "kind": 15,
        "location": {
            "uri": "file:///Users/myname/dev/myproject/ops/.cfn/mytemplate.cf.yml",
            "range": {
                "start": {
                    "line": 6,
                    "character": 6
                },
                "end": {
                    "line": 6,
                    "character": 13
                }
            }
        },
        "containerName": "Resources.MyWebAppUrl.Properties"
    },
    {
        "name": "Name",
        "kind": 18,
        "location": {
            "uri": "file:///Users/myname/dev/myproject/ops/.cfn/mytemplate.cf.yml",
            "range": {
                "start": {
                    "line": 7,
                    "character": 6
                },
                "end": {
                    "line": 7,
                    "character": 47
                }
            }
        },
        "containerName": "Resources.MyWebAppUrl.Properties"
    },
    {
        "name": "HostedZoneId",
        "kind": 15,
        "location": {
            "uri": "file:///Users/myname/dev/myproject/ops/.cfn/mytemplate.cf.yml",
            "range": {
                "start": {
                    "line": 8,
                    "character": 6
                },
                "end": {
                    "line": 8,
                    "character": 34
                }
            }
        },
        "containerName": "Resources.MyWebAppUrl.Properties"
    }
]
jrnail23 commented 5 years ago

After digging into the code a bit, it seems that the problem here is that !Join actually transforms a sequence into a scalar, but that concept doesn't appear to be supported by the custom tag parsing mechanism. As such, I'd expect that cloudformation's !Split function might be problematic for the same reasons (although in the opposite direction).

Perhaps the problem might be solved by adding another optional token to the custom tag to indicate the return type (if it differs from the input type). Something like !Join sequence -> scalar could work, and with that approach you could also have !Split -> sequence, where it would apply the convention of scalar being the default node type (thus omitted in this example), and sequence being the actual type of the transformed node.

programmer04 commented 5 years ago

It is crucial to fix because many other extensions have vscode-yaml as dependency e.g. Kubernetes, Atlassian for VSCode etc. So when you want to use vscode-cfn-lint you have to uninstall them and vscode-yaml.

DamirAinullin commented 5 years ago

I have the same problem with cloudformation script and !Join.

cybercussion commented 5 years ago

If it helps I notice I don't get the issue on a S3 WebsiteBucketPolicy Resource, but I do get the !Join not a string issue on a CloudFront Distribution Properties Origins DomainName.

Resources:
  S3Bucket:
  WebsiteBucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket: !Ref S3Bucket
        PolicyDocument:
          Statement:
          - Sid: PublicReadForGetBucketObjects
            Effect: Allow
            Principal: '*'
            Action: s3:GetObject
            Resource: !Join [ '', ['arn:aws:s3:::', !Ref S3Bucket, /*] ]

vs

CFDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Comment: Cloudfront Distribution pointing to S3 Bucket
        Origins:
        - DomainName: !Join [ '', [ !Ref S3Bucket, '.s3.amazonaws.com' ] ] # <-- Error Incorrect type, expected string
maczes commented 4 years ago

I'm experiencing this same issue when working with yaml template. I had to turn off yaml validation in config.json to get rid of it. My config.json settings:

"yaml.customTags": [
        "!And scalar",
        "!And mapping",
        "!And sequence",
        "!If scalar",
        "!If mapping",
        "!If sequence",
        "!Not scalar",
        "!Not mapping",
        "!Not sequence",
        "!Equals scalar",
        "!Equals mapping",
        "!Equals sequence",
        "!Or scalar",
        "!Or mapping",
        "!Or sequence",
        "!FindInMap scalar",
        "!FindInMap mappping",
        "!FindInMap sequence",
        "!Base64 scalar",
        "!Base64 mapping",
        "!Base64 sequence",
        "!Cidr scalar",
        "!Cidr mapping",
        "!Cidr sequence",
        "!Ref scalar",
        "!Ref mapping",
        "!Ref sequence",
        "!Sub scalar",
        "!Sub mapping",
        "!Sub sequence",
        "!GetAtt scalar",
        "!GetAtt mapping",
        "!GetAtt sequence",
        "!GetAZs scalar",
        "!GetAZs mapping",
        "!GetAZs sequence",
        "!ImportValue scalar",
        "!ImportValue mapping",
        "!ImportValue sequence",
        "!Select scalar",
        "!Select mapping",
        "!Select sequence",
        "!Split scalar",
        "!Split mapping",
        "!Split sequence",
        "!Join scalar",
        "!Join mapping",
        "!Join sequence",
        "!And",
        "!If",
        "!Not",
        "!Equals",
        "!Or",
        "!FindInMap",
        "!Base64",
        "!Join",
        "!Cidr",
        "!Ref",
        "!Sub",
        "!GetAtt",
        "!GetAZs",
        "!ImportValue",
        "!Select",
        "!Split"
    ],
    "yaml.format.enable": true,
    "yaml.validate": false,
pflugs30 commented 4 years ago

@jrnail23 were you ever able to resolve this issue or find a suitable workaround? I am facing the same thing today. Thanks.

jrnail23 commented 4 years ago

no, @pflugs30, I wasn't. We've since moved on to other ways of working with CloudFormation (building up the config using JS, rather than using YAML).

samuelms1 commented 3 years ago

Sad that this got closed b/c this is still an issue.

joshuawilson commented 3 years ago

@samuelms1 this is not closed. I just hasn't been touched in a while.

oshribr commented 2 years ago

@samuelms1 this is not closed. I just hasn't been touched in a while.

Any new update?

djodrell commented 1 year ago

This is still an issue: image

connell-theaa commented 1 year ago

This is as well: LogGroupName: !Join ["/", ["/aws/pipeline", !Ref "AWS::StackName"]]

diegojaguares commented 1 year ago

Mismo problema: La unica fue deshabilitar la valiacion... busque por horas y nada funciono!

AutorizerApiEntityManagements0001: Type: "AWS::ApiGateway::Authorizer" Properties: IdentitySource: method.request.header.Authorization Name: !ImportValue "Stack-AWS-Cognito-UserPool-UAT-UserPool" RestApiId: !Ref ApiEntityManagements0001 Type: "COGNITO_USER_POOLS" ProviderARNs: