deployku 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +7 -0
- data/README.md +234 -0
- data/Rakefile +14 -0
- data/bin/deployku +45 -0
- data/deployku.gemspec +23 -0
- data/lib/deployku/config.rb +92 -0
- data/lib/deployku/configurable.rb +75 -0
- data/lib/deployku/containerable.rb +82 -0
- data/lib/deployku/engine.rb +55 -0
- data/lib/deployku/helpers.rb +7 -0
- data/lib/deployku/plugins/access.rb +161 -0
- data/lib/deployku/plugins/app.rb +211 -0
- data/lib/deployku/plugins/docker.rb +77 -0
- data/lib/deployku/plugins/git.rb +56 -0
- data/lib/deployku/plugins/lxc.rb +5 -0
- data/lib/deployku/plugins/nginx.rb +140 -0
- data/lib/deployku/plugins/postgres.rb +139 -0
- data/lib/deployku/plugins/rails.rb +100 -0
- data/lib/deployku/plugins.rb +111 -0
- data/lib/deployku.rb +19 -0
- metadata +63 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Deployku
|
4
|
+
class AccessPlugin < Deployku::Plugin
|
5
|
+
describe :add, '<USER>', 'adds ssh key for user from STDIN'
|
6
|
+
def add(user_name)
|
7
|
+
allow = check_system_rights(:admin)
|
8
|
+
if !allow && get_users.count > 0
|
9
|
+
# allow add first user without privileges
|
10
|
+
puts "No rights."
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
key = $stdin.gets
|
14
|
+
key.chomp! if key
|
15
|
+
if !key || key == ''
|
16
|
+
puts "No key."
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
name = Deployku.sanitize_app_name(user_name)
|
20
|
+
user_add(user_name, key)
|
21
|
+
puts "User '#{user_name}' has been added."
|
22
|
+
unless allow
|
23
|
+
# first user
|
24
|
+
acl_system_set(user_name, 'admin')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe :delete, '<USER>', 'deletes user keys from authorized_keys', acl_sys: :admin
|
29
|
+
def delete(user_name)
|
30
|
+
user_delete(user_name)
|
31
|
+
acl_system_set(user_name, '')
|
32
|
+
apps = Deployku::AppPlugin.instance.get_app_list
|
33
|
+
apps.each { |app| acl_set(app, user_name, '') }
|
34
|
+
puts "All keys for user '#{name}' has been removed."
|
35
|
+
end
|
36
|
+
|
37
|
+
describe :show, '', 'shows authorized_keys file', acl_sys: :admin
|
38
|
+
def show
|
39
|
+
puts File.read(authorized_keys_path)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe :list, '', 'list user names', acl_sys: :admin
|
43
|
+
def list
|
44
|
+
p get_users
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'acl:set', '<APP> <USER> [LIST OF RIGHTS]', 'add user priviledges to application', acl_sys: :admin
|
48
|
+
def acl_set(app_name, user_name, rights='')
|
49
|
+
name = Deployku.sanitize_app_name(user_name)
|
50
|
+
urights = { name => rights.split(',').map { |r| r.chomp } }
|
51
|
+
rights = {}
|
52
|
+
if File.exists?(app_acl_path(app_name))
|
53
|
+
rights = YAML.load_file(app_acl_path(app_name))
|
54
|
+
end
|
55
|
+
rights.merge!(urights)
|
56
|
+
File.open(app_acl_path(app_name), 'w') do |f|
|
57
|
+
f << rights.to_yaml
|
58
|
+
end
|
59
|
+
puts "Application acl has been updated."
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'acl:system_set', '<USER> [LIST OF RIGHTS]', 'add system wide privileges', acl_sys: :admin
|
63
|
+
def acl_system_set(user_name, rights='')
|
64
|
+
name = Deployku.sanitize_app_name(user_name)
|
65
|
+
urights = { name => rights.split(',').map { |r| r.chomp } }
|
66
|
+
rights = {}
|
67
|
+
if File.exists?(system_acl_path)
|
68
|
+
rights = YAML.load_file(system_acl_path)
|
69
|
+
end
|
70
|
+
rights.merge!(urights)
|
71
|
+
File.open(system_acl_path, 'w') do |f|
|
72
|
+
f << rights.to_yaml
|
73
|
+
end
|
74
|
+
puts "System rights has been updated."
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'acl:list', '', 'lists all acls', acl_sys: :admin
|
78
|
+
def acl_list
|
79
|
+
users = get_users
|
80
|
+
apps = Deployku::AppPlugin.instance.get_app_list
|
81
|
+
rights = File.exists?(system_acl_path) ? YAML.load_file(system_acl_path) : {}
|
82
|
+
users.each do |user|
|
83
|
+
puts "#{user}:"
|
84
|
+
puts " system wide rights: #{rights[user]}"
|
85
|
+
apps.each do |app|
|
86
|
+
app_rights = File.exists?(app_acl_path(app)) ? YAML.load_file(app_acl_path(app)) : {}
|
87
|
+
puts " #{app}: #{app_rights[user]}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'acl:list_rights', '', 'lists available rights', acl_sys: :admin
|
93
|
+
def acl_list_rights
|
94
|
+
puts 'admin'
|
95
|
+
puts 'commit'
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_app_rights(app_name, right, ex=false)
|
99
|
+
p [app_name, right, ex]
|
100
|
+
name = Deployku.sanitize_app_name(ENV['NAME'].to_s)
|
101
|
+
app_rights = File.exists?(app_acl_path(app_name)) ? YAML.load_file(app_acl_path(app_name)) : {}
|
102
|
+
return true if app_rights[name] && (app_rights[name].include?(right.to_s) || app_rights[name].include?('admin'))
|
103
|
+
return check_system_rights(right, ex)
|
104
|
+
end
|
105
|
+
|
106
|
+
def check_system_rights(right, ex=false)
|
107
|
+
p [right, ex]
|
108
|
+
name = Deployku.sanitize_app_name(ENV['NAME'].to_s)
|
109
|
+
rights = File.exists?(system_acl_path) ? YAML.load_file(system_acl_path) : {}
|
110
|
+
return true if rights[name] && (rights[name].include?(right.to_s) || rights[name].include?('admin'))
|
111
|
+
if ex
|
112
|
+
puts "No rights."
|
113
|
+
exit 1
|
114
|
+
end
|
115
|
+
false
|
116
|
+
end
|
117
|
+
|
118
|
+
def user_add(user_name, key)
|
119
|
+
name = Deployku.sanitize_app_name(user_name)
|
120
|
+
File.open(authorized_keys_path, 'a') do |f|
|
121
|
+
f << "command=\"NAME=#{name} `cat #{sshcommand_path}` $SSH_ORIGINAL_COMMAND\",no-agent-forwarding,no-user-rc,no-X11-forwarding,no-port-forwarding #{key}\n"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def user_delete(user_name)
|
126
|
+
name = Deployku.sanitize_app_name(user_name)
|
127
|
+
lines = File.readlines(authorized_keys_path)
|
128
|
+
File.open(authorized_keys_path, 'w') do |f|
|
129
|
+
lines.each do |line|
|
130
|
+
f << "#{line}\n" unless line =~ /NAME=#{name}/
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def get_users
|
136
|
+
users = []
|
137
|
+
File.open(authorized_keys_path, 'r') do |f|
|
138
|
+
while l = f.gets
|
139
|
+
users << $1 if l =~ /NAME=([^\s]+)/
|
140
|
+
end
|
141
|
+
end if File.exists?(authorized_keys_path)
|
142
|
+
users
|
143
|
+
end
|
144
|
+
|
145
|
+
def app_acl_path(app_name)
|
146
|
+
File.join(Deployku::AppPlugin.instance.dir(app_name), 'DEPLOYKU_ACL.yml')
|
147
|
+
end
|
148
|
+
|
149
|
+
def system_acl_path
|
150
|
+
File.join(Deployku::Config.home, '.deployku_acl.yml')
|
151
|
+
end
|
152
|
+
|
153
|
+
def sshcommand_path
|
154
|
+
File.join(Deployku::Config.home, '.sshcommand')
|
155
|
+
end
|
156
|
+
|
157
|
+
def authorized_keys_path
|
158
|
+
File.join(Deployku::Config.home, '.ssh/authorized_keys')
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
module Deployku
|
2
|
+
class AppPlugin < Deployku::Plugin
|
3
|
+
include Deployku::Configurable
|
4
|
+
include Deployku::Containerable
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@config = {
|
8
|
+
'env' => {},
|
9
|
+
'links' => []
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
describe :create, '<APP>', 'creates new application', acl_sys: :admin
|
14
|
+
def create(app_name)
|
15
|
+
app_dir = dir(app_name)
|
16
|
+
unless Dir.exists?(app_dir)
|
17
|
+
Dir.mkdir(app_dir)
|
18
|
+
system "git init -q --bare '#{app_dir}'"
|
19
|
+
end
|
20
|
+
app_dir
|
21
|
+
end
|
22
|
+
|
23
|
+
describe :delete, '<APP>', 'deletes an existing application', acl_sys: :admin
|
24
|
+
def delete(app_name)
|
25
|
+
app_dir = dir(app_name)
|
26
|
+
if Dir.exists?(app_dir)
|
27
|
+
FileUtils.rm_rf(app_dir)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe :list, '', 'list available applications', acl_sys: :admin
|
32
|
+
def list
|
33
|
+
apps = get_app_list
|
34
|
+
apps.each { |app| puts app }
|
35
|
+
end
|
36
|
+
|
37
|
+
describe :status, '<APP>', 'show container status', acl_app: { 0 => :commit }
|
38
|
+
describe :start, '<APP>', 'starts container', acl_app: { 0 => :admin }
|
39
|
+
def start(app_name)
|
40
|
+
super(app_name)
|
41
|
+
result = true
|
42
|
+
plugins = Deployku::Plugin.filter_plugins(:after_start)
|
43
|
+
plugins.each do |plug|
|
44
|
+
result = result && plug.after_start(app_name)
|
45
|
+
end
|
46
|
+
result
|
47
|
+
end
|
48
|
+
describe :run, '<APP> <CMD>', 'starts a cmd in application environment', acl_app: { 0 => :admin }
|
49
|
+
describe :stop, '<APP>', 'stops running container', acl_app: { 0 => :admin }
|
50
|
+
describe :restart, '<APP>', 'restarts container', acl_app: { 0 => :admin }
|
51
|
+
describe :logs, '<APP>', 'show app logs', acl_app: { 0 => :admin }
|
52
|
+
|
53
|
+
describe :rebuild, '<APP> [REV]', 'rebuild container', acl_app: { 0 => :admin }
|
54
|
+
def rebuild(app_name, new_rev=nil)
|
55
|
+
app_dir = dir(app_name)
|
56
|
+
app_name = File.basename(app_dir)
|
57
|
+
Dir.mktmpdir('deployku_') do |tmp_dir|
|
58
|
+
tmp_app_dir = File.join(tmp_dir, 'app')
|
59
|
+
Dir.mkdir(tmp_app_dir)
|
60
|
+
system "git clone -q '#{app_dir}' '#{tmp_app_dir}'"
|
61
|
+
Dir.chdir(tmp_app_dir)
|
62
|
+
system "unset GIT_DIR GIT_WORK_TREE && git checkout #{new_rev}" if new_rev
|
63
|
+
system 'unset GIT_DIR GIT_WORK_TREE && git submodule update --init --recursive'
|
64
|
+
Dir.chdir(tmp_dir)
|
65
|
+
|
66
|
+
plugins = Deployku::Plugin.filter_plugins(:detect)
|
67
|
+
plugin = nil
|
68
|
+
plugins.each do |plug|
|
69
|
+
if plug.detect(tmp_app_dir)
|
70
|
+
plugin = plug
|
71
|
+
break
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
deployku_config_path = File.join(tmp_app_dir, 'deployku.yml')
|
76
|
+
Deployku::Config.load(deployku_config_path)
|
77
|
+
Deployku::Config.load(config_path(app_name))
|
78
|
+
config_load(app_name)
|
79
|
+
|
80
|
+
unless plugin
|
81
|
+
puts "Unsupported application type"
|
82
|
+
exit 1
|
83
|
+
else
|
84
|
+
if plugin.respond_to?(:port) && !@config['port']
|
85
|
+
config_set_port(app_name, plugin.port)
|
86
|
+
Deployku::Config.merge!({ port: plugin.port })
|
87
|
+
end
|
88
|
+
|
89
|
+
plugin.build_start_script(tmp_dir)
|
90
|
+
case Deployku::Config.engine
|
91
|
+
when 'docker'
|
92
|
+
plugin.build_dockerfile(tmp_dir)
|
93
|
+
when 'lxc'
|
94
|
+
puts 'not implemented'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
if Deployku::Engine.rebuild(app_name, tmp_dir)
|
99
|
+
plugin.volumes.each do |volume|
|
100
|
+
config_add_volume(app_name, volume)
|
101
|
+
end if plugin.respond_to?(:volumes)
|
102
|
+
|
103
|
+
restart(app_name)
|
104
|
+
else
|
105
|
+
exit 1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'config:show', '<APP>', 'shows app configuration', acl_app: { 0 => :admin }
|
111
|
+
describe 'config:set', '<APP> <ENV_VARIABLE> <VALUE>', 'sets environment variable', acl_app: { 0 => :admin }
|
112
|
+
describe 'config:unset', '<APP> <ENV_VARIABLE>', 'unsets environment variable', acl_app: { 0 => :admin }
|
113
|
+
describe 'config:set_from', '<APP> <VALUE>', 'sets base image name for container', acl_app: { 0 => :admin }
|
114
|
+
describe 'config:unset_from', '<APP>', 'sets base image to default', acl_app: { 0 => :admin }
|
115
|
+
describe 'config:set_engine', '<APP> <ENGINE>', 'sets container engine (docker, lxc)', acl_app: { 0 => :admin }
|
116
|
+
describe 'config:unset_engine', '<APP>', 'sets engine to default', acl_app: { 0 => :admin }
|
117
|
+
describe 'config:set_port', '<APP> <PORT>', 'sets port on which will application listen', acl_app: { 0 => :admin }
|
118
|
+
describe 'config:unset_port', '<APP>', 'remove port setting', acl_app: { 0 => :admin }
|
119
|
+
|
120
|
+
describe 'config:add_domain', '<APP> <DOMAIN>', 'bind domain with application', acl_app: { 0 => :admin }
|
121
|
+
def config_add_domain(app_name, domain)
|
122
|
+
config_load(app_name)
|
123
|
+
@config['domains'] ||= []
|
124
|
+
@config['domains'] << domain
|
125
|
+
config_save(app_name)
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'config:rm_domain', '<APP> <DOMAIN>', 'removes domain from the list', acl_app: { 0 => :admin }
|
129
|
+
def config_rm_domain(app_name, package)
|
130
|
+
config_load(app_name)
|
131
|
+
if @config['domains']
|
132
|
+
@config['domains'].delete(package)
|
133
|
+
config_save(app_name)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe 'config:add_package', '<APP> <PACKAGE>', 'will install additional package when rebuild', acl_app: { 0 => :admin }
|
138
|
+
def config_add_package(app_name, package)
|
139
|
+
config_load(app_name)
|
140
|
+
@config['packages'] ||= []
|
141
|
+
@config['packages'] << package
|
142
|
+
config_save(app_name)
|
143
|
+
end
|
144
|
+
|
145
|
+
describe 'config:rm_package', '<APP> <PACKAGE>', 'removes package from the list', acl_app: { 0 => :admin }
|
146
|
+
def config_rm_package(app_name, package)
|
147
|
+
config_load(app_name)
|
148
|
+
if @config['packages']
|
149
|
+
@config['packages'].delete(package)
|
150
|
+
config_save(app_name)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe 'config:add_volume', '<APP> <PATH>', 'mounts container path to app directory', acl_app: { 0 => :admin }
|
155
|
+
def config_add_volume(app_name, path)
|
156
|
+
config_load(app_name)
|
157
|
+
vpath = volume_path(app_name, path)
|
158
|
+
unless Dir.exists?(vpath)
|
159
|
+
FileUtils.mkpath(vpath)
|
160
|
+
end
|
161
|
+
@config['volumes'] ||= {}
|
162
|
+
@config['volumes'][vpath] = path unless @config['volumes'][vpath]
|
163
|
+
config_save(app_name)
|
164
|
+
end
|
165
|
+
|
166
|
+
describe 'config:rm_volume', '<APP> <PATH>', 'removes volume', acl_app: { 0 => :admin }
|
167
|
+
def config_rm_volume(app_name, path)
|
168
|
+
config_load(app_name)
|
169
|
+
vpath = volume_path(app_name, path)
|
170
|
+
if @config['volumes']
|
171
|
+
@config['volumes'].delete(vpath)
|
172
|
+
config_save(app_name)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe 'link', '<APP> <LINK>', 'adds link', acl_sys: :admin
|
177
|
+
def link(app_name, link)
|
178
|
+
config_load(app_name)
|
179
|
+
@config['links'] ||= []
|
180
|
+
@config['links'] << link
|
181
|
+
config_save(app_name)
|
182
|
+
end
|
183
|
+
|
184
|
+
describe 'unlink', '<APP> <LINK>', 'removes link', acl_sys: :admin
|
185
|
+
def unlink(app_name, link)
|
186
|
+
config_load(app_name)
|
187
|
+
if @config['links']
|
188
|
+
@config['links'].delete(link)
|
189
|
+
config_save(app_name)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def volume_path(app_name, path)
|
194
|
+
volume = Deployku.sanitize_app_name(path)
|
195
|
+
File.join(dir(app_name), 'DEPLOYKU_VOLUMES', volume)
|
196
|
+
end
|
197
|
+
|
198
|
+
def dir(app_name)
|
199
|
+
File.join(Deployku::Config.home, Deployku.sanitize_app_name(app_name))
|
200
|
+
end
|
201
|
+
|
202
|
+
def get_app_list
|
203
|
+
apps = []
|
204
|
+
Dir.glob(File.join(Deployku::Config.home, '*')) do |path|
|
205
|
+
apps << File.basename(path) if File.directory?(path)
|
206
|
+
end
|
207
|
+
apps
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Deployku
|
4
|
+
class DockerEngine < Deployku::Plugin
|
5
|
+
include Deployku::Engine
|
6
|
+
|
7
|
+
def start(app_name, app_dir=nil, name=nil)
|
8
|
+
args = build_args(app_name, app_dir, name)
|
9
|
+
hash = `docker run -d -P #{args.join(' ')} #{app_name}:latest`.chomp
|
10
|
+
if $?.exitstatus != 0 && name
|
11
|
+
hash = `docker start '#{name}'`.chomp
|
12
|
+
end
|
13
|
+
hash
|
14
|
+
end
|
15
|
+
|
16
|
+
def run(app_name, app_dir, *cmd)
|
17
|
+
args = build_args(app_name, app_dir)
|
18
|
+
system "docker run -t -i --rm --entrypoint=/bin/bash #{args.join(' ')} #{app_name}:latest -c \"#{cmd.join(' ')}\""
|
19
|
+
end
|
20
|
+
|
21
|
+
def stop(app_hash)
|
22
|
+
system "docker stop #{app_hash}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def logs(app_hash)
|
26
|
+
system "docker logs #{app_hash}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def rebuild(app_name, dir)
|
30
|
+
system "docker build -t #{app_name}:latest #{dir}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def running?(app_hash)
|
34
|
+
stat = JSON.parse(`docker inspect #{app_hash}`).first
|
35
|
+
return stat['State']['Running'] if stat && stat['State']
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def ip(app_hash)
|
40
|
+
stat = JSON.parse(`docker inspect #{app_hash}`).first
|
41
|
+
return stat['NetworkSettings']['IPAddress'] if stat && stat['NetworkSettings']
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def build_args(app_name, app_dir, name=nil)
|
48
|
+
args = []
|
49
|
+
if app_dir && Deployku::Config.env
|
50
|
+
env_path = File.join(app_dir, 'DEPLOYKU_ENV')
|
51
|
+
File.open(env_path, 'w') do |f|
|
52
|
+
Deployku::Config.env.each do |key, value|
|
53
|
+
f << "#{key}=#{value}\n"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
args << "--env-file='#{env_path}'"
|
57
|
+
end
|
58
|
+
|
59
|
+
if app_dir && Deployku::Config.volumes && Deployku::Config.volumes.count > 0
|
60
|
+
Deployku::Config.volumes.each do |src, dst|
|
61
|
+
args << "--volume='#{src}:#{dst}'"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
if app_dir && Deployku::Config.links && Deployku::Config.links.count > 0
|
66
|
+
Deployku::Config.links.each do |link|
|
67
|
+
args << "--link='#{link}'"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if name
|
72
|
+
args << "--name='#{name}'"
|
73
|
+
end
|
74
|
+
args
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
module Deployku
|
4
|
+
class GitPlugin < Deployku::Plugin
|
5
|
+
# describe :receive_pack, '<APP>', 'receives new commit'
|
6
|
+
def receive_pack app_name
|
7
|
+
unless app_name
|
8
|
+
exit 1
|
9
|
+
end
|
10
|
+
app_name = app_name.gsub(%r{'([^']+)'}, '\1')
|
11
|
+
app_dir = Deployku::AppPlugin.instance.create(app_name)
|
12
|
+
create_receive_hook(app_dir, File.basename(app_dir))
|
13
|
+
system "git-shell -c \"git-receive-pack '#{app_dir}'\""
|
14
|
+
end
|
15
|
+
|
16
|
+
describe :hook, '<APP>', 'receives new commit and builds new image', acl_app: { 0 => :commit }
|
17
|
+
def hook(app_name)
|
18
|
+
exit 1 unless app_name
|
19
|
+
app_dir = Deployku::AppPlugin.instance.dir(app_name)
|
20
|
+
app_name = File.basename(app_dir)
|
21
|
+
unless Dir.exists?(app_dir)
|
22
|
+
puts "Application directory '#{app_dir}' does not exist."
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
|
26
|
+
while line = $stdin.gets
|
27
|
+
old_rev, new_rev, branch = line.chomp.split(' ')
|
28
|
+
if branch != 'refs/heads/master'
|
29
|
+
puts 'Only master branch is supported now.'
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
unless new_rev
|
34
|
+
puts 'Missing new revision number'
|
35
|
+
exit 1
|
36
|
+
end
|
37
|
+
Deployku::AppPlugin.instance.rebuild(app_name, new_rev)
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def create_receive_hook(app_dir, app_name)
|
43
|
+
receive_hook_path = File.join(app_dir, 'hooks/pre-receive')
|
44
|
+
File.open(receive_hook_path, 'w') do |f|
|
45
|
+
f << <<EOF
|
46
|
+
#!/usr/bin/env bash
|
47
|
+
set -e; set -o pipefail;
|
48
|
+
|
49
|
+
cat | #{$0} git:hook '#{app_name}'
|
50
|
+
EOF
|
51
|
+
end
|
52
|
+
File.chmod(0755, receive_hook_path)
|
53
|
+
receive_hook_path
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
module Deployku
|
5
|
+
class NginxPlugin < Deployku::Plugin
|
6
|
+
describe :enable, '<APP>', 'enable nginx for application', acl_app: { 0 => :admin }
|
7
|
+
def enable(app_name)
|
8
|
+
app_plug = Deployku::AppPlugin.new
|
9
|
+
app_plug.config_load(app_name)
|
10
|
+
app_plug.config['nginx'] = {} unless app_plug.config['nginx']
|
11
|
+
app_plug.config['nginx']['enabled'] = true
|
12
|
+
app_plug.config['nginx']['port'] = 80 unless app_plug.config['nginx']['port']
|
13
|
+
app_plug.config['nginx']['wait'] = 300 unless app_plug.config['nginx']['wait']
|
14
|
+
app_plug.config['nginx']['public_volume'] = '/app/public/' unless app_plug.config['nginx']['public_volume']
|
15
|
+
app_plug.config_save(app_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe :disable, '<APP>', 'disable nginx for application', acl_app: { 0 => :admin }
|
19
|
+
def disable(app_name)
|
20
|
+
app_plug = Deployku::AppPlugin.new
|
21
|
+
app_plug.config_load(app_name)
|
22
|
+
if app_plug.config['nginx']
|
23
|
+
app_plug.config['nginx']['enabled'] = false
|
24
|
+
app_plug.config_save(app_name)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'config:set', '<APP> <NAME> <VALUE>', 'sets nginx parametr', acl_app: { 0 => :admin }
|
29
|
+
def config_set(app_name, name, value)
|
30
|
+
app_plug = Deployku::AppPlugin.new
|
31
|
+
app_plug.config_load(app_name)
|
32
|
+
app_plug.config['nginx'] = {} unless app_plug.config['nginx']
|
33
|
+
app_plug.config['nginx'][name] = value
|
34
|
+
app_plug.config_save(app_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'config:unset', '<APP> <NAME>', 'unsets nginx parametr', acl_app: { 0 => :admin }
|
38
|
+
def config_unset(app_name, name, value)
|
39
|
+
app_plug = Deployku::AppPlugin.new
|
40
|
+
app_plug.config_load(app_name)
|
41
|
+
if app_plug.config['nginx']
|
42
|
+
app_plug.config['nginx'].delete(name)
|
43
|
+
app_plug.config_save(app_name)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'config:build', '<APP>', 'rebuild config for an application', acl_app: { 0 => :admin }
|
48
|
+
def config_build(app_name)
|
49
|
+
app_plug = Deployku::AppPlugin.new
|
50
|
+
app_plug.config_load(app_name)
|
51
|
+
cid = app_plug.get_container_id(app_name)
|
52
|
+
ip = Deployku::Engine.ip(cid)
|
53
|
+
upstream = SecureRandom.uuid.gsub('-', '')
|
54
|
+
vpath = app_plug.volume_path(app_name, app_plug.config['nginx']['public_volume'])
|
55
|
+
domains = app_plug.config['domains']
|
56
|
+
if !domains || domains.empty?
|
57
|
+
puts "No domains."
|
58
|
+
exit 1
|
59
|
+
end
|
60
|
+
unless app_plug.config['port']
|
61
|
+
puts "No application port."
|
62
|
+
exit 1
|
63
|
+
end
|
64
|
+
File.open(config_path(app_name), 'w') do |f|
|
65
|
+
f << <<EOF
|
66
|
+
upstream #{upstream} {
|
67
|
+
server #{ip}:#{app_plug.config['port']};
|
68
|
+
}
|
69
|
+
|
70
|
+
server {
|
71
|
+
listen #{app_plug.config['nginx']['port']};
|
72
|
+
server_name #{domains.join(' ')};
|
73
|
+
root #{vpath};
|
74
|
+
|
75
|
+
gzip on;
|
76
|
+
gzip_http_version 1.1;
|
77
|
+
gzip_vary on;
|
78
|
+
gzip_comp_level 6;
|
79
|
+
gzip_proxied any;
|
80
|
+
gzip_types text/plain text/html text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml;
|
81
|
+
|
82
|
+
location / {
|
83
|
+
try_files $uri @#{upstream};
|
84
|
+
}
|
85
|
+
|
86
|
+
location @#{upstream} {
|
87
|
+
proxy_read_timeout 300;
|
88
|
+
proxy_connect_timeout 300;
|
89
|
+
proxy_redirect off;
|
90
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
91
|
+
proxy_set_header Host $http_host;
|
92
|
+
proxy_set_header X-Real-IP $remote_addr;
|
93
|
+
proxy_set_header CLIENT_IP $remote_addr;
|
94
|
+
proxy_set_header GEOIP_COUNTRY_CODE $geoip_country_code;
|
95
|
+
proxy_pass http://#{upstream};
|
96
|
+
}
|
97
|
+
}
|
98
|
+
EOF
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def after_start(app_name)
|
103
|
+
app_plug = Deployku::AppPlugin.new
|
104
|
+
app_plug.config_load(app_name)
|
105
|
+
if app_plug.config['nginx'] && app_plug.config['nginx']['enabled']
|
106
|
+
config_build(app_name)
|
107
|
+
cid = app_plug.get_container_id(app_name)
|
108
|
+
ip = Deployku::Engine.ip(cid)
|
109
|
+
counter = 0
|
110
|
+
$stdout.sync = true
|
111
|
+
while counter <= app_plug.config['nginx']['wait'].to_i && !up?(ip, app_plug.config['port'])
|
112
|
+
puts "wainting for webserver...#{counter+1}"
|
113
|
+
sleep 1
|
114
|
+
counter += 1
|
115
|
+
end
|
116
|
+
if counter > app_plug.config['nginx']['wait'].to_i
|
117
|
+
puts "timeouted"
|
118
|
+
return false
|
119
|
+
else
|
120
|
+
system 'sudo nginx -s reload'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
true
|
124
|
+
end
|
125
|
+
|
126
|
+
def up?(server, port)
|
127
|
+
begin
|
128
|
+
http = Net::HTTP.start(server, port, {open_timeout: 5, read_timeout: 5})
|
129
|
+
response = http.head("/")
|
130
|
+
response.code == "200"
|
131
|
+
rescue #Timeout::Error, SocketError
|
132
|
+
false
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def config_path(app_name)
|
137
|
+
File.join(Deployku::AppPlugin.instance.dir(app_name), 'nginx.conf')
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|