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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3cfcec77698c26df14d0107993faaa4b6e74d235c269ff66b8750645db8103e
4
- data.tar.gz: 9c5a5e8be3b5956ef6dabe22c4ddc792ca3edb9573d739821eb74378392e8ec2
3
+ metadata.gz: 55bfd2df0ae0be2b6c5794b147c767f1a2e2d798f68b6a0c6a34154133adf73b
4
+ data.tar.gz: 5c4ea4f15b55c194f0def295653a1b3278f4a0553fb8acc83ff1a1bc7a19a6ff
5
5
  SHA512:
6
- metadata.gz: e3fb6884204bb2110ac621bb63f6644ff4f60b66b84d9ca5aeaa6023276d629e0e61c43a6bb539051eb594b0c0ca6294a7e78b5e55db2fb7c51f2983c4da6fdb
7
- data.tar.gz: 80fd898e6c89cb1ba1ebd3aa2f5eadd04f00b12bf6ac234bdaf9eb9b72d0f2e07490400262263aab07bba73e53e7706a8d8bffb5e3d542ab285ec8502f2dd335
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
- sync
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
- def sync
34
- FileUtils.mv(".ufo", ".ufo.bak") if File.exist?(".ufo")
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
- FileUtils.cp_r(src, ".ufo")
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
- logger.info "The .ufo folder has been updated"
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
- "/tmp/ufo/central"
68
+ "#{ENV['HOME']}/.ufo/central"
62
69
  end
63
70
 
64
71
  def check_gitignore
65
- ok = true
72
+ ok = false
66
73
  if File.exist?('.gitignore')
67
74
  lines = IO.readlines('.gitignore')
68
75
  ok = lines.detect do |line|
@@ -18,7 +18,7 @@ class Ufo::CLI
18
18
  end
19
19
 
20
20
  cloudformation.delete_stack(stack_name: @stack_name)
21
- puts "Deleting stack with ECS resources: #{@stack_name}"
21
+ puts "Deleting stack #{@stack_name.color(:green)}"
22
22
 
23
23
  return unless @options[:wait]
24
24
  status.wait
@@ -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
- message = recent_message
91
- words = %w[fail unable]
92
- found = words.detect { |word| message.include?(word) }
93
- return unless found
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 cancel the stack with:
102
+ You might have to #{cancel_actions[:cfn]} the stack with:
97
103
 
98
- ufo cancel
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]
@@ -1,11 +1,8 @@
1
1
  class Ufo::CLI::Ps
2
- class Task
3
- def self.header
4
- %w[Task Name Release Started Status Notes]
5
- end
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
- stopped_at = time(@task["stopped_at"])
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" && stopped_at < time
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
- logger.info info.no_service_message
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 = convert_to_task_objects(all_task_arns)
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 show_tasks(tasks)
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
- logger.info "Configured autoscaling to min: #{@min} max: #{@max}"
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.scaling.warning = false
78
+ config.scale.warning = false
72
79
 
73
80
  EOL
74
81
  end
data/lib/ufo/cli/stop.rb CHANGED
@@ -29,7 +29,7 @@ class Ufo::CLI
29
29
  def show(tasks, preview: true)
30
30
  logger.info "Will stop the following tasks:" if preview
31
31
  ps = Ps.new(@options)
32
- ps.display_tasks(tasks)
32
+ ps.show_tasks(tasks)
33
33
  end
34
34
 
35
35
  # latest deployment task definition arn
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
- rendered: #{@path}
12
+ compiled: #{@path}
13
13
 
14
14
  EOL
15
- print_code(text)
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
@@ -1,3 +1,3 @@
1
1
  module Ufo
2
- VERSION = "6.0.1"
2
+ VERSION = "6.0.2"
3
3
  end
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.1
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-05 00:00:00.000000000 Z
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: '0'
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: '0'
222
+ version: 0.2.5
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: memoist
225
225
  requirement: !ruby/object:Gem::Requirement