rubycfn 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/lib/compound/resources.rb +1 -0
- data/lib/compound/vpc.rb +89 -0
- data/lib/compound.rb +1 -0
- data/lib/rubycfn/version.rb +1 -1
- data/lib/rubycfn.rb +54 -2
- data/templates/compile.rb.erb +2 -2
- data/templates/project_concern.rb.erb +18 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d01bd17b4d8c71bd2377cbee3606eddb28778df
|
4
|
+
data.tar.gz: 7d92a19ab91e083aed1492c4b0a00f74b01896d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3708591c58295896ef5a5b46924eead40ace9744a800a52361842d6e6057f4639bc87f13ee2bc80e50dc7e879b3f8fd51a8687e8e9bb2c1a5c37c6eab9191e8
|
7
|
+
data.tar.gz: 9174d991980b0ec38e0b2d92894f9de68307c1f0fc82f14b0fdcad7d347bd412ba61d319d108ecb2c1f2a11b930ad152fa7f13a5e08aba25c3b14fda516af831
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "vpc"
|
data/lib/compound/vpc.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
module RubyCfn
|
2
|
+
module VPC
|
3
|
+
def self.[](prefix, suffix, &block)
|
4
|
+
Module.new do
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
|
9
|
+
def validate_instance_tenancy(value)
|
10
|
+
unless ["", 'default', 'dedicated'].include? value
|
11
|
+
raise "Expected instance_tenancy to be within `default` or `dedicated`. Received `#{value}`"
|
12
|
+
end
|
13
|
+
value
|
14
|
+
end
|
15
|
+
|
16
|
+
variable :cidr_block,
|
17
|
+
default: "10.0.0.0/16"
|
18
|
+
variable :enable_dns_support,
|
19
|
+
default: true
|
20
|
+
variable :enable_dns_hostnames,
|
21
|
+
default: true
|
22
|
+
variable :instance_tenancy,
|
23
|
+
filter: :validate_instance_tenancy
|
24
|
+
# TODO: Move to separate compound resource
|
25
|
+
# variable :ipv6,
|
26
|
+
# default: false
|
27
|
+
# variable :subnets,
|
28
|
+
# default: 3
|
29
|
+
# variable :subnet_ip_addresses,
|
30
|
+
# default: 256
|
31
|
+
|
32
|
+
yield self if block_given? # Variable overrides
|
33
|
+
|
34
|
+
resource "#{prefix}_vpc#{suffix}",
|
35
|
+
type: "AWS::EC2::VPC" do |r, index|
|
36
|
+
r.property(:cidr_block) { cidr_block }
|
37
|
+
r.property(:enable_dns_support) { enable_dns_support }
|
38
|
+
r.property(:enable_dns_hostnames) { enable_dns_hostnames }
|
39
|
+
r.property(:instance_tenancy) { instance_tenancy } unless instance_tenancy.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
resource "#{prefix}_internet_gateway#{suffix}",
|
43
|
+
type: "AWS::EC2::InternetGateway"
|
44
|
+
|
45
|
+
resource "#{prefix}_route#{suffix}",
|
46
|
+
type: "AWS::EC2::Route" do |r, index|
|
47
|
+
r.property(:destination_cidr_block) { "0.0.0.0/0" }
|
48
|
+
r.property(:gateway_id) { "#{prefix}_internet_gateway#{suffix}".cfnize.ref }
|
49
|
+
r.property(:route_table_id) { "#{prefix}_route_table#{suffix}".cfnize.ref }
|
50
|
+
end
|
51
|
+
|
52
|
+
resource "#{prefix}_route_table#{suffix}",
|
53
|
+
type: "AWS::EC2::RouteTable" do |r, index|
|
54
|
+
r.property(:vpc_id) { "#{prefix}_vpc#{suffix}".cfnize.ref }
|
55
|
+
end
|
56
|
+
|
57
|
+
resource "#{prefix}_vpc_gateway_attachment#{suffix}",
|
58
|
+
type: "AWS::EC2::VPCGatewayAttachment" do |r, index|
|
59
|
+
r.property(:internet_gateway_id) { "#{prefix}_internet_gateway#{suffix}".cfnize.ref }
|
60
|
+
r.property(:vpc_id) { "#{prefix}_vpc#{suffix}".cfnize.ref }
|
61
|
+
end
|
62
|
+
|
63
|
+
# TODO: Move to separate compound resource
|
64
|
+
#subnets.times do |i|
|
65
|
+
# resource "#{prefix}_subnet#{suffix}#{i == 0 ? "" : i+1}",
|
66
|
+
# type: "AWS::EC2::Subnet",
|
67
|
+
# compound: true do |r, index|
|
68
|
+
# r.property(:vpc_id) { "#{prefix}_vpc#{suffix}".cfnize.ref }
|
69
|
+
# r.property(:cidr_block) { ["#{prefix}_vpc#{suffix}".cfnize.ref("CidrBlock"), subnets.to_s, ((Math.log(subnet_ip_addresses)/Math.log(2)).floor).to_s].fncidr.fnselect(i) }
|
70
|
+
# #if ipv6 == "true"
|
71
|
+
# # r.property(:ipv6_cidr_block) do
|
72
|
+
# # .. todo ..
|
73
|
+
# # end
|
74
|
+
# #end
|
75
|
+
# end
|
76
|
+
#end
|
77
|
+
|
78
|
+
#if ipv6 == "true"
|
79
|
+
# resource "#{prefix}_ipv6_cidr_block#{suffix}",
|
80
|
+
# type: "AWS::EC2::VPCCidrBlock" do |r, index|
|
81
|
+
# r.property(:vpc_id) { "#{prefix}_vpc#{suffix}".cfnize.ref }
|
82
|
+
# r.property(:amazon_provided_ipv6_cidr_block) { true }
|
83
|
+
# end
|
84
|
+
#end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/compound.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "compound/vpc"
|
data/lib/rubycfn/version.rb
CHANGED
data/lib/rubycfn.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require "neatjson"
|
3
3
|
require "json"
|
4
4
|
require "rubycfn/version"
|
5
|
+
require "compound/resources"
|
5
6
|
require 'active_support/concern'
|
6
7
|
|
7
8
|
@depends_on = []
|
@@ -9,6 +10,7 @@ require 'active_support/concern'
|
|
9
10
|
@outputs = {}
|
10
11
|
@parameters = {}
|
11
12
|
@properties = {}
|
13
|
+
@mappings = {}
|
12
14
|
@resources = {}
|
13
15
|
@variables = {}
|
14
16
|
@global_variables = {}
|
@@ -59,6 +61,22 @@ class String
|
|
59
61
|
end
|
60
62
|
|
61
63
|
class Array
|
64
|
+
def fncidr
|
65
|
+
{
|
66
|
+
"Fn::Cidr": self
|
67
|
+
}
|
68
|
+
end
|
69
|
+
alias_method :cidr, :fncidr
|
70
|
+
|
71
|
+
def fnfindinmap(name = nil)
|
72
|
+
self.unshift(name.cfnize) if name
|
73
|
+
{
|
74
|
+
"Fn::FindInMap": self
|
75
|
+
}
|
76
|
+
end
|
77
|
+
alias_method :find_in_map, :fnfindinmap
|
78
|
+
alias_method :findinmap, :fnfindinmap
|
79
|
+
|
62
80
|
def fnjoin(separator = "")
|
63
81
|
{
|
64
82
|
"Fn::Join": [
|
@@ -93,6 +111,15 @@ class ::Hash
|
|
93
111
|
def compact
|
94
112
|
delete_if { |k, v| v.nil? }
|
95
113
|
end
|
114
|
+
|
115
|
+
def fnselect(index = 0)
|
116
|
+
{
|
117
|
+
"Fn::Select": [
|
118
|
+
index,
|
119
|
+
self
|
120
|
+
]
|
121
|
+
}
|
122
|
+
end
|
96
123
|
end
|
97
124
|
|
98
125
|
module Rubycfn
|
@@ -115,6 +142,24 @@ module Rubycfn
|
|
115
142
|
end
|
116
143
|
end
|
117
144
|
|
145
|
+
def self.mapping(name, arguments = {})
|
146
|
+
raise "`name` is required for mapping." unless arguments[:name]
|
147
|
+
unless arguments[:data]
|
148
|
+
%w(key value).each do |k|
|
149
|
+
raise "`#{k}` is required for mapping, unless a `data` hash is passed." unless arguments[k.to_sym]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
name = name.to_s.cfnize
|
154
|
+
kv_pairs = arguments[:data] ? arguments[:data] : { "#{arguments[:key]}": "#{arguments[:value]}" }
|
155
|
+
res = {
|
156
|
+
"#{name}": {
|
157
|
+
"#{arguments[:name]}": kv_pairs
|
158
|
+
}
|
159
|
+
}
|
160
|
+
TOPLEVEL_BINDING.eval("@mappings = @mappings.deep_merge(#{res})")
|
161
|
+
end
|
162
|
+
|
118
163
|
def self.parameter(name, arguments)
|
119
164
|
name = name.to_s.cfnize
|
120
165
|
arguments[:type] ||= "String"
|
@@ -151,6 +196,7 @@ module Rubycfn
|
|
151
196
|
arguments[:value] ||= ""
|
152
197
|
arguments[:required] ||= false
|
153
198
|
arguments[:global] ||= false
|
199
|
+
arguments[:filter] ||= nil
|
154
200
|
|
155
201
|
if arguments[:value].empty?
|
156
202
|
arguments[:value] = arguments[:default]
|
@@ -161,6 +207,10 @@ module Rubycfn
|
|
161
207
|
end
|
162
208
|
end
|
163
209
|
|
210
|
+
if arguments[:filter]
|
211
|
+
arguments[:value] = self.send(arguments[:filter], arguments[:value])
|
212
|
+
end
|
213
|
+
|
164
214
|
res = {
|
165
215
|
"#{name}": arguments[:value]
|
166
216
|
}
|
@@ -197,11 +247,12 @@ module Rubycfn
|
|
197
247
|
|
198
248
|
def self.resource(name, arguments, &block)
|
199
249
|
arguments[:amount] ||= 1
|
250
|
+
origname = name.to_s
|
200
251
|
name = name.to_s.cfnize
|
201
252
|
arguments[:amount].times do |i|
|
202
253
|
resource_suffix = i == 0 ? "" : "#{i+1}"
|
203
254
|
if arguments[:type].class == Module
|
204
|
-
send("include", arguments[:type][
|
255
|
+
send("include", arguments[:type][origname, resource_suffix, &block])
|
205
256
|
else
|
206
257
|
yield self, i if block_given?
|
207
258
|
res = {
|
@@ -228,10 +279,11 @@ module Rubycfn
|
|
228
279
|
skeleton = { "AWSTemplateFormatVersion": "2010-09-09" }
|
229
280
|
skeleton = JSON.parse(skeleton.to_json)
|
230
281
|
skeleton.merge!(Description: TOPLEVEL_BINDING.eval("@description"))
|
282
|
+
skeleton.merge!(Mappings: sort_json(TOPLEVEL_BINDING.eval("@mappings")))
|
231
283
|
skeleton.merge!(Parameters: sort_json(TOPLEVEL_BINDING.eval("@parameters")))
|
232
284
|
skeleton.merge!(Resources: sort_json(TOPLEVEL_BINDING.eval("@resources")))
|
233
285
|
skeleton.merge!(Outputs: sort_json(TOPLEVEL_BINDING.eval("@outputs")))
|
234
|
-
TOPLEVEL_BINDING.eval("@variables = @resources = @outputs = @properties = @parameters = {}")
|
286
|
+
TOPLEVEL_BINDING.eval("@variables = @resources = @outputs = @properties = @mappings = @parameters = {}")
|
235
287
|
TOPLEVEL_BINDING.eval("@depends_on = []")
|
236
288
|
TOPLEVEL_BINDING.eval("@description = ''")
|
237
289
|
JSON.pretty_generate(skeleton.recursive_compact)
|
data/templates/compile.rb.erb
CHANGED
@@ -11,6 +11,6 @@ Module.constants.select do |mod|
|
|
11
11
|
end
|
12
12
|
|
13
13
|
stacks.each do |stack_name, stack|
|
14
|
-
puts "- Saved #{stack_name} to build/#{stack_name.downcase}.json"
|
15
|
-
File.open("build/#{stack_name.downcase}.json", "w") { |f| f.write(stack) }
|
14
|
+
puts "- Saved #{stack_name} to build/#{ENV["ENVIRONMENT"]}-#{stack_name.downcase}.json"
|
15
|
+
File.open("build/#{ENV["ENVIRONMENT"]}-#{stack_name.downcase}.json", "w") { |f| f.write(stack) }
|
16
16
|
end
|
@@ -20,6 +20,24 @@ module <%= name %>Stack
|
|
20
20
|
r.property(:name) { example_variable }
|
21
21
|
end
|
22
22
|
|
23
|
+
# Example VPC, creates VPC, IGW, Route, and VPCGatewayAttachment
|
24
|
+
# Settable variables:
|
25
|
+
# - cidr_block (defaults to 10.0.0.0/16)
|
26
|
+
# - enable_dns_support (boolean, default true)
|
27
|
+
# - enable_dns_hostnames (boolean, default true)
|
28
|
+
# - instance_tenancy (`default` or `dedicated`)
|
29
|
+
resource :my_first,
|
30
|
+
type: RubyCfn::VPC do |r|
|
31
|
+
r.set(:cidr_block) { "10.1.0.0/16" }
|
32
|
+
end
|
33
|
+
variable :cidr_block,
|
34
|
+
default: "10.0.0.0/16"
|
35
|
+
variable :enable_dns_support,
|
36
|
+
default: true
|
37
|
+
variable :enable_dns_hostnames,
|
38
|
+
default: true
|
39
|
+
variable :instance_tenancy,
|
40
|
+
filter: :validate_instance_tenancy
|
23
41
|
# Example resource, dynamically generated name
|
24
42
|
resource :my_example_s3_bucket,
|
25
43
|
type: "AWS::S3::Bucket"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubycfn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dennis Vink
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: neatjson
|
@@ -263,6 +263,9 @@ files:
|
|
263
263
|
- Rakefile
|
264
264
|
- bin/rubycfn
|
265
265
|
- lib/cli_methods.rb
|
266
|
+
- lib/compound.rb
|
267
|
+
- lib/compound/resources.rb
|
268
|
+
- lib/compound/vpc.rb
|
266
269
|
- lib/rubycfn.rb
|
267
270
|
- lib/rubycfn/version.rb
|
268
271
|
- rubycfn.gemspec
|