gaptool-server 0.7.0 → 0.7.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 +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)
|