gce-host 0.1.0
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/.gitignore +20 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +210 -0
- data/Rakefile +30 -0
- data/bin/gce-host +4 -0
- data/docs/GCE.html +132 -0
- data/docs/GCE/Host.html +901 -0
- data/docs/GCE/Host/CLI.html +610 -0
- data/docs/GCE/Host/Config.html +1195 -0
- data/docs/GCE/Host/GCEClient.html +215 -0
- data/docs/GCE/Host/GCEClient/Error.html +127 -0
- data/docs/GCE/Host/GCEClient/NotFound.html +131 -0
- data/docs/GCE/Host/HashUtil.html +178 -0
- data/docs/GCE/Host/HostData.html +1658 -0
- data/docs/GCE/Host/RoleData.html +932 -0
- data/docs/GCE/Host/StringUtil.html +359 -0
- data/docs/_index.html +231 -0
- data/docs/class_list.html +58 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +57 -0
- data/docs/css/style.css +339 -0
- data/docs/file.LICENSE.html +95 -0
- data/docs/file.README.html +312 -0
- data/docs/file_list.html +63 -0
- data/docs/frames.html +26 -0
- data/docs/index.html +312 -0
- data/docs/js/app.js +219 -0
- data/docs/js/full_list.js +181 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +477 -0
- data/docs/top-level-namespace.html +112 -0
- data/example/example.conf +8 -0
- data/example/example.rb +6 -0
- data/gce-host.gemspec +26 -0
- data/lib/gce-host.rb +7 -0
- data/lib/gce/host.rb +120 -0
- data/lib/gce/host/cli.rb +151 -0
- data/lib/gce/host/config.rb +109 -0
- data/lib/gce/host/gce_client.rb +69 -0
- data/lib/gce/host/hash_util.rb +11 -0
- data/lib/gce/host/host_data.rb +227 -0
- data/lib/gce/host/role_data.rb +64 -0
- data/lib/gce/host/string_util.rb +31 -0
- data/lib/gce/host/version.rb +5 -0
- data/spec/gce_client_spec.rb +29 -0
- data/spec/host_spec.rb +199 -0
- data/spec/spec_helper.rb +22 -0
- data/terraform.tf +52 -0
- metadata +226 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
require_relative 'version'
|
2
|
+
require 'google/apis/compute_v1'
|
3
|
+
|
4
|
+
class GCE
|
5
|
+
class Host
|
6
|
+
class GCEClient
|
7
|
+
class Error < ::StandardError; end
|
8
|
+
class NotFound < Error; end
|
9
|
+
|
10
|
+
def instances(condition = {})
|
11
|
+
filter = build_filter(condition)
|
12
|
+
instances = []
|
13
|
+
res = client.list_aggregated_instances(Config.project, filter: filter)
|
14
|
+
instances.concat(res.items.values.map(&:instances).compact.flatten(1))
|
15
|
+
while res.next_page_token
|
16
|
+
res = client.list_aggregated_instances(Config.project, filter: filter, page_token: res.next_page_token)
|
17
|
+
instances.concat(res.items.values.map(&:instances).compact.flatten(1))
|
18
|
+
end
|
19
|
+
instances
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def client
|
25
|
+
return @client if @client && @client_expiration > Time.now
|
26
|
+
|
27
|
+
scope = "https://www.googleapis.com/auth/compute.readonly"
|
28
|
+
client = Google::Apis::ComputeV1::ComputeService.new
|
29
|
+
client.client_options.application_name = 'gce-host'
|
30
|
+
client.client_options.application_name = GCE::Host::VERSION
|
31
|
+
client.request_options.retries = Config.retries
|
32
|
+
client.request_options.timeout_sec = Config.timeout_sec
|
33
|
+
client.request_options.open_timeout_sec = Config.open_timeout_sec
|
34
|
+
|
35
|
+
case Config.auth_method
|
36
|
+
when 'compute_engine'
|
37
|
+
auth = Google::Auth::GCECredentials.new
|
38
|
+
|
39
|
+
when 'json_key'
|
40
|
+
credential_file = Config.credential_file
|
41
|
+
auth = File.open(credential_file) do |f|
|
42
|
+
Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: f, scope: scope)
|
43
|
+
end
|
44
|
+
|
45
|
+
when 'application_default'
|
46
|
+
auth = Google::Auth.get_application_default([scope])
|
47
|
+
|
48
|
+
else
|
49
|
+
raise ConfigError, "Unknown auth method: #{Config.auth_method}"
|
50
|
+
end
|
51
|
+
|
52
|
+
client.authorization = auth
|
53
|
+
|
54
|
+
@client_expiration = Time.now + 1800
|
55
|
+
@client = client
|
56
|
+
end
|
57
|
+
|
58
|
+
# MEMO: OR did not work
|
59
|
+
# MEMO: filter for metadata and tags did not work (metadata.items[0].value eq role)
|
60
|
+
def build_filter(condition)
|
61
|
+
if names = (condition[:name] || condition[:hostname]) and Array(names).size == 1
|
62
|
+
"name eq #{Array(names).first}"
|
63
|
+
else
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
class GCE
|
4
|
+
class Host
|
5
|
+
# Represents each host
|
6
|
+
class HostData
|
7
|
+
attr_reader :instance
|
8
|
+
|
9
|
+
# :hostname, # hostname
|
10
|
+
# :roles, # roles.split(',') such as web:app1,db:app1
|
11
|
+
# :instance, # Aws::GCE::Types::Instance itself
|
12
|
+
#
|
13
|
+
# and OPTIONAL_ARRAY_KEYS, OPTIONAL_STRING_KEYS
|
14
|
+
def initialize(instance)
|
15
|
+
@instance = instance
|
16
|
+
end
|
17
|
+
|
18
|
+
def hostname
|
19
|
+
instance.name
|
20
|
+
end
|
21
|
+
|
22
|
+
def roles
|
23
|
+
return @roles if @roles
|
24
|
+
roles = find_array_key(Config.roles_key)
|
25
|
+
@roles = roles.map {|role| GCE::Host::RoleData.build(role) }
|
26
|
+
end
|
27
|
+
|
28
|
+
Config.optional_string_keys.each do |key|
|
29
|
+
field = StringUtil.underscore(key)
|
30
|
+
define_method(field) do
|
31
|
+
instance_variable_get("@#{field}") || instance_variable_set("@#{field}", find_string_key(key))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Config.optional_array_keys.each do |key|
|
36
|
+
field = StringUtil.underscore(key)
|
37
|
+
define_method(field) do
|
38
|
+
instance_variable_get("@#{field}") || instance_variable_set("@#{field}", find_array_key(key))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
define_method(Config.status) do
|
43
|
+
instance.status
|
44
|
+
end
|
45
|
+
|
46
|
+
def instance_id
|
47
|
+
instance.id
|
48
|
+
end
|
49
|
+
|
50
|
+
def zone
|
51
|
+
instance.zone.split('/').last
|
52
|
+
end
|
53
|
+
|
54
|
+
def private_ip_address
|
55
|
+
instance.network_interfaces.first.network_ip
|
56
|
+
end
|
57
|
+
|
58
|
+
def private_ip_addresses
|
59
|
+
instance.network_interfaces.map(&:network_ip)
|
60
|
+
end
|
61
|
+
|
62
|
+
def public_ip_address
|
63
|
+
instance.network_interfaces.first.access_configs.first.nat_ip
|
64
|
+
end
|
65
|
+
|
66
|
+
def public_ip_addresses
|
67
|
+
instance.network_interfaces.map {|i| i.access_configs.map(&:nat_ip) }.flatten(1)
|
68
|
+
end
|
69
|
+
|
70
|
+
def creation_timestamp
|
71
|
+
instance.creation_timestamp
|
72
|
+
end
|
73
|
+
|
74
|
+
# compatibility with dino-host
|
75
|
+
def ip
|
76
|
+
private_ip_address
|
77
|
+
end
|
78
|
+
|
79
|
+
# compatibility with dino-host
|
80
|
+
def start_date
|
81
|
+
creation_timestamp
|
82
|
+
end
|
83
|
+
|
84
|
+
# compatibility with dino-host
|
85
|
+
def usages
|
86
|
+
roles
|
87
|
+
end
|
88
|
+
|
89
|
+
def terminated?
|
90
|
+
instance.status == "TERMINATED"
|
91
|
+
end
|
92
|
+
|
93
|
+
def stopping?
|
94
|
+
instance.status == "STOPPING"
|
95
|
+
end
|
96
|
+
|
97
|
+
def running?
|
98
|
+
instance.status == "RUNNING"
|
99
|
+
end
|
100
|
+
|
101
|
+
def staging?
|
102
|
+
instance.status == "STAGING"
|
103
|
+
end
|
104
|
+
|
105
|
+
def provisioning?
|
106
|
+
instance.status == "PROVISIONING"
|
107
|
+
end
|
108
|
+
|
109
|
+
# match with condition or not
|
110
|
+
#
|
111
|
+
# @param [Hash] condition search parameters
|
112
|
+
def match?(condition)
|
113
|
+
return false if !condition[Config.status.to_sym] and (terminated? or stopping?)
|
114
|
+
return false unless role_match?(condition)
|
115
|
+
return false unless status_match?(condition)
|
116
|
+
return false unless instance_match?(condition)
|
117
|
+
true
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_hash
|
121
|
+
params = {
|
122
|
+
"hostname" => hostname,
|
123
|
+
"roles" => roles,
|
124
|
+
"zone" => zone,
|
125
|
+
}
|
126
|
+
Config.optional_string_keys.each do |key|
|
127
|
+
field = StringUtil.underscore(key)
|
128
|
+
params[field] = send(field)
|
129
|
+
end
|
130
|
+
Config.optional_array_keys.each do |key|
|
131
|
+
field = StringUtil.underscore(key)
|
132
|
+
params[field] = send(field)
|
133
|
+
end
|
134
|
+
params.merge!(
|
135
|
+
"instance_id" => instance_id,
|
136
|
+
"private_ip_address" => private_ip_address,
|
137
|
+
"public_ip_address" => public_ip_address,
|
138
|
+
"creation_timestamp" => creation_timestamp,
|
139
|
+
Config.status => send(Config.status),
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
def info
|
144
|
+
if self.class.display_short_info?
|
145
|
+
info = "#{hostname}:#{status}"
|
146
|
+
info << "(#{roles.join(',')})" unless roles.empty?
|
147
|
+
info << "[#{tags.join(',')}]" unless tags.empty?
|
148
|
+
info << "{#{service}}" unless service.empty?
|
149
|
+
info
|
150
|
+
else
|
151
|
+
to_hash.to_s
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def inspect
|
156
|
+
sprintf "#<GCE::Host::HostData %s>", info
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def find_string_key(key)
|
162
|
+
item = instance.metadata.items.find {|item| item.key == key } if instance.metadata.items
|
163
|
+
item ? item.value : ''
|
164
|
+
end
|
165
|
+
|
166
|
+
def find_array_key(key)
|
167
|
+
item = instance.metadata.items.find {|item| item.key == key } if instance.metadata.items
|
168
|
+
item ? item.value.split(Config.array_value_delimiter) : []
|
169
|
+
end
|
170
|
+
|
171
|
+
def role_match?(condition)
|
172
|
+
# usage is an alias of role
|
173
|
+
if role = (condition[:role] || condition[:usage])
|
174
|
+
role1, role2, role3 = role.first.split(':')
|
175
|
+
else
|
176
|
+
role1 = (condition[:role1] || condition[:usage1] || []).first
|
177
|
+
role2 = (condition[:role2] || condition[:usage2] || []).first
|
178
|
+
role3 = (condition[:role3] || condition[:usage3] || []).first
|
179
|
+
end
|
180
|
+
if role1
|
181
|
+
return false unless roles.find {|role| role.match?(role1, role2, role3) }
|
182
|
+
end
|
183
|
+
true
|
184
|
+
end
|
185
|
+
|
186
|
+
def status_match?(condition)
|
187
|
+
if values = condition[Config.status.to_sym]
|
188
|
+
return false unless values.map(&:downcase).include?(send(Config.status).downcase)
|
189
|
+
end
|
190
|
+
true
|
191
|
+
end
|
192
|
+
|
193
|
+
def instance_match?(condition)
|
194
|
+
condition = HashUtil.except(condition, :role, :role1, :role2, :role3, :usage, :usage1, :usage2, :usage3, Config.status.to_sym)
|
195
|
+
condition.each do |key, values|
|
196
|
+
v = instance_variable_recursive_get(key)
|
197
|
+
if v.is_a?(Array)
|
198
|
+
return false unless v.find {|_| values.include?(_) }
|
199
|
+
else
|
200
|
+
return false unless values.include?(v)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
true
|
204
|
+
end
|
205
|
+
|
206
|
+
# "instance.instance_id" => self.instance.instance_id
|
207
|
+
def instance_variable_recursive_get(key)
|
208
|
+
v = self
|
209
|
+
key.to_s.split('.').each {|k| v = v.send(k) }
|
210
|
+
v
|
211
|
+
end
|
212
|
+
|
213
|
+
# compatibility with dono-host
|
214
|
+
#
|
215
|
+
# If service,status,tags keys are defined
|
216
|
+
#
|
217
|
+
# OPTIONAL_STRING_KEYS=service,status
|
218
|
+
# OPTIONAL_ARRAY_KEYS=tags
|
219
|
+
#
|
220
|
+
# show in short format, otherwise, same with to_hash.to_s
|
221
|
+
def self.display_short_info?
|
222
|
+
return @display_short_info unless @display_short_info.nil?
|
223
|
+
@display_short_info = method_defined?(:service) and method_defined?(:status) and method_defined?(:tags)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class GCE
|
2
|
+
class Host
|
3
|
+
# Represents each role
|
4
|
+
class RoleData
|
5
|
+
attr_reader :role1, :role2, :role3
|
6
|
+
|
7
|
+
def initialize(role1, role2 = nil, role3 = nil)
|
8
|
+
@role1 = role1
|
9
|
+
@role2 = role2
|
10
|
+
@role3 = role3
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.build(role)
|
14
|
+
role1, role2, role3 = role.split(Config.role_value_delimiter, 3)
|
15
|
+
new(role1, role2, role3)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [String] something like "admin:jenkins:slave"
|
19
|
+
def role
|
20
|
+
@role ||= [role1, role2, role3].compact.reject(&:empty?).join(Config.role_value_delimiter)
|
21
|
+
end
|
22
|
+
alias :to_s :role
|
23
|
+
|
24
|
+
# @return [Array] something like ["admin", "admin:jenkins", "admin:jenkins:slave"]
|
25
|
+
def uppers
|
26
|
+
uppers = [RoleData.new(role1)]
|
27
|
+
uppers << RoleData.new(role1, role2) if role2 and !role2.empty?
|
28
|
+
uppers << RoleData.new(role1, role2, role3) if role3 and !role3.empty?
|
29
|
+
uppers
|
30
|
+
end
|
31
|
+
|
32
|
+
def match?(role1, role2 = nil, role3 = nil)
|
33
|
+
if role3
|
34
|
+
role1 == self.role1 and role2 == self.role2 and role3 == self.role3
|
35
|
+
elsif role2
|
36
|
+
role1 == self.role1 and role2 == self.role2
|
37
|
+
else
|
38
|
+
role1 == self.role1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Equality
|
43
|
+
#
|
44
|
+
# Role::Data.new('admin') == Role::Data.new('admin') #=> true
|
45
|
+
# Role::Data.new('admin', 'jenkin') == "admin:jenkins" #=> true
|
46
|
+
#
|
47
|
+
# @param [Object] other
|
48
|
+
def ==(other)
|
49
|
+
case other
|
50
|
+
when String
|
51
|
+
self.role == other
|
52
|
+
when GCE::Host::RoleData
|
53
|
+
super(other)
|
54
|
+
else
|
55
|
+
false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def inspect
|
60
|
+
"\"#{to_s}\""
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class GCE
|
2
|
+
class Host
|
3
|
+
# If want sophisticated utility, better to use ActiveSupport
|
4
|
+
module StringUtil
|
5
|
+
def self.camelize(string)
|
6
|
+
string = string.sub(/^[a-z\d]*/) { $&.capitalize }
|
7
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { $2.capitalize }
|
8
|
+
string.gsub!(/\//, '::')
|
9
|
+
string
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.underscore(camel_cased_word)
|
13
|
+
return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/
|
14
|
+
word = camel_cased_word.to_s.gsub(/::/, '/')
|
15
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
16
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
17
|
+
word.tr!("-", "_")
|
18
|
+
word.downcase!
|
19
|
+
word
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.pluralize(string)
|
23
|
+
"#{string.chomp('s')}s"
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.singularize(string)
|
27
|
+
string.chomp('s')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe GCE::Host::GCEClient do
|
4
|
+
let(:client) { GCE::Host::GCEClient.new }
|
5
|
+
let(:instances) { client.instances }
|
6
|
+
let(:instance) { instances.first }
|
7
|
+
let(:name) { instance.name }
|
8
|
+
|
9
|
+
describe '#instances' do
|
10
|
+
it do
|
11
|
+
expect(instances).not_to be_empty
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'filter with name' do
|
15
|
+
instances = client.instances(name: name)
|
16
|
+
expect(instances).not_to be_empty
|
17
|
+
expect(instances.first.name).to eq(name)
|
18
|
+
|
19
|
+
instances = client.instances(name: 'something_not_exist')
|
20
|
+
expect(instances).to be_empty
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'filter with hostname (alias of name)' do
|
24
|
+
instances = client.instances(hostname: name)
|
25
|
+
expect(instances).not_to be_empty
|
26
|
+
expect(instances.first.name).to eq(name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/host_spec.rb
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'host' do
|
4
|
+
it 'should respond_to' do
|
5
|
+
[ :hostname,
|
6
|
+
:roles,
|
7
|
+
:zone,
|
8
|
+
GCE::Host::Config.status.to_sym,
|
9
|
+
:service,
|
10
|
+
:status,
|
11
|
+
:tags,
|
12
|
+
:instance,
|
13
|
+
:instance_id,
|
14
|
+
:private_ip_address,
|
15
|
+
:private_ip_addresses,
|
16
|
+
:public_ip_address,
|
17
|
+
:public_ip_addresses,
|
18
|
+
:creation_timestamp,
|
19
|
+
:ip,
|
20
|
+
:start_date,
|
21
|
+
:usages,
|
22
|
+
].each do |k|
|
23
|
+
expect(subject.respond_to?(k)).to be_truthy
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe GCE::Host do
|
29
|
+
describe 'options' do
|
30
|
+
context do
|
31
|
+
let(:subject) { GCE::Host.new(hostname: 'gce-host-web', options: {foo:'bar'}) }
|
32
|
+
it { expect(subject.options).to eq({foo:'bar'}) }
|
33
|
+
it { expect(subject.conditions).to eq([{hostname: ['gce-host-web']}]) }
|
34
|
+
end
|
35
|
+
|
36
|
+
context do
|
37
|
+
let(:subject) { GCE::Host.new({hostname: 'gce-host-web'}, {hostname: 'gce-host-db'}, options: {foo:'bar'}) }
|
38
|
+
it { expect(subject.options).to eq({foo:'bar'}) }
|
39
|
+
it { expect(subject.conditions).to eq([{hostname: ['gce-host-web']}, {hostname: ['gce-host-db']}]) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context '#to_hash' do
|
44
|
+
let(:subject) { GCE::Host.new(service: 'gce-host').first.to_hash }
|
45
|
+
|
46
|
+
it 'keys' do
|
47
|
+
expect(subject.keys).to eq([
|
48
|
+
'hostname',
|
49
|
+
'roles',
|
50
|
+
'zone',
|
51
|
+
'service',
|
52
|
+
'status',
|
53
|
+
'tags',
|
54
|
+
'instance_id',
|
55
|
+
'private_ip_address',
|
56
|
+
'public_ip_address',
|
57
|
+
'creation_timestamp',
|
58
|
+
GCE::Host::Config.status,
|
59
|
+
])
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'values are not empty' do
|
63
|
+
expect(subject.values.any? {|v| v.nil? or (v.respond_to?(:empty?) and v.empty?) }).to be_falsey
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'by hostname' do
|
68
|
+
let(:hosts) { GCE::Host.new(hostname: 'gce-host-web').to_a }
|
69
|
+
let(:subject) { hosts.first }
|
70
|
+
it_should_behave_like 'host'
|
71
|
+
it { expect(hosts.size).to eq(1) }
|
72
|
+
it { expect(subject.hostname).to eq('gce-host-web') }
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'by instance_id' do
|
76
|
+
let(:instance_id) { GCE::Host.new(service: 'gce-host').first.instance_id }
|
77
|
+
|
78
|
+
context 'by instance_id' do
|
79
|
+
let(:hosts) { GCE::Host.new(instance_id: instance_id).to_a }
|
80
|
+
let(:subject) { hosts.first }
|
81
|
+
it_should_behave_like 'host'
|
82
|
+
it { expect(hosts.size).to eq(1) }
|
83
|
+
it { expect(subject.instance_id).to eq(instance_id) }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'by role' do
|
88
|
+
context 'by a role' do
|
89
|
+
let(:subject) { GCE::Host.new(role: 'web:test').first }
|
90
|
+
it_should_behave_like 'host'
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'by a role1' do
|
94
|
+
let(:subject) { GCE::Host.new(role1: 'web').first }
|
95
|
+
it_should_behave_like 'host'
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'by multiple roles (or)' do
|
99
|
+
let(:hosts) {
|
100
|
+
GCE::Host.new(
|
101
|
+
{
|
102
|
+
role1: 'web',
|
103
|
+
role2: 'test',
|
104
|
+
},
|
105
|
+
{
|
106
|
+
role1: 'db',
|
107
|
+
role2: 'test',
|
108
|
+
},
|
109
|
+
).to_a
|
110
|
+
}
|
111
|
+
let(:subject) { hosts.first }
|
112
|
+
it { expect(hosts.size).to be >= 2 }
|
113
|
+
it_should_behave_like 'host'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# for compatibility with dino-host
|
118
|
+
context 'by usage' do
|
119
|
+
context 'by a usage' do
|
120
|
+
let(:subject) { GCE::Host.new(usage: 'web:test').first }
|
121
|
+
it_should_behave_like 'host'
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'by a usage1' do
|
125
|
+
let(:subject) { GCE::Host.new(usage1: 'web').first }
|
126
|
+
it_should_behave_like 'host'
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'by multiple usages (or)' do
|
130
|
+
let(:hosts) {
|
131
|
+
GCE::Host.new(
|
132
|
+
{
|
133
|
+
usage1: 'web',
|
134
|
+
usage2: 'test',
|
135
|
+
},
|
136
|
+
{
|
137
|
+
usage1: 'db',
|
138
|
+
usage2: 'test',
|
139
|
+
},
|
140
|
+
).to_a
|
141
|
+
}
|
142
|
+
let(:subject) { hosts.first }
|
143
|
+
it { expect(hosts.size).to be >= 2 }
|
144
|
+
it_should_behave_like 'host'
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'by status (optional array tags)' do
|
149
|
+
context 'by a status' do
|
150
|
+
let(:subject) { GCE::Host.new(status: :active).first }
|
151
|
+
it_should_behave_like 'host'
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'by multiple status (or)' do
|
155
|
+
let(:hosts) { GCE::Host.new(status: [:reserve, :active]).to_a }
|
156
|
+
let(:subject) { hosts.first }
|
157
|
+
it_should_behave_like 'host'
|
158
|
+
it { expect(hosts.size).to be >= 2 }
|
159
|
+
end
|
160
|
+
|
161
|
+
context 'by a string status' do
|
162
|
+
let(:subject) { GCE::Host.new(status: 'active').first }
|
163
|
+
it_should_behave_like 'host'
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'by multiple string status (or)' do
|
167
|
+
let(:hosts) { GCE::Host.new(status: ['reserve', 'active']).to_a }
|
168
|
+
let(:subject) { hosts.first }
|
169
|
+
it_should_behave_like 'host'
|
170
|
+
it { expect(hosts.size).to be >= 2 }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context 'by service (optional string tags)' do
|
175
|
+
context 'by a service' do
|
176
|
+
let(:subject) { GCE::Host.new(service: 'gce-host').first }
|
177
|
+
it_should_behave_like 'host'
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'by multiple services (or)' do
|
181
|
+
let(:hosts) { GCE::Host.new(service: ['test', 'gce-host']) }
|
182
|
+
let(:subject) { hosts.first }
|
183
|
+
it_should_behave_like 'host'
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context 'by tags (optional array tags)' do
|
188
|
+
context 'by a tag' do
|
189
|
+
let(:subject) { GCE::Host.new(tags: 'master').first }
|
190
|
+
it_should_behave_like 'host'
|
191
|
+
end
|
192
|
+
|
193
|
+
context 'by multiple tags (or)' do
|
194
|
+
let(:hosts) { GCE::Host.new(tags: ['standby', 'master']) }
|
195
|
+
let(:subject) { hosts.first }
|
196
|
+
it_should_behave_like 'host'
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|