sparkle_formation 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ ## v0.1.0
2
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,23 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sparkle_formation (0.1.0)
5
+ attribute_struct (~> 0.1.6)
6
+
7
+ PATH
8
+ remote: /home/spox/Projects/chrisroberts/attribute_struct
9
+ specs:
10
+ attribute_struct (0.1.7)
11
+ hashie (>= 2.0.0)
12
+
13
+ GEM
14
+ remote: https://rubygems.org/
15
+ specs:
16
+ hashie (2.0.5)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ attribute_struct!
23
+ sparkle_formation!
data/README.md ADDED
@@ -0,0 +1,262 @@
1
+ # SparkleFormation
2
+
3
+ AWS CloudFormation template building tools for Ruby. Yay!
4
+
5
+ ## What's it do?
6
+
7
+ Provides a very loose DSL to describe an AWS CloudFormation
8
+ in Ruby.
9
+
10
+ ## Is that it?
11
+
12
+ Yes. Well, kinda. It also has some extra features, like defining
13
+ components, dynamics, merging, AWS builtin function helpers, and
14
+ conjouring magic (to get unicorns).
15
+
16
+ ## What's it look like?
17
+
18
+ Lets use one of the example CF templates that creates an EC2 instance. First
19
+ we can just convert it into a single file (ec2_example.rb):
20
+
21
+ ```ruby
22
+ SparkleFormation.new('ec2_example') do
23
+ description "AWS CloudFormation Sample Template EC2InstanceSample: Create an Amazon EC2 instance running the Amazon Linux AMI. The AMI is chosen based on the region in which the stack is run. This example uses the default security group, so to SSH to the new instance using the KeyPair you enter, you will need to have port 22 open in your default security group. **WARNING** This template an Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template."
24
+
25
+ parameters do
26
+ key_name do
27
+ description 'Name of an existing EC2 KeyPair to enable SSH access to the instance'
28
+ type 'String'
29
+ end
30
+ end
31
+
32
+ mappings.region_map do
33
+ _set('us-east-1', :ami => 'ami-7f418316')
34
+ _set('us-east-1', :ami => 'ami-7f418316')
35
+ _set('us-west-1', :ami => 'ami-951945d0')
36
+ _set('us-west-2', :ami => 'ami-16fd7026')
37
+ _set('eu-west-1', :ami => 'ami-24506250')
38
+ _set('sa-east-1', :ami => 'ami-3e3be423')
39
+ _set('ap-southeast-1', :ami => 'ami-74dda626')
40
+ _set('ap-northeast-1', :ami => 'ami-dcfa4edd')
41
+ end
42
+
43
+ resources do
44
+ my_instance do
45
+ type 'AWS::EC2::Instance'
46
+ properties do
47
+ key_name _cf_ref(:key_name)
48
+ image_id _cf_map(:region_map, 'AWS::Region', :ami)
49
+ user_data _cf_base64('80')
50
+ end
51
+ end
52
+ end
53
+
54
+ outputs do
55
+ instance_id do
56
+ description 'InstanceId of the newly created EC2 instance'
57
+ value _cf_ref(:my_instance)
58
+ end
59
+ az do
60
+ description 'Availability Zone of the newly created EC2 instance'
61
+ value _cf_attr(:my_instance, :availability_zone)
62
+ end
63
+ public_ip do
64
+ description 'Public IP address of the newly created EC2 instance'
65
+ value _cf_attr(:my_instance, :public_ip)
66
+ end
67
+ private_ip do
68
+ description 'Private IP address of the newly created EC2 instance'
69
+ value _cf_attr(:my_instance, :private_ip)
70
+ end
71
+ public_dns do
72
+ description 'Public DNSName of the newly created EC2 instance'
73
+ value _cf_attr(:my_instance, :public_dns_name)
74
+ end
75
+ private_dns do
76
+ description 'Private DNSName of the newly created EC2 instance'
77
+ value _cf_attr(:my_instance, :private_dns_name)
78
+ end
79
+ end
80
+ end
81
+ ```
82
+
83
+ And once compiled we get a nice Hash that we can then convert to JSON which
84
+ is ready for AWS. To print:
85
+
86
+ ```ruby
87
+ require 'sparkle_formation'
88
+ require 'json'
89
+
90
+ puts JSON.pretty_generate(
91
+ SparkleFormation.compile('ec2_example.rb')
92
+ )
93
+ ```
94
+
95
+ Easy!
96
+
97
+ ## Why not just write JSON?
98
+
99
+ Because, who in their right mind would want to write all of that in JSON? Also,
100
+ we can start applying some of the underlying features in `SparkleFormation` to
101
+ make this easier to maintain.
102
+
103
+ # Components
104
+
105
+ Lets say we have a handful of CF templates we want to maintain, and all of those
106
+ templates use the same AMI. Instead of copying that information into all the
107
+ templates, lets create an AMI component instead, and then load it into the actual
108
+ templates.
109
+
110
+ First, create the component (components/ami.rb):
111
+
112
+ ```ruby
113
+ SparkleFormation.build do
114
+
115
+ parameters do
116
+ key_name do
117
+ description 'Name of an existing EC2 KeyPair to enable SSH access to the instance'
118
+ type 'String'
119
+ end
120
+ end
121
+
122
+ mappings.region_map do
123
+ _set('us-east-1', :ami => 'ami-7f418316')
124
+ _set('us-east-1', :ami => 'ami-7f418316')
125
+ _set('us-west-1', :ami => 'ami-951945d0')
126
+ _set('us-west-2', :ami => 'ami-16fd7026')
127
+ _set('eu-west-1', :ami => 'ami-24506250')
128
+ _set('sa-east-1', :ami => 'ami-3e3be423')
129
+ _set('ap-southeast-1', :ami => 'ami-74dda626')
130
+ _set('ap-northeast-1', :ami => 'ami-dcfa4edd')
131
+ end
132
+ end
133
+ ```
134
+
135
+ Now, we can modify our initial example to use this component (ec2_example.rb):
136
+
137
+ ```ruby
138
+ SparkleFormation.new('ec2_example').load(:ami).overrides do
139
+
140
+ description "AWS CloudFormation Sample Template EC2InstanceSample: Create an Amazon EC2 instance running the Amazon Linux AMI. The AMI is chosen based on the region in which the stack is run. This example uses the default security group, so to SSH to the new instance using the KeyPair you enter, you will need to have port 22 open in your default security group. **WARNING** This template an Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template."
141
+
142
+ resources do
143
+ my_instance do
144
+ type 'AWS::EC2::Instance'
145
+ properties do
146
+ key_name _cf_ref(:key_name)
147
+ image_id _cf_map(:region_map, 'AWS::Region', :ami)
148
+ user_data _cf_base64('80')
149
+ end
150
+ end
151
+ end
152
+
153
+ outputs do
154
+ instance_id do
155
+ description 'InstanceId of the newly created EC2 instance'
156
+ value _cf_ref(:my_instance)
157
+ end
158
+ az do
159
+ description 'Availability Zone of the newly created EC2 instance'
160
+ value _cf_attr(:my_instance, :availability_zone)
161
+ end
162
+ public_ip do
163
+ description 'Public IP address of the newly created EC2 instance'
164
+ value _cf_attr(:my_instance, :public_ip)
165
+ end
166
+ private_ip do
167
+ description 'Private IP address of the newly created EC2 instance'
168
+ value _cf_attr(:my_instance, :private_ip)
169
+ end
170
+ public_dns do
171
+ description 'Public DNSName of the newly created EC2 instance'
172
+ value _cf_attr(:my_instance, :public_dns_name)
173
+ end
174
+ private_dns do
175
+ description 'Private DNSName of the newly created EC2 instance'
176
+ value _cf_attr(:my_instance, :private_dns_name)
177
+ end
178
+ end
179
+ end
180
+ ```
181
+
182
+ Now a few things have changed. Instead of passing a block directly to the
183
+ instance instantiation, we are loading a component (the `ami` component)
184
+ into the formation, and then applying an override block on top of the `ami`
185
+ component. The result is the same as the initial example, but now we have
186
+ a DRY component to use. Great!
187
+
188
+ ## Dynamics
189
+
190
+ Okay, so lets say we want to have two ec2 instances. We could duplicate the
191
+ resource and outputs, renaming where required. This would get ugly quick,
192
+ especially as more instances are added. Making a component for the ec2 resource
193
+ won't really help since components are static, used to apply the same common
194
+ parts to multiple templates. So what do we use?
195
+
196
+ Enter `dynamics`. These are much like components, except that instead of simply
197
+ being merged, they allow passing of arguments which makes them reusable to create
198
+ unique resources. So, from our last example, lets move the ec2 related items
199
+ into a dynamic (dynamics/ec2.rb):
200
+
201
+ ```ruby
202
+ SparkleFormation.dynamic(:ec2) do |_name|
203
+ resources("#{_name}_instance".to_sym)
204
+ type 'AWS::EC2::Instance'
205
+ properties do
206
+ key_name _cf_ref(:key_name)
207
+ image_id _cf_map(:region_map, 'AWS::Region', :ami)
208
+ user_data _cf_base64('80')
209
+ end
210
+ end
211
+
212
+ outputs("#{_name}_instance_id".to_sym) do
213
+ description 'InstanceId of the newly created EC2 instance'
214
+ value _cf_ref("#{_name}_instance".to_sym)
215
+ end
216
+ outputs("#{_name}_az".to_sym) do
217
+ description 'Availability Zone of the newly created EC2 instance'
218
+ value _cf_attr("#{_name}_instance".to_sym, :availability_zone)
219
+ end
220
+ outputs("#{_name}_public_ip".to_sym) do
221
+ description 'Public IP address of the newly created EC2 instance'
222
+ value _cf_attr("#{_name}_instance".to_sym, :public_ip)
223
+ end
224
+ outputs("#{_name}_private_ip".to_sym) do
225
+ description 'Private IP address of the newly created EC2 instance'
226
+ value _cf_attr("#{_name}_instance".to_sym, :private_ip)
227
+ end
228
+ outputs("#{_name}_public_dns".to_sym) do
229
+ description 'Public DNSName of the newly created EC2 instance'
230
+ value _cf_attr("#{_name}_instance".to_sym, :public_dns_name)
231
+ end
232
+ outputs("#{_name}_private_dns".to_sym) do
233
+ description 'Private DNSName of the newly created EC2 instance'
234
+ value _cf_attr("#{_name}_instance".to_sym, :private_dns_name)
235
+ end
236
+ end
237
+ ```
238
+
239
+ Now we can put all of these together, and create multiple ec2 instance
240
+ resource easily:
241
+
242
+ ```ruby
243
+ SparkleFormation.new('ec2_example').load(:ami).overrides do
244
+
245
+ description "AWS CloudFormation Sample Template EC2InstanceSample: Create an Amazon EC2 instance running the Amazon Linux AMI. The AMI is chosen based on the region in which the stack is run. This example uses the default security group, so to SSH to the new instance using the KeyPair you enter, you will need to have port 22 open in your default security group. **WARNING** This template an Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template."
246
+
247
+ [:node1, :node2, :node3].each do |_node_name|
248
+ SparkleFormation.insert(:ec2, self, _node_name)
249
+ end
250
+
251
+ end
252
+ ```
253
+
254
+ ## TODO
255
+ * Add information about symbol importance
256
+ * Add examples of camel case control
257
+ * Add examples of complex merge strategies
258
+ * Add examples of accessing parent hash elements
259
+
260
+ # Infos
261
+ * Repository: https://github.com/heavywater/sparkle_formation
262
+ * IRC: Freenode @ #heavywater
@@ -0,0 +1,59 @@
1
+ SparkleFormation.new('ec2_example') do
2
+ description "AWS CloudFormation Sample Template EC2InstanceSample: Create an Amazon EC2 instance running the Amazon Linux AMI. The AMI is chosen based on the region in which the stack is run. This example uses the default security group, so to SSH to the new instance using the KeyPair you enter, you will need to have port 22 open in your default security group. **WARNING** This template an Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template."
3
+
4
+ parameters do
5
+ key_name do
6
+ description 'Name of an existing EC2 KeyPair to enable SSH access to the instance'
7
+ type 'String'
8
+ end
9
+ end
10
+
11
+ mappings.region_map do
12
+ _set('us-east-1', :ami => 'ami-7f418316')
13
+ _set('us-east-1', :ami => 'ami-7f418316')
14
+ _set('us-west-1', :ami => 'ami-951945d0')
15
+ _set('us-west-2', :ami => 'ami-16fd7026')
16
+ _set('eu-west-1', :ami => 'ami-24506250')
17
+ _set('sa-east-1', :ami => 'ami-3e3be423')
18
+ _set('ap-southeast-1', :ami => 'ami-74dda626')
19
+ _set('ap-northeast-1', :ami => 'ami-dcfa4edd')
20
+ end
21
+
22
+ resources do
23
+ my_instance do
24
+ type 'AWS::EC2::Instance'
25
+ properties do
26
+ key_name _cf_ref(:key_name)
27
+ image_id _cf_map(:region_map, 'AWS::Region', :ami)
28
+ user_data _cf_base64('80')
29
+ end
30
+ end
31
+ end
32
+
33
+ outputs do
34
+ instance_id do
35
+ description 'InstanceId of the newly created EC2 instance'
36
+ value _cf_ref(:my_instance)
37
+ end
38
+ az do
39
+ description 'Availability Zone of the newly created EC2 instance'
40
+ value _cf_attr(:my_instance, :availability_zone)
41
+ end
42
+ public_ip do
43
+ description 'Public IP address of the newly created EC2 instance'
44
+ value _cf_attr(:my_instance, :public_ip)
45
+ end
46
+ private_ip do
47
+ description 'Private IP address of the newly created EC2 instance'
48
+ value _cf_attr(:my_instance, :private_ip)
49
+ end
50
+ public_dns do
51
+ description 'Public DNSName of the newly created EC2 instance'
52
+ value _cf_attr(:my_instance, :public_dns_name)
53
+ end
54
+ private_dns do
55
+ description 'Private DNSName of the newly created EC2 instance'
56
+ value _cf_attr(:my_instance, :private_dns_name)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,12 @@
1
+ require 'sparkle_formation'
2
+ require 'pp'
3
+ require 'json'
4
+
5
+ puts JSON.pretty_generate(
6
+ SparkleFormation.compile(
7
+ File.join(
8
+ File.dirname(__FILE__),
9
+ 'cloudformation/ec2_example.rb'
10
+ )
11
+ )
12
+ )
@@ -0,0 +1,21 @@
1
+ SparkleFormation.build do
2
+
3
+ parameters do
4
+ key_name do
5
+ description 'Name of an existing EC2 KeyPair to enable SSH access to the instance'
6
+ type 'String'
7
+ end
8
+ end
9
+
10
+ mappings.region_map do
11
+ _set('us-east-1', :ami => 'ami-7f418316')
12
+ _set('us-east-1', :ami => 'ami-7f418316')
13
+ _set('us-west-1', :ami => 'ami-951945d0')
14
+ _set('us-west-2', :ami => 'ami-16fd7026')
15
+ _set('eu-west-1', :ami => 'ami-24506250')
16
+ _set('sa-east-1', :ami => 'ami-3e3be423')
17
+ _set('ap-southeast-1', :ami => 'ami-74dda626')
18
+ _set('ap-northeast-1', :ami => 'ami-dcfa4edd')
19
+ end
20
+
21
+ end
@@ -0,0 +1,41 @@
1
+ SparkleFormation.new('ec2_example').load(:ami).overrides do
2
+ description "AWS CloudFormation Sample Template EC2InstanceSample: Create an Amazon EC2 instance running the Amazon Linux AMI. The AMI is chosen based on the region in which the stack is run. This example uses the default security group, so to SSH to the new instance using the KeyPair you enter, you will need to have port 22 open in your default security group. **WARNING** This template an Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template."
3
+
4
+ resources do
5
+ my_instance do
6
+ type 'AWS::EC2::Instance'
7
+ properties do
8
+ key_name _cf_ref(:key_name)
9
+ image_id _cf_map(:region_map, 'AWS::Region', :ami)
10
+ user_data _cf_base64('80')
11
+ end
12
+ end
13
+ end
14
+
15
+ outputs do
16
+ instance_id do
17
+ description 'InstanceId of the newly created EC2 instance'
18
+ value _cf_ref(:my_instance)
19
+ end
20
+ az do
21
+ description 'Availability Zone of the newly created EC2 instance'
22
+ value _cf_attr(:my_instance, :availability_zone)
23
+ end
24
+ public_ip do
25
+ description 'Public IP address of the newly created EC2 instance'
26
+ value _cf_attr(:my_instance, :public_ip)
27
+ end
28
+ private_ip do
29
+ description 'Private IP address of the newly created EC2 instance'
30
+ value _cf_attr(:my_instance, :private_ip)
31
+ end
32
+ public_dns do
33
+ description 'Public DNSName of the newly created EC2 instance'
34
+ value _cf_attr(:my_instance, :public_dns_name)
35
+ end
36
+ private_dns do
37
+ description 'Private DNSName of the newly created EC2 instance'
38
+ value _cf_attr(:my_instance, :private_dns_name)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,12 @@
1
+ require 'sparkle_formation'
2
+ require 'pp'
3
+ require 'json'
4
+
5
+ puts JSON.pretty_generate(
6
+ SparkleFormation.compile(
7
+ File.join(
8
+ File.dirname(__FILE__),
9
+ 'cloudformation/ec2_example.rb'
10
+ )
11
+ )
12
+ )
@@ -0,0 +1,84 @@
1
+ require 'attribute_struct'
2
+
3
+ module SparkleAttribute
4
+
5
+ def _cf_join(*args)
6
+ options = args.detect{|i| i.is_a?(Hash) && i[:options]} || {:options => {}}
7
+ args.delete(options)
8
+ unless(args.size == 1)
9
+ args = [args]
10
+ end
11
+ {'Fn::Join' => [options[:options][:delimiter] || '', *args]}
12
+ end
13
+
14
+ def _cf_ref(thing)
15
+ thing = _process_key(thing, :force) if thing.is_a?(Symbol)
16
+ {'Ref' => thing}
17
+ end
18
+ alias_method :_ref, :_cf_ref
19
+
20
+ def _cf_map(thing, key, *suffix)
21
+ suffix = suffix.map do |item|
22
+ if(item.is_a?(Symbol))
23
+ _process_key(item, :force)
24
+ else
25
+ item
26
+ end
27
+ end
28
+ thing = _process_key(thing, :force) if thing.is_a?(Symbol)
29
+ key = _process_key(key, :force) if key.is_a?(Symbol)
30
+ {'Fn::FindInMap' => [_process_key(thing), {'Ref' => _process_key(key)}, *suffix]}
31
+ end
32
+ alias_method :_cf_find_in_map, :_cf_map
33
+
34
+ def _cf_attr(*args)
35
+ args = args.map do |thing|
36
+ if(thing.is_a?(Symbol))
37
+ _process_key(thing, :force)
38
+ else
39
+ thing
40
+ end
41
+
42
+ end
43
+ {'Fn::GetAtt' => args}
44
+ end
45
+ alias_method :_cf_get_att, :_cf_attr
46
+
47
+ def _cf_base64(arg)
48
+ {'Fn::Base64' => arg}
49
+ end
50
+
51
+ def _cf_get_azs(region=nil)
52
+ region = case region
53
+ when Symbol
54
+ _cf_ref(region)
55
+ when NilClass
56
+ ''
57
+ else
58
+ region
59
+ end
60
+ {'Fn::GetAZs' => region}
61
+ end
62
+
63
+ def _cf_select(index, item)
64
+ item = _cf_ref(item) if item.is_a?(Symbol)
65
+ {'Fn::Select', [index.to_i.to_s, item]}
66
+ end
67
+
68
+ def rhel?
69
+ !!@platform[:rhel]
70
+ end
71
+
72
+ def debian?
73
+ !!@platform[:debian]
74
+ end
75
+
76
+ def _platform=(plat)
77
+ @platform || __hashish
78
+ @platform.clear
79
+ @platform[plat.to_sym] = true
80
+ end
81
+
82
+ end
83
+
84
+ AttributeStruct.send(:include, SparkleAttribute)
@@ -0,0 +1,137 @@
1
+ require 'attribute_struct'
2
+ require 'sparkle_formation/sparkle_attribute'
3
+ require 'sparkle_formation/utils'
4
+
5
+ AttributeStruct.camel_keys = true
6
+
7
+ class SparkleFormation
8
+
9
+ include SparkleFormation::Utils::AnimalStrings
10
+
11
+ class << self
12
+
13
+ attr_reader :dynamics
14
+ attr_reader :components_path
15
+ attr_reader :dynamics_path
16
+
17
+ def custom_paths
18
+ @_paths ||= {}
19
+ @_paths
20
+ end
21
+
22
+ def components_path=(path)
23
+ custom_paths[:sparkle_path] = path
24
+ end
25
+
26
+ def dynamics_path=(path)
27
+ custom_paths[:dynamics_directory] = path
28
+ end
29
+
30
+ def compile(path)
31
+ formation = self.instance_eval(IO.read(path), path, 1)
32
+ formation.compile._dump
33
+ end
34
+
35
+ def build(&block)
36
+ struct = AttributeStruct.new
37
+ struct.instance_exec(&block)
38
+ struct
39
+ end
40
+
41
+ def load_component(path)
42
+ self.instance_eval(IO.read(path), path, 1)
43
+ end
44
+
45
+ def load_dynamics!(directory)
46
+ @loaded_dynamics ||= []
47
+ Dir.glob(File.join(directory, '*.rb')).each do |dyn|
48
+ dyn = File.expand_path(dyn)
49
+ next if @loaded_dynamics.include?(dyn)
50
+ self.instance_eval(IO.read(dyn), dyn, 1)
51
+ @loaded_dynamics << dyn
52
+ end
53
+ @loaded_dynamics.uniq!
54
+ true
55
+ end
56
+
57
+ def dynamic(name, &block)
58
+ @dynamics ||= Mash.new
59
+ @dynamics[name] = block
60
+ end
61
+
62
+ def insert(dynamic_name, struct, *args)
63
+ if(@dynamics && @dynamics[dynamic_name])
64
+ struct.instance_exec(*args, &@dynamics[dynamic_name])
65
+ struct
66
+ else
67
+ raise "Failed to locate requested dynamic block for insertion: #{dynamic_name} (valid: #{@dynamics.keys.sort.join(', ')})"
68
+ end
69
+ end
70
+
71
+ def from_hash(hash)
72
+ struct = AttributeStruct.new
73
+ struct._camel_keys_set(:auto_discovery)
74
+ struct._load(hash)
75
+ struct._camel_keys_set(nil)
76
+ struct
77
+ end
78
+ end
79
+
80
+ attr_reader :name
81
+ attr_reader :sparkle_path
82
+ attr_reader :components
83
+ attr_reader :load_order
84
+
85
+ def initialize(name, options={}, &block)
86
+ @name = name
87
+ @sparkle_path = options[:sparkle_path] ||
88
+ self.class.custom_paths[:sparkle_path] ||
89
+ File.join(Dir.pwd, 'cloudformation/components')
90
+ @dynamics_directory = options[:dynamics_directory] ||
91
+ self.class.custom_paths[:dynamics_directory] ||
92
+ File.join(File.dirname(@sparkle_path), 'dynamics')
93
+ self.class.load_dynamics!(@dynamics_directory)
94
+ @components = AttributeStruct.hashish.new
95
+ @load_order = []
96
+ if(block)
97
+ load_block(block)
98
+ end
99
+ end
100
+
101
+ def load_block(block)
102
+ @components[:__base__] = self.class.build(&block)
103
+ @load_order << :__base__
104
+ end
105
+
106
+ def load(*args)
107
+ args.each do |thing|
108
+ if(thing.is_a?(Symbol))
109
+ path = File.join(sparkle_path, "#{thing}.rb")
110
+ else
111
+ path = thing
112
+ end
113
+ key = File.basename(path).sub('.rb', '')
114
+ components[key] = self.class.load_component(path)
115
+ @load_order << key
116
+ end
117
+ self
118
+ end
119
+
120
+ def overrides(&block)
121
+ @overrides = self.class.build(&block)
122
+ self
123
+ end
124
+
125
+ # Returns compiled Mash instance
126
+ def compile
127
+ compiled = AttributeStruct.new
128
+ @load_order.each do |key|
129
+ compiled._merge!(components[key])
130
+ end
131
+ if(@overrides)
132
+ compiled._merge!(@overrides)
133
+ end
134
+ compiled
135
+ end
136
+
137
+ end
@@ -0,0 +1,17 @@
1
+ class SparkleFormation
2
+ module Utils
3
+
4
+ module AnimalStrings
5
+
6
+ def camel(string)
7
+ string.to_s.split('_').map{|k| "#{k.slice(0,1).upcase}#{k.slice(1,k.length)}"}.join
8
+ end
9
+
10
+ def snake(string)
11
+ string.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase.to_sym
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ class SparkleFormation
2
+ class Version < Gem::Version
3
+ end
4
+ VERSION = Version.new('0.1.0')
5
+ end
@@ -0,0 +1,2 @@
1
+ require 'sparkle_formation/version'
2
+ require 'sparkle_formation/sparkle_formation'
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__)) + '/lib/'
2
+ require 'sparkle_formation/version'
3
+ Gem::Specification.new do |s|
4
+ s.name = 'sparkle_formation'
5
+ s.version = SparkleFormation::VERSION.version
6
+ s.summary = 'Cloud Formation builder'
7
+ s.author = 'Chris Roberts'
8
+ s.email = 'chrisroberts.code@gmail.com'
9
+ s.homepage = 'http://github.com/heavywater/sparkle_formation'
10
+ s.description = 'Cloud Formation builder'
11
+ s.require_path = 'lib'
12
+ s.add_dependency 'attribute_struct', '~> 0.1.6'
13
+ s.files = Dir['**/*']
14
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sparkle_formation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Roberts
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-10-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: attribute_struct
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.1.6
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.1.6
30
+ description: Cloud Formation builder
31
+ email: chrisroberts.code@gmail.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/sparkle_formation/sparkle_attribute.rb
37
+ - lib/sparkle_formation/version.rb
38
+ - lib/sparkle_formation/sparkle_formation.rb
39
+ - lib/sparkle_formation/utils.rb
40
+ - lib/sparkle_formation.rb
41
+ - examples/allinone/parse.rb
42
+ - examples/allinone/cloudformation/ec2_example.rb
43
+ - examples/ami_component/parse.rb
44
+ - examples/ami_component/cloudformation/components/ami.rb
45
+ - examples/ami_component/cloudformation/ec2_example.rb
46
+ - Gemfile
47
+ - sparkle_formation.gemspec
48
+ - README.md
49
+ - CHANGELOG.md
50
+ - Gemfile.lock
51
+ homepage: http://github.com/heavywater/sparkle_formation
52
+ licenses: []
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 1.8.24
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Cloud Formation builder
75
+ test_files: []
76
+ has_rdoc: