ufo 6.0.1 → 6.0.4
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 +13 -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/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/ps/errors.rb +22 -6
- data/lib/ufo/cli/ps/task.rb +14 -7
- data/lib/ufo/cli/ps.rb +16 -9
- data/lib/ufo/cli/scale.rb +9 -2
- data/lib/ufo/cli/stop.rb +1 -1
- data/lib/ufo/config.rb +13 -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/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 +24 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 784dac80ad55d14bb592bdc00d779a14ee4925ad1fdecc6733198201a197388b
|
4
|
+
data.tar.gz: '08dea1718845f515c26e9f255f6da8b4993b40db8db2d8d41485e6fd370b1ca3'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8b1e231432797e9090b1580144d70aa8845d03632b54cf1927dab54e45a49f8d2be75860ce2675f05dfdc2ab165879465e81d8bf65edad8c1fde46bb4fb3554
|
7
|
+
data.tar.gz: 691a8d849201ec754a69eda11fb873766c1f076cd4fafc1414c28f4c9ba76cf9e45e1e8483b452174ce1dde770cc66ba651857c194b6ed8c8ba4ecec0cea2079
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,19 @@
|
|
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.4] - 2022-03-07
|
7
|
+
- ufo ps: use stopped at for old_age filter
|
8
|
+
|
9
|
+
## [6.0.3] - 2022-03-07
|
10
|
+
- [#133](https://github.com/tongueroo/ufo/pull/133) improve ufo central and add helpers
|
11
|
+
|
12
|
+
## [6.0.2] - 2022-03-06
|
13
|
+
- [#128](https://github.com/tongueroo/ufo/pull/128) cleanup region with aws_data
|
14
|
+
- [#129](https://github.com/tongueroo/ufo/pull/129) Scale and Ps Edge Cases
|
15
|
+
- [#130](https://github.com/tongueroo/ufo/pull/130) compiled yaml errors: print code with line number context
|
16
|
+
- [#131](https://github.com/tongueroo/ufo/pull/131) ufo central update symlink creation
|
17
|
+
- [#132](https://github.com/tongueroo/ufo/pull/132) ufo ps improvements better catchall error messages reporting
|
18
|
+
|
6
19
|
## [6.0.1] - 2022-03-05
|
7
20
|
- [#126](https://github.com/tongueroo/ufo/pull/126) ecs deployment_configuration options
|
8
21
|
- [#127](https://github.com/tongueroo/ufo/pull/127) improve ps errors reporting
|
@@ -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
|
@@ -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/ps/errors.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
class Ufo::CLI::Ps
|
2
2
|
class Errors < Ufo::CLI::Ps
|
3
|
+
extend Memoist
|
4
|
+
|
3
5
|
def initialize(options={})
|
4
6
|
super
|
5
7
|
@tasks = options[:tasks]
|
@@ -87,21 +89,35 @@ class Ufo::CLI::Ps
|
|
87
89
|
# Example:
|
88
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.
|
89
91
|
def catchall
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
94
99
|
logger.error "ERROR: #{message}".color(:red)
|
100
|
+
|
95
101
|
logger.error <<~EOL
|
96
|
-
You might have to
|
102
|
+
You might have to #{cancel_actions[:cfn]} the stack with:
|
97
103
|
|
98
|
-
ufo
|
104
|
+
ufo #{cancel_actions[:ufo]}
|
99
105
|
|
100
106
|
And try again after fixing the issue.
|
101
107
|
EOL
|
102
108
|
end
|
103
109
|
|
104
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
|
+
|
105
121
|
# only check a few most recent
|
106
122
|
def recent_events
|
107
123
|
service["events"][0..4]
|
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,7 +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?
|
52
|
+
return false if @options[:status] == "stopped"
|
53
|
+
# Went back and forth with stopped_at vs started_at
|
54
|
+
# Seems like stopped_at is better as when ECS is trying to scale it leaves a lot of tasks
|
55
55
|
stopped_at = time(@task["stopped_at"])
|
56
|
+
return false unless stopped_at
|
56
57
|
time = Time.now - 60 * Ufo.config.ps.hide_age
|
57
58
|
status == "STOPPED" && stopped_at < time
|
58
59
|
end
|
@@ -92,5 +93,11 @@ class Ufo::CLI::Ps
|
|
92
93
|
start_time.strftime("%m/%d/%Y")
|
93
94
|
end
|
94
95
|
end
|
96
|
+
|
97
|
+
class << self
|
98
|
+
def header
|
99
|
+
%w[Task Name Release Started Status Notes]
|
100
|
+
end
|
101
|
+
end
|
95
102
|
end
|
96
103
|
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,8 +30,7 @@ class Ufo::CLI
|
|
25
30
|
resp["tasks"]
|
26
31
|
end.flatten
|
27
32
|
|
28
|
-
tasks =
|
29
|
-
show_tasks(tasks)
|
33
|
+
tasks = show_tasks(all_task_arns)
|
30
34
|
show_errors(tasks)
|
31
35
|
end
|
32
36
|
|
@@ -63,7 +67,14 @@ class Ufo::CLI
|
|
63
67
|
resp.scalable_targets.first # scalable_target
|
64
68
|
end
|
65
69
|
|
66
|
-
def
|
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
|
73
|
+
end
|
74
|
+
|
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)
|
67
78
|
tasks = tasks.reject(&:hide?)
|
68
79
|
show_notes = show_notes(tasks)
|
69
80
|
|
@@ -79,6 +90,7 @@ class Ufo::CLI
|
|
79
90
|
presenter.rows << row
|
80
91
|
end
|
81
92
|
presenter.show
|
93
|
+
tasks
|
82
94
|
end
|
83
95
|
|
84
96
|
def show_errors(tasks)
|
@@ -129,11 +141,6 @@ class Ufo::CLI
|
|
129
141
|
status == "ALL" ? valid_statuses : [status]
|
130
142
|
end
|
131
143
|
|
132
|
-
def convert_to_task_objects(task_arns)
|
133
|
-
task_arns.sort_by! { |t| t["task_arn"] }
|
134
|
-
task_arns.map { |t| Task.new(t) } # will have Task objects after this point
|
135
|
-
end
|
136
|
-
|
137
144
|
def task_arns
|
138
145
|
threads, results = [], {}
|
139
146
|
statuses.each do |status|
|
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/config.rb
CHANGED
@@ -56,20 +56,26 @@ module Ufo
|
|
56
56
|
config.ecs.scheduling_strategy = "REPLICA"
|
57
57
|
|
58
58
|
config.elb = ActiveSupport::OrderedOptions.new
|
59
|
-
config.elb.
|
59
|
+
config.elb.default_actions = nil # full override
|
60
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
|
+
|
61
67
|
config.elb.port = 80 # default listener port
|
62
|
-
config.elb.ssl = ActiveSupport::OrderedOptions.new
|
63
|
-
config.elb.ssl.certificates = nil
|
64
|
-
config.elb.ssl.enabled = false
|
65
|
-
config.elb.ssl.port = 443
|
66
|
-
config.elb.type = "application"
|
67
|
-
config.elb.default_actions = nil # full override
|
68
68
|
config.elb.redirect = ActiveSupport::OrderedOptions.new
|
69
69
|
config.elb.redirect.code = 302 # IE: 302 or 301
|
70
70
|
config.elb.redirect.enabled = false
|
71
71
|
config.elb.redirect.port = 443
|
72
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"
|
73
79
|
|
74
80
|
config.exec = ActiveSupport::OrderedOptions.new
|
75
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
|
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.4
|
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
|
@@ -570,8 +586,10 @@ files:
|
|
570
586
|
- lib/ufo/task_definition/erb/json.rb
|
571
587
|
- lib/ufo/task_definition/erb/yaml.rb
|
572
588
|
- lib/ufo/task_definition/helpers.rb
|
589
|
+
- lib/ufo/task_definition/helpers/acm.rb
|
573
590
|
- lib/ufo/task_definition/helpers/aws_data_helper.rb
|
574
591
|
- lib/ufo/task_definition/helpers/core.rb
|
592
|
+
- lib/ufo/task_definition/helpers/ecr.rb
|
575
593
|
- lib/ufo/task_definition/helpers/ssm.rb
|
576
594
|
- lib/ufo/task_definition/helpers/ssm/fetcher.rb
|
577
595
|
- lib/ufo/task_definition/helpers/stack_output.rb
|