stackup 1.0.4 → 1.1.0
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.
- checksums.yaml +4 -4
- data/CHANGES.md +6 -0
- data/bin/stackup +54 -38
- data/lib/stackup/source.rb +58 -0
- data/lib/stackup/version.rb +1 -1
- data/spec/stackup/source_spec.rb +75 -0
- metadata +18 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd8f6344aa29806003cac476d52ecd7070747ec3
|
4
|
+
data.tar.gz: 1a64e7205d279d0e7922171de005ac6ddcbb08ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abbf1538c8f0a04dcbd72b180803f7eb9211c07ec74eda51078135f40fd31088eaf6a3442688a6a92cee886799374475f7c4ca5ea9a350fc6fb6b6ea2ccc7b33
|
7
|
+
data.tar.gz: 6fd7cb6adb0b1bd846ab7a347be74f630a4ac6514db282d1f5cd3073991ce0155f80b09b100e32fbcd965f1ad30b6ab6d9caf9c7e0342756d6ee7b9c8a34dee8
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 1.1.0 (2017-02-23)
|
2
|
+
|
3
|
+
* The `stackup` CLI now allows stack template and policy documents to be specified as URLs.
|
4
|
+
* Template URL must point to a template stored in an Amazon S3 bucket, e.g. `https://s3-ap-southeast-2.amazonaws.com/bucket/template.json`.
|
5
|
+
* Policy URL must point to an object located in an S3 bucket in the same region as the stack.
|
6
|
+
|
1
7
|
## 1.0.4 (2017-01-04)
|
2
8
|
|
3
9
|
* Fix #34: make YAML parsing work in ruby-2.0.
|
data/bin/stackup
CHANGED
@@ -8,6 +8,7 @@ require "multi_json"
|
|
8
8
|
require "securerandom"
|
9
9
|
require "stackup"
|
10
10
|
require "stackup/differ"
|
11
|
+
require "stackup/source"
|
11
12
|
require "stackup/version"
|
12
13
|
require "stackup/yaml"
|
13
14
|
|
@@ -55,6 +56,8 @@ Clamp do
|
|
55
56
|
|
56
57
|
def run(arguments)
|
57
58
|
super(arguments)
|
59
|
+
rescue Stackup::Source::ReadError => e
|
60
|
+
signal_error e.message
|
58
61
|
rescue Stackup::ServiceError => e
|
59
62
|
signal_error e.message
|
60
63
|
rescue Aws::Errors::MissingCredentialsError
|
@@ -126,14 +129,10 @@ Clamp do
|
|
126
129
|
puts final_status unless final_status.nil?
|
127
130
|
end
|
128
131
|
|
129
|
-
def
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
end
|
134
|
-
|
135
|
-
def load_parameters(file)
|
136
|
-
Stackup::Parameters.new(load_data(file)).to_hash
|
132
|
+
def parameters_from_files
|
133
|
+
parameter_sources.map { |src|
|
134
|
+
Stackup::Parameters.new(src.data).to_hash
|
135
|
+
}.inject(:merge)
|
137
136
|
end
|
138
137
|
|
139
138
|
subcommand "status", "Print stack status." do
|
@@ -144,42 +143,58 @@ Clamp do
|
|
144
143
|
|
145
144
|
end
|
146
145
|
|
147
|
-
subcommand "up", "Create/update the stack" do
|
146
|
+
subcommand "up", "Create/update the stack." do
|
148
147
|
|
149
|
-
option ["-t", "--template"], "FILE", "template
|
150
|
-
:attribute_name => :
|
148
|
+
option ["-t", "--template"], "FILE", "template source",
|
149
|
+
:attribute_name => :template_source,
|
150
|
+
&Stackup::Source.method(:new)
|
151
151
|
|
152
152
|
option ["-T", "--use-previous-template"], :flag,
|
153
153
|
"reuse the existing template"
|
154
154
|
|
155
155
|
option ["-p", "--parameters"], "FILE", "parameters file (last wins)",
|
156
156
|
:multivalued => true,
|
157
|
-
:attribute_name => :
|
157
|
+
:attribute_name => :parameter_sources,
|
158
|
+
&Stackup::Source.method(:new)
|
158
159
|
|
159
160
|
option ["-o", "--override"], "PARAM=VALUE", "parameter overrides",
|
160
161
|
:multivalued => true,
|
161
162
|
:attribute_name => :override_list
|
162
163
|
|
163
164
|
option "--tags", "FILE", "stack tags file",
|
164
|
-
:attribute_name => :
|
165
|
+
:attribute_name => :tag_source,
|
166
|
+
&Stackup::Source.method(:new)
|
165
167
|
|
166
168
|
option "--policy", "FILE", "stack policy file",
|
167
|
-
:attribute_name => :
|
169
|
+
:attribute_name => :policy_source,
|
170
|
+
&Stackup::Source.method(:new)
|
168
171
|
|
169
172
|
option "--on-failure", "ACTION",
|
170
173
|
"when stack creation fails: DO_NOTHING, ROLLBACK, or DELETE",
|
171
174
|
:default => "ROLLBACK"
|
172
175
|
|
173
176
|
def execute
|
174
|
-
unless
|
177
|
+
unless template_source || use_previous_template?
|
175
178
|
signal_usage_error "Specify either --template or --use-previous-template"
|
176
179
|
end
|
177
180
|
options = {}
|
178
|
-
|
181
|
+
if template_source
|
182
|
+
if is_s3_url?(template_source.location)
|
183
|
+
options[:template_url] = template_source.location
|
184
|
+
else
|
185
|
+
options[:template] = template_source.data
|
186
|
+
end
|
187
|
+
end
|
179
188
|
options[:on_failure] = on_failure
|
180
189
|
options[:parameters] = parameters
|
181
|
-
options[:tags] =
|
182
|
-
|
190
|
+
options[:tags] = tag_source.data if tag_source
|
191
|
+
if policy_source
|
192
|
+
if is_s3_url?(policy_source.location)
|
193
|
+
options[:stack_policy_url] = policy_source.location
|
194
|
+
else
|
195
|
+
options[:stack_policy] = policy_source.data
|
196
|
+
end
|
197
|
+
end
|
183
198
|
options[:use_previous_template] = use_previous_template?
|
184
199
|
report_change do
|
185
200
|
stack.create_or_update(options)
|
@@ -189,9 +204,7 @@ Clamp do
|
|
189
204
|
private
|
190
205
|
|
191
206
|
def parameters
|
192
|
-
|
193
|
-
hashes << parameter_overrides
|
194
|
-
hashes.inject(:merge)
|
207
|
+
parameters_from_files.merge(parameter_overrides)
|
195
208
|
end
|
196
209
|
|
197
210
|
def parameter_overrides
|
@@ -203,36 +216,43 @@ Clamp do
|
|
203
216
|
end
|
204
217
|
end
|
205
218
|
|
219
|
+
def is_s3_url?(location)
|
220
|
+
location =~ %r{^https://s3\w*.amazonaws.com}
|
221
|
+
end
|
222
|
+
|
206
223
|
end
|
207
224
|
|
208
225
|
subcommand "diff", "Compare template/params to current stack." do
|
209
226
|
|
210
|
-
option ["-t", "--template"], "FILE", "template
|
211
|
-
:attribute_name => :
|
227
|
+
option ["-t", "--template"], "FILE", "template source",
|
228
|
+
:attribute_name => :template_source,
|
229
|
+
&Stackup::Source.method(:new)
|
212
230
|
|
213
231
|
option ["-p", "--parameters"], "FILE", "parameters file (last wins)",
|
214
232
|
:multivalued => true,
|
215
|
-
:attribute_name => :
|
233
|
+
:attribute_name => :parameter_sources,
|
234
|
+
&Stackup::Source.method(:new)
|
216
235
|
|
217
236
|
option "--tags", "FILE", "stack tags file",
|
218
|
-
:attribute_name => :
|
237
|
+
:attribute_name => :tag_source,
|
238
|
+
&Stackup::Source.method(:new)
|
219
239
|
|
220
240
|
option "--diff-format", "FORMAT", "'text', 'color', or 'html'", :default => "color"
|
221
241
|
|
222
242
|
def execute
|
223
243
|
current = {}
|
224
244
|
planned = {}
|
225
|
-
if
|
245
|
+
if template_source
|
226
246
|
current["Template"] = stack.template
|
227
|
-
planned["Template"] =
|
247
|
+
planned["Template"] = template_source.data
|
228
248
|
end
|
229
|
-
unless
|
249
|
+
unless parameter_sources.empty?
|
230
250
|
current["Parameters"] = existing_parameters.sort.to_h
|
231
251
|
planned["Parameters"] = new_parameters.sort.to_h
|
232
252
|
end
|
233
|
-
if
|
253
|
+
if tag_source
|
234
254
|
current["Tags"] = stack.tags.sort.to_h
|
235
|
-
planned["Tags"] =
|
255
|
+
planned["Tags"] = tag_source.data.sort.to_h
|
236
256
|
end
|
237
257
|
signal_usage_error "specify '--template' or '--parameters'" if planned.empty?
|
238
258
|
puts differ.diff(current, planned)
|
@@ -248,10 +268,6 @@ Clamp do
|
|
248
268
|
@existing_parameters ||= stack.parameters
|
249
269
|
end
|
250
270
|
|
251
|
-
def parameters_from_files
|
252
|
-
parameter_file_list.map(&method(:load_parameters)).inject(:merge)
|
253
|
-
end
|
254
|
-
|
255
271
|
def new_parameters
|
256
272
|
existing_parameters.merge(parameters_from_files)
|
257
273
|
end
|
@@ -268,7 +284,7 @@ Clamp do
|
|
268
284
|
|
269
285
|
end
|
270
286
|
|
271
|
-
subcommand "cancel-update", "Cancel the update in-progress" do
|
287
|
+
subcommand "cancel-update", "Cancel the update in-progress." do
|
272
288
|
|
273
289
|
def execute
|
274
290
|
report_change do
|
@@ -278,7 +294,7 @@ Clamp do
|
|
278
294
|
|
279
295
|
end
|
280
296
|
|
281
|
-
subcommand "wait", "Wait until stack is stable" do
|
297
|
+
subcommand "wait", "Wait until stack is stable." do
|
282
298
|
|
283
299
|
def execute
|
284
300
|
puts stack.wait
|
@@ -286,7 +302,7 @@ Clamp do
|
|
286
302
|
|
287
303
|
end
|
288
304
|
|
289
|
-
subcommand "events", "List stack events" do
|
305
|
+
subcommand "events", "List stack events." do
|
290
306
|
|
291
307
|
option ["-f", "--follow"], :flag, "follow new events"
|
292
308
|
option ["--data"], :flag, "display events as data"
|
@@ -376,7 +392,7 @@ Clamp do
|
|
376
392
|
|
377
393
|
end
|
378
394
|
|
379
|
-
subcommand "inspect", "Display stack particulars" do
|
395
|
+
subcommand "inspect", "Display stack particulars." do
|
380
396
|
|
381
397
|
def execute
|
382
398
|
data = {
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "aws-sdk-core"
|
2
|
+
require "open-uri"
|
3
|
+
require "stackup/stack"
|
4
|
+
|
5
|
+
module Stackup
|
6
|
+
|
7
|
+
# Represents a source of input, e.g. template, parameter, etc.
|
8
|
+
#
|
9
|
+
class Source
|
10
|
+
|
11
|
+
def initialize(location)
|
12
|
+
@location = location
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :location
|
16
|
+
|
17
|
+
def body
|
18
|
+
@body ||= read
|
19
|
+
end
|
20
|
+
|
21
|
+
def data
|
22
|
+
@data ||= parse_body
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
LOOKS_LIKE_JSON = /^\s*[\{\[]/
|
28
|
+
|
29
|
+
def uri
|
30
|
+
URI(location)
|
31
|
+
end
|
32
|
+
|
33
|
+
def read
|
34
|
+
if uri.scheme
|
35
|
+
uri.read
|
36
|
+
else
|
37
|
+
IO.read(location)
|
38
|
+
end
|
39
|
+
rescue Errno::ENOENT
|
40
|
+
raise ReadError, "no such file: #{location.inspect}"
|
41
|
+
rescue OpenURI::HTTPError => e
|
42
|
+
raise ReadError, "#{e}: #{location.inspect}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def parse_body
|
46
|
+
if body =~ LOOKS_LIKE_JSON
|
47
|
+
MultiJson.load(body)
|
48
|
+
else
|
49
|
+
Stackup::YAML.load(body)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class ReadError < StandardError
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/stackup/version.rb
CHANGED
@@ -0,0 +1,75 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require "multi_json"
|
4
|
+
require "stackup/source"
|
5
|
+
require "stackup/yaml"
|
6
|
+
|
7
|
+
describe Stackup::Source do
|
8
|
+
|
9
|
+
let(:example_dir) { File.expand_path("../../../examples", __FILE__) }
|
10
|
+
|
11
|
+
context "from a JSON file" do
|
12
|
+
|
13
|
+
let(:json_file) { File.join(example_dir, "template.json") }
|
14
|
+
|
15
|
+
subject(:source) { described_class.new(json_file) }
|
16
|
+
|
17
|
+
describe "#body" do
|
18
|
+
|
19
|
+
it "returns JSON body" do
|
20
|
+
expect(subject.body).to eql(File.read(json_file))
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#data" do
|
26
|
+
|
27
|
+
it "returns parsed JSON" do
|
28
|
+
expect(subject.data).to eql(MultiJson.load(File.read(json_file)))
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
context "from a YAML file" do
|
36
|
+
|
37
|
+
let(:yaml_file) { File.join(example_dir, "template.yml") }
|
38
|
+
|
39
|
+
subject(:source) { described_class.new(yaml_file) }
|
40
|
+
|
41
|
+
describe "#body" do
|
42
|
+
|
43
|
+
it "returns YAML body" do
|
44
|
+
expect(subject.body).to eql(File.read(yaml_file))
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#data" do
|
50
|
+
|
51
|
+
it "returns parsed YAML" do
|
52
|
+
expect(subject.data).to eql(Stackup::YAML.load_file(yaml_file))
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
context "with a non-existant file" do
|
60
|
+
|
61
|
+
let(:bogus_file) { "notreallythere.json" }
|
62
|
+
|
63
|
+
subject(:source) { described_class.new(bogus_file) }
|
64
|
+
|
65
|
+
describe "#body" do
|
66
|
+
|
67
|
+
it "raises a ReadError" do
|
68
|
+
expect { subject.body }.to raise_error(Stackup::Source::ReadError, %q(no such file: "notreallythere.json"))
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stackup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Williams
|
@@ -9,76 +9,76 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-02-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk-resources
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - ~>
|
18
|
+
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '2.0'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- - ~>
|
25
|
+
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '2.0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: clamp
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - ~>
|
32
|
+
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '1.0'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - ~>
|
39
|
+
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '1.0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: console_logger
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- -
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '0'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: diffy
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- - ~>
|
60
|
+
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '3.0'
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- - ~>
|
67
|
+
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '3.0'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: multi_json
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- -
|
74
|
+
- - ">="
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
84
|
description:
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- lib/stackup/parameters.rb
|
101
101
|
- lib/stackup/rake_tasks.rb
|
102
102
|
- lib/stackup/service.rb
|
103
|
+
- lib/stackup/source.rb
|
103
104
|
- lib/stackup/stack.rb
|
104
105
|
- lib/stackup/stack_watcher.rb
|
105
106
|
- lib/stackup/utils.rb
|
@@ -107,6 +108,7 @@ files:
|
|
107
108
|
- lib/stackup/yaml.rb
|
108
109
|
- spec/spec_helper.rb
|
109
110
|
- spec/stackup/parameters_spec.rb
|
111
|
+
- spec/stackup/source_spec.rb
|
110
112
|
- spec/stackup/stack_spec.rb
|
111
113
|
- spec/stackup/stack_watcher_spec.rb
|
112
114
|
- spec/stackup/utils_spec.rb
|
@@ -121,23 +123,24 @@ require_paths:
|
|
121
123
|
- lib
|
122
124
|
required_ruby_version: !ruby/object:Gem::Requirement
|
123
125
|
requirements:
|
124
|
-
- -
|
126
|
+
- - ">="
|
125
127
|
- !ruby/object:Gem::Version
|
126
128
|
version: '0'
|
127
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
130
|
requirements:
|
129
|
-
- -
|
131
|
+
- - ">="
|
130
132
|
- !ruby/object:Gem::Version
|
131
133
|
version: '0'
|
132
134
|
requirements: []
|
133
135
|
rubyforge_project:
|
134
|
-
rubygems_version: 2.6.
|
136
|
+
rubygems_version: 2.6.10
|
135
137
|
signing_key:
|
136
138
|
specification_version: 4
|
137
139
|
summary: Manage CloudFormation stacks
|
138
140
|
test_files:
|
139
141
|
- spec/spec_helper.rb
|
140
142
|
- spec/stackup/parameters_spec.rb
|
143
|
+
- spec/stackup/source_spec.rb
|
141
144
|
- spec/stackup/stack_spec.rb
|
142
145
|
- spec/stackup/stack_watcher_spec.rb
|
143
146
|
- spec/stackup/utils_spec.rb
|