sunzi 1.5.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +7 -0
  4. data/README.md +14 -37
  5. data/bin/console +14 -0
  6. data/bin/setup +8 -0
  7. data/{bin → exe}/sunzi +0 -0
  8. data/lib/sunzi.rb +18 -22
  9. data/lib/sunzi/actions.rb +35 -0
  10. data/lib/sunzi/cli.rb +6 -139
  11. data/lib/sunzi/command.rb +113 -0
  12. data/lib/sunzi/core_ext.rb +10 -0
  13. data/lib/sunzi/dependency.rb +26 -29
  14. data/lib/sunzi/endpoint.rb +17 -0
  15. data/lib/sunzi/plugin.rb +17 -0
  16. data/sunzi.gemspec +9 -9
  17. data/{lib/templates → templates}/create/.gitignore +0 -0
  18. data/{lib/templates → templates}/create/files/.gitkeep +0 -0
  19. data/{lib/templates → templates}/create/install.sh +13 -7
  20. data/{lib/templates → templates}/create/recipes/sunzi.sh +0 -0
  21. data/{lib/templates → templates}/create/roles/db.sh +0 -0
  22. data/{lib/templates → templates}/create/roles/web.sh +0 -0
  23. data/templates/create/sunzi.yml +27 -0
  24. data/templates/dependency/gemfile.erb +6 -0
  25. data/templates/dependency/install.erb +6 -0
  26. metadata +45 -36
  27. data/lib/sunzi/cloud.rb +0 -24
  28. data/lib/sunzi/cloud/base.rb +0 -98
  29. data/lib/sunzi/cloud/digital_ocean.rb +0 -78
  30. data/lib/sunzi/cloud/linode.rb +0 -154
  31. data/lib/sunzi/dns.rb +0 -25
  32. data/lib/sunzi/dns/base.rb +0 -7
  33. data/lib/sunzi/dns/linode.rb +0 -26
  34. data/lib/sunzi/dns/route53.rb +0 -25
  35. data/lib/sunzi/logger.rb +0 -17
  36. data/lib/sunzi/utility.rb +0 -17
  37. data/lib/templates/create/sunzi.yml +0 -30
  38. data/lib/templates/setup/digital_ocean/digital_ocean.yml +0 -28
  39. data/lib/templates/setup/linode/linode.yml +0 -42
  40. data/test/test_cli.rb +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c79ff341d30ba481b5240cf5c3048195ab083216
4
- data.tar.gz: 3daae0bd5c6856bd049ad389478e7e03defe15bc
2
+ SHA256:
3
+ metadata.gz: 7c118fcfb05d687e587068fea6079f6e365ffbf637ef0a4f73dbd1920dc8f138
4
+ data.tar.gz: 251b57a131bd76db42637bdcd0dad5b373b1a37e964680f5fde2531ff995b768
5
5
  SHA512:
6
- metadata.gz: dbdaa4fe5e8e08d0ef456f798ae66b24023e91ac9a94c1bd3e53e130ce98da248b371d0566322086f4a1c2864d267a9d9368db235c81957fdbc76705d22dde1a
7
- data.tar.gz: 6957a84b58e79c0fedad317489d4d2e010d974962a17a53a6e4b599ff8b94118ed1ff2c015f0755bdc3c7dd292a382218127a30fd421439775dea3e049a0c320
6
+ metadata.gz: 19c134eda8a7b0b53570ad335e79b019daa553ae46cb5f554bc80f2157ac11e10e04e51f0c6444d249d6b97f14aa806a85a7c78a11e555eddccb849fd320666b
7
+ data.tar.gz: be46e99817efb6b0a8e85c5b562297b1b755c3a552ff4977039e70bf672aea636b6fc9cc4e81520120c82f5267e3ff2ba249aed0f061dae9fa4b9adcc48ee1c4
@@ -2,4 +2,4 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.0
5
+ - ruby-head
@@ -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 attributes and retrieve remote recipes, then copy files into the `compiled` directory
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 attributes and remote recipes here
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
- There are two ways to pass dynamic values to the script - ruby and bash.
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 <%= @attributes.goodbye %>, Hello <%= @attributes.hello %>!"
96
+ echo "Goodbye <%= @vars.goodbye %>, Hello <%= @vars.hello %>!"
104
97
  ```
105
98
 
106
99
  With `sunzi.yml`:
107
100
 
108
101
  ```yaml
109
- attributes:
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
- ![Sunzi for Linode](http://farm8.staticflickr.com/7210/6783789868_ab89010d5c.jpg)
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::Config.run do |config|
175
- config.vm.provision :shell do |shell|
176
- shell.path = "chpasswd.sh"
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
@@ -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__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
File without changes
@@ -1,28 +1,24 @@
1
- require 'thor'
2
- require 'rainbow'
1
+ # Stdlib
2
+ require 'erb'
3
+ require 'pathname'
3
4
  require 'yaml'
4
5
 
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'
6
+ # Gems
7
+ require 'hashugar'
8
+ require 'rainbow/ext/string'
9
+ require 'thor'
8
10
 
11
+ # Sunzi
9
12
  module Sunzi
10
- autoload :Cli, 'sunzi/cli'
11
- autoload :Cloud, 'sunzi/cloud'
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
- class Cloud
18
- autoload :Base, 'sunzi/cloud/base'
19
- autoload :Linode, 'sunzi/cloud/linode'
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
- class DNS
24
- autoload :Base, 'sunzi/dns/base'
25
- autoload :Linode, 'sunzi/dns/linode'
26
- autoload :Route53, 'sunzi/dns/route53'
27
- end
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
@@ -1,35 +1,22 @@
1
- require 'open3'
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
- do_create(project)
8
+ Sunzi::Command.new.create(project)
12
9
  end
13
10
 
14
- desc 'deploy [user@host:port] [role] [--sudo] or deploy [linode|digital_ocean] [name] [role] [--sudo]', 'Deploy sunzi project'
15
- method_options :sudo => false
11
+ desc 'deploy [user@host:port] [role] [--sudo]', 'Deploy sunzi project'
12
+ method_options sudo: false
16
13
  def deploy(first, *args)
17
- do_deploy(first, *args)
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
- do_compile(role)
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