Git Product home page Git Product logo

Comments (13)

mdub avatar mdub commented on June 3, 2024 1

I'm kind of pissed at the way AWS have chosen to use (abuse?) YAML tags, in their adoption of YAML, e.g.

Outputs:
  LoadBalancerAddress:
    Value: !GetAtt
    - LoadBalancer
    - DNSName

as a shorthand for

Outputs:
  LoadBalancerAddress:
    Value: 
      Fn::GetAtt:
      - LoadBalancer
      - DNSName

As I understand it, tags are intended to denote types. The really annoying thing is that the first example above doesn't even round-trip via YAML!

irb> puts YAML.dump(YAML.load(raw))
---
Outputs:
  LoadBalancerAddress:
    Value:
    - LoadBalancer
    - DNSName

FFS! I wish they'd just treated YAML as an alternative serialisation format.

Anyway, If we want Stackup to support the new syntax, we have two options:

A. retain input template format/body (awscli-compatible)
B. parse-time conversion to data (backward-compatible)

Option A: retain input template format

To be fully compatible with what the AWS CLI (now) does, we'd have to retain the original YAML template text, and send it intact up to CloudFormation. As a result:

  • AWS would take take of the funky tag handling
  • we wouldn't lose tags used in the input YAML
  • Stackup's behaviour would change (where we now send JSON, we'd be sending YAML)
  • Stackup internals would have to change (because we currently treat templates as Ruby data)
  • we would no longer be "normalising" the template at load time, so "diffs" would get funky, if either the format (JSON/YAML) for formatting (e.g. amount of whitespace) changed

Option B: parse-time conversion

A simpler change is to stick with our current approach - converting the input JSON/YAML to data within Stackup - and just add some magic to convert the tags to their equivalent JSON-compatible forms, e.g. !GetAtt to Fn::GetAtt. And then:

  • most of Stackup would be unchanged
  • diffs would continue to work
  • bit it's a bit lossy, as tags are converted to their more verbose form
  • going forward, we would have to match any other "YAML magic" AWS chose to implement

from stackup.

mdub avatar mdub commented on June 3, 2024

Actually, stackup has always supported templates (and parameters) in YAML format. Internally, it's just data, which we then serialise to JSON when invoking the CloudFormation API.

I see no advantage in uploading the original YAML to CloudFormation, do you?

from stackup.

robert2d avatar robert2d commented on June 3, 2024

Perfect, thanks Mike.

from stackup.

mdub avatar mdub commented on June 3, 2024

I've reopened this because, while we already support YAML, we don't support the new "abbreviated syntax for tags", e.g. !GetAtt vs Fn::GetAtt.

from stackup.

lukeck avatar lukeck commented on June 3, 2024

I'm not sure how much of an advantage it is but if a template is uploaded in YAML, get-template gives it back to you in YAML.

from stackup.

mdub avatar mdub commented on June 3, 2024

@lukeck: Damn. If that's true it means we probably can't away with converting the template into a canonical form (i.e. data) within Stackup; instead, we'll have to retain the original template text.

from stackup.

tigris avatar tigris commented on June 3, 2024

This thread is relevant to my interests.

from stackup.

lukeck avatar lukeck commented on June 3, 2024

I'm not in love with option A but option B looks like it's a recipe for an ongoing headache.

from stackup.

mdub avatar mdub commented on June 3, 2024

I'm not sure it's that much of an ongoing headache, @lukeck. The logic I've implemented in #32 is basically:

  • if you see !Ref, substitute Ref
  • if you see !SomethingElse, substitute Fn::SomethingElse

See

def accept(target)
case target.tag
when "!Ref"
{ "Ref" => super }
when /^!(\w+)$/
{ "Fn::#{$1}" => super }
else
super
end
end

from stackup.

mdub avatar mdub commented on June 3, 2024

Closed with #32.

from stackup.

benhutchison avatar benhutchison commented on June 3, 2024

Stackup's implementation doesn't seem to support YAML AWS pseudo-parameter substitution via !Sub .

  SubscribeLambda:
    Type: "AWS::SNS::Subscription"
    Properties:
      Endpoint: !Sub |
        arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:addBuyProfile
      Protocol: lambda
      TopicArn: !Sub |
        arn:aws:sns:${AWS::Region}:${AWS::AccountId}:cbr-profiler

I concur with @lukeck assessment that option (b) will be a headache, due to this sort of thing

from stackup.

benhutchison avatar benhutchison commented on June 3, 2024

Additionally, there seems to be a trailing newlines that gets inserted into ARN strings in YAML, making them fail AWS validation

Template:

Resources:
  SnsPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Sub |
        arn:aws:lambda:ap-southeast-2:123456789012:function:myLambda
      Principal: sns.amazonaws.com
      SourceArn: !Sub |
        arn:aws:sns:ap-southeast-2:123456789012:*

Result (note the newline that has been retained at end of ARN is whats failing the regex validation)

INFO: [15:35:50] SnsPermission - CREATE_FAILED - 2 validation errors detected: Value 'arn:aws:sns:ap-southeast-2:123456789012:*
' at 'sourceArn' failed to satisfy constraint: Member must satisfy regular expression pattern: arn:aws:([a-zA-Z0-9\-])+:([a-z]{2}-[a-z]+-\d{1})?:(\d{12})?:(.*)

from stackup.

mdub avatar mdub commented on June 3, 2024

It should support !Sub, @benhutchison. I think the problem is that by using |, you've got newlines in the source YAML. Try without them, e.g.

 SubscribeLambda:
    Type: "AWS::SNS::Subscription"
    Properties:
      Endpoint: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:addBuyProfile
      Protocol: lambda
      TopicArn: !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:cbr-profiler

If that still doesn't work, please raise a separate issue.

from stackup.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.