ufo 6.2.4 → 6.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.cody/acceptance/bin/asg.sh +15 -0
  3. data/.cody/acceptance/bin/build.sh +6 -0
  4. data/.cody/acceptance/{role.rb → iam_role.rb} +1 -0
  5. data/.cody/acceptance/project.rb +5 -5
  6. data/.gitignore +1 -0
  7. data/CHANGELOG.md +12 -0
  8. data/lib/templates/hooks/docker.rb +9 -0
  9. data/lib/templates/hooks/ufo.rb +9 -0
  10. data/lib/templates/init/.ufo/vars/base.rb +2 -2
  11. data/lib/ufo/autoloader.rb +1 -1
  12. data/lib/ufo/cfn/stack/builder/resources/iam_roles/base.rb +2 -2
  13. data/lib/ufo/cfn/stack.rb +17 -13
  14. data/lib/ufo/cli/build.rb +0 -5
  15. data/lib/ufo/cli/destroy.rb +13 -10
  16. data/lib/ufo/cli/help/new/hook.md +7 -0
  17. data/lib/ufo/cli/new/hook.rb +18 -0
  18. data/lib/ufo/cli/new.rb +11 -4
  19. data/lib/ufo/cli/scale.rb +1 -0
  20. data/lib/ufo/command.rb +1 -1
  21. data/lib/ufo/config.rb +3 -0
  22. data/lib/ufo/docker/builder.rb +5 -1
  23. data/lib/ufo/docker/pusher.rb +5 -1
  24. data/lib/ufo/hooks/builder.rb +51 -0
  25. data/lib/ufo/hooks/concern.rb +10 -0
  26. data/lib/ufo/hooks/dsl.rb +20 -0
  27. data/lib/ufo/hooks/runner.rb +37 -0
  28. data/lib/ufo/iam_role/dsl.rb +1 -1
  29. data/lib/ufo/iam_role/registry.rb +2 -2
  30. data/lib/ufo/info.rb +1 -0
  31. data/lib/ufo/layering/layer.rb +1 -4
  32. data/lib/ufo/param.rb +1 -2
  33. data/lib/ufo/task_definition/helpers/acm.rb +1 -1
  34. data/lib/ufo/task_definition/helpers/ecr.rb +1 -1
  35. data/lib/ufo/task_definition/helpers/stack_output.rb +1 -1
  36. data/lib/ufo/task_definition/helpers/vars/builder.rb +51 -19
  37. data/lib/ufo/task_definition/helpers/vars.rb +2 -2
  38. data/lib/ufo/task_definition/helpers/waf.rb +1 -1
  39. data/lib/ufo/utils/call_line.rb +1 -1
  40. data/lib/ufo/version.rb +1 -1
  41. data/spec/ufo/iam_role/builder_spec.rb +1 -1
  42. data/spec/ufo/iam_role/dsl_spec.rb +2 -2
  43. metadata +12 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33b084a105deead3af06b7ee38478fe56875aa2a3e9728b4a78720ae33b7b100
4
- data.tar.gz: 9c84f76952079299b855ac987d7de849a352f978badc05daa4934de34b93f7be
3
+ metadata.gz: f1f60f15e2492a5d8e40c1b0a507e5eac51427963a2d29139235e1eb70d37c24
4
+ data.tar.gz: e6bc8a65ac678cddcccc000c9b829dfebd94aa91dd664129f7aed7f40310e271
5
5
  SHA512:
6
- metadata.gz: 5c2d0f3ce6c72e0db4841ed99aaf0eb5095e2f8e2eea156dce69ac936dcca1b76c9185c920a4f791ff71217bb27ada2a486a023c139ff2c12d156dee882ca217
7
- data.tar.gz: 285f2db81b8e5f49c0c2c52da74a896cfddee6df44853a61e9fa69f67b463654dff63f405229981db017c0bb7fcd0fa11b8993566aebe3c509ab7dbb72ccccf4
6
+ metadata.gz: e90f778cc345554a7ef971268297fd5b5e1969538056384f1bd1b3248aaa1519682f84d6a37b65c59ee70586494ff7111dacc3a8bf72a6bec62251aec63a338a
7
+ data.tar.gz: 2e0fd1b9d37604c15027f898b74e706e18304362fde5577b05db90190e0b747038a89068819ba9b213a403d3f20e051c4cab0bd7d11887142756b538460e8db5
@@ -0,0 +1,15 @@
1
+ function scale_asg_to() {
2
+ n=$1
3
+ ASG=$(asg)
4
+ echo "Scaling $ASG to $n"
5
+ aws autoscaling update-auto-scaling-group --auto-scaling-group-name $ASG \
6
+ --desired-capacity $n --min-size $n --max-size $n
7
+ }
8
+
9
+ # aws cloudformation describe-stacks --stack-name ecs-qa | jq -r '.Stacks[].Outputs[] | select(.OutputKey == "Asg") | .OutputValue'
10
+ # aws cloudformation describe-stack-resources --stack-name ecs-qa | jq -r '.StackResources[] | select(.LogicalResourceId == "Asg") | .PhysicalResourceId'
11
+ function asg() {
12
+ STACK_NAME=ecs-qa
13
+ ASG=$(aws cloudformation describe-stacks --stack-name $STACK_NAME | jq -r '.Stacks[].Outputs[] | select(.OutputKey == "Asg") | .OutputValue')
14
+ echo $ASG
15
+ }
@@ -1,5 +1,8 @@
1
1
  #!/bin/bash
2
2
 
3
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4
+ source "$DIR/asg.sh"
5
+
3
6
  final_status=0
4
7
  function capture_status {
5
8
  if [ "$?" -ne "0" ] && [ $final_status -ne 1 ] ; then
@@ -40,6 +43,7 @@ cat .ufo/vars/base.rb
40
43
  cat .ufo/vars/dev.rb
41
44
 
42
45
  export UFO_ENV=qa
46
+ scale_asg_to 1
43
47
 
44
48
  # Deploy
45
49
  ufo ship -y
@@ -95,3 +99,5 @@ ufo ps # see full output for debugging
95
99
  ufo ps 2>&1 | grep Stack | grep worker # should be success. IE: exit 0
96
100
  ufo destroy -y
97
101
  ufo ps 2>&1 | grep No | grep found # should be success. IE: exit 0
102
+
103
+ scale_asg_to 0
@@ -1,5 +1,6 @@
1
1
  iam_policy(
2
2
  "application-autoscaling",
3
+ "autoscaling",
3
4
  "cloudformation",
4
5
  "ec2",
5
6
  "ecr",
@@ -1,8 +1,8 @@
1
- github_url("https://github.com/boltops-tools/ufo")
2
- linux_image("aws/codebuild/amazonlinux2-x86_64-standard:3.0")
3
- environment_variables(
4
- DOCKER_USER: "ssm:/codebuild/ufo/DOCKER_USER",
5
- DOCKER_PASS: "ssm:/codebuild/ufo/DOCKER_PASS",
1
+ github("boltops-tools/ufo")
2
+ image("aws/codebuild/amazonlinux2-x86_64-standard:3.0")
3
+ env_vars(
4
+ DOCKER_USER: "ssm:/#{Cody.env}/DOCKER_USER",
5
+ DOCKER_PASS: "ssm:/#{Cody.env}/DOCKER_PASS",
6
6
  )
7
7
 
8
8
  # triggers(
data/.gitignore CHANGED
@@ -19,3 +19,4 @@ tmp
19
19
 
20
20
  .ruby-version
21
21
  Gemfile.lock
22
+ .cody/output
data/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
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.3.1] - 2022-03-25
7
+ - ufo init: improve vars base.rb
8
+
9
+ ## [6.3.0] - 2022-03-25
10
+ - [#162](https://github.com/tongueroo/ufo/pull/162) hooks support
11
+
12
+ ## [6.2.5] - 2022-03-24
13
+ - [#159](https://github.com/tongueroo/ufo/pull/159) improve ufo call line
14
+ - [#160](https://github.com/tongueroo/ufo/pull/160) conventionally lookup up secrets and env file
15
+ - [#161](https://github.com/tongueroo/ufo/pull/161) layering support for env files
16
+ - improve acceptance pipeline
17
+
6
18
  ## [6.2.4] - 2022-03-20
7
19
  - [#158](https://github.com/tongueroo/ufo/pull/158) warn on missing env and secrets file instead of error
8
20
 
@@ -0,0 +1,9 @@
1
+ # Docs: https://ufoships.com/docs/config/hooks/docker/
2
+
3
+ before("build",
4
+ execute: "echo 'docker build before hook'",
5
+ )
6
+
7
+ after("build",
8
+ execute: "echo 'docker build after hook'",
9
+ )
@@ -0,0 +1,9 @@
1
+ # Docs: https://ufoships.com/docs/config/hooks/ufo/
2
+
3
+ before("ship",
4
+ execute: "echo 'ufo before ship hook'",
5
+ )
6
+
7
+ after("ship",
8
+ execute: "echo 'ufo after ship hook'",
9
+ )
@@ -7,8 +7,8 @@
7
7
  @name = role # IE: web worker clock
8
8
  @image = docker_image # includes the git sha org/repo:ufo-[sha].
9
9
  # Docs: https://ufoships.com/docs/helpers/builtin/secrets/
10
- # @environment = env_file(".env")
11
- # @secrets = secrets_file(".secrets")
10
+ # @environment = env_file
11
+ # @secrets = secrets_file
12
12
  @cpu = 256
13
13
  @memory = 256
14
14
  @memory_reservation = 256
@@ -4,7 +4,7 @@ module Ufo
4
4
  class Autoloader
5
5
  class Inflector < Zeitwerk::Inflector
6
6
  def camelize(basename, _abspath)
7
- map = { cli: "CLI", dsl: "DSL", version: "VERSION" }
7
+ map = { cli: "CLI", version: "VERSION" }
8
8
  map[basename.to_sym] || super
9
9
  end
10
10
  end
@@ -1,7 +1,7 @@
1
1
  module Ufo::Cfn::Stack::Builder::Resources::IamRoles
2
2
  class Base < Ufo::Cfn::Stack::Builder::Base
3
3
  def build
4
- return unless self.class.build? # important because it runs DSL#evaluate
4
+ return unless self.class.build? # important because it runs Dsl#evaluate
5
5
  Ufo::IamRole::Builder.new(self.class.role_type).build
6
6
  end
7
7
 
@@ -13,7 +13,7 @@ module Ufo::Cfn::Stack::Builder::Resources::IamRoles
13
13
  def build?
14
14
  path = lookup_path
15
15
  return unless path.nil? || File.exist?(path)
16
- Ufo::IamRole::DSL.new(path).evaluate # runs the role.rb and registers items
16
+ Ufo::IamRole::Dsl.new(path).evaluate # runs the role.rb and registers items
17
17
  Ufo::IamRole::Builder.new(role_type).build?
18
18
  end
19
19
 
data/lib/ufo/cfn/stack.rb CHANGED
@@ -25,6 +25,7 @@ module Ufo::Cfn
25
25
  class Stack < Base
26
26
  extend Memoist
27
27
  include Ufo::TaskDefinition::Helpers::AwsHelper
28
+ include Ufo::Hooks::Concern
28
29
 
29
30
  def deploy
30
31
  build
@@ -39,15 +40,14 @@ module Ufo::Cfn
39
40
 
40
41
  exit_with_message(@stack) if @stack && !updatable?(@stack)
41
42
 
42
- @stack ? perform(:update) : perform(:create)
43
-
44
- stop_old_tasks if @options[:stop_old_task]
45
-
46
- return unless @options[:wait]
47
- status.wait
43
+ run_hooks(name: "ship", file: "ufo.rb") do
44
+ @stack ? perform(:update) : perform(:create)
45
+ stop_old_tasks if @options[:stop_old_task]
46
+ return unless @options[:wait]
47
+ status.wait
48
+ end
48
49
 
49
50
  logger.info status.rollback_error_message if status.update_rollback?
50
-
51
51
  status.success?
52
52
  end
53
53
 
@@ -78,13 +78,17 @@ module Ufo::Cfn
78
78
  end
79
79
  end
80
80
 
81
+ # Run hooks here so both ufo docker and ufo ship runs it
82
+ # ufo docker => CLI::Build#build => Cfn::Stack#build
81
83
  def build
82
- vars = Vars.new(@options).values
83
- options_with_vars = @options.dup.merge(vars: vars)
84
- params = Params.new(options_with_vars)
85
- @parameters = params.build
86
- template = Template.new(options_with_vars)
87
- @template_body = template.body
84
+ run_hooks(name: "build", file: "ufo.rb") do
85
+ vars = Vars.new(@options).values
86
+ options_with_vars = @options.dup.merge(vars: vars)
87
+ params = Params.new(options_with_vars)
88
+ @parameters = params.build
89
+ template = Template.new(options_with_vars)
90
+ @template_body = template.body
91
+ end
88
92
  end
89
93
 
90
94
  def scheduling_strategy
data/lib/ufo/cli/build.rb CHANGED
@@ -7,11 +7,6 @@ class Ufo::CLI
7
7
  end
8
8
  alias_method :all, :build
9
9
 
10
- def for_deploy
11
- docker
12
- task_definition
13
- end
14
-
15
10
  def task_definition
16
11
  Ufo::TaskDefinition::Builder.new(@options).build
17
12
  end
@@ -1,27 +1,30 @@
1
1
  class Ufo::CLI
2
2
  class Destroy < Base
3
+ include Ufo::Hooks::Concern
4
+
3
5
  def run
4
6
  are_you_sure?
5
7
 
6
8
  stack = find_stack(@stack_name)
7
9
  unless stack
8
- puts "Stack #{@stack_name.color(:green)} does not exist."
10
+ logger.info "Stack #{@stack_name.color(:green)} does not exist."
9
11
  exit 1
10
12
  end
11
13
 
12
14
  if stack.stack_status =~ /_IN_PROGRESS$/
13
- puts "Cannot destroy service #{@service.color(:green)}"
14
- puts "Cannot delete stack #{@stack_name.color(:green)} in this state: #{stack.stack_status.color(:green)}"
15
- puts "If the stack is taking a long time, you can cancel the current operation with:"
16
- puts " ufo cancel #{@service}"
15
+ logger.info "Cannot destroy service #{@service.color(:green)}"
16
+ logger.info "Cannot delete stack #{@stack_name.color(:green)} in this state: #{stack.stack_status.color(:green)}"
17
+ logger.info "If the stack is taking a long time, you can cancel the current operation with:"
18
+ logger.info " ufo cancel #{@service}"
17
19
  return
18
20
  end
19
21
 
20
- cfn.delete_stack(stack_name: @stack_name)
21
- puts "Deleting stack #{@stack_name.color(:green)}"
22
-
23
- return unless @options[:wait]
24
- status.wait
22
+ run_hooks(name: "destroy", file: "ufo.rb") do
23
+ cfn.delete_stack(stack_name: @stack_name)
24
+ logger.info "Deleting stack #{@stack_name.color(:green)}"
25
+ return unless @options[:wait]
26
+ status.wait
27
+ end
25
28
  end
26
29
 
27
30
  def are_you_sure?
@@ -0,0 +1,7 @@
1
+ ## Examples
2
+
3
+ $ ufo new hook docker
4
+ create .ufo/config/hooks/docker.rb
5
+ $ ufo new hook ufo
6
+ create .ufo/config/hooks/ufo.rb
7
+ $
@@ -0,0 +1,18 @@
1
+ class Ufo::CLI::New
2
+ class Hook < Sequence
3
+ argument :type, default: "ufo", description: "IE: docker, ufo" # description doesnt really show up
4
+
5
+ def self.cli_options
6
+ [
7
+ [:force, aliases: ["y"], type: :boolean, desc: "Bypass overwrite are you sure prompt for existing files"],
8
+ ]
9
+ end
10
+ cli_options.each { |args| class_option(*args) }
11
+
12
+ public
13
+ def create_hook
14
+ set_template_source("hooks")
15
+ template "#{type}.rb", ".ufo/config/hooks/#{type}.rb"
16
+ end
17
+ end
18
+ end
data/lib/ufo/cli/new.rb CHANGED
@@ -1,17 +1,24 @@
1
1
  class Ufo::CLI
2
2
  class New < Ufo::Command
3
- desc "boot_hook", "Generate boot_hook file"
3
+ desc "boot_hook", "Generate boot_hook"
4
4
  long_desc Help.text("new/boot_hook")
5
5
  BootHook.cli_options.each do |args|
6
6
  option(*args)
7
7
  end
8
- register(BootHook, "boot_hook", "boot_hook", "Generate boot_hook file")
8
+ register(BootHook, "boot_hook", "boot_hook", "Generate boot_hook")
9
9
 
10
- desc "helper", "Generate helper file"
10
+ desc "helper", "Generate helper"
11
11
  long_desc Help.text("new/helper")
12
12
  Helper.cli_options.each do |args|
13
13
  option(*args)
14
14
  end
15
- register(Helper, "helper", "helper", "Generate helper file")
15
+ register(Helper, "helper", "helper", "Generate helper")
16
+
17
+ desc "hook", "Generate hook"
18
+ long_desc Help.text("new/hook")
19
+ Hook.cli_options.each do |args|
20
+ option(*args)
21
+ end
22
+ register(Hook, "hook", "hook", "Generate hook")
16
23
  end
17
24
  end
data/lib/ufo/cli/scale.rb CHANGED
@@ -54,6 +54,7 @@ class Ufo::CLI
54
54
 
55
55
  def register_scalable_target(scalable_target)
56
56
  # service/dev/app1-web-dev-EcsService-Q0XkN6VtxGWv|ecs:service:DesiredCount|ecs
57
+ return unless scalable_target && scalable_target.physical_resource_id # stack still creating
57
58
  resource_id, scalable_dimension, service_namespace = scalable_target.physical_resource_id.split('|')
58
59
  applicationautoscaling.register_scalable_target(
59
60
  max_capacity: @max,
data/lib/ufo/command.rb CHANGED
@@ -78,7 +78,7 @@ module Ufo
78
78
  # See comment where configure_dsl_evaluator is used about Ufo.role
79
79
  def configure_dsl_evaluator
80
80
  DslEvaluator.configure do |config|
81
- config.backtrace.select_pattern = Ufo.root.to_s
81
+ config.backtrace.select_pattern = "#{Ufo.root}/.ufo"
82
82
  config.logger = Ufo.logger
83
83
  config.on_exception = :exit
84
84
  config.root = Ufo.root
data/lib/ufo/config.rb CHANGED
@@ -85,6 +85,9 @@ module Ufo
85
85
  config.exec.command = "/bin/bash" # aws ecs execute-command cli
86
86
  config.exec.enabled = true # EcsService EnableExecuteCommand
87
87
 
88
+ config.hooks = ActiveSupport::OrderedOptions.new
89
+ config.hooks.show = true
90
+
88
91
  config.layering = ActiveSupport::OrderedOptions.new
89
92
  config.layering.show = parsed_layering_show
90
93
  config.layering.show_for_commands = parsed_layering_show_for
@@ -2,6 +2,7 @@ module Ufo::Docker
2
2
  class Builder
3
3
  extend Memoist
4
4
  include Concerns
5
+ include Ufo::Hooks::Concern
5
6
 
6
7
  delegate :push, to: :pusher
7
8
  def self.build(options={})
@@ -28,7 +29,10 @@ module Ufo::Docker
28
29
  update_auth_token
29
30
  command = "docker build #{build_options}-t #{docker_image} -f #{@dockerfile} ."
30
31
  log = ".ufo/log/docker.log" if @options[:quiet]
31
- success = execute(command, log: log)
32
+ success = nil
33
+ run_hooks(name: "build", file: "docker.rb") do
34
+ success = execute(command, log: log)
35
+ end
32
36
  unless success
33
37
  docker_version_success = system("docker version > /dev/null 2>&1")
34
38
  unless docker_version_success
@@ -1,6 +1,7 @@
1
1
  module Ufo::Docker
2
2
  class Pusher
3
3
  include Concerns
4
+ include Ufo::Hooks::Concern
4
5
 
5
6
  delegate :docker_image, to: :builder
6
7
  attr_reader :last_image_name
@@ -17,7 +18,10 @@ module Ufo::Docker
17
18
  logger.info "Pushing Docker Image"
18
19
  command = "docker push #{last_image_name}"
19
20
  log = ".ufo/log/docker.log" if @options[:quiet]
20
- success = execute(command, log: log)
21
+ success = nil
22
+ run_hooks(name: "push", file: "docker.rb") do
23
+ success = execute(command, log: log)
24
+ end
21
25
  unless success
22
26
  logger.info "ERROR: The docker image fail to push.".color(:red)
23
27
  exit 1
@@ -0,0 +1,51 @@
1
+ module Ufo::Hooks
2
+ class Builder
3
+ extend Memoist
4
+ include Dsl
5
+ include DslEvaluator
6
+ include Ufo::Utils::Logging
7
+
8
+ attr_accessor :name
9
+ def initialize(options={})
10
+ @options = options
11
+ @file = options[:file] # IE: docker.rb
12
+ @dsl_file = "#{Ufo.root}/.ufo/config/hooks/#{@file}"
13
+ @name = options[:name].to_s
14
+ @hooks = {before: {}, after: {}}
15
+ end
16
+
17
+ def build
18
+ evaluate_file(@dsl_file)
19
+ @hooks.deep_stringify_keys!
20
+ end
21
+ memoize :build
22
+
23
+ def run_hooks
24
+ build
25
+ run_each_hook("before")
26
+ out = yield if block_given?
27
+ run_each_hook("after")
28
+ out
29
+ end
30
+
31
+ def run_each_hook(type)
32
+ hooks = @hooks.dig(type, @name) || []
33
+ hooks.each do |hook|
34
+ run_hook(type, hook)
35
+ end
36
+ end
37
+
38
+ def run_hook(type, hook)
39
+ return unless run?(hook)
40
+
41
+ id = "#{type} #{@name}"
42
+ label = " label: #{hook["label"]}" if hook["label"]
43
+ logger.info "Hook: Running #{id} hook#{label}".color(:cyan) if Ufo.config.hooks.show
44
+ Runner.new(hook).run
45
+ end
46
+
47
+ def run?(hook)
48
+ !!hook["execute"]
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,10 @@
1
+ module Ufo::Hooks
2
+ module Concern
3
+ # options example: {name: "build", file: "docker.rb"}
4
+ def run_hooks(options={}, &block)
5
+ hooks = Ufo::Hooks::Builder.new(options)
6
+ hooks.build # build hooks
7
+ hooks.run_hooks(&block)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ module Ufo::Hooks
2
+ module Dsl
3
+ def before(*commands, **props)
4
+ commands.each do |name|
5
+ each_hook(:before, name, props)
6
+ end
7
+ end
8
+
9
+ def after(*commands, **props)
10
+ commands.each do |name|
11
+ each_hook(:after, name, props)
12
+ end
13
+ end
14
+
15
+ def each_hook(type, name, props={})
16
+ @hooks[type][name] ||= []
17
+ @hooks[type][name] << props
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ module Ufo::Hooks
2
+ class Runner
3
+ include Ufo::Utils::Logging
4
+ include Ufo::Utils::Execute
5
+
6
+ attr_reader :hook
7
+ def initialize(hook)
8
+ @hook = hook
9
+ @execute = @hook["execute"]
10
+ end
11
+
12
+ def run
13
+ case @execute
14
+ when String
15
+ execute(@execute, exit_on_fail: @hook["exit_on_fail"])
16
+ when -> (e) { e.respond_to?(:public_instance_methods) && e.public_instance_methods.include?(:call) }
17
+ executor = @execute.new
18
+ when -> (e) { e.respond_to?(:call) }
19
+ executor = @execute
20
+ else
21
+ logger.warn "WARN: execute option not set for hook: #{@hook.inspect}"
22
+ end
23
+
24
+ return unless executor
25
+
26
+ meth = executor.method(:call)
27
+ case meth.arity
28
+ when 0
29
+ executor.call # backwards compatibility
30
+ when 1
31
+ executor.call(self)
32
+ else
33
+ raise "The #{executor} call method definition has been more than 1 arguments and is not supported"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,5 +1,5 @@
1
1
  module Ufo::IamRole
2
- class DSL
2
+ class Dsl
3
3
  include DslEvaluator
4
4
  include Ufo::TaskDefinition::Helpers::AwsHelper
5
5
 
@@ -11,13 +11,13 @@ module Ufo::IamRole
11
11
  def register_policy(role_type, policy_name, *statements)
12
12
  statements.flatten!
13
13
  self.policies[role_type] ||= Set.new
14
- self.policies[role_type].add([policy_name, statements]) # using set so DSL can safely be evaluated multiple times
14
+ self.policies[role_type].add([policy_name, statements]) # using set so Dsl can safely be evaluated multiple times
15
15
  end
16
16
 
17
17
  def register_managed_policy(role_type, *policies)
18
18
  policies.flatten!
19
19
  self.managed_policies[role_type] ||= Set.new
20
- self.managed_policies[role_type].merge(policies) # using set so DSL can safely be evaluated multiple times
20
+ self.managed_policies[role_type].merge(policies) # using set so Dsl can safely be evaluated multiple times
21
21
  end
22
22
  end
23
23
  end
data/lib/ufo/info.rb CHANGED
@@ -28,6 +28,7 @@ module Ufo
28
28
  )
29
29
  target_group = resp.target_groups.first
30
30
  load_balancer_arn = target_group.load_balancer_arns.first # assume first only
31
+ return unless load_balancer_arn # can occur while stack is being deleted
31
32
 
32
33
  resp = elb.describe_load_balancers(load_balancer_arns: [load_balancer_arn])
33
34
  resp.load_balancers.first
@@ -68,18 +68,15 @@ module Ufo::Layering
68
68
  paths
69
69
  end
70
70
 
71
- @@shown = false
72
71
  def show_layers(paths)
73
- return if @@shown
74
72
  logger.debug "Layers:"
75
73
  paths.each do |path|
76
74
  if ENV['UFO_LAYERS_ALL']
77
75
  logger.info " #{pretty_path(path)}"
78
- elsif Ufo.config.show_layers?
76
+ elsif Ufo.config.layering.show
79
77
  logger.info " #{pretty_path(path)}" if File.exist?(path)
80
78
  end
81
79
  end
82
- @@shown = true
83
80
  end
84
81
  end
85
82
  end
data/lib/ufo/param.rb CHANGED
@@ -18,8 +18,7 @@ module Ufo
18
18
  memoize :data
19
19
 
20
20
  def template_scope
21
- self # TODO: add access to helpers like network
22
- # @template_scope ||= Ufo::TemplateScope.new(Ufo::DSL::Helper.new, nil)
21
+ self
23
22
  end
24
23
  end
25
24
  end
@@ -14,7 +14,7 @@ module Ufo::TaskDefinition::Helpers
14
14
  else
15
15
  # Logger causes infinite loop when waf helper used in .ufo/
16
16
  logger.warn "WARN: ACM cert not found: #{domain}".color(:yellow)
17
- call_line = ufo_config_call_line
17
+ call_line = ufo_call_line
18
18
  DslEvaluator.print_code(call_line)
19
19
  nil
20
20
  end
@@ -12,7 +12,7 @@ module Ufo::TaskDefinition::Helpers
12
12
  resp.repositories.first
13
13
  rescue Aws::ECR::Errors::RepositoryNotFoundException => e
14
14
  logger.warn "WARN: #{e.class} #{e.message}".color(:yellow)
15
- call_line = ufo_config_call_line
15
+ call_line = ufo_call_line
16
16
  DslEvaluator.print_code(call_line)
17
17
  nil
18
18
  end
@@ -9,7 +9,7 @@ module Ufo::TaskDefinition::Helpers
9
9
  stack = find_stack(stack_name)
10
10
  unless stack
11
11
  logger.error "ERROR: Stack not found: #{stack_name}".color(:red)
12
- call_line = ufo_config_call_line
12
+ call_line = ufo_call_line
13
13
  DslEvaluator.print_code(call_line)
14
14
  return
15
15
  end
@@ -17,33 +17,61 @@ module Ufo::TaskDefinition::Helpers::Vars
17
17
  end
18
18
 
19
19
  def content
20
- @text || read(@file)
20
+ @text if @text
21
+ read(*find_files)
21
22
  end
22
23
 
23
- def read(path)
24
- full_path = "#{Ufo.root}/#{path}"
25
- unless File.exist?(full_path)
26
- logger.warn "WARN: The #{pretty_path(full_path)} env file could not be found. Are you sure it exists?".color(:yellow)
27
- logger.warn <<~EOL
28
- You can disable this warning with: secrets.warning = false
24
+ # Not considering .env files in project root since this is more for deployment
25
+ # Also ufo supports a smarter format than the normal .env files
26
+ def find_files
27
+ return @file if @file
28
+ layers = [
29
+ "base",
30
+ "#{Ufo.env}",
31
+ "#{Ufo.app}",
32
+ "#{Ufo.app}/base",
33
+ "#{Ufo.app}/#{Ufo.env}",
34
+ "#{Ufo.app}/#{Ufo.role}",
35
+ "#{Ufo.app}/#{Ufo.role}/base",
36
+ "#{Ufo.app}/#{Ufo.role}/#{Ufo.env}",
37
+ ]
38
+ layers.map! { |l| ".ufo/env_files/#{l}#{@ext}" }
39
+ show_layers(layers)
40
+ layers.select! { |l| File.exist?(l) }
41
+ layers
42
+ end
29
43
 
30
- See: https://ufoships.com/docs/helpers/builtin/secrets/
44
+ def show_layers(paths)
45
+ label = @ext.sub('.','').capitalize
46
+ paths.each do |path|
47
+ if ENV['UFO_LAYERS_ALL']
48
+ logger.info " #{path}"
49
+ elsif Ufo.config.layering.show
50
+ logger.info " #{path} "if File.exist?(path)
51
+ end
52
+ end
53
+ end
31
54
 
32
- EOL
33
- call_line = ufo_config_call_line
34
- DslEvaluator.print_code(call_line)
35
- return ''
55
+ def read(*paths)
56
+ text= ""
57
+ paths.compact.each do |path|
58
+ text << IO.read("#{Ufo.root}/#{path}")
59
+ text << "\n"
36
60
  end
37
- IO.read(full_path)
61
+ text
38
62
  end
39
63
 
40
- def env
64
+ def env(ext='.env')
65
+ @ext = ext # assign instance variable so dont have to pass around
41
66
  lines = filtered_lines(content)
42
67
  lines.map do |line|
68
+ line = line.sub('export ', '') # allow user to use export. ufo ignores it
43
69
  key,*value = line.strip.split("=").map do |x|
44
70
  remove_surrounding_quotes(x.strip)
45
71
  end
46
72
  value = value.join('=')
73
+ # Note: env vars do NOT support valueFrom
74
+ # Docs: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_environment
47
75
  {
48
76
  name: key,
49
77
  value: value,
@@ -52,7 +80,7 @@ module Ufo::TaskDefinition::Helpers::Vars
52
80
  end
53
81
 
54
82
  def secrets
55
- secrets = env
83
+ secrets = env('.secrets')
56
84
  secrets.map do |item|
57
85
  value = item.delete(:value)
58
86
  arn = normalize_to_arn(item[:name], value)
@@ -79,11 +107,15 @@ module Ufo::TaskDefinition::Helpers::Vars
79
107
  # arn:aws:ssm:us-west-2:111111111111:parameter/demo/dev/DB-NAME
80
108
  # arn:aws:ssm:us-west-2:111111111111:parameter/demo/dev/DB-NAME
81
109
  def expansion(arn)
82
- # performance improvement only run names.expansion on the name portion
83
110
  md = arn.match(/(.*:)(parameter\/|secret:)(.*)/)
84
- prefix, type, name = md[1], md[2], md[3]
85
- expanded_name = names.expansion(name, dasherize: false) # dasherize: false. dont turn SECRET_NAME => SECRET-NAME
86
- "#{prefix}#{type}#{expanded_name}"
111
+ if md
112
+ prefix, type, name = md[1], md[2], md[3]
113
+ # performance improvement only run names.expansion on the name portion
114
+ expanded_name = names.expansion(name, dasherize: false) # dasherize: false. dont turn SECRET_NAME => SECRET-NAME
115
+ "#{prefix}#{type}#{expanded_name}"
116
+ else # not arn full value. In case user accidentally puts value in .secrets file KEY=value
117
+ names.expansion(arn, dasherize: false) # dasherize: false. dont turn SECRET_NAME => SECRET-NAME
118
+ end
87
119
  end
88
120
 
89
121
  # Examples with config.secrets.provider = "ssm"
@@ -6,7 +6,7 @@ module Ufo::TaskDefinition::Helpers
6
6
  alias_method :env_vars, :env
7
7
  alias_method :environment, :env
8
8
 
9
- def env_file(path)
9
+ def env_file(path=nil)
10
10
  Builder.new(file: path).env
11
11
  end
12
12
 
@@ -14,7 +14,7 @@ module Ufo::TaskDefinition::Helpers
14
14
  Builder.new(text: text).secrets
15
15
  end
16
16
 
17
- def secrets_file(path)
17
+ def secrets_file(path=nil)
18
18
  Builder.new(file: path).secrets
19
19
  end
20
20
  end
@@ -20,7 +20,7 @@ module Ufo::TaskDefinition::Helpers
20
20
  else
21
21
  # Logger causes infinite loop when waf helper used in .ufo/
22
22
  logger.warn "WARN: Web ACL not found: #{name}".color(:yellow)
23
- call_line = ufo_config_call_line
23
+ call_line = ufo_call_line
24
24
  DslEvaluator.print_code(call_line)
25
25
  end
26
26
  end
@@ -2,7 +2,7 @@ module Ufo::Utils
2
2
  module CallLine
3
3
  include Pretty
4
4
 
5
- def ufo_config_call_line
5
+ def ufo_call_line
6
6
  caller.find { |l| l.include?('.ufo/') }
7
7
  end
8
8
  end
data/lib/ufo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ufo
2
- VERSION = "6.2.4"
2
+ VERSION = "6.3.1"
3
3
  end
@@ -12,7 +12,7 @@ describe Ufo::IamRole::Builder do
12
12
  {:Action=>["cloudwatch:PutMetricData"], :Effect=>"Allow", :Resource=>"*"}
13
13
  )
14
14
  # Called twice on purpose to show that duplicated items in the set wont create doubles.
15
- # This allows the DSL evaluate to be ran multiple times.
15
+ # This allows the Dsl evaluate to be ran multiple times.
16
16
  Ufo::IamRole::Registry.register_policy("task_role",
17
17
  "CloudwatchWrite",
18
18
  {:Action=>["cloudwatch:PutMetricData"], :Effect=>"Allow", :Resource=>"*"}
@@ -1,9 +1,9 @@
1
- describe Ufo::IamRole::DSL do
1
+ describe Ufo::IamRole::Dsl do
2
2
  let(:dsl) { described_class.new(path) }
3
3
  let(:path) { "spec/fixtures/iam_roles/task_role.rb" }
4
4
 
5
5
  context "evaluate" do
6
- it "registers policies from role DSL" do
6
+ it "registers policies from role Dsl" do
7
7
  dsl.evaluate
8
8
  expect(Ufo::IamRole::Registry.policies).not_to be_empty
9
9
  expect(Ufo::IamRole::Registry.managed_policies).not_to be_empty
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.2.4
4
+ version: 6.3.1
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-20 00:00:00.000000000 Z
11
+ date: 2022-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-logs
@@ -453,10 +453,11 @@ extensions: []
453
453
  extra_rdoc_files: []
454
454
  files:
455
455
  - ".cody/README.md"
456
+ - ".cody/acceptance/bin/asg.sh"
456
457
  - ".cody/acceptance/bin/build.sh"
457
458
  - ".cody/acceptance/buildspec.yml"
459
+ - ".cody/acceptance/iam_role.rb"
458
460
  - ".cody/acceptance/project.rb"
459
- - ".cody/acceptance/role.rb"
460
461
  - ".cody/shared/script/install.sh"
461
462
  - ".cody/shared/script/install/ufo.sh"
462
463
  - ".github/ISSUE_TEMPLATE.md"
@@ -479,6 +480,8 @@ files:
479
480
  - lib/templates/boot_hook/.ufo/config/boot.rb
480
481
  - lib/templates/docker/Dockerfile
481
482
  - lib/templates/helper/%underscore_name%_helper.rb.tt
483
+ - lib/templates/hooks/docker.rb
484
+ - lib/templates/hooks/ufo.rb
482
485
  - lib/templates/init/.ufo/config.rb.tt
483
486
  - lib/templates/init/.ufo/config/web/base.rb
484
487
  - lib/templates/init/.ufo/config/web/dev.rb
@@ -558,6 +561,7 @@ files:
558
561
  - lib/ufo/cli/help/init.md
559
562
  - lib/ufo/cli/help/logs.md
560
563
  - lib/ufo/cli/help/new/boot_hook.md
564
+ - lib/ufo/cli/help/new/hook.md
561
565
  - lib/ufo/cli/help/ps.md
562
566
  - lib/ufo/cli/help/releases.md
563
567
  - lib/ufo/cli/help/rollback.md
@@ -569,6 +573,7 @@ files:
569
573
  - lib/ufo/cli/new/boot_hook.rb
570
574
  - lib/ufo/cli/new/concerns.rb
571
575
  - lib/ufo/cli/new/helper.rb
576
+ - lib/ufo/cli/new/hook.rb
572
577
  - lib/ufo/cli/new/init.rb
573
578
  - lib/ufo/cli/new/sequence.rb
574
579
  - lib/ufo/cli/opts.rb
@@ -613,6 +618,10 @@ files:
613
618
  - lib/ufo/ext.rb
614
619
  - lib/ufo/ext/core/module.rb
615
620
  - lib/ufo/ext/core/nil_class.rb
621
+ - lib/ufo/hooks/builder.rb
622
+ - lib/ufo/hooks/concern.rb
623
+ - lib/ufo/hooks/dsl.rb
624
+ - lib/ufo/hooks/runner.rb
616
625
  - lib/ufo/iam_role/builder.rb
617
626
  - lib/ufo/iam_role/dsl.rb
618
627
  - lib/ufo/iam_role/registry.rb