ufo 6.0.0 → 6.0.3
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 +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/templates/init/.ufo/resources/task_definitions/web.yml +2 -0
- data/lib/ufo/aws_services.rb +6 -0
- data/lib/ufo/cfn/stack/builder/resources/ecs_service.rb +13 -0
- data/lib/ufo/cfn/stack/builder/resources/target_group.rb +15 -0
- data/lib/ufo/cfn/stack/builder.rb +3 -0
- data/lib/ufo/cfn/stack.rb +23 -12
- data/lib/ufo/cli/central/base.rb +12 -0
- data/lib/ufo/cli/central/clean.rb +10 -0
- data/lib/ufo/cli/central/update.rb +62 -28
- data/lib/ufo/cli/central.rb +7 -0
- data/lib/ufo/cli/clean.rb +0 -2
- data/lib/ufo/cli/destroy.rb +1 -1
- data/lib/ufo/cli/help/ship.md +3 -3
- data/lib/ufo/cli/logs.rb +1 -1
- data/lib/ufo/cli/ps/errors.rb +132 -0
- data/lib/ufo/cli/ps/task.rb +14 -9
- data/lib/ufo/cli/ps.rb +20 -46
- data/lib/ufo/cli/scale.rb +9 -2
- data/lib/ufo/cli/stop.rb +1 -1
- data/lib/ufo/cli.rb +2 -1
- data/lib/ufo/config.rb +16 -7
- data/lib/ufo/info.rb +1 -0
- data/lib/ufo/task_definition/erb/yaml.rb +10 -3
- data/lib/ufo/task_definition/erb.rb +5 -0
- data/lib/ufo/task_definition/helpers/acm.rb +18 -0
- data/lib/ufo/task_definition/helpers/ecr.rb +13 -0
- data/lib/ufo/task_definition/helpers/vars.rb +2 -2
- data/lib/ufo/utils/pretty.rb +5 -0
- data/lib/ufo/version.rb +1 -1
- data/lib/ufo/yaml/validator.rb +6 -22
- data/lib/ufo/yaml.rb +4 -0
- data/ufo.gemspec +3 -2
- metadata +25 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ddf01cabd60971596b36544d0e7e91484e935143d83fa1410eb6a5d29e06dff
|
4
|
+
data.tar.gz: 5bc24a9f42c06fb4ee486fbda776c2d8ffe4f7f35b3fce74f3837dfcded1c7b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a0ca12fac2697a82bb8b2930a5d20eef0dba27ac7c9be684a221b271d765fd923fd32f91b5fb5bf7aeafb416a4479e42be770055575451bae5102c0aba64a54
|
7
|
+
data.tar.gz: fd9c668daf4d70bc37f6898ea224578cfd3d47e87aa3d691f903664083fe3fd7083dabb8b279a2082a3283e4fd8a3d83413806a0e6c208e1489362b81041ac6f
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,20 @@
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
4
4
|
This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
|
5
5
|
|
6
|
+
## [6.0.3] - 2022-03-07
|
7
|
+
- [#133](https://github.com/tongueroo/ufo/pull/133) improve ufo central and add helpers
|
8
|
+
|
9
|
+
## [6.0.2] - 2022-03-06
|
10
|
+
- [#128](https://github.com/tongueroo/ufo/pull/128) cleanup region with aws_data
|
11
|
+
- [#129](https://github.com/tongueroo/ufo/pull/129) Scale and Ps Edge Cases
|
12
|
+
- [#130](https://github.com/tongueroo/ufo/pull/130) compiled yaml errors: print code with line number context
|
13
|
+
- [#131](https://github.com/tongueroo/ufo/pull/131) ufo central update symlink creation
|
14
|
+
- [#132](https://github.com/tongueroo/ufo/pull/132) ufo ps improvements better catchall error messages reporting
|
15
|
+
|
16
|
+
## [6.0.1] - 2022-03-05
|
17
|
+
- [#126](https://github.com/tongueroo/ufo/pull/126) ecs deployment_configuration options
|
18
|
+
- [#127](https://github.com/tongueroo/ufo/pull/127) improve ps errors reporting
|
19
|
+
|
6
20
|
## [6.0.0] - 2022-03-05
|
7
21
|
- [#125](https://github.com/tongueroo/ufo/pull/125) v6: major ufo upgrades and new structure
|
8
22
|
|
@@ -16,6 +16,8 @@ containerDefinitions:
|
|
16
16
|
protocol: tcp
|
17
17
|
<% end -%>
|
18
18
|
command: <%= @command.to_json %>
|
19
|
+
linuxParameters:
|
20
|
+
initProcessEnabled: true
|
19
21
|
environment: <%= @environment.to_json if @environment %>
|
20
22
|
secrets: <%= @secrets.to_json if @secrets %>
|
21
23
|
<% if @awslogs_group -%>
|
data/lib/ufo/aws_services.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "aws-sdk-acm"
|
1
2
|
require "aws-sdk-applicationautoscaling"
|
2
3
|
require "aws-sdk-cloudformation"
|
3
4
|
require "aws-sdk-cloudwatchlogs"
|
@@ -14,6 +15,11 @@ module Ufo
|
|
14
15
|
module AwsServices
|
15
16
|
extend Memoist
|
16
17
|
|
18
|
+
def acm
|
19
|
+
Aws::ACM::Client.new(aws_options)
|
20
|
+
end
|
21
|
+
memoize :acm
|
22
|
+
|
17
23
|
def applicationautoscaling
|
18
24
|
Aws::ApplicationAutoScaling::Client.new(aws_options)
|
19
25
|
end
|
@@ -14,6 +14,7 @@ class Ufo::Cfn::Stack::Builder::Resources
|
|
14
14
|
def properties
|
15
15
|
props = {
|
16
16
|
Cluster: @cluster,
|
17
|
+
DeploymentConfiguration: deployment_configuration,
|
17
18
|
DesiredCount: {
|
18
19
|
"Fn::If": [
|
19
20
|
"EcsDesiredCountIsBlank",
|
@@ -68,5 +69,17 @@ class Ufo::Cfn::Stack::Builder::Resources
|
|
68
69
|
|
69
70
|
props
|
70
71
|
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def deployment_configuration
|
75
|
+
ecs = Ufo.config.ecs
|
76
|
+
return ecs.configuration if ecs.configuration # provide user full control
|
77
|
+
|
78
|
+
# default
|
79
|
+
{
|
80
|
+
MaximumPercent: ecs.maximum_percent,
|
81
|
+
MinimumHealthyPercent: ecs.minimum_healthy_percent,
|
82
|
+
}
|
83
|
+
end
|
71
84
|
end
|
72
85
|
end
|
@@ -32,8 +32,23 @@ class Ufo::Cfn::Stack::Builder::Resources
|
|
32
32
|
|
33
33
|
props[:TargetType] = "ip" if vars[:container][:network_mode] == "awsvpc"
|
34
34
|
props[:HealthCheckPort] = vars[:container][:port] if vars[:elb_type] == "network" && vars[:network_mode] == "awsvpc"
|
35
|
+
props[:HealthCheckPath] = health_check_path
|
36
|
+
props[:HealthCheckIntervalSeconds] = health_check_interval_seconds
|
37
|
+
props[:HealthyThresholdCount] = healthy_threshold_count
|
38
|
+
props[:UnhealthyThresholdCount] = unhealthy_threshold_count
|
35
39
|
|
36
40
|
props
|
37
41
|
end
|
42
|
+
|
43
|
+
meths = %w[
|
44
|
+
health_check_interval_seconds
|
45
|
+
health_check_path
|
46
|
+
healthy_threshold_count
|
47
|
+
unhealthy_threshold_count
|
48
|
+
]
|
49
|
+
delegate *meths, to: :elb
|
50
|
+
def elb
|
51
|
+
Ufo.config.elb
|
52
|
+
end
|
38
53
|
end
|
39
54
|
end
|
@@ -24,6 +24,9 @@ class Ufo::Cfn::Stack
|
|
24
24
|
path = ".ufo/output/template.yml"
|
25
25
|
IO.write("#{Ufo.root}/#{path}", text)
|
26
26
|
logger.info "Template built: #{path}"
|
27
|
+
# Only basic YAML validation. Doesnt check for everything CloudFormation checks.
|
28
|
+
# For CloudFormation checks handled with an exception handler in Cfn::Stack#print_code(exception)
|
29
|
+
Ufo::Yaml.validate!(path)
|
27
30
|
text
|
28
31
|
end
|
29
32
|
end
|
data/lib/ufo/cfn/stack.rb
CHANGED
@@ -52,16 +52,7 @@ module Ufo::Cfn
|
|
52
52
|
|
53
53
|
def perform(action)
|
54
54
|
logger.info "#{action[0..-2].capitalize}ing stack #{@stack_name.color(:green)}"
|
55
|
-
# Example: cloudformation.send("update_stack", stack_options)
|
56
|
-
|
57
|
-
# o = stack_options.dup
|
58
|
-
# o[:template_body] = '...' if o[:template_body]
|
59
|
-
# puts "stack_options:"
|
60
|
-
# pp o
|
61
|
-
# puts "parameters:"
|
62
|
-
# pp o[:parameters]
|
63
|
-
|
64
|
-
cloudformation.send("#{action}_stack", stack_options)
|
55
|
+
cloudformation.send("#{action}_stack", stack_options) # Example: cloudformation.send("update_stack", stack_options)
|
65
56
|
rescue Aws::CloudFormation::Errors::ValidationError => e
|
66
57
|
handle_stack_error(e)
|
67
58
|
end
|
@@ -117,7 +108,6 @@ module Ufo::Cfn
|
|
117
108
|
memoize :rollback_task_definition
|
118
109
|
|
119
110
|
def exit_with_message(stack)
|
120
|
-
region = `aws configure get region`.strip rescue "us-east-1"
|
121
111
|
url = "https://console.aws.amazon.com/cloudformation/home?region=#{region}#/stacks"
|
122
112
|
logger.info "The stack is not in an updateable state: #{stack.stack_status.color(:yellow)}."
|
123
113
|
logger.info "Here's the CloudFormation url to check for more details #{url}"
|
@@ -134,13 +124,28 @@ module Ufo::Cfn
|
|
134
124
|
if message.include?('UPDATE_ROLLBACK_FAILED')
|
135
125
|
logger.info "You might be able to do a 'Continue Update Rollback' and skip some resources to get the stack back into a good state."
|
136
126
|
end
|
137
|
-
region = `aws configure get region`.strip rescue 'us-east-1'
|
138
127
|
url = "https://console.aws.amazon.com/cloudformation/home?region=#{region}"
|
139
128
|
logger.info "Here's the CloudFormation console url: #{url}"
|
140
129
|
exit 1
|
141
130
|
when /No updates are to be performed/
|
142
131
|
logger.info "There are no updates to be performed. Exiting.".color(:yellow)
|
143
132
|
exit 1
|
133
|
+
when /YAML not well-formed/ # happens if a value is a serialize Ruby Object. See: https://gist.github.com/tongueroo/737531d0bc8c92d92b5cd00493e15d9e
|
134
|
+
# e.message: Template format error: YAML not well-formed. (line 207, column 9)
|
135
|
+
print_code(e)
|
136
|
+
else
|
137
|
+
raise
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def print_code(exception)
|
142
|
+
path = ".ufo/output/template.yml"
|
143
|
+
md = exception.message.match(/line (\d+),/)
|
144
|
+
line_number = md[1]
|
145
|
+
logger.error "Template for debugging: #{path}"
|
146
|
+
if md
|
147
|
+
DslEvaluator.print_code(path, line_number)
|
148
|
+
exit 1
|
144
149
|
else
|
145
150
|
raise
|
146
151
|
end
|
@@ -171,5 +176,11 @@ module Ufo::Cfn
|
|
171
176
|
logger.info "The stack is not in a state to that is cancelable: #{stack.stack_status}"
|
172
177
|
end
|
173
178
|
end
|
179
|
+
|
180
|
+
delegate :region, to: :aws
|
181
|
+
def aws
|
182
|
+
AwsData.new
|
183
|
+
end
|
184
|
+
memoize :aws
|
174
185
|
end
|
175
186
|
end
|
@@ -1,68 +1,102 @@
|
|
1
1
|
class Ufo::CLI::Central
|
2
|
-
class Update
|
3
|
-
include Ufo::Utils::Logging
|
4
|
-
include Ufo::Utils::Execute
|
5
|
-
include Ufo::Utils::Sure
|
6
|
-
|
7
|
-
def initialize(options={})
|
8
|
-
@options = options
|
9
|
-
end
|
10
|
-
|
2
|
+
class Update < Base
|
11
3
|
def run
|
12
|
-
action = File.exist?(".ufo") ? "update" : "create"
|
13
|
-
sure?("Will #{action} the .ufo folder.") # IE: Will create the .ufo folder.
|
14
4
|
validate!
|
15
|
-
|
5
|
+
action = File.exist?(".ufo") ? "update" : "create"
|
6
|
+
sure?("Will #{action} the .ufo symlink") # IE: Will create the .ufo symlink
|
7
|
+
logger.info "Updating .ufo with #{central_repo}"
|
16
8
|
FileUtils.mkdir_p(tmp_area)
|
17
9
|
pull
|
18
|
-
|
10
|
+
symlink
|
19
11
|
check_gitignore
|
20
12
|
end
|
21
13
|
|
22
14
|
def pull
|
23
15
|
logger.debug "Within #{tmp_area}"
|
24
16
|
Dir.chdir(tmp_area) do
|
25
|
-
if File.exist?(
|
26
|
-
execute "cd #{
|
17
|
+
if File.exist?(repo)
|
18
|
+
execute "cd #{repo} && git pull"
|
27
19
|
else
|
28
|
-
execute "git clone #{
|
20
|
+
execute "git clone #{central_repo}"
|
29
21
|
end
|
30
22
|
end
|
31
23
|
end
|
32
24
|
|
33
|
-
|
34
|
-
|
35
|
-
src = "#{tmp_area}/#{
|
36
|
-
src += "/#{
|
37
|
-
|
25
|
+
# Always update the symlink in case use changes UFO_CENTRAL_REPO
|
26
|
+
def symlink
|
27
|
+
src = "#{tmp_area}/#{repo}"
|
28
|
+
src += "/#{central_folder}" if central_folder
|
29
|
+
|
30
|
+
FileUtils.mv(".ufo", ".ufo.bak") if File.exist?(".ufo") && File.directory?(".ufo")
|
31
|
+
|
32
|
+
# FileUtils.ln_s(target, link, options)
|
33
|
+
# ~/.ufo/central/repo -> .ufo
|
34
|
+
FileUtils.ln_sf(src, ".ufo", verbose: false) # force in case of existing broken symlink
|
38
35
|
FileUtils.rm_rf(".ufo.bak")
|
39
|
-
|
36
|
+
|
37
|
+
report_broken_symlink
|
38
|
+
|
39
|
+
logger.info "The .ufo symlink has been updated"
|
40
|
+
logger.info "Symlink: .ufo -> #{pretty_home(src)}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def report_broken_symlink
|
44
|
+
return unless File.symlink?('.ufo')
|
45
|
+
|
46
|
+
message =<<~EOL.color(:red)
|
47
|
+
ERROR: The .ufo symlink appears to pointing to a missing folder.
|
48
|
+
Please double check that the folder exist in the repo/
|
49
|
+
EOL
|
50
|
+
begin
|
51
|
+
target = File.readlink('.ufo')
|
52
|
+
unless File.exist?(target)
|
53
|
+
logger.error message
|
54
|
+
logger.error "Symlink: .ufo -> #{target}"
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
rescue Errno::EEXIST
|
58
|
+
logger.error message
|
59
|
+
exit 1
|
60
|
+
end
|
40
61
|
end
|
41
62
|
|
42
63
|
def validate!
|
43
|
-
return if
|
64
|
+
return if central_repo
|
44
65
|
logger.info "ERROR: Please set the env var: UFO_CENTRAL_REPO".color(:red)
|
66
|
+
logger.info "The ufo central update command requires it."
|
45
67
|
exit 1
|
46
68
|
end
|
47
69
|
|
48
|
-
|
49
|
-
|
70
|
+
# Assume github.com:org/repo. May not work for private "ssh://host:repo" style repos
|
71
|
+
# See: https://terraspace.cloud/docs/terrafile/sources/ssh/
|
72
|
+
# Will consider PRs.
|
73
|
+
#
|
74
|
+
# org is used for path to ~/.ufo/central/org/repo
|
75
|
+
#
|
76
|
+
def org
|
77
|
+
base = central_repo.split('/')[-2] # 1. git@github.com:org/repo 2. repo (for case of https://github.com/org/repo)
|
78
|
+
base.gsub!(/.*:/,'') # git@github.com:org/repo => org/repo
|
79
|
+
base
|
50
80
|
end
|
51
81
|
|
52
82
|
def repo
|
83
|
+
File.basename(central_repo)
|
84
|
+
end
|
85
|
+
|
86
|
+
def central_repo
|
53
87
|
ENV['UFO_CENTRAL_REPO']
|
54
88
|
end
|
55
89
|
|
56
|
-
def
|
90
|
+
def central_folder
|
57
91
|
ENV['UFO_CENTRAL_FOLDER']
|
58
92
|
end
|
59
93
|
|
60
94
|
def tmp_area
|
61
|
-
"
|
95
|
+
"#{ENV['HOME']}/.ufo/central/#{org}"
|
62
96
|
end
|
63
97
|
|
64
98
|
def check_gitignore
|
65
|
-
ok =
|
99
|
+
ok = false
|
66
100
|
if File.exist?('.gitignore')
|
67
101
|
lines = IO.readlines('.gitignore')
|
68
102
|
ok = lines.detect do |line|
|
data/lib/ufo/cli/central.rb
CHANGED
data/lib/ufo/cli/clean.rb
CHANGED
data/lib/ufo/cli/destroy.rb
CHANGED
data/lib/ufo/cli/help/ship.md
CHANGED
@@ -17,10 +17,10 @@ Confirm to ship:
|
|
17
17
|
|
18
18
|
Will deploy stack demo-web-dev (y/N) y
|
19
19
|
Building Docker Image
|
20
|
-
=> docker build -t
|
21
|
-
Docker Image built:
|
20
|
+
=> docker build -t 111111111111.dkr.ecr.us-west-2.amazonaws.com/demo:ufo-2022-03-02T20-32-33-12dc6e0 -f Dockerfile .
|
21
|
+
Docker Image built: 111111111111.dkr.ecr.us-west-2.amazonaws.com/demo:ufo-2022-03-02T20-32-33-12dc6e0
|
22
22
|
Pushing Docker Image
|
23
|
-
=> docker push
|
23
|
+
=> docker push 111111111111.dkr.ecr.us-west-2.amazonaws.com/demo:ufo-2022-03-02T20-32-33-12dc6e0
|
24
24
|
Task Definition built: .ufo/output/task_definition.json
|
25
25
|
Parameters built: .ufo/output/params.json
|
26
26
|
Template built: .ufo/output/template.yml
|
data/lib/ufo/cli/logs.rb
CHANGED
@@ -0,0 +1,132 @@
|
|
1
|
+
class Ufo::CLI::Ps
|
2
|
+
class Errors < Ufo::CLI::Ps
|
3
|
+
extend Memoist
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
super
|
7
|
+
@tasks = options[:tasks]
|
8
|
+
end
|
9
|
+
|
10
|
+
def show
|
11
|
+
message = recent_message
|
12
|
+
return unless message
|
13
|
+
return if message =~ /has reached a steady state/
|
14
|
+
|
15
|
+
scale
|
16
|
+
target_group
|
17
|
+
deployment_configuration
|
18
|
+
catchall
|
19
|
+
end
|
20
|
+
|
21
|
+
# If running count < desired account for a long time
|
22
|
+
# And see was unable to place a task
|
23
|
+
# Probably not enough capacity
|
24
|
+
def scale
|
25
|
+
return if service.running_count >= service.desired_count
|
26
|
+
|
27
|
+
error_event = recent_events.find do |e|
|
28
|
+
e.message =~ /was unable to place a task/
|
29
|
+
end
|
30
|
+
return unless error_event
|
31
|
+
|
32
|
+
logger.info "There is an issue scaling the #{@stack_name.color(:green)} service to #{service.desired_count}. Here's the error:"
|
33
|
+
logger.info error_event.message.color(:red)
|
34
|
+
if service.launch_type == "EC2"
|
35
|
+
logger.info <<~EOL
|
36
|
+
If AutoScaling is set up for the container instances,
|
37
|
+
it can take a little time to add additional instances.
|
38
|
+
You'll see this message until the capacity is added.
|
39
|
+
EOL
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# The error currently happens to be the 5th element.
|
44
|
+
#
|
45
|
+
# Example:
|
46
|
+
# (service XXX) (instance i-XXX) (port 32875) is unhealthy in (target-group arn:aws:elasticloadbalancing:us-east-1:111111111111:targetgroup/devel-Targe-1111111111111/1111111111111111) due to (reason Health checks failed with these codes: [400])">]
|
47
|
+
def target_group
|
48
|
+
error_event = recent_events.find do |e|
|
49
|
+
e.message =~ /is unhealthy in/ &&
|
50
|
+
e.message =~ /targetgroup/
|
51
|
+
end
|
52
|
+
return unless error_event
|
53
|
+
|
54
|
+
logger.error "There are targets in the target group reporting unhealthy. This can cause containers to cycle. Here's the error:"
|
55
|
+
logger.error error_event.message.color(:red)
|
56
|
+
logger.error <<~EOL
|
57
|
+
Check out the ECS console and EC2 Load Balancer console for more info.
|
58
|
+
Sometimes they may not helpful :(
|
59
|
+
Docs that may help: https://ufoships.com/docs/debug/unhealthy-targets/
|
60
|
+
EOL
|
61
|
+
end
|
62
|
+
|
63
|
+
# To reproduce
|
64
|
+
#
|
65
|
+
# .ufo/config.rb
|
66
|
+
#
|
67
|
+
# Ufo.configure do |config|
|
68
|
+
# config.ecs.maximum_percent = 150 # need at least 200 to go from 1 to 2 containers
|
69
|
+
# config.ecs.minimum_healthy_percent = 100
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# Event message error:
|
73
|
+
#
|
74
|
+
# ERROR: (service app1-web-dev-EcsService-8FMliG8m6M2p) was unable to stop or start tasks during a deployment because of the service deployment configuration. Update the minimumHealthyPercent or maximumPercent value and try again.
|
75
|
+
#
|
76
|
+
def deployment_configuration
|
77
|
+
message = recent_message
|
78
|
+
return unless message.include?("unable") && message.include?("deployment configuration")
|
79
|
+
|
80
|
+
logger.error "ERROR: Deployment Configuration".color(:red)
|
81
|
+
logger.error <<~EOL
|
82
|
+
You might have a Deployment Configuration that prevents the deployment from completing.
|
83
|
+
|
84
|
+
See: https://ufoships.com/docs/debug/deployment-configuration/
|
85
|
+
|
86
|
+
EOL
|
87
|
+
end
|
88
|
+
|
89
|
+
# Example:
|
90
|
+
# (service app1-web-dev-EcsService-8FMliG8m6M2p) was unable to stop or start tasks during a deployment because of the service deployment configuration. Update the minimumHealthyPercent or maximumPercent value and try again.
|
91
|
+
def catchall
|
92
|
+
words = %w[fail unable error]
|
93
|
+
recent_messages = recent_events.map(&:message)
|
94
|
+
message = recent_messages.find do |message|
|
95
|
+
words.detect { |word| message.include?(word) }
|
96
|
+
end
|
97
|
+
|
98
|
+
return unless message
|
99
|
+
logger.error "ERROR: #{message}".color(:red)
|
100
|
+
|
101
|
+
logger.error <<~EOL
|
102
|
+
You might have to #{cancel_actions[:cfn]} the stack with:
|
103
|
+
|
104
|
+
ufo #{cancel_actions[:ufo]}
|
105
|
+
|
106
|
+
And try again after fixing the issue.
|
107
|
+
EOL
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
def cancel_actions
|
112
|
+
stack = find_stack(@stack_name)
|
113
|
+
if stack && stack.stack_status == "CREATE_COMPLETE"
|
114
|
+
{ cfn: "delete", ufo: "destroy" }
|
115
|
+
else
|
116
|
+
{ cfn: "cancel", ufo: "cancel" }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
memoize :cancel_actions
|
120
|
+
|
121
|
+
# only check a few most recent
|
122
|
+
def recent_events
|
123
|
+
service["events"][0..4]
|
124
|
+
end
|
125
|
+
|
126
|
+
def recent_message
|
127
|
+
recent = recent_events.first
|
128
|
+
return unless recent
|
129
|
+
recent.message ? recent.message : nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/lib/ufo/cli/ps/task.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
class Ufo::CLI::Ps
|
2
|
-
class Task
|
3
|
-
def
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(task)
|
8
|
-
@task = task
|
2
|
+
class Task < Ufo::CLI::Base
|
3
|
+
def initialize(options={})
|
4
|
+
super
|
5
|
+
@task = options[:task] # task response from ecs.list_tasks
|
9
6
|
end
|
10
7
|
|
11
8
|
def to_a
|
@@ -52,9 +49,11 @@ class Ufo::CLI::Ps
|
|
52
49
|
# stopping_at=2018-07-05 22:03:44 -0700,
|
53
50
|
# stopped_at=2018-07-05 22:03:45 -0700,
|
54
51
|
def hide?
|
55
|
-
|
52
|
+
return false if @options[:status] == "stopped"
|
53
|
+
started_at = time(@task["started_at"])
|
54
|
+
return false unless started_at # edge case when started_at not yet set
|
56
55
|
time = Time.now - 60 * Ufo.config.ps.hide_age
|
57
|
-
status == "STOPPED" &&
|
56
|
+
status == "STOPPED" && started_at < time
|
58
57
|
end
|
59
58
|
|
60
59
|
def status
|
@@ -92,5 +91,11 @@ class Ufo::CLI::Ps
|
|
92
91
|
start_time.strftime("%m/%d/%Y")
|
93
92
|
end
|
94
93
|
end
|
94
|
+
|
95
|
+
class << self
|
96
|
+
def header
|
97
|
+
%w[Task Name Release Started Status Notes]
|
98
|
+
end
|
99
|
+
end
|
95
100
|
end
|
96
101
|
end
|
data/lib/ufo/cli/ps.rb
CHANGED
@@ -9,7 +9,12 @@ class Ufo::CLI
|
|
9
9
|
|
10
10
|
def run
|
11
11
|
unless service
|
12
|
-
|
12
|
+
stack = find_stack(@stack_name)
|
13
|
+
if stack && stack.stack_status == "CREATE_IN_PROGRESS"
|
14
|
+
logger.info "Stack is still creating. Try again after it completes."
|
15
|
+
else
|
16
|
+
logger.info info.no_service_message
|
17
|
+
end
|
13
18
|
return
|
14
19
|
end
|
15
20
|
|
@@ -25,9 +30,8 @@ class Ufo::CLI
|
|
25
30
|
resp["tasks"]
|
26
31
|
end.flatten
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
display_target_group_help
|
33
|
+
tasks = show_tasks(all_task_arns)
|
34
|
+
show_errors(tasks)
|
31
35
|
end
|
32
36
|
|
33
37
|
def summary
|
@@ -63,50 +67,14 @@ class Ufo::CLI
|
|
63
67
|
resp.scalable_targets.first # scalable_target
|
64
68
|
end
|
65
69
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
# The error currently happens to be the 5th element.
|
71
|
-
#
|
72
|
-
# Example:
|
73
|
-
# "(service XXX) (instance i-XXX) (port 32875) is unhealthy in (target-group arn:aws:elasticloadbalancing:us-east-1:111111111111:targetgroup/devel-Targe-1111111111111/1111111111111111) due to (reason Health checks failed with these codes: [400])">]
|
74
|
-
error_event = events.find do |e|
|
75
|
-
e.message =~ /is unhealthy in/ &&
|
76
|
-
e.message =~ /targetgroup/
|
77
|
-
end
|
78
|
-
return unless error_event
|
79
|
-
|
80
|
-
logger.error "There are targets in the target group reporting unhealthy. This can cause containers to cycle. Here's the error:"
|
81
|
-
logger.error error_event.message.color(:red)
|
82
|
-
logger.error <<~EOL
|
83
|
-
Check out the ECS console and EC2 Load Balancer console for more info.
|
84
|
-
Sometimes they may not helpful :(
|
85
|
-
Docs that may help: https://ufoships.com/docs/debug/unhealthy-targets/
|
86
|
-
EOL
|
87
|
-
end
|
88
|
-
|
89
|
-
# If the running count less than the desired account yet, check the events
|
90
|
-
# and show a message with helpful debugging information.
|
91
|
-
def display_scale_help
|
92
|
-
return if service.running_count >= service.desired_count
|
93
|
-
|
94
|
-
events = service["events"][0..3] # only check most recent 4 messages
|
95
|
-
error_event = events.find do |e|
|
96
|
-
e.message =~ /was unable to place a task/
|
97
|
-
end
|
98
|
-
return unless error_event
|
99
|
-
|
100
|
-
logger.info "There is an issue scaling the #{@service.color(:green)} service to #{service.desired_count}. Here's the error:"
|
101
|
-
logger.info error_event.message.color(:red)
|
102
|
-
if service.launch_type == "EC2"
|
103
|
-
logger.info "If AutoScaling is set up for the container instances, it can take a little time to add additional instances. You'll see this message until the capacity is added."
|
104
|
-
end
|
70
|
+
def convert_to_task_objects(task_arns)
|
71
|
+
task_arns.sort_by! { |t| t["task_arn"] }
|
72
|
+
task_arns.map { |t| Task.new(@options.merge(task: t)) } # will have Task objects after this point
|
105
73
|
end
|
106
74
|
|
107
|
-
|
108
|
-
|
109
|
-
tasks =
|
75
|
+
# Note: ufo stop also uses Ps#show_tasks. Thats why convert_to_task_objects within the method
|
76
|
+
def show_tasks(tasks_arns)
|
77
|
+
tasks = convert_to_task_objects(tasks_arns)
|
110
78
|
tasks = tasks.reject(&:hide?)
|
111
79
|
show_notes = show_notes(tasks)
|
112
80
|
|
@@ -122,8 +90,14 @@ class Ufo::CLI
|
|
122
90
|
presenter.rows << row
|
123
91
|
end
|
124
92
|
presenter.show
|
93
|
+
tasks
|
94
|
+
end
|
95
|
+
|
96
|
+
def show_errors(tasks)
|
97
|
+
Errors.new(@options.merge(tasks: tasks)).show
|
125
98
|
end
|
126
99
|
|
100
|
+
private
|
127
101
|
def show_notes(tasks)
|
128
102
|
tasks.detect { |t| !t.notes.blank? }
|
129
103
|
end
|
data/lib/ufo/cli/scale.rb
CHANGED
@@ -45,6 +45,11 @@ class Ufo::CLI
|
|
45
45
|
scalable_target = stack_resources.find do |r|
|
46
46
|
r.logical_resource_id == "ScalingTarget"
|
47
47
|
end
|
48
|
+
register_scalable_target(scalable_target)
|
49
|
+
logger.info "Configured autoscaling to min: #{@min} max: #{@max}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def register_scalable_target(scalable_target)
|
48
53
|
# service/dev/app1-web-dev-EcsService-Q0XkN6VtxGWv|ecs:service:DesiredCount|ecs
|
49
54
|
resource_id, scalable_dimension, service_namespace = scalable_target.physical_resource_id.split('|')
|
50
55
|
applicationautoscaling.register_scalable_target(
|
@@ -54,7 +59,9 @@ class Ufo::CLI
|
|
54
59
|
scalable_dimension: scalable_dimension,
|
55
60
|
service_namespace: service_namespace,
|
56
61
|
)
|
57
|
-
|
62
|
+
rescue Aws::ApplicationAutoScaling::Errors::ValidationException => e
|
63
|
+
logger.error "ERROR: #{e.class} #{e.message}".color(:red)
|
64
|
+
exit 1
|
58
65
|
end
|
59
66
|
|
60
67
|
def warning
|
@@ -68,7 +75,7 @@ class Ufo::CLI
|
|
68
75
|
|
69
76
|
You can also turn off this warning with
|
70
77
|
|
71
|
-
config.
|
78
|
+
config.scale.warning = false
|
72
79
|
|
73
80
|
EOL
|
74
81
|
end
|
data/lib/ufo/cli/stop.rb
CHANGED
data/lib/ufo/cli.rb
CHANGED
@@ -85,7 +85,8 @@ module Ufo
|
|
85
85
|
long_desc Help.text(:ps)
|
86
86
|
option :status, default: "all", desc: "Status filter: all, pending, stopped, running."
|
87
87
|
# not setting format default so we can use Ufo.config.ps.format and dont want to trigger a config load this early
|
88
|
-
|
88
|
+
formats = CliFormat.formats + ["auto"]
|
89
|
+
option :format, desc: "Output formats: #{formats.sort.join(', ')}"
|
89
90
|
def ps
|
90
91
|
Ps.new(options).run
|
91
92
|
end
|
data/lib/ufo/config.rb
CHANGED
@@ -49,24 +49,33 @@ module Ufo
|
|
49
49
|
|
50
50
|
config.ecs = ActiveSupport::OrderedOptions.new
|
51
51
|
config.ecs.cluster = ":ENV" # => dev
|
52
|
+
config.ecs.deployment_configuration = nil # full control
|
52
53
|
config.ecs.desired_count = nil # only respected when config.autoscaling.enabled = false
|
54
|
+
config.ecs.maximum_percent = 200 # nil
|
55
|
+
config.ecs.minimum_healthy_percent = 100 # nil
|
53
56
|
config.ecs.scheduling_strategy = "REPLICA"
|
54
57
|
|
55
58
|
config.elb = ActiveSupport::OrderedOptions.new
|
56
|
-
config.elb.
|
59
|
+
config.elb.default_actions = nil # full override
|
57
60
|
config.elb.enabled = "auto" # "auto", true or false
|
61
|
+
|
62
|
+
config.elb.health_check_interval_seconds = 10
|
63
|
+
config.elb.health_check_path = nil # When nil its AWS default /
|
64
|
+
config.elb.healthy_threshold_count = 5
|
65
|
+
config.elb.unhealthy_threshold_count = 2
|
66
|
+
|
58
67
|
config.elb.port = 80 # default listener port
|
59
|
-
config.elb.ssl = ActiveSupport::OrderedOptions.new
|
60
|
-
config.elb.ssl.certificates = nil
|
61
|
-
config.elb.ssl.enabled = false
|
62
|
-
config.elb.ssl.port = 443
|
63
|
-
config.elb.type = "application"
|
64
|
-
config.elb.default_actions = nil # full override
|
65
68
|
config.elb.redirect = ActiveSupport::OrderedOptions.new
|
66
69
|
config.elb.redirect.code = 302 # IE: 302 or 301
|
67
70
|
config.elb.redirect.enabled = false
|
68
71
|
config.elb.redirect.port = 443
|
69
72
|
config.elb.redirect.protocol = "HTTPS"
|
73
|
+
config.elb.ssl = ActiveSupport::OrderedOptions.new
|
74
|
+
config.elb.ssl.certificates = nil
|
75
|
+
config.elb.ssl.enabled = false
|
76
|
+
config.elb.ssl.port = 443
|
77
|
+
config.elb.subnet_mappings = nil # static IP addresses for network load balancer
|
78
|
+
config.elb.type = "application"
|
70
79
|
|
71
80
|
config.exec = ActiveSupport::OrderedOptions.new
|
72
81
|
config.exec.command = "/bin/bash" # aws ecs execute-command cli
|
data/lib/ufo/info.rb
CHANGED
@@ -40,6 +40,7 @@ module Ufo
|
|
40
40
|
service = stack_resources.find { |r| r.resource_type == "AWS::ECS::Service" }
|
41
41
|
return unless service # stack is still creating
|
42
42
|
arn = service.physical_resource_id
|
43
|
+
return unless arn # can be nil for a few seconds while stack is still creating it
|
43
44
|
resp = ecs.describe_services(services: [arn], cluster: @cluster)
|
44
45
|
resp.services.first
|
45
46
|
end
|
@@ -4,15 +4,22 @@ class Ufo::TaskDefinition::Erb
|
|
4
4
|
text = IO.read(@path)
|
5
5
|
YAML.load(text)
|
6
6
|
rescue Psych::SyntaxError => e
|
7
|
-
logger.error "ERROR: #{e.class}: #{e.message}"
|
7
|
+
logger.error "ERROR: #{e.class}: #{e.message}".color(:red)
|
8
8
|
logger.error <<~EOL
|
9
9
|
Rendered file contains invalid YAML. For debugging, files available at:
|
10
10
|
|
11
11
|
source: #{@task_definition.path}
|
12
|
-
|
12
|
+
compiled: #{@path}
|
13
13
|
|
14
14
|
EOL
|
15
|
-
|
15
|
+
|
16
|
+
md = e.message.match(/at line (\d+) column (\d+)/)
|
17
|
+
if md
|
18
|
+
line_number = md[1]
|
19
|
+
DslEvaluator.print_code(@path, line_number)
|
20
|
+
else
|
21
|
+
print_code(text) # fallback to simpler print code if cannot find line numbers
|
22
|
+
end
|
16
23
|
end
|
17
24
|
end
|
18
25
|
end
|
@@ -21,6 +21,11 @@ class Ufo::TaskDefinition
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def check_empty!(data)
|
24
|
+
if data.nil?
|
25
|
+
logger.error "ERROR: Unable to compile the YAML".color(:red) # invalid YAML will result in data == nil
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
|
24
29
|
return unless data == true || data == false || data.empty?
|
25
30
|
logger.error "ERROR: Empty task definition results".color(:red)
|
26
31
|
logger.error <<~EOL
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Ufo::TaskDefinition::Helpers
|
2
|
+
module Acm
|
3
|
+
# returns cert arn
|
4
|
+
def acm_cert(domain)
|
5
|
+
certs = acm_certs
|
6
|
+
cert = certs.find do |c|
|
7
|
+
c.domain_name == domain
|
8
|
+
end
|
9
|
+
cert.certificate_arn if cert
|
10
|
+
end
|
11
|
+
|
12
|
+
# TODO: handle when there are lots of certs by paging
|
13
|
+
def acm_certs
|
14
|
+
resp = acm.list_certificates
|
15
|
+
resp.certificate_summary_list
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Ufo::TaskDefinition::Helpers
|
2
|
+
module Ecr
|
3
|
+
def ecr_repo(name)
|
4
|
+
repository = ecr_repository(name)
|
5
|
+
repository.repository_uri
|
6
|
+
end
|
7
|
+
|
8
|
+
def ecr_repository(name)
|
9
|
+
resp = ecr.describe_repositories(repository_names: [name])
|
10
|
+
resp.repositories.first
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -65,8 +65,8 @@ module Ufo::TaskDefinition::Helpers
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
# arn:aws:ssm:us-west-2:
|
69
|
-
# arn:aws:ssm:us-west-2:
|
68
|
+
# arn:aws:ssm:us-west-2:111111111111:parameter/demo/dev/DB-NAME
|
69
|
+
# arn:aws:ssm:us-west-2:111111111111:parameter/demo/dev/DB-NAME
|
70
70
|
def expansion(arn)
|
71
71
|
# performance improvement only run names.expansion on the name portion
|
72
72
|
md = arn.match(/(.*:)(parameter\/|secret:)(.*)/)
|
data/lib/ufo/utils/pretty.rb
CHANGED
@@ -4,6 +4,11 @@ module Ufo::Utils
|
|
4
4
|
path.sub("#{Ufo.root}/",'').sub(/^\.\//,'')
|
5
5
|
end
|
6
6
|
|
7
|
+
# Replace HOME with ~ - different from the main pretty_path
|
8
|
+
def pretty_home(path)
|
9
|
+
path.sub(ENV['HOME'], '~')
|
10
|
+
end
|
11
|
+
|
7
12
|
# http://stackoverflow.com/questions/4175733/convert-duration-to-hoursminutesseconds-or-similar-in-rails-3-or-ruby
|
8
13
|
def pretty_time(total_seconds)
|
9
14
|
minutes = (total_seconds / 60) % 60
|
data/lib/ufo/version.rb
CHANGED
data/lib/ufo/yaml/validator.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
class Ufo::Yaml
|
2
2
|
class Validator
|
3
|
+
include Ufo::Utils::Logging
|
4
|
+
|
3
5
|
def initialize(path)
|
4
6
|
@path = path
|
5
7
|
end
|
@@ -18,34 +20,16 @@ class Ufo::Yaml
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def handle_yaml_syntax_error(e, path)
|
21
|
-
|
22
|
-
|
23
|
-
io.puts "ERROR: #{e.message}".color(:red)
|
23
|
+
logger.error "ERROR: #{e.message}".color(:red)
|
24
|
+
logger.error "Invalid yaml. Output written for debugging: #{path}".color(:red)
|
24
25
|
|
25
26
|
# Grab line info. Example error:
|
26
27
|
# ERROR: (<unknown>): could not find expected ':' while scanning a simple key at line 2 column 1
|
27
28
|
md = e.message.match(/at line (\d+) column (\d+)/)
|
28
29
|
line = md[1].to_i
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
top, bottom = [line-context-1, 0].max, line+context-1
|
33
|
-
spacing = lines.size.to_s.size
|
34
|
-
lines[top..bottom].each_with_index do |line_content, index|
|
35
|
-
line_number = top+index+1
|
36
|
-
if line_number == line
|
37
|
-
io.printf("%#{spacing}d %s\n".color(:red), line_number, line_content)
|
38
|
-
else
|
39
|
-
io.printf("%#{spacing}d %s\n", line_number, line_content)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
if ENV['LONO_TEST']
|
44
|
-
io.string
|
45
|
-
else
|
46
|
-
puts io.string
|
47
|
-
exit 1
|
48
|
-
end
|
31
|
+
DslEvaluator.print_code(path, line_number)
|
32
|
+
exit 1
|
49
33
|
end
|
50
34
|
end
|
51
35
|
end
|
data/lib/ufo/yaml.rb
CHANGED
data/ufo.gemspec
CHANGED
@@ -20,19 +20,20 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_dependency "aws-logs"
|
22
22
|
spec.add_dependency "aws-mfa-secure", ">= 0.4.3"
|
23
|
+
spec.add_dependency "aws-sdk-acm"
|
23
24
|
spec.add_dependency "aws-sdk-applicationautoscaling"
|
24
25
|
spec.add_dependency "aws-sdk-cloudformation"
|
25
26
|
spec.add_dependency "aws-sdk-cloudwatchlogs"
|
26
27
|
spec.add_dependency "aws-sdk-ec2"
|
27
28
|
spec.add_dependency "aws-sdk-ecr"
|
28
29
|
spec.add_dependency "aws-sdk-ecs"
|
29
|
-
spec.add_dependency "aws-sdk-ssm"
|
30
30
|
spec.add_dependency "aws-sdk-elasticloadbalancingv2"
|
31
|
+
spec.add_dependency "aws-sdk-ssm"
|
31
32
|
spec.add_dependency "aws_data"
|
32
33
|
spec.add_dependency "cfn-status"
|
33
34
|
spec.add_dependency "cli-format"
|
34
35
|
spec.add_dependency "deep_merge"
|
35
|
-
spec.add_dependency "dsl_evaluator"
|
36
|
+
spec.add_dependency "dsl_evaluator", ">= 0.2.5" # for DslEvaluator.print_code
|
36
37
|
spec.add_dependency "memoist"
|
37
38
|
spec.add_dependency "plissken"
|
38
39
|
spec.add_dependency "rainbow"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ufo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.
|
4
|
+
version: 6.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03-
|
11
|
+
date: 2022-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-logs
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.4.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: aws-sdk-acm
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: aws-sdk-applicationautoscaling
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +137,7 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name: aws-sdk-
|
140
|
+
name: aws-sdk-elasticloadbalancingv2
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - ">="
|
@@ -137,7 +151,7 @@ dependencies:
|
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '0'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
|
-
name: aws-sdk-
|
154
|
+
name: aws-sdk-ssm
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
157
|
- - ">="
|
@@ -212,14 +226,14 @@ dependencies:
|
|
212
226
|
requirements:
|
213
227
|
- - ">="
|
214
228
|
- !ruby/object:Gem::Version
|
215
|
-
version:
|
229
|
+
version: 0.2.5
|
216
230
|
type: :runtime
|
217
231
|
prerelease: false
|
218
232
|
version_requirements: !ruby/object:Gem::Requirement
|
219
233
|
requirements:
|
220
234
|
- - ">="
|
221
235
|
- !ruby/object:Gem::Version
|
222
|
-
version:
|
236
|
+
version: 0.2.5
|
223
237
|
- !ruby/object:Gem::Dependency
|
224
238
|
name: memoist
|
225
239
|
requirement: !ruby/object:Gem::Requirement
|
@@ -484,6 +498,8 @@ files:
|
|
484
498
|
- lib/ufo/cli/build.rb
|
485
499
|
- lib/ufo/cli/cancel.rb
|
486
500
|
- lib/ufo/cli/central.rb
|
501
|
+
- lib/ufo/cli/central/base.rb
|
502
|
+
- lib/ufo/cli/central/clean.rb
|
487
503
|
- lib/ufo/cli/central/update.rb
|
488
504
|
- lib/ufo/cli/clean.rb
|
489
505
|
- lib/ufo/cli/destroy.rb
|
@@ -518,6 +534,7 @@ files:
|
|
518
534
|
- lib/ufo/cli/new/sequence.rb
|
519
535
|
- lib/ufo/cli/opts.rb
|
520
536
|
- lib/ufo/cli/ps.rb
|
537
|
+
- lib/ufo/cli/ps/errors.rb
|
521
538
|
- lib/ufo/cli/ps/task.rb
|
522
539
|
- lib/ufo/cli/releases.rb
|
523
540
|
- lib/ufo/cli/rollback.rb
|
@@ -569,8 +586,10 @@ files:
|
|
569
586
|
- lib/ufo/task_definition/erb/json.rb
|
570
587
|
- lib/ufo/task_definition/erb/yaml.rb
|
571
588
|
- lib/ufo/task_definition/helpers.rb
|
589
|
+
- lib/ufo/task_definition/helpers/acm.rb
|
572
590
|
- lib/ufo/task_definition/helpers/aws_data_helper.rb
|
573
591
|
- lib/ufo/task_definition/helpers/core.rb
|
592
|
+
- lib/ufo/task_definition/helpers/ecr.rb
|
574
593
|
- lib/ufo/task_definition/helpers/ssm.rb
|
575
594
|
- lib/ufo/task_definition/helpers/ssm/fetcher.rb
|
576
595
|
- lib/ufo/task_definition/helpers/stack_output.rb
|