sparkle_formation 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cba70b56deef5fd41dfd28df337ac9f1af137119
4
+ data.tar.gz: 08122ae8c40990d331d8be3bbff0b58293162f18
5
+ SHA512:
6
+ metadata.gz: 5fdcff8822399fa54d5274642e865198514607ef84c8eacb70bbe6ab06e86da2fb9fdd97c4092e5abfd2c3a991a4c1bf2c61c8b7f57c31b59c89276ef8604411
7
+ data.tar.gz: 027bae7862955e2e0d3ff4aac121daa4a4f67a1937850ce62d90a3d3528c6470b3f8f51009ae58989af726c7c06e11400a38826b9a46cbb7e6d220e732bc8a0c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## v0.2.2
2
+ * Lots of translation updates (AWS -> RS "hot")
3
+ * User Documentation!
4
+
1
5
  ## v0.2.0
2
6
  * Add Registry helper into Utils
3
7
  * Add script for collecting cfn and hot resources
data/Gemfile.lock CHANGED
@@ -1,16 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sparkle_formation (0.2.0)
4
+ sparkle_formation (0.2.2)
5
5
  attribute_struct (~> 0.2.2)
6
6
  multi_json
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- attribute_struct (0.2.2)
12
- hashie (>= 2.0.0)
13
- hashie (2.1.1)
11
+ attribute_struct (0.2.8)
14
12
  multi_json (1.10.1)
15
13
 
16
14
  PLATFORMS
data/docs/README.md ADDED
@@ -0,0 +1,177 @@
1
+ ## Overview
2
+ SparkleFormation is a Ruby DSL for programatically composing
3
+ [AWS Cloudformation][cloudformation], [OpenStack Heat][heat]
4
+ provisioning templates for the purpose of interacting with cloud
5
+ infrastructure orchestration APIs.
6
+
7
+ SparkleFormation templates describe the creation and configuration of
8
+ collections of cloud resources (a stack) as code, allowing you to
9
+ provision stacks in a predictable and repeatable manner. Stacks can be
10
+ managed as single unit, allowing you to create, modify, or delete
11
+ collections of resources via a single API call.
12
+
13
+ SparkleFormation composes templates in the native cloud orchestration
14
+ formats for AWS, Rackspace, Google Compute, and similar services.
15
+
16
+ ## Table of Contents
17
+
18
+ - [Getting Started](#getting-started)
19
+ - [What It Looks Like](#what-it-looks-like)
20
+ - [Building Blocks](building-blocks.md)
21
+ - [Components](building-blocks.md#components)
22
+ - [Dynamics](building-blocks.md#dynamics)
23
+ - [Registries](building-blocks.md#registries)
24
+ - [Template Anatomy](anatomy.md)
25
+ - [Parameters](anatomy.md#parameters)
26
+ - [Resources](anatomy.md#resources)
27
+ - [Mappings](anatomy.md#mappings)
28
+ - [Outputs](anatomy.md#outputs)
29
+ - [Intrinsic Functions](functions.md)
30
+ - [Ref](functions.md#ref)
31
+ - [Attr](functions.md#attr)
32
+ - [Join](functions.md#join)
33
+ - [Universal Properties](properties.md)
34
+ - [Tags](properties.md#tags)
35
+
36
+ ## Getting Started
37
+ ### Gemfile
38
+ SparkleFormation is in active development. To access all the features
39
+ detailed in the documentation (using the knife plugin CLI), you should
40
+ install the plugin and supporting libraries from git:
41
+
42
+ ```ruby
43
+ gem 'fog', :git => 'https://github.com/chrisroberts/fog.git', :ref => 'feature/orchestration'
44
+ gem 'fog-core', :git => 'https://github.com/chrisroberts/fog-core.git', :ref => 'feature/orchestration'
45
+ gem 'knife-cloudformation', :git => 'https://github.com/heavywater/knife-cloudformation.git', :ref => 'feature/fog-model'
46
+ ```
47
+
48
+ The Knife Cloudformation gem is only needed for stack provisioning via
49
+ knife. You could also upload SparkleFormation generated templates to AWS via the WebUI.
50
+
51
+ ### Knife Config
52
+ To use Knife for provisioning, you will need to add the following to
53
+ your `knife.rb` file:
54
+
55
+ ```ruby
56
+ knife[:aws_access_key_id] = ENV['AWS_ACCESS_KEY_ID']
57
+ knife[:aws_secret_access_key] = ENV['AWS_SECRET_ACCESS_KEY']
58
+
59
+ [:cloudformation, :options].inject(knife){ |m,k| m[k] ||= Mash.new }
60
+ knife[:cloudformation][:options][:disable_rollback] = ENV['AWS_CFN_DISABLE_ROLLBACK'].to_s.downcase == 'true'
61
+ knife[:cloudformation][:options][:capabilities] = ['CAPABILITY_IAM']
62
+ knife[:cloudformation][:processing] = true
63
+ knife[:cloudformation][:credentials] = {
64
+ :aws_access_key_id => knife[:aws_access_key_id],
65
+ :aws_secret_access_key => knife[:aws_secret_access_key]
66
+ }
67
+ ```
68
+
69
+ | Attribute | Function |
70
+ |--------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
71
+ | `[:cloudformation][:options][:disable_rollback]` | Disables rollback if stack is unsuccessful. Useful for debugging. |
72
+ | `[:cloudformation][:credentials]` | Credentials for a user that is allowed to create stacks. |
73
+ | `[:cloudformation][:options][:capabilities]` | Enables IAM creation (AWS only). Options are `nil` or `['CAPABILITY_IAM']` |
74
+ | `[:cloudformation][:processing]` | Enables processing SparkleFormation templates (otherwise knife cloudformation will expect a JSON CFN template. |
75
+
76
+ ## What it Looks Like
77
+ Below is a basic SparkleFormation template which would provision an
78
+ elastic load balancer forwarding port 80 to an autoscaling group of
79
+ ec2 instances.
80
+
81
+ ```ruby
82
+ SparkleFormation.new('website') do
83
+
84
+ set!('AWSTemplateFormatVersion', '2010-09-09')
85
+
86
+ description 'Supercool Website'
87
+
88
+ resources.cfn_user do
89
+ type 'AWS::IAM::User'
90
+ properties.path '/'
91
+ properties.policies _array(
92
+ -> {
93
+ policy_name 'cfn_access'
94
+ policy_document.statement _array(
95
+ -> {
96
+ effect 'Allow'
97
+ action 'cloudformation:DescribeStackResource'
98
+ resource '*'
99
+ }
100
+ )
101
+ }
102
+ )
103
+ end
104
+
105
+ resources.cfn_keys do
106
+ type 'AWS::IAM::AccessKey'
107
+ properties.user_name ref!(:cfn_user)
108
+ end
109
+
110
+ parameters.web_nodes do
111
+ type 'Number'
112
+ description 'Number of web nodes for ASG.'
113
+ default 2
114
+ end
115
+
116
+ resources.website_autoscale do
117
+ type 'AWS::AutoScaling::AutoScalingGroup'
118
+ properties do
119
+ availability_zones({'Fn::GetAZs' => ''})
120
+ launch_configuration_name ref!(:website_launch_config)
121
+ min_size ref!(:web_nodes)
122
+ max_size ref!(:web_nodes)
123
+ end
124
+ end
125
+
126
+ resources.website_launch_config do
127
+ type 'AWS::AutoScaling::LaunchConfiguration'
128
+ properties do
129
+ image_id 'ami-123456'
130
+ instance_type 'm3.medium'
131
+ end
132
+ end
133
+
134
+ resources.website_elb do
135
+ type 'AWS::ElasticLoadBalancing::LoadBalancer'
136
+ properties do
137
+ availability_zones._set('Fn::GetAZs', '')
138
+ listeners _array(
139
+ -> {
140
+ load_balancer_port '80'
141
+ protocol 'HTTP'
142
+ instance_port '80'
143
+ instance_protocol 'HTTP'
144
+ }
145
+ )
146
+ health_check do
147
+ target 'HTTP:80/'
148
+ healthy_threshold '3'
149
+ unhealthy_threshold '3'
150
+ interval '5'
151
+ timeout '15'
152
+ end
153
+ end
154
+ end
155
+ end
156
+ ```
157
+
158
+ This template is 74 lines long (with generous spacing for
159
+ readability). The [json template this
160
+ renders](examples/template_json/website.json) is 88 lines, without
161
+ spacing). This can be improved, though. SparkleFormation allows you to
162
+ create resusable files such that the above template can become :
163
+
164
+ ```ruby
165
+ SparkleFormation.new(:website).load(:base).overrides do
166
+
167
+ description 'Supercool Website'
168
+
169
+ dynamic!(:autoscale, 'website', :nodes => 2)
170
+ dynamic!(:launch_config, 'website', :image_id => 'ami-123456', :instance_type => 'm3.medium')
171
+ dynamic!(:elb, 'website')
172
+
173
+ end
174
+ ```
175
+
176
+ [cloudformation]: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-guide.html
177
+ [heat]: http://docs.openstack.org/developer/heat/template_guide/index.html
data/docs/anatomy.md ADDED
@@ -0,0 +1,203 @@
1
+ ## Template Anatomy
2
+
3
+ ### Parameters
4
+ Parameters are prompts for stack specific values. A default may be
5
+ specified, but is not required. Every parameter must have a value at runtime.
6
+
7
+ In the Getting Started example we had one parameter, `web_nodes` which
8
+ set the min and max for the autoscaling group:
9
+
10
+ ```ruby
11
+ parameters.web_nodes do
12
+ type 'Number'
13
+ description 'Number of web nodes for ASG.'
14
+ default 2
15
+ end
16
+ ```
17
+
18
+ Every parameter must have a type and a description. Available types are `String`,
19
+ `Number` (an integer), and `CommaDelimitedList` (an array of
20
+ strings, as-in: `['alpha', 'beta', '1', 2']`). The descriptions is a
21
+ string describing the resource.
22
+
23
+ Parameters support optional default values, declared as
24
+ above. An array of accepted values may be set, as well:
25
+
26
+ ```ruby
27
+ parameters.web_nodes do
28
+ type 'Number'
29
+ description 'Number of web nodes for ASG.'
30
+ default 2
31
+ allowed_values [1, 2, 3, 5]
32
+ end
33
+ ```
34
+
35
+ ### Resources
36
+ Resources are the infrastructure resources that are provisioned with
37
+ the stack. Every resource must have a type that corresponds to a
38
+ supported cloud resource. Resources typically have a properties hash
39
+ that configures the resource. Some resources also have metadata. For
40
+ the complete list of required and optional options, see the
41
+ individual resource documentation.
42
+
43
+ Resource availability is not consistent across
44
+ providers. SparkleFormation's resources support is based on AWS, and
45
+ not all resources will be available on other platforms. See the
46
+ [resource reference](resource-reference.md) table for more information.
47
+
48
+ The prior example included the following resources:
49
+ - cfn_user: The IAM user for the stack, which will be used to
50
+ provision stack resources.
51
+
52
+ ```ruby
53
+ resources.cfn_user do
54
+ type 'AWS::IAM::User'
55
+ properties.path '/'
56
+ properties.policies _array(
57
+ -> {
58
+ policy_name 'cfn_access'
59
+ policy_document.statement _array(
60
+ -> {
61
+ effect 'Allow'
62
+ action 'cloudformation:DescribeStackResource'
63
+ resource '*'
64
+ }
65
+ )
66
+ }
67
+ )
68
+ end
69
+ ```
70
+
71
+ - cfn_key: The IAM keys for the stack IAM user.
72
+
73
+ ```ruby
74
+ resources.cfn_keys do
75
+ type 'AWS::IAM::AccessKey'
76
+ properties.user_name ref!(:cfn_user)
77
+ end
78
+ ```
79
+
80
+ - website_asg: The autoscaling group containing website nodes. The
81
+ size of the autoscaling group is set to the value of the web_nodes
82
+ parameter.
83
+
84
+ ```ruby
85
+ resources.website_autoscale do
86
+ type 'AWS::AutoScaling::AutoScalingGroup'
87
+ properties do
88
+ availability_zones({'Fn::GetAZs' => ''})
89
+ launch_configuration_name ref!(:website_launch_config)
90
+ min_size ref!(:web_nodes)
91
+ max_size ref!(:web_nodes)
92
+ end
93
+ end
94
+ ```
95
+
96
+ - website_launch_configuration: The launch configuration for
97
+ website_asg nodes. The AMI image ID and instance type (size) are
98
+ required.
99
+
100
+ ```ruby
101
+ resources.website_launch_config do
102
+ type 'AWS::AutoScaling::LaunchConfiguration'
103
+ properties do
104
+ image_id 'ami-123456'
105
+ instance_type 'm3.medium'
106
+ end
107
+ end
108
+ ```
109
+
110
+ - website_elb: The elastic load balancer for the website. The
111
+ listeners array configures port forwarding. The health check
112
+ configures the load balancer health check target and thresholds.
113
+
114
+ ```ruby
115
+ resources.website_elb do
116
+ type 'AWS::ElasticLoadBalancing::LoadBalancer'
117
+ properties do
118
+ availability_zones._set('Fn::GetAZs', '')
119
+ listeners _array(
120
+ -> {
121
+ load_balancer_port '80'
122
+ protocol 'HTTP'
123
+ instance_port '80'
124
+ instance_protocol 'HTTP'
125
+ }
126
+ )
127
+ health_check do
128
+ target 'HTTP:80/'
129
+ healthy_threshold '3'
130
+ unhealthy_threshold '3'
131
+ interval '5'
132
+ timeout '15'
133
+ end
134
+ end
135
+ end
136
+ ```
137
+
138
+ ### Mappings
139
+ Mappings allow you to create key/value pairs which can be referenced
140
+ at runtime. This is useful for things like an image id that differs
141
+ by region or environment.
142
+
143
+ Mappings for the 2014.09 Amazon Linux PV Instance Store 64-bit AMIs
144
+ for each US region:
145
+
146
+ ```ruby
147
+ mappings.region_map do
148
+ set!('us-east-1', :ami => 'ami-8e852ce6')
149
+ set!('us-west-1', :ami => 'ami-03a8a146')
150
+ set!('us-west-2', :ami => 'ami-f786c6c7')
151
+ end
152
+ ```
153
+
154
+ These can be referenced, in turn, with the following:
155
+
156
+ ```ruby
157
+ map!(:region_map, ref!('AWS::Region'), :ami)
158
+ ```
159
+
160
+ 'AWS::Region' is a psuedo parameter. We could also perform a lookup
161
+ based on a parameter we provide, e.g. an instance size based on the environment:
162
+
163
+ ```ruby
164
+ parameters.environment do
165
+ type 'String'
166
+ allowed_values ['development', 'staging', 'production']
167
+ end
168
+
169
+ mappings.instance_size do
170
+ set!('development', :instance => 'm3.small')
171
+ set!('staging', :instance => 'm3.medium')
172
+ set!('production', :instance => 'm3.large')
173
+ end
174
+
175
+ resources.website_launch_config do
176
+ type 'AWS::AutoScaling::LaunchConfiguration'
177
+ properties do
178
+ image_id map!(:region_map, 'AWS::Region', :ami)
179
+ instance_type map!(:instance_size, ref!(:environment), :instance)
180
+ end
181
+ end
182
+ ```
183
+
184
+ ### Outputs
185
+ Outputs provide metadata for the stack, as key/value pairs within an
186
+ outputs block. Note that this block lives outside the resource
187
+ blocks. This will retrieve the DNSName attribute for our load
188
+ balancer, and provide it as a value for an 'Elb Dns' output:
189
+
190
+ ```ruby
191
+ outputs do
192
+ elb_dns do
193
+ value attr!(:website_elb, 'DNSName')
194
+ description "Website ELB DNS name"
195
+ end
196
+ end
197
+ ```
198
+
199
+ Outputs are not simply informational. You can interact with them
200
+ during [provisioning](provisioning.md#knife-cloudformation) using the [knife-cloudformation
201
+ plugin](https://rubygems.org/gems/knife-cloudformation).
202
+
203
+
@@ -0,0 +1,275 @@
1
+ ## SparkleFormation Building Blocks
2
+
3
+ Using SparkleFormation for the above template has already saved us
4
+ many keystrokes, but what about reusing SparkleFormation code between
5
+ similar stacks? This is where SparkleFormation concepts like
6
+ components, dynamics, and registries come into play.
7
+
8
+ ### Components
9
+
10
+ Components are static configuration which can be reused between many
11
+ stack templates. In our example case we have decided that all our
12
+ stacks will need to make use of IAM credentials, so we will create
13
+ a component which allows us to inserts the two IAM resources into any
14
+ template in a resuable fashion. The component, which we will call
15
+ 'base' and put in a file called 'base.rb,' would look like this:
16
+
17
+ ```ruby
18
+ SparkleFormation.build do
19
+ set!('AWSTemplateFormatVersion', '2010-09-09')
20
+
21
+ resources.cfn_user do
22
+ type 'AWS::IAM::User'
23
+ properties.path '/'
24
+ properties.policies _array(
25
+ -> {
26
+ policy_name 'cfn_access'
27
+ policy_document.statement _array(
28
+ -> {
29
+ effect 'Allow'
30
+ action 'cloudformation:DescribeStackResource'
31
+ resource '*'
32
+ }
33
+ )
34
+ }
35
+ )
36
+ end
37
+
38
+ resources.cfn_keys do
39
+ type 'AWS::IAM::AccessKey'
40
+ properties.user_name ref!(:cfn_user)
41
+ end
42
+ end
43
+ ```
44
+
45
+ After moving these resources out of the initial template and into a
46
+ component, we will update the template so that the base component is
47
+ loaded on the first line, and the resources it contains are no longer
48
+ present in the template itself:
49
+
50
+ ```ruby
51
+ SparkleFormation.new(:website).load(:base).overrides do
52
+
53
+ description 'Supercool Website'
54
+
55
+ parameters.web_nodes do
56
+ type 'Number'
57
+ description 'Number of web nodes for ASG.'
58
+ default '2'
59
+ end
60
+
61
+ resources.website_autoscale do
62
+ type 'AWS::AutoScaling::AutoScalingGroup'
63
+ properties do
64
+ availability_zones({'Fn::GetAZs' => ''})
65
+ launch_configuration_name ref!(:website_launch_config)
66
+ min_size ref!(:web_nodes)
67
+ max_size ref!(:web_nodes)
68
+ end
69
+ end
70
+
71
+ resources.website_launch_config do
72
+ type 'AWS::AutoScaling::LaunchConfiguration'
73
+ properties do
74
+ image_id 'ami-123456'
75
+ instance_type 'm3.medium'
76
+ end
77
+ end
78
+
79
+ resources.website_elb do
80
+ type 'AWS::ElasticLoadBalancing::LoadBalancer'
81
+ properties do
82
+ availability_zones._set('Fn::GetAZs', '')
83
+ listeners _array(
84
+ -> {
85
+ load_balancer_port '80'
86
+ protocol 'HTTP'
87
+ instance_port '80'
88
+ instance_protocol 'HTTP'
89
+ }
90
+ )
91
+ health_check do
92
+ target 'HTTP:80/'
93
+ healthy_threshold '3'
94
+ unhealthy_threshold '3'
95
+ interval '5'
96
+ timeout '15'
97
+ end
98
+ end
99
+ end
100
+ end
101
+ ```
102
+
103
+ ### Dynamics
104
+
105
+ Like components, dynamics are another SparkleFormation feature which
106
+ enables code reuse between stack templates. Where components are
107
+ static, dynamics are useful for creating unique resources via
108
+ the passing of arguments.
109
+
110
+ In our example scenario we have decided that we want to use elastic
111
+ load balancer resources in many of our stack templates, we want to
112
+ create a dynamic which makes inserting ELB resources much easier than
113
+ copying the full resource configuration between templates.
114
+
115
+ The resulting implementation would look something like this:
116
+
117
+ ```ruby
118
+ SparkleFormation.dynamic(:elb) do |_name, _config={}|
119
+ resources("#{_name}_elb".to_sym) do
120
+ type 'AWS::ElasticLoadBalancing::LoadBalancer'
121
+ properties do
122
+ availability_zones._set('Fn::GetAZs', '')
123
+ listeners _array(
124
+ -> {
125
+ load_balancer_port _config[:load_balancer_port] || '80'
126
+ protocol _config[:protocol] || 'HTTP'
127
+ instance_port _config[:instance_port] || '80'
128
+ instance_protocol _config[:instance_protocol] || 'HTTP'
129
+ }
130
+ )
131
+ health_check do
132
+ target _config[:target] || 'HTTP:80/'
133
+ healthy_threshold _config[:healthy_threshold] || '3'
134
+ unhealthy_threshold _config[:unhealthy_threshold] || '3'
135
+ interval _config[:interval] || '5'
136
+ timeout _config[:timeout] || '15'
137
+ end
138
+ end
139
+ end
140
+ end
141
+ ```
142
+
143
+ This dynamic accepts two arguments: `_name` (a string, required) and `_config`
144
+ (a hash, optional). The dynamic will use the values passed in these
145
+ arguments to generate a new ELB resource, and override the default ELB
146
+ properties wherever a corresponding key/value pair is provided in the
147
+ `_config` hash.
148
+
149
+ Once updated to make use of the new ELB dynamic, our template looks
150
+ like this:
151
+
152
+ ```ruby
153
+ SparkleFormation.new(:website).load(:base).overrides do
154
+
155
+ description 'Supercool Website'
156
+
157
+ parameters.web_nodes do
158
+ type 'Number'
159
+ description 'Number of web nodes for ASG.'
160
+ default '2'
161
+ end
162
+
163
+ resources.website_autoscale do
164
+ type 'AWS::AutoScaling::AutoScalingGroup'
165
+ properties do
166
+ availability_zones({'Fn::GetAZs' => ''})
167
+ launch_configuration_name ref!(:website_launch_config)
168
+ min_size ref!(:web_nodes)
169
+ max_size ref!(:web_nodes)
170
+ end
171
+ end
172
+
173
+ resources.website_launch_config do
174
+ type 'AWS::AutoScaling::LaunchConfiguration'
175
+ properties do
176
+ image_id 'ami-123456'
177
+ instance_type 'm3.medium'
178
+ end
179
+ end
180
+
181
+ dynamic!(:elb, 'website')
182
+ end
183
+ ```
184
+
185
+ If we wanted to override the default configuration for the ELB,
186
+ e.g. to configure the ELB to listen on and communicate with back-end
187
+ node on port 8080 instead of 80, we can specify these override values
188
+ in the configuration passed to the ELB dynamic:
189
+
190
+ ```ruby
191
+ dynamic!(:elb, 'website', :load_balancer_port => 8080, :instance_port => 8080)
192
+ ```
193
+
194
+ We're passing three arguments here:
195
+
196
+ 1. `:elb` is the name of the dynamic to insert, as a ruby symbol
197
+ 2. A name string (`'website'`), which is passed to `_name` in the
198
+ dynamic. This is prepended to the resource name in the dynamic,
199
+ resulting in a unique resource name.
200
+ 3. The ELB ports to configure as key/value pairs. These are passed into the dynamic as
201
+ the `_config` hash.
202
+
203
+ ### Registries
204
+
205
+ Similar to dynamics, registries are reusable resource configuration
206
+ code which can be reused inside different resource definitions.
207
+
208
+ Registries are useful for defining properties that may be reused
209
+ between resources of different types. For example, the
210
+ LaunchConfiguration and Instance resource types make use of metadata
211
+ properties which inform both resource types how to bootstrap one or
212
+ more instances.
213
+
214
+ In our example scenario we would like our new instances to run
215
+ 'sudo apt-get update && sudo apt-get upgrade -y' at first boot,
216
+ regardless of whether or not the instances are members of an
217
+ autoscaling group.
218
+
219
+ Because these resources are of different types, placing the metadata
220
+ required for this task directly inside a dynamic isn't going to work
221
+ quite the way we need. Instead we can put this inside a registry which
222
+ can be inserted into the resources defined in one or more dynamics:
223
+
224
+ ```ruby
225
+ SparkleFormation::Registry.register(:apt_get_update) do
226
+ metadata('AWS::CloudFormation::Init') do
227
+ _camel_keys_set(:auto_disable) do
228
+ commands('01_apt_get_update') do
229
+ command 'sudo apt-get update'
230
+ end
231
+ commands('02_apt_get_upgrade') do
232
+ command 'sudo apt-get upgrade -y'
233
+ end
234
+ end
235
+ end
236
+ ```
237
+
238
+ Now we can insert this registry entry into our existing template, to
239
+ ensure that apt is updated upon provisioning:
240
+
241
+ ```ruby
242
+ SparkleFormation.new(:website).load(:base).overrides do
243
+
244
+ description 'Supercool Website'
245
+
246
+ parameters.web_nodes do
247
+ type 'Number'
248
+ description 'Number of web nodes for ASG.'
249
+ default 2
250
+ end
251
+
252
+ resources.website_autoscale do
253
+ type 'AWS::AutoScaling::AutoScalingGroup'
254
+ properties do
255
+ availability_zones({'Fn::GetAZs' => ''})
256
+ launch_configuration_name ref!(:website_launch_config)
257
+ min_size ref!(:web_nodes)
258
+ max_size ref!(:web_nodes)
259
+ end
260
+ end
261
+
262
+ resources.website_launch_config do
263
+ type 'AWS::AutoScaling::LaunchConfiguration'
264
+ registry!(:apt_get_update, 'website')
265
+ properties do
266
+ image_id 'ami-123456'
267
+ instance_type 'm3.medium'
268
+ end
269
+ end
270
+
271
+ dynamic!(:elb, 'website')
272
+
273
+ registry!(:apt_get_update, 'website')
274
+ end
275
+ ```