gaptool-server 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/app.rb +27 -0
- data/lib/routes.rb +1 -3
- data/tasks/docker.rb +1 -1
- data/test/api_test.rb +24 -2
- data/test/test_helper.rb +9 -0
- metadata +40 -14
- data/bin/gaptool_server_migrate_0.6-0.7 +0 -35
- data/lib/helpers/data.rb +0 -306
- data/lib/helpers/ec2.rb +0 -179
- data/lib/helpers/init.rb +0 -4
- data/lib/helpers/redis.rb +0 -23
- data/lib/helpers/rehash.rb +0 -83
- data/lib/views/init.erb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91476ed75e704cd7168262de3aee3563632c6571
|
4
|
+
data.tar.gz: 6e20d2d9cfd1f1e6d386bf3f8b801ef353cae179
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db20d97b206b75e2753165da1eb30047ff8afede719f0e262477773187d19b916ec1fd9d3faae18a3e6fab08524d62fc9233c4affd0e90e9ef77634da105fbf8
|
7
|
+
data.tar.gz: c56b3aa929695a7b9948580ad0c65e0fdaf76c2df6d0d35d4c2c122eb0f77ca21898b46ba0a867c7014c20b7c532b73b6a44eb11e063719e2d8b201066247d9d
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.7.
|
1
|
+
0.7.1
|
data/lib/app.rb
CHANGED
@@ -10,6 +10,7 @@ require 'net/ssh'
|
|
10
10
|
require 'peach'
|
11
11
|
require 'airbrake'
|
12
12
|
require 'logger'
|
13
|
+
require 'versionomy'
|
13
14
|
require_relative 'exceptions'
|
14
15
|
|
15
16
|
class GaptoolServer < Sinatra::Application
|
@@ -36,6 +37,24 @@ class GaptoolServer < Sinatra::Application
|
|
36
37
|
halt(401, error_response("Unauthenticated"))
|
37
38
|
end
|
38
39
|
|
40
|
+
def check_version(server, client)
|
41
|
+
@@client_versions ||= {}
|
42
|
+
cl_v = @@client_versions[client]
|
43
|
+
if cl_v.nil?
|
44
|
+
begin
|
45
|
+
@@client_versions[client] = Versionomy.parse(client)
|
46
|
+
cl_v = @@client_versions[client]
|
47
|
+
rescue
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
cl_v.major == server.major && cl_v.minor == server.minor
|
52
|
+
end
|
53
|
+
|
54
|
+
def invalid_version(server, client)
|
55
|
+
halt(400, error_response("Invalid version #{client} (server: #{server})"))
|
56
|
+
end
|
57
|
+
|
39
58
|
error do
|
40
59
|
status 500
|
41
60
|
error_response
|
@@ -51,6 +70,11 @@ class GaptoolServer < Sinatra::Application
|
|
51
70
|
disable :sessions
|
52
71
|
enable :dump_errors
|
53
72
|
disable :show_exceptions
|
73
|
+
version = File.read(File.realpath(
|
74
|
+
File.join(File.dirname(__FILE__), "..", 'VERSION')
|
75
|
+
)).strip
|
76
|
+
set(:version, version)
|
77
|
+
set(:version_parsed, Versionomy.parse(version))
|
54
78
|
end
|
55
79
|
|
56
80
|
before do
|
@@ -58,6 +82,9 @@ class GaptoolServer < Sinatra::Application
|
|
58
82
|
user = Gaptool::Data.user(env['HTTP_X_GAPTOOL_USER'])
|
59
83
|
return unauthenticated if user.nil?
|
60
84
|
return unauthenticated unless user[:key] == env['HTTP_X_GAPTOOL_KEY']
|
85
|
+
if !ENV['GAPTOOL_CHECK_CLIENT_VERSION'].nil? && !check_version(settings.version_parsed, env['HTTP_X_GAPTOOL_VERSION'])
|
86
|
+
return invalid_version(settings.version, env['HTTP_X_GAPTOOL_VERSION'])
|
87
|
+
end
|
61
88
|
end
|
62
89
|
end
|
63
90
|
|
data/lib/routes.rb
CHANGED
@@ -227,9 +227,7 @@ class GaptoolServer < Sinatra::Application
|
|
227
227
|
end
|
228
228
|
|
229
229
|
get '/version' do
|
230
|
-
version =
|
231
|
-
File.join(File.dirname(__FILE__), "..", 'VERSION')
|
232
|
-
)).strip
|
230
|
+
version = settings.version
|
233
231
|
json server_version: version, api: {v0: "/"}
|
234
232
|
end
|
235
233
|
|
data/tasks/docker.rb
CHANGED
data/test/api_test.rb
CHANGED
@@ -5,15 +5,21 @@ require 'set'
|
|
5
5
|
describe "Test API" do
|
6
6
|
before(:all) do
|
7
7
|
ENV['DRYRUN'] = 'true'
|
8
|
+
ENV['GAPTOOL_CHECK_CLIENT_VERSION'] = 'true'
|
9
|
+
@version = File.read(File.realpath(
|
10
|
+
File.join(File.dirname(__FILE__), "..", 'VERSION')
|
11
|
+
)).strip.split(".")[0..1].join(".")
|
8
12
|
end
|
9
13
|
|
10
14
|
after(:all) do
|
11
15
|
ENV['DRYRUN'] = nil
|
16
|
+
ENV['GAPTOOL_CHECK_CLIENT_VERSION'] = nil
|
12
17
|
end
|
13
18
|
|
14
19
|
before(:each) do
|
15
|
-
header '
|
16
|
-
header '
|
20
|
+
header 'X-GAPTOOL-USER', 'test'
|
21
|
+
header 'X-GAPTOOL-KEY', 'test'
|
22
|
+
header 'X-GAPTOOL-VERSION', @version
|
17
23
|
$redis.flushall
|
18
24
|
DH.useradd('test', 'test')
|
19
25
|
$time = Time.now
|
@@ -410,4 +416,20 @@ describe "Test API" do
|
|
410
416
|
expect(last_response.status).to eq(200)
|
411
417
|
expect(JSON.parse(last_response.body)).to eq(apps_list)
|
412
418
|
end
|
419
|
+
|
420
|
+
it "should fail as client did not send version" do
|
421
|
+
header 'X-GAPTOOL-VERSION', nil
|
422
|
+
get "/version"
|
423
|
+
expect(last_response.status).to eq(400)
|
424
|
+
resp = JSON.parse(last_response.body)
|
425
|
+
expect(resp['result']).to eq('error')
|
426
|
+
expect(resp['message']).to match(/^Invalid version/)
|
427
|
+
end
|
428
|
+
|
429
|
+
it "should not check version for clients" do
|
430
|
+
ENV['GAPTOOL_CHECK_CLIENT_VERSION'] = nil
|
431
|
+
header 'X_GAPTOOL_VERSION', nil
|
432
|
+
get "/version"
|
433
|
+
expect(last_response.status).to eq(200)
|
434
|
+
end
|
413
435
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
ENV['RACK_ENV'] = 'test'
|
2
2
|
if ENV['COVERAGE']
|
3
3
|
require 'simplecov'
|
4
|
+
require 'simplecov-rcov'
|
5
|
+
|
6
|
+
class SimpleCov::Formatter::MergedFormatter
|
7
|
+
def format(result)
|
8
|
+
SimpleCov::Formatter::HTMLFormatter.new.format(result)
|
9
|
+
SimpleCov::Formatter::RcovFormatter.new.format(result)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
SimpleCov.formatter = SimpleCov::Formatter::MergedFormatter
|
4
13
|
SimpleCov.start do
|
5
14
|
add_filter '/test/'
|
6
15
|
add_group 'helpers', 'lib/helpers'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gaptool-server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Bailey
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-
|
13
|
+
date: 2015-06-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: sinatra
|
@@ -45,6 +45,9 @@ dependencies:
|
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
47
|
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '2.11'
|
50
|
+
- - ">="
|
48
51
|
- !ruby/object:Gem::Version
|
49
52
|
version: 2.11.1
|
50
53
|
type: :runtime
|
@@ -52,6 +55,9 @@ dependencies:
|
|
52
55
|
version_requirements: !ruby/object:Gem::Requirement
|
53
56
|
requirements:
|
54
57
|
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '2.11'
|
60
|
+
- - ">="
|
55
61
|
- !ruby/object:Gem::Version
|
56
62
|
version: 2.11.1
|
57
63
|
- !ruby/object:Gem::Dependency
|
@@ -116,14 +122,14 @@ dependencies:
|
|
116
122
|
requirements:
|
117
123
|
- - "~>"
|
118
124
|
- !ruby/object:Gem::Version
|
119
|
-
version: '4.
|
125
|
+
version: '4.2'
|
120
126
|
type: :runtime
|
121
127
|
prerelease: false
|
122
128
|
version_requirements: !ruby/object:Gem::Requirement
|
123
129
|
requirements:
|
124
130
|
- - "~>"
|
125
131
|
- !ruby/object:Gem::Version
|
126
|
-
version: '4.
|
132
|
+
version: '4.2'
|
127
133
|
- !ruby/object:Gem::Dependency
|
128
134
|
name: racksh
|
129
135
|
requirement: !ruby/object:Gem::Requirement
|
@@ -194,6 +200,20 @@ dependencies:
|
|
194
200
|
- - "~>"
|
195
201
|
- !ruby/object:Gem::Version
|
196
202
|
version: '10'
|
203
|
+
- !ruby/object:Gem::Dependency
|
204
|
+
name: versionomy
|
205
|
+
requirement: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - "~>"
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '0.4'
|
210
|
+
type: :runtime
|
211
|
+
prerelease: false
|
212
|
+
version_requirements: !ruby/object:Gem::Requirement
|
213
|
+
requirements:
|
214
|
+
- - "~>"
|
215
|
+
- !ruby/object:Gem::Version
|
216
|
+
version: '0.4'
|
197
217
|
- !ruby/object:Gem::Dependency
|
198
218
|
name: rspec
|
199
219
|
requirement: !ruby/object:Gem::Requirement
|
@@ -242,20 +262,33 @@ dependencies:
|
|
242
262
|
requirements:
|
243
263
|
- - "~>"
|
244
264
|
- !ruby/object:Gem::Version
|
245
|
-
version: '0
|
265
|
+
version: '0'
|
266
|
+
type: :development
|
267
|
+
prerelease: false
|
268
|
+
version_requirements: !ruby/object:Gem::Requirement
|
269
|
+
requirements:
|
270
|
+
- - "~>"
|
271
|
+
- !ruby/object:Gem::Version
|
272
|
+
version: '0'
|
273
|
+
- !ruby/object:Gem::Dependency
|
274
|
+
name: simplecov-rcov
|
275
|
+
requirement: !ruby/object:Gem::Requirement
|
276
|
+
requirements:
|
277
|
+
- - "~>"
|
278
|
+
- !ruby/object:Gem::Version
|
279
|
+
version: '0'
|
246
280
|
type: :development
|
247
281
|
prerelease: false
|
248
282
|
version_requirements: !ruby/object:Gem::Requirement
|
249
283
|
requirements:
|
250
284
|
- - "~>"
|
251
285
|
- !ruby/object:Gem::Version
|
252
|
-
version: '0
|
286
|
+
version: '0'
|
253
287
|
description: gaptool-server for managing cloud resources
|
254
288
|
email: ops@gild.com
|
255
289
|
executables:
|
256
290
|
- gaptool-server
|
257
291
|
- gaptool-shell
|
258
|
-
- gaptool_server_migrate_0.6-0.7
|
259
292
|
extensions: []
|
260
293
|
extra_rdoc_files:
|
261
294
|
- LICENSE.txt
|
@@ -269,17 +302,10 @@ files:
|
|
269
302
|
- VERSION
|
270
303
|
- bin/gaptool-server
|
271
304
|
- bin/gaptool-shell
|
272
|
-
- bin/gaptool_server_migrate_0.6-0.7
|
273
305
|
- config.ru
|
274
306
|
- lib/app.rb
|
275
307
|
- lib/exceptions.rb
|
276
|
-
- lib/helpers/data.rb
|
277
|
-
- lib/helpers/ec2.rb
|
278
|
-
- lib/helpers/init.rb
|
279
|
-
- lib/helpers/redis.rb
|
280
|
-
- lib/helpers/rehash.rb
|
281
308
|
- lib/routes.rb
|
282
|
-
- lib/views/init.erb
|
283
309
|
- tasks/app.rb
|
284
310
|
- tasks/config.rb
|
285
311
|
- tasks/docker.rb
|
@@ -1,35 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# Convert all apps for new data format
|
4
|
-
|
5
|
-
libpath = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
|
6
|
-
$:.unshift(libpath)
|
7
|
-
require "#{libpath}/helpers/redis"
|
8
|
-
require "#{libpath}/helpers/data"
|
9
|
-
DH = Gaptool::Data
|
10
|
-
|
11
|
-
# - $redis.sadd("role:#{role}:apps", name)
|
12
|
-
# - $redis.set("app:#{name}", role)
|
13
|
-
# + $redis.sadd("apps:#{environment}", name)
|
14
|
-
# + $redis.sadd("role:#{role}:#{environment}:apps", name)
|
15
|
-
# + $redis.hset("app:#{name}", environment, role)
|
16
|
-
# - role = $redis.get(key)
|
17
|
-
# + roles = $redis.hgetall(key)
|
18
|
-
# - role = $redis.get("app:#{app}")
|
19
|
-
# + return $redis.hgetall("app:#{app}")
|
20
|
-
# - $redis.smembers("role:#{role}:apps")
|
21
|
-
# + $redis.smembers("apps:#{environment}")
|
22
|
-
# + $redis.smembers("role:#{role}:#{environment}:apps")
|
23
|
-
|
24
|
-
puts 'Removing role:*:apps'
|
25
|
-
$redis.keys("role:*:apps").each {|k| $redis.del(k)}
|
26
|
-
puts "Migrating apps"
|
27
|
-
$redis.keys("app:*").each do |key|
|
28
|
-
app = key.sub(/app:/, "")
|
29
|
-
puts " * app: #{app} (#{key})"
|
30
|
-
role = $redis.get(key)
|
31
|
-
$redis.del("app:#{app}")
|
32
|
-
%w(staging production).each do |env|
|
33
|
-
DH.add_app(app, role, env)
|
34
|
-
end
|
35
|
-
end
|
data/lib/helpers/data.rb
DELETED
@@ -1,306 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'securerandom'
|
3
|
-
|
4
|
-
module Gaptool
|
5
|
-
module Data
|
6
|
-
|
7
|
-
def self.init_recipe
|
8
|
-
'recipe[init]'
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.default_runlist
|
12
|
-
[init_recipe]
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.addserver(instance, data, secret)
|
16
|
-
role = data['role']
|
17
|
-
environment = data['environment']
|
18
|
-
if role.nil? || environment.nil?
|
19
|
-
raise ArgumentError, "Missing role or environment"
|
20
|
-
end
|
21
|
-
|
22
|
-
if instance.nil? || instance.empty?
|
23
|
-
raise ArgumentError, "Missing instance"
|
24
|
-
end
|
25
|
-
|
26
|
-
$redis.sadd("instances", instance)
|
27
|
-
$redis.sadd("role:#{role}:instances", instance)
|
28
|
-
$redis.sadd("environment:#{environment}:instances", instance)
|
29
|
-
unless secret.nil?
|
30
|
-
data['registered'] = false
|
31
|
-
$redis.sadd('instances:unregistered', instance)
|
32
|
-
$redis.set("instances:secrets:#{data['role']}:#{data['environment']}:#{secret}", instance)
|
33
|
-
data['secret'] = secret
|
34
|
-
end
|
35
|
-
save_server_data instance, data
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.overwrite_hash(key, data)
|
39
|
-
if !key.nil? && !data.nil? && !data.empty?
|
40
|
-
$redis.multi do
|
41
|
-
$redis.del(key)
|
42
|
-
$redis.hmset(key, *data.select{ |k,v| !v.nil? && ((v.is_a?(String) && !v.empty?) || (v.is_a?(Integer)) || !!v == v)}.flatten)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.set_server_data_attr(instance, attr, value)
|
48
|
-
return if value.nil? || (value.is_a?(String) && value.empty?) || !!value == value
|
49
|
-
$redis.hset("instance:#{instance}", attr, value)
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.set_server_data_attributes(instance, attrs)
|
53
|
-
return if attrs.values.any? {|v| v.nil? || (v.is_a?(String) && v.empty?) || !!v == v}
|
54
|
-
$redis.hmset("instance:#{instance}", *attrs.flatten)
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.save_server_data(instance, data)
|
58
|
-
|
59
|
-
unless data['chef_runlist'].nil?
|
60
|
-
data['chef_runlist'] = [*data['chef_runlist']]
|
61
|
-
unless data['chef_runlist'].include? init_recipe
|
62
|
-
data['chef_runlist'].unshift(init_recipe)
|
63
|
-
end
|
64
|
-
|
65
|
-
if data['chef_runlist'] == default_runlist
|
66
|
-
data.delete('chef_runlist')
|
67
|
-
else
|
68
|
-
data['chef_runlist'] = data['chef_runlist'].to_json
|
69
|
-
end
|
70
|
-
end
|
71
|
-
overwrite_hash("instance:#{instance}", data)
|
72
|
-
end
|
73
|
-
|
74
|
-
def self.register_server(role, environment, secret)
|
75
|
-
key = "instances:secrets:#{role}:#{environment}:#{secret}"
|
76
|
-
instance = nil
|
77
|
-
$redis.watch(key) do
|
78
|
-
instance = $redis.get(key)
|
79
|
-
if !instance.nil? && !instance.empty?
|
80
|
-
$redis.multi do |m|
|
81
|
-
m.hdel("instance:#{instance}", "secret")
|
82
|
-
m.hdel("instance:#{instance}", "registered")
|
83
|
-
m.srem('instances:unregistered', instance)
|
84
|
-
m.del(key)
|
85
|
-
end
|
86
|
-
else
|
87
|
-
$redis.unwatch
|
88
|
-
instance = nil
|
89
|
-
end
|
90
|
-
end
|
91
|
-
instance
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.rmserver(instance)
|
95
|
-
data = get_server_data instance
|
96
|
-
return if data.nil?
|
97
|
-
$redis.multi do |m|
|
98
|
-
m.srem("instances", instance)
|
99
|
-
m.srem("role:#{data['role']}:instances", instance)
|
100
|
-
m.srem("environment:#{data['environment']}:instances", instance)
|
101
|
-
m.del("instance:#{instance}")
|
102
|
-
end
|
103
|
-
instance
|
104
|
-
end
|
105
|
-
|
106
|
-
def self.get_config(key)
|
107
|
-
$redis.hget('config', key)
|
108
|
-
end
|
109
|
-
|
110
|
-
def self.ensure_config(key, default)
|
111
|
-
cur = get_config(key)
|
112
|
-
cur = set_config(key, default) if cur.nil? || cur.empty?
|
113
|
-
cur
|
114
|
-
end
|
115
|
-
|
116
|
-
def self.set_config(key, value)
|
117
|
-
$redis.hset('config', key, value)
|
118
|
-
value
|
119
|
-
end
|
120
|
-
|
121
|
-
def self.del_config(key)
|
122
|
-
$redis.hdel('config', key)
|
123
|
-
end
|
124
|
-
|
125
|
-
def self.get_all_configs
|
126
|
-
$redis.hgetall('config')
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.get_server_data(instance, opts={})
|
130
|
-
rs = $redis.hgetall("instance:#{instance}")
|
131
|
-
return nil if rs.nil? || rs.empty?
|
132
|
-
rs['instance'] = instance
|
133
|
-
if !rs['chef_runlist'].nil? && !rs['chef_runlist'].empty?
|
134
|
-
rs['chef_runlist'] = JSON.parse rs['chef_runlist']
|
135
|
-
else
|
136
|
-
rs['chef_runlist'] = get_runlist_for_role rs['role']
|
137
|
-
end
|
138
|
-
|
139
|
-
%w(chef_repo chef_branch).each do |v|
|
140
|
-
if rs[v].nil? || rs[v].empty?
|
141
|
-
rs[v] = get_config(v)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
if opts[:initkey]
|
146
|
-
rs['initkey'] = get_config('initkey')
|
147
|
-
end
|
148
|
-
|
149
|
-
if !rs['terminable'].nil? && rs['terminable'] == "false"
|
150
|
-
rs['terminable'] = false
|
151
|
-
else
|
152
|
-
rs.delete('terminable')
|
153
|
-
end
|
154
|
-
|
155
|
-
if !rs['hidden'].nil? && rs['hidden'] == "true"
|
156
|
-
rs['hidden'] = true
|
157
|
-
end
|
158
|
-
|
159
|
-
if opts[:force_runlist] && rs['chef_runlist'].nil?
|
160
|
-
rs['chef_runlist'] = default_runlist
|
161
|
-
end
|
162
|
-
|
163
|
-
rs.delete_if {|k,v| v.nil? || (!!v != v && v.empty?)}
|
164
|
-
rs['launch_time'] = rs['launch_time'].to_i if rs['launch_time']
|
165
|
-
rs['apps'] = apps_in_role(rs['role'], rs['environment'])
|
166
|
-
rs
|
167
|
-
end
|
168
|
-
|
169
|
-
def self.save_role_data(role, data)
|
170
|
-
return if role.nil? || data.nil?
|
171
|
-
if data['amis']
|
172
|
-
amis = data.delete("amis") || {}
|
173
|
-
overwrite_hash("role:#{role}:amis", amis)
|
174
|
-
end
|
175
|
-
if data['sg']
|
176
|
-
sgs = data.delete("sg") || {}
|
177
|
-
overwrite_hash("role:#{role}:sg", sgs)
|
178
|
-
end
|
179
|
-
if data['apps']
|
180
|
-
apps = data.delete("apps")
|
181
|
-
apps.each {|env, app| add_app(app, role, env)}
|
182
|
-
end
|
183
|
-
overwrite_hash("role:#{role}", data)
|
184
|
-
$redis.sadd("roles", role)
|
185
|
-
end
|
186
|
-
|
187
|
-
def self.get_role_data(role, environment=nil)
|
188
|
-
res = $redis.hgetall("role:#{role}")
|
189
|
-
res['apps'] = environment ? apps_in_role(role, environment) : []
|
190
|
-
res['amis'] = $redis.hgetall("role:#{role}:amis")
|
191
|
-
res['sg'] = $redis.hgetall("role:#{role}:sg")
|
192
|
-
res
|
193
|
-
end
|
194
|
-
|
195
|
-
def self.get_ami_for_role(role, region=nil)
|
196
|
-
$redis.hget("role:#{role}:amis", region) || $redis.hget("amis", region)
|
197
|
-
end
|
198
|
-
|
199
|
-
def self.get_sg_for_role(role, environment)
|
200
|
-
$redis.hget("role:#{role}:sg", environment) || "#{role}-#{environment}"
|
201
|
-
end
|
202
|
-
|
203
|
-
def self.get_runlist_for_role(role)
|
204
|
-
rl = $redis.hget("role:#{role}", "chef_runlist")
|
205
|
-
return nil if rl.nil?
|
206
|
-
rl = JSON.parse rl
|
207
|
-
return nil if rl == default_runlist
|
208
|
-
rl
|
209
|
-
end
|
210
|
-
|
211
|
-
def self.set_amis(amis)
|
212
|
-
overwrite_hash("amis", amis)
|
213
|
-
end
|
214
|
-
|
215
|
-
def self.zones
|
216
|
-
$redis.hgetall('amis').keys
|
217
|
-
end
|
218
|
-
|
219
|
-
def self.servers_in_role(role)
|
220
|
-
$redis.smembers("role:#{role}:instances")
|
221
|
-
end
|
222
|
-
|
223
|
-
def self.servers_in_env(env)
|
224
|
-
$redis.smembers("environment:#{env}:instances")
|
225
|
-
end
|
226
|
-
|
227
|
-
def self.servers_in_role_env(role, env)
|
228
|
-
$redis.sinter("role:#{role}:instances", "environment:#{env}:instances")
|
229
|
-
end
|
230
|
-
|
231
|
-
def self.servers
|
232
|
-
$redis.smembers("instances")
|
233
|
-
end
|
234
|
-
|
235
|
-
def self.roles
|
236
|
-
Hash[$redis.smembers("roles").map {|r| [r, get_role_data(r)] }]
|
237
|
-
end
|
238
|
-
|
239
|
-
def self.add_app(name, role, environment)
|
240
|
-
return if name.nil? || role.nil?
|
241
|
-
$redis.multi do
|
242
|
-
$redis.sadd("apps", name)
|
243
|
-
$redis.sadd("apps:#{environment}", name)
|
244
|
-
$redis.sadd("role:#{role}:#{environment}:apps", name)
|
245
|
-
$redis.hset("app:#{name}", environment, role)
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def self.remove_app(name)
|
250
|
-
return if name.nil?
|
251
|
-
key = "app:#{name}"
|
252
|
-
$redis.watch(key) do
|
253
|
-
roles = $redis.hgetall(key)
|
254
|
-
if !roles.nil?
|
255
|
-
$redis.multi do |m|
|
256
|
-
m.del(key)
|
257
|
-
m.srem("apps", name)
|
258
|
-
roles.each do |env, role|
|
259
|
-
m.srem("role:#{role}:#{env}:apps", name)
|
260
|
-
end
|
261
|
-
end
|
262
|
-
else
|
263
|
-
$redis.unwatch
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
def self.get_app_data(app)
|
269
|
-
return $redis.hgetall("app:#{app}")
|
270
|
-
end
|
271
|
-
|
272
|
-
def self.apps
|
273
|
-
$redis.smembers("apps")
|
274
|
-
end
|
275
|
-
|
276
|
-
def self.apps_in_role(role, environment)
|
277
|
-
$redis.smembers("role:#{role}:#{environment}:apps")
|
278
|
-
end
|
279
|
-
|
280
|
-
def self.stringify_apps(rs)
|
281
|
-
if !rs.nil? && !rs['apps'].nil?
|
282
|
-
rs['apps'] = rs['apps'].to_json
|
283
|
-
end
|
284
|
-
rs
|
285
|
-
end
|
286
|
-
|
287
|
-
def self.useradd(user, key=nil)
|
288
|
-
key = SecureRandom.hex(64) unless key
|
289
|
-
$redis.hset('users', user, key)
|
290
|
-
{username: user, key: key}
|
291
|
-
end
|
292
|
-
|
293
|
-
def self.userdel(user)
|
294
|
-
$redis.hdel('users', user)
|
295
|
-
end
|
296
|
-
|
297
|
-
def self.users
|
298
|
-
$redis.hgetall('users')
|
299
|
-
end
|
300
|
-
|
301
|
-
def self.user(user)
|
302
|
-
userdesc = {username: user, key: $redis.hget('users', user)}
|
303
|
-
return userdesc[:key].nil? ? nil : userdesc
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
data/lib/helpers/ec2.rb
DELETED
@@ -1,179 +0,0 @@
|
|
1
|
-
require 'aws-sdk'
|
2
|
-
require 'securerandom'
|
3
|
-
require 'logger'
|
4
|
-
require 'airbrake'
|
5
|
-
|
6
|
-
# encoding: utf-8
|
7
|
-
module Gaptool
|
8
|
-
module EC2
|
9
|
-
@@logger = Logger.new(STDERR)
|
10
|
-
|
11
|
-
def self.configure_ec2 zone
|
12
|
-
return if ENV['DRYRUN']
|
13
|
-
id = ENV['AWS_ACCESS_KEY_ID']
|
14
|
-
secret = ENV['AWS_SECRET_ACCESS_KEY']
|
15
|
-
AWS.config(access_key_id: id, secret_access_key: secret,
|
16
|
-
ec2_endpoint: "ec2.#{zone}.amazonaws.com")
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.putkey(host)
|
20
|
-
return "FAKEKEY", "FAKEPUB" if ENV['DRYRUN']
|
21
|
-
key = OpenSSL::PKey::RSA.new 2048
|
22
|
-
pubkey = "#{key.ssh_type} #{[key.to_blob].pack('m0')} GAPTOOL_GENERATED_KEY"
|
23
|
-
ENV['SSH_AUTH_SOCK'] = ''
|
24
|
-
Net::SSH.start(host, 'admin',
|
25
|
-
:key_data => [$redis.hget('config', 'gaptoolkey')],
|
26
|
-
:config => false, :keys_only => true,
|
27
|
-
:paranoid => false) do |ssh|
|
28
|
-
ssh.exec! "grep -v GAPTOOL_GENERATED_KEY ~/.ssh/authorized_keys > /tmp/pubkeys"
|
29
|
-
ssh.exec! "echo #{pubkey} >> /tmp/pubkeys"
|
30
|
-
ssh.exec! "mv /tmp/pubkeys ~/.ssh/authorized_keys"
|
31
|
-
end
|
32
|
-
return key.to_pem, pubkey
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.get_or_create_securitygroup(role, environment, zone, groupname=nil)
|
36
|
-
return "sg-test#{SecureRandom.hex(2)}" if ENV['DRYRUN']
|
37
|
-
configure_ec2 zone.chop
|
38
|
-
ec2 = AWS::EC2.new
|
39
|
-
groupname = groupname || "#{role}-#{environment}"
|
40
|
-
ec2.security_groups.each do |group|
|
41
|
-
if group.name == groupname
|
42
|
-
return group.id
|
43
|
-
end
|
44
|
-
end
|
45
|
-
internet = ['0.0.0.0/0']
|
46
|
-
sg = ec2.security_groups.create(groupname)
|
47
|
-
sg.authorize_ingress :tcp, 22, *internet
|
48
|
-
return sg.id
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.create_ec2_instance(ec2opts, data, retries=3, sleeptime=0.5)
|
52
|
-
if ENV['DRYRUN']
|
53
|
-
id = "i-test#{SecureRandom.hex(2)}"
|
54
|
-
return {id: id,
|
55
|
-
hostname: "test-#{id}.#{data[:zone].chop}.compute.amazonaws.com",
|
56
|
-
instance: nil,
|
57
|
-
launch_time: Time.now.to_i}
|
58
|
-
end
|
59
|
-
configure_ec2 data[:zone].chop
|
60
|
-
ec2 = AWS::EC2.new
|
61
|
-
|
62
|
-
i = 0
|
63
|
-
begin
|
64
|
-
instance = ec2.instances.create(ec2opts)
|
65
|
-
@@logger.debug("Spawned instance #{instance.id}")
|
66
|
-
rescue => e
|
67
|
-
i += 1
|
68
|
-
raise if i > retries
|
69
|
-
@@logger.error("Error while creating instance: #{e}: sleeping #{sleeptime}s and retrying (#{i}/#{retries})")
|
70
|
-
sleep sleeptime
|
71
|
-
retry
|
72
|
-
end
|
73
|
-
|
74
|
-
i = 0
|
75
|
-
begin
|
76
|
-
hostname = instance.public_dns_name
|
77
|
-
rescue => e
|
78
|
-
i += 1
|
79
|
-
if i > retries
|
80
|
-
@@logger.error("Could not get hostname for instance #{instance} after #{retries} retries, setting to nil")
|
81
|
-
hostname = nil
|
82
|
-
Airbrake.notify_or_ignore(
|
83
|
-
e,
|
84
|
-
error_class: "EC2 public dns fail",
|
85
|
-
parameters: {instance: instance.id, role: data['role'], environment: data['environment'], hostname: nil}
|
86
|
-
)
|
87
|
-
else
|
88
|
-
@@logger.error("Error getting hostname for instance: #{e}: sleeping #{sleeptime}s and retrying (#{i}/#{retries})")
|
89
|
-
sleep sleeptime
|
90
|
-
retry
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
i = 0
|
95
|
-
begin
|
96
|
-
launch_time = instance.launch_time.to_i
|
97
|
-
raise unless launch_time.is_a? Integer
|
98
|
-
|
99
|
-
rescue => e
|
100
|
-
i += 1
|
101
|
-
if i > retries
|
102
|
-
@@logger.error("Cloud not get launch time for instance #{instance} after #{retries} retries. Setting to now()")
|
103
|
-
launch_time = Time.now.to_i
|
104
|
-
Airbrake.notify_or_ignore(
|
105
|
-
e,
|
106
|
-
error_class: "EC2 get launch_time fail",
|
107
|
-
parameters: {instance: instance.id, role: data['role'], environment: data['environment'], hostname: nil}
|
108
|
-
)
|
109
|
-
else
|
110
|
-
@@logger.error("Error getting launch_time for instance: #{e}: sleeping #{sleeptime}s and retrying (#{i}/#{retries})")
|
111
|
-
sleep sleeptime
|
112
|
-
retry
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
@@logger.info {"Instance #{instance.id} launch_time: #{launch_time} #{instance.launch_time}"}
|
117
|
-
|
118
|
-
{
|
119
|
-
id: instance.id,
|
120
|
-
instance: instance,
|
121
|
-
hostname: hostname,
|
122
|
-
launch_time: launch_time
|
123
|
-
}
|
124
|
-
end
|
125
|
-
|
126
|
-
def self.tag_ec2_instance(instance, key, value, retries=5, sleeptime=0.5)
|
127
|
-
return true if ENV['DRYRUN']
|
128
|
-
i = 0
|
129
|
-
begin
|
130
|
-
instance.add_tag(key, value: value)
|
131
|
-
@@logger.debug("Added tag #{key}=#{value} to #{instance.id}")
|
132
|
-
true
|
133
|
-
rescue => e
|
134
|
-
i += 1
|
135
|
-
raise if i > retries
|
136
|
-
@@logger.error("Error adding tag #{key} to #{instance.id}: #{e}: sleeping #{sleeptime}s and retrying (#{i}/#{retries})")
|
137
|
-
sleep sleeptime
|
138
|
-
retry
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def self.terminate_ec2_instance(zone, id)
|
143
|
-
return if ENV['DRYRUN']
|
144
|
-
configure_ec2 zone
|
145
|
-
ec2 = AWS::EC2.new
|
146
|
-
instance = ec2.instances[id]
|
147
|
-
instance.terminate
|
148
|
-
end
|
149
|
-
|
150
|
-
def self.get_ec2_instance_data(zone, id)
|
151
|
-
if ENV['DRYRUN']
|
152
|
-
return {
|
153
|
-
hostname: 'fake.hostname.gild.com'
|
154
|
-
}
|
155
|
-
end
|
156
|
-
configure_ec2 zone
|
157
|
-
ec2 = AWS::EC2.new
|
158
|
-
instance = ec2.instances[id]
|
159
|
-
return {
|
160
|
-
hostname: instance.dns_name
|
161
|
-
}
|
162
|
-
end
|
163
|
-
|
164
|
-
def self.retag()
|
165
|
-
logger = Logger.new(STDOUT)
|
166
|
-
Gaptool::Data::servers.each do |id|
|
167
|
-
data = Gaptool::Data.get_server_data(id)
|
168
|
-
next if data.nil? || data['zone'].nil? || data['zone'].empty?
|
169
|
-
Gaptool::EC2::configure_ec2 data['zone'].chop
|
170
|
-
ec2 = AWS::EC2.new(region: data['zone'].chop)
|
171
|
-
instance = ec2.instances[id]
|
172
|
-
next if instance.tags.role && instance.tags.environment
|
173
|
-
logger.info("Retagging instance #{id} in zone #{data['zone'].chop}")
|
174
|
-
instance.tags.role = data['role']
|
175
|
-
instance.tags.environment = data['environment']
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
data/lib/helpers/init.rb
DELETED
data/lib/helpers/redis.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'redis'
|
2
|
-
require 'redis-namespace'
|
3
|
-
|
4
|
-
# docker links support
|
5
|
-
unless ENV['REDIS_PORT_6379_TCP_ADDR'].nil?
|
6
|
-
ENV['REDIS_HOST'] = ENV['REDIS_PORT_6379_TCP_ADDR']
|
7
|
-
ENV['REDIS_PORT'] = ENV['REDIS_PORT_6379_TCP_PORT']
|
8
|
-
ENV.delete('REDIS_PASS')
|
9
|
-
end
|
10
|
-
|
11
|
-
ENV['REDIS_HOST'] = 'localhost' unless ENV['REDIS_HOST']
|
12
|
-
ENV['REDIS_PORT'] = '6379' unless ENV['REDIS_PORT']
|
13
|
-
ENV['REDIS_PASS'] = nil unless ENV['REDIS_PASS']
|
14
|
-
ENV['REDIS_DB'] = '0' unless ENV['REDIS_DB']
|
15
|
-
|
16
|
-
prefix = ENV.fetch('REDIS_PREFIX', 'gt')
|
17
|
-
|
18
|
-
conn = Redis.new(:host => ENV['REDIS_HOST'],
|
19
|
-
:port => ENV['REDIS_PORT'].to_i,
|
20
|
-
:password => ENV['REDIS_PASS'],
|
21
|
-
:db => ENV['REDIS_DB'].to_i)
|
22
|
-
|
23
|
-
$redis = Redis::Namespace.new(prefix, redis: conn)
|
data/lib/helpers/rehash.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
require_relative "ec2"
|
2
|
-
require_relative "data"
|
3
|
-
require "logger"
|
4
|
-
|
5
|
-
module Gaptool
|
6
|
-
module EC2
|
7
|
-
def self.rehash()
|
8
|
-
Gaptool::Data::servers.each do |inst|
|
9
|
-
Gaptool::Data::rmserver inst
|
10
|
-
end
|
11
|
-
roles = Gaptool::Data::roles
|
12
|
-
Gaptool::Data::zones.each do |zone|
|
13
|
-
Gaptool::EC2::configure_ec2 zone
|
14
|
-
@ec2 = AWS::EC2.new
|
15
|
-
ilist = []
|
16
|
-
@ec2.instances.each do |instance|
|
17
|
-
if instance.tags['gaptool'] == 'yes' && instance.status == :running
|
18
|
-
ilist << instance
|
19
|
-
end
|
20
|
-
end
|
21
|
-
ilist.each do |instance|
|
22
|
-
puts " - #{instance.tags['Name']}"
|
23
|
-
role, environment, iid = instance.tags['Name'].split('-', 3)
|
24
|
-
data = {
|
25
|
-
"zone"=> instance.availability_zone,
|
26
|
-
"role"=> role,
|
27
|
-
"environment"=> environment,
|
28
|
-
"hostname" => instance.public_dns_name,
|
29
|
-
"launch_time" => instance.launch_time.to_s,
|
30
|
-
"apps" => roles[role].to_s,
|
31
|
-
"instance"=> instance.instance_id,
|
32
|
-
"security_group" => instance.security_groups[0].name
|
33
|
-
}
|
34
|
-
Gaptool::Data::addserver(iid, data, nil)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
return {"action" => "complete"}
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.rehash_property(property)
|
41
|
-
Gaptool::Data::servers.each do |id|
|
42
|
-
rehash_property_for_instance(property, id)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.rehash_properties_for_instance(instance_id)
|
47
|
-
res = {}
|
48
|
-
%w[hostname itype security_group].each do |property|
|
49
|
-
res[property] = self.rehash_property_for_instance(property, instance_id, false)
|
50
|
-
end
|
51
|
-
Gaptool::Data::set_server_data_attributes(instance_id, res)
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.rehash_property_for_instance(property, instance_id, save=true)
|
55
|
-
logger = Logger.new(STDOUT)
|
56
|
-
data = Gaptool::Data.get_server_data(instance_id)
|
57
|
-
return false if data.nil? || data['zone'].nil? || data['zone'].empty?
|
58
|
-
Gaptool::EC2::configure_ec2 data['zone'].chop
|
59
|
-
ec2 = AWS::EC2.new(region: data['zone'].chop)
|
60
|
-
logger.info("Updating #{property} for #{instance_id} in zone #{data['zone'].chop}")
|
61
|
-
instance = ec2.instances[instance_id]
|
62
|
-
return false if instance.nil?
|
63
|
-
case property
|
64
|
-
when "hostname"
|
65
|
-
value = instance.public_dns_name
|
66
|
-
when "itype"
|
67
|
-
value = instance.instance_type
|
68
|
-
when "security_group"
|
69
|
-
value = instance.security_groups[0].name
|
70
|
-
when "launch_time"
|
71
|
-
value = instance.launch_time.to_i
|
72
|
-
else
|
73
|
-
return false
|
74
|
-
end
|
75
|
-
logger.info("Setting #{property} to #{value} for #{instance_id}")
|
76
|
-
if save
|
77
|
-
Gaptool::Data.set_server_data_attr(instance_id, property, value)
|
78
|
-
else
|
79
|
-
value
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
data/lib/views/init.erb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
#!/bin/bash
|
2
|
-
set -e
|
3
|
-
cd /root
|
4
|
-
apt-get update
|
5
|
-
apt-get install -ymq zsh git libssl-dev ruby1.9.1-full build-essential
|
6
|
-
curl -LO https://www.getchef.com/chef/install.sh
|
7
|
-
bash install.sh -v <%= chef_version %>
|
8
|
-
|
9
|
-
cat << 'EOFKEY' > /root/.ssh/id_rsa
|
10
|
-
<%= initkey %>
|
11
|
-
EOFKEY
|
12
|
-
chmod 600 /root/.ssh/id_rsa
|
13
|
-
echo 'StrictHostKeyChecking no' > /root/.ssh/config
|
14
|
-
|
15
|
-
git clone -b <%= chef_branch %> <%= chef_repo %> /root/ops
|
16
|
-
echo '<%= json %>' > /root/init.json
|
17
|
-
chef-solo -c /root/ops/cookbooks/init.rb -j /root/init.json -E <%= chef_environment %> && \
|
18
|
-
(rm /root/.ssh/id_rsa; userdel -r ubuntu; rm -rf /root/.ssh; rm -rf /root/ops)
|