applb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +255 -0
- data/Rakefile +6 -0
- data/applb.gemspec +33 -0
- data/aws_config.yml.enc +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/applb +5 -0
- data/lib/applb.rb +14 -0
- data/lib/applb/cli.rb +80 -0
- data/lib/applb/client.rb +386 -0
- data/lib/applb/client_wrapper.rb +85 -0
- data/lib/applb/converter.rb +22 -0
- data/lib/applb/dsl.rb +56 -0
- data/lib/applb/dsl/attributes.rb +49 -0
- data/lib/applb/dsl/checker.rb +27 -0
- data/lib/applb/dsl/ec2.rb +35 -0
- data/lib/applb/dsl/listener.rb +140 -0
- data/lib/applb/dsl/listeners.rb +29 -0
- data/lib/applb/dsl/load_balancer.rb +209 -0
- data/lib/applb/dsl/rule.rb +157 -0
- data/lib/applb/dsl/rules.rb +32 -0
- data/lib/applb/dsl/target_group.rb +156 -0
- data/lib/applb/dsl/target_groups.rb +28 -0
- data/lib/applb/error.rb +4 -0
- data/lib/applb/exporter.rb +7 -0
- data/lib/applb/filterable.rb +13 -0
- data/lib/applb/output_alb.erb +122 -0
- data/lib/applb/template_helper.rb +20 -0
- data/lib/applb/utils.rb +48 -0
- data/lib/applb/version.rb +3 -0
- metadata +192 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
module Applb
|
2
|
+
class DSL
|
3
|
+
class EC2
|
4
|
+
class LoadBalancer
|
5
|
+
class Listeners
|
6
|
+
class Listener
|
7
|
+
class Rules
|
8
|
+
class Rule
|
9
|
+
include Applb::DSL::Checker
|
10
|
+
|
11
|
+
class Result
|
12
|
+
ATTRIBUTES = %i/priority actions conditions listener_arn rule_arn/
|
13
|
+
attr_accessor *ATTRIBUTES
|
14
|
+
|
15
|
+
def initialize(context, listener)
|
16
|
+
@context = context
|
17
|
+
@options = context.options
|
18
|
+
@listener = listener
|
19
|
+
end
|
20
|
+
|
21
|
+
def aws(aws_rule)
|
22
|
+
@aws_rule = aws_rule
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
Hash[ATTRIBUTES.sort.map { |name| [name, public_send(name)] }]
|
28
|
+
end
|
29
|
+
|
30
|
+
def create
|
31
|
+
Applb.logger.info("Create rule #{conditions.first[:values].first}")
|
32
|
+
return if @options[:dry_run]
|
33
|
+
|
34
|
+
Applb.logger.debug("create rule with option blow.")
|
35
|
+
Applb.logger.debug(create_option.pretty_inspect)
|
36
|
+
rule = client.create_rule(create_option).rules.first
|
37
|
+
rule_arn = rule.rule_arn
|
38
|
+
rule
|
39
|
+
end
|
40
|
+
|
41
|
+
def modify
|
42
|
+
dsl_hash = to_diff_h
|
43
|
+
aws_hash = to_diff_h_aws
|
44
|
+
result = nil
|
45
|
+
|
46
|
+
# modify rule
|
47
|
+
if dsl_hash != aws_hash
|
48
|
+
Applb.logger.info("Modify rule #{@aws_rule.rule_arn}")
|
49
|
+
Applb.logger.info("<diff>\n#{Applb::Utils.diff(aws_hash, dsl_hash, color: @options[:color])}")
|
50
|
+
|
51
|
+
unless @options[:dry_run]
|
52
|
+
result = client.modify_rule(modify_option).rules.first
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# modify rule priority
|
57
|
+
if priority.to_s != @aws_rule.priority
|
58
|
+
Applb.logger.info("Modify priority #{@aws_rule.priority} to #{priority}")
|
59
|
+
Applb.logger.info("<diff>\n#{Applb::Utils.diff(@aws_rule.priority, priority, color: @options[:color])}")
|
60
|
+
|
61
|
+
unless @options[:dry_run]
|
62
|
+
rule_priority_option = {
|
63
|
+
rule_priorities: [{ rule_arn: @aws_rule.rule_arn, priority: priority}]
|
64
|
+
}
|
65
|
+
result = client.set_rule_priorities(rule_priority_option).rules.first
|
66
|
+
end
|
67
|
+
end
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def create_option
|
74
|
+
options = to_h.reject { |k, v| k == :rule_arn }
|
75
|
+
options[:actions].first.delete(:target_group_name)
|
76
|
+
options
|
77
|
+
end
|
78
|
+
|
79
|
+
def modify_option
|
80
|
+
options = to_h.reject { |k, v| k == :priority }
|
81
|
+
options[:rule_arn] = @aws_rule.rule_arn
|
82
|
+
options[:actions].first.delete(:target_group_name)
|
83
|
+
options.delete(:listener_arn)
|
84
|
+
options
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_diff_h
|
88
|
+
Applb::Utils.normalize_hash(to_h).reject do |k, v|
|
89
|
+
%i/:priority listener_arn rule_arn priority/.include?(k)
|
90
|
+
end.tap { |h| h[:actions].first.delete(:target_group_name) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_diff_h_aws
|
94
|
+
Applb::Utils.normalize_hash(@aws_rule.to_h).reject do |k, v|
|
95
|
+
%i/priority is_default rule_arn/.include?(k)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def needs_modify?
|
100
|
+
to_diff_h != to_diff_h_aws
|
101
|
+
end
|
102
|
+
|
103
|
+
def client
|
104
|
+
@client ||= Applb::ClientWrapper.new(@options)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def initialize(context, listener, &block)
|
109
|
+
@context = context.dup
|
110
|
+
@listener = listener
|
111
|
+
|
112
|
+
@result = Result.new(context, listener)
|
113
|
+
@result.actions = []
|
114
|
+
@result.conditions = []
|
115
|
+
|
116
|
+
instance_eval(&block)
|
117
|
+
end
|
118
|
+
|
119
|
+
def result
|
120
|
+
required(:conditions, @result.conditions)
|
121
|
+
required(:priority, @result.priority)
|
122
|
+
required(:actions, @result.actions)
|
123
|
+
@result
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def rule_arn(rule_arn)
|
129
|
+
@result.rule_arn = rule_arn
|
130
|
+
end
|
131
|
+
|
132
|
+
def priority(priority)
|
133
|
+
@result.priority = priority
|
134
|
+
end
|
135
|
+
|
136
|
+
def actions(target_group_name: nil, target_group_arn: nil, type:)
|
137
|
+
@result.actions << {
|
138
|
+
target_group_arn: target_group_arn,
|
139
|
+
target_group_name: target_group_name,
|
140
|
+
type: type,
|
141
|
+
}
|
142
|
+
end
|
143
|
+
|
144
|
+
def conditions(field: , values:)
|
145
|
+
@result.conditions << {
|
146
|
+
field: field,
|
147
|
+
values: values,
|
148
|
+
}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'applb/dsl/rule'
|
2
|
+
|
3
|
+
module Applb
|
4
|
+
class DSL
|
5
|
+
class EC2
|
6
|
+
class LoadBalancer
|
7
|
+
class Listeners
|
8
|
+
class Listener
|
9
|
+
class Rules
|
10
|
+
def initialize(context, listener, &block)
|
11
|
+
@context = context.dup
|
12
|
+
@listener = listener
|
13
|
+
|
14
|
+
@result = []
|
15
|
+
|
16
|
+
instance_eval(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :result
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def rule(&block)
|
24
|
+
@result << Rule.new(@context, @listener, &block).result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Applb
|
2
|
+
class DSL
|
3
|
+
class EC2
|
4
|
+
class LoadBalancer
|
5
|
+
class TargetGroups
|
6
|
+
class TargetGroup
|
7
|
+
include Checker
|
8
|
+
include Applb::TemplateHelper
|
9
|
+
|
10
|
+
class Result
|
11
|
+
ATTRIBUTES = %i/
|
12
|
+
name protocol port vpc_id health_check_protocol health_check_port health_check_path
|
13
|
+
health_check_interval_seconds health_check_timeout_seconds healthy_threshold_count
|
14
|
+
unhealthy_threshold_count matcher
|
15
|
+
/
|
16
|
+
|
17
|
+
attr_accessor *ATTRIBUTES
|
18
|
+
|
19
|
+
def initialize(context)
|
20
|
+
@context = context
|
21
|
+
@options = context.options
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_h
|
25
|
+
Hash[ATTRIBUTES.sort.map { |name| [name, public_send(name)] }]
|
26
|
+
end
|
27
|
+
|
28
|
+
def aws(aws_tg)
|
29
|
+
@aws_tg = aws_tg
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def create
|
34
|
+
Applb.logger.info("Create target group #{name}")
|
35
|
+
return if @options[:dry_run]
|
36
|
+
client.create_target_group(create_option).target_groups.first
|
37
|
+
end
|
38
|
+
|
39
|
+
def modify
|
40
|
+
dsl_hash = to_diff_h
|
41
|
+
aws_hash = to_diff_h_aws
|
42
|
+
return if dsl_hash == aws_hash
|
43
|
+
|
44
|
+
Applb.logger.info("Modify target group #{name}")
|
45
|
+
Applb.logger.info("<diff>\n#{Applb::Utils.diff(aws_hash, dsl_hash, color: @options[:color])}")
|
46
|
+
return if @options[:dry_run]
|
47
|
+
|
48
|
+
puts modify_option
|
49
|
+
client.modify_target_group(modify_option).target_groups.first
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def create_option
|
55
|
+
to_h
|
56
|
+
end
|
57
|
+
|
58
|
+
UNMODIFIABLE_ATTRIBUTES = %i/name port protocol vpc_id/
|
59
|
+
def modify_option
|
60
|
+
options = to_h.
|
61
|
+
merge(target_group_arn: @aws_tg.target_group_arn).
|
62
|
+
reject! { |k, v| UNMODIFIABLE_ATTRIBUTES.include?(k) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_diff_h
|
66
|
+
hash = to_h
|
67
|
+
hash.delete(:target_group_arn)
|
68
|
+
Hash[hash.sort]
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_diff_h_aws
|
72
|
+
hash = @aws_tg.to_h
|
73
|
+
hash[:name] = hash.delete(:target_group_name)
|
74
|
+
hash.delete(:target_group_arn)
|
75
|
+
hash.delete(:load_balancer_arns)
|
76
|
+
Hash[hash.sort]
|
77
|
+
end
|
78
|
+
|
79
|
+
def client
|
80
|
+
@client ||= Applb::ClientWrapper.new(@options)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def initialize(context, name, lb_name, &block)
|
85
|
+
@context = context.dup
|
86
|
+
@lb_name = lb_name
|
87
|
+
@result = Result.new(@context)
|
88
|
+
@result.name = name
|
89
|
+
|
90
|
+
instance_eval(&block)
|
91
|
+
end
|
92
|
+
|
93
|
+
def result
|
94
|
+
required(:name, @result.name)
|
95
|
+
required(:protocol, @result.protocol)
|
96
|
+
required(:port, @result.port)
|
97
|
+
required(:vpc_id, @result.vpc_id)
|
98
|
+
|
99
|
+
@result
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def name(name)
|
105
|
+
@result.name = name
|
106
|
+
end
|
107
|
+
|
108
|
+
def protocol(protocol)
|
109
|
+
@result.protocol = protocol
|
110
|
+
end
|
111
|
+
|
112
|
+
def port(port)
|
113
|
+
@result.port = port
|
114
|
+
end
|
115
|
+
|
116
|
+
def vpc_id(vpc_id)
|
117
|
+
@result.vpc_id = vpc_id
|
118
|
+
end
|
119
|
+
|
120
|
+
def health_check_protocol(health_check_protocol)
|
121
|
+
@result.health_check_protocol = health_check_protocol
|
122
|
+
end
|
123
|
+
|
124
|
+
def health_check_port(health_check_port)
|
125
|
+
@result.health_check_port = health_check_port
|
126
|
+
end
|
127
|
+
|
128
|
+
def health_check_path(health_check_path)
|
129
|
+
@result.health_check_path = health_check_path
|
130
|
+
end
|
131
|
+
|
132
|
+
def health_check_interval_seconds(health_check_interval_seconds)
|
133
|
+
@result.health_check_interval_seconds = health_check_interval_seconds
|
134
|
+
end
|
135
|
+
|
136
|
+
def health_check_timeout_seconds(health_check_timeout_seconds)
|
137
|
+
@result.health_check_timeout_seconds = health_check_timeout_seconds
|
138
|
+
end
|
139
|
+
|
140
|
+
def healthy_threshold_count(healthy_threshold_count)
|
141
|
+
@result.healthy_threshold_count = healthy_threshold_count
|
142
|
+
end
|
143
|
+
|
144
|
+
def unhealthy_threshold_count(unhealthy_threshold_count)
|
145
|
+
@result.unhealthy_threshold_count = unhealthy_threshold_count
|
146
|
+
end
|
147
|
+
|
148
|
+
def matcher(http_code:)
|
149
|
+
@result.matcher = { http_code: http_code }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'applb/dsl/target_group'
|
2
|
+
|
3
|
+
module Applb
|
4
|
+
class DSL
|
5
|
+
class EC2
|
6
|
+
class LoadBalancer
|
7
|
+
class TargetGroups
|
8
|
+
include Applb::TemplateHelper
|
9
|
+
|
10
|
+
attr_reader :result
|
11
|
+
|
12
|
+
def initialize(context, lb, &block)
|
13
|
+
@context = context.dup
|
14
|
+
@lb = lb
|
15
|
+
@result = []
|
16
|
+
instance_eval(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def target_group(name, &block)
|
22
|
+
@result << TargetGroup.new(@context, name, @lb, &block).result
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/applb/error.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Applb
|
2
|
+
module Filterable
|
3
|
+
def target?(lb_name)
|
4
|
+
unless @options[:includes].empty?
|
5
|
+
return @options[:includes].include?(lb_name)
|
6
|
+
end
|
7
|
+
unless @options[:excludes].empty?
|
8
|
+
return !@options[:excludes].any? { |regex| lb_name =~ regex }
|
9
|
+
end
|
10
|
+
true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
ec2 <%= vpc_id.inspect %> do
|
2
|
+
<%- lbs_by_name.each do |name, attr| -%>
|
3
|
+
elb_v2 <%= name.inspect %> do
|
4
|
+
subnets(
|
5
|
+
<%- attr[:availability_zones].each do |az| -%>
|
6
|
+
<%= az[:subnet_id].inspect %>, # <%= az[:zone_name] %>
|
7
|
+
<%- end -%>
|
8
|
+
)
|
9
|
+
|
10
|
+
security_groups(
|
11
|
+
<%- attr[:security_groups].each do |sg| -%>
|
12
|
+
<%= sg.inspect %>,
|
13
|
+
<%- end -%>
|
14
|
+
)
|
15
|
+
|
16
|
+
scheme(<%= attr[:scheme].inspect %>)
|
17
|
+
|
18
|
+
<%- unless tags_by_arn[attr[:load_balancer_arn]].empty? -%>
|
19
|
+
tags(
|
20
|
+
<%- tags_by_arn[attr[:load_balancer_arn]].each do |key, value| -%>
|
21
|
+
<%= key.inspect %> => <%= value.inspect %>,
|
22
|
+
<%- end -%>
|
23
|
+
)
|
24
|
+
|
25
|
+
<%- end -%>
|
26
|
+
ip_address_type(<%= attr[:ip_address_type].inspect %>)
|
27
|
+
|
28
|
+
attributes do
|
29
|
+
<%- attr[:attributes].each do |key, value|
|
30
|
+
case key
|
31
|
+
when "access_logs" then -%>
|
32
|
+
access_logs({
|
33
|
+
s3_enabled: <%= value[:s3][:enabled] %>,
|
34
|
+
s3_bucket: <%= value[:s3][:bucket].inspect %>,
|
35
|
+
s3_prefix: <%= value[:s3][:prefix].inspect %>,
|
36
|
+
})
|
37
|
+
<%- else -%>
|
38
|
+
<%= key.gsub('.', ' ') %>: <%= value %>
|
39
|
+
<%- end
|
40
|
+
end
|
41
|
+
-%>
|
42
|
+
end
|
43
|
+
|
44
|
+
target_groups do
|
45
|
+
<%- attr[:target_groups].each do |target_group| -%>
|
46
|
+
target_group <%= target_group.target_group_name.inspect %> do
|
47
|
+
protocol <%= target_group.protocol.inspect %>
|
48
|
+
port <%= target_group.port %>
|
49
|
+
vpc_id <%= vpc_id.inspect %>
|
50
|
+
health_check_interval_seconds <%= target_group.health_check_interval_seconds %>
|
51
|
+
health_check_path <%= target_group.health_check_path.inspect %>
|
52
|
+
health_check_port <%= target_group.health_check_port.inspect %>
|
53
|
+
health_check_protocol <%= target_group.health_check_protocol.inspect %>
|
54
|
+
health_check_timeout_seconds <%= target_group.health_check_timeout_seconds %>
|
55
|
+
healthy_threshold_count <%= target_group.healthy_threshold_count %>
|
56
|
+
unhealthy_threshold_count <%= target_group.unhealthy_threshold_count %>
|
57
|
+
matcher http_code: <%= target_group.matcher.http_code.inspect %>
|
58
|
+
end
|
59
|
+
<%- end -%>
|
60
|
+
end
|
61
|
+
|
62
|
+
listeners do
|
63
|
+
<%- attr[:listeners].each do |listener| -%>
|
64
|
+
listener do
|
65
|
+
<%- listener.certificates.each do |certificate| -%>
|
66
|
+
certificates certificate_arn: <%= certificate.certificate_arn.inspect %>
|
67
|
+
<%- end -%>
|
68
|
+
<%- if listener.ssl_policy -%>
|
69
|
+
ssl_policy <%= listener.ssl_policy.inspect %>
|
70
|
+
<%- end -%>
|
71
|
+
port <%= listener.port %>
|
72
|
+
protocol <%= listener.protocol.inspect %>
|
73
|
+
<%- listener.default_actions.each do |action| -%>
|
74
|
+
|
75
|
+
default_actions(
|
76
|
+
target_group_name: <%= attr[:target_groups].find { |target_group| target_group.target_group_arn == action.target_group_arn }.target_group_name.inspect %>,
|
77
|
+
target_group_arn: <%= action.target_group_arn.inspect %>,
|
78
|
+
type: <%= action.type.inspect %>,
|
79
|
+
)
|
80
|
+
<%- end -%>
|
81
|
+
|
82
|
+
rules do
|
83
|
+
<%- if attr[:rules_by_listener_arn][listener.listener_arn].reject(&:is_default).empty? -%>
|
84
|
+
# no rules
|
85
|
+
<%- end -%>
|
86
|
+
<%- attr[:rules_by_listener_arn][listener.listener_arn].reject(&:is_default).each do |rule| -%>
|
87
|
+
rule do
|
88
|
+
rule_arn <%= rule.rule_arn.inspect %>
|
89
|
+
priority <%= rule.priority.inspect %>
|
90
|
+
|
91
|
+
<%- rule.actions.each do |action| -%>
|
92
|
+
actions(
|
93
|
+
target_group_name: <%= attr[:target_groups].find { |target_group| target_group.target_group_arn == action.target_group_arn }.target_group_name.inspect %>,
|
94
|
+
target_group_arn: <%= action.target_group_arn.inspect %>,
|
95
|
+
type: <%= action.type.inspect %>,
|
96
|
+
)
|
97
|
+
|
98
|
+
<%- end -%>
|
99
|
+
conditions(
|
100
|
+
<%- rule.conditions.each do |condition| -%>
|
101
|
+
field: <%= condition.field.inspect %>,
|
102
|
+
values: <%= condition.values.inspect %>,
|
103
|
+
<%- end -%>
|
104
|
+
)
|
105
|
+
end
|
106
|
+
<%- if attr[:rules_by_listener_arn][listener.listener_arn].reject(&:is_default).last != rule -%>
|
107
|
+
|
108
|
+
<%- end -%>
|
109
|
+
<%- end -%>
|
110
|
+
end
|
111
|
+
end
|
112
|
+
<%- if attr[:listeners].last != listener -%>
|
113
|
+
|
114
|
+
<%- end -%>
|
115
|
+
<%- end -%>
|
116
|
+
end
|
117
|
+
end
|
118
|
+
<%- if lbs_by_name.keys.last != name -%>
|
119
|
+
|
120
|
+
<%- end -%>
|
121
|
+
<%- end -%>
|
122
|
+
end
|