cuffsert 0.10.1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +16 -6
- data/cuffsert.gemspec +2 -1
- data/lib/cuffsert/actions.rb +109 -0
- data/lib/cuffsert/cfarguments.rb +41 -10
- data/lib/cuffsert/cli_args.rb +11 -0
- data/lib/cuffsert/main.rb +21 -69
- data/lib/cuffsert/messages.rb +10 -2
- data/lib/cuffsert/metadata.rb +5 -1
- data/lib/cuffsert/presenters.rb +16 -8
- data/lib/cuffsert/rxcfclient.rb +11 -10
- data/lib/cuffsert/rxs3client.rb +44 -0
- data/lib/cuffsert/version.rb +1 -1
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1be8dd08dce49cf000289c1a1e198026bf48e2c5
|
4
|
+
data.tar.gz: 3e0846cd94c5273d1ef260105b962c3c3196d6cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75340fd814849e4c1f42f6ec007eac89d20d2f925b599cdaf9ad32e489638ac00808a9879e2361f8c5d5833a2082b3b0f3992f90e2c061d8efa0f3e7ad6e4e3a
|
7
|
+
data.tar.gz: 92da57f24fb3c7443462404602d22b9a28c615ecd258e648e4bf22640e3441224e48465266f766ffc930b0a639a885e2ba674de7109e602e457d647431c150fa
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cuffsert (0.
|
4
|
+
cuffsert (0.11.0)
|
5
5
|
aws-sdk-cloudformation (~> 1.3.0)
|
6
|
+
aws-sdk-s3 (~> 1.8.0)
|
6
7
|
colorize
|
7
8
|
ruby-termios
|
8
9
|
rx
|
@@ -10,20 +11,29 @@ PATH
|
|
10
11
|
GEM
|
11
12
|
remote: https://rubygems.org/
|
12
13
|
specs:
|
13
|
-
aws-
|
14
|
+
aws-eventstream (1.0.0)
|
15
|
+
aws-partitions (1.87.0)
|
14
16
|
aws-sdk-cloudformation (1.3.0)
|
15
17
|
aws-sdk-core (~> 3)
|
16
18
|
aws-sigv4 (~> 1.0)
|
17
|
-
aws-sdk-core (3.
|
19
|
+
aws-sdk-core (3.21.2)
|
20
|
+
aws-eventstream (~> 1.0)
|
18
21
|
aws-partitions (~> 1.0)
|
19
22
|
aws-sigv4 (~> 1.0)
|
20
23
|
jmespath (~> 1.0)
|
24
|
+
aws-sdk-kms (1.5.0)
|
25
|
+
aws-sdk-core (~> 3)
|
26
|
+
aws-sigv4 (~> 1.0)
|
27
|
+
aws-sdk-s3 (1.8.2)
|
28
|
+
aws-sdk-core (~> 3)
|
29
|
+
aws-sdk-kms (~> 1)
|
30
|
+
aws-sigv4 (~> 1.0)
|
21
31
|
aws-sigv4 (1.0.2)
|
22
32
|
byebug (9.0.6)
|
23
33
|
colorize (0.8.1)
|
24
34
|
diff-lcs (1.2.5)
|
25
35
|
docile (1.1.5)
|
26
|
-
jmespath (1.
|
36
|
+
jmespath (1.4.0)
|
27
37
|
json (2.0.2)
|
28
38
|
rspec (3.5.0)
|
29
39
|
rspec-core (~> 3.5.0)
|
@@ -40,7 +50,7 @@ GEM
|
|
40
50
|
rspec-support (3.5.0)
|
41
51
|
ruby-termios (1.0.2)
|
42
52
|
rx (0.0.3)
|
43
|
-
rx-rspec (0.
|
53
|
+
rx-rspec (0.4.3)
|
44
54
|
rx
|
45
55
|
simplecov (0.12.0)
|
46
56
|
docile (~> 1.1.0)
|
@@ -56,7 +66,7 @@ DEPENDENCIES
|
|
56
66
|
byebug
|
57
67
|
cuffsert!
|
58
68
|
rspec (~> 3.0)
|
59
|
-
rx-rspec (~> 0.
|
69
|
+
rx-rspec (~> 0.4.3)
|
60
70
|
simplecov
|
61
71
|
|
62
72
|
BUNDLED WITH
|
data/cuffsert.gemspec
CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.required_ruby_version = '>= 2.0.0'
|
17
17
|
|
18
18
|
spec.add_runtime_dependency 'aws-sdk-cloudformation', '~> 1.3.0'
|
19
|
+
spec.add_runtime_dependency 'aws-sdk-s3', '~> 1.8.0'
|
19
20
|
spec.add_runtime_dependency 'colorize'
|
20
21
|
spec.add_runtime_dependency 'ruby-termios'
|
21
22
|
spec.add_runtime_dependency 'rx'
|
@@ -23,6 +24,6 @@ Gem::Specification.new do |spec|
|
|
23
24
|
spec.add_development_dependency 'bundler', '~> 1.12'
|
24
25
|
spec.add_development_dependency 'byebug'
|
25
26
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
|
-
spec.add_development_dependency 'rx-rspec', '~> 0.
|
27
|
+
spec.add_development_dependency 'rx-rspec', '~> 0.4.3'
|
27
28
|
spec.add_development_dependency 'simplecov'
|
28
29
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'cuffsert/actions'
|
2
|
+
require 'cuffsert/cfarguments'
|
3
|
+
require 'cuffsert/messages'
|
4
|
+
require 'rx'
|
5
|
+
|
6
|
+
module CuffSert
|
7
|
+
class BaseAction
|
8
|
+
attr_accessor :cfclient, :confirmation, :s3client
|
9
|
+
|
10
|
+
def initialize(meta, stack)
|
11
|
+
@cfclient = nil
|
12
|
+
@confirmation = nil
|
13
|
+
@meta = meta
|
14
|
+
@s3client = nil
|
15
|
+
@stack = stack
|
16
|
+
end
|
17
|
+
|
18
|
+
def upload_template_if_oversized(cfargs)
|
19
|
+
if cfargs[:template_body].nil? && cfargs[:template_url].nil?
|
20
|
+
raise 'Template bigger than 51200; please supply --s3-upload-prefix' unless @s3client
|
21
|
+
uri, progress = @s3client.upload(@meta.stack_uri)
|
22
|
+
[CuffSert.s3_uri_to_https(uri).to_s, progress]
|
23
|
+
else
|
24
|
+
[nil, Rx::Observable.empty]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class CreateStackAction < BaseAction
|
30
|
+
def as_observable
|
31
|
+
cfargs = CuffSert.as_create_stack_args(@meta)
|
32
|
+
upload_uri, maybe_upload = upload_template_if_oversized(cfargs)
|
33
|
+
cfargs[:template_url] = upload_uri if upload_uri
|
34
|
+
maybe_upload.concat(
|
35
|
+
Rx::Observable.of([:create, @meta.stackname]),
|
36
|
+
Rx::Observable.defer do
|
37
|
+
if @confirmation.call(@meta, :create, nil)
|
38
|
+
Rx::Observable.concat(
|
39
|
+
@cfclient.create_stack(cfargs),
|
40
|
+
Done.new.as_observable
|
41
|
+
)
|
42
|
+
else
|
43
|
+
Abort.new('User abort!').as_observable
|
44
|
+
end
|
45
|
+
end
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class UpdateStackAction < BaseAction
|
51
|
+
def as_observable
|
52
|
+
cfargs = CuffSert.as_update_change_set(@meta)
|
53
|
+
upload_uri, maybe_upload = upload_template_if_oversized(cfargs)
|
54
|
+
cfargs[:template_url] = upload_uri if upload_uri
|
55
|
+
maybe_upload
|
56
|
+
.concat(@cfclient.prepare_update(cfargs))
|
57
|
+
.flat_map do |change_set|
|
58
|
+
if change_set.is_a? Aws::CloudFormation::Types::DescribeChangeSetOutput
|
59
|
+
Rx::Observable.concat(
|
60
|
+
Rx::Observable.of(change_set),
|
61
|
+
Rx::Observable.defer {
|
62
|
+
if change_set[:status] == 'FAILED'
|
63
|
+
Rx::Observable.concat(
|
64
|
+
@cfclient.abort_update(change_set[:change_set_id]),
|
65
|
+
Abort.new("Update failed: #{change_set[:status_reason]}").as_observable
|
66
|
+
)
|
67
|
+
elsif @confirmation.call(@meta, :update, change_set)
|
68
|
+
Rx::Observable.concat(
|
69
|
+
@cfclient.update_stack(change_set[:stack_id], change_set[:change_set_id]),
|
70
|
+
Done.new.as_observable
|
71
|
+
)
|
72
|
+
else
|
73
|
+
Rx::Observable.concat(
|
74
|
+
@cfclient.abort_update(change_set[:change_set_id]),
|
75
|
+
Abort.new('User abort!').as_observable
|
76
|
+
)
|
77
|
+
end
|
78
|
+
}
|
79
|
+
)
|
80
|
+
else
|
81
|
+
Rx::Observable.just(change_set)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class RecreateStackAction < BaseAction
|
88
|
+
def as_observable
|
89
|
+
crt_args = CuffSert.as_create_stack_args(@meta)
|
90
|
+
del_args = CuffSert.as_delete_stack_args(@stack)
|
91
|
+
upload_uri, maybe_upload = upload_template_if_oversized(crt_args)
|
92
|
+
crt_args[:template_url] = upload_uri if upload_uri
|
93
|
+
maybe_upload.concat(
|
94
|
+
Rx::Observable.of([:recreate, @stack]),
|
95
|
+
Rx::Observable.defer do
|
96
|
+
if @confirmation.call(@meta, :recreate, @stack)
|
97
|
+
Rx::Observable.concat(
|
98
|
+
@cfclient.delete_stack(del_args),
|
99
|
+
@cfclient.create_stack(crt_args),
|
100
|
+
Done.new.as_observable
|
101
|
+
)
|
102
|
+
else
|
103
|
+
CuffSert::Abort.new('User abort!').as_observable
|
104
|
+
end
|
105
|
+
end
|
106
|
+
)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/cuffsert/cfarguments.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'open-uri'
|
2
|
+
require 'yaml'
|
2
3
|
|
3
4
|
# TODO:
|
4
5
|
# - propagate timeout here (from config?)
|
5
|
-
# - fail on template body > 51200 bytes
|
6
6
|
# - creation change-set: cfargs[:change_set_type] = 'CREATE'
|
7
7
|
|
8
8
|
module CuffSert
|
@@ -33,15 +33,7 @@ module CuffSert
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
|
-
cfargs[:template_url] = meta.stack_uri.to_s
|
38
|
-
elsif meta.stack_uri.scheme == 'file'
|
39
|
-
file = meta.stack_uri.to_s.sub(/^file:\/+/, '/')
|
40
|
-
cfargs[:template_body] = open(file).read
|
41
|
-
else
|
42
|
-
raise "Unsupported scheme #{meta.stack_uri.scheme}"
|
43
|
-
end
|
44
|
-
cfargs
|
36
|
+
cfargs.merge!(self.template_parameters(meta))
|
45
37
|
end
|
46
38
|
|
47
39
|
def self.as_create_stack_args(meta)
|
@@ -65,4 +57,43 @@ module CuffSert
|
|
65
57
|
def self.as_delete_stack_args(stack)
|
66
58
|
{ :stack_name => stack[:stack_id] }
|
67
59
|
end
|
60
|
+
|
61
|
+
def self.s3_uri_to_https(uri)
|
62
|
+
region = ENV['AWS_REGION'] || ENV['AWS_DEFAULT_REGION'] || 'us-east-1'
|
63
|
+
bucket = uri.host
|
64
|
+
key = uri.path
|
65
|
+
host = region == 'us-east-1' ? 's3.amazonaws.com' : "s3-#{region}.amazonaws.com"
|
66
|
+
"https://#{host}/#{bucket}#{key}"
|
67
|
+
end
|
68
|
+
|
69
|
+
private_class_method
|
70
|
+
|
71
|
+
def self.load_minified_template(file)
|
72
|
+
template = open(file).read
|
73
|
+
YAML.load(template).to_json
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.template_parameters(meta)
|
77
|
+
template_parameters = {}
|
78
|
+
|
79
|
+
if meta.stack_uri.scheme == 's3'
|
80
|
+
template_parameters[:template_url] = self.s3_uri_to_https(meta.stack_uri)
|
81
|
+
elsif meta.stack_uri.scheme == 'https'
|
82
|
+
if meta.stack_uri.host.end_with?('amazonaws.com')
|
83
|
+
template_parameters[:template_url] = meta.stack_uri.to_s
|
84
|
+
else
|
85
|
+
raise 'Only HTTPS URLs pointing to amazonaws.com supported.'
|
86
|
+
end
|
87
|
+
elsif meta.stack_uri.scheme == 'file'
|
88
|
+
file = meta.stack_uri.to_s.sub(/^file:\/+/, '/')
|
89
|
+
template = self.load_minified_template(file)
|
90
|
+
if template.size <= 51200
|
91
|
+
template_parameters[:template_body] = template
|
92
|
+
end
|
93
|
+
else
|
94
|
+
raise "Unsupported scheme #{meta.stack_uri.scheme}"
|
95
|
+
end
|
96
|
+
|
97
|
+
template_parameters
|
98
|
+
end
|
68
99
|
end
|
data/lib/cuffsert/cli_args.rb
CHANGED
@@ -60,6 +60,17 @@ module CuffSert
|
|
60
60
|
args[:overrides][:tags][key] = val
|
61
61
|
end
|
62
62
|
|
63
|
+
opts.on('--region=aws_region', 'AWS region, overrides env variable AWS_REGION') do |region|
|
64
|
+
args[:aws_region] = region
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on('--s3-upload-prefix=prefix', 'Templates > 51200 bytes are uploaded here. Format: s3://bucket-name/[pre/fix]') do |prefix|
|
68
|
+
unless prefix.start_with?('s3://')
|
69
|
+
raise "Upload prefix #{prefix} must start with s3://"
|
70
|
+
end
|
71
|
+
args[:s3_upload_prefix] = prefix
|
72
|
+
end
|
73
|
+
|
63
74
|
opts.on('--json', 'Output events in JSON, no progressbar, colors') do
|
64
75
|
args[:output] = :json
|
65
76
|
end
|
data/lib/cuffsert/main.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'cuffsert/
|
1
|
+
require 'cuffsert/actions'
|
2
2
|
require 'cuffsert/cfstates'
|
3
3
|
require 'cuffsert/cli_args'
|
4
4
|
require 'cuffsert/confirmation'
|
@@ -6,79 +6,27 @@ require 'cuffsert/messages'
|
|
6
6
|
require 'cuffsert/metadata'
|
7
7
|
require 'cuffsert/presenters'
|
8
8
|
require 'cuffsert/rxcfclient'
|
9
|
+
require 'cuffsert/rxs3client'
|
9
10
|
require 'rx'
|
10
11
|
require 'uri'
|
11
12
|
|
12
13
|
module CuffSert
|
13
|
-
def self.
|
14
|
-
|
15
|
-
Rx::Observable.concat(
|
16
|
-
Rx::Observable.of([:create, meta.stackname]),
|
17
|
-
Rx::Observable.defer do
|
18
|
-
if confirm_create.call(meta, :create, nil)
|
19
|
-
client.create_stack(cfargs)
|
20
|
-
else
|
21
|
-
Abort.new('User abort!').as_observable
|
22
|
-
end
|
23
|
-
end
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.update_stack(client, meta, confirm_update)
|
28
|
-
cfargs = CuffSert.as_update_change_set(meta)
|
29
|
-
client.prepare_update(cfargs)
|
30
|
-
.last
|
31
|
-
.flat_map do |change_set|
|
32
|
-
Rx::Observable.concat(
|
33
|
-
Rx::Observable.of(change_set),
|
34
|
-
Rx::Observable.defer {
|
35
|
-
if change_set[:status] == 'FAILED'
|
36
|
-
client.abort_update(change_set[:change_set_id])
|
37
|
-
elsif confirm_update.call(meta, :update, change_set)
|
38
|
-
client.update_stack(change_set[:stack_id], change_set[:change_set_id])
|
39
|
-
else
|
40
|
-
Rx::Observable.concat(
|
41
|
-
client.abort_update(change_set[:change_set_id]),
|
42
|
-
Abort.new('User abort!').as_observable
|
43
|
-
)
|
44
|
-
end
|
45
|
-
}
|
46
|
-
)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.recreate_stack(client, stack, meta, confirm_recreate)
|
51
|
-
crt_args = CuffSert.as_create_stack_args(meta)
|
52
|
-
del_args = CuffSert.as_delete_stack_args(stack)
|
53
|
-
Rx::Observable.concat(
|
54
|
-
Rx::Observable.of([:recreate, stack]),
|
55
|
-
Rx::Observable.defer do
|
56
|
-
if confirm_recreate.call(meta, :recreate, stack)
|
57
|
-
Rx::Observable.concat(
|
58
|
-
client.delete_stack(del_args),
|
59
|
-
client.create_stack(crt_args)
|
60
|
-
)
|
61
|
-
else
|
62
|
-
CuffSert::Abort.new('User abort!').as_observable
|
63
|
-
end
|
64
|
-
end
|
65
|
-
)
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.execute(meta, confirm_update, force_replace: false, client: RxCFClient.new)
|
69
|
-
sources = []
|
70
|
-
found = client.find_stack_blocking(meta)
|
14
|
+
def self.determine_action(meta, cfclient, force_replace: false)
|
15
|
+
found = cfclient.find_stack_blocking(meta)
|
71
16
|
|
72
17
|
if found && INPROGRESS_STATES.include?(found[:stack_status])
|
73
|
-
|
74
|
-
elsif found.nil?
|
75
|
-
sources << self.create_stack(client, meta, confirm_update)
|
76
|
-
elsif found[:stack_status] == 'ROLLBACK_COMPLETE' || force_replace
|
77
|
-
sources << self.recreate_stack(client, found, meta, confirm_update)
|
18
|
+
action = Abort.new('Stack operation already in progress')
|
78
19
|
else
|
79
|
-
|
20
|
+
if found.nil?
|
21
|
+
action = CreateStackAction.new(meta, nil)
|
22
|
+
elsif found[:stack_status] == 'ROLLBACK_COMPLETE' || force_replace
|
23
|
+
action = RecreateStackAction.new(meta, found)
|
24
|
+
else
|
25
|
+
action = UpdateStackAction.new(meta, found)
|
26
|
+
end
|
27
|
+
yield action
|
80
28
|
end
|
81
|
-
|
29
|
+
action
|
82
30
|
end
|
83
31
|
|
84
32
|
def self.make_renderer(cli_args)
|
@@ -93,9 +41,13 @@ module CuffSert
|
|
93
41
|
cli_args = CuffSert.parse_cli_args(argv)
|
94
42
|
CuffSert.validate_cli_args(cli_args)
|
95
43
|
meta = CuffSert.build_meta(cli_args)
|
96
|
-
|
97
|
-
|
44
|
+
cfclient = RxCFClient.new(cli_args)
|
45
|
+
action = CuffSert.determine_action(meta, cfclient, force_replace: cli_args[:force_replace]) do |a|
|
46
|
+
a.confirmation = CuffSert.method(:confirmation)
|
47
|
+
a.s3client = RxS3Client.new(cli_args) if cli_args[:s3_upload_prefix]
|
48
|
+
a.cfclient = cfclient
|
49
|
+
end
|
98
50
|
renderer = CuffSert.make_renderer(cli_args)
|
99
|
-
RendererPresenter.new(
|
51
|
+
RendererPresenter.new(action.as_observable, renderer)
|
100
52
|
end
|
101
53
|
end
|
data/lib/cuffsert/messages.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module CuffSert
|
2
|
-
class
|
2
|
+
class Message
|
3
3
|
attr_reader :message
|
4
4
|
|
5
5
|
def initialize(message)
|
@@ -8,11 +8,19 @@ module CuffSert
|
|
8
8
|
|
9
9
|
def ===(other)
|
10
10
|
# For the benefit of value_matches? and regex
|
11
|
-
other.is_a?(
|
11
|
+
other.is_a?(self.class) && (other.message === @message || @message === other.message)
|
12
12
|
end
|
13
13
|
|
14
14
|
def as_observable
|
15
15
|
Rx::Observable.just(self)
|
16
16
|
end
|
17
17
|
end
|
18
|
+
|
19
|
+
class Abort < Message ; end
|
20
|
+
class Report < Message ; end
|
21
|
+
class Done < Message
|
22
|
+
def initialize
|
23
|
+
super('Done.')
|
24
|
+
end
|
25
|
+
end
|
18
26
|
end
|
data/lib/cuffsert/metadata.rb
CHANGED
@@ -82,7 +82,11 @@ module CuffSert
|
|
82
82
|
private_class_method
|
83
83
|
|
84
84
|
def self.meta_defaults(cli_args)
|
85
|
-
|
85
|
+
if File.exists?(cli_args[:stack_path][0])
|
86
|
+
nil_params = CuffBase.empty_from_template(open(cli_args[:stack_path][0]))
|
87
|
+
else
|
88
|
+
nil_params = {}
|
89
|
+
end
|
86
90
|
default = StackConfig.new
|
87
91
|
default.update_from({:parameters => nil_params})
|
88
92
|
default.suffix = File.basename(cli_args[:metadata], '.yml') if cli_args[:metadata]
|
data/lib/cuffsert/presenters.rb
CHANGED
@@ -5,7 +5,6 @@ require 'cuffsert/messages'
|
|
5
5
|
require 'rx'
|
6
6
|
|
7
7
|
# TODO: Animate in-progress states
|
8
|
-
# - Introduce a Done message and stop printing in on_complete
|
9
8
|
# - Present the error message in change_set properly - and abort
|
10
9
|
# - badness goes to stderr
|
11
10
|
# - change sets should present modification details indented under each entry
|
@@ -55,9 +54,6 @@ module CuffSert
|
|
55
54
|
end
|
56
55
|
|
57
56
|
def on_event(event)
|
58
|
-
# Workaround for now
|
59
|
-
event = event.data if event.class == Seahorse::Client::Response
|
60
|
-
|
61
57
|
case event
|
62
58
|
when Aws::CloudFormation::Types::StackEvent
|
63
59
|
on_stack_event(event)
|
@@ -66,15 +62,18 @@ module CuffSert
|
|
66
62
|
# when [:recreate, Aws::CloudFormation::Types::Stack]
|
67
63
|
when Array
|
68
64
|
on_stack(*event)
|
65
|
+
when ::CuffSert::Report
|
66
|
+
@renderer.report(event)
|
69
67
|
when ::CuffSert::Abort
|
70
68
|
@renderer.abort(event)
|
69
|
+
when ::CuffSert::Done
|
70
|
+
@renderer.done(event)
|
71
71
|
else
|
72
72
|
puts event
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
76
|
def on_complete
|
77
|
-
@renderer.done
|
78
77
|
end
|
79
78
|
|
80
79
|
private
|
@@ -139,8 +138,9 @@ module CuffSert
|
|
139
138
|
def event(event, resource) ; end
|
140
139
|
def clear ; end
|
141
140
|
def resource(resource) ; end
|
141
|
+
def report(message) ; end
|
142
142
|
def abort(message) ; end
|
143
|
-
def done ; end
|
143
|
+
def done(event) ; end
|
144
144
|
end
|
145
145
|
|
146
146
|
class JsonRenderer < BaseRenderer
|
@@ -156,6 +156,10 @@ module CuffSert
|
|
156
156
|
@output.write(stack.to_json) unless @verbosity < 1
|
157
157
|
end
|
158
158
|
|
159
|
+
def report(event)
|
160
|
+
@output.write(event.message + "\n") unless @verbosity < 2
|
161
|
+
end
|
162
|
+
|
159
163
|
def abort(event)
|
160
164
|
@error.write(event.message + "\n") unless @verbosity < 1
|
161
165
|
end
|
@@ -279,12 +283,16 @@ module CuffSert
|
|
279
283
|
))
|
280
284
|
end
|
281
285
|
|
286
|
+
def report(event)
|
287
|
+
@output.write(event.message.colorize(:white) + "\n") unless @verbosity < 2
|
288
|
+
end
|
289
|
+
|
282
290
|
def abort(event)
|
283
291
|
@error.write(event.message.colorize(:red) + "\n") unless @verbosity < 1
|
284
292
|
end
|
285
293
|
|
286
|
-
def done
|
287
|
-
@output.write(
|
294
|
+
def done(event)
|
295
|
+
@output.write(event.message.colorize(:green) + "\n") unless @verbosity < 1
|
288
296
|
end
|
289
297
|
|
290
298
|
private
|
data/lib/cuffsert/rxcfclient.rb
CHANGED
@@ -4,13 +4,12 @@ require 'rx'
|
|
4
4
|
|
5
5
|
module CuffSert
|
6
6
|
class RxCFClient
|
7
|
-
def initialize(
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@pause = pause
|
7
|
+
def initialize(cli_args, **options)
|
8
|
+
initargs = {retry_limit: 8}
|
9
|
+
initargs[:region] = cli_args[:aws_region] if cli_args[:aws_region]
|
10
|
+
@cf = options[:aws_cf] || Aws::CloudFormation::Client.new(initargs)
|
11
|
+
@max_items = options[:max_items] || 1000
|
12
|
+
@pause = options[:pause] || 5
|
14
13
|
end
|
15
14
|
|
16
15
|
def find_stack_blocking(meta)
|
@@ -36,8 +35,10 @@ module CuffSert
|
|
36
35
|
change_set_id = @cf.create_change_set(cfargs)[:id]
|
37
36
|
loop do
|
38
37
|
change_set = @cf.describe_change_set(change_set_name: change_set_id)
|
39
|
-
|
40
|
-
|
38
|
+
if FINAL_STATES.include?(change_set.data[:status])
|
39
|
+
observer.on_next(change_set.data)
|
40
|
+
break
|
41
|
+
end
|
41
42
|
end
|
42
43
|
observer.on_completed
|
43
44
|
end
|
@@ -53,7 +54,7 @@ module CuffSert
|
|
53
54
|
observer.on_completed
|
54
55
|
end
|
55
56
|
end
|
56
|
-
|
57
|
+
|
57
58
|
def abort_update(change_set_id)
|
58
59
|
Rx::Observable.create do |observer|
|
59
60
|
@cf.delete_change_set(change_set_name: change_set_id)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'aws-sdk-s3'
|
2
|
+
require 'rx'
|
3
|
+
|
4
|
+
module CuffSert
|
5
|
+
class RxS3Client
|
6
|
+
def initialize(cli_args, client: nil)
|
7
|
+
@bucket, @path_prefix = split_prefix(cli_args[:s3_upload_prefix])
|
8
|
+
initargs = {retry_limit: 8}
|
9
|
+
initargs[:region] = cli_args[:aws_region] if cli_args[:aws_region]
|
10
|
+
@client = client || Aws::S3::Client.new(initargs)
|
11
|
+
end
|
12
|
+
|
13
|
+
def upload(stack_uri)
|
14
|
+
file = stack_uri.to_s.sub(/^file:\/+/, '/')
|
15
|
+
name = File.basename(file)
|
16
|
+
s3_uri = "s3://#{@bucket}/#{@path_prefix}#{name}"
|
17
|
+
observable = Rx::Observable.create do |observer|
|
18
|
+
body = open(file).read
|
19
|
+
begin
|
20
|
+
observer.on_next(Report.new("Uploading template to #{s3_uri}"))
|
21
|
+
@client.put_object({
|
22
|
+
body: body,
|
23
|
+
bucket: @bucket,
|
24
|
+
key: "#{@path_prefix}#{name}"
|
25
|
+
})
|
26
|
+
observer.on_completed
|
27
|
+
rescue => e
|
28
|
+
observer.on_error(e)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
[URI(s3_uri), observable]
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def split_prefix(s3_upload_prefix)
|
37
|
+
m = s3_upload_prefix.match(/^s3:\/\/([-a-z0-9]+)(\/?.*)$/)
|
38
|
+
bucket = m[1]
|
39
|
+
prefix = m[2].sub(/^\//, '')
|
40
|
+
prefix += '/' unless prefix.empty? || prefix.end_with?('/')
|
41
|
+
[bucket, prefix]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/cuffsert/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuffsert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anders Qvist
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-cloudformation
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.3.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk-s3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.8.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.8.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: colorize
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,14 +128,14 @@ dependencies:
|
|
114
128
|
requirements:
|
115
129
|
- - ~>
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
131
|
+
version: 0.4.3
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
136
|
- - ~>
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
138
|
+
version: 0.4.3
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: simplecov
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,6 +173,7 @@ files:
|
|
159
173
|
- bin/cuffup
|
160
174
|
- cuffsert.gemspec
|
161
175
|
- lib/cuffbase.rb
|
176
|
+
- lib/cuffsert/actions.rb
|
162
177
|
- lib/cuffsert/cfarguments.rb
|
163
178
|
- lib/cuffsert/cfstates.rb
|
164
179
|
- lib/cuffsert/cli_args.rb
|
@@ -168,6 +183,7 @@ files:
|
|
168
183
|
- lib/cuffsert/metadata.rb
|
169
184
|
- lib/cuffsert/presenters.rb
|
170
185
|
- lib/cuffsert/rxcfclient.rb
|
186
|
+
- lib/cuffsert/rxs3client.rb
|
171
187
|
- lib/cuffsert/version.rb
|
172
188
|
- lib/cuffup.rb
|
173
189
|
homepage: https://github.com/bittrance/cuffsert
|