cuffsert 0.10.1 → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ba819164ec3e9ae15f381a2418cc99a72bfe709
4
- data.tar.gz: d8c953a9c481ca2c6f93d1a201052171ad94849c
3
+ metadata.gz: 1be8dd08dce49cf000289c1a1e198026bf48e2c5
4
+ data.tar.gz: 3e0846cd94c5273d1ef260105b962c3c3196d6cc
5
5
  SHA512:
6
- metadata.gz: 2860822ae2a9fb5f4f9259dac8809472c5346fde9ec78e24270c293685c94db2b5236ee2fdcaf91e674e9e797011a29e6f69e61c310f22345a6b404d8971d4ee
7
- data.tar.gz: be0e28c65fa2c900abdb6483a2033a4a7da0792ab0a82e92db597da758253b93fc56a4bf5b4c7b234633a043b88b5f8772faa2c27605e4161bcfa78ed5efd30a
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.10.1)
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-partitions (1.45.0)
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.11.0)
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.3.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.1.3)
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.1.3)
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.1.3'
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
@@ -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
- if meta.stack_uri.scheme == 's3'
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
@@ -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/cfarguments'
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.create_stack(client, meta, confirm_create)
14
- cfargs = CuffSert.as_create_stack_args(meta)
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
- sources << Abort.new('Stack operation already in progress').as_observable
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
- sources << self.update_stack(client, meta, confirm_update)
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
- Rx::Observable.concat(*sources)
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
- events = CuffSert.execute(meta, CuffSert.method(:confirmation),
97
- force_replace: cli_args[:force_replace])
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(events, renderer)
51
+ RendererPresenter.new(action.as_observable, renderer)
100
52
  end
101
53
  end
@@ -1,5 +1,5 @@
1
1
  module CuffSert
2
- class Abort
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?(Abort) && (other.message === @message || @message === other.message)
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
@@ -82,7 +82,11 @@ module CuffSert
82
82
  private_class_method
83
83
 
84
84
  def self.meta_defaults(cli_args)
85
- nil_params = CuffBase.empty_from_template(open(cli_args[:stack_path][0]))
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]
@@ -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("\nDone.\n".colorize(:green)) unless @verbosity < 1
294
+ def done(event)
295
+ @output.write(event.message.colorize(:green) + "\n") unless @verbosity < 1
288
296
  end
289
297
 
290
298
  private
@@ -4,13 +4,12 @@ require 'rx'
4
4
 
5
5
  module CuffSert
6
6
  class RxCFClient
7
- def initialize(
8
- aws_cf = Aws::CloudFormation::Client.new(retry_limit: 8),
9
- pause: 5,
10
- max_items: 1000)
11
- @cf = aws_cf
12
- @max_items = max_items
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
- observer.on_next(change_set)
40
- break if FINAL_STATES.include?(change_set[:status])
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
@@ -1,3 +1,3 @@
1
1
  module CuffSert
2
- VERSION = '0.10.1'
2
+ VERSION = '0.11.0'
3
3
  end
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.10.1
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: 2017-12-06 00:00:00.000000000 Z
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.1.3
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.1.3
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