aws-cfn-dsl 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,59 @@
1
+ module Aws
2
+ module Cfn
3
+ module Dsl
4
+ module Simplify
5
+
6
+ def simplify(val,start=false)
7
+ logStep "Simplify a block ..." if start
8
+ if val.is_a?(Hash)
9
+ val = Hash[val.map { |k,v| [k, simplify(v)] }]
10
+ if val.length != 1
11
+ val
12
+ else
13
+ k, v = val.entries[0]
14
+ case @config[:functions]
15
+ when @on_yes_regex then
16
+ case
17
+ # CloudFormation functions
18
+ when k == 'Fn::Base64'
19
+ FnCall.new 'base64', [v], true
20
+ when k == 'Fn::FindInMap'
21
+ FnCall.new 'find_in_map', v
22
+ when k == 'Fn::GetAtt'
23
+ FnCall.new 'get_att', v
24
+ when k == 'Fn::GetAZs'
25
+ FnCall.new 'get_azs', v != '' ? [v] : []
26
+ when k == 'Fn::Join'
27
+ FnCall.new 'join', [v[0]] + v[1], true
28
+ when k == 'Fn::Select'
29
+ FnCall.new 'select', v
30
+ when k == 'Ref' && v == 'AWS::Region'
31
+ FnCall.new 'aws_region', []
32
+ when k == 'Ref' && v == 'AWS::StackName'
33
+ FnCall.new 'aws_stack_name', []
34
+ # CloudFormation internal references
35
+ when k == 'Ref'
36
+ FnCall.new 'ref', [v]
37
+ else
38
+ val
39
+ end
40
+ else
41
+ val
42
+ end
43
+ end
44
+ elsif val.is_a?(Array)
45
+ val.map { |v| simplify(v) }
46
+ else
47
+ val
48
+ end
49
+ end
50
+
51
+
52
+ def self.included(includer)
53
+
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -91,170 +91,6 @@ module Aws
91
91
  end
92
92
  end
93
93
 
94
- def exec!(argv=ARGV)
95
- @opts = Slop.parse(help: true) do
96
- banner "usage: #{$PROGRAM_NAME} <expand|diff|validate|create|update|delete>"
97
- on :o, :output=, 'The template file to save this DSL expansion to', as: String
98
- end
99
-
100
- action = argv[0] || 'expand'
101
- unless %w(expand diff validate create update delete).include? action
102
- $stderr.puts "usage: #{$PROGRAM_NAME} <expand|diff|validate|create|update|delete>"
103
- exit(2)
104
- end
105
- unless (argv & %w(--template-file --template-url)).empty?
106
- $stderr.puts "#{File.basename($PROGRAM_NAME)}: The --template-file and --template-url command-line options are not allowed. (You are running the template itself right now ... !)"
107
- exit(2)
108
- end
109
-
110
- # Find parameters where extension attribute :Immutable is true then remove it from the
111
- # cfn template since we can't pass it to CloudFormation.
112
- immutable_parameters = excise_parameter_attribute!(:Immutable)
113
-
114
- # Tag CloudFormation stacks based on :Tags defined in the template
115
- cfn_tags = excise_tags!
116
- # The command line string looks like: --tag "Key=key; Value=value" --tag "Key2=key2; Value2=value"
117
- cfn_tags_options = cfn_tags.sort.map { |tag| ["--tag", "Key=%s; Value=%s" % tag.split('=')] }.flatten
118
-
119
- # example: <template.rb> cfn-create-stack my-stack-name --parameters "Env=prod" --region eu-west-1
120
- # Execute the AWS CLI cfn-cmd command to validate/create/update a CloudFormation stack.
121
- if action == 'diff' or (action == 'expand' and not nopretty)
122
- template_string = JSON.pretty_generate(self)
123
- else
124
- template_string = JSON.generate(self)
125
- end
126
-
127
- if action == 'expand'
128
- # Write the pretty-printed JSON template to stdout and exit. [--nopretty] option writes output with minimal whitespace
129
- # example: <template.rb> expand --parameters "Env=prod" --region eu-west-1 --nopretty
130
- if @opts[:output]
131
- dest = @opts[:output]
132
- if File.directory? dest
133
- file = File.basename $PROGRAM_NAME
134
- file.gsub!(%r'\.rb', '.json')
135
- dest = File.join dest, file
136
- end
137
- IO.write(dest, template_string)
138
- else
139
- puts template_string
140
- end
141
- exit(true)
142
- end
143
-
144
- temp_file = File.absolute_path("#{$PROGRAM_NAME}.expanded.json")
145
- File.write(temp_file, template_string)
146
-
147
- cmdline = ['cfn-cmd'] + argv + ['--template-file', temp_file] + cfn_tags_options
148
-
149
- case action
150
- when 'diff'
151
- # example: <template.rb> diff my-stack-name --parameters "Env=prod" --region eu-west-1
152
- # Diff the current template for an existing stack with the expansion of this template.
153
-
154
- # The --parameters and --tag options were used to expand the template but we don't need them anymore. Discard.
155
- _, cfn_options = extract_options(argv[1..-1], %w(), %w(--parameters --tag))
156
-
157
- # Separate the remaining command-line options into options for 'cfn-cmd' and options for 'diff'.
158
- cfn_options, diff_options = extract_options(cfn_options, %w(),
159
- %w(--stack-name --region --parameters --connection-timeout -I --access-key-id -S --secret-key -K --ec2-private-key-file-path -U --url))
160
-
161
- # If the first argument is a stack name then shift it from diff_options over to cfn_options.
162
- if diff_options[0] && !(/^-/ =~ diff_options[0])
163
- cfn_options.unshift(diff_options.shift)
164
- end
165
-
166
- # Run CloudFormation commands to describe the existing stack
167
- cfn_options_string = cfn_options.map { |arg| "'#{arg}'" }.join(' ')
168
- old_template_raw = exec_capture_stdout("cfn-cmd cfn-get-template #{cfn_options_string}")
169
- # ec2 template output is not valid json: TEMPLATE "<json>\n"\n
170
- old_template_object = JSON.parse(old_template_raw[11..-3])
171
- old_template_string = JSON.pretty_generate(old_template_object)
172
- old_stack_attributes = exec_describe_stack(cfn_options_string)
173
- old_tags_string = old_stack_attributes["TAGS"]
174
- old_parameters_string = old_stack_attributes["PARAMETERS"]
175
-
176
- # Sort the tag strings alphabetically to make them easily comparable
177
- old_tags_string = (old_tags_string || '').split(';').sort.map { |tag| %Q(TAG "#{tag}"\n) }.join
178
- tags_string = cfn_tags.sort.map { |tag| "TAG \"#{tag}\"\n" }.join
179
-
180
- # Sort the parameter strings alphabetically to make them easily comparable
181
- old_parameters_string = (old_parameters_string || '').split(';').sort.map { |param| %Q(PARAMETER "#{param}"\n) }.join
182
- parameters_string = parameters.sort.map { |key, value| "PARAMETER \"#{key}=#{value}\"\n" }.join
183
-
184
- # Diff the expanded template with the template from CloudFormation.
185
- old_temp_file = File.absolute_path("#{$PROGRAM_NAME}.current.json")
186
- new_temp_file = File.absolute_path("#{$PROGRAM_NAME}.expanded.json")
187
- File.write(old_temp_file, old_tags_string + old_parameters_string + old_template_string)
188
- File.write(new_temp_file, tags_string + parameters_string + template_string)
189
-
190
- # Compare templates
191
- system(*["diff"] + diff_options + [old_temp_file, new_temp_file])
192
-
193
- File.delete(old_temp_file)
194
- File.delete(new_temp_file)
195
-
196
- exit(true)
197
-
198
- when 'cfn-validate-template'
199
- # The cfn-validate-template command doesn't support --parameters so remove it if it was provided for template expansion.
200
- _, cmdline = extract_options(cmdline, %w(), %w(--parameters --tag))
201
-
202
- when 'cfn-update-stack'
203
- # Pick out the subset of cfn-update-stack options that apply to cfn-describe-stacks.
204
- cfn_options, other_options = extract_options(argv[1..-1], %w(),
205
- %w(--stack-name --region --connection-timeout -I --access-key-id -S --secret-key -K --ec2-private-key-file-path -U --url))
206
-
207
- # If the first argument is a stack name then shift it over to cfn_options.
208
- if other_options[0] && !(/^-/ =~ other_options[0])
209
- cfn_options.unshift(other_options.shift)
210
- end
211
-
212
- # Run CloudFormation command to describe the existing stack
213
- cfn_options_string = cfn_options.map { |arg| "'#{arg}'" }.join(' ')
214
- old_stack_attributes = exec_describe_stack(cfn_options_string)
215
-
216
- # If updating a stack and some parameters are marked as immutable, fail if the new parameters don't match the old ones.
217
- if not immutable_parameters.empty?
218
- old_parameters_string = old_stack_attributes["PARAMETERS"]
219
- old_parameters = Hash[(old_parameters_string || '').split(';').map { |pair| pair.split('=', 2) }]
220
- new_parameters = parameters
221
-
222
- immutable_parameters.sort.each do |param|
223
- if old_parameters[param].to_s != new_parameters[param].to_s
224
- $stderr.puts "Error: cfn-update-stack may not update immutable parameter " +
225
- "'#{param}=#{old_parameters[param]}' to '#{param}=#{new_parameters[param]}'."
226
- exit(false)
227
- end
228
- end
229
- end
230
-
231
- # Tags are immutable in CloudFormation. The cfn-update-stack command doesn't support --tag options, so remove
232
- # the argument (if it exists) and validate against the existing stack to ensure tags haven't changed.
233
- # Compare the sorted arrays for an exact match
234
- old_cfn_tags = old_stack_attributes['TAGS'].split(';').sort rescue [] # Use empty Array if .split fails
235
- if cfn_tags != old_cfn_tags
236
- $stderr.puts "CloudFormation stack tags do not match and cannot be updated. You must either use the same tags or create a new stack." +
237
- "\n" + (old_cfn_tags - cfn_tags).map {|tag| "< #{tag}" }.join("\n") +
238
- "\n" + "---" +
239
- "\n" + (cfn_tags - old_cfn_tags).map {|tag| "> #{tag}"}.join("\n")
240
- exit(false)
241
- end
242
- _, cmdline = extract_options(cmdline, %w(), %w(--tag))
243
- end
244
-
245
- # Execute command cmdline
246
- unless system(*cmdline)
247
- $stderr.puts "\nExecution of 'cfn-cmd' failed. To facilitate debugging, the generated JSON template " +
248
- "file was not deleted. You may delete the file manually if it isn't needed: #{temp_file}"
249
- exit(false)
250
- end
251
-
252
- File.delete(temp_file)
253
-
254
- exit(true)
255
- end
256
-
257
-
258
94
  end
259
95
  end
260
96
  end
@@ -1,7 +1,7 @@
1
1
  module Aws
2
2
  module Cfn
3
3
  module Dsl
4
- VERSION = "0.6.0"
4
+ VERSION = '0.7.0'
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,77 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-cfn-dsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christo DeLange
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-28 00:00:00.000000000 Z
11
+ date: 2014-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.2.0
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - ! '>='
27
+ - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '0'
29
+ version: '1.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.2.0
27
33
  - !ruby/object:Gem::Dependency
28
- name: json
34
+ name: psych
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
- - - ! '>='
37
+ - - ">="
32
38
  - !ruby/object:Gem::Version
33
39
  version: '0'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
- - - ! '>='
44
+ - - ">="
39
45
  - !ruby/object:Gem::Version
40
46
  version: '0'
41
47
  - !ruby/object:Gem::Dependency
42
- name: cloudformation-ruby-dsl
48
+ name: json
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
- - - ~>
46
- - !ruby/object:Gem::Version
47
- version: '0.4'
48
- - - ! '>='
51
+ - - ">="
49
52
  - !ruby/object:Gem::Version
50
- version: 0.4.3
53
+ version: '0'
51
54
  type: :runtime
52
55
  prerelease: false
53
56
  version_requirements: !ruby/object:Gem::Requirement
54
57
  requirements:
55
- - - ~>
56
- - !ruby/object:Gem::Version
57
- version: '0.4'
58
- - - ! '>='
58
+ - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 0.4.3
60
+ version: '0'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: slop
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - ! '>='
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - ! '>='
72
+ - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: cloudformation-ruby-dsl
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.4'
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 0.4.3
85
+ type: :runtime
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '0.4'
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 0.4.3
75
95
  description: Ruby DSL for creating Cloudformation templates
76
96
  email:
77
97
  - rubygems@dldinternet.com
@@ -80,7 +100,7 @@ executables:
80
100
  extensions: []
81
101
  extra_rdoc_files: []
82
102
  files:
83
- - .gitignore
103
+ - ".gitignore"
84
104
  - Gemfile
85
105
  - LICENSE
86
106
  - LICENSE.txt
@@ -93,6 +113,12 @@ files:
93
113
  - lib/aws/cfn/dsl/base.rb
94
114
  - lib/aws/cfn/dsl/fncall.rb
95
115
  - lib/aws/cfn/dsl/main.rb
116
+ - lib/aws/cfn/dsl/mixins/dsl.rb
117
+ - lib/aws/cfn/dsl/mixins/maintainer.rb
118
+ - lib/aws/cfn/dsl/mixins/options.rb
119
+ - lib/aws/cfn/dsl/mixins/output.rb
120
+ - lib/aws/cfn/dsl/mixins/prettyprint.rb
121
+ - lib/aws/cfn/dsl/mixins/simplify.rb
96
122
  - lib/aws/cfn/dsl/template.rb
97
123
  - lib/aws/cfn/dsl/version.rb
98
124
  homepage: ''
@@ -105,12 +131,12 @@ require_paths:
105
131
  - lib
106
132
  required_ruby_version: !ruby/object:Gem::Requirement
107
133
  requirements:
108
- - - ! '>='
134
+ - - ">="
109
135
  - !ruby/object:Gem::Version
110
136
  version: '0'
111
137
  required_rubygems_version: !ruby/object:Gem::Requirement
112
138
  requirements:
113
- - - ! '>='
139
+ - - ">="
114
140
  - !ruby/object:Gem::Version
115
141
  version: '0'
116
142
  requirements: []