kelbim 0.0.1
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 +7 -0
- data/README.md +104 -0
- data/bin/kelbim +138 -0
- data/lib/kelbim/client.rb +217 -0
- data/lib/kelbim/dsl/checker.rb +65 -0
- data/lib/kelbim/dsl/converter.rb +177 -0
- data/lib/kelbim/dsl/ec2.rb +37 -0
- data/lib/kelbim/dsl/health-check.rb +57 -0
- data/lib/kelbim/dsl/listener.rb +61 -0
- data/lib/kelbim/dsl/listeners.rb +56 -0
- data/lib/kelbim/dsl/load-balancer.rb +85 -0
- data/lib/kelbim/dsl.rb +44 -0
- data/lib/kelbim/exporter.rb +66 -0
- data/lib/kelbim/ext/ec2-ext.rb +27 -0
- data/lib/kelbim/ext/elb-listener-ext.rb +21 -0
- data/lib/kelbim/ext/elb-load-balancer-ext.rb +15 -0
- data/lib/kelbim/ext/string-ext.rb +27 -0
- data/lib/kelbim/logger.rb +33 -0
- data/lib/kelbim/policy-types.rb +100 -0
- data/lib/kelbim/version.rb +3 -0
- data/lib/kelbim/wrapper/elb-wrapper.rb +21 -0
- data/lib/kelbim/wrapper/listener-collection.rb +88 -0
- data/lib/kelbim/wrapper/listener.rb +110 -0
- data/lib/kelbim/wrapper/load-balancer-collection.rb +101 -0
- data/lib/kelbim/wrapper/load-balancer.rb +217 -0
- data/lib/kelbim/wrapper/policy-collection.rb +96 -0
- data/lib/kelbim/wrapper/policy.rb +52 -0
- data/lib/kelbim.rb +2 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7eedb5e0c3b9983991baaaacd8233fe41d9ed137
|
4
|
+
data.tar.gz: 73b2b07df5e2219bfaaf81c9d0d39b9b56d363eb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6aa83ac6a4a98111e0f3816c15d200236256bbe6cff68c24087be96c11b27da1952e1b7f7e9dd66ecc91f2a73b3c4e43430c59ac1b87927cb87bcf5705f59f07
|
7
|
+
data.tar.gz: 430af7b5270717adddd3cd7452f15e392cb118c845b5db5930a9097c458740233d1d14583ba88affbd4d655562c1d01977b03d307fb003c3eb559b0e081ae160
|
data/README.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# Kelbim
|
2
|
+
|
3
|
+
Kelbim is a tool to manage ELB.
|
4
|
+
|
5
|
+
It defines the state of ELB using DSL, and updates ELB according to DSL.
|
6
|
+
|
7
|
+
**Attention! This is the alpha version!**
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'kelbim'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install kelbim
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
```sh
|
26
|
+
export AWS_ACCESS_KEY_ID='...'
|
27
|
+
export AWS_SECRET_ACCESS_KEY='...'
|
28
|
+
export AWS_REGION='ap-northeast-1'
|
29
|
+
kelbim -e -o ELBfile # export EKB
|
30
|
+
vi ELB
|
31
|
+
kelbim -a --dry-run
|
32
|
+
kelbim -a # apply `ELBfile` to ELB
|
33
|
+
```
|
34
|
+
|
35
|
+
## ELBfile example
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
require 'other/elbfile'
|
39
|
+
|
40
|
+
# EC2 Classic
|
41
|
+
ec2 do
|
42
|
+
load_balancer "my-load-balancer" do
|
43
|
+
instances(
|
44
|
+
"cthulhu",
|
45
|
+
"nyar",
|
46
|
+
)
|
47
|
+
|
48
|
+
listeners do
|
49
|
+
listener [:http, 80] => [:http, 80]
|
50
|
+
end
|
51
|
+
|
52
|
+
health_check do
|
53
|
+
target "HTTP:80/index.html"
|
54
|
+
timeout 5
|
55
|
+
interval 30
|
56
|
+
healthy_threshold 10
|
57
|
+
unhealthy_threshold 2
|
58
|
+
end
|
59
|
+
|
60
|
+
availability_zones(
|
61
|
+
"ap-northeast-1a",
|
62
|
+
"ap-northeast-1b"
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# EC2 VPC
|
68
|
+
ec2 "vpc-XXXXXXXXX" do
|
69
|
+
load_balancer "my-load-balancer", :internal => true do
|
70
|
+
instances(
|
71
|
+
"nyar",
|
72
|
+
"yog"
|
73
|
+
)
|
74
|
+
|
75
|
+
listeners do
|
76
|
+
listener [:tcp, 80] => [:tcp, 80]
|
77
|
+
listener [:https, 443] => [:http, 80] do
|
78
|
+
app_cookie_stickiness "CookieName"=>"20"
|
79
|
+
ssl_negotiation ["Protocol-TLSv1", "Protocol-SSLv3", "AES256-SHA", ...]
|
80
|
+
server_certificate "my-cert"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
health_check do
|
85
|
+
target "TCP:80"
|
86
|
+
timeout 5
|
87
|
+
interval 30
|
88
|
+
healthy_threshold 10
|
89
|
+
unhealthy_threshold 2
|
90
|
+
end
|
91
|
+
|
92
|
+
subnets(
|
93
|
+
"subnet-XXXXXXXX"
|
94
|
+
)
|
95
|
+
|
96
|
+
security_groups(
|
97
|
+
"default"
|
98
|
+
)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
## Link
|
104
|
+
* [RubyGems.org site](http://rubygems.org/gems/kelbim)
|
data/bin/kelbim
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.expand_path("#{File.dirname __FILE__}/../lib")
|
3
|
+
require 'rubygems'
|
4
|
+
require 'kelbim'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
DEFAULT_FILENAME = 'ELBfile'
|
8
|
+
|
9
|
+
mode = nil
|
10
|
+
file = DEFAULT_FILENAME
|
11
|
+
output_file = '-'
|
12
|
+
split = false
|
13
|
+
|
14
|
+
options = {
|
15
|
+
:dry_run => false,
|
16
|
+
:color => true,
|
17
|
+
:debug => false,
|
18
|
+
}
|
19
|
+
|
20
|
+
ARGV.options do |opt|
|
21
|
+
begin
|
22
|
+
access_key = nil
|
23
|
+
secret_key = nil
|
24
|
+
region = nil
|
25
|
+
|
26
|
+
opt.on('-k', '--access-key ACCESS_KEY') {|v| access_key = v }
|
27
|
+
opt.on('-s', '--secret-key SECRET_KEY') {|v| secret_key = v }
|
28
|
+
opt.on('-r', '--region REGION') {|v| region = v }
|
29
|
+
opt.on('-a', '--apply') {|v| mode = :apply }
|
30
|
+
opt.on('-f', '--file FILE') {|v| file = v }
|
31
|
+
opt.on('', '--dry-run') {|v| options[:dry_run] = true }
|
32
|
+
opt.on('-e', '--export') {|v| mode = :export }
|
33
|
+
opt.on('-o', '--output FILE') {|v| output_file = v }
|
34
|
+
opt.on('', '--split') {|v| split = true }
|
35
|
+
opt.on('-t', '--test') {|v| mode = :test }
|
36
|
+
opt.on('' , '--no-color') { options[:color] = false }
|
37
|
+
opt.on('' , '--debug') { options[:debug] = true }
|
38
|
+
opt.parse!
|
39
|
+
|
40
|
+
if access_key and secret_key
|
41
|
+
aws_opts = {
|
42
|
+
:access_key_id => access_key,
|
43
|
+
:secret_access_key => secret_key,
|
44
|
+
}
|
45
|
+
aws_opts[:region] = region if region
|
46
|
+
AWS.config(aws_opts)
|
47
|
+
elsif (access_key and !secret_key) or (!access_key and secret_key) or mode.nil?
|
48
|
+
puts opt.help
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
rescue => e
|
52
|
+
$stderr.puts("[ERROR] #{e.message}")
|
53
|
+
exit 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
String.colorize = options[:color]
|
58
|
+
|
59
|
+
if options[:debug]
|
60
|
+
AWS.config({
|
61
|
+
:http_wire_trace => true,
|
62
|
+
:logger => Kelbim::Logger.instance,
|
63
|
+
})
|
64
|
+
end
|
65
|
+
|
66
|
+
begin
|
67
|
+
logger = Kelbim::Logger.instance
|
68
|
+
logger.set_debug(options[:debug])
|
69
|
+
client = Kelbim::Client.new(options)
|
70
|
+
|
71
|
+
case mode
|
72
|
+
when :export
|
73
|
+
if split
|
74
|
+
logger.info('Export ELB')
|
75
|
+
|
76
|
+
output_file = DEFAULT_FILENAME if output_file == '-'
|
77
|
+
requires = []
|
78
|
+
|
79
|
+
client.export do |exported, converter|
|
80
|
+
exported.each do |vpc, elbs|
|
81
|
+
elb_file = File.join(File.dirname(output_file), "#{vpc || :classic}.elb")
|
82
|
+
requires << elb_file
|
83
|
+
|
84
|
+
logger.info(" write `#{elb_file}`")
|
85
|
+
|
86
|
+
open(elb_file, 'wb') do |f|
|
87
|
+
f.puts converter.call(vpc => elbs)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
logger.info(" write `#{output_file}`")
|
93
|
+
|
94
|
+
open(output_file, 'wb') do |f|
|
95
|
+
requires.each do |elb_file|
|
96
|
+
f.puts "require '#{File.basename elb_file}'"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
else
|
100
|
+
if output_file == '-'
|
101
|
+
logger.info('# Export ELB')
|
102
|
+
puts client.export
|
103
|
+
else
|
104
|
+
logger.info("Export ELB to `#{output_file}`")
|
105
|
+
open(output_file, 'wb') {|f| f.puts client.export }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
when :apply
|
109
|
+
unless File.exist?(file)
|
110
|
+
raise "No ELBfile found (looking for: #{file})"
|
111
|
+
end
|
112
|
+
|
113
|
+
msg = "Apply `#{file}` to ELB"
|
114
|
+
msg << ' (dry-run)' if options[:dry_run]
|
115
|
+
logger.info(msg)
|
116
|
+
|
117
|
+
updated = client.apply(file)
|
118
|
+
|
119
|
+
logger.info('No change'.intense_blue) unless updated
|
120
|
+
when :test
|
121
|
+
unless File.exist?(file)
|
122
|
+
raise "No ELBfile found (looking for: #{file})"
|
123
|
+
end
|
124
|
+
|
125
|
+
logger.info("Test `#{file}`")
|
126
|
+
# XXX:
|
127
|
+
client.test(file)
|
128
|
+
else
|
129
|
+
raise 'must not happen'
|
130
|
+
end
|
131
|
+
rescue => e
|
132
|
+
if options[:debug]
|
133
|
+
raise e
|
134
|
+
else
|
135
|
+
$stderr.puts("[ERROR] #{e.message}".red)
|
136
|
+
exit 1
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require 'kelbim/dsl'
|
3
|
+
require 'kelbim/exporter'
|
4
|
+
require 'kelbim/ext/ec2-ext'
|
5
|
+
require 'kelbim/ext/elb-load-balancer-ext'
|
6
|
+
require 'kelbim/policy-types'
|
7
|
+
require 'kelbim/wrapper/elb-wrapper'
|
8
|
+
require 'kelbim/logger'
|
9
|
+
|
10
|
+
module Kelbim
|
11
|
+
class Client
|
12
|
+
include Logger::ClientHelper
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
@options = OpenStruct.new(options)
|
16
|
+
@options.elb = AWS::ELB.new
|
17
|
+
@options.ec2 = AWS::EC2.new
|
18
|
+
@options.iam = AWS::IAM.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def apply(file)
|
22
|
+
AWS.memoize { walk(file) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def test(file)
|
26
|
+
# XXX:
|
27
|
+
end
|
28
|
+
|
29
|
+
def export
|
30
|
+
exported = nil
|
31
|
+
instance_names = nil
|
32
|
+
|
33
|
+
AWS.memoize do
|
34
|
+
exported = Exporter.export(@options.elb)
|
35
|
+
instance_names = @options.ec2.instance_names
|
36
|
+
end
|
37
|
+
|
38
|
+
if block_given?
|
39
|
+
converter = proc do |src|
|
40
|
+
DSL.convert(src, instance_names)
|
41
|
+
end
|
42
|
+
|
43
|
+
yield(exported, converter)
|
44
|
+
else
|
45
|
+
DSL.convert(exported, instance_names)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def load_file(file)
|
51
|
+
if file.kind_of?(String)
|
52
|
+
open(file) do |f|
|
53
|
+
DSL.define(f.read, file).result
|
54
|
+
end
|
55
|
+
elsif file.respond_to?(:read)
|
56
|
+
DSL.define(file.read, file.path).result
|
57
|
+
else
|
58
|
+
raise TypeError, "can't convert #{file} into File"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def walk(file)
|
63
|
+
dsl = load_file(file)
|
64
|
+
|
65
|
+
dsl_ec2s = dsl.ec2s
|
66
|
+
elb = ELBWrapper.new(@options.elb, @options)
|
67
|
+
|
68
|
+
aws_ec2s = collect_to_hash(elb.load_balancers, :has_many => true) do |item|
|
69
|
+
item.vpc_id
|
70
|
+
end
|
71
|
+
|
72
|
+
dsl_ec2s.each do |vpc, ec2_dsl|
|
73
|
+
ec2_aws = aws_ec2s[vpc]
|
74
|
+
|
75
|
+
if ec2_aws
|
76
|
+
walk_ec2(vpc, ec2_dsl, ec2_aws, elb.load_balancers)
|
77
|
+
else
|
78
|
+
log(:warn, "EC2 `#{vpc || :classic}` is not found", :yellow)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
elb.updated?
|
83
|
+
end
|
84
|
+
|
85
|
+
def walk_ec2(vpc, ec2_dsl, ec2_aws, collection_api)
|
86
|
+
lb_list_dsl = collect_to_hash(ec2_dsl.load_balancers, :name)
|
87
|
+
lb_list_aws = collect_to_hash(ec2_aws, :name)
|
88
|
+
|
89
|
+
lb_list_dsl.each do |key, lb_dsl|
|
90
|
+
name = key[0]
|
91
|
+
lb_aws = lb_list_aws[key]
|
92
|
+
|
93
|
+
unless lb_aws
|
94
|
+
lb_aws = collection_api.create(lb_dsl, vpc)
|
95
|
+
lb_list_aws[key] = lb_aws
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
lb_list_dsl.each do |key, lb_dsl|
|
100
|
+
lb_aws = lb_list_aws.delete(key)
|
101
|
+
walk_load_balancer(lb_dsl, lb_aws)
|
102
|
+
end
|
103
|
+
|
104
|
+
lb_list_aws.each do |key, lb_aws|
|
105
|
+
lb_aws.delete
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def walk_load_balancer(load_balancer_dsl, load_balancer_aws)
|
110
|
+
unless load_balancer_aws.eql?(load_balancer_dsl)
|
111
|
+
load_balancer_aws.update(load_balancer_dsl)
|
112
|
+
end
|
113
|
+
|
114
|
+
lstnr_list_dsl = collect_to_hash(load_balancer_dsl.listeners, :port)
|
115
|
+
listeners = load_balancer_aws.listeners
|
116
|
+
lstnr_list_aws = collect_to_hash(listeners, :port)
|
117
|
+
|
118
|
+
walk_listeners(lstnr_list_dsl, lstnr_list_aws, listeners)
|
119
|
+
end
|
120
|
+
|
121
|
+
def walk_listeners(listeners_dsl, listeners_aws, collection_api)
|
122
|
+
listeners_dsl.each do |key, lstnr_dsl|
|
123
|
+
lstnr_aws = listeners_aws[key]
|
124
|
+
|
125
|
+
unless lstnr_aws
|
126
|
+
lstnr_aws = collection_api.create(lstnr_dsl)
|
127
|
+
listeners_aws[key] = lstnr_aws
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
listeners_dsl.each do |key, lstnr_dsl|
|
132
|
+
lstnr_aws = listeners_aws.delete(key)
|
133
|
+
walk_listener(lstnr_dsl, lstnr_aws, collection_api)
|
134
|
+
end
|
135
|
+
|
136
|
+
listeners_aws.each do |key, lstnr_aws|
|
137
|
+
lstnr_aws.delete
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def walk_listener(listener_dsl, listener_aws, collection_api)
|
142
|
+
unless listener_aws.eql?(listener_dsl)
|
143
|
+
if listener_aws.has_difference_protocol_port?(listener_dsl)
|
144
|
+
listener_aws.delete
|
145
|
+
listener_aws = collection_api.create(listener_dsl)
|
146
|
+
else
|
147
|
+
listener_aws.update(listener_dsl)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
plcy_list_dsl = collect_to_hash(listener_dsl.policies) do |policy_type, name_or_attrs|
|
152
|
+
[PolicyTypes.symbol_to_string(policy_type)]
|
153
|
+
end
|
154
|
+
|
155
|
+
policies = listener_aws.policies
|
156
|
+
plcy_list_aws = collect_to_hash(policies, :type)
|
157
|
+
|
158
|
+
walk_policies(listener_aws, plcy_list_dsl, plcy_list_aws, policies)
|
159
|
+
end
|
160
|
+
|
161
|
+
def walk_policies(listener, policies_dsl, policies_aws, collection_api)
|
162
|
+
orig_policy_names = policies_aws.map {|k, v| v.name }
|
163
|
+
new_policies = []
|
164
|
+
old_policies = []
|
165
|
+
|
166
|
+
policies_dsl.each do |key, plcy_dsl|
|
167
|
+
unless policies_aws[key]
|
168
|
+
new_policies << collection_api.create(plcy_dsl)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
policies_dsl.each do |key, plcy_dsl|
|
173
|
+
plcy_aws = policies_aws.delete(key)
|
174
|
+
next unless plcy_aws
|
175
|
+
|
176
|
+
if plcy_aws.eql?(plcy_dsl)
|
177
|
+
new_policies << plcy_aws
|
178
|
+
else
|
179
|
+
new_policies << collection_api.create(plcy_dsl)
|
180
|
+
old_policies << plcy_aws
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
policies_aws.each do |key, plcy_aws|
|
185
|
+
old_policies << plcy_aws
|
186
|
+
end
|
187
|
+
|
188
|
+
if not new_policies.empty? and orig_policy_names.sort != new_policies.map {|i| i.name }.sort
|
189
|
+
listener.policies = new_policies
|
190
|
+
|
191
|
+
unless @options.without_deleting_policy
|
192
|
+
old_policies.each do |plcy_aws|
|
193
|
+
plcy_aws.delete
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def collect_to_hash(collection, *key_attrs)
|
200
|
+
options = key_attrs.last.kind_of?(Hash) ? key_attrs.pop : {}
|
201
|
+
hash = {}
|
202
|
+
|
203
|
+
collection.each do |item|
|
204
|
+
key = block_given? ? yield(item) : key_attrs.map {|k| item.send(k) }
|
205
|
+
|
206
|
+
if options[:has_many]
|
207
|
+
hash[key] ||= []
|
208
|
+
hash[key] << item
|
209
|
+
else
|
210
|
+
hash[key] = item
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
return hash
|
215
|
+
end
|
216
|
+
end # Client
|
217
|
+
end # Kelbim
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Kelbim
|
2
|
+
class DSL
|
3
|
+
module Checker
|
4
|
+
private
|
5
|
+
def required(name, value)
|
6
|
+
invalid = false
|
7
|
+
|
8
|
+
if value
|
9
|
+
case value
|
10
|
+
when String
|
11
|
+
invalid = value.strip.empty?
|
12
|
+
when Array, Hash
|
13
|
+
invalid = value.empty?
|
14
|
+
end
|
15
|
+
else
|
16
|
+
invalid = true
|
17
|
+
end
|
18
|
+
|
19
|
+
raise __identify("`#{name}` is required") if invalid
|
20
|
+
end
|
21
|
+
|
22
|
+
def expected_type(value, *types)
|
23
|
+
unless types.any? {|t| value.kind_of?(t) }
|
24
|
+
raise __identify("Invalid type: #{value}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def expected_length(value, length)
|
29
|
+
if value.length != length
|
30
|
+
raise __identify("Invalid length: #{value}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def expected_value(value, *list)
|
35
|
+
unless list.any? {|i| value == i }
|
36
|
+
raise __identify("Invalid value: #{value}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def not_include(value, list)
|
41
|
+
if list.include?(value)
|
42
|
+
raise __identify("`#{value}` is already included")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def call_once(method_name)
|
47
|
+
@called ||= []
|
48
|
+
|
49
|
+
if @called.include?(method_name)
|
50
|
+
raise __identify("`#{method_name}` is already defined")
|
51
|
+
end
|
52
|
+
|
53
|
+
@called << method_name
|
54
|
+
end
|
55
|
+
|
56
|
+
def __identify(errmsg)
|
57
|
+
if @error_identifier
|
58
|
+
errmsg = "#{@error_identifier}: #{errmsg}"
|
59
|
+
end
|
60
|
+
|
61
|
+
return errmsg
|
62
|
+
end
|
63
|
+
end # Checker
|
64
|
+
end # DSL
|
65
|
+
end # Kelbim
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'kelbim/policy-types'
|
2
|
+
|
3
|
+
module Kelbim
|
4
|
+
class DSL
|
5
|
+
class Converter
|
6
|
+
class << self
|
7
|
+
def convert(exported, instance_names)
|
8
|
+
self.new(exported, instance_names).convert
|
9
|
+
end
|
10
|
+
end # of class methods
|
11
|
+
|
12
|
+
def initialize(exported, instance_names)
|
13
|
+
@exported = exported
|
14
|
+
@instance_names = instance_names
|
15
|
+
end
|
16
|
+
|
17
|
+
def convert
|
18
|
+
@exported.each.map {|vpc, load_balancers|
|
19
|
+
output_ec2(vpc, load_balancers)
|
20
|
+
}.join("\n")
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def output_ec2(vpc, load_balancers)
|
25
|
+
arg_vpc = vpc ? vpc.inspect + ' ' : ''
|
26
|
+
load_balancers = load_balancers.map {|name, load_balancer|
|
27
|
+
output_load_balancer(vpc, name, load_balancer)
|
28
|
+
}.join("\n").strip
|
29
|
+
|
30
|
+
<<-EOS
|
31
|
+
ec2 #{arg_vpc}do
|
32
|
+
#{load_balancers}
|
33
|
+
end
|
34
|
+
EOS
|
35
|
+
end
|
36
|
+
|
37
|
+
def output_load_balancer(vpc, name, load_balancer)
|
38
|
+
name = name.inspect
|
39
|
+
internal = (load_balancer[:scheme] == 'internal') ? ', :internal => true ' : ' '
|
40
|
+
instances = output_instances(load_balancer[:instances], vpc).strip
|
41
|
+
listeners = output_listeners(load_balancer[:listeners]).strip
|
42
|
+
health_check = output_health_check(load_balancer[:health_check]).strip
|
43
|
+
dns_name = load_balancer[:dns_name]
|
44
|
+
|
45
|
+
out = <<-EOS
|
46
|
+
load_balancer #{name}#{internal}do
|
47
|
+
#test do
|
48
|
+
# #host = #{dns_name.inspect}
|
49
|
+
# #expect(Net::HTTP.start(host, 80).get("/")).to be_a(Net::HTTPOK)
|
50
|
+
#end
|
51
|
+
|
52
|
+
#{instances}
|
53
|
+
|
54
|
+
#{listeners}
|
55
|
+
|
56
|
+
#{health_check}
|
57
|
+
EOS
|
58
|
+
|
59
|
+
if vpc
|
60
|
+
subnets = load_balancer[:subnets]
|
61
|
+
subnets = subnets.map {|i| i.inspect }.join(",\n ")
|
62
|
+
|
63
|
+
out << "\n"
|
64
|
+
out.concat(<<-EOS)
|
65
|
+
subnets(
|
66
|
+
#{subnets}
|
67
|
+
)
|
68
|
+
EOS
|
69
|
+
|
70
|
+
security_groups = load_balancer[:security_groups]
|
71
|
+
security_groups = security_groups.map {|i| i.inspect }.join(",\n ")
|
72
|
+
|
73
|
+
out << "\n"
|
74
|
+
out.concat(<<-EOS)
|
75
|
+
security_groups(
|
76
|
+
#{security_groups}
|
77
|
+
)
|
78
|
+
EOS
|
79
|
+
else
|
80
|
+
availability_zones = load_balancer[:availability_zones]
|
81
|
+
availability_zones = availability_zones.map {|i| i.inspect }.join(",\n ")
|
82
|
+
|
83
|
+
out << "\n"
|
84
|
+
out.concat(<<-EOS)
|
85
|
+
availability_zones(
|
86
|
+
#{availability_zones}
|
87
|
+
)
|
88
|
+
EOS
|
89
|
+
end
|
90
|
+
|
91
|
+
out << " end\n"
|
92
|
+
return out
|
93
|
+
end
|
94
|
+
|
95
|
+
def output_instances(instances, vpc)
|
96
|
+
if instances.empty?
|
97
|
+
instances = '# not registered'
|
98
|
+
else
|
99
|
+
instance_id_names = @instance_names[vpc] || {}
|
100
|
+
|
101
|
+
instances = instances.map {|instance_id|
|
102
|
+
instance_id_names.fetch(instance_id, instance_id).inspect
|
103
|
+
}.join(",\n ")
|
104
|
+
end
|
105
|
+
|
106
|
+
<<-EOS
|
107
|
+
instances(
|
108
|
+
#{instances}
|
109
|
+
)
|
110
|
+
EOS
|
111
|
+
end
|
112
|
+
|
113
|
+
def output_listeners(listeners)
|
114
|
+
items = listeners.map {|listener|
|
115
|
+
output_listener(listener).strip
|
116
|
+
}.join("\n ")
|
117
|
+
|
118
|
+
<<-EOS
|
119
|
+
listeners do
|
120
|
+
#{items}
|
121
|
+
end
|
122
|
+
EOS
|
123
|
+
end
|
124
|
+
|
125
|
+
def output_listener(listener)
|
126
|
+
protocol = listener[:protocol].inspect
|
127
|
+
port = listener[:port]
|
128
|
+
instance_protocol = listener[:instance_protocol].inspect
|
129
|
+
instance_port = listener[:instance_port]
|
130
|
+
policies = listener[:policies]
|
131
|
+
server_certificate = listener[:server_certificate]
|
132
|
+
|
133
|
+
out = "listener [#{protocol}, #{port}] => [#{instance_protocol}, #{instance_port}]"
|
134
|
+
|
135
|
+
if policies.empty? and server_certificate.nil?
|
136
|
+
return out
|
137
|
+
end
|
138
|
+
|
139
|
+
out << " do\n"
|
140
|
+
|
141
|
+
unless policies.empty?
|
142
|
+
policies_dsl = policies.map {|policy|
|
143
|
+
PolicyTypes.convert_to_dsl(policy)
|
144
|
+
}.join("\n ")
|
145
|
+
|
146
|
+
out << " #{policies_dsl}\n"
|
147
|
+
end
|
148
|
+
|
149
|
+
if server_certificate
|
150
|
+
out << " server_certificate #{server_certificate.name.inspect}\n"
|
151
|
+
end
|
152
|
+
|
153
|
+
out << " end"
|
154
|
+
|
155
|
+
return out
|
156
|
+
end
|
157
|
+
|
158
|
+
def output_health_check(health_check)
|
159
|
+
target = health_check[:target].inspect
|
160
|
+
timeout = health_check[:timeout]
|
161
|
+
interval = health_check[:interval]
|
162
|
+
healthy_threshold = health_check[:healthy_threshold]
|
163
|
+
unhealthy_threshold = health_check[:unhealthy_threshold]
|
164
|
+
|
165
|
+
<<-EOS
|
166
|
+
health_check do
|
167
|
+
target #{target}
|
168
|
+
timeout #{timeout}
|
169
|
+
interval #{interval}
|
170
|
+
healthy_threshold #{healthy_threshold}
|
171
|
+
unhealthy_threshold #{unhealthy_threshold}
|
172
|
+
end
|
173
|
+
EOS
|
174
|
+
end
|
175
|
+
end # Converter
|
176
|
+
end # DSL
|
177
|
+
end # Kelbim
|