ufo 6.2.5 → 6.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|