ufo 6.0.1 → 6.0.2
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 +7 -0
- data/lib/templates/init/.ufo/resources/task_definitions/web.yml +2 -0
- data/lib/ufo/cfn/stack.rb +7 -12
- data/lib/ufo/cli/central/update.rb +16 -9
- 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 -9
- 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/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/version.rb +1 -1
- data/ufo.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55bfd2df0ae0be2b6c5794b147c767f1a2e2d798f68b6a0c6a34154133adf73b
|
4
|
+
data.tar.gz: 5c4ea4f15b55c194f0def295653a1b3278f4a0553fb8acc83ff1a1bc7a19a6ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0d1c61ec52f1ae980eeca81eb7c7e8b90f3c1bd815ec3a700457ddc4a48de984d5c6c0db18271b6252e39c9f9e364640ce676c5b5a08b029e73016dcf5a78c4
|
7
|
+
data.tar.gz: c979b7f7174b98c9308d10650e467208e5c9bb30af2dc6b0b9153860ca8f0d61aee42314d3472b0ec05f6ce3b8756f9fbbaae40434fc9e5220c968a9f7f928dd
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,13 @@
|
|
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.2] - 2022-03-06
|
7
|
+
- [#128](https://github.com/tongueroo/ufo/pull/128) cleanup region with aws_data
|
8
|
+
- [#129](https://github.com/tongueroo/ufo/pull/129) Scale and Ps Edge Cases
|
9
|
+
- [#130](https://github.com/tongueroo/ufo/pull/130) compiled yaml errors: print code with line number context
|
10
|
+
- [#131](https://github.com/tongueroo/ufo/pull/131) ufo central update symlink creation
|
11
|
+
- [#132](https://github.com/tongueroo/ufo/pull/132) ufo ps improvements better catchall error messages reporting
|
12
|
+
|
6
13
|
## [6.0.1] - 2022-03-05
|
7
14
|
- [#126](https://github.com/tongueroo/ufo/pull/126) ecs deployment_configuration options
|
8
15
|
- [#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/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,7 +124,6 @@ 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
|
@@ -171,5 +160,11 @@ module Ufo::Cfn
|
|
171
160
|
logger.info "The stack is not in a state to that is cancelable: #{stack.stack_status}"
|
172
161
|
end
|
173
162
|
end
|
163
|
+
|
164
|
+
delegate :region, to: :aws
|
165
|
+
def aws
|
166
|
+
AwsData.new
|
167
|
+
end
|
168
|
+
memoize :aws
|
174
169
|
end
|
175
170
|
end
|
@@ -9,13 +9,13 @@ class Ufo::CLI::Central
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def run
|
12
|
-
action = File.exist?(".ufo") ? "update" : "create"
|
13
|
-
sure?("Will #{action} the .ufo folder.") # IE: Will create the .ufo folder.
|
14
12
|
validate!
|
13
|
+
action = File.exist?(".ufo") ? "update" : "create"
|
14
|
+
sure?("Will #{action} the .ufo symlink") # IE: Will create the .ufo symlink
|
15
15
|
logger.info "Updating .ufo with #{repo}"
|
16
16
|
FileUtils.mkdir_p(tmp_area)
|
17
17
|
pull
|
18
|
-
|
18
|
+
symlink
|
19
19
|
check_gitignore
|
20
20
|
end
|
21
21
|
|
@@ -30,18 +30,25 @@ class Ufo::CLI::Central
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
# Always update the symlink in case use changes UFO_CENTRAL_REPO
|
34
|
+
def symlink
|
35
35
|
src = "#{tmp_area}/#{repo_name}"
|
36
36
|
src += "/#{folder}" if folder
|
37
|
-
|
37
|
+
|
38
|
+
FileUtils.mv(".ufo", ".ufo.bak") if File.exist?(".ufo") && File.directory?(".ufo")
|
39
|
+
|
40
|
+
# FileUtils.ln_s(target, link, options)
|
41
|
+
# ~/.ufo/central/repo -> .ufo
|
42
|
+
FileUtils.ln_s(src, ".ufo", verbose: true)
|
38
43
|
FileUtils.rm_rf(".ufo.bak")
|
39
|
-
|
44
|
+
|
45
|
+
logger.info "The .ufo symlink has been updated"
|
40
46
|
end
|
41
47
|
|
42
48
|
def validate!
|
43
49
|
return if repo
|
44
50
|
logger.info "ERROR: Please set the env var: UFO_CENTRAL_REPO".color(:red)
|
51
|
+
logger.info "The ufo central update command requires it."
|
45
52
|
exit 1
|
46
53
|
end
|
47
54
|
|
@@ -58,11 +65,11 @@ class Ufo::CLI::Central
|
|
58
65
|
end
|
59
66
|
|
60
67
|
def tmp_area
|
61
|
-
"
|
68
|
+
"#{ENV['HOME']}/.ufo/central"
|
62
69
|
end
|
63
70
|
|
64
71
|
def check_gitignore
|
65
|
-
ok =
|
72
|
+
ok = false
|
66
73
|
if File.exist?('.gitignore')
|
67
74
|
lines = IO.readlines('.gitignore')
|
68
75
|
ok = lines.detect do |line|
|
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,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,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/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
|
data/lib/ufo/version.rb
CHANGED
data/ufo.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_dependency "cfn-status"
|
33
33
|
spec.add_dependency "cli-format"
|
34
34
|
spec.add_dependency "deep_merge"
|
35
|
-
spec.add_dependency "dsl_evaluator"
|
35
|
+
spec.add_dependency "dsl_evaluator", ">= 0.2.5" # for DslEvaluator.print_code
|
36
36
|
spec.add_dependency "memoist"
|
37
37
|
spec.add_dependency "plissken"
|
38
38
|
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.2
|
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-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-logs
|
@@ -212,14 +212,14 @@ dependencies:
|
|
212
212
|
requirements:
|
213
213
|
- - ">="
|
214
214
|
- !ruby/object:Gem::Version
|
215
|
-
version:
|
215
|
+
version: 0.2.5
|
216
216
|
type: :runtime
|
217
217
|
prerelease: false
|
218
218
|
version_requirements: !ruby/object:Gem::Requirement
|
219
219
|
requirements:
|
220
220
|
- - ">="
|
221
221
|
- !ruby/object:Gem::Version
|
222
|
-
version:
|
222
|
+
version: 0.2.5
|
223
223
|
- !ruby/object:Gem::Dependency
|
224
224
|
name: memoist
|
225
225
|
requirement: !ruby/object:Gem::Requirement
|