gaptool-server 0.6.4 → 0.6.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ddb439ba551286b15caaccf7ba3990faec9dcbb
4
- data.tar.gz: 3e4e425e4cb7d018903ed538a367af4f736dd83d
3
+ metadata.gz: 6323ce0f24d59f15f894675c6cf76724f5b8ace1
4
+ data.tar.gz: 4af7e863c6b3527d54ff458fa29cdaebf09583eb
5
5
  SHA512:
6
- metadata.gz: 5fd00e76e360031a00389f6ab31735007e70e31366b230430055825417cbaaf99534c64b5ef3498e39484883cbcf082f41e76cf21777ab957959812a75b50005
7
- data.tar.gz: 5894bb1f4762abbb4fed353324dc8ae5f4c00179c098d9dcd789f370362da914be9df30b06e33909dafc4c330ca95942e0746eb68b4b77179e651cf46cbf099d
6
+ metadata.gz: 8bb6202e2fc26965a53acad59625830ea198cd7c930414d005b4977291a49c1a79823e5a29ad00c8c97ed68f0a979ab047f93d5933203455f199138d29f7a1b0
7
+ data.tar.gz: 97cdc9abf27d57332ef261dac8b7919bd732102362d6b5a79bf70b26df9870ab4e1c8911edfe8c2c59a3cf050036f1a9f77477a355988f6f82a2cc82f25fcc31
data/Rakefile CHANGED
@@ -4,10 +4,12 @@ Dir.chdir(File.dirname(__FILE__))
4
4
  require 'shellwords'
5
5
  require 'rspec/core/rake_task'
6
6
  require_relative 'lib/helpers/redis'
7
+ require_relative 'lib/helpers/ec2'
7
8
  require_relative 'lib/helpers/init'
8
9
  require_relative 'lib/helpers/rehash'
9
10
 
10
11
  DH = Gaptool::Data
12
+ EC2 = Gaptool::EC2
11
13
  $stdout.sync = true
12
14
 
13
15
  def sys(cmd)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.4
1
+ 0.6.6
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # convert the old data model for the gaptool server
4
+ # to the new struct
5
+
6
+ libpath = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
7
+ $:.unshift(libpath)
8
+ require "#{libpath}/helpers/redis"
9
+ require "#{libpath}/helpers/data"
10
+ DH = Gaptool::Data
11
+
12
+ $redis.keys("role:*").each do |k|
13
+ next if k.end_with?('instances') || k.end_with?('apps') || k.end_with?('amis')
14
+ puts "Migrating #{k}"
15
+ sgroup = $redis.hget(k, "security_group")
16
+ $redis.hset("#{k}:sg", "production", sgroup)
17
+ $redis.del(k)
18
+ end
data/lib/app.rb CHANGED
@@ -9,14 +9,16 @@ require 'openssl'
9
9
  require 'net/ssh'
10
10
  require 'peach'
11
11
  require 'airbrake'
12
+ require 'logger'
12
13
  require_relative 'exceptions'
13
14
 
14
15
  class GaptoolServer < Sinatra::Application
15
16
  helpers Sinatra::JSON
17
+ use Airbrake::Sinatra
16
18
 
17
19
  def error_response msg=''
18
- message = "#{env['sinatra.error'].message}"
19
- message = "#{msg} #{message}" unless msg.empty?
20
+ message = env['sinatra_error'].nil? ? "" : " #{env['sinatra.error'].message}"
21
+ message = "#{msg}#{message}" unless msg.empty?
20
22
  json result: 'error', message: message
21
23
  end
22
24
 
@@ -30,6 +32,10 @@ class GaptoolServer < Sinatra::Application
30
32
  error_response
31
33
  end
32
34
 
35
+ def unauthenticated
36
+ halt(401, error_response("Unauthenticated"))
37
+ end
38
+
33
39
  error do
34
40
  status 500
35
41
  error_response
@@ -39,8 +45,8 @@ class GaptoolServer < Sinatra::Application
39
45
  unless ENV['AIRBRAKE_API_KEY'].nil?
40
46
  Airbrake.configure do |cfg|
41
47
  cfg.api_key = ENV['AIRBRAKE_API_KEY']
48
+ cfg.logger = Logger.new(STDOUT)
42
49
  end
43
- use Airbrake::Sinatra
44
50
  end
45
51
  disable :sessions
46
52
  enable :dump_errors
@@ -50,8 +56,8 @@ class GaptoolServer < Sinatra::Application
50
56
  before do
51
57
  if request.path_info != '/ping' && ENV['GAPTOOL_DISABLE_AUTH'].nil?
52
58
  user = Gaptool::Data.user(env['HTTP_X_GAPTOOL_USER'])
53
- raise Unauthenticated if user.nil?
54
- raise Unauthenticated unless user[:key] == env['HTTP_X_GAPTOOL_KEY']
59
+ return unauthenticated if user.nil?
60
+ return unauthenticated unless user[:key] == env['HTTP_X_GAPTOOL_KEY']
55
61
  end
56
62
  end
57
63
 
data/lib/exceptions.rb CHANGED
@@ -18,10 +18,6 @@ class BadRequest < ClientError
18
18
  @code = 400
19
19
  end
20
20
 
21
- class Unauthenticated < ClientError
22
- @code = 401
23
- end
24
-
25
21
  class Forbidden < ClientError
26
22
  @code = 403
27
23
  end
data/lib/helpers/data.rb CHANGED
@@ -49,6 +49,11 @@ module Gaptool
49
49
  $redis.hset("instance:#{instance}", attr, value)
50
50
  end
51
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
+
52
57
  def self.save_server_data(instance, data)
53
58
 
54
59
  unless data['chef_runlist'].nil?
@@ -151,8 +156,9 @@ module Gaptool
151
156
  rs['chef_runlist'] = default_runlist
152
157
  end
153
158
 
154
- rs['apps'] = apps_in_role(rs['role'])
155
159
  rs.delete_if {|k,v| v.nil? || (!!v != v && v.empty?)}
160
+ rs['apps'] = apps_in_role(rs['role'])
161
+ rs
156
162
  end
157
163
 
158
164
  def self.save_role_data(role, data)
@@ -161,6 +167,10 @@ module Gaptool
161
167
  amis = data.delete("amis") || {}
162
168
  overwrite_hash("role:#{role}:amis", amis)
163
169
  end
170
+ if data['sg']
171
+ sgs = data.delete("sg") || {}
172
+ overwrite_hash("role:#{role}:sg", sgs)
173
+ end
164
174
  if data['apps']
165
175
  apps = data.delete("apps") || []
166
176
  apps.each {|a| add_app(a, role)}
@@ -173,14 +183,18 @@ module Gaptool
173
183
  res = $redis.hgetall("role:#{role}")
174
184
  res['apps'] = apps_in_role(role)
175
185
  res['amis'] = $redis.hgetall("role:#{role}:amis")
186
+ res['sg'] = $redis.hgetall("role:#{role}:sg")
176
187
  res
177
188
  end
178
189
 
179
190
  def self.get_ami_for_role(role, region=nil)
180
-
181
191
  $redis.hget("role:#{role}:amis", region) || $redis.hget("amis", region)
182
192
  end
183
193
 
194
+ def self.get_sg_for_role(role, environment)
195
+ $redis.hget("role:#{role}:sg", environment) || "#{role}-#{environment}"
196
+ end
197
+
184
198
  def self.get_runlist_for_role(role)
185
199
  rl = $redis.hget("role:#{role}", "chef_runlist")
186
200
  return nil if rl.nil?
@@ -257,7 +271,7 @@ module Gaptool
257
271
  end
258
272
 
259
273
  def self.stringify_apps(rs)
260
- unless rs['apps'].nil?
274
+ if !rs.nil? && !rs['apps'].nil?
261
275
  rs['apps'] = rs['apps'].to_json
262
276
  end
263
277
  rs
data/lib/helpers/ec2.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  require 'aws-sdk'
2
2
  require 'securerandom'
3
+ require 'logger'
4
+ require 'airbrake'
3
5
 
4
6
  # encoding: utf-8
5
7
  module Gaptool
6
8
  module EC2
9
+ @@logger = Logger.new(STDERR)
7
10
 
8
11
  def self.configure_ec2 zone
9
12
  return if ENV['DRYRUN']
@@ -45,28 +48,79 @@ module Gaptool
45
48
  return sg.id
46
49
  end
47
50
 
48
- def self.create_ec2_instance(ec2opts, data)
51
+ def self.create_ec2_instance(ec2opts, data, retries=3, sleeptime=0.5)
49
52
  if ENV['DRYRUN']
50
53
  id = "i-test#{SecureRandom.hex(2)}"
51
54
  return {id: id,
52
55
  hostname: "test-#{id}.#{data[:zone].chop}.compute.amazonaws.com",
56
+ instance: nil,
53
57
  launch_time: Time.now.to_s}
54
58
  end
55
59
  configure_ec2 data[:zone].chop
56
60
  ec2 = AWS::EC2.new
57
61
 
58
- instance = ec2.instances.create(ec2opts)
59
- instance.add_tag('Name', value: "#{data[:role]}-#{data[:env]}-#{instance.id}")
60
- instance.add_tag('gaptool', :value => "yes")
61
- launch_time = instance.launch_time.to_s
62
- launch_time = launch_time.empty? ? Time.now.to_s : launch_time
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
+ begin
75
+ launch_time = instance.launch_time.to_s
76
+ launch_time = launch_time.empty? ? Time.now.to_s : launch_time
77
+ rescue
78
+ launch_time = Time.now.to_s
79
+ end
80
+
81
+ i = 0
82
+ begin
83
+ hostname = instance.public_dns_name
84
+ rescue => e
85
+ i += 1
86
+ if i > retries
87
+ @@logger.error("Could not get hostname for instance #{instance} after #{retries} retries, setting to nil")
88
+ hostname = nil
89
+ Airbrake.notify_or_ignore(
90
+ e,
91
+ error_class: "EC2 public dns fail",
92
+ parameters: {instance: instance[:id], role: data['role'], environment: data['environment'], hostname: nil}
93
+ )
94
+ else
95
+ @@logger.error("Error getting hostname for instance: #{e}: sleeping #{sleeptime}s and retrying (#{i}/#{retries})")
96
+ sleep sleeptime
97
+ retry
98
+ end
99
+ end
63
100
  {
64
101
  id: instance.id,
65
- hostname: instance.public_dns_name,
102
+ instance: instance,
103
+ hostname: hostname,
66
104
  launch_time: launch_time
67
105
  }
68
106
  end
69
107
 
108
+ def self.tag_ec2_instance(instance, key, value, retries=5, sleeptime=0.5)
109
+ return true if ENV['DRYRUN']
110
+ i = 0
111
+ begin
112
+ instance.add_tag(key, value: value)
113
+ @@logger.debug("Added tag #{key}=#{value} to #{instance.id}")
114
+ true
115
+ rescue => e
116
+ i += 1
117
+ raise if i > retries
118
+ @@logger.error("Error adding tag #{key} to #{instance.id}: #{e}: sleeping #{sleeptime}s and retrying (#{i}/#{retries})")
119
+ sleep sleeptime
120
+ retry
121
+ end
122
+ end
123
+
70
124
  def self.terminate_ec2_instance(zone, id)
71
125
  return if ENV['DRYRUN']
72
126
  configure_ec2 zone
@@ -1,5 +1,6 @@
1
1
  require_relative "ec2"
2
2
  require_relative "data"
3
+ require "logger"
3
4
 
4
5
  module Gaptool
5
6
  module EC2
@@ -27,12 +28,54 @@ module Gaptool
27
28
  "hostname" => instance.public_dns_name,
28
29
  "launch_time" => instance.launch_time.to_s,
29
30
  "apps" => roles[role].to_s,
30
- "instance"=> instance.instance_id
31
+ "instance"=> instance.instance_id,
32
+ "security_group" => instance.security_groups[0].name
31
33
  }
32
34
  Gaptool::Data::addserver(iid, data, nil)
33
35
  end
34
36
  end
35
37
  return {"action" => "complete"}
36
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::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
+ else
71
+ return false
72
+ end
73
+ if save
74
+ logger.info("Setting #{property} to #{value} for #{instance_id}")
75
+ Gaptool::Data.set_server_data_attr(instance_id, property, value)
76
+ else
77
+ value
78
+ end
79
+ end
37
80
  end
38
81
  end
data/lib/routes.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  require 'securerandom'
3
3
  require 'set'
4
4
  require_relative 'exceptions'
5
+
5
6
  class GaptoolServer < Sinatra::Application
6
7
 
7
8
  def require_parameters(required_keys, data)
@@ -27,8 +28,8 @@ class GaptoolServer < Sinatra::Application
27
28
  JSON.parse(request.body.read))
28
29
 
29
30
  secret = SecureRandom.hex(12)
30
- security_group = data['security_group'] || Gaptool::Data::get_role_data(data['role'])["security_group"]
31
- sgid = Gaptool::EC2::get_or_create_securitygroup(data['role'], data['environment'], data['zone'], security_group)
31
+ data['security_group'] = data['security_group'] || Gaptool::Data::get_sg_for_role(data['role'], data['environment'])
32
+ sgid = Gaptool::EC2::get_or_create_securitygroup(data['role'], data['environment'], data['zone'], data['security_group'])
32
33
  image_id = data['ami'] || Gaptool::Data::get_ami_for_role(data['role'], data['zone'].chop)
33
34
  data['terminable'] = data['terminable'].nil? ? true : !!data['terminable']
34
35
  data['secret'] = secret
@@ -47,8 +48,26 @@ class GaptoolServer < Sinatra::Application
47
48
  zone: data['zone']
48
49
  }
49
50
  )
51
+
52
+ # Tag instance
53
+ role = data['role']
54
+ env = data['environment']
55
+ name = "#{role}-#{env}-#{instance[:id]}"
56
+ {'Name' => name, 'gaptool' => 'yes', 'role' => role, 'environment' => env}.each do |tag, value|
57
+ begin
58
+ Gaptool::EC2::tag_ec2_instance(instance[:instance], tag, value)
59
+ rescue => e
60
+ logger.error("Error while tagging: #{e}. Skipping tag")
61
+ Airbrake.notify_or_ignore(
62
+ e,
63
+ error_class: "EC2 Tag failed",
64
+ parameters: {instance: instance[:id], name: name, role: role, environment: env}
65
+ )
66
+ end
67
+ end
68
+
50
69
  # Add host tag
51
- data.merge(instance.reject { |k, v| k == :id })
70
+ data.merge(instance.reject { |k, v| [:id, :instance].include?(k) })
52
71
  Gaptool::Data::addserver(instance[:id], data, secret)
53
72
  json({instance: instance[:id],
54
73
  ami: image_id,
@@ -139,7 +158,13 @@ class GaptoolServer < Sinatra::Application
139
158
  end
140
159
 
141
160
  get '/instance/:id' do
142
- json Gaptool::Data::stringify_apps(Gaptool::Data::get_server_data(params[:id]))
161
+ rs = Gaptool::Data::get_server_data(params[:id])
162
+ if rs.nil?
163
+ status 404
164
+ error_response "instance with id '#{params[:id]}' not found"
165
+ else
166
+ json Gaptool::Data::stringify_apps(rs)
167
+ end
143
168
  end
144
169
 
145
170
  get '/hosts/:role/:environment' do
data/tasks/ec2.rb ADDED
@@ -0,0 +1,44 @@
1
+ namespace :ec2 do
2
+ desc "Rehash instances"
3
+ task :rehash do |t|
4
+ EC2.rehash
5
+ end
6
+
7
+ desc "Rehash single attribute of all instances"
8
+ task :rehash_attr_all, [:property] do |t, args|
9
+ if args[:property].nil?
10
+ puts "Missing property"
11
+ return 1
12
+ end
13
+ EC2.rehash_property(args[:property])
14
+ end
15
+
16
+ desc "Rehash ec2 attributes for a single instance"
17
+ task :rehash_attrs_for, [:instance] do |t, args|
18
+ if args[:instance].nil?
19
+ puts "Missing instance"
20
+ return 1
21
+ end
22
+ res = EC2.rehash_properties_for_instance(args[:instance])
23
+ return 1 unless res
24
+ end
25
+
26
+ desc "Rehash a single property for an instance"
27
+ task :rehash_attr_for, [:instance, :property] do |t, args|
28
+ if args[:instance].nil?
29
+ puts "Missing instance"
30
+ return 1
31
+ end
32
+ if args[:property].nil?
33
+ puts "Missing property"
34
+ return 1
35
+ end
36
+ res = EC2.rehash_property_for_instance(args[:property], args[:instance])
37
+ if res
38
+ puts "#{property} for instance #{instance} set to '#{res}'"
39
+ else
40
+ return 1
41
+ end
42
+ end
43
+
44
+ end
data/tasks/role.rb ADDED
@@ -0,0 +1,9 @@
1
+ namespace :role do
2
+ desc "Set security group for a role"
3
+ task :set_sg, [:role, :environment, :security_group] do |t, args|
4
+ abort("Missing parameters") if args[:role].nil? || args[:environment].nil? || args[:role].empty? || args[:environment].empty? || args[:security_group].nil? || args[:security_group].empty?
5
+ role = DH.get_role_data(args[:role])
6
+ role['sg'].merge!(args[:environment] => args[:security_group])
7
+ DH.save_role_data(args[:role], role)
8
+ end
9
+ end
data/tasks/server.rb CHANGED
@@ -8,4 +8,13 @@ namespace :server do
8
8
  DH.set_server_data_attr args[:instance], 'terminable', (args[:value] == "true" ? "true" : "false")
9
9
  puts DH.get_server_data args[:instance]
10
10
  end
11
+
12
+ desc "Remove a server from the gaptool database (no actions on AWS)"
13
+ task :rm, [:instance] do |t, args|
14
+ if args[:instance].nil?
15
+ puts "You must select an instance"
16
+ return 1
17
+ end
18
+ DH.rmserver(args[:instance])
19
+ end
11
20
  end
data/test/api_test.rb CHANGED
@@ -79,6 +79,23 @@ describe "Test API" do
79
79
  expect(resp['chef_runlist']).to eq(['recipe[other]'])
80
80
  end
81
81
 
82
+ it "should get the security group from the role" do
83
+ DH.save_role_data(host_data['role'], "sg" => {host_data['environment'] => "mysg-in-role"})
84
+ id = add_and_register_server(host_data.reject{|k,v| k == 'security_group'})['instance']
85
+ get "/host/testrole/testenv/#{id}"
86
+ resp = JSON.parse(last_response.body)
87
+ expect(resp.keys).to include("security_group")
88
+ expect(resp['security_group']).to eq("mysg-in-role")
89
+ end
90
+
91
+ it "should get the default security group" do
92
+ id = add_and_register_server(host_data.reject{|k,v| k == 'security_group'})['instance']
93
+ get "/host/testrole/testenv/#{id}"
94
+ resp = JSON.parse(last_response.body)
95
+ expect(resp.keys).to include("security_group")
96
+ expect(resp['security_group']).to eq("#{host_data['role']}-#{host_data['environment']}")
97
+ end
98
+
82
99
  it "should remove default runlist" do
83
100
  id = add_and_register_server(host_data.merge("chef_runlist"=> ['recipe[init]']))['instance']
84
101
  get "/host/testrole/testenv/#{id}"
@@ -93,7 +110,6 @@ describe "Test API" do
93
110
  resp = JSON.parse(last_response.body)
94
111
  expect(resp.keys).not_to include("chef_runlist")
95
112
  expect(resp['chef_runlist']).to be(nil)
96
-
97
113
  end
98
114
 
99
115
  it "should get the ami from the role" do
@@ -188,7 +204,8 @@ describe "Test API" do
188
204
  id = add_and_register_server()['instance']
189
205
  get '/hosts'
190
206
  expect(last_response.status).to eq(200)
191
- exp_data = host_data.reject{|k,v| k == 'terminable'}.merge('chef_runlist' => expanded_runlist)
207
+ exp_data = host_data.reject{|k,v| k == 'terminable'}.merge('chef_runlist' => expanded_runlist,
208
+ 'apps'=> [])
192
209
  exp_data['instance'] = id
193
210
  expect(JSON.parse(last_response.body)).to eq([exp_data])
194
211
  end
@@ -200,9 +217,11 @@ describe "Test API" do
200
217
  expect(last_response.status).to eq(200)
201
218
  exp_data = [
202
219
  host_data.reject{|k,v| k == 'terminable'}.merge({'instance' => id1,
203
- 'chef_runlist' => expanded_runlist}),
220
+ 'chef_runlist' => expanded_runlist,
221
+ 'apps' => []}),
204
222
  host_data.reject{|k,v| k == 'terminable'}.merge({'instance' => id2,
205
- 'chef_runlist' => expanded_runlist})
223
+ 'chef_runlist' => expanded_runlist,
224
+ 'apps' => []})
206
225
  ].to_set
207
226
  expect(JSON.parse(last_response.body).to_set).to eq(exp_data)
208
227
  end
@@ -215,7 +234,8 @@ describe "Test API" do
215
234
  get '/hosts/otherrole'
216
235
  expect(last_response.status).to eq(200)
217
236
  exp_data = [other.reject{|k,v| k == 'terminable'}.merge({'instance'=> id1,
218
- 'chef_runlist' => expanded_runlist})]
237
+ 'chef_runlist' => expanded_runlist,
238
+ 'apps' => []})]
219
239
  expect(JSON.parse(last_response.body)).to eq(exp_data)
220
240
  end
221
241
 
@@ -226,11 +246,21 @@ describe "Test API" do
226
246
  expect(last_response.status).to eq(200)
227
247
  exp_data = host_data.reject{|k,v| k == 'terminable'}.merge({
228
248
  'instance'=> id,
229
- 'chef_runlist' => expanded_runlist})
249
+ 'chef_runlist' => expanded_runlist,
250
+ 'apps' => "[]"})
230
251
  expect(JSON.parse(last_response.body)).to eq(exp_data)
231
252
  end
232
253
  end
233
254
 
255
+ it "should not find an host by id" do
256
+ add_and_register_server()['instance']
257
+ get '/instance/other'
258
+ expect(last_response.status).to eq(404)
259
+ expect(JSON.parse(last_response.body)).to eq(
260
+ {"result" => "error",
261
+ "message" => "instance with id 'other' not found"})
262
+ end
263
+
234
264
  it "should find all hosts by environment and role" do
235
265
  id1 = add_and_register_server()['instance']
236
266
  id2 = add_and_register_server()['instance']
@@ -238,7 +268,7 @@ describe "Test API" do
238
268
  id4 = add_and_register_server(host_data.merge({'role' => 'otherrole'}))['instance']
239
269
  get '/hosts/testrole/testenv'
240
270
  expect(last_response.status).to eq(200)
241
- d = host_data.reject{|k,v| k == 'terminable'}.merge('chef_runlist' => expanded_runlist)
271
+ d = host_data.reject{|k,v| k == 'terminable'}.merge('chef_runlist' => expanded_runlist, 'apps'=> '[]')
242
272
  exp_data = [
243
273
  d.merge({'instance' => id1}),
244
274
  d.merge({'instance' => id2})
data/test/data_test.rb CHANGED
@@ -36,7 +36,8 @@ describe "data helpers" do
36
36
  'chef_repo' => 'myrepo',
37
37
  'chef_branch' => 'master',
38
38
  'registered' => 'false',
39
- 'secret' => 'secret'
39
+ 'secret' => 'secret',
40
+ 'apps' => []
40
41
  }))
41
42
  end
42
43
 
@@ -46,7 +47,8 @@ describe "data helpers" do
46
47
  expect(server).to eq(data.merge({
47
48
  'instance' => instid,
48
49
  'chef_repo' => 'myrepo',
49
- 'chef_branch' => 'master'
50
+ 'chef_branch' => 'master',
51
+ 'apps' => []
50
52
  }))
51
53
  end
52
54
 
@@ -61,7 +63,8 @@ describe "data helpers" do
61
63
  expect(server).to eq(data.merge({
62
64
  'instance' => instid,
63
65
  'chef_repo' => 'myrepo',
64
- 'chef_branch' => 'master'
66
+ 'chef_branch' => 'master',
67
+ 'apps' => []
65
68
  }))
66
69
  end
67
70
 
@@ -94,7 +97,8 @@ describe "data helpers" do
94
97
  'instance' => instid,
95
98
  'chef_repo' => 'myrepo',
96
99
  'chef_branch' => 'master',
97
- 'initkey' => 'FAKEKEY'
100
+ 'initkey' => 'FAKEKEY',
101
+ 'apps' => []
98
102
  }))
99
103
  end
100
104
 
@@ -104,12 +108,14 @@ describe "data helpers" do
104
108
  role = DH.get_role_data("role")
105
109
  expect(role).to eq({"chef_runlist"=> ["recipe[myrecipe]"].to_json,
106
110
  "apps" => [],
107
- "amis" => {}})
111
+ "amis" => {},
112
+ "sg" => {}})
108
113
  server = DH.get_server_data(instid)
109
114
  expect(server).to eq(data.merge("instance" => instid,
110
115
  "chef_runlist" => ["recipe[myrecipe]"],
111
116
  "chef_repo" => "myrepo",
112
- "chef_branch" => "master" ))
117
+ "chef_branch" => "master",
118
+ "apps" => [] ))
113
119
  end
114
120
 
115
121
  it "shoud get the ami for a node from the role" do
@@ -118,6 +124,16 @@ describe "data helpers" do
118
124
  role = DH.get_role_data("role")
119
125
  expect(role).to eq({'ami' => 'ami-1234567',
120
126
  "apps" => [],
121
- "amis" => {}})
127
+ "amis" => {},
128
+ "sg" => {}})
129
+ end
130
+
131
+ it "shoud get the sg for a node from the role" do
132
+ DH.save_role_data("role", ami: 'ami-1234567', "sg" => {"test" => "my_role"})
133
+ role = DH.get_role_data("role")
134
+ expect(role).to eq({'ami' => 'ami-1234567',
135
+ "apps" => [],
136
+ "amis" => {},
137
+ "sg" => {"test" => "my_role"}})
122
138
  end
123
139
  end
data/test/test_helper.rb CHANGED
@@ -6,7 +6,8 @@ if ENV['COVERAGE']
6
6
  add_group 'helpers', 'lib/helpers'
7
7
  end
8
8
  end
9
-
9
+ # Clear airbrake env if set
10
+ ENV['AIRBRAKE_API_KEY'] = nil
10
11
  libpath = File.realpath(File.join(File.dirname(__FILE__), "..", "lib"))
11
12
  require 'rspec'
12
13
  require 'rack/test'
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.6.4
4
+ version: 0.6.6
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: 2014-12-12 00:00:00.000000000 Z
13
+ date: 2015-01-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sinatra
@@ -166,6 +166,20 @@ dependencies:
166
166
  - - "~>"
167
167
  - !ruby/object:Gem::Version
168
168
  version: '1.5'
169
+ - !ruby/object:Gem::Dependency
170
+ name: json
171
+ requirement: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - "~>"
174
+ - !ruby/object:Gem::Version
175
+ version: '1.8'
176
+ type: :runtime
177
+ prerelease: false
178
+ version_requirements: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - "~>"
181
+ - !ruby/object:Gem::Version
182
+ version: '1.8'
169
183
  - !ruby/object:Gem::Dependency
170
184
  name: rspec
171
185
  requirement: !ruby/object:Gem::Requirement
@@ -227,7 +241,7 @@ email: ops@gild.com
227
241
  executables:
228
242
  - gaptool-server
229
243
  - gaptool-shell
230
- - gaptool_server_migrate_0.5-0.6
244
+ - gaptool_migrate_security_groups
231
245
  extensions: []
232
246
  extra_rdoc_files:
233
247
  - LICENSE.txt
@@ -241,7 +255,7 @@ files:
241
255
  - VERSION
242
256
  - bin/gaptool-server
243
257
  - bin/gaptool-shell
244
- - bin/gaptool_server_migrate_0.5-0.6
258
+ - bin/gaptool_migrate_security_groups
245
259
  - config.ru
246
260
  - lib/app.rb
247
261
  - lib/exceptions.rb
@@ -255,7 +269,9 @@ files:
255
269
  - tasks/app.rb
256
270
  - tasks/config.rb
257
271
  - tasks/docker.rb
272
+ - tasks/ec2.rb
258
273
  - tasks/gem.rb
274
+ - tasks/role.rb
259
275
  - tasks/server.rb
260
276
  - tasks/user.rb
261
277
  - test/api_test.rb
@@ -1,113 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # convert the old data model for the gaptool server
4
- # to the new struct
5
-
6
- libpath = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
7
- $:.unshift(libpath)
8
- require "#{libpath}/helpers/redis"
9
- require "#{libpath}/helpers/data"
10
- DH = Gaptool::Data
11
-
12
- puts "Removing cruft"
13
- # First, remove cruft. Like all servers created but never registered, etc
14
- ['instance:*', '_*', 'apikey:*', 'service:*', 'running', 'ec2*',
15
- 'failover', 'capacity', 'sg:*'].each do |pattern|
16
- $redis.redis.keys(pattern).each do |key|
17
- $redis.redis.del key
18
- end
19
- end
20
-
21
- puts "Migrating roles..."
22
- $redis.redis.keys('role:*').each do |key|
23
- puts " - #{key}"
24
- data = $redis.redis.hgetall(key)
25
- role = key.sub('role:', '')
26
- unless data['ami'].nil?
27
- # We didn't have per-regin ami in roles, so
28
- # default to us-west-2
29
- data['amis'] = {'us-west-2' => data['ami']}
30
- role.delete('ami')
31
- end
32
- DH.save_role_data(role, data)
33
- end
34
-
35
- puts "Migrating ami info to role..."
36
- $redis.redis.keys('amis:*').each do |key|
37
- role = key.sub("amis:", '')
38
- puts " - #{key}"
39
- amis = $redis.redis.hgetall(key)
40
- roledata = DH.get_role_data(role)
41
- roledata['amis'] = amis.merge(roledata['amis'] || {})
42
- DH.save_role_data(role, roledata)
43
- $redis.redis.del(key)
44
- end
45
-
46
- puts "Migrating apps..."
47
- $redis.redis.keys('app:*').each do |key|
48
- puts " - #{key}"
49
- appname = key.sub('app:', '')
50
- role = $redis.redis.hget(key, "role")
51
- if role.nil? || appname.nil?
52
- puts "Missing info for app: #{appname} role: #{role}"
53
- end
54
- $redis.redis.del(key)
55
- DH.add_app(appname, role) unless role.nil?
56
- end
57
-
58
- puts "Migrating instances..."
59
- $redis.redis.keys('host:*').each do |key|
60
- puts " - #{key}"
61
- pfx, role, env, iid = key.split(':')
62
- data = $redis.redis.hgetall(key)
63
- data['role'] = role
64
- data['environment'] = env
65
- unless data['chef_runlist'].nil?
66
- data['chef_runlist'] = JSON.parse data['chef_runlist']
67
- end
68
- DH.addserver(iid, data, nil)
69
- $redis.redis.del(key)
70
- # remove stale keys from hsh
71
- $redis.hdel "instance:#{iid}", ["capacity", "mirror", "secret", 'instance']
72
- end
73
-
74
- puts "Removing unneeded info from instance data..."
75
- $redis.smembers('instances').each do |inst|
76
- $redis.hdel "instance:#{inst}", ["capacity", "mirror", "secret", "instance"]
77
- if $redis.hget("instance:#{inst}", 'chef_runlist') == "recipe[init]"
78
- $redis.hdel "instance:#{inst}", "chef_runlist"
79
- end
80
- term = $redis.hget("instance:#{inst}", "terminate")
81
- unless term.nil?
82
- unless term == 'true'
83
- $redis.hset("instance:#{inst}", "terminable", term)
84
- end
85
- $redis.hdel("instance:#{inst}", "terminate")
86
- end
87
- end
88
-
89
- puts "Rename old config keys"
90
- $redis.redis.rename('config', 'gt:config')
91
- $redis.hset('config', 'chef_repo', $redis.hget('config', 'chefrepo'))
92
- $redis.hset('config', 'chef_branch', $redis.hget('config', 'chefbranch'))
93
-
94
- puts "Removing old config keys"
95
- ['remoteredis:host', 'remoteredis:port', 'aws_id', 'aws_secret',
96
- 'chefrepo', 'chefbranch'].each do |key|
97
- $redis.hdel 'config', key
98
- end
99
-
100
- unless ARGV[0].nil?
101
- puts "Updating GT_URL to #{ARGV[0]}"
102
- $redis.hset('config', 'url', ARGV[0])
103
- end
104
-
105
- puts "Namespace remaining keys"
106
- ['users', 'amis'].each { |k| $redis.redis.rename(k, "gt:#{k}")}
107
-
108
- puts "Removing out-of-namespace keys"
109
- $redis.redis.keys('*').select { |k| !k.start_with? ('gt:')}.each do |k|
110
- $redis.redis.del(k)
111
- end
112
-
113
- $redis.save