deployku 0.0.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 +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
|