sunzi 1.5.2 → 2.0.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 +5 -5
- data/.travis.yml +1 -1
- data/CHANGELOG.md +7 -0
- data/README.md +14 -37
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/{bin → exe}/sunzi +0 -0
- data/lib/sunzi.rb +18 -22
- data/lib/sunzi/actions.rb +35 -0
- data/lib/sunzi/cli.rb +6 -139
- data/lib/sunzi/command.rb +113 -0
- data/lib/sunzi/core_ext.rb +10 -0
- data/lib/sunzi/dependency.rb +26 -29
- data/lib/sunzi/endpoint.rb +17 -0
- data/lib/sunzi/plugin.rb +17 -0
- data/sunzi.gemspec +9 -9
- data/{lib/templates → templates}/create/.gitignore +0 -0
- data/{lib/templates → templates}/create/files/.gitkeep +0 -0
- data/{lib/templates → templates}/create/install.sh +13 -7
- data/{lib/templates → templates}/create/recipes/sunzi.sh +0 -0
- data/{lib/templates → templates}/create/roles/db.sh +0 -0
- data/{lib/templates → templates}/create/roles/web.sh +0 -0
- data/templates/create/sunzi.yml +27 -0
- data/templates/dependency/gemfile.erb +6 -0
- data/templates/dependency/install.erb +6 -0
- metadata +45 -36
- data/lib/sunzi/cloud.rb +0 -24
- data/lib/sunzi/cloud/base.rb +0 -98
- data/lib/sunzi/cloud/digital_ocean.rb +0 -78
- data/lib/sunzi/cloud/linode.rb +0 -154
- data/lib/sunzi/dns.rb +0 -25
- data/lib/sunzi/dns/base.rb +0 -7
- data/lib/sunzi/dns/linode.rb +0 -26
- data/lib/sunzi/dns/route53.rb +0 -25
- data/lib/sunzi/logger.rb +0 -17
- data/lib/sunzi/utility.rb +0 -17
- data/lib/templates/create/sunzi.yml +0 -30
- data/lib/templates/setup/digital_ocean/digital_ocean.yml +0 -28
- data/lib/templates/setup/linode/linode.yml +0 -42
- data/test/test_cli.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7c118fcfb05d687e587068fea6079f6e365ffbf637ef0a4f73dbd1920dc8f138
|
4
|
+
data.tar.gz: 251b57a131bd76db42637bdcd0dad5b373b1a37e964680f5fde2531ff995b768
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19c134eda8a7b0b53570ad335e79b019daa553ae46cb5f554bc80f2157ac11e10e04e51f0c6444d249d6b97f14aa806a85a7c78a11e555eddccb849fd320666b
|
7
|
+
data.tar.gz: be46e99817efb6b0a8e85c5b562297b1b755c3a552ff4977039e70bf672aea636b6fc9cc4e81520120c82f5267e3ff2ba249aed0f061dae9fa4b9adcc48ee1c4
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 2.0, release 2018-01
|
2
|
+
* Plug-in support for commands.
|
3
|
+
* Separate "setup" and "teardown" commands for VPS into the "sunzi-vps" gem as a plugin.
|
4
|
+
* "attributes" are now "vars" in sunzi.yml and shell scripts.
|
5
|
+
* ERB templating (e.g. <%= @vars.environment %>) is always enabled.
|
6
|
+
* Individual attribute files compiled/attributes/* are no longer supported. Use ERB template methods instead.
|
7
|
+
|
1
8
|
## 1.5, release 2013-09-27
|
2
9
|
* `sunzi deploy [linode|digital_ocean] [name]` will deploy to the instance with additional attributes.
|
3
10
|
|
data/README.md
CHANGED
@@ -46,7 +46,7 @@ $ sunzi deploy example.com
|
|
46
46
|
|
47
47
|
Now, what it actually does is:
|
48
48
|
|
49
|
-
1. Compile `sunzi.yml` to generate
|
49
|
+
1. Compile `sunzi.yml` to generate variables and retrieve remote recipes, then copy files into the `compiled` directory
|
50
50
|
1. SSH to `example.com` and login as `root`
|
51
51
|
1. Transfer the content of the `compiled` directory to the remote server and extract in `$HOME/sunzi`
|
52
52
|
1. Run `install.sh` on the remote server
|
@@ -60,12 +60,8 @@ Commands
|
|
60
60
|
|
61
61
|
```bash
|
62
62
|
$ sunzi # Show command help
|
63
|
-
$ sunzi compile # Compile Sunzi project
|
64
63
|
$ sunzi create # Create a new Sunzi project
|
65
64
|
$ sunzi deploy [user@host:port] [role] [--sudo] # Deploy Sunzi project
|
66
|
-
|
67
|
-
$ sunzi setup [linode|digital_ocean] # Setup a new VM on the cloud services
|
68
|
-
$ sunzi teardown [linode|digital_ocean] # Teardown an existing VM on the cloud services
|
69
65
|
```
|
70
66
|
|
71
67
|
Directory structure
|
@@ -76,7 +72,7 @@ Here's the directory structure that `sunzi create` automatically generates:
|
|
76
72
|
```bash
|
77
73
|
sunzi/
|
78
74
|
install.sh # main script
|
79
|
-
sunzi.yml # add custom
|
75
|
+
sunzi.yml # add custom variables and remote recipes here
|
80
76
|
|
81
77
|
recipes/ # put commonly used scripts here, referred from install.sh
|
82
78
|
sunzi.sh
|
@@ -84,6 +80,7 @@ sunzi/
|
|
84
80
|
db.sh # to install.sh in the compile phase
|
85
81
|
web.sh
|
86
82
|
files/ # put any files to be transferred
|
83
|
+
|
87
84
|
compiled/ # everything under this folder will be transferred to the
|
88
85
|
# remote server (do not edit directly)
|
89
86
|
```
|
@@ -91,22 +88,18 @@ sunzi/
|
|
91
88
|
How do you pass dynamic values?
|
92
89
|
-------------------------------
|
93
90
|
|
94
|
-
|
95
|
-
|
96
|
-
**For ruby (recommended)**: Make sure `eval_erb: true` is set in `sunzi.yml`. In the compile phase, attributes defined in `sunzi.yml` are accessible from any files in the form of `<%= @attributes.ruby_version %>`.
|
97
|
-
|
98
|
-
**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.
|
91
|
+
In the compile phase, variables defined in `sunzi.yml` are accessible from any files in the form of `<%= @vars.ruby_version %>`
|
99
92
|
|
100
93
|
For instance, given the following `install.sh`:
|
101
94
|
|
102
95
|
```bash
|
103
|
-
echo "Goodbye <%= @
|
96
|
+
echo "Goodbye <%= @vars.goodbye %>, Hello <%= @vars.hello %>!"
|
104
97
|
```
|
105
98
|
|
106
99
|
With `sunzi.yml`:
|
107
100
|
|
108
101
|
```yaml
|
109
|
-
|
102
|
+
vars:
|
110
103
|
goodbye: Chef
|
111
104
|
hello: Sunzi
|
112
105
|
```
|
@@ -150,19 +143,6 @@ sunzi deploy example.com web
|
|
150
143
|
|
151
144
|
It is equivalent to running `install.sh`, followed by `web.sh`.
|
152
145
|
|
153
|
-
Cloud Support
|
154
|
-
-------------
|
155
|
-
|
156
|
-
You can setup a new VM, or teardown an existing VM interactively. Use `sunzi setup` and `sunzi teardown` for that.
|
157
|
-
|
158
|
-
The following screenshot says it all.
|
159
|
-
|
160
|
-

|
161
|
-
|
162
|
-
Right now, only [Linode](http://www.linode.com/) and [DigitalOcean](https://www.digitalocean.com) are supported.
|
163
|
-
|
164
|
-
For DNS, Linode and [Amazon Route 53](http://aws.amazon.com/route53/) are supported.
|
165
|
-
|
166
146
|
Vagrant
|
167
147
|
-------
|
168
148
|
|
@@ -171,21 +151,13 @@ If you're using Sunzi with [Vagrant](http://vagrantup.com/), make sure that you
|
|
171
151
|
An easy way is to edit `Vagrantfile`:
|
172
152
|
|
173
153
|
```ruby
|
174
|
-
Vagrant
|
175
|
-
config.vm.provision
|
176
|
-
|
154
|
+
Vagrant.configure("2") do |config|
|
155
|
+
config.vm.provision "shell",
|
156
|
+
inline: "sudo echo 'root:vagrant' | /usr/sbin/chpasswd"
|
177
157
|
end
|
178
158
|
end
|
179
159
|
```
|
180
160
|
|
181
|
-
with `chpasswd.sh`:
|
182
|
-
|
183
|
-
```bash
|
184
|
-
#!/bin/bash
|
185
|
-
|
186
|
-
sudo echo 'root:vagrant' | /usr/sbin/chpasswd
|
187
|
-
```
|
188
|
-
|
189
161
|
and now run `vagrant up`, it will change the root password to `vagrant`.
|
190
162
|
|
191
163
|
Also keep in mind that you need to specify the port number 2222.
|
@@ -193,3 +165,8 @@ Also keep in mind that you need to specify the port number 2222.
|
|
193
165
|
```bash
|
194
166
|
$ sunzi deploy localhost:2222
|
195
167
|
```
|
168
|
+
|
169
|
+
Demonstration Videos
|
170
|
+
-------
|
171
|
+
|
172
|
+
You can watch video on how to deploy a Rails 4.1 app with Sunzi and Capistrano 3 at http://youtu.be/3mwupXqtkmg
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'sunzi'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require 'pry'
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/{bin → exe}/sunzi
RENAMED
File without changes
|
data/lib/sunzi.rb
CHANGED
@@ -1,28 +1,24 @@
|
|
1
|
-
|
2
|
-
require '
|
1
|
+
# Stdlib
|
2
|
+
require 'erb'
|
3
|
+
require 'pathname'
|
3
4
|
require 'yaml'
|
4
5
|
|
5
|
-
#
|
6
|
-
require '
|
7
|
-
require 'rainbow/ext/string'
|
6
|
+
# Gems
|
7
|
+
require 'hashugar'
|
8
|
+
require 'rainbow/ext/string'
|
9
|
+
require 'thor'
|
8
10
|
|
11
|
+
# Sunzi
|
9
12
|
module Sunzi
|
10
|
-
|
11
|
-
|
12
|
-
autoload :Dependency, 'sunzi/dependency'
|
13
|
-
autoload :DNS, 'sunzi/dns'
|
14
|
-
autoload :Logger, 'sunzi/logger'
|
15
|
-
autoload :Utility, 'sunzi/utility'
|
13
|
+
GemRoot = Pathname.new(Gem.loaded_specs['sunzi'].gem_dir)
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
autoload :DigitalOcean, 'sunzi/cloud/digital_ocean'
|
21
|
-
end
|
16
|
+
require 'sunzi/core_ext'
|
17
|
+
require 'sunzi/actions'
|
18
|
+
require 'sunzi/dependency'
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
20
|
+
require 'sunzi/cli'
|
21
|
+
|
22
|
+
# Plug-ins
|
23
|
+
require 'sunzi/plugin'
|
24
|
+
Sunzi::Plugin.load
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Sunzi
|
4
|
+
class Actions < Thor
|
5
|
+
# This class exists because thor has to be inherited AND included to import actions.
|
6
|
+
#
|
7
|
+
# https://github.com/erikhuda/thor/wiki/Actions
|
8
|
+
#
|
9
|
+
# This interface is ugly. Instead, initialize once and reuse everywhere.
|
10
|
+
|
11
|
+
include Thor::Actions
|
12
|
+
|
13
|
+
source_root GemRoot
|
14
|
+
|
15
|
+
# include this module to use delegate_to_thor method.
|
16
|
+
module Delegate
|
17
|
+
def self.included(base)
|
18
|
+
base.extend Forwardable
|
19
|
+
base.extend ClassMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
def delegate_to_thor(*args)
|
24
|
+
def_delegators :'Sunzi.thor', *args
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
def thor
|
32
|
+
@thor ||= Sunzi::Actions.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/sunzi/cli.rb
CHANGED
@@ -1,35 +1,22 @@
|
|
1
|
-
require '
|
2
|
-
require 'ostruct'
|
3
|
-
require 'net/ssh'
|
1
|
+
require 'sunzi/command'
|
4
2
|
|
5
3
|
module Sunzi
|
6
4
|
class Cli < Thor
|
7
|
-
include Thor::Actions
|
8
5
|
|
9
6
|
desc 'create', 'Create sunzi project'
|
10
7
|
def create(project = 'sunzi')
|
11
|
-
|
8
|
+
Sunzi::Command.new.create(project)
|
12
9
|
end
|
13
10
|
|
14
|
-
desc 'deploy [user@host:port] [role] [--sudo]
|
15
|
-
method_options :
|
11
|
+
desc 'deploy [user@host:port] [role] [--sudo]', 'Deploy sunzi project'
|
12
|
+
method_options sudo: false
|
16
13
|
def deploy(first, *args)
|
17
|
-
|
14
|
+
Sunzi::Command.new.deploy(first, *args)
|
18
15
|
end
|
19
16
|
|
20
17
|
desc 'compile', 'Compile sunzi project'
|
21
18
|
def compile(role = nil)
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
desc 'setup [linode|digital_ocean]', 'Setup a new VM'
|
26
|
-
def setup(provider)
|
27
|
-
Sunzi::Cloud.new(self, provider).setup
|
28
|
-
end
|
29
|
-
|
30
|
-
desc 'teardown [linode|digital_ocean]', 'Teardown an existing VM'
|
31
|
-
def teardown(provider)
|
32
|
-
Sunzi::Cloud.new(self, provider).teardown
|
19
|
+
Sunzi::Command.new.compile(role)
|
33
20
|
end
|
34
21
|
|
35
22
|
desc 'version', 'Show version'
|
@@ -37,125 +24,5 @@ module Sunzi
|
|
37
24
|
puts Gem.loaded_specs['sunzi'].version.to_s
|
38
25
|
end
|
39
26
|
|
40
|
-
no_tasks do
|
41
|
-
include Sunzi::Utility
|
42
|
-
|
43
|
-
def self.source_root
|
44
|
-
File.expand_path('../../',__FILE__)
|
45
|
-
end
|
46
|
-
|
47
|
-
def do_create(project)
|
48
|
-
copy_file 'templates/create/.gitignore', "#{project}/.gitignore"
|
49
|
-
copy_file 'templates/create/sunzi.yml', "#{project}/sunzi.yml"
|
50
|
-
copy_file 'templates/create/install.sh', "#{project}/install.sh"
|
51
|
-
copy_file 'templates/create/recipes/sunzi.sh', "#{project}/recipes/sunzi.sh"
|
52
|
-
copy_file 'templates/create/roles/db.sh', "#{project}/roles/db.sh"
|
53
|
-
copy_file 'templates/create/roles/web.sh', "#{project}/roles/web.sh"
|
54
|
-
copy_file 'templates/create/files/.gitkeep', "#{project}/files/.gitkeep"
|
55
|
-
end
|
56
|
-
|
57
|
-
def do_deploy(first, *args)
|
58
|
-
if ['linode', 'digital_ocean'].include?(first)
|
59
|
-
@instance_attributes = YAML.load(File.read("#{first}/instances/#{args[0]}.yml"))
|
60
|
-
target = @instance_attributes[:fqdn]
|
61
|
-
role = args[1]
|
62
|
-
else
|
63
|
-
target = first
|
64
|
-
role = args[0]
|
65
|
-
end
|
66
|
-
|
67
|
-
sudo = 'sudo ' if options.sudo?
|
68
|
-
user, host, port = parse_target(target)
|
69
|
-
endpoint = "#{user}@#{host}"
|
70
|
-
|
71
|
-
# compile attributes and recipes
|
72
|
-
do_compile(role)
|
73
|
-
|
74
|
-
# The host key might change when we instantiate a new VM, so
|
75
|
-
# we remove (-R) the old host key from known_hosts.
|
76
|
-
`ssh-keygen -R #{host} 2> /dev/null`
|
77
|
-
|
78
|
-
remote_commands = <<-EOS
|
79
|
-
rm -rf ~/sunzi &&
|
80
|
-
mkdir ~/sunzi &&
|
81
|
-
cd ~/sunzi &&
|
82
|
-
tar xz &&
|
83
|
-
#{sudo}bash install.sh
|
84
|
-
EOS
|
85
|
-
|
86
|
-
remote_commands.strip! << ' && rm -rf ~/sunzi' if @config['preferences'] and @config['preferences']['erase_remote_folder']
|
87
|
-
|
88
|
-
local_commands = <<-EOS
|
89
|
-
cd compiled
|
90
|
-
tar cz . | ssh -o 'StrictHostKeyChecking no' #{endpoint} -p #{port} '#{remote_commands}'
|
91
|
-
EOS
|
92
|
-
|
93
|
-
Open3.popen3(local_commands) do |stdin, stdout, stderr|
|
94
|
-
stdin.close
|
95
|
-
t = Thread.new do
|
96
|
-
while (line = stderr.gets)
|
97
|
-
print line.color(:red)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
while (line = stdout.gets)
|
101
|
-
print line.color(:green)
|
102
|
-
end
|
103
|
-
t.join
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def do_compile(role)
|
108
|
-
# Check if you're in the sunzi directory
|
109
|
-
abort_with 'You must be in the sunzi folder' unless File.exists?('sunzi.yml')
|
110
|
-
# Check if role exists
|
111
|
-
abort_with "#{role} doesn't exist!" if role and !File.exists?("roles/#{role}.sh")
|
112
|
-
|
113
|
-
# Load sunzi.yml
|
114
|
-
@config = YAML.load(File.read('sunzi.yml'))
|
115
|
-
|
116
|
-
# Merge instance attributes
|
117
|
-
@config['attributes'] ||= {}
|
118
|
-
@config['attributes'].update(Hash[@instance_attributes.map{|k,v| [k.to_s, v] }]) if @instance_attributes
|
119
|
-
|
120
|
-
# Break down attributes into individual files
|
121
|
-
(@config['attributes'] || {}).each {|key, value| create_file "compiled/attributes/#{key}", value }
|
122
|
-
|
123
|
-
# Retrieve remote recipes via HTTP
|
124
|
-
cache_remote_recipes = @config['preferences'] && @config['preferences']['cache_remote_recipes']
|
125
|
-
(@config['recipes'] || []).each do |key, value|
|
126
|
-
next if cache_remote_recipes and File.exists?("compiled/recipes/#{key}.sh")
|
127
|
-
get value, "compiled/recipes/#{key}.sh"
|
128
|
-
end
|
129
|
-
|
130
|
-
# Copy local files
|
131
|
-
@attributes = OpenStruct.new(@config['attributes'])
|
132
|
-
copy_or_template = (@config['preferences'] && @config['preferences']['eval_erb']) ? :template : :copy_file
|
133
|
-
Dir['recipes/*'].each {|file| send copy_or_template, File.expand_path(file), "compiled/recipes/#{File.basename(file)}" }
|
134
|
-
Dir['roles/*'].each {|file| send copy_or_template, File.expand_path(file), "compiled/roles/#{File.basename(file)}" }
|
135
|
-
Dir['files/*'].each {|file| send copy_or_template, File.expand_path(file), "compiled/files/#{File.basename(file)}" }
|
136
|
-
(@config['files'] || []).each {|file| send copy_or_template, File.expand_path(file), "compiled/files/#{File.basename(file)}" }
|
137
|
-
|
138
|
-
# Build install.sh
|
139
|
-
if role
|
140
|
-
if copy_or_template == :template
|
141
|
-
template File.expand_path('install.sh'), 'compiled/_install.sh'
|
142
|
-
create_file 'compiled/install.sh', File.binread('compiled/_install.sh') << "\n" << File.binread("compiled/roles/#{role}.sh")
|
143
|
-
else
|
144
|
-
create_file 'compiled/install.sh', File.binread('install.sh') << "\n" << File.binread("roles/#{role}.sh")
|
145
|
-
end
|
146
|
-
else
|
147
|
-
send copy_or_template, File.expand_path('install.sh'), 'compiled/install.sh'
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def parse_target(target)
|
152
|
-
target.match(/(.*@)?(.*?)(:.*)?$/)
|
153
|
-
# Load ssh config if it exists
|
154
|
-
config = Net::SSH::Config.for($2)
|
155
|
-
[ ($1 && $1.delete('@') || config[:user] || 'root'),
|
156
|
-
config[:host_name] || $2,
|
157
|
-
($3 && $3.delete(':') || config[:port] && config[:port].to_s || '22') ]
|
158
|
-
end
|
159
|
-
end
|
160
27
|
end
|
161
28
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'sunzi/endpoint'
|
3
|
+
|
4
|
+
module Sunzi
|
5
|
+
class Command
|
6
|
+
include Sunzi::Actions::Delegate
|
7
|
+
|
8
|
+
delegate_to_thor :copy_file, :template, :get, :append_to_file, :options
|
9
|
+
|
10
|
+
def create(project)
|
11
|
+
copy_file 'templates/create/.gitignore', "#{project}/.gitignore"
|
12
|
+
copy_file 'templates/create/sunzi.yml', "#{project}/sunzi.yml"
|
13
|
+
copy_file 'templates/create/install.sh', "#{project}/install.sh"
|
14
|
+
copy_file 'templates/create/recipes/sunzi.sh', "#{project}/recipes/sunzi.sh"
|
15
|
+
copy_file 'templates/create/roles/db.sh', "#{project}/roles/db.sh"
|
16
|
+
copy_file 'templates/create/roles/web.sh', "#{project}/roles/web.sh"
|
17
|
+
copy_file 'templates/create/files/.gitkeep', "#{project}/files/.gitkeep"
|
18
|
+
end
|
19
|
+
|
20
|
+
def deploy(first, *args)
|
21
|
+
role = args[0]
|
22
|
+
|
23
|
+
sudo = 'sudo ' if options.sudo?
|
24
|
+
endpoint = Endpoint.new(first)
|
25
|
+
|
26
|
+
# compile vars and recipes
|
27
|
+
compile(role)
|
28
|
+
|
29
|
+
# The host key might change when we instantiate a new VM, so
|
30
|
+
# we remove (-R) the old host key from known_hosts.
|
31
|
+
`ssh-keygen -R #{endpoint.host} 2> /dev/null`
|
32
|
+
|
33
|
+
remote_commands = <<-EOS
|
34
|
+
rm -rf ~/sunzi &&
|
35
|
+
mkdir ~/sunzi &&
|
36
|
+
cd ~/sunzi &&
|
37
|
+
tar xz &&
|
38
|
+
#{sudo}bash install.sh
|
39
|
+
EOS
|
40
|
+
|
41
|
+
remote_commands.strip! << ' && rm -rf ~/sunzi' if config.preferences.erase_remote_folder
|
42
|
+
|
43
|
+
local_commands = <<-EOS
|
44
|
+
cd compiled
|
45
|
+
tar cz . | ssh -o 'StrictHostKeyChecking no' #{endpoint.user}@#{endpoint.host} -p #{endpoint.port} '#{remote_commands}'
|
46
|
+
EOS
|
47
|
+
|
48
|
+
Open3.popen3(local_commands) do |stdin, stdout, stderr|
|
49
|
+
stdin.close
|
50
|
+
t = Thread.new do
|
51
|
+
while (line = stderr.gets)
|
52
|
+
print line.color(:red)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
while (line = stdout.gets)
|
56
|
+
print line.color(:green)
|
57
|
+
end
|
58
|
+
t.join
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def compile(role = nil)
|
63
|
+
abort_with "#{role} doesn't exist!" if role && !File.exist?("roles/#{role}.sh")
|
64
|
+
abort_with 'As of v2, "attributes" are now "vars" in sunzi.yml and shell scripts.' if config.attributes
|
65
|
+
|
66
|
+
# Retrieve remote recipes via HTTP
|
67
|
+
(config.recipes || []).each do |key, value|
|
68
|
+
dest = "compiled/recipes/#{key}.sh"
|
69
|
+
next if config.preferences.cache_remote_recipes && File.exist?(dest)
|
70
|
+
get value, dest
|
71
|
+
end
|
72
|
+
|
73
|
+
@vars = config.vars # Used within ERB templates
|
74
|
+
|
75
|
+
# Copy local files to compiled folder
|
76
|
+
files = Dir['{recipes,roles,files}/**/*'].select { |file| File.file?(file) }
|
77
|
+
|
78
|
+
files.each do |file|
|
79
|
+
render file, "compiled/#{file}"
|
80
|
+
end
|
81
|
+
|
82
|
+
# Copy files specified in sunzi.yml
|
83
|
+
(config.files || []).each do |file|
|
84
|
+
render file, "compiled/files/#{File.basename(file)}"
|
85
|
+
end
|
86
|
+
|
87
|
+
# Build install.sh
|
88
|
+
render 'install.sh', 'compiled/install.sh'
|
89
|
+
|
90
|
+
# Append role at the bottom of install.sh
|
91
|
+
if role
|
92
|
+
append_to_file 'compiled/install.sh', "\n" + File.read("compiled/roles/#{role}.sh")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def config
|
99
|
+
@config ||= begin
|
100
|
+
abort_with 'You must be in a sunzi folder' unless File.exist?('sunzi.yml')
|
101
|
+
|
102
|
+
YAML.load(File.read('sunzi.yml')).to_hashugar
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# template method requires absolute path to work with current directory
|
107
|
+
#
|
108
|
+
def render(source, target)
|
109
|
+
template File.expand_path(source), target, context: binding
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|