dokuen 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -0
- data/bin/dokuen +1 -1
- data/bin/dokuen_restart_nginx +1 -4
- data/data/templates/bin_command.erb +3 -0
- data/data/templates/deploy_command.erb +3 -0
- data/data/templates/gitolite_command.erb +4 -0
- data/data/templates/instructions.erb +24 -0
- data/data/templates/mac_launchdaemon.erb +19 -0
- data/data/templates/nginx.erb +22 -0
- data/data/templates/pre_receive_hook.erb +16 -0
- data/data/templates/ubuntu_upstart.erb +5 -0
- data/lib/dokuen/application.rb +279 -0
- data/lib/dokuen/cli.rb +134 -197
- data/lib/dokuen/config.rb +23 -0
- data/lib/dokuen/platform.rb +16 -0
- data/lib/dokuen/version.rb +1 -1
- data/lib/dokuen/wrapper.rb +127 -0
- data/lib/dokuen.rb +14 -41
- metadata +14 -3
- data/lib/dokuen/deploy.rb +0 -173
data/README.md
CHANGED
@@ -44,6 +44,8 @@ Create a `git` user and install gitolite according to [package directions](http:
|
|
44
44
|
Run this:
|
45
45
|
|
46
46
|
```
|
47
|
+
$ sudo mkdir -p /usr/local/var/dokuen
|
48
|
+
$ cd /usr/local/var/dokuen
|
47
49
|
$ sudo dokuen setup
|
48
50
|
```
|
49
51
|
|
@@ -108,3 +110,4 @@ $ ssh git@<your_host> dokuen restart_app <name>
|
|
108
110
|
|
109
111
|
Unfortunately the stock Heroku buildpacks install a vendored node.js compiled for the Heroku platform, which happens to be linux. This doesn't work for Mac, which means you have to use a slightly patched version. This one works with a homebrew-installed node.js: https://github.com/peterkeen/heroku-buildpack-ruby
|
110
112
|
|
113
|
+
|
data/bin/dokuen
CHANGED
data/bin/dokuen_restart_nginx
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
==== IMPORTANT INSTRUCTIONS ====
|
2
|
+
|
3
|
+
In your .gitolite.rc file, in the COMMANDS section, add the following:
|
4
|
+
|
5
|
+
'dokuen' => 1
|
6
|
+
|
7
|
+
In your gitolite.conf file, add the following:
|
8
|
+
|
9
|
+
repo apps/[a-zA-Z0-9].*
|
10
|
+
C = @all
|
11
|
+
RW+ = CREATOR
|
12
|
+
config hooks.pre = "<%= File.expand_path('./bin/dokuen-deploy') %>"
|
13
|
+
|
14
|
+
In your nginx.conf, add the following to your http section:
|
15
|
+
|
16
|
+
include "<%= File.expand_path('nginx') %>/*.conf";
|
17
|
+
|
18
|
+
Run "sudo visudo" and add the following lines:
|
19
|
+
|
20
|
+
Runas_Alias APPUSERS = <%= options[:appuser] %>
|
21
|
+
|
22
|
+
git ALL=(APPUSERS) NOPASSWD: <%= File.expand_path('./bin/dokuen') %>
|
23
|
+
<%= options[:appuser] %> ALL=NOPASSWD: <%= @current_bin_path %>/dokuen_restart_nginx
|
24
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>Label</key>
|
6
|
+
<string>info.bugpslat.dokuen</string>
|
7
|
+
<key>ProgramArguments</key>
|
8
|
+
<array>
|
9
|
+
<string><%= File.expand_path("./bin/dokuen") %></string>
|
10
|
+
<string>boot</string>
|
11
|
+
</array>
|
12
|
+
<key>RunAtLoad</key>
|
13
|
+
<true/>
|
14
|
+
<key>WorkingDirectory</key>
|
15
|
+
<string><%= File.expand_path(".") %></string>
|
16
|
+
<key>UserName</key>
|
17
|
+
<string<%= options[:appuser] %></string>
|
18
|
+
</dict>
|
19
|
+
</plist>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<% if ports.length > 0 %>
|
2
|
+
upstream <%= name %> {
|
3
|
+
<% ports.each do |port| %>
|
4
|
+
server localhost:<%= port %>;
|
5
|
+
<% end %>
|
6
|
+
}
|
7
|
+
|
8
|
+
server {
|
9
|
+
listen 80;
|
10
|
+
listen 443 default ssl;
|
11
|
+
|
12
|
+
server_name <%= name %>.<%= config.base_domain_name %>;
|
13
|
+
|
14
|
+
if ($ssl_protocol = "") {
|
15
|
+
rewrite ^ https://$server_name$request_uri? permanent;
|
16
|
+
}
|
17
|
+
|
18
|
+
location / {
|
19
|
+
proxy_pass http://<%= name %>;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
hook = `git config hooks.pre`.chomp
|
3
|
+
|
4
|
+
rev = nil
|
5
|
+
|
6
|
+
STDIN.each do |line|
|
7
|
+
parts = line.split(/\s/)
|
8
|
+
next if parts[2] != "refs/heads/master"
|
9
|
+
rev = parts[1]
|
10
|
+
end
|
11
|
+
|
12
|
+
if hook != ""
|
13
|
+
name = File.basename(ENV['GL_REPO']).gsub(".git", '')
|
14
|
+
cmd = "env REV=#{rev} APP=#{name} #{hook}"
|
15
|
+
system(cmd) or raise "Error running pre-hook: #{cmd} returned #{$?}"
|
16
|
+
end
|
@@ -0,0 +1,279 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
class Dokuen::Application
|
6
|
+
|
7
|
+
attr_reader :name, :config
|
8
|
+
|
9
|
+
def initialize(name, config)
|
10
|
+
@name = name
|
11
|
+
@config = config
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_env(var)
|
15
|
+
with_app_dir do
|
16
|
+
env_path = File.join("env", var)
|
17
|
+
if File.exists?(env_path)
|
18
|
+
return File.read(env_path)
|
19
|
+
else
|
20
|
+
return nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_env(var, val)
|
26
|
+
with_app_dir do
|
27
|
+
env_path = File.join("env", var)
|
28
|
+
File.open(env_path, "w+") do |f|
|
29
|
+
f.write(val)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_env(var)
|
35
|
+
with_app_dir do
|
36
|
+
File.delete(File.join("env", var)) rescue nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def env
|
41
|
+
vars = read_env_dir("#{config.dokuen_dir}/env")
|
42
|
+
with_app_dir do
|
43
|
+
vars.merge!(read_env_dir('env'))
|
44
|
+
with_current_release do
|
45
|
+
File.open(".env") do |f|
|
46
|
+
f.lines.each do |line|
|
47
|
+
key, val = line.split('=', 2)
|
48
|
+
vars[key] = val.chomp
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
vars
|
54
|
+
end
|
55
|
+
|
56
|
+
def create
|
57
|
+
Dir.chdir(File.join(config.dokuen_dir, 'apps')) do
|
58
|
+
if File.exists?(name)
|
59
|
+
raise "Application #{name} exists!"
|
60
|
+
end
|
61
|
+
|
62
|
+
FileUtils.mkdir_p(name)
|
63
|
+
with_app_dir do
|
64
|
+
dirs = [
|
65
|
+
'releases',
|
66
|
+
'env',
|
67
|
+
'logs',
|
68
|
+
'build'
|
69
|
+
]
|
70
|
+
FileUtils.mkdir_p(dirs)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def deploy(revision)
|
76
|
+
git_dir = Dir.getwd
|
77
|
+
|
78
|
+
with_app_dir do
|
79
|
+
now = Time.now().utc().strftime("%Y%m%dT%H%M%S")
|
80
|
+
release_dir = "releases/#{now}"
|
81
|
+
clone_dir = clone(git_dir, revision)
|
82
|
+
|
83
|
+
buildpack = get_env('BUILDPACK_URL')
|
84
|
+
if buildpack
|
85
|
+
buildpack = "-b #{buildpack}"
|
86
|
+
else
|
87
|
+
buildpack = ''
|
88
|
+
end
|
89
|
+
|
90
|
+
sys("mason build #{clone_dir} #{buildpack} -o #{release_dir} -c build")
|
91
|
+
Dir.mkdir("#{release_dir}/.dokuen")
|
92
|
+
|
93
|
+
hook = get_env('DOKUEN_AFTER_BUILD')
|
94
|
+
if hook
|
95
|
+
sys("foreman run #{hook}")
|
96
|
+
end
|
97
|
+
|
98
|
+
if File.symlink?("previous")
|
99
|
+
File.unlink("previous")
|
100
|
+
File.symlink(File.readlink("current"), "previous")
|
101
|
+
end
|
102
|
+
|
103
|
+
if File.symlink?("current")
|
104
|
+
File.unlink("current")
|
105
|
+
end
|
106
|
+
|
107
|
+
File.symlink(File.expand_path(release_dir), "current")
|
108
|
+
end
|
109
|
+
|
110
|
+
scale
|
111
|
+
if File.symlink?("previous")
|
112
|
+
shutdown(File.readlink("previous"))
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def scale
|
117
|
+
puts "Scaling..."
|
118
|
+
with_current_release do
|
119
|
+
processes = running_processes
|
120
|
+
running_count_by_name = {}
|
121
|
+
|
122
|
+
processes.each do |proc, pidfile|
|
123
|
+
proc_name = proc.split('.')[0]
|
124
|
+
running_count_by_name[proc_name] ||= 0
|
125
|
+
running_count_by_name[proc_name] += 1
|
126
|
+
end
|
127
|
+
|
128
|
+
desired_count_by_name = {}
|
129
|
+
scale_spec = get_env('DOKUEN_SCALE')
|
130
|
+
if scale_spec
|
131
|
+
scale_spec.split(',').each do |spec|
|
132
|
+
proc_name, count = spec.split('=')
|
133
|
+
desired_count_by_name[proc_name] = count.to_i
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
to_start = []
|
138
|
+
to_stop = []
|
139
|
+
|
140
|
+
desired_count_by_name.each do |proc_name, count|
|
141
|
+
running = running_count_by_name[proc_name] || 0
|
142
|
+
if running < count
|
143
|
+
(count - running).times do |i|
|
144
|
+
index = running + i + 1
|
145
|
+
to_start << [proc_name, index]
|
146
|
+
end
|
147
|
+
elsif running > count
|
148
|
+
(running - count).times do |i|
|
149
|
+
index = count + i + 1
|
150
|
+
to_stop << [proc_name, index]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
running_count_by_name.each do |proc_name, count|
|
156
|
+
if not desired_count_by_name.has_key?(proc_name)
|
157
|
+
count.times do |i|
|
158
|
+
to_stop << [proc_name, i]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
to_start.each do |proc_name, index|
|
164
|
+
port = reserve_port
|
165
|
+
fork do
|
166
|
+
Dokuen::Wrapper.new(self, proc_name, index, File.join(config.dokuen_dir, 'ports', port.to_s)).run!
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
to_stop.each do |proc_name, index|
|
171
|
+
pid_file = processes["#{proc_name}.#{index}"]
|
172
|
+
pid = YAML.load(File.read(pid_file))['pid']
|
173
|
+
Process.kill("TERM", pid)
|
174
|
+
end
|
175
|
+
install_nginx_config
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def shutdown(release)
|
180
|
+
with_release_dir(release) do
|
181
|
+
running_processes.each do |proc, pidfile|
|
182
|
+
pid = File.read(pidfile).to_i rescue nil
|
183
|
+
if pid
|
184
|
+
Process.kill("TERM", pid)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def install_nginx_config
|
191
|
+
puts "Installing nginx config"
|
192
|
+
sleep 2
|
193
|
+
@ssl_on = get_env('USE_SSL') ? 'on' : 'off'
|
194
|
+
@listen_port = get_env('USE_SSL') ? 443 : 80
|
195
|
+
conf = Dokuen.template('nginx', binding)
|
196
|
+
File.open(File.join(config.dokuen_dir, "nginx", "#{name}.#{config.base_domain_name}.conf"), "w+") do |f|
|
197
|
+
f.write(conf)
|
198
|
+
end
|
199
|
+
|
200
|
+
sys("sudo #{config.bin_path}/dokuen_restart_nginx")
|
201
|
+
end
|
202
|
+
|
203
|
+
private
|
204
|
+
|
205
|
+
def clone(git_dir, revision)
|
206
|
+
dir = Dir.mktmpdir
|
207
|
+
Dir.chdir(dir) do
|
208
|
+
sys("git clone #{git_dir} .")
|
209
|
+
sys("git checkout -q #{revision}")
|
210
|
+
end
|
211
|
+
dir
|
212
|
+
end
|
213
|
+
|
214
|
+
def sys(command)
|
215
|
+
system(command) or raise "Error running command: #{command}"
|
216
|
+
end
|
217
|
+
|
218
|
+
def with_app_dir
|
219
|
+
Dir.chdir(File.join(config.dokuen_dir, 'apps', name)) do
|
220
|
+
yield
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def with_release_dir(release)
|
225
|
+
Dir.chdir(release) do
|
226
|
+
yield
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def with_current_release
|
231
|
+
with_app_dir do
|
232
|
+
if File.symlink?("current")
|
233
|
+
with_release_dir(File.readlink("current")) do
|
234
|
+
yield
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def running_processes
|
241
|
+
procs = {}
|
242
|
+
Dir.glob(".dokuen/*.pid").map do |pidfile|
|
243
|
+
proc_name = File.basename(pidfile).gsub('.pid', '')
|
244
|
+
proc_name = proc_name.gsub("dokuen.#{name}.", '')
|
245
|
+
procs[proc_name] = pidfile
|
246
|
+
end
|
247
|
+
procs
|
248
|
+
end
|
249
|
+
|
250
|
+
def read_env_dir(dir)
|
251
|
+
vars = {}
|
252
|
+
Dir.glob("#{dir}/*").each do |key|
|
253
|
+
vars[File.basename(key)] = File.read(key).chomp
|
254
|
+
end
|
255
|
+
vars
|
256
|
+
end
|
257
|
+
|
258
|
+
def reserve_port
|
259
|
+
ports_dir = config.dokuen_dir + "/ports"
|
260
|
+
port_range = config.max_port - config.min_port
|
261
|
+
1000.times do
|
262
|
+
port = rand(port_range) + config.min_port
|
263
|
+
path = File.join(ports_dir, port.to_s)
|
264
|
+
if not File.exists?(path)
|
265
|
+
FileUtils.touch(path)
|
266
|
+
return port
|
267
|
+
end
|
268
|
+
end
|
269
|
+
raise "Could not find free port!"
|
270
|
+
end
|
271
|
+
|
272
|
+
def ports
|
273
|
+
_ports = []
|
274
|
+
running_processes.each do |proc_name, pidfile|
|
275
|
+
_ports << YAML.load(File.read(pidfile))['port']
|
276
|
+
end
|
277
|
+
_ports
|
278
|
+
end
|
279
|
+
end
|
data/lib/dokuen/cli.rb
CHANGED
@@ -1,226 +1,163 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "thor"
|
2
|
+
require "thor/shell/basic"
|
3
|
+
require "yaml"
|
4
4
|
|
5
|
-
|
6
|
-
class Cli < Thor
|
7
|
-
include Thor::Actions
|
8
|
-
|
9
|
-
desc "setup", "Set up relevant things. Needs to be run as sudo."
|
10
|
-
def setup
|
11
|
-
raise "Must be run as root" unless Process.uid == 0
|
12
|
-
git_username = ask("What is your git username (usually git)?")
|
13
|
-
gitolite_src = ask("What is the path to your gitolite clone?")
|
14
|
-
say("Installing gitolite command")
|
15
|
-
create_file "#{gitolite_src}/src/commands/dokuen", <<HERE
|
16
|
-
#!/bin/sh
|
17
|
-
/usr/local/bin/dokuen $@
|
18
|
-
HERE
|
19
|
-
File.chmod(0755, "#{gitolite_src}/src/commands/dokuen")
|
20
|
-
say("Installing gitolite hook")
|
21
|
-
hook_path = "/Users/#{git_username}/.gitolite/hooks/common/pre-receive"
|
22
|
-
create_file(hook_path, <<'HERE'
|
23
|
-
#!/usr/bin/env ruby
|
24
|
-
hook = `git config hooks.pre`.chomp
|
25
|
-
|
26
|
-
rev = nil
|
27
|
-
|
28
|
-
STDIN.each do |line|
|
29
|
-
parts = line.split(/\s/)
|
30
|
-
next if parts[2] != "refs/heads/master"
|
31
|
-
rev = parts[1]
|
32
|
-
end
|
33
|
-
|
34
|
-
if hook != ""
|
35
|
-
name = File.basename(ENV['GL_REPO'])
|
36
|
-
cmd = "#{hook} #{name} #{rev}"
|
37
|
-
system(cmd) or raise "Error running pre-hook: #{cmd} returned #{$?}"
|
38
|
-
end
|
39
|
-
HERE
|
40
|
-
)
|
41
|
-
File.chmod(0755, hook_path)
|
42
|
-
say("Creating directories")
|
43
|
-
dirs = [
|
44
|
-
'/usr/local/var/dokuen/env',
|
45
|
-
'/usr/local/var/dokuen/env/_common',
|
46
|
-
'/usr/local/var/dokuen/log',
|
47
|
-
'/usr/local/var/dokuen/nginx',
|
48
|
-
'/usr/local/var/dokuen/build',
|
49
|
-
'/usr/local/var/dokuen/release',
|
50
|
-
]
|
51
|
-
FileUtils.mkdir_p(dirs, :mode => 0775)
|
52
|
-
FileUtils.chown(git_username, 'staff', dirs)
|
53
|
-
|
54
|
-
if yes?("Do you want to set up DNS?")
|
55
|
-
basename = ask("What is your DNS base domain? For example, if have a wildcard CNAME for *.example.com, this would be example.com.")
|
56
|
-
create_file("/usr/local/var/dokuen/env/_common/BASE_DOMAIN", basename)
|
57
|
-
end
|
58
|
-
git_hostname = `hostname`.chomp
|
59
|
-
if no?("Is #{git_hostname} the correct hostname for git remotes?")
|
60
|
-
git_hostname = ask("What hostname should we use instead?")
|
61
|
-
end
|
62
|
-
create_file("/usr/local/var/dokuen/env/_common/DOKUEN_GIT_SERVER", git_hostname)
|
63
|
-
create_file("/usr/local/var/dokuen/env/_common/DOKUEN_GIT_USER", git_username)
|
64
|
-
|
65
|
-
say(<<HERE
|
66
|
-
|
67
|
-
==== IMPORTANT INSTRUCTIONS ====
|
68
|
-
|
69
|
-
In your .gitolite.rc file, in the COMMANDS section, add the following:
|
70
|
-
|
71
|
-
'dokuen' => 1
|
5
|
+
class Dokuen::CLI < Thor
|
72
6
|
|
73
|
-
|
7
|
+
include Thor::Actions
|
74
8
|
|
75
|
-
|
76
|
-
|
77
|
-
RW+ = CREATOR
|
78
|
-
config hooks.pre = "/usr/local/bin/dokuen deploy"
|
9
|
+
def initialize(*args)
|
10
|
+
super(*args)
|
79
11
|
|
80
|
-
|
12
|
+
if not options[:config].nil?
|
13
|
+
@config = Dokuen::Config.new(options[:config])
|
14
|
+
end
|
15
|
+
end
|
81
16
|
|
82
|
-
|
17
|
+
class_option :application, :type => :string, :desc => "Application name"
|
18
|
+
class_option :config, :type => :string, :desc => "Configuration file"
|
19
|
+
class_option :debug, :type => :boolean, :desc => "Show backtraces"
|
20
|
+
|
21
|
+
desc "setup DIR", "set up dokuen in the given directory"
|
22
|
+
method_option :gituser, :desc => "Username of git user", :default => 'git'
|
23
|
+
method_option :gitgroup, :desc => "Group of git user", :default => 'staff'
|
24
|
+
method_option :appuser, :desc => "Username of app user", :default => 'dokuen'
|
25
|
+
method_option :gitolite, :desc => "Path to gitolite directory", :default => 'GITUSER_HOME/gitolite'
|
26
|
+
method_option :platform, :desc => "Which platform to install. Can be 'mac', 'ubuntu', or 'centos'", :default => 'mac'
|
27
|
+
def setup(dir)
|
28
|
+
|
29
|
+
@current_script = File.expand_path($0)
|
30
|
+
@current_bin_path = File.dirname(@current_script)
|
31
|
+
|
32
|
+
Dir.chdir(dir) do
|
33
|
+
setup_dirs
|
34
|
+
setup_bin
|
35
|
+
setup_gitolite
|
36
|
+
write_config
|
37
|
+
install_boot_script
|
38
|
+
puts Dokuen.template('instructions', binding)
|
39
|
+
end
|
40
|
+
end
|
83
41
|
|
84
|
-
|
42
|
+
desc "create", "create application"
|
43
|
+
def create
|
44
|
+
Dokuen::Application.new(options[:application], @config).create
|
45
|
+
puts "git remote add dokuen #{@config.git_user}@#{@config.git_server}:apps/#{options[:application]}.git"
|
46
|
+
end
|
85
47
|
|
86
|
-
|
48
|
+
desc "deploy", "deploy application", :hide => true
|
49
|
+
method_option :rev, :desc => "Revision to deploy"
|
50
|
+
def deploy
|
51
|
+
ENV['GIT_DIR'] = nil
|
52
|
+
ENV['PATH'] = "#{@config.bin_path}:#{ENV['PATH']}"
|
53
|
+
ENV.each do |k,v|
|
54
|
+
puts "#{k}=#{v}"
|
55
|
+
end
|
56
|
+
Dokuen::Application.new(options[:application], @config).deploy(options[:rev])
|
57
|
+
end
|
87
58
|
|
88
|
-
|
89
|
-
|
59
|
+
desc "scale SCALE_SPEC", "scale to the given spec"
|
60
|
+
def scale(spec)
|
61
|
+
app = Dokuen::Application.new(options[:application], @config)
|
62
|
+
app.set_env('DOKUEN_SCALE', spec)
|
63
|
+
app.scale
|
64
|
+
end
|
90
65
|
|
66
|
+
desc "config", "show the config for the given app"
|
67
|
+
def config
|
68
|
+
app = Dokuen::Application.new(options[:application], @config)
|
69
|
+
app.env.each do |key, val|
|
70
|
+
puts "#{key}=#{val}"
|
91
71
|
end
|
72
|
+
end
|
92
73
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
FileUtils.mkdir_p(Dokuen.dir("build", app))
|
100
|
-
puts "Created new application named #{app}"
|
101
|
-
puts "Git remote: #{Dokuen.base_clone_url}:apps/#{app}.git"
|
74
|
+
desc "config_set VARS", "set some config variables"
|
75
|
+
def config_set(*vars)
|
76
|
+
app = Dokuen::Application.new(options[:application], @config)
|
77
|
+
vars.each do |var|
|
78
|
+
key, val = var.chomp.split('=', 2)
|
79
|
+
app.set_env(key, val)
|
102
80
|
end
|
81
|
+
end
|
103
82
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
deploy.install_launch_daemon
|
110
|
-
deploy.install_nginx_conf
|
111
|
-
puts "App restarted"
|
83
|
+
desc "config_delete VARS", "delete some config variables"
|
84
|
+
def config_delete(*vars)
|
85
|
+
app = Dokuen::Application.new(options[:application], @config)
|
86
|
+
vars.each do |var|
|
87
|
+
app.delete_env(var)
|
112
88
|
end
|
89
|
+
end
|
113
90
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
base_port = ENV['PORT'].to_i - 200
|
121
|
-
scale = ENV['DOKUEN_SCALE'].nil? ? "" : "-c #{ENV['DOKUEN_SCALE']}"
|
122
|
-
Dokuen.sys("foreman start #{scale} -p #{base_port}")
|
123
|
-
end
|
91
|
+
desc "boot", "Scale all of the current applications"
|
92
|
+
def boot
|
93
|
+
Dir.glob("#{@config.dokuen_dir}/apps/*") do |appdir|
|
94
|
+
next if File.basename(appdir)[0] == '.'
|
95
|
+
app = Dokuen::Application.new(File.basename(appdir), @config)
|
96
|
+
app.scale
|
124
97
|
end
|
98
|
+
end
|
125
99
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
100
|
+
private
|
101
|
+
|
102
|
+
def setup_dirs
|
103
|
+
dirs = [
|
104
|
+
'apps',
|
105
|
+
'env',
|
106
|
+
'ports',
|
107
|
+
'nginx',
|
108
|
+
'bin'
|
109
|
+
]
|
135
110
|
|
136
|
-
|
137
|
-
|
138
|
-
check_app(app)
|
139
|
-
read_env(app)
|
140
|
-
Dokuen::Deploy.new(app, rev).run
|
141
|
-
puts "App #{app} deployed"
|
111
|
+
dirs.each do |dir|
|
112
|
+
empty_directory(File.join(Dir.getwd, dir))
|
142
113
|
end
|
143
114
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
check_app(app)
|
148
|
-
read_env(app)
|
115
|
+
FileUtils.chown(options[:gituser], options[:gitgroup], dirs)
|
116
|
+
FileUtils.chmod(0777, ['apps', 'ports', 'nginx'])
|
117
|
+
end
|
149
118
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
119
|
+
def setup_bin
|
120
|
+
@script_path = File.expand_path("bin/dokuen")
|
121
|
+
@deploy_script_path = File.expand_path("bin/dokuen-deploy")
|
122
|
+
write_template(@script_path, "bin_command", 0755)
|
123
|
+
write_template(@deploy_script_path, "deploy_command", 0755)
|
124
|
+
end
|
155
125
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
check_app(app)
|
160
|
-
case subcommand
|
161
|
-
when "set"
|
162
|
-
set_vars(app)
|
163
|
-
restart_app(app)
|
164
|
-
when "delete"
|
165
|
-
delete_vars(app)
|
166
|
-
restart_app(app)
|
167
|
-
else
|
168
|
-
show_vars(app)
|
169
|
-
end
|
170
|
-
end
|
126
|
+
def setup_gitolite
|
127
|
+
githome = File.expand_path("~#{options[:gituser]}")
|
128
|
+
gitolite = options[:gitolite].gsub('GITUSER_HOME', githome)
|
171
129
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
Dokuen.sys("/usr/local/bin/mason buildpacks:install #{url}")
|
176
|
-
end
|
130
|
+
write_template("#{gitolite}/src/commands/dokuen", 'gitolite_command', 0755)
|
131
|
+
write_template("#{githome}/.gitolite/hooks/common/pre-receive", 'pre_receive_hook', 0755)
|
132
|
+
end
|
177
133
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
134
|
+
def write_config
|
135
|
+
config = {
|
136
|
+
'base_domain_name' => 'dokuen',
|
137
|
+
'git_server' => `hostname`.chomp,
|
138
|
+
'git_user' => options[:gituser],
|
139
|
+
'app_user' => options[:appuser],
|
140
|
+
'min_port' => 5000,
|
141
|
+
'max_port' => 6000,
|
142
|
+
'bin_path' => @current_bin_path,
|
143
|
+
'dokuen_dir' => File.expand_path('.')
|
144
|
+
}
|
145
|
+
|
146
|
+
File.open("./dokuen.conf", 'w+') do |f|
|
147
|
+
YAML.dump(config, f)
|
182
148
|
end
|
149
|
+
|
150
|
+
end
|
183
151
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
152
|
+
def write_template(filename, template, mode=0644)
|
153
|
+
t = Dokuen.template(template, binding)
|
154
|
+
create_file(filename, t)
|
155
|
+
File.chmod(mode, filename)
|
156
|
+
end
|
188
157
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
vars = options[:vars]
|
193
|
-
vars.each do |var|
|
194
|
-
key, val = var.split(/\=/)
|
195
|
-
Dokuen.set_env(app, key, val)
|
196
|
-
end
|
197
|
-
puts "Vars set"
|
198
|
-
end
|
199
|
-
|
200
|
-
def delete_vars(app)
|
201
|
-
vars = options[:vars]
|
202
|
-
|
203
|
-
vars.each do |var|
|
204
|
-
Dokuen.rm_env(app, var)
|
205
|
-
end
|
206
|
-
puts "Vars removed"
|
207
|
-
end
|
208
|
-
|
209
|
-
def show_vars(app)
|
210
|
-
read_env(app)
|
211
|
-
ENV.each do |key, val|
|
212
|
-
puts "#{key}=#{val}"
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def read_env(app)
|
217
|
-
Dokuen.read_env("_common")
|
218
|
-
Dokuen.read_env(app)
|
219
|
-
end
|
220
|
-
|
221
|
-
def check_app(app)
|
222
|
-
Dokuen.app_exists?(app) or raise "App '#{app}' does not exist!"
|
223
|
-
end
|
224
|
-
end
|
158
|
+
def install_boot_script
|
159
|
+
filename, template_name = Dokuen::Platform.boot_script(options[:platform])
|
160
|
+
write_template(filename, template_name)
|
225
161
|
end
|
162
|
+
|
226
163
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
class Dokuen::Config
|
4
|
+
def initialize(path)
|
5
|
+
@path = path
|
6
|
+
@config = {}
|
7
|
+
read_config
|
8
|
+
end
|
9
|
+
|
10
|
+
def read_config
|
11
|
+
@config = YAML.load(File.read(@path))
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(m, *args, &block)
|
15
|
+
str_meth = m.to_s
|
16
|
+
if @config.has_key? str_meth
|
17
|
+
@config[str_meth]
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Dokuen
|
2
|
+
module Platform
|
3
|
+
|
4
|
+
def self.boot_script(platform)
|
5
|
+
case platform
|
6
|
+
when 'mac'
|
7
|
+
return "/Library/LaunchDaemons/dokuen.plist", "mac_launchdaemon"
|
8
|
+
when 'ubuntu'
|
9
|
+
return "/etc/init/dokuen", "ubuntu_upstart"
|
10
|
+
else
|
11
|
+
raise "Unknow platform: #{platform}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
data/lib/dokuen/version.rb
CHANGED
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'foreman'
|
2
|
+
require 'foreman/procfile'
|
3
|
+
require 'foreman/process'
|
4
|
+
|
5
|
+
class Dokuen::Wrapper
|
6
|
+
|
7
|
+
attr_reader :release_dir, :app, :proc, :index, :portfile
|
8
|
+
|
9
|
+
def initialize(app, proc, index, portfile)
|
10
|
+
@release_dir = Dir.getwd
|
11
|
+
@app = app
|
12
|
+
@proc = proc
|
13
|
+
@index = index
|
14
|
+
@portfile = portfile
|
15
|
+
end
|
16
|
+
|
17
|
+
def run!
|
18
|
+
return if daemonize! == nil
|
19
|
+
load_env
|
20
|
+
loop do
|
21
|
+
run_loop
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def procname
|
26
|
+
"dokuen.#{app.name}.#{proc}.#{index}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def procdir
|
30
|
+
File.join(release_dir, '.dokuen')
|
31
|
+
end
|
32
|
+
|
33
|
+
def pidfile
|
34
|
+
File.join(procdir, "#{procname}.pid")
|
35
|
+
end
|
36
|
+
|
37
|
+
def outfile
|
38
|
+
File.join(procdir, "#{procname}.out")
|
39
|
+
end
|
40
|
+
|
41
|
+
def errfile
|
42
|
+
File.join(procdir, "#{procname}.err")
|
43
|
+
end
|
44
|
+
|
45
|
+
def port
|
46
|
+
File.basename(portfile).to_i
|
47
|
+
end
|
48
|
+
|
49
|
+
def daemonize!
|
50
|
+
pf = File.join(pidfile)
|
51
|
+
raise "Process already running!" if File.exists?(pf)
|
52
|
+
|
53
|
+
return unless do_fork.nil?
|
54
|
+
write_pidfile
|
55
|
+
set_procname
|
56
|
+
redirect
|
57
|
+
end
|
58
|
+
|
59
|
+
def redirect
|
60
|
+
$stdin.reopen("/dev/null")
|
61
|
+
$stdout.sync = $stderr.sync = true
|
62
|
+
$stdout.reopen(File.new(outfile, "a"))
|
63
|
+
$stderr.reopen(File.new(errfile, "a"))
|
64
|
+
end
|
65
|
+
|
66
|
+
def write_pidfile
|
67
|
+
File.open(pidfile, "w+") do |f|
|
68
|
+
f.write(YAML.dump({'pid' => Process.pid, 'port' => port}))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_procname
|
73
|
+
$0 = procname
|
74
|
+
end
|
75
|
+
|
76
|
+
def do_fork
|
77
|
+
raise 'first fork failed' if (pid = fork) == -1
|
78
|
+
exit unless pid.nil?
|
79
|
+
Process.setsid
|
80
|
+
raise 'second fork failed' if (pid = fork) == -1
|
81
|
+
exit unless pid.nil?
|
82
|
+
end
|
83
|
+
|
84
|
+
def load_env
|
85
|
+
app.env.each do |key, val|
|
86
|
+
ENV[key] = val
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def run_loop
|
91
|
+
reader, writer = (IO.method(:pipe).arity == 0 ? IO.pipe : IO.pipe("BINARY"))
|
92
|
+
procfile = Foreman::Procfile.new("Procfile")
|
93
|
+
entry = procfile[proc]
|
94
|
+
process = Foreman::Process.new(entry, index.to_i, port.to_i)
|
95
|
+
log_path = "../../logs/#{procname}"
|
96
|
+
log_file = File.open(log_path, 'a')
|
97
|
+
|
98
|
+
Signal.trap("USR2") do
|
99
|
+
process.kill("TERM")
|
100
|
+
end
|
101
|
+
|
102
|
+
Signal.trap("TERM") do
|
103
|
+
if not process.kill(9)
|
104
|
+
raise "Failed to kill process #{process.pid}"
|
105
|
+
end
|
106
|
+
File.delete(pidfile)
|
107
|
+
File.delete("../../../../ports/#{port}")
|
108
|
+
exit! 0
|
109
|
+
end
|
110
|
+
|
111
|
+
process.run(writer, release_dir, {})
|
112
|
+
thread = Thread.new do
|
113
|
+
loop do
|
114
|
+
data = reader.gets
|
115
|
+
next unless data
|
116
|
+
ps, message = data.split(",", 2)
|
117
|
+
log_file.puts("[#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}][#{ps}] #{message}")
|
118
|
+
log_file.flush
|
119
|
+
end
|
120
|
+
end
|
121
|
+
Process.wait(process.pid)
|
122
|
+
thread.exit
|
123
|
+
reader.close
|
124
|
+
writer.close
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
data/lib/dokuen.rb
CHANGED
@@ -1,46 +1,19 @@
|
|
1
|
-
require
|
2
|
-
require 'dokuen/deploy'
|
1
|
+
require "erb"
|
3
2
|
|
4
3
|
module Dokuen
|
5
|
-
def self.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
File.join(parts)
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.sys(command)
|
16
|
-
system(command) or raise "Error running #{command}"
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.read_env(name)
|
20
|
-
env_dir = Dokuen.dir('env', name)
|
21
|
-
Dir.glob("#{env_dir}/*") do |var|
|
22
|
-
var_name = File.basename(var)
|
23
|
-
ENV[var_name] = File.open(var).read().chomp()
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.set_env(name, key, value)
|
28
|
-
env_dir = Dokuen.dir('env', name)
|
29
|
-
File.open(File.join(env_dir, key), "w+") do |f|
|
30
|
-
f.write value
|
4
|
+
def self.template(name, bind)
|
5
|
+
path = File.expand_path("../../data/templates/#{name}.erb", __FILE__)
|
6
|
+
if File.exists?(path)
|
7
|
+
t = ERB.new(File.read(path))
|
8
|
+
t.result(bind)
|
9
|
+
else
|
10
|
+
raise "Unknown template: #{name}"
|
31
11
|
end
|
32
12
|
end
|
33
|
-
|
34
|
-
def self.rm_env(name, key)
|
35
|
-
env_dir = Dokuen.dir('env', name)
|
36
|
-
File.delete(File.join(env_dir, key))
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.base_clone_url
|
40
|
-
"#{ENV['DOKUEN_GIT_USER']}@#{ENV['DOKUEN_GIT_SERVER']}"
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.app_exists?(name)
|
44
|
-
File.exists?(Dokuen.dir('env', name))
|
45
|
-
end
|
46
13
|
end
|
14
|
+
|
15
|
+
require "dokuen/cli"
|
16
|
+
require "dokuen/config"
|
17
|
+
require "dokuen/application"
|
18
|
+
require "dokuen/wrapper"
|
19
|
+
require "dokuen/platform"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dokuen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-29 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -91,11 +91,22 @@ files:
|
|
91
91
|
- bin/dokuen
|
92
92
|
- bin/dokuen_install_launchdaemon
|
93
93
|
- bin/dokuen_restart_nginx
|
94
|
+
- data/templates/bin_command.erb
|
95
|
+
- data/templates/deploy_command.erb
|
96
|
+
- data/templates/gitolite_command.erb
|
97
|
+
- data/templates/instructions.erb
|
98
|
+
- data/templates/mac_launchdaemon.erb
|
99
|
+
- data/templates/nginx.erb
|
100
|
+
- data/templates/pre_receive_hook.erb
|
101
|
+
- data/templates/ubuntu_upstart.erb
|
94
102
|
- dokuen.gemspec
|
95
103
|
- lib/dokuen.rb
|
104
|
+
- lib/dokuen/application.rb
|
96
105
|
- lib/dokuen/cli.rb
|
97
|
-
- lib/dokuen/
|
106
|
+
- lib/dokuen/config.rb
|
107
|
+
- lib/dokuen/platform.rb
|
98
108
|
- lib/dokuen/version.rb
|
109
|
+
- lib/dokuen/wrapper.rb
|
99
110
|
homepage: https://github.com/peterkeen/dokuen
|
100
111
|
licenses: []
|
101
112
|
post_install_message:
|
data/lib/dokuen/deploy.rb
DELETED
@@ -1,173 +0,0 @@
|
|
1
|
-
require 'tmpdir'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'time'
|
4
|
-
require 'erb'
|
5
|
-
|
6
|
-
module Dokuen
|
7
|
-
class Deploy
|
8
|
-
|
9
|
-
def initialize(app, rev, release_dir=nil)
|
10
|
-
@app = app || app_name_from_env
|
11
|
-
@rev = rev
|
12
|
-
ENV['GIT_DIR'] = nil
|
13
|
-
ENV['PATH'] = "/usr/local/bin:#{ENV['PATH']}"
|
14
|
-
if release_dir
|
15
|
-
@release_dir = release_dir
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def run
|
20
|
-
read_app_env
|
21
|
-
make_dirs
|
22
|
-
clone
|
23
|
-
build
|
24
|
-
install_launch_daemon
|
25
|
-
install_nginx_conf
|
26
|
-
end
|
27
|
-
|
28
|
-
def read_app_env
|
29
|
-
Dokuen.read_env('_common')
|
30
|
-
Dokuen.read_env(@app)
|
31
|
-
end
|
32
|
-
|
33
|
-
def make_dirs
|
34
|
-
FileUtils.mkdir_p([
|
35
|
-
env_dir,
|
36
|
-
release_dir,
|
37
|
-
cache_dir,
|
38
|
-
nginx_dir
|
39
|
-
])
|
40
|
-
end
|
41
|
-
|
42
|
-
def clone
|
43
|
-
Dokuen.sys("git clone #{git_dir} #{clone_dir}")
|
44
|
-
Dir.chdir(clone_dir)
|
45
|
-
Dokuen.sys("git checkout #{@rev}")
|
46
|
-
end
|
47
|
-
|
48
|
-
def build
|
49
|
-
Dokuen.sys("mason build #{clone_dir} #{buildpack} -o #{release_dir} -c #{cache_dir}")
|
50
|
-
Dokuen.sys("chmod -R a+r #{release_dir}")
|
51
|
-
Dokuen.sys("find #{release_dir} -type d -exec chmod a+x {} \\;")
|
52
|
-
Dokuen.set_env(@app, 'DOKUEN_RELEASE_DIR', release_dir)
|
53
|
-
|
54
|
-
hook = ENV['DOKUEN_AFTER_BUILD']
|
55
|
-
if not hook.nil?
|
56
|
-
Dir.chdir release_dir do
|
57
|
-
Dokuen.sys("foreman run #{hook}")
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def buildpack
|
63
|
-
if not ENV['BUILDPACK_URL'].nil?
|
64
|
-
"-b #{ENV['BUILDPACK_URL']}"
|
65
|
-
else
|
66
|
-
""
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def install_launch_daemon
|
71
|
-
t = ERB.new(launch_daemon_template)
|
72
|
-
plist_path = File.join(release_dir, "dokuen.#{@app}.plist")
|
73
|
-
File.open(plist_path, "w+") do |f|
|
74
|
-
f.write(t.result(binding))
|
75
|
-
end
|
76
|
-
Dokuen.sys("sudo /usr/local/bin/dokuen_install_launchdaemon #{plist_path}")
|
77
|
-
end
|
78
|
-
|
79
|
-
def install_nginx_conf
|
80
|
-
t = ERB.new(nginx_template)
|
81
|
-
File.open(File.join(nginx_dir, "#{@app}.#{base_domain}.conf"), "w+") do |f|
|
82
|
-
f.write(t.result(binding))
|
83
|
-
end
|
84
|
-
Dokuen.sys("sudo /usr/local/bin/dokuen_restart_nginx")
|
85
|
-
end
|
86
|
-
|
87
|
-
def base_domain
|
88
|
-
ENV['BASE_DOMAIN'] || 'dokuen'
|
89
|
-
end
|
90
|
-
|
91
|
-
def app_name_from_env
|
92
|
-
File.basename(ENV['GL_REPO']).gsub(/\.git$/, '')
|
93
|
-
end
|
94
|
-
|
95
|
-
def env_dir
|
96
|
-
Dokuen.dir("env", @app)
|
97
|
-
end
|
98
|
-
|
99
|
-
def clone_dir
|
100
|
-
@clone_dir ||= Dir.mktmpdir
|
101
|
-
end
|
102
|
-
|
103
|
-
def git_dir
|
104
|
-
@git_dir || Dir.getwd
|
105
|
-
end
|
106
|
-
|
107
|
-
def release_dir
|
108
|
-
@now = Time.now().utc().strftime("%Y%m%dT%H%M%S")
|
109
|
-
@release_dir ||= File.join(Dokuen.dir('release', @app), @now)
|
110
|
-
end
|
111
|
-
|
112
|
-
def cache_dir
|
113
|
-
Dokuen.dir('build', @app)
|
114
|
-
end
|
115
|
-
|
116
|
-
def nginx_dir
|
117
|
-
Dokuen.dir('nginx')
|
118
|
-
end
|
119
|
-
|
120
|
-
def server_port
|
121
|
-
ENV['USE_SSL'] ? "443" : "80"
|
122
|
-
end
|
123
|
-
|
124
|
-
def ssl_on
|
125
|
-
ENV['USE_SSL'] ? "on" : "off"
|
126
|
-
end
|
127
|
-
|
128
|
-
def launch_daemon_template
|
129
|
-
<<HERE
|
130
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
131
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
132
|
-
<plist version="1.0">
|
133
|
-
<dict>
|
134
|
-
<key>KeepAlive</key>
|
135
|
-
<true/>
|
136
|
-
<key>Label</key>
|
137
|
-
<string>dokuen.<%= @app %></string>
|
138
|
-
<key>ProgramArguments</key>
|
139
|
-
<array>
|
140
|
-
<string>/usr/local/bin/dokuen</string>
|
141
|
-
<string>start_app</string>
|
142
|
-
<string><%= @app %></string>
|
143
|
-
</array>
|
144
|
-
<key>RunAtLoad</key>
|
145
|
-
<true/>
|
146
|
-
<key>UserName</key>
|
147
|
-
<string>peter</string>
|
148
|
-
<key>WorkingDirectory</key>
|
149
|
-
<string>/usr/local/var/dokuen</string>
|
150
|
-
<key>StandardOutPath</key>
|
151
|
-
<string>/usr/local/var/dokuen/log/<%= @app %>.log</string>
|
152
|
-
<key>StandardErrorPath</key>
|
153
|
-
<string>/usr/local/var/dokuen/log/<%= @app %>.log</string>
|
154
|
-
</dict>
|
155
|
-
</plist>
|
156
|
-
HERE
|
157
|
-
end
|
158
|
-
|
159
|
-
def nginx_template
|
160
|
-
<<HERE
|
161
|
-
server {
|
162
|
-
server_name <%= @app %>.<%= base_domain %>;
|
163
|
-
listen <%= server_port %>;
|
164
|
-
ssl <%= ssl_on %>;
|
165
|
-
location / {
|
166
|
-
proxy_pass http://localhost:<%= ENV['PORT'] %>/;
|
167
|
-
}
|
168
|
-
}
|
169
|
-
HERE
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|