cfn-status 0.2.0 → 0.3.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
  SHA256:
3
- metadata.gz: 20ff184a75d8e49d8a510a06a1840b5038b93e9e365a41c37504d8af708fec55
4
- data.tar.gz: ee4a201d624daeeccd161ff42cbc3e5fdd83510dde35ac54f624a35543ce95de
3
+ metadata.gz: db0db619c3720d0b8aa596db7f48638b88ad4866b110647cba6af9bdef8a083b
4
+ data.tar.gz: f911ca63d21c025da730f3b96065982698d0e2f4b2321a01d74c4ce854a0095e
5
5
  SHA512:
6
- metadata.gz: 62c536dfe7039ec34fc868bcf758afb40e94de5dc3c0b7f103e397b242147e1601076009995c9c3176a6de3aae47aea3b58abe7ef531c79964a1a63840b49540
7
- data.tar.gz: 5320aa2e9668ccd173b3fdc9d991b0c909d29438529e6e8f03714ceb5d808d35d98a39cdc7f299eb39dd134fddfca413b09a0160f4fe8dbf89c7c986f7dd3b99
6
+ metadata.gz: 506a3a5fda2b73a8a33e5aac2afb7e94dcbf63a6d90e4e3dad7bee7f1e182360b559db97b5c721a2282e0ec199e12d0f615c8dd2483e6c1b3b1a99a1cd8cf3f0
7
+ data.tar.gz: 38991d9cdf18ea678061a4c0e60297b236a912cc208a49fc58ffad339d94864da229b92c25e649e7a290dc33c8590af37a8a6f2056bc00f2d94e9cca0e5574bb
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ Gemfile.lock
@@ -1,7 +1,11 @@
1
1
  # Change Log
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
- This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
4
+ This project *loosely* adheres to [Semantic Versioning](http://semver.org/), even before v1.0.
5
+
6
+ ## [0.3.0]
7
+ - #1 Breaking change: rename Rename to CfnStatus, cfn/status to cfn_status
8
+ - Handle large templates and long stack_events via paginating the cfn.describe_stack_events until
5
9
 
6
10
  ## [0.2.0]
7
11
  - allow require "cfn-status" to work also
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Cfn Status
2
2
 
3
+ [![BoltOps Badge](https://img.boltops.com/boltops/badges/boltops-badge.png)](https://www.boltops.com)
4
+
3
5
  Helper library provides status of CloudFormation stack.
4
6
 
5
7
  ## Usage
@@ -13,13 +15,13 @@ Add this line to your gem's gemspec:
13
15
  Require it to your library:
14
16
 
15
17
  ```ruby
16
- require "cfn/status"
18
+ require "cfn_status"
17
19
  ```
18
20
 
19
21
  Use like so:
20
22
 
21
23
  ```ruby
22
- status = Cfn::Status.new(stack_name)
24
+ status = CfnStatus.new(stack_name)
23
25
  status.run # prints out stack events
24
26
  ```
25
27
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "bundler/setup"
4
- require "cfn/status"
4
+ require "cfn_status"
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -1,11 +1,11 @@
1
1
 
2
2
  lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "cfn/status/version"
4
+ require "cfn_status/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "cfn-status"
8
- spec.version = Cfn::Status::VERSION
8
+ spec.version = CfnStatus::VERSION
9
9
  spec.authors = ["Tung Nguyen"]
10
10
  spec.email = ["tongueroo@gmail.com"]
11
11
 
@@ -1 +1 @@
1
- require "cfn/status"
1
+ require "cfn_status"
@@ -0,0 +1,245 @@
1
+ require "cfn_status/version"
2
+
3
+ class CfnStatus
4
+ class Error < StandardError; end
5
+
6
+ autoload :AwsService, "cfn_status/aws_service"
7
+ include AwsService
8
+
9
+ attr_reader :events
10
+ def initialize(stack_name, options={})
11
+ @stack_name = stack_name
12
+ @options = options
13
+ reset
14
+ end
15
+
16
+ def run
17
+ unless stack_exists?(@stack_name)
18
+ puts "The stack #{@stack_name.color(:green)} does not exist."
19
+ return true
20
+ end
21
+
22
+ resp = cfn.describe_stacks(stack_name: @stack_name)
23
+ stack = resp.stacks.first
24
+
25
+ puts "The current status for the stack #{@stack_name.color(:green)} is #{stack.stack_status.color(:green)}"
26
+ if stack.stack_status =~ /_IN_PROGRESS$/
27
+ puts "Stack events (tailing):"
28
+ # tail all events until done
29
+ @hide_time_took = true
30
+ wait
31
+ else
32
+ puts "Stack events:"
33
+ # show the last events that was user initiated
34
+ refresh_events
35
+ show_events(final: true)
36
+ end
37
+ success?
38
+ end
39
+
40
+ def reset
41
+ @events = [] # constantly replaced with recent events
42
+ @last_shown_event_id = nil
43
+ @stack_deletion_completed = nil
44
+ end
45
+
46
+ # check for /(_COMPLETE|_FAILED)$/ status
47
+ def wait
48
+ puts "Waiting for stack to complete"
49
+ start_time = Time.now
50
+
51
+ refresh_events
52
+ until completed || @stack_deletion_completed
53
+ show_events(final: false)
54
+ end
55
+ show_events(final: true) # show the final event
56
+
57
+ if @stack_deletion_completed
58
+ puts "Stack #{@stack_name} deleted."
59
+ return
60
+ end
61
+
62
+ # Never gets beyond here when deleting a stack because the describe stack returns nothing
63
+ # once the stack is deleted. Gets here for stack create and update though.
64
+
65
+ if last_event_status =~ /_FAILED/
66
+ puts "Stack failed: #{last_event_status}".color(:red)
67
+ puts "Stack reason #{@events[0]["resource_status_reason"]}".color(:red)
68
+ elsif last_event_status =~ /_ROLLBACK_/
69
+ puts "Stack rolled back: #{last_event_status}".color(:red)
70
+ else # success
71
+ puts "Stack success status: #{last_event_status}".color(:green)
72
+ end
73
+
74
+ return if @hide_time_took # set in run
75
+ took = Time.now - start_time
76
+ puts "Time took for stack deployment: #{pretty_time(took).color(:green)}."
77
+ success?
78
+ end
79
+
80
+ def completed
81
+ last_event_status =~ /(_COMPLETE|_FAILED)$/ &&
82
+ @events[0]["logical_resource_id"] == @stack_name &&
83
+ @events[0]["resource_type"] == "AWS::CloudFormation::Stack"
84
+ end
85
+
86
+ def last_event_status
87
+ @events.dig(0, "resource_status")
88
+ end
89
+
90
+ # Only shows new events
91
+ def show_events(final: false)
92
+ if @last_shown_event_id.nil?
93
+ i = start_index
94
+ print_events(i)
95
+ else
96
+ i = last_shown_index
97
+ # puts "last_shown index #{i}"
98
+ print_events(i-1) unless i == 0
99
+ end
100
+
101
+ return if final
102
+ sleep 5 unless ENV['TEST']
103
+ refresh_events
104
+ end
105
+
106
+ def print_events(i)
107
+ @events[0..i].reverse.each do |e|
108
+ print_event(e)
109
+ end
110
+
111
+ @last_shown_event_id = @events[0]["event_id"]
112
+ # puts "@last_shown_event_id #{@last_shown_event_id.inspect}"
113
+ end
114
+
115
+ def print_event(e)
116
+ message = [
117
+ event_time(e["timestamp"]),
118
+ e["resource_status"],
119
+ e["resource_type"],
120
+ e["logical_resource_id"],
121
+ e["resource_status_reason"]
122
+ ].join(" ")
123
+ message = message.color(:red) if e["resource_status"] =~ /_FAILED/
124
+ puts message
125
+ end
126
+
127
+ # https://stackoverflow.com/questions/18000432/rails-12-hour-am-pm-range-for-a-day
128
+ def event_time(timestamp)
129
+ Time.parse(timestamp.to_s).localtime.strftime("%I:%M:%S%p")
130
+ end
131
+
132
+ # Refreshes the @events in memory.
133
+ #
134
+ def refresh_events
135
+ resp = cfn.describe_stack_events(stack_name: @stack_name)
136
+ @events = resp["stack_events"]
137
+
138
+ # refresh_events uses add_events_pages and resp["next_token"] to load all events until:
139
+ #
140
+ # 1. @last_shown_event_id found - if @last_shown_event_id is set
141
+ # 2. User Initiated Event found - fallback when @last_shown_event_id is not set
142
+ #
143
+ if @last_shown_event_id
144
+ add_events_pages(resp, :last_shown_index)
145
+ else
146
+ add_events_pages(resp, :start_index)
147
+ end
148
+
149
+ rescue Aws::CloudFormation::Errors::ValidationError => e
150
+ if e.message =~ /Stack .* does not exis/
151
+ @stack_deletion_completed = true
152
+ else
153
+ raise
154
+ end
155
+ end
156
+
157
+ # Examples:
158
+ #
159
+ # add_events_pages(:start_index)
160
+ # add_events_pages(:last_shown_index)
161
+ #
162
+ # if index_method is start_index
163
+ # loops add_events_pagess through describe_stack_events until "User Initiated" is found
164
+ #
165
+ # if index_method is last_shown_index
166
+ # loops add_events_pagess through describe_stack_events until last_shown_index is found
167
+ #
168
+ def add_events_pages(resp, index_method)
169
+ found = !!send(index_method)
170
+ until found
171
+ resp = cfn.describe_stack_events(stack_name: @stack_name, next_token: resp["next_token"])
172
+ @events += resp["stack_events"]
173
+ found = !!send(index_method)
174
+ end
175
+ end
176
+
177
+ # Should always find a "User Initiated" stack event when @last_shown_index is not set
178
+ def start_index
179
+ @events.find_index do |event|
180
+ event["resource_type"] == "AWS::CloudFormation::Stack" &&
181
+ event["resource_status_reason"] == "User Initiated"
182
+ end
183
+ end
184
+
185
+ def last_shown_index
186
+ @events.find_index do |event|
187
+ event["event_id"] == @last_shown_event_id
188
+ end
189
+ end
190
+
191
+ def success?
192
+ resource_status = @events[0]["resource_status"]
193
+ %w[CREATE_COMPLETE UPDATE_COMPLETE].include?(resource_status)
194
+ end
195
+
196
+ def update_rollback?
197
+ @events[0]["resource_status"] == "UPDATE_ROLLBACK_COMPLETE"
198
+ end
199
+
200
+ def find_update_failed_event
201
+ i = @events.find_index do |event|
202
+ event["resource_type"] == "AWS::CloudFormation::Stack" &&
203
+ event["resource_status_reason"] == "User Initiated"
204
+ end
205
+
206
+ @events[0..i].reverse.find do |e|
207
+ e["resource_status"] == "UPDATE_FAILED"
208
+ end
209
+ end
210
+
211
+ def rollback_error_message
212
+ return unless update_rollback?
213
+
214
+ event = find_update_failed_event
215
+ return unless event
216
+
217
+ reason = event["resource_status_reason"]
218
+ messages_map.each do |pattern, message|
219
+ if reason =~ pattern
220
+ return message
221
+ end
222
+ end
223
+
224
+ reason # default message is original reason if not found in messages map
225
+ end
226
+
227
+ def messages_map
228
+ {
229
+ /CloudFormation cannot update a stack when a custom-named resource requires replacing/ => "A workaround is to run ufo again with STATIC_NAME=0 and to switch to dynamic names for resources. Then run ufo again with STATIC_NAME=1 to get back to statically name resources. Note, there are caveats with the workaround.",
230
+ /cannot be associated with more than one load balancer/ => "There's was an issue updating the stack. Target groups can only be associated with one load balancer at a time. The workaround for this is to use UFO_FORCE_TARGET_GROUP=1 and run the command again. This will force the recreation of the target group resource.",
231
+ /SetSubnets is not supported for load balancers of type/ => "Changing subnets for Network Load Balancers is currently not supported. You can try workarouding this with UFO_FORCE_ELB=1 and run the command again. This will force the recreation of the elb resource."
232
+ }
233
+ end
234
+
235
+ # http://stackoverflow.com/questions/4175733/convert-duration-to-hoursminutesseconds-or-similar-in-rails-3-or-ruby
236
+ def pretty_time(total_seconds)
237
+ minutes = (total_seconds / 60) % 60
238
+ seconds = total_seconds % 60
239
+ if total_seconds < 60
240
+ "#{seconds.to_i}s"
241
+ else
242
+ "#{minutes.to_i}m #{seconds.to_i}s"
243
+ end
244
+ end
245
+ end
@@ -1,6 +1,6 @@
1
1
  require "aws-sdk-cloudformation"
2
2
 
3
- module Cfn
3
+ class CfnStatus
4
4
  module AwsService
5
5
  def cfn
6
6
  @cfn ||= Aws::CloudFormation::Client.new
@@ -45,7 +45,7 @@ module Cfn
45
45
  end
46
46
 
47
47
  def rollback_complete?(stack)
48
- stack.stack_status == 'ROLLBACK_COMPLETE'
48
+ stack&.stack_status == 'ROLLBACK_COMPLETE'
49
49
  end
50
50
  end
51
51
  end
@@ -0,0 +1,3 @@
1
+ class CfnStatus
2
+ VERSION = "0.3.0"
3
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfn-status
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-30 00:00:00.000000000 Z
11
+ date: 2020-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-cloudformation
@@ -78,7 +78,6 @@ files:
78
78
  - ".travis.yml"
79
79
  - CHANGELOG.md
80
80
  - Gemfile
81
- - Gemfile.lock
82
81
  - LICENSE.txt
83
82
  - README.md
84
83
  - Rakefile
@@ -86,9 +85,9 @@ files:
86
85
  - bin/setup
87
86
  - cfn-status.gemspec
88
87
  - lib/cfn-status.rb
89
- - lib/cfn/aws_service.rb
90
- - lib/cfn/status.rb
91
- - lib/cfn/status/version.rb
88
+ - lib/cfn_status.rb
89
+ - lib/cfn_status/aws_service.rb
90
+ - lib/cfn_status/version.rb
92
91
  homepage: https://github.com/tongueroo/cfn-status
93
92
  licenses:
94
93
  - MIT
@@ -108,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
107
  - !ruby/object:Gem::Version
109
108
  version: '0'
110
109
  requirements: []
111
- rubygems_version: 3.0.3
110
+ rubygems_version: 3.1.2
112
111
  signing_key:
113
112
  specification_version: 4
114
113
  summary: CloudFormation status library
@@ -1,49 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- cfn-status (0.1.0)
5
- aws-sdk-cloudformation
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- aws-eventstream (1.0.3)
11
- aws-partitions (1.170.0)
12
- aws-sdk-cloudformation (1.22.0)
13
- aws-sdk-core (~> 3, >= 3.53.0)
14
- aws-sigv4 (~> 1.1)
15
- aws-sdk-core (3.54.1)
16
- aws-eventstream (~> 1.0, >= 1.0.2)
17
- aws-partitions (~> 1.0)
18
- aws-sigv4 (~> 1.1)
19
- jmespath (~> 1.0)
20
- aws-sigv4 (1.1.0)
21
- aws-eventstream (~> 1.0, >= 1.0.2)
22
- diff-lcs (1.3)
23
- jmespath (1.4.0)
24
- rake (10.5.0)
25
- rspec (3.8.0)
26
- rspec-core (~> 3.8.0)
27
- rspec-expectations (~> 3.8.0)
28
- rspec-mocks (~> 3.8.0)
29
- rspec-core (3.8.0)
30
- rspec-support (~> 3.8.0)
31
- rspec-expectations (3.8.3)
32
- diff-lcs (>= 1.2.0, < 2.0)
33
- rspec-support (~> 3.8.0)
34
- rspec-mocks (3.8.0)
35
- diff-lcs (>= 1.2.0, < 2.0)
36
- rspec-support (~> 3.8.0)
37
- rspec-support (3.8.0)
38
-
39
- PLATFORMS
40
- ruby
41
-
42
- DEPENDENCIES
43
- bundler (~> 2.0)
44
- cfn-status!
45
- rake (~> 10.0)
46
- rspec (~> 3.0)
47
-
48
- BUNDLED WITH
49
- 2.0.1
@@ -1,219 +0,0 @@
1
- require "cfn/status/version"
2
-
3
- module Cfn
4
- autoload :AwsService, "cfn/aws_service"
5
-
6
- class Status
7
- class Error < StandardError; end
8
-
9
- include AwsService
10
-
11
- attr_reader :events
12
- def initialize(stack_name, options={})
13
- @stack_name = stack_name
14
- @options = options
15
- reset
16
- end
17
-
18
- def run
19
- unless stack_exists?(@stack_name)
20
- puts "The stack #{@stack_name.color(:green)} does not exist."
21
- return true
22
- end
23
-
24
- resp = cfn.describe_stacks(stack_name: @stack_name)
25
- stack = resp.stacks.first
26
-
27
- puts "The current status for the stack #{@stack_name.color(:green)} is #{stack.stack_status.color(:green)}"
28
- if stack.stack_status =~ /_IN_PROGRESS$/
29
- puts "Stack events (tailing):"
30
- # tail all events until done
31
- @hide_time_took = true
32
- wait
33
- else
34
- puts "Stack events:"
35
- # show the last events that was user initiated
36
- refresh_events
37
- show_events(true)
38
- end
39
- success?
40
- end
41
-
42
- def reset
43
- @events = [] # constantly replaced with recent events
44
- @last_shown_event_id = nil
45
- @stack_deletion_completed = nil
46
- end
47
-
48
- # check for /(_COMPLETE|_FAILED)$/ status
49
- def wait
50
- puts "Waiting for stack to complete"
51
- start_time = Time.now
52
-
53
- refresh_events
54
- until completed || @stack_deletion_completed
55
- show_events
56
- end
57
- show_events(true) # show the final event
58
-
59
- if @stack_deletion_completed
60
- puts "Stack #{@stack_name} deleted."
61
- return
62
- end
63
-
64
- if last_event_status =~ /_FAILED/
65
- puts "Stack failed: #{last_event_status}".color(:red)
66
- puts "Stack reason #{@events[0]["resource_status_reason"]}".color(:red)
67
- elsif last_event_status =~ /_ROLLBACK_/
68
- puts "Stack rolled back: #{last_event_status}".color(:red)
69
- else # success
70
- puts "Stack success status: #{last_event_status}".color(:green)
71
- end
72
-
73
- # Never gets here when deleting a stack because the describe stack returns nothing
74
- # once the stack is deleted. Gets here for stack create and update though.
75
- return if @hide_time_took # set in run
76
- took = Time.now - start_time
77
- puts "Time took for stack deployment: #{pretty_time(took).color(:green)}."
78
- success?
79
- end
80
-
81
- def completed
82
- last_event_status =~ /(_COMPLETE|_FAILED)$/ &&
83
- @events[0]["logical_resource_id"] == @stack_name &&
84
- @events[0]["resource_type"] == "AWS::CloudFormation::Stack"
85
- end
86
-
87
- def last_event_status
88
- @events[0]["resource_status"]
89
- end
90
-
91
- # Only shows new events
92
- def show_events(final=false)
93
- if @last_shown_event_id.nil?
94
- i = find_index(:start, final)
95
- print_events(i)
96
- else
97
- i = find_index(:last_shown, final)
98
- # puts "last_shown index #{i}"
99
- print_events(i-1) unless i == 0
100
- end
101
-
102
- return if final
103
- sleep 5 unless ENV['TEST']
104
- refresh_events
105
- end
106
-
107
- def print_events(i)
108
- @events[0..i].reverse.each do |e|
109
- print_event(e)
110
- end
111
- @last_shown_event_id = @events[0]["event_id"]
112
- # puts "@last_shown_event_id #{@last_shown_event_id.inspect}"
113
- end
114
-
115
- def print_event(e)
116
- message = [
117
- event_time(e["timestamp"]),
118
- e["resource_status"],
119
- e["resource_type"],
120
- e["logical_resource_id"],
121
- e["resource_status_reason"]
122
- ].join(" ")
123
- message = message.color(:red) if e["resource_status"] =~ /_FAILED/
124
- puts message
125
- end
126
-
127
- # https://stackoverflow.com/questions/18000432/rails-12-hour-am-pm-range-for-a-day
128
- def event_time(timestamp)
129
- Time.parse(timestamp.to_s).localtime.strftime("%I:%M:%S%p")
130
- end
131
-
132
- # refreshes the loaded events in memory
133
- def refresh_events
134
- resp = cfn.describe_stack_events(stack_name: @stack_name)
135
- @events = resp["stack_events"]
136
- rescue Aws::CloudFormation::Errors::ValidationError => e
137
- if e.message =~ /Stack .* does not exis/
138
- @stack_deletion_completed = true
139
- else
140
- raise
141
- end
142
- end
143
-
144
- def find_index(name, final=false)
145
- send("#{name}_index", final)
146
- end
147
-
148
- def start_index(final=false)
149
- index = @events.find_index do |event|
150
- event["resource_type"] == "AWS::CloudFormation::Stack" &&
151
- event["resource_status_reason"] == "User Initiated"
152
- end
153
- # Instead of paginating until until we find the first "User Initiated" "AWS::CloudFormation::Stack" event
154
- # we'll use the max.
155
- index ? index : @events.size - 1
156
- end
157
-
158
- def last_shown_index(_)
159
- @events.find_index do |event|
160
- event["event_id"] == @last_shown_event_id
161
- end
162
- end
163
-
164
- def success?
165
- resource_status = @events[0]["resource_status"]
166
- %w[CREATE_COMPLETE UPDATE_COMPLETE].include?(resource_status)
167
- end
168
-
169
- def update_rollback?
170
- @events[0]["resource_status"] == "UPDATE_ROLLBACK_COMPLETE"
171
- end
172
-
173
- def find_update_failed_event
174
- i = @events.find_index do |event|
175
- event["resource_type"] == "AWS::CloudFormation::Stack" &&
176
- event["resource_status_reason"] == "User Initiated"
177
- end
178
-
179
- @events[0..i].reverse.find do |e|
180
- e["resource_status"] == "UPDATE_FAILED"
181
- end
182
- end
183
-
184
- def rollback_error_message
185
- return unless update_rollback?
186
-
187
- event = find_update_failed_event
188
- return unless event
189
-
190
- reason = event["resource_status_reason"]
191
- messages_map.each do |pattern, message|
192
- if reason =~ pattern
193
- return message
194
- end
195
- end
196
-
197
- reason # default message is original reason if not found in messages map
198
- end
199
-
200
- def messages_map
201
- {
202
- /CloudFormation cannot update a stack when a custom-named resource requires replacing/ => "A workaround is to run ufo again with STATIC_NAME=0 and to switch to dynamic names for resources. Then run ufo again with STATIC_NAME=1 to get back to statically name resources. Note, there are caveats with the workaround.",
203
- /cannot be associated with more than one load balancer/ => "There's was an issue updating the stack. Target groups can only be associated with one load balancer at a time. The workaround for this is to use UFO_FORCE_TARGET_GROUP=1 and run the command again. This will force the recreation of the target group resource.",
204
- /SetSubnets is not supported for load balancers of type/ => "Changing subnets for Network Load Balancers is currently not supported. You can try workarouding this with UFO_FORCE_ELB=1 and run the command again. This will force the recreation of the elb resource."
205
- }
206
- end
207
-
208
- # http://stackoverflow.com/questions/4175733/convert-duration-to-hoursminutesseconds-or-similar-in-rails-3-or-ruby
209
- def pretty_time(total_seconds)
210
- minutes = (total_seconds / 60) % 60
211
- seconds = total_seconds % 60
212
- if total_seconds < 60
213
- "#{seconds.to_i}s"
214
- else
215
- "#{minutes.to_i}m #{seconds.to_i}s"
216
- end
217
- end
218
- end
219
- end
@@ -1,5 +0,0 @@
1
- module Cfn
2
- class Status
3
- VERSION = "0.2.0"
4
- end
5
- end