cuffsert 0.11.0 → 0.12.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: 1be8dd08dce49cf000289c1a1e198026bf48e2c5
4
- data.tar.gz: 3e0846cd94c5273d1ef260105b962c3c3196d6cc
3
+ metadata.gz: 5e2a534e878fbb69920af515d5829138351c4937
4
+ data.tar.gz: 9697ef60c78c97f5823f089d8efd67f95723a411
5
5
  SHA512:
6
- metadata.gz: 75340fd814849e4c1f42f6ec007eac89d20d2f925b599cdaf9ad32e489638ac00808a9879e2361f8c5d5833a2082b3b0f3992f90e2c061d8efa0f3e7ad6e4e3a
7
- data.tar.gz: 92da57f24fb3c7443462404602d22b9a28c615ecd258e648e4bf22640e3441224e48465266f766ffc930b0a639a885e2ba674de7109e602e457d647431c150fa
6
+ metadata.gz: 37643076b4d503a37ac1d12f997c27230a90904386157fcad1b4a668b126b886091f775e4244c9442d62f027e0b40fac9b7cc94e6c5b60c219563cc46da6690d
7
+ data.tar.gz: 46a6d4ba65176322eb3da8c3abb4fe5641ba0157d7885670410849b324880b5090b4c457251d6fed61feb2230e75a1e2e0126d2c49685b22ed28fc327ad702cc
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cuffsert (0.11.0)
4
+ cuffsert (0.12.0)
5
5
  aws-sdk-cloudformation (~> 1.3.0)
6
6
  aws-sdk-s3 (~> 1.8.0)
7
7
  colorize
data/README.md CHANGED
@@ -14,7 +14,11 @@ If `./my-template.json` has no parameters the above command would create the sta
14
14
 
15
15
  If you also want to provide a value for a stack parameter (whether on creation or update), you can use `-p key=value` to pass parameters. For all other parameters, cuffsert will tell CloudFormation to use the existing value.
16
16
 
17
- Cuffsert can not (yet) be executed without a template in order to only change parameters.
17
+ Cuffsert can also be executed by naming an existing stack and no template in order to only change parameters, e.g.
18
+
19
+ ```bash
20
+ cuffsert -n my-stack -p MyDesiredCapacity=8
21
+ ```
18
22
 
19
23
  ## Parameters under version control
20
24
 
data/bin/cuffdown CHANGED
@@ -1,55 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'cuffsert/metadata'
4
- require 'cuffsert/rxcfclient'
5
- require 'yaml'
3
+ require 'cuffdown/main'
6
4
 
7
- module CuffDown
8
- def self.parameters(stack)
9
- (stack[:parameters] || []).map do |param|
10
- {
11
- 'Name' => param[:parameter_key],
12
- 'Value' => param[:parameter_value],
13
- }
14
- end
15
- end
16
-
17
- def self.tags(stack)
18
- (stack[:tags] || []).map do |param|
19
- {
20
- 'Name' => param[:key],
21
- 'Value' => param[:value],
22
- }
23
- end
24
- end
25
-
26
- def self.dump(name, params, tags, output)
27
- result = {
28
- 'Format' => 'v1',
29
- 'Suffix' => name,
30
- 'Parameters' => params,
31
- 'Tags' => tags,
32
- }
33
- YAML.dump(result, output)
34
- end
35
-
36
- def self.run(args)
37
- meta = CuffSert::StackConfig.new
38
- meta.stackname = args[0]
39
- client = CuffSert::RxCFClient.new
40
- stack = client.find_stack_blocking(meta)
41
- unless stack
42
- STDERR.puts "No such stack #{meta.stackname}"
43
- exit(1)
44
- end
45
- stack = stack.to_h
46
- self.dump(
47
- stack[:stack_name],
48
- self.parameters(stack),
49
- self.tags(stack),
50
- STDOUT
51
- )
52
- end
53
- end
54
-
55
- CuffDown.run(ARGV)
5
+ CuffDown.run(ARGV, STDOUT)
data/lib/cuffbase.rb CHANGED
@@ -1,6 +1,12 @@
1
1
  require 'yaml'
2
2
 
3
3
  module CuffBase
4
+ def self.shared_cli_args(opts, args)
5
+ opts.on('--region=aws_region', 'AWS region, overrides env variable AWS_REGION') do |region|
6
+ args[:aws_region] = region
7
+ end
8
+ end
9
+
4
10
  def self.empty_from_template(io)
5
11
  self.template_parameters(io) {|_| nil }
6
12
  end
@@ -0,0 +1,67 @@
1
+ require 'cuffbase'
2
+ require 'cuffsert/metadata'
3
+ require 'cuffsert/rxcfclient'
4
+ require 'optparse'
5
+ require 'yaml'
6
+
7
+ module CuffDown
8
+ def self.parse_cli_args(argv)
9
+ args = {}
10
+ parser = OptionParser.new do |opts|
11
+ opts.banner = 'Output CuffSert-formatted metadata from an existing stack.'
12
+ opts.separator('')
13
+ opts.separator('Usage: cuffdown stack-name')
14
+ CuffBase.shared_cli_args(opts, args)
15
+ end
16
+ stackname, _ = parser.parse(argv)
17
+ args[:stackname] = stackname
18
+ args
19
+ end
20
+
21
+ def self.parameters(stack)
22
+ (stack[:parameters] || []).map do |param|
23
+ {
24
+ 'Name' => param[:parameter_key],
25
+ 'Value' => param[:parameter_value],
26
+ }
27
+ end
28
+ end
29
+
30
+ def self.tags(stack)
31
+ (stack[:tags] || []).map do |param|
32
+ {
33
+ 'Name' => param[:key],
34
+ 'Value' => param[:value],
35
+ }
36
+ end
37
+ end
38
+
39
+ def self.dump(name, params, tags, output)
40
+ result = {
41
+ 'Format' => 'v1',
42
+ 'Suffix' => name,
43
+ 'Parameters' => params,
44
+ 'Tags' => tags,
45
+ }
46
+ YAML.dump(result, output)
47
+ end
48
+
49
+ def self.run(argv, output)
50
+ cli_args = self.parse_cli_args(argv)
51
+ meta = CuffSert::StackConfig.new
52
+ meta.stackname = cli_args[:stackname]
53
+ client = CuffSert::RxCFClient.new(cli_args[:aws_region])
54
+ stack = client.find_stack_blocking(meta)
55
+ unless stack
56
+ STDERR.puts "No such stack #{meta.stackname}"
57
+ exit(1)
58
+ end
59
+ stack = stack.to_h
60
+ self.dump(
61
+ stack[:stack_name],
62
+ self.parameters(stack),
63
+ self.tags(stack),
64
+ output
65
+ )
66
+ end
67
+ end
@@ -16,17 +16,31 @@ module CuffSert
16
16
  end
17
17
 
18
18
  def upload_template_if_oversized(cfargs)
19
- if cfargs[:template_body].nil? && cfargs[:template_url].nil?
19
+ if needs_template_upload?(cfargs)
20
20
  raise 'Template bigger than 51200; please supply --s3-upload-prefix' unless @s3client
21
21
  uri, progress = @s3client.upload(@meta.stack_uri)
22
- [CuffSert.s3_uri_to_https(uri).to_s, progress]
22
+ [CuffSert.s3_uri_to_https(uri, @meta.aws_region).to_s, progress]
23
23
  else
24
24
  [nil, Rx::Observable.empty]
25
25
  end
26
26
  end
27
+
28
+ private
29
+
30
+ def needs_template_upload?(cfargs)
31
+ cfargs[:template_body].nil? &&
32
+ cfargs[:template_url].nil? &&
33
+ !cfargs[:use_previous_template]
34
+ end
27
35
  end
28
36
 
29
37
  class CreateStackAction < BaseAction
38
+ def validate!
39
+ if @meta.stack_uri.nil?
40
+ raise "You need to pass a template to create #{@meta.stackname}" # in #{@meta.aws_region}."
41
+ end
42
+ end
43
+
30
44
  def as_observable
31
45
  cfargs = CuffSert.as_create_stack_args(@meta)
32
46
  upload_uri, maybe_upload = upload_template_if_oversized(cfargs)
@@ -48,43 +62,61 @@ module CuffSert
48
62
  end
49
63
 
50
64
  class UpdateStackAction < BaseAction
65
+ def validate!
66
+ if @meta.stack_uri.nil?
67
+ if @meta.parameters.empty? && @meta.tags.empty?
68
+ raise "Stack update without template needs at least one parameter (-p) or tag (-t)."
69
+ end
70
+ end
71
+ end
72
+
51
73
  def as_observable
52
- cfargs = CuffSert.as_update_change_set(@meta)
74
+ cfargs = CuffSert.as_update_change_set(@meta, @stack)
53
75
  upload_uri, maybe_upload = upload_template_if_oversized(cfargs)
54
76
  cfargs[:template_url] = upload_uri if upload_uri
55
77
  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
- )
78
+ .concat(@cfclient.prepare_update(cfargs).map {|change_set| CuffSert::ChangeSet.new(change_set) })
79
+ .flat_map(&method(:on_event))
80
+ end
81
+
82
+ private
83
+
84
+ def on_event(event)
85
+ Rx::Observable.concat(
86
+ Rx::Observable.just(event),
87
+ Rx::Observable.defer do
88
+ case event
89
+ when CuffSert::ChangeSet
90
+ on_changeset(event.message)
80
91
  else
81
- Rx::Observable.just(change_set)
92
+ Rx::Observable.empty
82
93
  end
83
94
  end
95
+ )
96
+ end
97
+
98
+ def on_changeset(change_set)
99
+ if change_set[:status] == 'FAILED'
100
+ message = "Update failed: #{change_set[:status_reason]}"
101
+ @cfclient.abort_update(change_set[:change_set_id])
102
+ .concat(Abort.new(message).as_observable)
103
+ elsif @confirmation.call(@meta, :update, change_set)
104
+ @cfclient.update_stack(change_set[:stack_id], change_set[:change_set_id])
105
+ .concat(Done.new.as_observable)
106
+ else
107
+ @cfclient.abort_update(change_set[:change_set_id])
108
+ .concat(Abort.new('User abort!').as_observable)
109
+ end
84
110
  end
85
111
  end
86
112
 
87
113
  class RecreateStackAction < BaseAction
114
+ def validate!
115
+ if @meta.stack_uri.nil?
116
+ raise "You need to pass a template to re-create #{@meta.stackname}" # in #{@meta.aws_region}."
117
+ end
118
+ end
119
+
88
120
  def as_observable
89
121
  crt_args = CuffSert.as_create_stack_args(@meta)
90
122
  del_args = CuffSert.as_delete_stack_args(@stack)
@@ -33,7 +33,10 @@ module CuffSert
33
33
  end
34
34
  end
35
35
 
36
- cfargs.merge!(self.template_parameters(meta))
36
+ if meta.stack_uri
37
+ cfargs.merge!(self.template_parameters(meta))
38
+ end
39
+ cfargs
37
40
  end
38
41
 
39
42
  def self.as_create_stack_args(meta)
@@ -46,11 +49,26 @@ module CuffSert
46
49
  cfargs
47
50
  end
48
51
 
49
- def self.as_update_change_set(meta)
52
+ def self.as_update_change_set(meta, stack)
50
53
  cfargs = self.as_cloudformation_args(meta)
51
- cfargs[:use_previous_template] = false
52
54
  cfargs[:change_set_name] = meta.stackname
53
55
  cfargs[:change_set_type] = 'UPDATE'
56
+ if cfargs[:use_previous_template] = meta.stack_uri.nil?
57
+ Array(stack[:parameters]).each do |param|
58
+ key = param[:parameter_key]
59
+ unless meta.parameters.include?(key)
60
+ cfargs[:parameters] ||= []
61
+ cfargs[:parameters] << {:parameter_key => key, :use_previous_value => true}
62
+ end
63
+ end
64
+ if !meta.tags.empty?
65
+ Array(stack[:tags]).each do |tag|
66
+ unless meta.tags.include?(tag[:key])
67
+ cfargs[:tags] << tag
68
+ end
69
+ end
70
+ end
71
+ end
54
72
  cfargs
55
73
  end
56
74
 
@@ -58,8 +76,7 @@ module CuffSert
58
76
  { :stack_name => stack[:stack_id] }
59
77
  end
60
78
 
61
- def self.s3_uri_to_https(uri)
62
- region = ENV['AWS_REGION'] || ENV['AWS_DEFAULT_REGION'] || 'us-east-1'
79
+ def self.s3_uri_to_https(uri, region)
63
80
  bucket = uri.host
64
81
  key = uri.path
65
82
  host = region == 'us-east-1' ? 's3.amazonaws.com' : "s3-#{region}.amazonaws.com"
@@ -77,7 +94,7 @@ module CuffSert
77
94
  template_parameters = {}
78
95
 
79
96
  if meta.stack_uri.scheme == 's3'
80
- template_parameters[:template_url] = self.s3_uri_to_https(meta.stack_uri)
97
+ template_parameters[:template_url] = self.s3_uri_to_https(meta.stack_uri, meta.aws_region)
81
98
  elsif meta.stack_uri.scheme == 'https'
82
99
  if meta.stack_uri.host.end_with?('amazonaws.com')
83
100
  template_parameters[:template_url] = meta.stack_uri.to_s
@@ -1,4 +1,5 @@
1
1
  require 'optparse'
2
+ require 'cuffbase'
2
3
  require 'cuffsert/version'
3
4
 
4
5
  module CuffSert
@@ -18,7 +19,14 @@ module CuffSert
18
19
  parser = OptionParser.new do |opts|
19
20
  opts.banner = "Upsert a CloudFormation template, reading creation options and metadata from a yaml file. Currently, parameter values, stack name and stack tags are read from metadata file. Version #{CuffSert::VERSION}."
20
21
  opts.separator('')
21
- opts.separator('Usage: cuffsert --selector production/us stack.json')
22
+ opts.separator('Usage:')
23
+ opts.separator(' cuffsert --name <stackname> stack.json')
24
+ opts.separator(' cuffsert --name <stackname> {--parameter Name=Value | --tag Name=Value}... [stack.json]')
25
+ opts.separator(' cuffsert --metadata <metadata.json> --selector <path/in/metadata> stack.json')
26
+ opts.separator(' cuffsert --metadata <metadata.json> --selector <path/in/metadata> {--parameter Name=Value | --tag Name=Value}... [stack.json]')
27
+
28
+ CuffBase.shared_cli_args(opts, args)
29
+
22
30
  opts.on('--metadata path', '-m path', 'Yaml file to read stack metadata from') do |path|
23
31
  path = '/dev/stdin' if path == '-'
24
32
  unless File.exist?(path)
@@ -60,10 +68,6 @@ module CuffSert
60
68
  args[:overrides][:tags][key] = val
61
69
  end
62
70
 
63
- opts.on('--region=aws_region', 'AWS region, overrides env variable AWS_REGION') do |region|
64
- args[:aws_region] = region
65
- end
66
-
67
71
  opts.on('--s3-upload-prefix=prefix', 'Templates > 51200 bytes are uploaded here. Format: s3://bucket-name/[pre/fix]') do |prefix|
68
72
  unless prefix.start_with?('s3://')
69
73
  raise "Upload prefix #{prefix} must start with s3://"
@@ -87,13 +91,18 @@ module CuffSert
87
91
  args[:force_replace] = true
88
92
  end
89
93
 
94
+ opts.on('--ask', 'Always ask for confirmation') do
95
+ raise 'You can only use one of --yes, --ask and --dry-run' if args[:op_mode]
96
+ args[:op_mode] = :always_ask
97
+ end
98
+
90
99
  opts.on('--yes', '-y', 'Don\'t ask to replace and delete stack resources') do
91
- raise 'You cannot do --yes and --dry-run at the same time' if args[:op_mode]
100
+ raise 'You can only use one of --yes, --ask and --dry-run' if args[:op_mode]
92
101
  args[:op_mode] = :dangerous_ok
93
102
  end
94
103
 
95
104
  opts.on('--dry-run', 'Describe what would be done') do
96
- raise 'You cannot do --yes and --dry-run at the same time' if args[:op_mode]
105
+ raise 'You can only use one of --yes, --ask and --dry-run' if args[:op_mode]
97
106
  args[:op_mode] = :dry_run
98
107
  end
99
108
 
@@ -109,21 +118,21 @@ module CuffSert
109
118
  args
110
119
  end
111
120
  end
112
-
121
+
113
122
  def self.validate_cli_args(cli_args)
114
123
  errors = []
115
- if cli_args[:stack_path].nil? || cli_args[:stack_path].size != 1
116
- errors << 'Requires exactly one template'
124
+ if cli_args[:stack_path] != nil && cli_args[:stack_path].size > 1
125
+ errors << 'Require at most one template'
117
126
  end
118
127
 
119
128
  if cli_args[:metadata].nil? && cli_args[:overrides][:stackname].nil?
120
129
  errors << 'Without --metadata, you must supply --name to identify stack to update'
121
130
  end
122
-
131
+
123
132
  if cli_args[:selector] && cli_args[:metadata].nil?
124
133
  errors << 'You cannot use --selector without --metadata'
125
134
  end
126
-
135
+
127
136
  raise errors.join(', ') unless errors.empty?
128
137
  end
129
138
  end
@@ -2,6 +2,7 @@ require 'termios'
2
2
 
3
3
  module CuffSert
4
4
  def self.need_confirmation(meta, action, desc)
5
+ return true if meta.op_mode == :always_ask
5
6
  return false if meta.op_mode == :dangerous_ok
6
7
  case action
7
8
  when :create
data/lib/cuffsert/main.rb CHANGED
@@ -41,12 +41,13 @@ module CuffSert
41
41
  cli_args = CuffSert.parse_cli_args(argv)
42
42
  CuffSert.validate_cli_args(cli_args)
43
43
  meta = CuffSert.build_meta(cli_args)
44
- cfclient = RxCFClient.new(cli_args)
44
+ cfclient = RxCFClient.new(meta.aws_region)
45
45
  action = CuffSert.determine_action(meta, cfclient, force_replace: cli_args[:force_replace]) do |a|
46
46
  a.confirmation = CuffSert.method(:confirmation)
47
- a.s3client = RxS3Client.new(cli_args) if cli_args[:s3_upload_prefix]
47
+ a.s3client = RxS3Client.new(cli_args, meta.aws_region) if cli_args[:s3_upload_prefix]
48
48
  a.cfclient = cfclient
49
49
  end
50
+ action.validate!
50
51
  renderer = CuffSert.make_renderer(cli_args)
51
52
  RendererPresenter.new(action.as_observable, renderer)
52
53
  end
@@ -23,4 +23,5 @@ module CuffSert
23
23
  super('Done.')
24
24
  end
25
25
  end
26
+ class ChangeSet < Message ; end
26
27
  end
@@ -3,10 +3,11 @@ require 'yaml'
3
3
 
4
4
  module CuffSert
5
5
  class StackConfig
6
- attr_accessor :stackname, :selected_path, :op_mode, :stack_uri
6
+ attr_accessor :aws_region, :stackname, :selected_path, :op_mode, :stack_uri
7
7
  attr_accessor :suffix, :parameters, :tags
8
8
 
9
9
  def initialize
10
+ @aws_region = ENV['AWS_REGION'] || ENV['AWS_DEFAULT_REGION'] || 'us-east-1'
10
11
  @selected_path = []
11
12
  @op_mode = :normal
12
13
  @parameters = {}
@@ -57,7 +58,7 @@ module CuffSert
57
58
 
58
59
  def self.meta_for_path(metadata, path, target = StackConfig.new)
59
60
  target.update_from(metadata)
60
- candidate, path = path
61
+ candidate, *path = path
61
62
  key = candidate || metadata[:defaultpath]
62
63
  variants = metadata[:variants]
63
64
  if key.nil?
@@ -82,8 +83,9 @@ module CuffSert
82
83
  private_class_method
83
84
 
84
85
  def self.meta_defaults(cli_args)
85
- if File.exists?(cli_args[:stack_path][0])
86
- nil_params = CuffBase.empty_from_template(open(cli_args[:stack_path][0]))
86
+ stack_path = (cli_args[:stack_path] || [])[0]
87
+ if stack_path && File.exists?(stack_path)
88
+ nil_params = CuffBase.empty_from_template(open(stack_path))
87
89
  else
88
90
  nil_params = {}
89
91
  end
@@ -104,9 +106,11 @@ module CuffSert
104
106
 
105
107
  def self.cli_overrides(meta, cli_args)
106
108
  meta.update_from(cli_args[:overrides])
109
+ meta.aws_region = cli_args[:aws_region] || meta.aws_region
107
110
  meta.op_mode = cli_args[:op_mode] || meta.op_mode
108
- stack_path = cli_args[:stack_path][0]
109
- meta.stack_uri = CuffSert.validate_and_urlify(stack_path)
111
+ if (stack_path = (cli_args[:stack_path] || [])[0])
112
+ meta.stack_uri = CuffSert.validate_and_urlify(stack_path)
113
+ end
110
114
  meta
111
115
  end
112
116
 
@@ -57,8 +57,8 @@ module CuffSert
57
57
  case event
58
58
  when Aws::CloudFormation::Types::StackEvent
59
59
  on_stack_event(event)
60
- when Aws::CloudFormation::Types::DescribeChangeSetOutput
61
- on_change_set(event)
60
+ when ::CuffSert::ChangeSet
61
+ on_change_set(event.message)
62
62
  # when [:recreate, Aws::CloudFormation::Types::Stack]
63
63
  when Array
64
64
  on_stack(*event)
@@ -4,9 +4,9 @@ require 'rx'
4
4
 
5
5
  module CuffSert
6
6
  class RxCFClient
7
- def initialize(cli_args, **options)
7
+ def initialize(aws_region = nil, **options)
8
8
  initargs = {retry_limit: 8}
9
- initargs[:region] = cli_args[:aws_region] if cli_args[:aws_region]
9
+ initargs[:region] = aws_region if aws_region
10
10
  @cf = options[:aws_cf] || Aws::CloudFormation::Client.new(initargs)
11
11
  @max_items = options[:max_items] || 1000
12
12
  @pause = options[:pause] || 5
@@ -3,10 +3,10 @@ require 'rx'
3
3
 
4
4
  module CuffSert
5
5
  class RxS3Client
6
- def initialize(cli_args, client: nil)
6
+ def initialize(cli_args, aws_region = nil, client: nil)
7
7
  @bucket, @path_prefix = split_prefix(cli_args[:s3_upload_prefix])
8
8
  initargs = {retry_limit: 8}
9
- initargs[:region] = cli_args[:aws_region] if cli_args[:aws_region]
9
+ initargs[:region] = aws_region if aws_region
10
10
  @client = client || Aws::S3::Client.new(initargs)
11
11
  end
12
12
 
@@ -1,3 +1,3 @@
1
1
  module CuffSert
2
- VERSION = '0.11.0'
2
+ VERSION = '0.12.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.11.0
4
+ version: 0.12.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: 2018-08-30 00:00:00.000000000 Z
11
+ date: 2018-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-cloudformation
@@ -173,6 +173,7 @@ files:
173
173
  - bin/cuffup
174
174
  - cuffsert.gemspec
175
175
  - lib/cuffbase.rb
176
+ - lib/cuffdown/main.rb
176
177
  - lib/cuffsert/actions.rb
177
178
  - lib/cuffsert/cfarguments.rb
178
179
  - lib/cuffsert/cfstates.rb