ufo 6.2.5 → 6.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/lib/templates/env_file/file.env +2 -0
- data/lib/templates/env_file/file.secrets.tt +5 -0
- data/lib/templates/hook/docker.rb +9 -0
- data/lib/templates/hook/ufo.rb +9 -0
- data/lib/templates/init/.ufo/config.rb.tt +1 -2
- data/lib/templates/init/.ufo/vars/base.rb +2 -2
- data/lib/ufo/autoloader.rb +1 -1
- data/lib/ufo/cfn/stack/builder/resources/dns.rb +38 -1
- data/lib/ufo/cfn/stack/builder/resources/iam_roles/base.rb +2 -2
- data/lib/ufo/cfn/stack/builder/resources/listener.rb +2 -2
- data/lib/ufo/cfn/stack/vars.rb +18 -2
- data/lib/ufo/cfn/stack.rb +17 -13
- data/lib/ufo/cli/build.rb +0 -5
- data/lib/ufo/cli/destroy.rb +13 -10
- data/lib/ufo/cli/help/new/hook.md +7 -0
- data/lib/ufo/cli/new/env_file.rb +18 -0
- data/lib/ufo/cli/new/hook.rb +18 -0
- data/lib/ufo/cli/new.rb +18 -4
- data/lib/ufo/config/parse.rb +4 -2
- data/lib/ufo/config.rb +9 -4
- data/lib/ufo/docker/builder.rb +5 -1
- data/lib/ufo/docker/pusher.rb +5 -1
- data/lib/ufo/hooks/builder.rb +51 -0
- data/lib/ufo/hooks/concern.rb +10 -0
- data/lib/ufo/hooks/dsl.rb +20 -0
- data/lib/ufo/hooks/runner.rb +37 -0
- data/lib/ufo/iam_role/dsl.rb +1 -1
- data/lib/ufo/iam_role/registry.rb +2 -2
- data/lib/ufo/param.rb +1 -2
- data/lib/ufo/task_definition/helpers/vars/builder.rb +30 -7
- data/lib/ufo/version.rb +1 -1
- data/spec/ufo/iam_role/builder_spec.rb +1 -1
- data/spec/ufo/iam_role/dsl_spec.rb +2 -2
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee25a6ee92c06422088b489aa3f9d27d8fb0dfd229b7bb6e0b0eb2241a4d3902
|
4
|
+
data.tar.gz: f4a8043b8ab3bbb33794d3002d58890d8aa4753ffe3ac4b029432599195e5289
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76beccace3016451330c40b589fa7c3f95680eff187a667f520eed80c7d4cd90b91667dd06d58288cabf4c5d5acb699cf53ecc6c296dcb48e66504a0c02147ad
|
7
|
+
data.tar.gz: 22700e11a6de03b489deacf6fbde1e7b5652b4048b078b1d3750dfc0f1b083e5e3bbc417057f04d9fe73e48ac609139aea92bc526ae4c33cfdee16253f341db8
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,17 @@
|
|
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.2] - 2022-03-26
|
7
|
+
- [#164](https://github.com/tongueroo/ufo/pull/164) existing elb target group support
|
8
|
+
- [#165](https://github.com/tongueroo/ufo/pull/165) improve secrets support
|
9
|
+
- [#166](https://github.com/tongueroo/ufo/pull/166) infer elb dns name from target group when possible
|
10
|
+
|
11
|
+
## [6.3.1] - 2022-03-25
|
12
|
+
- ufo init: improve vars base.rb
|
13
|
+
|
14
|
+
## [6.3.0] - 2022-03-25
|
15
|
+
- [#162](https://github.com/tongueroo/ufo/pull/162) hooks support
|
16
|
+
|
6
17
|
## [6.2.5] - 2022-03-24
|
7
18
|
- [#159](https://github.com/tongueroo/ufo/pull/159) improve ufo call line
|
8
19
|
- [#160](https://github.com/tongueroo/ufo/pull/160) conventionally lookup up secrets and env file
|
@@ -35,6 +35,5 @@ Ufo.configure do |config|
|
|
35
35
|
# config.logs.filter_pattern = '- "HealthChecker"'
|
36
36
|
|
37
37
|
# Docs: https://ufoships.com/docs/config/reference/
|
38
|
-
#
|
39
|
-
# config.ship.docker.quiet = false # default is true.
|
38
|
+
# config.ship.docker.quiet = true # default is false
|
40
39
|
end
|
@@ -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
|
-
|
11
|
-
|
10
|
+
@environment = env_file
|
11
|
+
@secrets = secrets_file
|
12
12
|
@cpu = 256
|
13
13
|
@memory = 256
|
14
14
|
@memory_reservation = 256
|
data/lib/ufo/autoloader.rb
CHANGED
@@ -8,7 +8,7 @@ class Ufo::Cfn::Stack::Builder::Resources
|
|
8
8
|
Comment: dns.comment,
|
9
9
|
Type: dns.type, # CNAME
|
10
10
|
TTL: dns.ttl, # 60 ttl has special casing
|
11
|
-
ResourceRecords: [
|
11
|
+
ResourceRecords: [resource_record]
|
12
12
|
}
|
13
13
|
# HostedZoneName: yourdomain. # dont forget the trailing period
|
14
14
|
props[:HostedZoneName] = hosted_zone_name if hosted_zone_name
|
@@ -21,6 +21,43 @@ class Ufo::Cfn::Stack::Builder::Resources
|
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
24
|
+
def resource_record
|
25
|
+
existing = Ufo.config.elb.existing
|
26
|
+
if existing.target_group
|
27
|
+
existing_dns_name
|
28
|
+
else
|
29
|
+
{"Fn::GetAtt": "Elb.DNSName"}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def existing_dns_name
|
34
|
+
existing = Ufo.config.elb.existing
|
35
|
+
resp = elb.describe_target_groups(target_group_arns: [existing.target_group])
|
36
|
+
target_group = resp.target_groups.first
|
37
|
+
load_balancer_arns = target_group.load_balancer_arns
|
38
|
+
if load_balancer_arns.size == 1
|
39
|
+
resp = elb.describe_load_balancers(load_balancer_arns: load_balancer_arns)
|
40
|
+
load_balancer = resp.load_balancers.first
|
41
|
+
load_balancer.dns_name
|
42
|
+
else
|
43
|
+
return existing.dns_name if existing.dns_name
|
44
|
+
logger.error "ERROR: config.existing.dns_name must to be set".color(:red)
|
45
|
+
logger.error <<~EOL
|
46
|
+
This target group is associated with multiple load balancers.
|
47
|
+
UFO cannot infer the dns name in this case. You must set:
|
48
|
+
|
49
|
+
config.existing.dns_name
|
50
|
+
|
51
|
+
Info:
|
52
|
+
|
53
|
+
target group: #{existing.target_group}
|
54
|
+
load balancers: #{load_balancer_arns}
|
55
|
+
|
56
|
+
EOL
|
57
|
+
exit 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
24
61
|
def dns_name
|
25
62
|
return unless dns.domain || dns.name
|
26
63
|
name = dns.name # my.domain.com
|
@@ -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
|
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::
|
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
|
|
@@ -55,8 +55,8 @@ class Ufo::Cfn::Stack::Builder::Resources
|
|
55
55
|
TargetGroupArn: {
|
56
56
|
"Fn::If": [
|
57
57
|
"ElbTargetGroupIsBlank",
|
58
|
-
{Ref: "TargetGroup"},
|
59
|
-
{Ref: "ElbTargetGroup"}
|
58
|
+
{Ref: "TargetGroup"}, # UFO managed
|
59
|
+
{Ref: "ElbTargetGroup"} # Managed by user outside of UFO
|
60
60
|
]
|
61
61
|
}
|
62
62
|
}
|
data/lib/ufo/cfn/stack/vars.rb
CHANGED
@@ -9,10 +9,11 @@ class Ufo::Cfn::Stack
|
|
9
9
|
container: container,
|
10
10
|
create_elb: create_elb?, # helps set Ecs DependsOn
|
11
11
|
create_listener_ssl: create_listener_ssl?,
|
12
|
-
create_route53:
|
12
|
+
create_route53: create_route53?,
|
13
13
|
default_listener_protocol: default_listener_protocol,
|
14
14
|
default_listener_ssl_protocol: default_listener_ssl_protocol,
|
15
15
|
default_target_group_protocol: default_target_group_protocol,
|
16
|
+
elb_target_group: elb_target_group,
|
16
17
|
elb_type: elb_type,
|
17
18
|
new_stack: new_stack,
|
18
19
|
rollback_task_definition: rollback_task_definition,
|
@@ -63,15 +64,30 @@ class Ufo::Cfn::Stack
|
|
63
64
|
elb.ssl.enabled && elb.ssl.certificates
|
64
65
|
end
|
65
66
|
|
67
|
+
def create_route53?
|
68
|
+
return false unless dns_configured?
|
69
|
+
if create_elb?
|
70
|
+
true
|
71
|
+
else
|
72
|
+
Ufo.config.elb.existing.target_group
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
66
76
|
def create_elb?
|
67
77
|
elb = Ufo.config.elb
|
68
|
-
if elb.
|
78
|
+
if elb.existing.target_group
|
79
|
+
false
|
80
|
+
elsif elb.enabled.to_s == "auto"
|
69
81
|
container[:name] == "web" # convention
|
70
82
|
else
|
71
83
|
elb.enabled # true or false
|
72
84
|
end
|
73
85
|
end
|
74
86
|
|
87
|
+
def elb_target_group
|
88
|
+
Ufo.config.elb.existing.target_group
|
89
|
+
end
|
90
|
+
|
75
91
|
def container
|
76
92
|
task_definition = Builder::Resources::TaskDefinition::Reconstructor.new(@task_definition, @options[:rollback]).reconstruct
|
77
93
|
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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
data/lib/ufo/cli/destroy.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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,18 @@
|
|
1
|
+
class Ufo::CLI::New
|
2
|
+
class EnvFile < Sequence
|
3
|
+
argument :type, default: "env", description: "IE: env or secrets" # 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("env_file")
|
15
|
+
template "file.#{type}", ".ufo/config/env_files/#{Ufo.env}.#{type}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -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("hook")
|
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,31 @@
|
|
1
1
|
class Ufo::CLI
|
2
2
|
class New < Ufo::Command
|
3
|
-
desc "boot_hook", "Generate boot_hook
|
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
|
8
|
+
register(BootHook, "boot_hook", "boot_hook", "Generate boot_hook")
|
9
9
|
|
10
|
-
desc "
|
10
|
+
desc "env_file", "Generate env_file"
|
11
|
+
long_desc Help.text("new/env_file")
|
12
|
+
EnvFile.cli_options.each do |args|
|
13
|
+
option(*args)
|
14
|
+
end
|
15
|
+
register(EnvFile, "env_file", "env_file", "Generate env_file")
|
16
|
+
|
17
|
+
desc "helper", "Generate helper"
|
11
18
|
long_desc Help.text("new/helper")
|
12
19
|
Helper.cli_options.each do |args|
|
13
20
|
option(*args)
|
14
21
|
end
|
15
|
-
register(Helper, "helper", "helper", "Generate helper
|
22
|
+
register(Helper, "helper", "helper", "Generate helper")
|
23
|
+
|
24
|
+
desc "hook", "Generate hook"
|
25
|
+
long_desc Help.text("new/hook")
|
26
|
+
Hook.cli_options.each do |args|
|
27
|
+
option(*args)
|
28
|
+
end
|
29
|
+
register(Hook, "hook", "hook", "Generate hook")
|
16
30
|
end
|
17
31
|
end
|
data/lib/ufo/config/parse.rb
CHANGED
@@ -19,10 +19,12 @@ class Ufo::Config
|
|
19
19
|
return false unless config_line # default is false
|
20
20
|
config_value = config_line.gsub(/.*=/,'').strip.gsub(/["']/,'')
|
21
21
|
case type
|
22
|
-
when :boolean
|
23
|
-
config_value != "false" && config_value != "nil"
|
24
22
|
when :array
|
25
23
|
eval(config_value) # IE: '["a"]' => ["a"]
|
24
|
+
when :boolean
|
25
|
+
config_value != "false" && config_value != "nil"
|
26
|
+
when :string
|
27
|
+
config_value.sub(/\s+#.*/,'') # remove trailing comment
|
26
28
|
else
|
27
29
|
raise "Type #{type.inspect} not supported"
|
28
30
|
end
|
data/lib/ufo/config.rb
CHANGED
@@ -63,6 +63,10 @@ module Ufo
|
|
63
63
|
config.elb.default_actions = nil # full override
|
64
64
|
config.elb.enabled = "auto" # "auto", true or false
|
65
65
|
|
66
|
+
config.elb.existing = ActiveSupport::OrderedOptions.new
|
67
|
+
config.elb.existing.target_group = nil
|
68
|
+
config.elb.existing.dns_name = nil # for managed route53 records
|
69
|
+
|
66
70
|
config.elb.health_check_interval_seconds = 10 # keep at 10 in case of network ELB, which is min 10
|
67
71
|
config.elb.health_check_path = nil # When nil its AWS default /
|
68
72
|
config.elb.healthy_threshold_count = 3 # The AWS usual default is 5
|
@@ -85,6 +89,9 @@ module Ufo
|
|
85
89
|
config.exec.command = "/bin/bash" # aws ecs execute-command cli
|
86
90
|
config.exec.enabled = true # EcsService EnableExecuteCommand
|
87
91
|
|
92
|
+
config.hooks = ActiveSupport::OrderedOptions.new
|
93
|
+
config.hooks.show = true
|
94
|
+
|
88
95
|
config.layering = ActiveSupport::OrderedOptions.new
|
89
96
|
config.layering.show = parsed_layering_show
|
90
97
|
config.layering.show_for_commands = parsed_layering_show_for
|
@@ -108,11 +115,9 @@ module Ufo
|
|
108
115
|
config.ps.summary = true
|
109
116
|
|
110
117
|
config.secrets = ActiveSupport::OrderedOptions.new
|
111
|
-
config.secrets.
|
112
|
-
config.secrets.
|
113
|
-
config.secrets.pattern.ssm = ":APP/:ENV/:SECRET_NAME" # => demo/dev/DB_PASS
|
118
|
+
config.secrets.manager_pattern = ":APP/:ENV/:SECRET_NAME" # => demo/dev/DB_PASS
|
119
|
+
config.secrets.ssm_pattern = ":APP/:ENV/:SECRET_NAME" # => demo/dev/DB_PASS
|
114
120
|
config.secrets.provider = "ssm" # default provider for conventional expansion IE: ssm or secretsmanager
|
115
|
-
config.secrets.warning = true
|
116
121
|
|
117
122
|
config.ship = ActiveSupport::OrderedOptions.new
|
118
123
|
config.ship.docker = ActiveSupport::OrderedOptions.new
|
data/lib/ufo/docker/builder.rb
CHANGED
@@ -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 =
|
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
|
data/lib/ufo/docker/pusher.rb
CHANGED
@@ -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 =
|
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,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
|
data/lib/ufo/iam_role/dsl.rb
CHANGED
@@ -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
|
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
|
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/param.rb
CHANGED
@@ -37,8 +37,7 @@ module Ufo::TaskDefinition::Helpers::Vars
|
|
37
37
|
]
|
38
38
|
layers.map! { |l| ".ufo/env_files/#{l}#{@ext}" }
|
39
39
|
show_layers(layers)
|
40
|
-
layers.select
|
41
|
-
layers
|
40
|
+
layers.select { |l| File.exist?(l) }
|
42
41
|
end
|
43
42
|
|
44
43
|
def show_layers(paths)
|
@@ -63,7 +62,8 @@ module Ufo::TaskDefinition::Helpers::Vars
|
|
63
62
|
|
64
63
|
def env(ext='.env')
|
65
64
|
@ext = ext # assign instance variable so dont have to pass around
|
66
|
-
|
65
|
+
result = render_erb(content) # tricky: use result instead of content for variable assignment or content method is not called
|
66
|
+
lines = filtered_lines(result)
|
67
67
|
lines.map do |line|
|
68
68
|
line = line.sub('export ', '') # allow user to use export. ufo ignores it
|
69
69
|
key,*value = line.strip.split("=").map do |x|
|
@@ -97,7 +97,7 @@ module Ufo::TaskDefinition::Helpers::Vars
|
|
97
97
|
value.sub(/^ssm:/i, "arn:aws:ssm:#{region}:#{account}:parameter/")
|
98
98
|
when /^secretsmanager:/i
|
99
99
|
value.sub(/^secretsmanager:/i, "arn:aws:secretsmanager:#{region}:#{account}:secret:")
|
100
|
-
when '' # blank string will mean use convention
|
100
|
+
when '', *available_providers # blank string will mean use convention
|
101
101
|
conventional_pattern(name, value)
|
102
102
|
else
|
103
103
|
value # assume full arn has been passed
|
@@ -129,11 +129,11 @@ module Ufo::TaskDefinition::Helpers::Vars
|
|
129
129
|
# DB_NAME=:APP/:ENV/:SECRET_NAME # expansion will use => demo/dev/DB_NAME
|
130
130
|
#
|
131
131
|
def conventional_pattern(name, value)
|
132
|
-
|
133
|
-
provider = secrets.provider # ssm or secretsmanager
|
132
|
+
provider = get_provider(value)
|
134
133
|
namespace = provider == "ssm" ? "parameter/" : "secret:"
|
135
134
|
|
136
|
-
|
135
|
+
field = provider == "secretsmanager" ? "manager_pattern" : "ssm_pattern"
|
136
|
+
config_name = "secrets.#{field}"
|
137
137
|
pattern = callable_option(
|
138
138
|
config_name: config_name, # Ufo.config.names.stack => :APP-:ROLE-:ENV => demo-web-dev
|
139
139
|
passed_args: [self],
|
@@ -143,6 +143,22 @@ module Ufo::TaskDefinition::Helpers::Vars
|
|
143
143
|
"arn:aws:#{provider}:#{region}:#{account}:#{namespace}#{pattern}"
|
144
144
|
end
|
145
145
|
|
146
|
+
# Allows user to override one-off value. IE: DB_PASS=secretsmanager
|
147
|
+
# Note there's no point in disabling this override ability since valueFrom examples a reference.
|
148
|
+
#
|
149
|
+
# {
|
150
|
+
# "name": "PASS",
|
151
|
+
# "valueFrom": "arn:aws:ssm:us-west-2:1111111111111:parameter/demo/dev/PASS"
|
152
|
+
# }
|
153
|
+
#
|
154
|
+
def get_provider(value)
|
155
|
+
available_providers.include?(value) ? value : Ufo.config.secrets.provider
|
156
|
+
end
|
157
|
+
|
158
|
+
def available_providers
|
159
|
+
%w[ssm secretsmanager]
|
160
|
+
end
|
161
|
+
|
146
162
|
def remove_surrounding_quotes(s)
|
147
163
|
if s =~ /^"/ && s =~ /"$/
|
148
164
|
s.sub(/^["]/, '').gsub(/["]$/,'') # remove surrounding double quotes
|
@@ -162,5 +178,12 @@ module Ufo::TaskDefinition::Helpers::Vars
|
|
162
178
|
# filter out empty lines
|
163
179
|
lines = lines.reject { |l| l.strip.empty? }
|
164
180
|
end
|
181
|
+
|
182
|
+
def render_erb(content)
|
183
|
+
path = ".ufo/output/params.erb"
|
184
|
+
FileUtils.mkdir_p(File.dirname(path))
|
185
|
+
IO.write(path, content)
|
186
|
+
RenderMePretty.result(path, context: self)
|
187
|
+
end
|
165
188
|
end
|
166
189
|
end
|
data/lib/ufo/version.rb
CHANGED
@@ -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
|
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::
|
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
|
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
|
+
version: 6.3.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-
|
11
|
+
date: 2022-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-logs
|
@@ -479,7 +479,11 @@ files:
|
|
479
479
|
- exe/ufo
|
480
480
|
- lib/templates/boot_hook/.ufo/config/boot.rb
|
481
481
|
- lib/templates/docker/Dockerfile
|
482
|
+
- lib/templates/env_file/file.env
|
483
|
+
- lib/templates/env_file/file.secrets.tt
|
482
484
|
- lib/templates/helper/%underscore_name%_helper.rb.tt
|
485
|
+
- lib/templates/hook/docker.rb
|
486
|
+
- lib/templates/hook/ufo.rb
|
483
487
|
- lib/templates/init/.ufo/config.rb.tt
|
484
488
|
- lib/templates/init/.ufo/config/web/base.rb
|
485
489
|
- lib/templates/init/.ufo/config/web/dev.rb
|
@@ -559,6 +563,7 @@ files:
|
|
559
563
|
- lib/ufo/cli/help/init.md
|
560
564
|
- lib/ufo/cli/help/logs.md
|
561
565
|
- lib/ufo/cli/help/new/boot_hook.md
|
566
|
+
- lib/ufo/cli/help/new/hook.md
|
562
567
|
- lib/ufo/cli/help/ps.md
|
563
568
|
- lib/ufo/cli/help/releases.md
|
564
569
|
- lib/ufo/cli/help/rollback.md
|
@@ -569,7 +574,9 @@ files:
|
|
569
574
|
- lib/ufo/cli/new.rb
|
570
575
|
- lib/ufo/cli/new/boot_hook.rb
|
571
576
|
- lib/ufo/cli/new/concerns.rb
|
577
|
+
- lib/ufo/cli/new/env_file.rb
|
572
578
|
- lib/ufo/cli/new/helper.rb
|
579
|
+
- lib/ufo/cli/new/hook.rb
|
573
580
|
- lib/ufo/cli/new/init.rb
|
574
581
|
- lib/ufo/cli/new/sequence.rb
|
575
582
|
- lib/ufo/cli/opts.rb
|
@@ -614,6 +621,10 @@ files:
|
|
614
621
|
- lib/ufo/ext.rb
|
615
622
|
- lib/ufo/ext/core/module.rb
|
616
623
|
- lib/ufo/ext/core/nil_class.rb
|
624
|
+
- lib/ufo/hooks/builder.rb
|
625
|
+
- lib/ufo/hooks/concern.rb
|
626
|
+
- lib/ufo/hooks/dsl.rb
|
627
|
+
- lib/ufo/hooks/runner.rb
|
617
628
|
- lib/ufo/iam_role/builder.rb
|
618
629
|
- lib/ufo/iam_role/dsl.rb
|
619
630
|
- lib/ufo/iam_role/registry.rb
|