cfer 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,170 @@
1
+ module Cfer::Core
2
+
3
+ # Defines the structure of a CloudFormation stack
4
+ class Stack < Cfer::Block
5
+ include Cfer::Core
6
+ include Cfer::Cfn
7
+
8
+ attr_reader :parameters
9
+ attr_reader :options
10
+ attr_reader :git
11
+
12
+ def converge!
13
+ if @options[:client]
14
+ @options[:client].converge self
15
+ end
16
+ end
17
+
18
+ def tail!(&block)
19
+ if @options[:client]
20
+ @options[:client].tail self, &block
21
+ end
22
+ end
23
+
24
+ def resolve(val)
25
+ @options[:client] ? @options[:client].resolve(val) : val
26
+ end
27
+
28
+ def initialize(options = {})
29
+ self[:AWSTemplateFormatVersion] = '2010-09-09'
30
+ self[:Description] = ''
31
+
32
+ @options = options
33
+ @git = Rugged::Repository.discover('.')
34
+
35
+ self[:Parameters] = {}
36
+ self[:Mappings] = {}
37
+ self[:Conditions] = {}
38
+ self[:Resources] = {}
39
+ self[:Outputs] = {}
40
+
41
+ @parameters = HashWithIndifferentAccess.new
42
+
43
+ if options[:parameters]
44
+ options[:parameters].each do |key, val|
45
+ @parameters[key] = resolve(val)
46
+ end
47
+ end
48
+ end
49
+
50
+ def pre_block
51
+ end
52
+
53
+ # Sets the description for this CloudFormation stack
54
+ def description(desc)
55
+ self[:Description] = desc
56
+ end
57
+
58
+ # Declares a CloudFormation parameter
59
+ #
60
+ # @param name [String] The parameter name
61
+ # @param options [Hash]
62
+ # @option options [String] :type The type for the CloudFormation parameter
63
+ # @option options [String] :default A value of the appropriate type for the template to use if no value is specified when a stack is created. If you define constraints for the parameter, you must specify a value that adheres to those constraints.
64
+ # @option options [String] :no_echo Whether to mask the parameter value whenever anyone makes a call that describes the stack. If you set the value to `true`, the parameter value is masked with asterisks (*****).
65
+ # @option options [String] :allowed_values An array containing the list of values allowed for the parameter.
66
+ # @option options [String] :allowed_pattern A regular expression that represents the patterns you want to allow for String types.
67
+ # @option options [Number] :max_length An integer value that determines the largest number of characters you want to allow for String types.
68
+ # @option options [Number] :min_length An integer value that determines the smallest number of characters you want to allow for String types.
69
+ # @option options [Number] :max_value A numeric value that determines the largest numeric value you want to allow for Number types.
70
+ # @option options [Number] :min_value A numeric value that determines the smallest numeric value you want to allow for Number types.
71
+ # @option options [String] :description A string of up to 4000 characters that describes the parameter.
72
+ # @option options [String] :constraint_description A string that explains the constraint when the constraint is violated. For example, without a constraint description, a parameter that has an allowed pattern of `[A-Za-z0-9]+` displays the following error message when the user specifies an invalid value:
73
+ #
74
+ # ```Malformed input-Parameter MyParameter must match pattern [A-Za-z0-9]+```
75
+ #
76
+ # By adding a constraint description, such as must only contain upper- and lowercase letters, and numbers, you can display a customized error message:
77
+ #
78
+ # ```Malformed input-Parameter MyParameter must only contain upper and lower case letters and numbers```
79
+ def parameter(name, options = {})
80
+ param = {}
81
+ options.each do |key, v|
82
+ k = key.to_s.camelize.to_sym
83
+ param[k] =
84
+ case k
85
+ when :AllowedValues
86
+ str_list = v.join(',')
87
+ verify_param(name, "Parameter #{name} must be one of: #{str_list}") { |input_val| str_list.include?(input_val) }
88
+ str_list
89
+ when :AllowedPattern
90
+ if v.class == Regexp
91
+ verify_param(name, "Parameter #{name} must match /#{v.source}/") { |input_val| v =~ input_val }
92
+ v.source
93
+ else
94
+ verify_param(name, "Parameter #{name} must match /#{v}/") { |input_val| Regexp.new(v) =~ input_val }
95
+ v
96
+ end
97
+ when :MaxLength
98
+ verify_param(name, "Parameter #{name} must have length <= #{v}") { |input_val| input_val.length <= v.to_i }
99
+ v
100
+ when :MinLength
101
+ verify_param(name, "Parameter #{name} must have length >= #{v}") { |input_val| input_val.length >= v.to_i }
102
+ v
103
+ when :MaxValue
104
+ verify_param(name, "Parameter #{name} must be <= #{v}") { |input_val| input_val.to_i <= v.to_i }
105
+ v
106
+ when :MinValue
107
+ verify_param(name, "Parameter #{name} must be >= #{v}") { |input_val| input_val.to_i >= v.to_i }
108
+ v
109
+ when :Description
110
+ Preconditions.check_argument(v.length <= 4000, "#{key} must be <= 4000 characters")
111
+ v
112
+ when :Default
113
+ @parameters[name] ||= resolve(v)
114
+ end
115
+ param[k] ||= v
116
+ end
117
+ param[:Type] ||= 'String'
118
+ self[:Parameters][name] = param
119
+ end
120
+
121
+ # Sets the mappings block for this stack. See [The CloudFormation Documentation](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html) for more details
122
+ def mappings(mappings)
123
+ self[:Mappings] = mappings
124
+ end
125
+
126
+ # Adds a condition to the template.
127
+ # @param name [String] The name of the condition.
128
+ # @param expr [Hash] The CloudFormation condition to add. See [The Cloudformation Documentation](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html) for more details
129
+ def condition(name, expr)
130
+ self[:Conditions][name] = expr
131
+ end
132
+
133
+ # Creates a CloudFormation resource
134
+ # @param name [String] The name of the resource (must be alphanumeric)
135
+ # @param type [String] The type of CloudFormation resource to create.
136
+ # @param options [Hash] Additional attributes to add to the resource block (such as the `UpdatePolicy` for an `AWS::AutoScaling::AutoScalingGroup`)
137
+ def resource(name, type, options = {}, &block)
138
+ Preconditions.check_argument(/[[:alnum:]]+/ =~ name, "Resource name must be alphanumeric")
139
+
140
+ clazz = "CferExt::#{type}".split('::').inject(Object) { |o, c| o.const_get c if o && o.const_defined?(c) } || Cfer::Cfn::Resource
141
+ Preconditions.check_argument clazz <= Cfer::Cfn::Resource, "#{type} is not a valid resource type because CferExt::#{type} does not inherit from `Cfer::Cfn::Resource`"
142
+
143
+ rc = clazz.new(name, type, options, &block)
144
+
145
+ self[:Resources][name] = rc
146
+ rc
147
+ end
148
+
149
+ # Adds an output to the CloudFormation stack.
150
+ # @param name [String] The Logical ID of the output parameter
151
+ # @param value [String] Value to return
152
+ # @param options [Hash] Extra options for this output parameter
153
+ # @option options [String] :Description Informationa bout the value
154
+ def output(name, value, options = {})
155
+ self[:Outputs][name] = options.merge('Value' => value)
156
+ end
157
+
158
+ # Renders the stack into a CloudFormation template.
159
+ # @return [String] The final template
160
+ def to_cfn
161
+ to_h.to_json
162
+ end
163
+
164
+ private
165
+ def verify_param(param_name, err_msg)
166
+ raise Cfer::Util::CferError, err_msg if (@parameters[param_name] && !yield(@parameters[param_name].to_s))
167
+ end
168
+ end
169
+
170
+ end
@@ -0,0 +1,31 @@
1
+ module Cfer::Util
2
+ require 'highline/import'
3
+ class CferError < StandardError
4
+ end
5
+
6
+ class StackExistsError < CferError
7
+ end
8
+
9
+ class TemplateError < CferError
10
+ attr_reader :template_backtrace
11
+
12
+ def initialize(template_backtrace)
13
+ @template_backtrace = template_backtrace
14
+ super
15
+ end
16
+ end
17
+
18
+ def self.bug_report(e)
19
+ gather_report e
20
+ transmit_report if agree('Would you like to send this information in a bug report? (type yes/no)')
21
+ end
22
+
23
+ private
24
+ def self.gather_report(e)
25
+ puts e
26
+ end
27
+
28
+ def self.transmit_report
29
+ puts "Sending report."
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Cfer
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,12 @@
1
+ require 'cferext/provisioning'
2
+
3
+ module CferExt::AWS::EC2
4
+ class Instance < Cfer::Cfn::Resource
5
+ include CferExt::Provisioning
6
+
7
+ def initialize(name, type, options = {}, &block)
8
+ options[:Metadata] ||= {}
9
+ super(name, type, options, &block)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ module CferExt::Provisioning
2
+ def cloud_init(doc)
3
+ userdata doc
4
+ end
5
+ end
6
+
metadata ADDED
@@ -0,0 +1,271 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cfer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Sean Edwards
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: docile
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: aws-sdk
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: aws-sdk-resources
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: preconditions
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: semantic
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rainbow
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: highline
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rugged
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: table_print
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ! '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rake
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ! '>='
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: bundler
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ! '>='
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ! '>='
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: yard
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ! '>='
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ! '>='
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ description: Toolkit for automating infrastructure using AWS CloudFormation
210
+ email:
211
+ - stedwards87+git@gmail.com
212
+ executables:
213
+ - cfer
214
+ extensions: []
215
+ extra_rdoc_files: []
216
+ files:
217
+ - .gitignore
218
+ - .rspec
219
+ - .travis.yml
220
+ - .yardopts
221
+ - CODE_OF_CONDUCT.md
222
+ - Gemfile
223
+ - LICENSE.txt
224
+ - README.md
225
+ - Rakefile
226
+ - bin/cfer
227
+ - bin/cfer-dbg
228
+ - bin/console
229
+ - bin/setup
230
+ - cfer-demo.gif
231
+ - cfer.gemspec
232
+ - examples/instance.rb
233
+ - examples/vpc.rb
234
+ - lib/cfer.rb
235
+ - lib/cfer/block.rb
236
+ - lib/cfer/cfn/aws.rb
237
+ - lib/cfer/cfn/client.rb
238
+ - lib/cfer/cli.rb
239
+ - lib/cfer/core/client.rb
240
+ - lib/cfer/core/fn.rb
241
+ - lib/cfer/core/resource.rb
242
+ - lib/cfer/core/stack.rb
243
+ - lib/cfer/util/error.rb
244
+ - lib/cfer/version.rb
245
+ - lib/cferext/aws/ec2/instance.rb
246
+ - lib/cferext/provisioning.rb
247
+ homepage: https://github.com/seanedwards/cfer
248
+ licenses:
249
+ - MIT
250
+ metadata: {}
251
+ post_install_message:
252
+ rdoc_options: []
253
+ require_paths:
254
+ - lib
255
+ required_ruby_version: !ruby/object:Gem::Requirement
256
+ requirements:
257
+ - - ! '>='
258
+ - !ruby/object:Gem::Version
259
+ version: '0'
260
+ required_rubygems_version: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ! '>='
263
+ - !ruby/object:Gem::Version
264
+ version: '0'
265
+ requirements: []
266
+ rubyforge_project:
267
+ rubygems_version: 2.4.5
268
+ signing_key:
269
+ specification_version: 4
270
+ summary: Toolkit for automating infrastructure using AWS CloudFormation
271
+ test_files: []