ufo 4.4.3 → 4.5.0

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.
Files changed (84) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +6 -0
  4. data/docs/_docs/conventions.md +1 -1
  5. data/docs/_docs/extras/codebuild-iam-role.md +1 -1
  6. data/docs/_docs/extras/dockerfile-erb.md +60 -0
  7. data/docs/_docs/extras/ecs-network-mode.md +1 -1
  8. data/docs/_docs/extras/load-balancer.md +1 -1
  9. data/docs/_docs/extras/minimal-deploy-iam.md +1 -1
  10. data/docs/_docs/extras/redirection-support.md +1 -1
  11. data/docs/_docs/extras/route53-support.md +1 -1
  12. data/docs/_docs/extras/security-groups.md +1 -1
  13. data/docs/_docs/extras/ssl-support.md +1 -1
  14. data/docs/_docs/faq.md +2 -2
  15. data/docs/_docs/helpers.md +1 -1
  16. data/docs/_docs/more/auto-completion.md +11 -15
  17. data/docs/_docs/more/automated-cleanup.md +1 -1
  18. data/docs/_docs/more/customize-cloudformation.md +5 -5
  19. data/docs/_docs/more/migrations.md +5 -11
  20. data/docs/_docs/more/run-in-pieces.md +6 -12
  21. data/docs/_docs/more/single-task.md +9 -14
  22. data/docs/_docs/more/stuck-cloudformation.md +1 -1
  23. data/docs/_docs/more/why-cloudformation.md +1 -1
  24. data/docs/_docs/next-steps.md +1 -1
  25. data/docs/_docs/settings.md +3 -60
  26. data/docs/_docs/settings/aws_profile.md +36 -0
  27. data/docs/_docs/{settings-cfn.md → settings/cfn.md} +2 -0
  28. data/docs/_docs/settings/cluster.md +72 -0
  29. data/docs/_docs/{settings-network.md → settings/network.md} +3 -1
  30. data/docs/_docs/structure.md +1 -1
  31. data/docs/_docs/ufo-current.md +1 -1
  32. data/docs/_docs/ufo-env-extra.md +1 -1
  33. data/docs/_docs/ufo-env.md +1 -1
  34. data/docs/_docs/{params.md → ufo-task-params.md} +13 -6
  35. data/docs/_docs/upgrading.md +1 -1
  36. data/docs/_docs/upgrading/upgrade4.5.md +54 -0
  37. data/docs/_docs/upgrading/upgrade4.md +1 -1
  38. data/docs/_docs/variables.md +1 -1
  39. data/docs/_includes/subnav.html +13 -4
  40. data/docs/_reference/ufo-apps.md +1 -0
  41. data/docs/_reference/ufo-docker-base.md +10 -0
  42. data/docs/_reference/ufo-network-init.md +6 -5
  43. data/docs/_reference/ufo-task.md +10 -0
  44. data/docs/_reference/ufo-upgrade-v43to45.md +15 -0
  45. data/docs/_reference/ufo-upgrade.md +1 -1
  46. data/docs/articles.md +1 -1
  47. data/lib/ufo.rb +3 -37
  48. data/lib/ufo/apps.rb +18 -11
  49. data/lib/ufo/apps/cfn_map.rb +1 -1
  50. data/lib/ufo/apps/cluster.rb +24 -0
  51. data/lib/ufo/autoloader.rb +21 -0
  52. data/lib/ufo/base.rb +3 -3
  53. data/lib/ufo/cli.rb +2 -1
  54. data/lib/ufo/completer.rb +0 -2
  55. data/lib/ufo/docker.rb +0 -5
  56. data/lib/ufo/docker/builder.rb +12 -4
  57. data/lib/ufo/docker/compiler.rb +21 -0
  58. data/lib/ufo/docker/dockerfile.rb +1 -2
  59. data/lib/ufo/docker/variables.rb +26 -0
  60. data/lib/ufo/dsl.rb +0 -4
  61. data/lib/ufo/help/docker/base.md +10 -0
  62. data/lib/ufo/help/task.md +10 -0
  63. data/lib/ufo/network.rb +0 -4
  64. data/lib/ufo/param.rb +1 -16
  65. data/lib/ufo/ps.rb +0 -2
  66. data/lib/ufo/setting.rb +0 -2
  67. data/lib/ufo/ship.rb +2 -3
  68. data/lib/ufo/stack.rb +1 -4
  69. data/lib/ufo/stack/context.rb +4 -4
  70. data/lib/ufo/stack/helper.rb +10 -4
  71. data/lib/ufo/task.rb +2 -1
  72. data/lib/ufo/tasks.rb +0 -3
  73. data/lib/ufo/upgrade.rb +3 -8
  74. data/lib/ufo/upgrade/{upgrade43to44.rb → upgrade43to45.rb} +5 -5
  75. data/lib/ufo/util.rb +5 -2
  76. data/lib/ufo/version.rb +1 -1
  77. data/spec/fixtures/settings.yml +1 -1
  78. data/ufo.gemspec +1 -0
  79. metadata +30 -13
  80. data/Gemfile.lock +0 -113
  81. data/docs/_docs/upgrading/upgrade4.4.md +0 -39
  82. data/docs/_reference/ufo-upgrade-v43to44.md +0 -15
  83. data/lib/ufo/ecr.rb +0 -6
  84. data/lib/ufo/ecs.rb +0 -5
data/lib/ufo/apps.rb CHANGED
@@ -2,33 +2,40 @@ require 'text-table'
2
2
 
3
3
  module Ufo
4
4
  class Apps
5
- autoload :CfnMap, "ufo/apps/cfn_map"
6
- autoload :Service, "ufo/apps/service"
7
-
8
5
  extend Memoist
9
6
  include Stack::Helper
10
7
 
11
8
  def initialize(options)
12
9
  @options = options
13
- @cluster = @options[:cluster] || default_cluster
10
+ @clusters = @options[:cluster] || @options[:clusters]
11
+ @clusters = [@clusters].flatten.compact
12
+ if @clusters.empty?
13
+ @clusters = Cluster.all
14
+ end
15
+ end
16
+
17
+ def list_all
18
+ @clusters.each do |cluster|
19
+ list(cluster)
20
+ end
14
21
  end
15
22
 
16
- def list
23
+ def list(cluster)
17
24
  begin
18
- resp = ecs.list_services(cluster: @cluster)
25
+ resp = ecs.list_services(cluster: cluster)
19
26
  rescue Aws::ECS::Errors::ClusterNotFoundException => e
20
- puts "ECS cluster #{@cluster.color(:green)} not found."
21
- exit 1
27
+ puts "ECS cluster #{cluster.color(:green)} not found."
28
+ return
22
29
  end
23
30
  arns = resp.service_arns.sort
24
31
 
25
- puts "Listing ECS services in the #{@cluster.color(:green)} cluster."
32
+ puts "Listing ECS services in the #{cluster.color(:green)} cluster."
26
33
  if arns.empty?
27
- puts "No ECS services found in the #{@cluster.color(:green)} cluster."
34
+ puts "No ECS services found in the #{cluster.color(:green)} cluster."
28
35
  return
29
36
  end
30
37
 
31
- resp = ecs.describe_services(services: arns, cluster: @cluster)
38
+ resp = ecs.describe_services(services: arns, cluster: cluster)
32
39
  display_info(resp)
33
40
  end
34
41
 
@@ -5,7 +5,7 @@ class Ufo::Apps
5
5
 
6
6
  def initialize(options = {})
7
7
  @options = options
8
- @cluster = @options[:cluster] || default_cluster
8
+ @cluster = @options[:cluster] || default_cluster(options[:service])
9
9
  @map = {}
10
10
  end
11
11
 
@@ -0,0 +1,24 @@
1
+ class Ufo::Apps
2
+ class Cluster
3
+ def self.all
4
+ new.all
5
+ end
6
+
7
+ def all
8
+ Ufo.check_ufo_project!
9
+ clusters = if settings[:service_cluster]
10
+ settings[:service_cluster].values
11
+ elsif settings[:cluster]
12
+ settings[:cluster]
13
+ else
14
+ Ufo.env
15
+ end
16
+ [clusters].flatten.compact
17
+ end
18
+
19
+ private
20
+ def settings
21
+ @settings ||= Ufo.settings
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ require "zeitwerk"
2
+
3
+ module Ufo
4
+ class Autoloader
5
+ class Inflector < Zeitwerk::Inflector
6
+ def camelize(basename, _abspath)
7
+ map = { cli: "CLI", dsl: "DSL", version: "VERSION" }
8
+ map[basename.to_sym] || super
9
+ end
10
+ end
11
+
12
+ class << self
13
+ def setup
14
+ loader = Zeitwerk::Loader.new
15
+ loader.inflector = Inflector.new
16
+ loader.push_dir(File.dirname(__dir__)) # lib
17
+ loader.setup
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/ufo/base.rb CHANGED
@@ -7,7 +7,7 @@ module Ufo
7
7
  @service = switch_current(service)
8
8
  @options = options
9
9
 
10
- @cluster = @options[:cluster] || default_cluster
10
+ @cluster = @options[:cluster] || default_cluster(@service)
11
11
  @stack_name = adjust_stack_name(@cluster, @service)
12
12
  end
13
13
 
@@ -22,8 +22,8 @@ module Ufo
22
22
 
23
23
  def no_service_message
24
24
  <<-EOL
25
- No #{@service.color(:green)} found.
26
- No CloudFormation stack named #{@stack_name} found.
25
+ No #{@service.color(:green)} ecs service found.
26
+ No CloudFormation stack named #{@stack_name.color(:green)} found.
27
27
  Are sure it exists?
28
28
  EOL
29
29
  end
data/lib/ufo/cli.rb CHANGED
@@ -143,8 +143,9 @@ module Ufo
143
143
 
144
144
  desc "apps", "List apps."
145
145
  long_desc Help.text(:apps)
146
+ option :clusters, type: :array, desc: "List of clusters"
146
147
  def apps
147
- Apps.new(options).list
148
+ Apps.new(options).list_all
148
149
  end
149
150
 
150
151
  desc "resources SERVICE", "The ECS service resources."
data/lib/ufo/completer.rb CHANGED
@@ -70,8 +70,6 @@ Auto-completion accounts for each of these type of commands.
70
70
  =end
71
71
  module Ufo
72
72
  class Completer
73
- autoload :Script, 'ufo/completer/script'
74
-
75
73
  def initialize(command_class, *params)
76
74
  @params = params
77
75
  @current_command = @params[0]
data/lib/ufo/docker.rb CHANGED
@@ -1,10 +1,5 @@
1
1
  module Ufo
2
2
  class Docker < Command
3
- autoload :Builder, 'ufo/docker/builder'
4
- autoload :Pusher, 'ufo/docker/pusher'
5
- autoload :Dockerfile, 'ufo/docker/dockerfile'
6
- autoload :Cleaner, 'ufo/docker/cleaner'
7
-
8
3
  desc "build", "Build docker image."
9
4
  long_desc Help.text("docker:build")
10
5
  option :push, type: :boolean, default: false
@@ -23,12 +23,12 @@ class Ufo::Docker
23
23
  start_time = Time.now
24
24
  store_full_image_name
25
25
 
26
- update_auth_token
27
-
28
26
  command = "docker build #{build_options}-t #{full_image_name} -f #{@dockerfile} ."
29
27
  say "Building docker image with:".color(:green)
30
28
  say " #{command}".color(:green)
29
+ compile_dockerfile_erb
31
30
  check_dockerfile_exists
31
+ update_auth_token
32
32
  command = "cd #{Ufo.root} && #{command}"
33
33
  success = execute(command, use_system: true)
34
34
  unless success
@@ -81,6 +81,10 @@ class Ufo::Docker
81
81
  @pusher ||= Pusher.new(full_image_name, @options)
82
82
  end
83
83
 
84
+ def compile_dockerfile_erb
85
+ Compiler.new("#{Ufo.root}/#{@dockerfile}").compile
86
+ end
87
+
84
88
  def check_dockerfile_exists
85
89
  unless File.exist?("#{Ufo.root}/#{@dockerfile}")
86
90
  puts "#{@dockerfile} does not exist. Are you sure it exists?"
@@ -139,8 +143,12 @@ class Ufo::Docker
139
143
  end
140
144
 
141
145
  def update_dockerfile
142
- dockerfile = Dockerfile.new(full_image_name, @options)
143
- dockerfile.update
146
+ updater = if File.exist?("#{Ufo.root}/Dockerfile.erb") # dont use @dockerfile on purpose
147
+ Variables.new(full_image_name, @options)
148
+ else
149
+ Dockerfile.new(full_image_name, @options)
150
+ end
151
+ updater.update
144
152
  end
145
153
 
146
154
  def say(msg)
@@ -0,0 +1,21 @@
1
+ class Ufo::Docker
2
+ class Compiler
3
+ def initialize(dockerfile)
4
+ @dockerfile = dockerfile
5
+ @erb_file = "#{dockerfile}.erb"
6
+ end
7
+
8
+ def compile
9
+ return unless File.exist?(@erb_file)
10
+
11
+ puts "Compiled #{File.basename(@erb_file).color(:green)} to #{File.basename(@dockerfile).color(:green)}"
12
+ path = "#{Ufo.root}/.ufo/settings/dockerfile_variables.yml"
13
+ vars = YAML.load_file(path)[Ufo.env] if File.exist?(path)
14
+ vars ||= {}
15
+ result = RenderMePretty.result(@erb_file, vars)
16
+ comment = "# Note this file was generated from #{File.basename(@erb_file)} as a part of running ufo ship"
17
+ result = "#{comment}\n#{result}"
18
+ IO.write(@dockerfile, result)
19
+ end
20
+ end
21
+ end
@@ -1,8 +1,7 @@
1
1
  module Ufo
2
2
  class Docker::Dockerfile
3
3
  def initialize(full_image_name, options={})
4
- @full_image_name = full_image_name
5
- @options = options
4
+ @full_image_name, @options = full_image_name, options
6
5
  end
7
6
 
8
7
  def update
@@ -0,0 +1,26 @@
1
+ class Ufo::Docker
2
+ class Variables
3
+ @@variables_path = "#{Ufo.root}/.ufo/settings/dockerfile_variables.yml"
4
+
5
+ def initialize(full_image_name, options={})
6
+ @full_image_name, @options = full_image_name, options
7
+ end
8
+
9
+ def update
10
+ data = current_data
11
+ data[Ufo.env] ||= {}
12
+ data[Ufo.env]["base_image"] = @full_image_name
13
+ pretty_path = @@variables_path.sub("#{Ufo.root}/", "")
14
+ IO.write(@@variables_path, YAML.dump(data))
15
+
16
+ unless @options[:mute]
17
+ puts "The #{pretty_path} base_image has been updated with the latest base image:".color(:green)
18
+ puts " #{@full_image_name}".color(:green)
19
+ end
20
+ end
21
+
22
+ def current_data
23
+ File.exist?(@@variables_path) ? YAML.load_file(@@variables_path) : {}
24
+ end
25
+ end
26
+ end
data/lib/ufo/dsl.rb CHANGED
@@ -2,10 +2,6 @@ require 'ostruct'
2
2
 
3
3
  module Ufo
4
4
  class DSL
5
- autoload :TaskDefinition, 'ufo/dsl/task_definition'
6
- autoload :Outputter, 'ufo/dsl/outputter'
7
- autoload :Helper, 'ufo/dsl/helper'
8
-
9
5
  def initialize(template_definitions_path, options={})
10
6
  @template_definitions_path = template_definitions_path
11
7
  @options = options
@@ -36,4 +36,14 @@ Some of the output has been excluded so we can focus on the important parts to p
36
36
 
37
37
  It is using the docker `-f Dockerfile.base` option to build the base image. It names the image with `tongueroo/demo-ufo:base-2017-06-12T14-36-44-2af505e`. The image tag contains useful information: the timestamp when the image was built and the exact git sha of the code. The image gets push to a registry immediately.
38
38
 
39
+ ## Dockerfile FROM updated
40
+
39
41
  Notice at the very end, the *current* `Dockerfile`'s FROM statement has been updated with the newly built base Docker image automatically. This saves you from forgetting to copying and pasting it the `Dockerfile` yourself.
42
+
43
+ If you're using a [Dockerfile.erb](https://ufoships.com/docs/extras/dockerfile-erb/), then ufo will update the `.ufo/settings/dockerfile_variables.yml` file instead. It assumes you're using a Dockerfile.erb that looks something like this:
44
+
45
+ ```Dockerfile
46
+ FROM <%= @base_image %>
47
+ # ...
48
+ CMD ["bin/web"]
49
+ ```
data/lib/ufo/help/task.md CHANGED
@@ -1,3 +1,9 @@
1
+ The `ufo task` commands:
2
+
3
+ 1. Builds the docker image
4
+ 2. Registers the ECS task definition
5
+ 3. Runs the command
6
+
1
7
  ## Examples
2
8
 
3
9
  You can use the `--command` or `-c` option to override the Docker container command.
@@ -15,3 +21,7 @@ The `--task-only` option is useful. By default, the `ufo task` command will buil
15
21
  ufo task demo-web -c uptime # build at least once
16
22
  ufo task demo-web --task-only -c ls # skip docker for speed
17
23
  ufo task demo-web --task-only -c pwd # skip docker for speed
24
+
25
+ ## Params
26
+
27
+ You can control and customize the params that get sent to the ECS run_task call with a `config/params.yml` file. More info here: https://ufoships.com/docs/ufo-task-params/
data/lib/ufo/network.rb CHANGED
@@ -1,9 +1,5 @@
1
1
  module Ufo
2
2
  class Network < Command
3
- autoload :Init, "ufo/network/init"
4
- autoload :Helper, "ufo/network/helper"
5
- autoload :Fetch, "ufo/network/fetch"
6
-
7
3
  def self.cli_options
8
4
  [
9
5
  [:force, type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files."],
data/lib/ufo/param.rb CHANGED
@@ -9,7 +9,7 @@ module Ufo
9
9
  end
10
10
 
11
11
  def data
12
- upgrade_message!
12
+ return {} unless File.exist?(@params_path)
13
13
 
14
14
  result = RenderMePretty.result(@params_path, context: template_scope)
15
15
  data = YAML.load(result) || {}
@@ -20,20 +20,5 @@ module Ufo
20
20
  def template_scope
21
21
  @template_scope ||= Ufo::TemplateScope.new(Ufo::DSL::Helper.new, nil)
22
22
  end
23
-
24
- # Ufo version 3.3 to 3.4 added a concept of a .ufo/params.yml file to support
25
- # fargate: https://github.com/tongueroo/ufo/pull/31
26
- #
27
- # Warn user and tell them to run the `ufo upgrade v3_3to3_4` command to upgrade.
28
- def upgrade_message!
29
- return if File.exist?(@params_path)
30
-
31
- puts "ERROR: Your project is missing the .ufo/params.yml.".color(:red)
32
- puts "This was added in ufo version 3.4"
33
- puts "You can find more info about the params file here: http://ufoships.com/docs/params/"
34
- puts "To upgrade run:"
35
- puts " ufo upgrade v3_3to3_4"
36
- exit 1
37
- end
38
23
  end
39
24
  end
data/lib/ufo/ps.rb CHANGED
@@ -2,8 +2,6 @@ require 'text-table'
2
2
 
3
3
  module Ufo
4
4
  class Ps < Base
5
- autoload :Task, 'ufo/ps/task'
6
-
7
5
  delegate :service, to: :info
8
6
 
9
7
  def run
data/lib/ufo/setting.rb CHANGED
@@ -3,8 +3,6 @@ require 'yaml'
3
3
  module Ufo
4
4
  class Setting
5
5
  extend Memoist
6
- autoload :Profile, "ufo/setting/profile"
7
-
8
6
  def initialize(check_ufo_project=true)
9
7
  @check_ufo_project = check_ufo_project
10
8
  end
data/lib/ufo/ship.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  module Ufo
2
2
  class UfoError < RuntimeError; end
3
3
  class ShipmentOverridden < UfoError; end
4
- autoload :KillTask, 'ufo/ship/kill_task'
5
4
 
6
5
  class Ship < Base
7
6
  def initialize(service, options={})
@@ -10,13 +9,13 @@ module Ufo
10
9
  end
11
10
 
12
11
  def deploy
13
- message = "Deploying #{@service}..."
12
+ message = "Deploying service #{@service.color(:green)} to cluster #{@cluster.color(:green)}..."
14
13
  unless @options[:mute]
15
14
  if @options[:noop]
16
15
  puts "NOOP: #{message}"
17
16
  return
18
17
  else
19
- puts message.color(:green)
18
+ puts message
20
19
  end
21
20
  end
22
21
 
data/lib/ufo/stack.rb CHANGED
@@ -23,9 +23,6 @@
23
23
  #
24
24
  module Ufo
25
25
  class Stack
26
- autoload :Context, "ufo/stack/context"
27
- autoload :Helper, "ufo/stack/helper"
28
- autoload :Status, "ufo/stack/status"
29
26
  extend Memoist
30
27
  include Helper
31
28
 
@@ -33,7 +30,7 @@ module Ufo
33
30
  @options = options
34
31
  @task_definition = options[:task_definition]
35
32
  @service = options[:service]
36
- @cluster = @options[:cluster] || default_cluster
33
+ @cluster = @options[:cluster] || default_cluster(@service)
37
34
  @stack_name = adjust_stack_name(@cluster, options[:service])
38
35
  end
39
36
 
@@ -91,12 +91,12 @@ class Ufo::Stack
91
91
  create_elb == "true" # convert to boolean
92
92
  end
93
93
 
94
- # if --elb is not set at all, so it's nil. Thhen it defaults to creating the
95
- # load balancer if the ecs service has a container name "web".
94
+ # If --elb is not set at all and is nil, then it defaults to creating the load balancer if the ecs service has
95
+ # a container name "web".
96
96
  #
97
- # --elb '' - wont crete an elb
97
+ # --elb '' - will not crete an elb
98
98
  # --elb 'auto' - creates an elb
99
- # --elb arn:... - wont create elb and use the existing target group
99
+ # --elb arn:... - will not create elb and use the existing target group
100
100
  #
101
101
  def elb_options
102
102
  case @options[:elb]
@@ -17,14 +17,20 @@ class Ufo::Stack
17
17
  end
18
18
 
19
19
  def adjust_stack_name(cluster, service)
20
- if settings[:stack_naming] != "append_env"
21
- puts "WARN: In ufo v4.4 the environment name gets appends to the end of the CloudFormation stack name. This means a new stack gets created. You must upgrade to using the new stack and delete the old stack manually. More info: http://ufoships.com/docs/upgrading/upgrade4.4/".color(:yellow)
22
- puts "To get rid of this warning you can add `stack_naming: append_env` to your `.ufo/settings.yml config. New versions of ufo init does this automatically."
20
+ upgraded_namings = %w[append_ufo_env append_env append_cluster]
21
+ unless upgraded_namings.include?(settings[:stack_naming])
22
+ puts "WARN: In ufo v4.6 the UFO_ENV value gets appends to the end of the CloudFormation stack name. This means a new stack gets created. You must upgrade to using the new stack and delete the old stack manually. More info: http://ufoships.com/docs/upgrading/upgrade4.x/".color(:yellow)
23
+ puts "To get rid of this warning you can add `stack_naming: append_ufo_env` to your `.ufo/settings.yml config. New versions of ufo init do this automatically."
23
24
  puts "Pausing for 20 seconds."
24
25
  sleep 20
25
26
  end
26
27
 
27
- parts = if settings[:stack_naming] == "append_env"
28
+ parts = case settings[:stack_naming]
29
+ when "append_ufo_env" # ufo v4.6
30
+ [service, Ufo.env, Ufo.env_extra]
31
+ when "append_env", "append_cluster" # ufo v4.5
32
+ # append_env will be removed in the next major version in favor of apend_cluster.
33
+ # To avoid confusiong with append_ufo_env
28
34
  [service, cluster, Ufo.env_extra]
29
35
  else
30
36
  # legacy, to be removed in next major version