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.
@@ -0,0 +1,88 @@
1
+ require 'ostruct'
2
+ require 'kelbim/wrapper/listener'
3
+ require 'kelbim/logger'
4
+
5
+ module Kelbim
6
+ class ELBWrapper
7
+ class LoadBalancerCollection
8
+ class LoadBalancer
9
+ class ListenerCollection
10
+ include Logger::ClientHelper
11
+
12
+ def initialize(listeners, load_balancer, options)
13
+ @listeners = listeners
14
+ @load_balancer = load_balancer
15
+ @options = options
16
+ end
17
+
18
+ def each
19
+ @listeners.each do |lstnr|
20
+ yield(Listener.new(lstnr, @options))
21
+ end
22
+ end
23
+
24
+ def create(dsl)
25
+ log_id = [[dsl.protocol, dsl.port], [dsl.instance_protocol, dsl.instance_port]].map {|i| i.inspect }.join(' => ')
26
+ log_id = "#{@load_balancer.vpc_id || :classic} > #{@load_balancer.name} > #{log_id}"
27
+ log(:info, 'Create Listener', :cyan, log_id)
28
+
29
+ if @options.dry_run
30
+ lstnr = OpenStruct.new({
31
+ :protocol => dsl.protocol,
32
+ :port => dsl.port,
33
+ :instance_protocol => dsl.instance_protocol,
34
+ :instance_port => dsl.instance_port,
35
+ :policies => dsl.policies.map {|i| PolicyCollection.create_mock_policy(i) },
36
+ })
37
+
38
+ if dsl.server_certificate
39
+ lstnr.server_certificate = OpenStruct.new(:name => dsl.server_certificate)
40
+ end
41
+ else
42
+ lstnr_opts = {
43
+ :protocol => dsl.protocol,
44
+ :port => dsl.port,
45
+ :instance_protocol => dsl.instance_protocol,
46
+ :instance_port => dsl.instance_port,
47
+ }
48
+
49
+ if (ss_name = dsl.server_certificate)
50
+ ss = @options.iam.server_certificates[ss_name]
51
+
52
+ unless ss
53
+ raise "Can't find ServerCertificate: #{ss_name} in #{load_balancer.vpc_id || :classic} > #{@load_balancer.name}"
54
+ end
55
+
56
+ lstnr_opts[:server_certificate] = ss.arn
57
+ end
58
+
59
+ # lstnr_optsは破壊的に更新される
60
+ lstnr = @listeners.create(lstnr_opts.dup)
61
+ @options.updated = true
62
+
63
+ # XXX: 新規作成後、_descriptionはセットされない
64
+ fix_new_listener(lstnr, lstnr_opts)
65
+ end
66
+
67
+ Listener.new(lstnr, @options)
68
+ end
69
+
70
+ private
71
+ def fix_new_listener(lstnr, lstnr_opts)
72
+ lstnr.instance_variable_set(:@__server_certificate__, lstnr_opts[:server_certificate])
73
+
74
+ def lstnr.server_certificate
75
+ if @__server_certificate__
76
+ OpenStruct.new(:name => @__server_certificate__)
77
+ else
78
+ nil
79
+ end
80
+ end
81
+
82
+ def lstnr.policy_names; []; end
83
+ end
84
+ end # ListenerCollection
85
+ end # LoadBalancer
86
+ end # LoadBalancerCollection
87
+ end # ELBWrapper
88
+ end # Kelbim
@@ -0,0 +1,110 @@
1
+ require 'forwardable'
2
+ require 'kelbim/ext/elb-listener-ext'
3
+ require 'kelbim/wrapper/policy-collection'
4
+ require 'kelbim/logger'
5
+
6
+ module Kelbim
7
+ class ELBWrapper
8
+ class LoadBalancerCollection
9
+ class LoadBalancer
10
+ class ListenerCollection
11
+ class Listener
12
+ extend Forwardable
13
+ include Logger::ClientHelper
14
+
15
+ def_delegators(
16
+ :@listener,
17
+ :protocol, :port, :instance_protocol, :instance_port, :load_balancer)
18
+
19
+ def initialize(listener, options)
20
+ @listener = listener
21
+ @options = options
22
+ end
23
+
24
+ def policies
25
+ PolicyCollection.new(@listener.policies, self, @options)
26
+ end
27
+
28
+ def eql?(dsl)
29
+ not has_difference_protocol_port?(dsl) and compare_server_certificate(dsl)
30
+ end
31
+
32
+ def update(dsl)
33
+ log(:info, 'Update Listener', :green, log_id)
34
+
35
+ compare_server_certificate(dsl) do
36
+ log(:info, " set server_certificate=#{dsl.server_certificate}", :green)
37
+
38
+ unless @options.dry_run
39
+ ss = @options.iam.server_certificates[dsl.server_certificate]
40
+
41
+ unless ss
42
+ raise "Can't find ServerCertificate: #{ss_name} in #{log_id}"
43
+ end
44
+
45
+ @listener.server_certificate = ss
46
+ @options.updated = true
47
+ end
48
+ end
49
+ end
50
+
51
+ def policies=(policy_list)
52
+ log(:info, 'Update Listener Policies', :green, log_id)
53
+ log(:info, ' set policies=' + policy_list.map {|i| i.name }.join(', '), :green)
54
+
55
+ unless @options.dry_run
56
+ @options.elb.client.set_load_balancer_policies_of_listener({
57
+ :load_balancer_name => @listener.load_balancer.name,
58
+ :load_balancer_port => @listener.port,
59
+ :policy_names => policy_list.map {|i| i.name },
60
+ })
61
+
62
+ @options.updated = true
63
+ end
64
+ end
65
+
66
+ def delete
67
+ log(:info, 'Delete Listener', :red, log_id)
68
+
69
+ related_policies = self.policies
70
+
71
+ unless @options.dry_run
72
+ @listener.delete
73
+ @options.updated = true
74
+ end
75
+
76
+ unless @options.without_deleting_policy
77
+ related_policies.each do |plcy|
78
+ plcy.delete
79
+ end
80
+ end
81
+ end
82
+
83
+ def has_difference_protocol_port?(dsl)
84
+ not (
85
+ @listener.protocol == dsl.protocol &&
86
+ @listener.port == dsl.port &&
87
+ @listener.instance_protocol == dsl.instance_protocol &&
88
+ @listener.instance_port == dsl.instance_port
89
+ )
90
+ end
91
+
92
+ def log_id
93
+ log_id = [[@listener.protocol, @listener.port], [@listener.instance_protocol, @listener.instance_port]].map {|i| i.inspect }.join(' => ')
94
+ "#{@listener.load_balancer.vpc_id || :classic} > #{@listener.load_balancer.name} > #{log_id}"
95
+ end
96
+
97
+ private
98
+ def compare_server_certificate(dsl)
99
+ aws_server_certificate = @listener.server_certificate
100
+ aws_server_certificate = aws_server_certificate.name if aws_server_certificate
101
+ same = (aws_server_certificate == dsl.server_certificate)
102
+ yield if !same && block_given?
103
+ return same
104
+ end
105
+ end # Listener
106
+ end # ListenerCollection
107
+ end # LoadBalancer
108
+ end # LoadBalancerCollection
109
+ end # ELBWrapper
110
+ end # Kelbim
@@ -0,0 +1,101 @@
1
+ require 'ostruct'
2
+ require 'kelbim/wrapper/load-balancer'
3
+ require 'kelbim/logger'
4
+
5
+ module Kelbim
6
+ class ELBWrapper
7
+ class LoadBalancerCollection
8
+ include Logger::ClientHelper
9
+
10
+ def initialize(load_balancers, options)
11
+ @load_balancers = load_balancers
12
+ @options = options
13
+ end
14
+
15
+ def each
16
+ @load_balancers.each do |lb|
17
+ yield(LoadBalancer.new(lb, @options))
18
+ end
19
+ end
20
+
21
+ def create(dsl, vpc)
22
+ log(:info, 'Create LoadBalancer', :cyan, "#{vpc || :classic} > #{dsl.name}")
23
+
24
+ if @options.dry_run
25
+ listeners = dsl.listeners
26
+
27
+ lb = OpenStruct.new({
28
+ :id => "<new load balancer name=#{dsl.name}>",
29
+ :name => dsl.name,
30
+ :vpc_id => vpc,
31
+ :instances => dsl.instances,
32
+ :scheme => (dsl.internal ? 'internal' : 'internet-facing'),
33
+ :listeners => listeners,
34
+ :health_check => {}, # health_checkはLoadBalancerの処理で更新
35
+ })
36
+
37
+ listeners.each do |lstnr|
38
+ lstnr.load_balancer = lb
39
+
40
+ if lstnr.server_certificate
41
+ lstnr.server_certificate = OpenStruct.new(:name => lstnr.server_certificate)
42
+ end
43
+ end
44
+
45
+ if vpc
46
+ lb.subnets = dsl.subnets.map {|i| OpenStruct.new(:id => i) }
47
+ sg_names = @options.security_group_names[vpc] || {}
48
+ lb.security_group_ids = dsl.security_groups {|i| sg_names.key(i) || i }
49
+ else
50
+ lb.availability_zones = dsl.availability_zones.map {|i| OpenStruct.new(:name => i) }
51
+ end
52
+ else
53
+ opts = {
54
+ :scheme => (dsl.internal ? 'internal' : 'internet-facing'),
55
+ :listeners => [],
56
+ }
57
+
58
+ opts[:instances] = dsl.instances unless dsl.instances.empty?
59
+
60
+ dsl.listeners.each do |lstnr|
61
+ lstnr_opts = {
62
+ :port => lstnr.port,
63
+ :protocol => lstnr.protocol,
64
+ :instance_protocol => lstnr.instance_protocol,
65
+ :instance_port => lstnr.instance_port,
66
+ }
67
+
68
+ if (ss_name = lstnr.server_certificate)
69
+ ss = @options.iam.server_certificates[ss_name]
70
+
71
+ unless ss
72
+ raise "Can't find ServerCertificate: #{ss_name} in #{vpc || :classic} > #{dsl.name}"
73
+ end
74
+
75
+ lstnr_opts[:server_certificate] = ss.arn
76
+ end
77
+
78
+ opts[:listeners] << lstnr_opts
79
+ end
80
+
81
+ if vpc
82
+ opts[:subnets] = dsl.subnets.map {|i| AWS::EC2::Subnet.new(i) }
83
+ sg_names = @options.security_group_names[vpc] || {}
84
+
85
+ opts[:security_groups] = dsl.security_groups.map do |i|
86
+ AWS::EC2::SecurityGroup.new(sg_names.key(i) || i)
87
+ end
88
+ else
89
+ opts[:availability_zones] = dsl.availability_zones.map {|i| AWS::EC2::AvailabilityZone.new(i) }
90
+ end
91
+
92
+ # health_checkはLoadBalancerの処理で更新
93
+ lb = @load_balancers.create(dsl.name, opts)
94
+ @options.updated = true
95
+ end
96
+
97
+ LoadBalancer.new(lb, @options)
98
+ end
99
+ end # LoadBalancerCollection
100
+ end # ELBWrapper
101
+ end # Kelbim
@@ -0,0 +1,217 @@
1
+ require 'forwardable'
2
+ require 'kelbim/wrapper/listener-collection'
3
+ require 'kelbim/logger'
4
+
5
+ module Kelbim
6
+ class ELBWrapper
7
+ class LoadBalancerCollection
8
+ class LoadBalancer
9
+ extend Forwardable
10
+ include Logger::ClientHelper
11
+
12
+ def_delegators(
13
+ :@load_balancer,
14
+ :vpc_id, :name)
15
+
16
+ def initialize(load_balancer, options)
17
+ @load_balancer = load_balancer
18
+ @options = options
19
+ end
20
+
21
+ def listeners
22
+ ListenerCollection.new(@load_balancer.listeners, self, @options)
23
+ end
24
+
25
+ def eql?(dsl)
26
+ compare_health_check(dsl) or return false
27
+
28
+ if self.vpc_id
29
+ compare_subnet_ids(dsl) or return false
30
+ compare_security_groups(dsl) or return false
31
+ else
32
+ compare_availability_zones(dsl) or return false
33
+ end
34
+
35
+ compare_instances(dsl)
36
+ end
37
+
38
+ def update(dsl)
39
+ log(:info, 'Update LoadBalancer', :green, log_id)
40
+
41
+ compare_instances(dsl) do |aws_instance_ids, dsl_instance_ids|
42
+ instance_names = @options.instance_names[self.vpc_id] || {}
43
+
44
+ add_ids = (dsl_instance_ids - aws_instance_ids)
45
+
46
+ unless add_ids.empty?
47
+ log(:info, ' register instances=' + add_ids.map {|i| instance_names.fetch(i, i) }.join(', '), :green)
48
+
49
+ unless @options.dry_run
50
+ @load_balancer.instances.register(*add_ids)
51
+ @options.updated = true
52
+ end
53
+ end
54
+
55
+ del_ids = (aws_instance_ids - dsl_instance_ids)
56
+
57
+ unless del_ids.empty?
58
+ log(:info, ' deregister instances=' + del_ids.map {|i| instance_names.fetch(i, i) }.join(', '), :green)
59
+
60
+ unless @options.dry_run
61
+ @load_balancer.instances.deregister(*del_ids)
62
+ @options.updated = true
63
+ end
64
+ end
65
+ end
66
+
67
+ compare_health_check(dsl) do
68
+ log(:info, ' set health_check=' + dsl.health_check.inspect, :green)
69
+
70
+ unless @options.dry_run
71
+ @load_balancer.configure_health_check(dsl.health_check)
72
+ @options.updated = true
73
+ end
74
+ end
75
+
76
+ if self.vpc_id
77
+ compare_subnet_ids(dsl) do |aws_subnet_ids, dsl_subnet_ids|
78
+ add_ids = (dsl_subnet_ids - aws_subnet_ids)
79
+
80
+ unless add_ids.empty?
81
+ log(:info, ' attach subnets=' + add_ids.join(', '), :green)
82
+
83
+ unless @options.dry_run
84
+ @options.elb.client.attach_load_balancer_to_subnets(
85
+ :load_balancer_name => @load_balancer.name,
86
+ :subnets => add_ids,
87
+ )
88
+
89
+ @options.updated = true
90
+ end
91
+ end
92
+
93
+ del_ids = (aws_subnet_ids - dsl_subnet_ids)
94
+
95
+ unless del_ids.empty?
96
+ log(:info, ' detach subnets=' + del_ids.join(', '), :green)
97
+
98
+ unless @options.dry_run
99
+ @options.elb.client.detach_load_balancer_from_subnets(
100
+ :load_balancer_name => @load_balancer.name,
101
+ :subnets => del_ids,
102
+ )
103
+
104
+ @options.updated = true
105
+ end
106
+ end
107
+ end
108
+
109
+ compare_security_groups(dsl) do |dsl_sg_ids|
110
+ sg_names = @options.security_group_names[self.vpc_id] || {}
111
+ log(:info, ' apply security groups=' + dsl_sg_ids.map {|i| sg_names.fetch(i, i) }.join(', '), :green)
112
+
113
+ unless @options.dry_run
114
+ @options.elb.client.apply_security_groups_to_load_balancer(
115
+ :load_balancer_name => @load_balancer.name,
116
+ :security_groups => dsl_sg_ids,
117
+ )
118
+
119
+ @options.updated = true
120
+ end
121
+ end
122
+ else
123
+ compare_availability_zones(dsl) do |aws_az_names, dsl_az_names|
124
+ add_names = (dsl_az_names - aws_az_names)
125
+
126
+ unless add_names.empty?
127
+ log(:info, ' enable availability zones=' + add_names.join(', '), :green)
128
+
129
+ unless @options.dry_run
130
+ add_names.each do |az_name|
131
+ @load_balancer.availability_zones.enable(az_name)
132
+ end
133
+
134
+ @options.updated = true
135
+ end
136
+ end
137
+
138
+ del_names = (aws_az_names - dsl_az_names)
139
+
140
+ unless del_names.empty?
141
+ log(:info, ' disable availability zones=' + del_names.join(', '), :green)
142
+
143
+ unless @options.dry_run
144
+ del_names.each do |az_name|
145
+ @load_balancer.availability_zones.disable(az_name)
146
+ end
147
+
148
+ @options.updated = true
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ def delete
156
+ log(:info, 'Delete LoadBalancer', :red, log_id)
157
+
158
+ unless @options.dry_run
159
+ @load_balancer.delete
160
+ @options.updated = true
161
+ end
162
+ end
163
+
164
+ private
165
+ def compare_health_check(dsl)
166
+ same = (@load_balancer.health_check.sort == dsl.health_check.sort)
167
+ yield if !same && block_given?
168
+ return same
169
+ end
170
+
171
+ def compare_subnet_ids(dsl)
172
+ subnet_ids = @load_balancer.subnets.map {|i| i.id }
173
+ same = (subnet_ids.sort == dsl.subnets.sort )
174
+ yield(subnet_ids, dsl.subnets) if !same && block_given?
175
+ return same
176
+ end
177
+
178
+ def compare_security_groups(dsl)
179
+ aws_sg_ids = @load_balancer.security_group_ids.sort
180
+ sg_names = @options.security_group_names[self.vpc_id] || {}
181
+
182
+ dsl_sg_ids = dsl.security_groups.map {|i|
183
+ sg_names.key(i) || i
184
+ }.sort
185
+
186
+ same = (aws_sg_ids == dsl_sg_ids)
187
+ yield(dsl_sg_ids) if !same && block_given?
188
+ return same
189
+ end
190
+
191
+ def compare_availability_zones(dsl)
192
+ az_names = @load_balancer.availability_zones.map {|i| i.name }
193
+ same = (az_names.sort == dsl.availability_zones.sort)
194
+ yield(az_names, dsl.availability_zones) if !same && block_given?
195
+ return same
196
+ end
197
+
198
+ def compare_instances(dsl)
199
+ aws_instance_ids = @load_balancer.instances.map {|i| i.id }.sort
200
+
201
+ dsl_instance_ids = dsl.instances.map {|i|
202
+ instance_names = @options.instance_names[self.vpc_id] || {}
203
+ instance_names.key(i) || i
204
+ }.sort
205
+
206
+ same = (aws_instance_ids == dsl_instance_ids)
207
+ yield(aws_instance_ids, dsl_instance_ids) if !same && block_given?
208
+ return same
209
+ end
210
+
211
+ def log_id
212
+ "#{self.vpc_id || :classic} > #{self.name}"
213
+ end
214
+ end # LoadBalancer
215
+ end # LoadBalancerCollection
216
+ end # ELBWrapper
217
+ end # Kelbim
@@ -0,0 +1,96 @@
1
+ require 'ostruct'
2
+ require 'kelbim/wrapper/policy'
3
+ require 'kelbim/policy-types'
4
+ require 'kelbim/logger'
5
+ require 'uuid'
6
+
7
+ module Kelbim
8
+ class ELBWrapper
9
+ class LoadBalancerCollection
10
+ class LoadBalancer
11
+ class ListenerCollection
12
+ class Listener
13
+ class PolicyCollection
14
+ include Logger::ClientHelper
15
+
16
+ class << self
17
+ def create_mock_policy(dsl)
18
+ dsl_type, dsl_name_or_attrs = dsl
19
+ policy_type = PolicyTypes.symbol_to_string(dsl_type)
20
+ plcy = OpenStruct.new(:type => policy_type)
21
+
22
+ if PolicyTypes.name?(dsl_name_or_attrs)
23
+ plcy.name = dsl_name_or_attrs
24
+ plcy.type = {'<new policy attribute name>' => ['<new policy attribute value>']}
25
+ else
26
+ plcy.name = '<new policy name>'
27
+ plcy.attributes = PolicyTypes.unexpand(dsl_type, dsl_name_or_attrs)
28
+ end
29
+
30
+ return plcy
31
+ end
32
+ end # of class methods
33
+
34
+ def initialize(policies, listener, options)
35
+ @policies = policies
36
+ @listener = listener
37
+ @options = options
38
+ end
39
+
40
+ def each
41
+ @policies.each do |plcy|
42
+ yield(Policy.new(plcy, @listener, @options))
43
+ end
44
+ end
45
+
46
+ def create(dsl)
47
+ dsl_type, dsl_name_or_attrs = dsl
48
+ log_id = "#{@listener.load_balancer.vpc_id || :classic} > #{@listener.load_balancer.name} > #{PolicyTypes.symbol_to_string(dsl_type)}: "
49
+ log_id += PolicyTypes.name?(dsl_name_or_attrs) ? dsl_name_or_attrs : dsl_name_or_attrs.inspect
50
+ log(:info, 'Create Policy', :cyan, log_id)
51
+
52
+ plcy = @options.dry_run ? self.class.create_mock_policy(dsl) : create_policy(dsl)
53
+ Policy.new(plcy, @listener, @options)
54
+ end
55
+
56
+ private
57
+ def create_policy(dsl)
58
+ dsl_type, dsl_name_or_attrs = dsl
59
+ policy_type = PolicyTypes.symbol_to_string(dsl_type)
60
+
61
+ if PolicyTypes.name?(dsl_name_or_attrs)
62
+ plcy = @listener.load_balancer.policies[dsl_name_or_attrs]
63
+
64
+ unless plcy
65
+ raise "Can't find Policy: #{dsl_name_or_attrs} in #{@listener.load_balancer.vpc_id || :classic} > #{@listener.load_balancer.name}"
66
+ end
67
+ else
68
+ policy_name = [
69
+ @listener.load_balancer.vpc_id || :classic,
70
+ @listener.load_balancer.name,
71
+ @listener.protocol,
72
+ @listener.port,
73
+ @listener.instance_protocol,
74
+ @listener.instance_port,
75
+ policy_type,
76
+ UUID.new.generate,
77
+ ].join('-').gsub(/\s/, '_')
78
+
79
+ plcy = @listener.load_balancer.policies.create(
80
+ policy_name,
81
+ policy_type,
82
+ PolicyTypes.unexpand(dsl_type, dsl_name_or_attrs)
83
+ )
84
+ end
85
+
86
+ @options.updated = true
87
+
88
+ return plcy
89
+ end
90
+ end # PolicyCollection
91
+ end # Listener
92
+ end # ListenerCollection
93
+ end # LoadBalancer
94
+ end # LoadBalancerCollection
95
+ end # ELBWrapper
96
+ end # Kelbim
@@ -0,0 +1,52 @@
1
+ require 'forwardable'
2
+ require 'kelbim/policy-types'
3
+ require 'kelbim/logger'
4
+
5
+ module Kelbim
6
+ class ELBWrapper
7
+ class LoadBalancerCollection
8
+ class LoadBalancer
9
+ class ListenerCollection
10
+ class Listener
11
+ class PolicyCollection
12
+ class Policy
13
+ extend Forwardable
14
+ include Logger::ClientHelper
15
+
16
+ def_delegators(
17
+ :@policy,
18
+ :name, :type)
19
+
20
+ def initialize(policy, listener, options)
21
+ @policy = policy
22
+ @listener = listener
23
+ @options = options
24
+ end
25
+
26
+ def eql?(dsl)
27
+ dsl_type, dsl_name_or_attrs = dsl
28
+
29
+ if PolicyTypes.name?(dsl_name_or_attrs)
30
+ @policy.name == dsl_name_or_attrs
31
+ else
32
+ aws_attrs = PolicyTypes.expand(@policy.type, @policy.attributes)
33
+ aws_attrs.sort == dsl_name_or_attrs.sort
34
+ end
35
+ end
36
+
37
+ def delete
38
+ log(:info, 'Delete Policy', :red, "#{@listener.log_id} > #{self.name}")
39
+
40
+ unless @options.dry_run
41
+ @policy.delete
42
+ @options.updated = true
43
+ end
44
+ end
45
+ end # Policy
46
+ end # PolicyCollection
47
+ end # Listener
48
+ end # ListenerCollection
49
+ end # LoadBalancer
50
+ end # LoadBalancerCollection
51
+ end # ELBWrapper
52
+ end # Kelbim
data/lib/kelbim.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'kelbim/version'
2
+ require 'kelbim/client'