/
cli.rb
128 lines (105 loc) · 4.33 KB
/
cli.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
require 'open3'
module Sunzi
class Cli < Thor
include Thor::Actions
desc "create", "Create sunzi project"
def create(project = 'sunzi')
do_create(project)
end
desc "deploy [user@host:port] [role]", "Deploy sunzi project"
def deploy(target, role = nil)
do_deploy(target, role)
end
desc "compile", "Compile sunzi project"
def compile(role = nil)
do_compile(role)
end
desc "setup [linode|ec2]", "Setup a new VM"
def setup(target)
Cloud::Base.choose(self, target).setup
end
desc "teardown [linode|ec2] [name]", "Teardown an existing VM"
def teardown(target, name)
Cloud::Base.choose(self, target).teardown(name)
end
no_tasks do
include Sunzi::Utility
def self.source_root
File.expand_path('../../',__FILE__)
end
def do_create(project)
template "templates/create/.gitignore", "#{project}/.gitignore"
template "templates/create/sunzi.yml", "#{project}/sunzi.yml"
template "templates/create/install.sh", "#{project}/install.sh"
template "templates/create/recipes/sunzi.sh", "#{project}/recipes/sunzi.sh"
template "templates/create/recipes/ssh_key.sh", "#{project}/recipes/ssh_key.sh"
template "templates/create/roles/app.sh", "#{project}/roles/app.sh"
template "templates/create/roles/db.sh", "#{project}/roles/db.sh"
template "templates/create/roles/web.sh", "#{project}/roles/web.sh"
end
def do_deploy(target, role)
user, host, port = parse_target(target)
endpoint = "#{user}@#{host}"
# compile attributes and recipes
do_compile(role)
# The host key might change when we instantiate a new VM, so
# we remove (-R) the old host key from known_hosts.
`ssh-keygen -R #{host} 2> /dev/null`
remote_commands = <<-EOS
rm -rf ~/sunzi &&
mkdir ~/sunzi &&
cd ~/sunzi &&
tar xz &&
bash install.sh
EOS
remote_commands.strip! << ' && rm -rf ~/sunzi' if @config['preferences'] and @config['preferences']['erase_remote_folder']
local_commands = <<-EOS
cd compiled
tar cz . | ssh -o 'StrictHostKeyChecking no' #{endpoint} -p #{port} '#{remote_commands}'
EOS
Open3.popen3(local_commands) do |stdin, stdout, stderr|
stdin.close
t = Thread.new do
while (line = stderr.gets)
print line.color(:red)
end
end
while (line = stdout.gets)
print line.color(:green)
end
t.join
end
end
def do_compile(role)
# Check if you're in the sunzi directory
abort_with "You must be in the sunzi folder" unless File.exists?('sunzi.yml')
# Check if role exists
abort_with "#{role} doesn't exist!" if role and !File.exists?("roles/#{role}.sh")
# Load sunzi.yml
@config = YAML.load(File.read('sunzi.yml'))
# Break down attributes into individual files
(@config['attributes'] || []).each {|key, value| create_file "compiled/attributes/#{key}", value }
# Retrieve remote recipes via HTTP
cache_remote_recipes = @config['preferences'] && @config['preferences']['cache_remote_recipes']
(@config['recipes'] || []).each do |key, value|
next if cache_remote_recipes and File.exists?("compiled/recipes/#{key}.sh")
get value, "compiled/recipes/#{key}.sh"
end
# Copy local files
Dir['recipes/*'].each {|file| copy_file File.expand_path(file), "compiled/recipes/#{File.basename(file)}" }
Dir['roles/*'].each {|file| copy_file File.expand_path(file), "compiled/roles/#{File.basename(file)}" }
(@config['files'] || []).each {|file| copy_file File.expand_path(file), "compiled/files/#{File.basename(file)}" }
# Build install.sh
if role
create_file 'compiled/install.sh', File.binread("install.sh") << "\n" << File.binread("roles/#{role}.sh")
else
copy_file File.expand_path('install.sh'), 'compiled/install.sh'
end
end
def parse_target(target)
target.match(/(.*@)?(.*?)(:.*)?$/)
[ ($1 && $1.delete('@') || 'root'), $2, ($3 && $3.delete(':') || '22') ]
end
end
end
end