sunzi-rails 0.1.0
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/.gitignore +7 -0
- data/Gemfile +3 -0
- data/README.md +200 -0
- data/Rakefile +9 -0
- data/bin/sunzi-cap +17 -0
- data/lib/sunzi/cli/capistrano.rb +43 -0
- data/lib/sunzi/cli/database.rb +23 -0
- data/lib/sunzi/cli/secrets.rb +14 -0
- data/lib/sunzi/cli.rb +161 -0
- data/lib/sunzi/logger.rb +17 -0
- data/lib/sunzi/utility.rb +17 -0
- data/lib/sunzi.rb +25 -0
- data/lib/templates/create/files/authorized_keys +1 -0
- data/lib/templates/create/files/sudoers +1 -0
- data/lib/templates/create/install.sh +14 -0
- data/lib/templates/create/recipes/libraries.sh +24 -0
- data/lib/templates/create/recipes/mysql.sh +19 -0
- data/lib/templates/create/recipes/nodejs.sh +6 -0
- data/lib/templates/create/recipes/passenger.sh +19 -0
- data/lib/templates/create/recipes/postgres.sh +14 -0
- data/lib/templates/create/recipes/ruby.sh +28 -0
- data/lib/templates/create/recipes/setup.sh +11 -0
- data/lib/templates/create/recipes/sunzi.sh +99 -0
- data/lib/templates/create/recipes/sysstat.sh +8 -0
- data/lib/templates/create/recipes/update.sh +2 -0
- data/lib/templates/create/recipes/user.sh +23 -0
- data/lib/templates/create/roles/admin.sh +16 -0
- data/lib/templates/create/roles/deployer.sh +7 -0
- data/lib/templates/create/roles/updater.sh +5 -0
- data/lib/templates/create/sunzi.yml +26 -0
- data/sunzi.gemspec +25 -0
- data/test/sunzi_test_dir/files/nginx/nginx.conf +0 -0
- data/test/sunzi_test_dir/recipes/nginx.sh +0 -0
- data/test/test_cli.rb +52 -0
- metadata +174 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7d4434d8e754ea42e09e0b32fb93d466dd8ffcb4
|
4
|
+
data.tar.gz: 4159fb253fdc588e033f8f8df4e1c59a85a48296
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9ead76c9956fa2747ef0ba5100b1f6d8e98ca05ec5278dd8e1845daf36ece3f57afe9f15bb49573c4cd20d8b7b3bd51c0361f5ff89ec8532c3896fae8728cf6f
|
7
|
+
data.tar.gz: 7358cbfbd5cee07e3a2a06dda5ec4cfe25d75d26fd905bca5356451a444e373c97005d82870cf4d86ed96b018ed70c597f8afe490df3e0bd14663639110a8a2e
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
Sunzi-Rails
|
2
|
+
===========
|
3
|
+
|
4
|
+
```
|
5
|
+
"The supreme art of war is to subdue the enemy without fighting." - Sunzi
|
6
|
+
```
|
7
|
+
|
8
|
+
Sunzi is the easiest [server provisioning](http://en.wikipedia.org/wiki/Provisioning#Server_provisioning) utility designed for mere mortals. If Chef or Puppet is driving you nuts, try Sunzi!
|
9
|
+
|
10
|
+
Sunzi assumes that modern Linux distributions have (mostly) sane defaults and great package managers.
|
11
|
+
|
12
|
+
Its design goals are:
|
13
|
+
|
14
|
+
* **It's just shell script.** No clunky Ruby DSL involved. Most of the information about server configuration on the web is written in shell commands. Just copy-paste them, rather than translate it into an arbitrary DSL. Also, Bash is the greatest common denominator on minimum Linux installs.
|
15
|
+
* **Focus on diff from default.** No big-bang overwriting. Append or replace the smallest possible piece of data in a config file. Loads of custom configurations make it difficult to understand what you are really doing.
|
16
|
+
* **Always use the root user.** Think twice before blindly assuming you need a regular user - it doesn't add any security benefit for server provisioning, it just adds extra verbosity for nothing. However, it doesn't mean that you shouldn't create regular users with Sunzi - feel free to write your own recipes.
|
17
|
+
* **Minimum dependencies.** No configuration server required. You don't even need a Ruby runtime on the remote server.
|
18
|
+
|
19
|
+
Quickstart
|
20
|
+
----------
|
21
|
+
|
22
|
+
Install:
|
23
|
+
|
24
|
+
```bash
|
25
|
+
$ [sudo] gem install sunzi-rails
|
26
|
+
```
|
27
|
+
|
28
|
+
Go into your Rails project directory, then:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
$ sunzi-cap create
|
32
|
+
```
|
33
|
+
|
34
|
+
It generates a `config/sunzi` folder along with subdirectories and templates. Inside `sunzi`, there are `sunzi.yml` and `install.sh`. Those two are the most important files that you mainly work on.
|
35
|
+
|
36
|
+
Go into your `config/deploy.rb` and make sure to have these set:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
set :ruby_version, IO.read("#{File.dirname(__FILE__)}/../../.ruby-version").strip
|
40
|
+
set :admin_name, 'admin'
|
41
|
+
set :deployer_name, 'deployer'
|
42
|
+
```
|
43
|
+
|
44
|
+
Go into your `config/deploy/[stage].rb` and make sure to have these set:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
set :server, 'example.com'
|
48
|
+
server fetch(:server), user: fetch(:deployer_name), roles: %w[app web db]
|
49
|
+
```
|
50
|
+
|
51
|
+
Go into your `config/secrets.yml` and make sure to have these set:
|
52
|
+
|
53
|
+
```
|
54
|
+
[stage]:
|
55
|
+
deployer_password: password
|
56
|
+
deployer_public_key: "ssh-rsa ...== deployer@example.com"
|
57
|
+
```
|
58
|
+
|
59
|
+
Finally, add `/compiled` to your `.gitignore` file.
|
60
|
+
|
61
|
+
All those settings can be overriden in your `sunzi.yml` file within `attributes`.
|
62
|
+
|
63
|
+
Go into the project directory, then run `sunzi-cap deploy`:
|
64
|
+
|
65
|
+
```bash
|
66
|
+
$ sunzi-cap deploy staging admin --sudo
|
67
|
+
$ sunzi-cap deploy staging deployer
|
68
|
+
```
|
69
|
+
|
70
|
+
Now, what it actually does is:
|
71
|
+
|
72
|
+
1. Compile `sunzi.yml` to generate attributes and retrieve remote recipes, then copy files scoped to `admin` role into the `compiled` directory
|
73
|
+
1. SSH to `user@example.com` defined within your Cpistrano `config/deploy/staging.rb` file
|
74
|
+
1. Transfer the content of the `compiled` directory to the remote server and extract in `$HOME/sunzi`
|
75
|
+
1. Run `install.sh` on the remote server with sudo mode turned on
|
76
|
+
1. Idem for the `deployer` role, but with sudo mode turned off
|
77
|
+
|
78
|
+
As you can see, all you need to do is edit `install.sh` and add some shell commands. That's it.
|
79
|
+
|
80
|
+
A Sunzi project without any recipes or roles is totally fine, so that you can start small, go big as you get along.
|
81
|
+
|
82
|
+
Commands
|
83
|
+
--------
|
84
|
+
|
85
|
+
```bash
|
86
|
+
$ sunzi-cap # Show command help
|
87
|
+
$ sunzi-cap create # Create a new Sunzi project
|
88
|
+
$ sunzi-cap compile [stage] [role] [--sudo] # Compile Sunzi project
|
89
|
+
$ sunzi-cap deploy [stage] [role] [--sudo] # Deploy Sunzi project
|
90
|
+
```
|
91
|
+
|
92
|
+
Directory structure
|
93
|
+
-------------------
|
94
|
+
|
95
|
+
Here's the directory structure that `sunzi-cap create` automatically generates:
|
96
|
+
|
97
|
+
```bash
|
98
|
+
compiled/ # everything under this folder will be transferred to the
|
99
|
+
# remote server (do not edit directly)
|
100
|
+
config/sunzi/
|
101
|
+
install.sh # main script
|
102
|
+
sunzi.yml # add custom attributes and remote recipes here
|
103
|
+
|
104
|
+
recipes/ # put commonly used scripts here, referred from install.sh
|
105
|
+
sunzi.sh
|
106
|
+
roles/ # when role is specified, scripts here will be concatenated
|
107
|
+
db.sh # to install.sh in the compile phase
|
108
|
+
web.sh
|
109
|
+
files/ # put any files to be transferred
|
110
|
+
```
|
111
|
+
|
112
|
+
How do you pass dynamic values?
|
113
|
+
-------------------------------
|
114
|
+
|
115
|
+
There are two ways to pass dynamic values to the script - ruby and bash.
|
116
|
+
|
117
|
+
**For ruby**: In the compile phase, attributes defined in `sunzi.yml` are accessible from any files in the form of `<%= @attributes.ruby_version %>`.
|
118
|
+
|
119
|
+
**For bash**: In the compile phase, attributes defined in `sunzi.yml` are split into multiple files in `compiled/attributes`, one per attribute. Now you can refer to it by `$(cat attributes/ruby_version)` in the script.
|
120
|
+
|
121
|
+
For instance, given the following `install.sh`:
|
122
|
+
|
123
|
+
```bash
|
124
|
+
echo "Goodbye <%= @attributes.goodbye %>, Hello <%= @attributes.hello %>!"
|
125
|
+
```
|
126
|
+
|
127
|
+
With `sunzi.yml`:
|
128
|
+
|
129
|
+
```yaml
|
130
|
+
attributes:
|
131
|
+
goodbye: Chef
|
132
|
+
hello: Sunzi
|
133
|
+
```
|
134
|
+
|
135
|
+
Now, you get the following result.
|
136
|
+
|
137
|
+
```
|
138
|
+
Goodbye Chef, Hello Sunzi!
|
139
|
+
```
|
140
|
+
|
141
|
+
Remote Recipes
|
142
|
+
--------------
|
143
|
+
|
144
|
+
Recipes can be retrieved remotely via HTTP. Put a URL in the recipes section of `sunzi.yml`, and Sunzi will automatically load the content and put it into the `compiled/recipes` folder in the compile phase.
|
145
|
+
|
146
|
+
For instance, if you have the following line in `sunzi.yml`,
|
147
|
+
|
148
|
+
```yaml
|
149
|
+
recipes:
|
150
|
+
rvm: https://raw.github.com/kenn/sunzi-recipes/master/ruby/rvm.sh
|
151
|
+
```
|
152
|
+
|
153
|
+
`rvm.sh` will be available and you can refer to that recipe by `source recipes/rvm.sh`.
|
154
|
+
|
155
|
+
You may find sample recipes in this repository useful: https://github.com/kenn/sunzi-recipes
|
156
|
+
|
157
|
+
Role-based configuration
|
158
|
+
------------------------
|
159
|
+
|
160
|
+
You probably have different configurations between **web servers** and **database servers**.
|
161
|
+
|
162
|
+
No problem - how Sunzi handles role-based configuration is refreshingly simple.
|
163
|
+
|
164
|
+
Shell scripts under the `roles` directory, such as `web.sh` or `db.sh`, are automatically recognized as a role. The role script will be appended to `install.sh` at deploy, so you should put common configurations in `install.sh` and role specific procedures in the role script.
|
165
|
+
|
166
|
+
For instance, when you set up a new web server, deploy with a role name:
|
167
|
+
|
168
|
+
```bash
|
169
|
+
sunzi-cap deploy production web
|
170
|
+
```
|
171
|
+
|
172
|
+
It is equivalent to running `install.sh`, followed by `web.sh`.
|
173
|
+
|
174
|
+
Vagrant
|
175
|
+
-------
|
176
|
+
|
177
|
+
If you're using Sunzi with [Vagrant](http://vagrantup.com/), make sure that you have a root access via SSH.
|
178
|
+
|
179
|
+
An easy way is to edit `Vagrantfile`:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
Vagrant.configure("2") do |config|
|
183
|
+
config.vm.provision "shell",
|
184
|
+
inline: "sudo echo 'root:vagrant' | /usr/sbin/chpasswd"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
and now run `vagrant up`, it will change the root password to `vagrant`.
|
190
|
+
|
191
|
+
Also keep in mind that you need to specify the port number 2222 within `config/deploy/vagrant.rb`.
|
192
|
+
|
193
|
+
```bash
|
194
|
+
$ sunzi-cap deploy vagrant deployer
|
195
|
+
```
|
196
|
+
|
197
|
+
Demonstration Videos
|
198
|
+
-------
|
199
|
+
|
200
|
+
You can watch video on how to deploy a Rails 4.1 app with Sunzi and Capistrano 3 at http://youtu.be/3mwupXqtkmg
|
data/Rakefile
ADDED
data/bin/sunzi-cap
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Abort beautifully with ctrl+c.
|
4
|
+
Signal.trap(:INT) { abort "\nAborting." }
|
5
|
+
|
6
|
+
# Load the main lib and invoke CLI.
|
7
|
+
if ENV['RAILS_ENV'] == 'development'
|
8
|
+
require './lib/sunzi'
|
9
|
+
else
|
10
|
+
require 'sunzi'
|
11
|
+
end
|
12
|
+
require 'active_support/core_ext/hash/slice'
|
13
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
14
|
+
require 'active_support/ordered_hash'
|
15
|
+
require 'active_support/hash_with_indifferent_access'
|
16
|
+
|
17
|
+
Sunzi::Cli.start(ARGV, { destination_root: 'config' })
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Sunzi
|
2
|
+
module Cli::Capistrano
|
3
|
+
extend self
|
4
|
+
|
5
|
+
attr_accessor :env
|
6
|
+
@env = {}
|
7
|
+
|
8
|
+
def load_env(stage)
|
9
|
+
deploy_path = File.expand_path('config/deploy.rb')
|
10
|
+
stage_path = File.expand_path("config/deploy/#{stage}.rb")
|
11
|
+
instance_eval(File.read(deploy_path), deploy_path)
|
12
|
+
instance_eval(File.read(stage_path), stage_path)
|
13
|
+
@env = HashWithIndifferentAccess.new(@env)
|
14
|
+
end
|
15
|
+
|
16
|
+
def lock(version); end
|
17
|
+
def namespace(options = {}); end
|
18
|
+
|
19
|
+
def set(key, value)
|
20
|
+
@env[key] = value
|
21
|
+
end
|
22
|
+
|
23
|
+
def fetch(key, value = nil)
|
24
|
+
if @env.has_key?(key)
|
25
|
+
@env[key]
|
26
|
+
else
|
27
|
+
@env[key] = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def server(name, properties = {})
|
32
|
+
@env[:server] = {name: name}.merge(properties)
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(name, *args, &block)
|
36
|
+
if caller.join.include? 'load_env'
|
37
|
+
# do nothing
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Sunzi
|
2
|
+
module Cli::Database
|
3
|
+
extend self
|
4
|
+
|
5
|
+
attr_accessor :env
|
6
|
+
|
7
|
+
def load_env(stage)
|
8
|
+
path = File.expand_path('config/database.yml')
|
9
|
+
@env = YAML.load(File.read(path))[stage]
|
10
|
+
scope_keys
|
11
|
+
@env = HashWithIndifferentAccess.new(@env)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def scope_keys
|
17
|
+
@env = @env.reduce({}) do |env, (key, value)|
|
18
|
+
env[:"db_#{key}"] = value
|
19
|
+
env
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'active_support/hash_with_indifferent_access'
|
2
|
+
|
3
|
+
module Sunzi
|
4
|
+
module Cli::Secrets
|
5
|
+
extend self
|
6
|
+
|
7
|
+
attr_accessor :env
|
8
|
+
|
9
|
+
def load_env(stage)
|
10
|
+
path = File.expand_path('config/secrets.yml')
|
11
|
+
@env = HashWithIndifferentAccess.new(YAML.load(File.read(path))[stage])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/sunzi/cli.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'net/ssh'
|
4
|
+
|
5
|
+
module Sunzi
|
6
|
+
class Cli < Thor
|
7
|
+
include Thor::Actions
|
8
|
+
|
9
|
+
desc 'create', 'Create sunzi project'
|
10
|
+
def create(project = 'sunzi')
|
11
|
+
do_create(project)
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'deploy [stage] [role] [--sudo]', 'Deploy sunzi project'
|
15
|
+
method_options :sudo => false
|
16
|
+
def deploy(first, *args)
|
17
|
+
do_deploy(first, *args)
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'compile', 'Compile sunzi project'
|
21
|
+
def compile(first, *args)
|
22
|
+
do_compile(first, *args)
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'version', 'Show version'
|
26
|
+
def version
|
27
|
+
puts Gem.loaded_specs['sunzi'].version.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
no_tasks do
|
31
|
+
include Sunzi::Utility
|
32
|
+
|
33
|
+
def self.source_root
|
34
|
+
File.expand_path('../../',__FILE__)
|
35
|
+
end
|
36
|
+
|
37
|
+
def do_create(project)
|
38
|
+
copy_file 'templates/create/.gitignore', "#{project}/.gitignore"
|
39
|
+
copy_file 'templates/create/sunzi.yml', "#{project}/sunzi.yml"
|
40
|
+
copy_file 'templates/create/install.sh', "#{project}/install.sh"
|
41
|
+
copy_file 'templates/create/recipes/sunzi.sh', "#{project}/recipes/sunzi.sh"
|
42
|
+
copy_file 'templates/create/roles/db.sh', "#{project}/roles/db.sh"
|
43
|
+
copy_file 'templates/create/roles/web.sh', "#{project}/roles/web.sh"
|
44
|
+
copy_file 'templates/create/files/.gitkeep', "#{project}/files/.gitkeep"
|
45
|
+
end
|
46
|
+
|
47
|
+
def do_deploy(first, *args)
|
48
|
+
# compile attributes and recipes
|
49
|
+
do_compile(first, *args)
|
50
|
+
|
51
|
+
# The host key might change when we instantiate a new VM, so
|
52
|
+
# we remove (-R) the old host key from known_hosts.
|
53
|
+
`ssh-keygen -R #{@host} 2> /dev/null`
|
54
|
+
|
55
|
+
remote_commands = <<-EOS
|
56
|
+
rm -rf ~/sunzi &&
|
57
|
+
mkdir ~/sunzi &&
|
58
|
+
cd ~/sunzi &&
|
59
|
+
tar xz &&
|
60
|
+
#{@sudo}bash install.sh
|
61
|
+
EOS
|
62
|
+
|
63
|
+
remote_commands.strip! << ' && rm -rf ~/sunzi' if @config['preferences'] and @config['preferences']['erase_remote_folder']
|
64
|
+
|
65
|
+
local_commands = <<-EOS
|
66
|
+
cd compiled
|
67
|
+
tar cz . | ssh -o 'StrictHostKeyChecking no' #{@user}@#{@host} -p #{@port} '#{remote_commands}'
|
68
|
+
EOS
|
69
|
+
|
70
|
+
Open3.popen3(local_commands) do |stdin, stdout, stderr|
|
71
|
+
stdin.close
|
72
|
+
t = Thread.new do
|
73
|
+
while (line = stderr.gets)
|
74
|
+
print line.color(:red)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
while (line = stdout.gets)
|
78
|
+
print line.color(:green)
|
79
|
+
end
|
80
|
+
t.join
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def do_compile(first, *args)
|
85
|
+
load_env(first, *args)
|
86
|
+
|
87
|
+
compile_attributes
|
88
|
+
copy_remote_recipes
|
89
|
+
copy_local_files
|
90
|
+
build_install
|
91
|
+
end
|
92
|
+
|
93
|
+
def load_env(first, *args)
|
94
|
+
@stage = first
|
95
|
+
@role = args[0]
|
96
|
+
|
97
|
+
abort_with 'You must have a sunzi folder' unless File.exists?(based("sunzi.yml"))
|
98
|
+
abort_with "#{@role} doesn't exist!" unless File.exists?(based("roles/#{@role}.sh"))
|
99
|
+
|
100
|
+
cap = Capistrano.load_env(@stage)
|
101
|
+
if options.sudo?
|
102
|
+
@sudo = 'sudo '
|
103
|
+
@user = cap[:sys_admin]
|
104
|
+
else
|
105
|
+
@user = cap[:server][:user]
|
106
|
+
end
|
107
|
+
@host = cap[:server][:name]
|
108
|
+
@port = cap[:port]
|
109
|
+
|
110
|
+
@config = YAML.load(File.read(based("sunzi.yml")))
|
111
|
+
|
112
|
+
@attributes = Database.load_env(@stage)
|
113
|
+
.merge(cap.slice(:ruby_version, :deployer_name))
|
114
|
+
.merge(Secrets.load_env(@stage).slice(:deployer_password, :deployer_public_key))
|
115
|
+
.merge(@config['attributes'] || {})
|
116
|
+
end
|
117
|
+
|
118
|
+
def compile_attributes
|
119
|
+
# Break down attributes into individual files
|
120
|
+
@attributes.each {|key, value| create_file compiled("attributes/#{key}"), value }
|
121
|
+
@attributes = OpenStruct.new(@attributes)
|
122
|
+
end
|
123
|
+
|
124
|
+
def copy_remote_recipes
|
125
|
+
# Retrieve remote recipes via HTTP
|
126
|
+
cache_remote_recipes = @config['preferences'] && @config['preferences']['cache_remote_recipes']
|
127
|
+
(@config['recipes'] || []).each do |key, value|
|
128
|
+
next if cache_remote_recipes and File.exists?(compiled("recipes/#{key}.sh"))
|
129
|
+
get value, "compiled/recipes/#{key}.sh"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def copy_local_files
|
134
|
+
files = Dir["{config/sunzi/recipes,config/sunzi/roles,config/sunzi/files}/**/*"].select { |file| File.file?(file) }
|
135
|
+
|
136
|
+
files.each do |file|
|
137
|
+
template based(file), compiled(file)
|
138
|
+
end
|
139
|
+
|
140
|
+
(@config['files'] || []).each do |file|
|
141
|
+
template based(file), compiled("files/#{File.basename(file)}")
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def build_install
|
146
|
+
_install_path = compiled("_install.sh")
|
147
|
+
template based("install.sh"), _install_path
|
148
|
+
content = File.binread(_install_path) << "\n" << File.binread(compiled("roles/#{@role}.sh"))
|
149
|
+
create_file compiled("install.sh"), content
|
150
|
+
end
|
151
|
+
|
152
|
+
def based(file)
|
153
|
+
File.expand_path("config/sunzi/#{file.sub('config/sunzi/', '')}")
|
154
|
+
end
|
155
|
+
|
156
|
+
def compiled(file)
|
157
|
+
File.expand_path("compiled/#{file.sub('config/sunzi/', '')}")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/lib/sunzi/logger.rb
ADDED
data/lib/sunzi.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'rainbow'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
# Starting 2.0.0, Rainbow no longer patches string with the color method by default.
|
6
|
+
require 'rainbow/version'
|
7
|
+
require 'rainbow/ext/string' unless Rainbow::VERSION < '2.0.0'
|
8
|
+
|
9
|
+
module Sunzi
|
10
|
+
if ENV['RAILS_ENV'] == 'development'
|
11
|
+
autoload :Capistrano, './lib/sunzi/cli/capistrano'
|
12
|
+
autoload :Database, './lib/sunzi/cli/database'
|
13
|
+
autoload :Secrets, './lib/sunzi/cli/secrets'
|
14
|
+
autoload :Cli, './lib/sunzi/cli'
|
15
|
+
autoload :Logger, './lib/sunzi/logger'
|
16
|
+
autoload :Utility, './lib/sunzi/utility'
|
17
|
+
else
|
18
|
+
autoload :Capistrano, 'sunzi/cli/capistrano'
|
19
|
+
autoload :Database, 'sunzi/cli/database'
|
20
|
+
autoload :Secrets, 'sunzi/cli/secrets'
|
21
|
+
autoload :Cli, 'sunzi/cli'
|
22
|
+
autoload :Logger, 'sunzi/logger'
|
23
|
+
autoload :Utility, 'sunzi/utility'
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @attributes.deployer_public_key %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @attributes.deployer_name %> ALL=(ALL) NOPASSWD:ALL
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -e
|
3
|
+
|
4
|
+
# Load base utility functions like sunzi.mute() and sunzi.install()
|
5
|
+
source recipes/sunzi.sh
|
6
|
+
|
7
|
+
# This line is necessary for automated provisioning for Debian/Ubuntu.
|
8
|
+
# Remove if you're not on Debian/Ubuntu.
|
9
|
+
export DEBIAN_FRONTEND=noninteractive
|
10
|
+
export TERM=linux
|
11
|
+
|
12
|
+
# Add Dotdeb repository. Recommended if you're using Debian. See http://www.dotdeb.org/about/
|
13
|
+
# source recipes/dotdeb.sh
|
14
|
+
# source recipes/backports.sh
|
@@ -0,0 +1,24 @@
|
|
1
|
+
if sunzi.to_be_done "install librairies"; then
|
2
|
+
sunzi.install "autoconf"
|
3
|
+
sunzi.install "bison"
|
4
|
+
sunzi.install "libncurses5-dev"
|
5
|
+
sunzi.install "libgdbm3"
|
6
|
+
sunzi.install "libgdbm-dev"
|
7
|
+
|
8
|
+
sunzi.install "git-core"
|
9
|
+
sunzi.install "zlib1g-dev"
|
10
|
+
sunzi.install "build-essential"
|
11
|
+
sunzi.install "libssl-dev"
|
12
|
+
sunzi.install "libreadline-dev"
|
13
|
+
sunzi.install "libyaml-dev"
|
14
|
+
sunzi.install "libsqlite3-dev"
|
15
|
+
sunzi.install "sqlite3"
|
16
|
+
sunzi.install "libxml2-dev"
|
17
|
+
sunzi.install "libxslt1-dev"
|
18
|
+
sunzi.install "libcurl4-openssl-dev"
|
19
|
+
sunzi.install "python-software-properties"
|
20
|
+
sunzi.install "libffi-dev"
|
21
|
+
sunzi.install "imagemagick"
|
22
|
+
|
23
|
+
sunzi.done "install librairies"
|
24
|
+
fi
|
@@ -0,0 +1,19 @@
|
|
1
|
+
DB_NAME=<%= @attributes.db_database %>
|
2
|
+
DB_USER=<%= @attributes.db_username %>
|
3
|
+
DB_PWD=<%= @attributes.db_password %>
|
4
|
+
DB_ROOT_PWD=<%= @attributes.mysql_root_password %>
|
5
|
+
|
6
|
+
if sunzi.to_be_done "install mysql"; then
|
7
|
+
sudo debconf-set-selections <<< "mysql-server mysql-server/root_password password $DB_ROOT_PWD"
|
8
|
+
sudo debconf-set-selections <<< "mysql-server mysql-server/root_password_again password $DB_ROOT_PWD"
|
9
|
+
sunzi.install "mysql-server"
|
10
|
+
sunzi.install "mysql-client"
|
11
|
+
sunzi.install "libmysqlclient-dev"
|
12
|
+
|
13
|
+
sudo -u root mysql -proot -e "create database $DB_NAME;"
|
14
|
+
sudo -u root mysql -proot -e "create user '$DB_USER'@'localhost' identified by '$DB_PWD';"
|
15
|
+
sudo -u root mysql -proot -e "grant all privileges on $DB_NAME.* to '$DB_USER'@'%' identified by '$DB_PWD';"
|
16
|
+
sudo -u root mysql -proot -e "flush privileges;"
|
17
|
+
|
18
|
+
sunzi.done "install mysql"
|
19
|
+
fi
|
@@ -0,0 +1,19 @@
|
|
1
|
+
DEPLOYER_NAME=<%= @attributes.deployer_name %>
|
2
|
+
DEPLOYER_PATH=/home/$DEPLOYER_NAME
|
3
|
+
RBENV_PATH=$DEPLOYER_PATH/.rbenv
|
4
|
+
|
5
|
+
if sunzi.to_be_done "install passenger"; then
|
6
|
+
sunzi.mute "apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7"
|
7
|
+
sunzi.install "apt-transport-https"
|
8
|
+
sunzi.install "ca-certificates"
|
9
|
+
sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main > /etc/apt/sources.list.d/passenger.list'
|
10
|
+
sunzi.mute "apt-get update"
|
11
|
+
|
12
|
+
sunzi.install "nginx-extras"
|
13
|
+
sunzi.install "passenger"
|
14
|
+
|
15
|
+
sed -i -e "s|# passenger_root|passenger_root|g" /etc/nginx/nginx.conf
|
16
|
+
sed -i -e "s|# passenger_ruby /usr/bin/passenger_free_ruby|passenger_ruby $RBENV_PATH/shims/ruby|g" /etc/nginx/nginx.conf
|
17
|
+
|
18
|
+
sunzi.done "install passenger"
|
19
|
+
fi
|
@@ -0,0 +1,14 @@
|
|
1
|
+
DB_NAME=<%= @attributes.db_database %>
|
2
|
+
DB_USER=<%= @attributes.db_username %>
|
3
|
+
DB_PWD=<%= @attributes.db_password %>
|
4
|
+
|
5
|
+
if sunzi.to_be_done "install postgres"; then
|
6
|
+
sunzi.install "postgresql"
|
7
|
+
sunzi.install "postgresql-contrib"
|
8
|
+
sunzi.install "libpq-dev"
|
9
|
+
|
10
|
+
sudo -u postgres psql -c "create user $DB_USER with password '$DB_PWD';"
|
11
|
+
sudo -u postgres psql -c "create database $DB_NAME owner $DB_USER;"
|
12
|
+
|
13
|
+
sunzi.done "install postgres"
|
14
|
+
fi
|
@@ -0,0 +1,28 @@
|
|
1
|
+
DEPLOYER_NAME=<%= @attributes.deployer_name %>
|
2
|
+
DEPLOYER_PATH=/home/$DEPLOYER_NAME
|
3
|
+
RBENV_PATH=$DEPLOYER_PATH/.rbenv
|
4
|
+
PLUGINS_PATH=$RBENV_PATH/plugins
|
5
|
+
PROFILE=$DEPLOYER_PATH/.bashrc
|
6
|
+
RUBY_VERSION=<%= @attributes.ruby_version %>
|
7
|
+
RBENV_EXPORT_PATH="export PATH=\"$RBENV_PATH/bin:$PLUGINS_PATH/ruby-build/bin:$PATH\""
|
8
|
+
RBENV_INIT='eval "$(rbenv init -)"'
|
9
|
+
|
10
|
+
if sunzi.to_be_done "install ruby"; then
|
11
|
+
git clone git://github.com/sstephenson/rbenv.git $RBENV_PATH
|
12
|
+
git clone git://github.com/sstephenson/ruby-build.git $PLUGINS_PATH/ruby-build
|
13
|
+
git clone git://github.com/sstephenson/rbenv-gem-rehash.git $PLUGINS_PATH/rbenv-gem-rehash
|
14
|
+
git clone git://github.com/dcarley/rbenv-sudo.git $PLUGINS_PATH/rbenv-sudo
|
15
|
+
|
16
|
+
eval $RBENV_EXPORT_PATH
|
17
|
+
eval $RBENV_INIT
|
18
|
+
echo $RBENV_EXPORT_PATH >> $PROFILE
|
19
|
+
echo $RBENV_INIT >> $PROFILE
|
20
|
+
|
21
|
+
rbenv install $RUBY_VERSION
|
22
|
+
rbenv global $RUBY_VERSION
|
23
|
+
echo 'gem: --no-ri --no-rdoc' > $DEPLOYER_PATH/.gemrc
|
24
|
+
gem install bundler
|
25
|
+
gem install backup
|
26
|
+
|
27
|
+
sunzi.done "install ruby"
|
28
|
+
fi
|
@@ -0,0 +1,11 @@
|
|
1
|
+
if sunzi.to_be_done "setup system"; then
|
2
|
+
sunzi.mute "apt-get update"
|
3
|
+
yes | apt-get upgrade
|
4
|
+
sunzi.mute "timedatectl set-timezone <%= @attributes.timezone %>"
|
5
|
+
sunzi.mute "locale-gen <%= @attributes.locales %>"
|
6
|
+
sunzi.mute "dpkg-reconfigure locales"
|
7
|
+
sunzi.install "curl"
|
8
|
+
sunzi.install "ntp"
|
9
|
+
|
10
|
+
sunzi.done "setup system"
|
11
|
+
fi
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# This file is used to define functions under the sunzi.* namespace.
|
2
|
+
|
3
|
+
# Set $sunzi_pkg to "apt-get" or "yum", or abort.
|
4
|
+
#
|
5
|
+
if which apt-get >/dev/null 2>&1; then
|
6
|
+
export sunzi_pkg=apt-get
|
7
|
+
elif which yum >/dev/null 2>&1; then
|
8
|
+
export sunzi_pkg=yum
|
9
|
+
fi
|
10
|
+
|
11
|
+
if [ "$sunzi_pkg" = '' ]; then
|
12
|
+
echo 'sunzi only supports apt-get or yum!' >&2
|
13
|
+
exit 1
|
14
|
+
fi
|
15
|
+
|
16
|
+
# Mute STDOUT and STDERR
|
17
|
+
#
|
18
|
+
function sunzi.mute() {
|
19
|
+
echo "Running \"$@\""
|
20
|
+
`$@ >/dev/null 2>&1`
|
21
|
+
return $?
|
22
|
+
}
|
23
|
+
|
24
|
+
function sunzi.sudo_mute() {
|
25
|
+
echo "Running \"$@\""
|
26
|
+
`sudo $@ >/dev/null 2>&1`
|
27
|
+
return $?
|
28
|
+
}
|
29
|
+
|
30
|
+
# Installer
|
31
|
+
#
|
32
|
+
function sunzi.installed() {
|
33
|
+
if [ "$sunzi_pkg" = 'apt-get' ]; then
|
34
|
+
dpkg -s $@ >/dev/null 2>&1
|
35
|
+
elif [ "$sunzi_pkg" = 'yum' ]; then
|
36
|
+
rpm -qa | grep $@ >/dev/null
|
37
|
+
fi
|
38
|
+
return $?
|
39
|
+
}
|
40
|
+
|
41
|
+
# When there's "set -e" in install.sh, sunzi.install should be used with if statement,
|
42
|
+
# otherwise the script may exit unexpectedly when the package is already installed.
|
43
|
+
#
|
44
|
+
function sunzi.install() {
|
45
|
+
if sunzi.installed "$@"; then
|
46
|
+
echo "$@ already installed"
|
47
|
+
else
|
48
|
+
echo "No packages found matching $@. Installing..."
|
49
|
+
sunzi.mute "$sunzi_pkg -y install $@"
|
50
|
+
fi
|
51
|
+
return 0
|
52
|
+
}
|
53
|
+
|
54
|
+
function sunzi.sudo_install() {
|
55
|
+
if sunzi.installed "$@"; then
|
56
|
+
echo "$@ already installed"
|
57
|
+
else
|
58
|
+
echo "No packages found matching $@. Installing..."
|
59
|
+
sunzi.sudo_mute "$sunzi_pkg -y install $@"
|
60
|
+
fi
|
61
|
+
return 0
|
62
|
+
}
|
63
|
+
|
64
|
+
function sunzi.setup_progress() {
|
65
|
+
if [[ -e "$HOME/sunzi_progress.txt" ]]; then
|
66
|
+
echo "Provisioning already started"
|
67
|
+
else
|
68
|
+
echo "New provisioning"
|
69
|
+
touch "$HOME/sunzi_progress.txt"
|
70
|
+
fi
|
71
|
+
return 0
|
72
|
+
}
|
73
|
+
|
74
|
+
function sunzi.to_be_done() {
|
75
|
+
if [[ -z $(grep -Fx "Done $@" "$HOME/sunzi_progress.txt") ]]; then
|
76
|
+
echo "Executing $@"
|
77
|
+
return 0
|
78
|
+
else
|
79
|
+
echo "Done $@"
|
80
|
+
return 1
|
81
|
+
fi
|
82
|
+
}
|
83
|
+
|
84
|
+
function sunzi.done() {
|
85
|
+
echo "Done $@" | tee -a "$HOME/sunzi_progress.txt"
|
86
|
+
return 0
|
87
|
+
}
|
88
|
+
|
89
|
+
function sunzi.start_time() {
|
90
|
+
echo $(date -u +"%s")
|
91
|
+
}
|
92
|
+
|
93
|
+
function sunzi.elapsed_time() {
|
94
|
+
start=$1
|
95
|
+
finish=$(date -u +"%s")
|
96
|
+
elapsed_time=$(($finish-$start))
|
97
|
+
echo "$(($elapsed_time / 60)) minutes and $(($elapsed_time % 60)) seconds elapsed."
|
98
|
+
return 0
|
99
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
DEPLOYER_NAME=<%= @attributes.deployer_name %>
|
2
|
+
DEPLOYER_PWD=<%= @attributes.deployer_password %>
|
3
|
+
DEPLOYER_PATH=/home/$DEPLOYER_NAME
|
4
|
+
|
5
|
+
if sunzi.to_be_done "create deployer"; then
|
6
|
+
adduser $DEPLOYER_NAME --gecos "First Last,RoomNumber,WorkPhone,HomePhone" --disabled-password
|
7
|
+
echo "$DEPLOYER_NAME:$DEPLOYER_PWD" | sudo chpasswd
|
8
|
+
adduser $DEPLOYER_NAME sudo
|
9
|
+
|
10
|
+
mkdir $DEPLOYER_PATH/.ssh
|
11
|
+
chmod 700 $DEPLOYER_PATH/.ssh
|
12
|
+
|
13
|
+
mv files/authorized_keys $DEPLOYER_PATH/.ssh/authorized_keys
|
14
|
+
chmod 644 $DEPLOYER_PATH/.ssh/authorized_keys
|
15
|
+
|
16
|
+
chown -R $DEPLOYER_NAME:$DEPLOYER_NAME $DEPLOYER_PATH
|
17
|
+
|
18
|
+
mv files/sudoers /etc/sudoers.d/$DEPLOYER_NAME
|
19
|
+
chown root:root /etc/sudoers.d/$DEPLOYER_NAME
|
20
|
+
chmod 0440 /etc/sudoers.d/$DEPLOYER_NAME
|
21
|
+
|
22
|
+
sunzi.done "create deployer"
|
23
|
+
fi
|
@@ -0,0 +1,16 @@
|
|
1
|
+
sunzi.setup_progress
|
2
|
+
|
3
|
+
start=$(sunzi.start_time)
|
4
|
+
|
5
|
+
source recipes/setup.sh
|
6
|
+
source recipes/libraries.sh
|
7
|
+
source recipes/nodejs.sh
|
8
|
+
source recipes/postgres.sh
|
9
|
+
# source recipes/mysql.sh
|
10
|
+
source recipes/passenger.sh
|
11
|
+
source recipes/user.sh
|
12
|
+
# source recipes/sysstat.sh
|
13
|
+
|
14
|
+
sunzi.elapsed_time $start
|
15
|
+
|
16
|
+
reboot
|
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
# Dynamic variables here will be compiled to individual files in compiled/attributes.
|
3
|
+
attributes:
|
4
|
+
timezone: America/New_York
|
5
|
+
locales: en_US en_US.UTF-8
|
6
|
+
# mysql_root_password: secret
|
7
|
+
|
8
|
+
# Remote recipes here will be downloaded to compiled/recipes.
|
9
|
+
recipes:
|
10
|
+
# rvm: https://raw.githubusercontent.com/kenn/sunzi-recipes/master/ruby/rvm.sh
|
11
|
+
# dotdeb: https://raw.githubusercontent.com/kenn/sunzi-recipes/master/debian/dotdeb-wheezy.sh
|
12
|
+
# backports: https://raw.githubusercontent.com/kenn/sunzi-recipes/master/debian/backports-wheezy.sh
|
13
|
+
# mongodb-10gen: https://raw.githubusercontent.com/kenn/sunzi-recipes/master/debian/mongodb-10gen.sh
|
14
|
+
|
15
|
+
# Files specified here will be copied to compiled/files.
|
16
|
+
# files:
|
17
|
+
# - ~/.ssh/id_rsa.pub
|
18
|
+
|
19
|
+
# Fine tune how Sunzi should work.
|
20
|
+
preferences:
|
21
|
+
# Erase the generated folder on the server after deploy.
|
22
|
+
erase_remote_folder: false
|
23
|
+
|
24
|
+
# Skip retrieving remote recipes when local copies already exist. This setting helps
|
25
|
+
# iterative deploy testing considerably faster, when you have a lot of remote recipes.
|
26
|
+
cache_remote_recipes: false
|
data/sunzi.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'sunzi-rails'
|
5
|
+
spec.version = '0.1.0' # retrieve this value by: Gem.loaded_specs['sunzi'].version.to_s
|
6
|
+
spec.authors = ['Kenn Ejima', 'Patrice Lebel']
|
7
|
+
spec.email = ['kenn.ejima@gmail.com']
|
8
|
+
spec.homepage = 'http://github.com/o2web/sunzi-rails'
|
9
|
+
spec.summary = %q{Server provisioning utility for minimalists}
|
10
|
+
spec.description = %q{Server provisioning utility for minimalists}
|
11
|
+
spec.license = 'MIT'
|
12
|
+
|
13
|
+
spec.files = `git ls-files`.split($/)
|
14
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
15
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
spec.require_paths = ['lib']
|
17
|
+
|
18
|
+
spec.add_runtime_dependency 'thor'
|
19
|
+
spec.add_runtime_dependency 'rainbow'
|
20
|
+
spec.add_runtime_dependency 'net-ssh'
|
21
|
+
spec.add_runtime_dependency 'rails', "~> 4.2", ">= 4.2.0"
|
22
|
+
|
23
|
+
spec.add_development_dependency 'rake'
|
24
|
+
spec.add_development_dependency 'minitest'
|
25
|
+
end
|
File without changes
|
File without changes
|
data/test/test_cli.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'sunzi'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
class TestCli < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@cli = Sunzi::Cli.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_parse_target
|
10
|
+
assert_equal ['user', 'example.com', '2222'], @cli.parse_target('user@example.com:2222')
|
11
|
+
assert_equal ['root', 'example.com', '2222'], @cli.parse_target('example.com:2222')
|
12
|
+
assert_equal ['user', 'example.com', '22'], @cli.parse_target('user@example.com')
|
13
|
+
assert_equal ['root', 'example.com', '22'], @cli.parse_target('example.com')
|
14
|
+
assert_equal ['root', '192.168.0.1', '22'], @cli.parse_target('192.168.0.1')
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_parse_target_with_ssh_config
|
18
|
+
ssh_config = lambda do |host|
|
19
|
+
if host == 'example.com'
|
20
|
+
{ :host_name => "buzz.example.com", :user => "foobar", :port => 2222 }
|
21
|
+
else
|
22
|
+
{}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Net::SSH::Config.stub(:for, ssh_config) do
|
27
|
+
assert_equal ['foobar', 'buzz.example.com', '2222'], @cli.parse_target('example.com')
|
28
|
+
assert_equal ['foobar', 'buzz.example.com', '8080'], @cli.parse_target('example.com:8080')
|
29
|
+
assert_equal ['piyo', 'buzz.example.com', '2222'], @cli.parse_target('piyo@example.com')
|
30
|
+
assert_equal ['piyo', 'buzz.example.com', '8080'], @cli.parse_target('piyo@example.com:8080')
|
31
|
+
assert_equal ['root', '192.168.0.1', '22'], @cli.parse_target('192.168.0.1')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_create
|
36
|
+
@cli.create 'sandbox'
|
37
|
+
assert File.exist?('sandbox/sunzi.yml')
|
38
|
+
FileUtils.rm_rf 'sandbox'
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_copy_local_files
|
42
|
+
pwd = Dir.pwd
|
43
|
+
Dir.chdir('test/sunzi_test_dir')
|
44
|
+
|
45
|
+
@cli.copy_local_files({}, :copy_file)
|
46
|
+
assert File.exists?('compiled/files/nginx/nginx.conf')
|
47
|
+
assert File.exists?('compiled/recipes/nginx.sh')
|
48
|
+
FileUtils.rm_rf 'compiled'
|
49
|
+
|
50
|
+
Dir.chdir(pwd)
|
51
|
+
end
|
52
|
+
end
|
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sunzi-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kenn Ejima
|
8
|
+
- Patrice Lebel
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-01-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: thor
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rainbow
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: net-ssh
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rails
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '4.2'
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 4.2.0
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - "~>"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '4.2'
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 4.2.0
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: rake
|
78
|
+
requirement: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: minitest
|
92
|
+
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
type: :development
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
description: Server provisioning utility for minimalists
|
105
|
+
email:
|
106
|
+
- kenn.ejima@gmail.com
|
107
|
+
executables:
|
108
|
+
- sunzi-cap
|
109
|
+
extensions: []
|
110
|
+
extra_rdoc_files: []
|
111
|
+
files:
|
112
|
+
- ".gitignore"
|
113
|
+
- Gemfile
|
114
|
+
- README.md
|
115
|
+
- Rakefile
|
116
|
+
- bin/sunzi-cap
|
117
|
+
- lib/sunzi.rb
|
118
|
+
- lib/sunzi/cli.rb
|
119
|
+
- lib/sunzi/cli/capistrano.rb
|
120
|
+
- lib/sunzi/cli/database.rb
|
121
|
+
- lib/sunzi/cli/secrets.rb
|
122
|
+
- lib/sunzi/logger.rb
|
123
|
+
- lib/sunzi/utility.rb
|
124
|
+
- lib/templates/create/files/authorized_keys
|
125
|
+
- lib/templates/create/files/sudoers
|
126
|
+
- lib/templates/create/install.sh
|
127
|
+
- lib/templates/create/recipes/libraries.sh
|
128
|
+
- lib/templates/create/recipes/mysql.sh
|
129
|
+
- lib/templates/create/recipes/nodejs.sh
|
130
|
+
- lib/templates/create/recipes/passenger.sh
|
131
|
+
- lib/templates/create/recipes/postgres.sh
|
132
|
+
- lib/templates/create/recipes/ruby.sh
|
133
|
+
- lib/templates/create/recipes/setup.sh
|
134
|
+
- lib/templates/create/recipes/sunzi.sh
|
135
|
+
- lib/templates/create/recipes/sysstat.sh
|
136
|
+
- lib/templates/create/recipes/update.sh
|
137
|
+
- lib/templates/create/recipes/user.sh
|
138
|
+
- lib/templates/create/roles/admin.sh
|
139
|
+
- lib/templates/create/roles/deployer.sh
|
140
|
+
- lib/templates/create/roles/updater.sh
|
141
|
+
- lib/templates/create/sunzi.yml
|
142
|
+
- sunzi.gemspec
|
143
|
+
- test/sunzi_test_dir/files/nginx/nginx.conf
|
144
|
+
- test/sunzi_test_dir/recipes/nginx.sh
|
145
|
+
- test/test_cli.rb
|
146
|
+
homepage: http://github.com/o2web/sunzi-rails
|
147
|
+
licenses:
|
148
|
+
- MIT
|
149
|
+
metadata: {}
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
requirements: []
|
165
|
+
rubyforge_project:
|
166
|
+
rubygems_version: 2.4.5.1
|
167
|
+
signing_key:
|
168
|
+
specification_version: 4
|
169
|
+
summary: Server provisioning utility for minimalists
|
170
|
+
test_files:
|
171
|
+
- test/sunzi_test_dir/files/nginx/nginx.conf
|
172
|
+
- test/sunzi_test_dir/recipes/nginx.sh
|
173
|
+
- test/test_cli.rb
|
174
|
+
has_rdoc:
|