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 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