ufo 4.4.3 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
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