appserver 0.0.1 → 0.0.2
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.
- data/.gitignore +3 -0
- data/README.md +30 -9
- data/Rakefile +31 -0
- data/bin/appserver +9 -6
- data/lib/appserver.rb +10 -6
- data/lib/appserver/app.rb +106 -65
- data/lib/appserver/appserver.conf.rb +126 -0
- data/lib/appserver/command.rb +38 -10
- data/lib/appserver/configurator.rb +38 -0
- data/lib/appserver/logrotate.rb +46 -0
- data/lib/appserver/monit.rb +45 -0
- data/lib/appserver/nginx.rb +71 -0
- data/lib/appserver/repository.rb +80 -21
- data/lib/appserver/server_dir.rb +100 -0
- data/lib/appserver/unicorn.conf.rb +23 -27
- data/lib/appserver/utils.rb +24 -15
- data/test/apps/rack-simple/config.ru +7 -0
- data/test/apps/sinatra/Gemfile +4 -0
- data/test/apps/sinatra/config.ru +2 -0
- data/test/apps/sinatra/hello.rb +9 -0
- data/test/apps/sinatra/views/index.erb +1 -0
- data/test/helper.rb +49 -0
- data/test/unit/test_app.rb +72 -0
- data/test/unit/test_appserver.rb +26 -0
- data/test/unit/test_command.rb +64 -0
- data/test/unit/test_configurator.rb +116 -0
- data/test/unit/test_logrotate.rb +14 -0
- data/test/unit/test_monit.rb +13 -0
- data/test/unit/test_nginx.rb +13 -0
- data/test/unit/test_repository.rb +50 -0
- data/test/unit/test_server_dir.rb +121 -0
- data/test/unit/test_unicorn_conf.rb +58 -0
- data/test/unit/test_utils.rb +36 -0
- metadata +84 -11
- data/lib/appserver/appserver.yml +0 -85
- data/lib/appserver/server.rb +0 -136
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestLogrotate < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_write_config
|
6
|
+
in_server_dir do |server_dir|
|
7
|
+
create_app('rack-simple', 'apps/hello')
|
8
|
+
create_app('rack-simple', 'apps/hello2')
|
9
|
+
assert !File.exist?('logrotate.conf')
|
10
|
+
Appserver::Logrotate.write_config(server_dir)
|
11
|
+
assert File.exist?('logrotate.conf')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestMonit < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_write_config
|
6
|
+
in_server_dir do |server_dir|
|
7
|
+
create_app('rack-simple', 'apps/hello')
|
8
|
+
assert !File.exist?('monitrc')
|
9
|
+
Appserver::Monit.write_config(server_dir)
|
10
|
+
assert File.exist?('monitrc')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestNginx < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_write_config
|
6
|
+
in_server_dir do |server_dir|
|
7
|
+
create_app('rack-simple', 'apps/hello')
|
8
|
+
assert !File.exist?('nginx.conf')
|
9
|
+
Appserver::Nginx.write_config(server_dir)
|
10
|
+
assert File.exist?('nginx.conf')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestRepository < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
# FIXME: This is currently needed to silence appserver output during tests :(
|
7
|
+
Appserver::Repository.any_instance.stubs(:puts)
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_valid
|
11
|
+
in_server_dir do |server_dir|
|
12
|
+
create_app_repo 'rack-simple', 'hello.git'
|
13
|
+
repo = Appserver::Repository.new(server_dir, 'hello.git', {})
|
14
|
+
assert repo.valid?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_install_hook
|
19
|
+
in_server_dir do |server_dir|
|
20
|
+
create_app_repo 'rack-simple', 'hello.git'
|
21
|
+
repo = Appserver::Repository.new(server_dir, 'hello.git', {})
|
22
|
+
repo.install_hook
|
23
|
+
assert File.executable?('hello.git/hooks/update')
|
24
|
+
assert File.readlines('hello.git/hooks/update').grep(/appserver.*deploy/).size == 1
|
25
|
+
repo.install_hook # Try it a second time
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_deploy
|
30
|
+
in_server_dir do |server_dir|
|
31
|
+
create_app_repo 'rack-simple', 'hello.git'
|
32
|
+
repo = Appserver::Repository.new(server_dir, 'hello.git', {})
|
33
|
+
assert !server_dir.app('hello').exist?
|
34
|
+
repo.deploy
|
35
|
+
assert server_dir.app('hello').exist? && server_dir.app('hello').rack?
|
36
|
+
repo.deploy # Try it a second time
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_deploy_with_gemfile
|
41
|
+
in_server_dir do |server_dir|
|
42
|
+
create_app_repo 'sinatra', 'hello.git'
|
43
|
+
repo = Appserver::Repository.new(server_dir, 'hello.git', {})
|
44
|
+
repo.expects(:system).with { |cmd| cmd =~ /bundle install/ }.at_least_once
|
45
|
+
repo.deploy
|
46
|
+
assert File.exist?(server_dir.app('hello').gem_file)
|
47
|
+
repo.deploy # Try it a second time
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestServerDir < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_discover_raises_error_if_not_found
|
6
|
+
in_empty_dir do
|
7
|
+
assert_raise Appserver::NotInitializedError do
|
8
|
+
Appserver::ServerDir.discover
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_discover_finds_current_dir
|
14
|
+
in_empty_dir do
|
15
|
+
Appserver::ServerDir.init('.', :force => true)
|
16
|
+
server_dir = Appserver::ServerDir.discover
|
17
|
+
assert_kind_of Appserver::ServerDir, server_dir
|
18
|
+
assert_equal Dir.pwd, server_dir.path
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_discover_finds_parent_dir
|
23
|
+
in_empty_dir do
|
24
|
+
Appserver::ServerDir.init('.', :force => true)
|
25
|
+
Dir.mkdir('foo')
|
26
|
+
Dir.chdir('foo') do
|
27
|
+
server_dir = Appserver::ServerDir.discover
|
28
|
+
assert_kind_of Appserver::ServerDir, server_dir
|
29
|
+
assert_equal File.expand_path('..'), server_dir.path
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_init_creates_config_file_and_subdirs
|
35
|
+
in_empty_dir do
|
36
|
+
assert_kind_of Appserver::ServerDir, Appserver::ServerDir.init('.', :force => true)
|
37
|
+
assert File.exist?(Appserver::ServerDir::CONFIG_FILE_NAME)
|
38
|
+
assert File.directory?('apps')
|
39
|
+
assert File.directory?('tmp')
|
40
|
+
assert File.directory?('log')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_init_creates_directory
|
45
|
+
in_empty_dir do
|
46
|
+
assert_kind_of Appserver::ServerDir, Appserver::ServerDir.init('foo/bar/somewhere')
|
47
|
+
assert File.exist?("foo/bar/somewhere/#{Appserver::ServerDir::CONFIG_FILE_NAME}")
|
48
|
+
assert File.directory?('foo/bar/somewhere/apps')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_init_fails_if_directory_exists
|
53
|
+
in_empty_dir do
|
54
|
+
Dir.mkdir('foo')
|
55
|
+
assert_raise Appserver::DirectoryAlreadyExistError do
|
56
|
+
Appserver::ServerDir.init('foo')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_init_works_if_directory_exists_but_forced
|
62
|
+
in_empty_dir do
|
63
|
+
Appserver::ServerDir.init('foo')
|
64
|
+
assert_nothing_raised do
|
65
|
+
assert_kind_of Appserver::ServerDir, Appserver::ServerDir.init('foo', :force => true)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_new_works_with_non_existing_directory
|
71
|
+
in_empty_dir do
|
72
|
+
assert_nothing_raised do
|
73
|
+
Appserver::ServerDir.new('foo/bar')
|
74
|
+
assert !File.exist?('foo')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_new_works_with_empty_config_file
|
80
|
+
in_empty_dir do
|
81
|
+
FileUtils.touch Appserver::ServerDir::CONFIG_FILE_NAME
|
82
|
+
assert_nothing_raised do
|
83
|
+
Appserver::ServerDir.new('.')
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_app_creates_the_named_app_only_once
|
89
|
+
in_server_dir do |server_dir|
|
90
|
+
Appserver::App.expects(:new).returns(stub('App')).once
|
91
|
+
assert_not_nil server_dir.app('foo')
|
92
|
+
assert_not_nil server_dir.app('foo')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_apps_returns_apps_for_every_normal_dir
|
97
|
+
in_server_dir do |server_dir|
|
98
|
+
['apps/foo', 'apps/bar', 'apps/bar.old', 'apps/bar.new', 'apps/junk'].each do |path|
|
99
|
+
create_app('rack-simple', path)
|
100
|
+
end
|
101
|
+
assert_equal ['bar', 'foo', 'junk'], server_dir.apps.map { |app| app.name }.sort
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_repository_creates_the_named_repository_only_once
|
106
|
+
in_server_dir do |server_dir|
|
107
|
+
Appserver::Repository.expects(:new).returns(stub('Repository')).once
|
108
|
+
assert_not_nil server_dir.repository('/var/git/foo.git')
|
109
|
+
assert_not_nil server_dir.repository('/var/git/foo.git')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_write_configs
|
114
|
+
in_server_dir do |server_dir|
|
115
|
+
Appserver::Monit.expects(:write_config).with(server_dir)
|
116
|
+
Appserver::Nginx.expects(:write_config).with(server_dir)
|
117
|
+
Appserver::Logrotate.expects(:write_config).with(server_dir)
|
118
|
+
server_dir.write_configs
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'unicorn'
|
3
|
+
require 'etc'
|
4
|
+
|
5
|
+
class TestUnicornConf < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_unicorn_configuration
|
8
|
+
in_server_dir do |server_dir|
|
9
|
+
create_app('rack-simple', 'apps/hello')
|
10
|
+
app = server_dir.app('hello')
|
11
|
+
Appserver::App.any_instance.expects(:user => Etc.getlogin).at_least_once
|
12
|
+
Appserver::App.any_instance.expects(:setup_env!)
|
13
|
+
Unicorn::Configurator.any_instance.expects(:working_directory).with(app.path)
|
14
|
+
Unicorn::Configurator.any_instance.expects(:stderr_path).with(app.server_log)
|
15
|
+
Unicorn::Configurator.any_instance.expects(:stdout_path).with(app.server_log)
|
16
|
+
Unicorn::Configurator.any_instance.expects(:pid).with(app.pid_file)
|
17
|
+
Unicorn::Configurator.any_instance.expects(:listen).with('unix:' + app.socket, :backlog => 64)
|
18
|
+
Unicorn::Configurator.any_instance.expects(:user).with(app.user, app.group)
|
19
|
+
Unicorn::Configurator.any_instance.expects(:worker_processes).with(app.instances)
|
20
|
+
Unicorn::Configurator.any_instance.expects(:preload_app).with(app.preload)
|
21
|
+
Unicorn::Configurator.any_instance.expects(:timeout).with(30)
|
22
|
+
Unicorn::Configurator.any_instance.expects(:before_fork)
|
23
|
+
Unicorn::Configurator.any_instance.expects(:after_fork)
|
24
|
+
Unicorn::HttpServer::START_CTX[:argv] = [app.rack_config]
|
25
|
+
Unicorn::HttpServer.new(Unicorn.builder(app.rack_config, {}), :config_file => app.unicorn_config)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def wait_unicorn_ready (app)
|
30
|
+
50.times do
|
31
|
+
return if File.exist?(app.server_log) && File.readlines(app.server_log).grep(/master process ready/)[0]
|
32
|
+
sleep 0.2
|
33
|
+
end
|
34
|
+
raise 'Unicorn did not become ready'
|
35
|
+
end
|
36
|
+
|
37
|
+
def assert_shutdown (pid)
|
38
|
+
assert_nothing_raised { Process.kill(:TERM, pid) }
|
39
|
+
status = nil
|
40
|
+
assert_nothing_raised { pid, status = Process.waitpid2(pid) }
|
41
|
+
assert status.success?, 'exited successfully'
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_unicorn_server
|
45
|
+
in_server_dir do |server_dir|
|
46
|
+
create_app('rack-simple', 'apps/hello')
|
47
|
+
app = server_dir.app('hello')
|
48
|
+
pid = fork { app.start_server }
|
49
|
+
wait_unicorn_ready(app)
|
50
|
+
UNIXSocket.open(app.socket) do |s|
|
51
|
+
s.write "GET / HTTP/1.1\r\n\r\n"
|
52
|
+
response = s.readlines
|
53
|
+
assert_match /^HTTP\/1.1 200 /, response[0]
|
54
|
+
end
|
55
|
+
assert_shutdown(pid)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
class TestUtils < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_find_in_path
|
7
|
+
Appserver::Utils.send(:const_set, :ENV, 'PATH' => '/some/where/bin:/no/where/bin:/home/foo/bin')
|
8
|
+
File.stubs(:executable?).returns(false)
|
9
|
+
File.expects(:executable?).with('/home/foo/bin/theapp').returns(true)
|
10
|
+
assert_equal '/home/foo/bin/theapp', Appserver::Utils.find_in_path('theapp')
|
11
|
+
Appserver::Utils.send(:remove_const, :ENV)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_find_in_path_fails
|
15
|
+
Appserver::Utils.send(:const_set, :ENV, 'PATH' => '/some/where/bin:/no/where/bin:/home/foo/bin')
|
16
|
+
File.expects(:executable?).returns(false).at_least_once
|
17
|
+
assert_nil Appserver::Utils.find_in_path('theapp')
|
18
|
+
Appserver::Utils.send(:remove_const, :ENV)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_system_hostname
|
22
|
+
Socket.expects(:gethostname).returns('foo.bar.net')
|
23
|
+
assert_equal 'foo.bar.net', Appserver::Utils.system_hostname
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_system_domainname
|
27
|
+
Appserver::Utils.expects(:system_hostname).returns('foo.bar.net')
|
28
|
+
assert_equal 'bar.net', Appserver::Utils.system_domainname
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_number_of_cpus
|
32
|
+
File.stubs(:exist?).with('/proc/cpuinfo').returns(true)
|
33
|
+
File.expects(:readlines).with('/proc/cpuinfo').returns(["processor : 0\n", "processor : 1\n"])
|
34
|
+
assert_equal 2, Appserver::Utils.number_of_cpus.to_i
|
35
|
+
end
|
36
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Andreas Neuhaus
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-05-12 00:00:00 +02:00
|
18
18
|
default_executable: appserver
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +30,46 @@ dependencies:
|
|
30
30
|
version: "0.97"
|
31
31
|
type: :runtime
|
32
32
|
version_requirements: *id001
|
33
|
-
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: git
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
segments:
|
41
|
+
- 1
|
42
|
+
- 2
|
43
|
+
version: "1.2"
|
44
|
+
type: :runtime
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
- 9
|
56
|
+
- 24
|
57
|
+
version: 0.9.24
|
58
|
+
type: :runtime
|
59
|
+
version_requirements: *id003
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: mocha
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
type: :development
|
71
|
+
version_requirements: *id004
|
72
|
+
description: This tool automatically generates server configs for Monit, Nginx and Unicorn to host your Rack-based (Rails) applications. Running it automatically in git update hooks provides an automatic deployment of applications whenever the repository is updated on the server.
|
34
73
|
email: zargony@gmail.com
|
35
74
|
executables:
|
36
75
|
- appserver
|
@@ -40,17 +79,40 @@ extra_rdoc_files:
|
|
40
79
|
- LICENSE
|
41
80
|
- README.md
|
42
81
|
files:
|
82
|
+
- .gitignore
|
43
83
|
- LICENSE
|
44
84
|
- README.md
|
85
|
+
- Rakefile
|
45
86
|
- bin/appserver
|
46
87
|
- lib/appserver.rb
|
47
88
|
- lib/appserver/app.rb
|
48
|
-
- lib/appserver/appserver.
|
89
|
+
- lib/appserver/appserver.conf.rb
|
49
90
|
- lib/appserver/command.rb
|
91
|
+
- lib/appserver/configurator.rb
|
92
|
+
- lib/appserver/logrotate.rb
|
93
|
+
- lib/appserver/monit.rb
|
94
|
+
- lib/appserver/nginx.rb
|
50
95
|
- lib/appserver/repository.rb
|
51
|
-
- lib/appserver/
|
96
|
+
- lib/appserver/server_dir.rb
|
52
97
|
- lib/appserver/unicorn.conf.rb
|
53
98
|
- lib/appserver/utils.rb
|
99
|
+
- test/apps/rack-simple/config.ru
|
100
|
+
- test/apps/sinatra/Gemfile
|
101
|
+
- test/apps/sinatra/config.ru
|
102
|
+
- test/apps/sinatra/hello.rb
|
103
|
+
- test/apps/sinatra/views/index.erb
|
104
|
+
- test/helper.rb
|
105
|
+
- test/unit/test_app.rb
|
106
|
+
- test/unit/test_appserver.rb
|
107
|
+
- test/unit/test_command.rb
|
108
|
+
- test/unit/test_configurator.rb
|
109
|
+
- test/unit/test_logrotate.rb
|
110
|
+
- test/unit/test_monit.rb
|
111
|
+
- test/unit/test_nginx.rb
|
112
|
+
- test/unit/test_repository.rb
|
113
|
+
- test/unit/test_server_dir.rb
|
114
|
+
- test/unit/test_unicorn_conf.rb
|
115
|
+
- test/unit/test_utils.rb
|
54
116
|
has_rdoc: true
|
55
117
|
homepage: http://github.com/zargony/appserver
|
56
118
|
licenses: []
|
@@ -75,12 +137,23 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
137
|
- 0
|
76
138
|
version: "0"
|
77
139
|
requirements:
|
78
|
-
-
|
79
|
-
- monit v5.x or greater
|
140
|
+
- a server with Monit, Nginx and Git
|
80
141
|
rubyforge_project:
|
81
142
|
rubygems_version: 1.3.6
|
82
143
|
signing_key:
|
83
144
|
specification_version: 3
|
84
|
-
summary: Monit/
|
85
|
-
test_files:
|
86
|
-
|
145
|
+
summary: Monit/Nginx/Unicorn application server configurator using deployment via git
|
146
|
+
test_files:
|
147
|
+
- test/apps/sinatra/hello.rb
|
148
|
+
- test/helper.rb
|
149
|
+
- test/unit/test_app.rb
|
150
|
+
- test/unit/test_appserver.rb
|
151
|
+
- test/unit/test_command.rb
|
152
|
+
- test/unit/test_configurator.rb
|
153
|
+
- test/unit/test_logrotate.rb
|
154
|
+
- test/unit/test_monit.rb
|
155
|
+
- test/unit/test_nginx.rb
|
156
|
+
- test/unit/test_repository.rb
|
157
|
+
- test/unit/test_server_dir.rb
|
158
|
+
- test/unit/test_unicorn_conf.rb
|
159
|
+
- test/unit/test_utils.rb
|