ufo 6.0.2 → 6.0.5

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: 55bfd2df0ae0be2b6c5794b147c767f1a2e2d798f68b6a0c6a34154133adf73b
4
- data.tar.gz: 5c4ea4f15b55c194f0def295653a1b3278f4a0553fb8acc83ff1a1bc7a19a6ff
3
+ metadata.gz: 731c8ef178a8fe9586b08eef48c7cdc4b1014e58b601155a46bed1f0c5657afa
4
+ data.tar.gz: 1654ffccfb5a57827b63e4cf8777f2ff0884e52a4e29ee0591296947443e8189
5
5
  SHA512:
6
- metadata.gz: e0d1c61ec52f1ae980eeca81eb7c7e8b90f3c1bd815ec3a700457ddc4a48de984d5c6c0db18271b6252e39c9f9e364640ce676c5b5a08b029e73016dcf5a78c4
7
- data.tar.gz: c979b7f7174b98c9308d10650e467208e5c9bb30af2dc6b0b9153860ca8f0d61aee42314d3472b0ec05f6ce3b8756f9fbbaae40434fc9e5220c968a9f7f928dd
6
+ metadata.gz: ebf9a0cbd7b7d2b532c85a8776180475d38ae5fdb4bd2b0dd1cc4ce93df3546b9af65385e3632cc936a0825e1252377c354ed4c409cb8f9723bcf0baa9a09134
7
+ data.tar.gz: '0913ec88f24b35bd34208cdbc286fcd1a1ad021538feebb66e7d9fff7bfb2eaeba7d902f5581a3003a1dc92f8a491b09bb9aab25fc0b21f4c788194c5b487f4a'
data/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
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.5] - 2022-03-07
7
+ - change default config.ship.docker.quiet = true
8
+
9
+ ## [6.0.4] - 2022-03-07
10
+ - ufo ps: use stopped at for old_age filter
11
+
12
+ ## [6.0.3] - 2022-03-07
13
+ - [#133](https://github.com/tongueroo/ufo/pull/133) improve ufo central and add helpers
14
+
6
15
  ## [6.0.2] - 2022-03-06
7
16
  - [#128](https://github.com/tongueroo/ufo/pull/128) cleanup region with aws_data
8
17
  - [#129](https://github.com/tongueroo/ufo/pull/129) Scale and Ps Edge Cases
@@ -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
@@ -130,6 +130,22 @@ module Ufo::Cfn
130
130
  when /No updates are to be performed/
131
131
  logger.info "There are no updates to be performed. Exiting.".color(:yellow)
132
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
133
149
  else
134
150
  raise
135
151
  end
@@ -0,0 +1,12 @@
1
+ class Ufo::CLI::Central
2
+ class Base
3
+ include Ufo::Utils::Execute
4
+ include Ufo::Utils::Logging
5
+ include Ufo::Utils::Pretty
6
+ include Ufo::Utils::Sure
7
+
8
+ def initialize(options={})
9
+ @options = options
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ class Ufo::CLI::Central
2
+ class Clean < Base
3
+ def run
4
+ path = "#{ENV['HOME']}/.ufo/central"
5
+ sure?("Will remove folder with repo caches: #{pretty_home(path)}")
6
+ FileUtils.rm_rf(path)
7
+ logger.info "Removed: #{pretty_home(path)}"
8
+ end
9
+ end
10
+ end
@@ -1,18 +1,10 @@
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
4
  validate!
13
5
  action = File.exist?(".ufo") ? "update" : "create"
14
6
  sure?("Will #{action} the .ufo symlink") # IE: Will create the .ufo symlink
15
- logger.info "Updating .ufo with #{repo}"
7
+ logger.info "Updating .ufo with #{central_repo}"
16
8
  FileUtils.mkdir_p(tmp_area)
17
9
  pull
18
10
  symlink
@@ -22,50 +14,85 @@ class Ufo::CLI::Central
22
14
  def pull
23
15
  logger.debug "Within #{tmp_area}"
24
16
  Dir.chdir(tmp_area) do
25
- if File.exist?(repo_name)
26
- execute "cd #{repo_name} && git pull"
17
+ if File.exist?(repo)
18
+ execute "cd #{repo} && git pull"
27
19
  else
28
- execute "git clone #{repo}"
20
+ execute "git clone #{central_repo}"
29
21
  end
30
22
  end
31
23
  end
32
24
 
33
25
  # Always update the symlink in case use changes UFO_CENTRAL_REPO
34
26
  def symlink
35
- src = "#{tmp_area}/#{repo_name}"
36
- src += "/#{folder}" if folder
27
+ src = "#{tmp_area}/#{repo}"
28
+ src += "/#{central_folder}" if central_folder
37
29
 
38
30
  FileUtils.mv(".ufo", ".ufo.bak") if File.exist?(".ufo") && File.directory?(".ufo")
39
31
 
40
32
  # FileUtils.ln_s(target, link, options)
41
33
  # ~/.ufo/central/repo -> .ufo
42
- FileUtils.ln_s(src, ".ufo", verbose: true)
34
+ FileUtils.ln_sf(src, ".ufo", verbose: false) # force in case of existing broken symlink
43
35
  FileUtils.rm_rf(".ufo.bak")
44
36
 
37
+ report_broken_symlink
38
+
45
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
46
61
  end
47
62
 
48
63
  def validate!
49
- return if repo
64
+ return if central_repo
50
65
  logger.info "ERROR: Please set the env var: UFO_CENTRAL_REPO".color(:red)
51
66
  logger.info "The ufo central update command requires it."
52
67
  exit 1
53
68
  end
54
69
 
55
- def repo_name
56
- File.basename(repo)
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
57
80
  end
58
81
 
59
82
  def repo
83
+ File.basename(central_repo)
84
+ end
85
+
86
+ def central_repo
60
87
  ENV['UFO_CENTRAL_REPO']
61
88
  end
62
89
 
63
- def folder
90
+ def central_folder
64
91
  ENV['UFO_CENTRAL_FOLDER']
65
92
  end
66
93
 
67
94
  def tmp_area
68
- "#{ENV['HOME']}/.ufo/central"
95
+ "#{ENV['HOME']}/.ufo/central/#{org}"
69
96
  end
70
97
 
71
98
  def check_gitignore
@@ -8,5 +8,12 @@ class Ufo::CLI
8
8
  def update
9
9
  Update.new(options).run
10
10
  end
11
+
12
+ desc "clean", "remove ~/.ufo/central"
13
+ long_desc Help.text("central/clean")
14
+ opts.yes
15
+ def clean
16
+ Clean.new(options).run
17
+ end
11
18
  end
12
19
  end
data/lib/ufo/cli/clean.rb CHANGED
@@ -1,5 +1,3 @@
1
- require "fileutils"
2
-
3
1
  class Ufo::CLI
4
2
  class Clean < Base
5
3
  def run
@@ -50,10 +50,12 @@ class Ufo::CLI::Ps
50
50
  # stopped_at=2018-07-05 22:03:45 -0700,
51
51
  def hide?
52
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
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
+ stopped_at = time(@task["stopped_at"])
56
+ return false unless stopped_at
55
57
  time = Time.now - 60 * Ufo.config.ps.hide_age
56
- status == "STOPPED" && started_at < time
58
+ status == "STOPPED" && stopped_at < time
57
59
  end
58
60
 
59
61
  def status
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.subnet_mappings = nil # static IP addresses for network load balancer
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
@@ -104,7 +110,7 @@ module Ufo
104
110
 
105
111
  config.ship = ActiveSupport::OrderedOptions.new
106
112
  config.ship.docker = ActiveSupport::OrderedOptions.new
107
- config.ship.docker.quiet = true # only affects ufo ship docker commands output
113
+ config.ship.docker.quiet = false # only affects ufo ship docker commands output
108
114
 
109
115
  config.state = ActiveSupport::OrderedOptions.new
110
116
  config.state.reminder = true
@@ -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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Ufo
2
- VERSION = "6.0.2"
2
+ VERSION = "6.0.5"
3
3
  end
@@ -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
- io = StringIO.new
22
- io.puts "Invalid yaml. Output written for debugging: #{path}".color(:red)
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
- lines = IO.read(path).split("\n")
31
- context = 5 # lines of context
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
@@ -8,6 +8,10 @@ module Ufo
8
8
  Validator.new(path).validate!
9
9
  Loader.new(text).load
10
10
  end
11
+
12
+ def validate!(path)
13
+ Validator.new(path).validate!
14
+ end
11
15
  end
12
16
  end
13
17
  end
data/ufo.gemspec CHANGED
@@ -20,14 +20,15 @@ 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"
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.2
4
+ version: 6.0.5
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-06 00:00:00.000000000 Z
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-ssm
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-elasticloadbalancingv2
154
+ name: aws-sdk-ssm
141
155
  requirement: !ruby/object:Gem::Requirement
142
156
  requirements:
143
157
  - - ">="
@@ -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