gaptool-server 0.5.19 → 0.6.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ require 'redis'
2
+
3
+ # docker links support
4
+ unless ENV['REDIS_PORT_6379_TCP_ADDR'].nil?
5
+ ENV['REDIS_HOST'] = ENV['REDIS_PORT_6379_TCP_ADDR']
6
+ ENV['REDIS_PORT'] = ENV['REDIS_PORT_6379_TCP_PORT']
7
+ ENV.delete('REDIS_PASS')
8
+ end
9
+
10
+ ENV['REDIS_HOST'] = 'localhost' unless ENV['REDIS_HOST']
11
+ ENV['REDIS_PORT'] = '6379' unless ENV['REDIS_PORT']
12
+ ENV['REDIS_PASS'] = nil unless ENV['REDIS_PASS']
13
+ ENV['REDIS_DB'] = '0' unless ENV['REDIS_DB']
14
+
15
+ $redis = Redis.new(:host => ENV['REDIS_HOST'],
16
+ :port => ENV['REDIS_PORT'].to_i,
17
+ :password => ENV['REDIS_PASS'],
18
+ :db => ENV['REDIS_DB'].to_i)
19
+
@@ -1,63 +1,38 @@
1
- module RehashHelpers
2
- def rehash()
3
- @layout = {}
4
- @roles = []
5
- $redis.keys('app:*').each do |app|
6
- role = $redis.hget(app,'role')
7
- unless role == 'nil'
8
- @roles << role
1
+ module Gaptool
2
+ module EC2
3
+ def self.rehash()
4
+ servers.each do |inst|
5
+ rmserver inst
9
6
  end
10
- end
11
- $redis.keys('host:*').each do |key|
12
- @roles << key.gsub('host:','').gsub(/:.*:i-.*/,'')
13
- end
14
- @roles.uniq!
15
- @roles.each do |role|
16
- apps = []
17
- $redis.keys('app:*').each do |app|
18
- if $redis.hget(app,'role') == role
19
- apps << app.gsub('app:','')
20
- end
21
- end
22
- @layout[role] = apps
23
- end
24
-
25
- $redis.keys("host:*").each do |rediskey|
26
- $redis.del rediskey
27
- end
28
-
29
- $redis.keys("instance:*").each do |rediskey|
30
- $redis.del rediskey
31
- end
32
-
33
- @zones = $redis.hgetall('amis').keys
34
- @zones.each do |zone|
35
- @ec2 = AWS::EC2.new(:access_key_id => $redis.hget('config', 'aws_id'), :secret_access_key => $redis.hget('config', 'aws_secret'), :ec2_endpoint => "ec2.#{zone}.amazonaws.com")
36
- @instances = []
37
- @ec2.instances.each do |instance|
38
- if instance.tags['gaptool'] == 'yes' && instance.status == :running
39
- @instances << instance
7
+ layout = roles()
8
+ puts layout
9
+ zones.each do |zone|
10
+ @ec2 = AWS::EC2.new(:access_key_id => $redis.hget('config', 'aws_id'),
11
+ :secret_access_key => $redis.hget('config', 'aws_secret'),
12
+ :ec2_endpoint => "ec2.#{zone}.amazonaws.com")
13
+ ilist = []
14
+ @ec2.instances.each do |instance|
15
+ if instance.tags['gaptool'] == 'yes' && instance.status == :running
16
+ ilist << instance
17
+ end
40
18
  end
41
- end
42
- @instances.each do |instance|
43
- @name = instance.tags['Name'].split('-')
44
- @rediskey = "host:#{@name[0]}:#{@name[1]}:i-#{@name.last}"
45
- @host = {
46
- "zone"=> instance.availability_zone,
47
- "itype"=> instance.instance_type,
48
- "role"=> @name.first,
49
- "environment"=> @name[1],
50
- "secret"=>"NA",
51
- "capacity"=>"6",
52
- "hostname"=> instance.public_dns_name,
53
- "apps" => @layout[@name[0]].to_s,
54
- "instance"=> instance.instance_id
55
- }
56
- @host.keys.each do |key|
57
- $redis.hset(@rediskey, key, @host[key])
19
+ ilist.each do |instance|
20
+ puts " - #{instance.tags['Name']}"
21
+ role, environment, iid = instance.tags['Name'].split('-')
22
+ data = {
23
+ "zone"=> instance.availability_zone,
24
+ "itype"=> instance.instance_type,
25
+ "role"=> role,
26
+ "environment"=> environment,
27
+ "hostname"=> instance.public_dns_name,
28
+ "apps" => layout[role].to_s,
29
+ "instance"=> instance.instance_id
30
+ }
31
+ puts data
32
+ addserver(data['instance'], data, nil)
58
33
  end
59
34
  end
35
+ return {"action" => "complete"}
60
36
  end
61
- return {"action" => "complete"}
62
37
  end
63
38
  end
data/lib/routes.rb ADDED
@@ -0,0 +1,172 @@
1
+ # encoding: utf-8
2
+ require 'securerandom'
3
+ require 'set'
4
+ require_relative 'exceptions'
5
+ class GaptoolServer < Sinatra::Application
6
+
7
+ def require_parameters(required_keys, data)
8
+ data = data.delete_if { |k,v| v.nil? }
9
+ required_keys = [*required_keys].to_set unless required_keys.is_a? Set
10
+ keys = data.keys.to_set
11
+ unless keys >= required_keys
12
+ raise BadRequest, "Missing required_parameters: #{(required_keys - keys).to_a.join(" ")}"
13
+ end
14
+ data
15
+ end
16
+
17
+ get '/' do
18
+ "You must be lost. Read the instructions."
19
+ end
20
+
21
+ get '/ping' do
22
+ "PONG"
23
+ end
24
+
25
+ post '/init' do
26
+ data = require_parameters(%w(role environment zone itype),
27
+ JSON.parse(request.body.read))
28
+
29
+ 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)
32
+ image_id = data['ami'] || Gaptool::Data::get_ami_for_role(data['role'], data['zone'].chop)
33
+ data['terminable'] = data['terminable'].nil? ? true : !!data['terminable']
34
+
35
+ id = Gaptool::EC2::create_ec2_instance(
36
+ {
37
+ :image_id => image_id,
38
+ :availability_zone => data['zone'],
39
+ :instance_type => data['itype'],
40
+ :key_name => "gaptool",
41
+ :security_group_ids => sgid,
42
+ :user_data => "#!/bin/bash\ncurl --silent -H 'X-GAPTOOL-USER: #{env['HTTP_X_GAPTOOL_USER']}' -H 'X-GAPTOOL-KEY: #{env['HTTP_X_GAPTOOL_KEY']}' #{$redis.hget('config', 'url')}/register -X PUT --data '#{data.to_json}' | bash"
43
+ }, {
44
+ role: data['role'],
45
+ env: data['environment'],
46
+ zone: data['zone']
47
+ }
48
+ )
49
+ # Add host tag
50
+ Gaptool::Data::addserver(id, data, secret)
51
+ json({instance: id,
52
+ ami: image_id,
53
+ role: data['role'],
54
+ environment: data['environment'],
55
+ secret: secret,
56
+ terminable: data['terminable'],
57
+ security_group: sgid})
58
+ end
59
+
60
+ post '/terminate' do
61
+ data = require_parameters("id",
62
+ JSON.parse(request.body.read))
63
+ host_data = Gaptool::Data::get_server_data data['id']
64
+ raise NotFound, "No such instance: #{data['id']}" if host_data.nil?
65
+ raise Conflict, "Instance #{data['id']} cannot be terminated" if host_data['terminable'] == false
66
+
67
+ Gaptool::EC2::terminate_ec2_instance(data['zone'], data['id'])
68
+ Gaptool::Data::rmserver(data['id'])
69
+ json data['id'] => {'status' => 'terminated'}
70
+ end
71
+
72
+ put '/register' do
73
+ data = JSON.parse request.body.read
74
+ data = require_parameters(%w(role zone environment secret), data)
75
+ instance_id = Gaptool::Data::register_server data['role'], data['environment'], data['secret']
76
+
77
+ raise Forbidden, "Can't register instance: wrong secret or missing role/environment" unless instance_id
78
+
79
+ hostname = Gaptool::EC2::get_ec2_instance_data(data['zone'].chop, instance_id)[:hostname]
80
+ host_data = Gaptool::Data::get_server_data instance_id, initkey: true, force_runlist: true
81
+
82
+ chef_repo = host_data['chef_repo']
83
+ chef_branch = host_data['chef_branch']
84
+ # FIXME: remove init key from redis
85
+ initkey = host_data['init_key']
86
+ run_list = host_data['chef_runlist'].to_json
87
+
88
+ jdata = {
89
+ 'hostname' => hostname,
90
+ 'recipe' => 'init',
91
+ 'number' => instance_id,
92
+ 'instance' => instance_id,
93
+ 'run_list' => run_list,
94
+ 'role' => data['role'],
95
+ 'environment' => data['environment'],
96
+ 'chefrepo' => chef_repo,
97
+ 'chefbranch' => chef_branch,
98
+ 'identity' => initkey,
99
+ 'appuser' => Gaptool::Data::get_config('appuser'),
100
+ 'apps' => host_data['apps']
101
+ }.to_json
102
+
103
+ erb :init, locals: {
104
+ initkey: initkey,
105
+ chef_branch: chef_branch,
106
+ chef_repo: chef_repo,
107
+ json: jdata
108
+ }
109
+ end
110
+
111
+ get '/hosts' do
112
+ servers = Gaptool::Data::servers.map do |inst|
113
+ Gaptool::Data::get_server_data inst
114
+ end
115
+ json servers
116
+ end
117
+
118
+ get '/apps' do
119
+ out = {}
120
+ Gaptool::Data.apps.each do |app|
121
+ out[app] = Gaptool::Data::get_app_data(app)
122
+ end
123
+ json out
124
+ end
125
+
126
+ get '/hosts/:role' do
127
+ servers = Gaptool::Data::servers_in_role(params[:role]).map do |inst|
128
+ Gaptool::Data::get_server_data inst
129
+ end
130
+ json servers
131
+ end
132
+
133
+ get '/instance/:id' do
134
+ json Gaptool::Data::get_server_data(params[:id])
135
+ end
136
+
137
+ get '/hosts/:role/:environment' do
138
+ if params[:role] == 'ALL'
139
+ list = Gaptool::Data::servers_in_env params[:environment]
140
+ else
141
+ list = Gaptool::Data::servers_in_role_env params[:role], params[:environment]
142
+ end
143
+ servers = list.map do |inst|
144
+ Gaptool::Data::get_server_data inst
145
+ end
146
+
147
+ json servers
148
+ end
149
+
150
+ get '/host/:role/:environment/:instance' do
151
+ json Gaptool::Data::get_server_data params[:instance]
152
+ end
153
+
154
+ get '/ssh/:role/:environment/:instance' do
155
+ data = Gaptool::Data::get_server_data params[:instance]
156
+ host = data['hostname']
157
+ key, pubkey = Gaptool::EC2::putkey(host)
158
+ json hostname: host, key: key, pubkey: pubkey
159
+ end
160
+
161
+ get '/version' do
162
+ version = File.read(File.realpath(
163
+ File.join(File.dirname(__FILE__), "..", 'VERSION')
164
+ )).strip
165
+ json server_version: version, api: {v0: "/"}
166
+ end
167
+
168
+ post '/rehash' do
169
+ json Gaptool::Rehash::rehash()
170
+ end
171
+
172
+ end
data/lib/views/init.erb CHANGED
@@ -1,14 +1,12 @@
1
1
  apt-get update
2
2
  apt-get install -ymq zsh git libssl-dev ruby1.9.1-full build-essential
3
- curl -LO https://www.getchef.com/chef/install.sh
4
- bash install.sh -v <%= @chef_version %>
5
-
3
+ gem install --bindir /usr/local/bin --no-ri --no-rdoc chef
6
4
  cat << 'EOFKEY' > /root/.ssh/id_rsa
7
- <%= @initkey %>
5
+ <%= initkey %>
8
6
  EOFKEY
9
7
  chmod 600 /root/.ssh/id_rsa
10
8
  echo 'StrictHostKeyChecking no' > /root/.ssh/config
11
- git clone -b <%= @chef_branch %> <%= @chef_repo %> /root/ops
12
- echo '<%= @json %>' > /root/init.json
13
- chef-solo -c /root/ops/cookbooks/init.rb -j /root/init.json -E <%= @chef_environment %> && \
14
- (rm /root/.ssh/id_rsa; rm /root/install.sh; userdel -r ubuntu; rm -rf /root/.ssh; rm -rf /root/ops)
9
+ git clone -b <%= chef_branch %> <%= chef_repo %> /root/ops
10
+ echo '<%= json %>' > /root/init.json
11
+ chef-solo -c /root/ops/cookbooks/init.rb -j /root/init.json && \
12
+ (rm /root/.ssh/id_rsa; userdel -r ubuntu; rm -rf /root/.ssh; rm -rf /root/ops)
data/tasks/app.rb ADDED
@@ -0,0 +1,28 @@
1
+ namespace :app do
2
+ desc "Add an application"
3
+ task :add, [:app, :role] do |t, args|
4
+ abort("Missing parameters") if args[:app].nil? || args[:app].empty? || args[:role].nil? || args[:role].empty?
5
+ ex = DH.get_app_data(args[:app])
6
+ unless ex.nil?
7
+ puts "Updating application #{args[:app]}" unless ex.nil?
8
+ DH.remove_app(args[:app])
9
+ end
10
+ DH.add_app(args[:app], args[:role])
11
+ puts "Added app #{args[:app]} in role #{args[:role]}"
12
+ end
13
+
14
+ desc "Remove an application"
15
+ task :delete, [:app] do |t, args|
16
+ DH.remove_app(args[:app])
17
+ puts "Removed app #{args[:app]}"
18
+ end
19
+ end
20
+
21
+ desc "List apps"
22
+ task :app do
23
+ puts "Apps:"
24
+ DH.apps.each do |app|
25
+ info = DH.get_app_data(app)
26
+ puts " * #{app} => #{info["role"]}"
27
+ end
28
+ end
data/tasks/docker.rb ADDED
@@ -0,0 +1,84 @@
1
+ def printimages
2
+ puts %x[docker images | grep '^gild/gaptool']
3
+ end
4
+
5
+ unless File.exists?('/.dockerenv')
6
+ namespace :docker do
7
+ namespace :build do
8
+ task :image do
9
+ sys(%w(./scripts/build_docker_images.sh))
10
+ printimages
11
+ end
12
+
13
+ desc "Build the release image"
14
+ task :release do
15
+ sys(%w(./scripts/build_docker_images.sh -t release))
16
+ printimages
17
+ end
18
+
19
+ task :all => [:image]
20
+ end
21
+
22
+ namespace :push do
23
+ task :release do
24
+ sys(%w(docker push gild/gaptool:release))
25
+ end
26
+
27
+ desc 'Push all tags to the Docker Hub'
28
+ task :all do
29
+ sys(%w(docker push gild/gaptool))
30
+ end
31
+ end
32
+
33
+ desc 'Build the docker image'
34
+ task :build => 'build:image'
35
+
36
+ desc "Push the release image to the Docker Hub"
37
+ task :push => 'push:release'
38
+
39
+ task :up => [:build, :recreate]
40
+
41
+ desc "Run tests w/ docker"
42
+ task :test => :build do
43
+ sys(%w(fig run --rm gaptool rake test))
44
+ end
45
+
46
+ desc "Stop docker containers"
47
+ task :stop do
48
+ sys(%w(fig stop))
49
+ end
50
+
51
+ desc "Start docker containers"
52
+ task :start do
53
+ sys(%w(fig start))
54
+ end
55
+
56
+ desc "Restart docker containers"
57
+ task :restart => [:stop, :start]
58
+
59
+ desc "Stop and remove docker containers (alias 'rm')"
60
+ task :remove => :stop do
61
+ sys(%w(fig rm --force))
62
+ end
63
+
64
+ task :rm => :remove
65
+
66
+ desc "Recreate docker containers without building"
67
+ task :recreate do
68
+ sys(%w(fig up -d))
69
+ end
70
+
71
+ desc "Run a command in the docker container"
72
+ task :run do
73
+ exit sys(%W(fig run --rm gaptool #{ARGV[1..-1].shelljoin}))
74
+ end
75
+
76
+ desc "Run a rake task inside the docker container"
77
+ task :rake do
78
+ exit sys(%W(fig run --rm gaptool rake #{ARGV[1..-1].shelljoin}))
79
+ end
80
+ end
81
+
82
+ desc "Bring up docker containers"
83
+ task :docker => 'docker:up'
84
+ end
data/tasks/gem.rb ADDED
@@ -0,0 +1,27 @@
1
+ namespace :gem do
2
+
3
+ desc "Build the gem"
4
+ task :build => :clean do
5
+ sys(%w(gem build gaptool-server.gemspec))
6
+ end
7
+
8
+ desc "Clean built file"
9
+ task :clean do
10
+ sys(%w(rm -vf *.gem))
11
+ end
12
+
13
+ desc "Bump the version"
14
+ task :bump do
15
+ version = File.read('VERSION').strip
16
+ nver = version.next
17
+ f = File.open('VERSION', 'w')
18
+ f.write(nver)
19
+ f.close
20
+ puts "Bumped #{version} => #{nver}"
21
+ end
22
+
23
+ desc "Push"
24
+ task :push => :build do
25
+ sys(%w(gem push gaptool-server*.gem))
26
+ end
27
+ end
data/tasks/user.rb ADDED
@@ -0,0 +1,32 @@
1
+ namespace :user do
2
+ desc "Add a new user. rake user:create <username>"
3
+ task :create, [:username] do |t, args|
4
+ puts DH.useradd(args[:username])[:key]
5
+ end
6
+
7
+ desc "Rename a user. rake user:rename <oldname> <newname>"
8
+ task :rename, [:oldname, :newname] do |t, args|
9
+ user = DH.user(args[:oldname])
10
+ abort("Unknown user #{args[:oldname]}") if user.nil?
11
+ DH.userdel(user[:username])
12
+ DH.useradd(args[:newname], user[:key])
13
+ puts "User #{args[:oldname]} renamed to #{args[:newname]}"
14
+ end
15
+
16
+ desc "Delete a user. rake user:delete <username>"
17
+ task :delete, [:username] do |t, args|
18
+ DH.userdel(args[:username])
19
+ end
20
+
21
+ desc "Set user key. rake user:setkey <username> <key>"
22
+ task :setkey, [:username, :key] do |t, args|
23
+ user = DH.user(args[:username])
24
+ abort("Unknown user #{args[:username]}") if user.nil?
25
+ puts DH.useradd(args[:username], args[:key])
26
+ end
27
+ end
28
+
29
+ desc "List users"
30
+ task :user do
31
+ puts DH.users.keys.sort.join("\n")
32
+ end