Comments (5)
These two types are substantially different from the rest of the resource types, because they live in a resource's metadata.
cfndsl currently does support metadata. For example, the following
# Example cribbed partially from aws cloudformation user guide
CloudFormation {
Description "Example of using Metadata"
Parameter("BucketName") {
Type "String"
}
Parameter("S3User") {
Type "String"
}
Instance("WebServer") {
DependsOn "BucketPolicy"
Metadata("AWS::CloudFormation::Authentication", {
"S3AccessCreds" => {
"type" => "S3",
"accessKeyId" => Ref("CfnKeys"),
"secretKey" => FnGetAtt( "CfnKeys", "SecretAccessKey" )
}
})
Metadata("AWS::CloudFormation::Init",
{
'config' => {
"packages" => { "yum" => { "httpd" => [] } },
"files" => {
"/var/www/html/index.html" => {
"source" =>
FnFormat( "http://s3.amazonaws.com/%{BucketName}/index.html"),
"mode" => "000400",
"owner" => "apache",
"group" => "apache",
"authentication" => "S3AccessCreds"
}
},
"services" => {
"sysvinit" => {
"httpd" => {
"enabled" => "true",
"ensureRunning" => "true" }
}
}
}
})
InstanceType "m1.small"
}
BucketPolicy("BucketPolicy") {
Bucket Ref("BucketName")
PolicyDocument({
"key" => "value"
})
}
AccessKey("CfnKeys") {
UserName Ref("S3User")
}
}
Produces this:
{
"Parameters" : {
"BucketName" : {
"Type" : "String"
},
"S3User" : {
"Type" : "String"
}
},
"Resources" : {
"BucketPolicy" : {
"Type" : "AWS::S3::BucketPolicy",
"Properties" : {
"Bucket" : {
"Ref" : "BucketName"
},
"PolicyDocument" : {
"key" : "value"
}
}
},
"CfnKeys" : {
"Type" : "AWS::IAM::AccessKey",
"Properties" : {
"UserName" : {
"Ref" : "S3User"
}
}
},
"WebServer" : {
"DependsOn" : "BucketPolicy",
"Type" : "AWS::EC2::Instance",
"Properties" : {
"InstanceType" : "m1.small"
},
"Metadata" : {
"AWS::CloudFormation::Authentication" : {
"S3AccessCreds" : {
"accessKeyId" : {
"Ref" : "CfnKeys"
},
"type" : "S3",
"secretKey" : {
"Fn::GetAtt" : [
"CfnKeys",
"SecretAccessKey"
]
}
}
},
"AWS::CloudFormation::Init" : {
"config" : {
"packages" : {
"yum" : {
"httpd" : []
}
},
"services" : {
"sysvinit" : {
"httpd" : {
"ensureRunning" : "true",
"enabled" : "true"
}
}
},
"files" : {
"/var/www/html/index.html" : {
"owner" : "apache",
"source" : {
"Fn::Join" : [
"",
[
"http://s3.amazonaws.com/",
{
"Ref" : "BucketName"
},
"/index.html"
]
]
},
"group" : "apache",
"mode" : "000400",
"authentication" : "S3AccessCreds"
}
}
}
}
}
}
},
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Example of using Metadata"
}
II'l try to come up with better ways to do this, though.
from cfndsl.
A question now would be, what should cfndsl support for CloudFormation::Init and CloudFormation::Authentication look like. Perhaps it would look something like this following template:
CloudFormation {
Description "Example of using Metadata"
Parameter("BucketName") {
Type "String"
}
Parameter("S3User") {
Type "String"
}
Instance("WebServer") {
DependsOn "BucketPolicy"
CloudFormation_Authentication("S3AccessCreds") {
type "S3"
accessKeyId Ref("CfnKeys")
secretKey FnGetAtt( "CfnKeys", "SecretAccessKey" )
# or perhaps even for these last two have a shortcut
awsKey("CfnKeys")
}
CloudFormation_Init {
config {
package("yum", "httpd")
file("/var/www/html/index.html") {
source FnFormat( "http://s3.amazonaws.com/%{BucketName}/index.html"),
mode "000400",
owner "apache",
group "apache",
authentication "S3AccessCreds"
}
service("sysvinit", "httpd") {
enabled true
ensureRunning true
}
|
InstanceType "m1.small"
}
BucketPolicy("BucketPolicy") {
Bucket Ref("BucketName")
PolicyDocument({
"key" => "value"
})
}
AccessKey("CfnKeys") {
UserName Ref("S3User")
}
}
Here, the methods CloudFormation_Authentication and CloudFormation_Init would be special methods that would create entries into the Metadata, sort of like, but somewhat different from Propterty methods like InstanceType. There would be a handful of new types (MetadataAuthentication, InitConfig, InitPackages, InitFiles, ...) Some of these new types would be dictionary types types instead of Array types, so this would mean writing some new metacoding architecture to handle the new types of types. I think that all of this can be done, but it is a resonably big chunk of work.
from cfndsl.
Hi Chris,
Your solution on both of the types are workable. But in order to maintain the consistency of type construction and being able to closely reflect similar structure to CloudFormation template. I prefer the following use case
Instance("WebServer") {
DependsOn "BucketPolicy"
Metadata {
Resource('S3AccessCreds'){
Type 'AWS::CloudFormation::Authentication'
ServiceType :S3
AccessKeyId Ref("CfnKeys")
AecretKey FnGetAtt( "CfnKeys", "SecretAccessKey" )
Buckets(Ref("Bucket1"), Ref("Bucket2"))
}
}
Metadata {
AnnonymousResource{
Type 'AWS::CloudFormation::Init'
ConfigSet('set1', ['config1', 'config2'])
Config('config1') {
package("yum", "httpd")
file("/var/www/html/index.html") {
source FnFormat( "http://s3.amazonaws.com/%{BucketName}/index.html"),
mode "000400",
owner "apache",
group "apache",
authentication "S3AccessCreds"
}
service("sysvinit", "httpd") {
enabled true
ensureRunning true
}
}
# config2 goes into here similar to config 1
}
}
InstanceType "m1.small"
}
from cfndsl.
I am afraid that I do not agree. Neither CloudFormation::Init nor CloudFormation::Authentication objects are structured like Resources, and calling them Resources would cloud the issue. Let me show you what I mean. Here is a snippet of template from the AWS CloudFormation Samples (http://aws.amazon.com/code/3233063344774450) from the S3Bucket_SourceAuth.template:
"Resources": {
...
"WebServer": {
"Type": "AWS::EC2::Instance",
"DependsOn" : "BucketPolicy",
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"packages" : {
"yum" : {
"httpd" : []
}
},
"sources" : {
"/var/www/html" : { "Fn::Join" : ["", ["http://", { "Ref" : "Buc
ketName" }, ".s3.amazonaws.com/website.tar.gz"]]}
},
"services" : {
"sysvinit" : {
"httpd" : { "enabled" : "true", "ensureRunning" : "true" }
}
}
}
},
"AWS::CloudFormation::Authentication" : {
"S3AccessCreds" : {
"type" : "S3",
"accessKeyId" : { "Ref" : "CfnKeys" },
"secretKey" : {"Fn::GetAtt": ["CfnKeys", "SecretAccessKey"]},
"buckets" : [ { "Ref" : "BucketName" } ]
}
}
},
"Properties": {
"ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
"InstanceType" : { "Ref" : "InstanceType" },
"SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ],
"KeyName" : { "Ref" : "KeyName" },
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash\n",
"yum update -y aws-cfn-bootstrap\n",
"# Install application\n",
"/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServer ",
" --region ", { "Ref" : "AWS::Region" }, "\n",
"# All is well so signal success\n",
"/opt/aws/bin/cfn-signal -e $? '", { "Ref" : "WaitHandle" }, "'\n"
]]}}
}
},
}
Here "WebServer is a Resource - it lives directly in the resources container object, and it has the format
name: {
Type: AWS::blah::blah
Properties: {
foo: bar
}
}
The CloudFormation::Init and CloudFormation::Authentication sections live inside the Metadata on this resource. Even within that, they differ substantially from Resource objects:
Metadata:
AWS::CloudFormation::Type: {
contents
}
There is no "Type" section, no Properties section, nor any other of the trappings of a resource. Neither one of these creates a resource that you can use Ref or Fn::GetAtt on, they do not DependsOn anything (other than the implicit relationship they have with the Resource their metadata is on) nor can other resources DependsOn them.
Basically, the Metadata section of a resource is just a bib blob of json that gets associated with the created resource in the cloud. You can actually put anything you like in them, and get it out at runtime with a call to cfn-get-metadata. The other cfn-init scripts treat two sections of the metadata special - AWS::CloudFormation::Init and AWS::CloudFormation::Authentication.
from cfndsl.
Hi Chris,
I can see your point, and I agree that both of them are not directly attached to resources root. Now, I don't think they should be represented by Resource. So I scratch my previous idea.
Though they are not classified as resource, I think they are some kind of types that used in Metadata. And I still want them to be modeled rather than represented by a Hash.
So I come up a second idea that these two types has a capability to present themselves in Metadata. Please see the following use case for example
s3_access_creds = AWSCloudFormationAuthentication('S3AccessCreds'){
Type 'S3'
AccessKeyId Ref("CfnKeys")
AecretKey FnGetAtt( "CfnKeys", "SecretAccessKey" )
Buckets(Ref("Bucket1"), Ref("Bucket2"))
}
cfn_init = AWSCloudFormationInit {
ConfigSet('set1', ['config1', 'config2'])
Config('config1') {
package("yum", "httpd")
file("/var/www/html/index.html") {
source FnFormat( "http://s3.amazonaws.com/%{BucketName}/index.html")
mode "000400"
owner "apache"
group "apache"
authentication "S3AccessCreds"
}
service("sysvinit", "httpd") {
enabled true
ensureRunning true
}
}
#...
}
Metadata(s3_access_creds.to_metadata)
Metadata(cfn_init.to_metadata)
from cfndsl.
Related Issues (20)
- undefined method `EC2_LaunchTemplate' for #<CfnDsl::CloudFormationTemplate:...> (NoMethodError) HOT 1
- gitter.im link is broken (gives 404 not found) HOT 2
- Where should we define custom helper methods? HOT 1
- Possible regressions 0.17.5 -> 1.0.0 HOT 8
- Resources ["Foo"] refer to unknown Reference AWS::Partition HOT 4
- Typo in README examples
- CloudFrontOriginAccessIdentity is an undefined method HOT 4
- Issue with DSL generation from cli arguments HOT 1
- unknown type AWSResourceGroupsGroupJson HOT 1
- Shorthand method of accessing resource attributes via FnSub fails reference checks HOT 1
- Outdated assertion in Readme HOT 1
- SecurityGroupIngress is always an array - 1.1.1 HOT 2
- Task: Generate types from CloudFormation resource registry schemas
- Freeze specifications version HOT 2
- Allow ruby versions until eol
- Missing Support for the TimeZone property of AWS::AutoScaling::ScheduledAction HOT 1
- List ItemType in the specification file breaking template generation with spec version 69.0.0 HOT 1
- AWS::CloudFormation::Interface HOT 4
- Missing AWS::ElasticLoadBalancingV2::LoadBalancer SubnetMapping HOT 2
- Undefined method `Name' for `CfnDsl::AWS::Types::AWS_SSM_Association` HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cfndsl.