orats 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed3528a226c156ebd2bb1155fc50f3a5074f78cb
4
- data.tar.gz: 972dd00fe19344f92c8079837f841db6226b9425
3
+ metadata.gz: df0e6a8e4b16283b4ee0da8cd5cdb7c5004b8fa4
4
+ data.tar.gz: 9e484f41808728ea3cb9c23984f5fc0f0dc6bf6e
5
5
  SHA512:
6
- metadata.gz: 1ca57f387e3d371752ae69c303c14044491e8abfd8fd8ac093b3c860ae5c307c85576638ffdf11e4f82b320c8d9e405c4324645ad8335a28829960fd96ba77c5
7
- data.tar.gz: 20d28d78394998d2d0f4ead1969aa0f959c279753f1bffd836d783b3f79503b938092543393f32b56b4c5c12dbaa27cd0fab885b2ffc513c2bad54820397a753
6
+ metadata.gz: 6665735679ce17c0f7967357b27ce391b60d5d1abcb7eee4ceedf8a5253bd171a95bdd4c2d416b6e9e10d91b5eae7f50a9a309f8022a8b54756fb6254bd306c1
7
+ data.tar.gz: cace2be230a652af3d08cb595860649a8e4c0deb64d52b3703a468f008ea0179128630f90f24f72153b7da8f27302cefe54bfeb0b811288229ec798ebe5432d2
data/.gitignore CHANGED
@@ -4,5 +4,5 @@
4
4
  .*.sw*
5
5
  *~
6
6
  .idea/
7
- .gem
7
+ *.gem
8
8
  Gemfile.lock
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  ## What is orats and what problem does it solve?
2
2
 
3
3
  It stands for opinionated rails application templates. The templates include solving tedious tasks that you would do for most
4
- projects. It handles creating a rails application with a bunch of opinions and optionally a chef cookbook so you can deploy
5
- your app quickly.
4
+ projects. It handles creating a rails application with a bunch of opinions and optionally an ansible playbook so you can
5
+ deploy your apps quickly.
6
6
 
7
7
  Everything is accessed through the [orats gem](#installation).
8
8
 
9
9
  ## What version of Rails and Ruby are you targeting?
10
10
 
11
- #### Rails 4.0.x and Ruby 2.1.x
11
+ #### Rails 4.1.x and Ruby 2.1.x
12
12
 
13
13
  I will be updating them as new versions come out and when the gems used are proven to work. All important gems in the Gemfile
14
14
  are locked using the pessimistic operator `~>` so you can be sure that everything plays nice as long as rubygems.org is up!
@@ -19,7 +19,7 @@ are locked using the pessimistic operator `~>` so you can be sure that everythin
19
19
  - To download each rails template and automate running certain tasks.
20
20
  - Ruby 2.1.x
21
21
  - Yep, you really need Ruby to run Ruby modules.
22
- - Rails 4.0.x
22
+ - Rails 4.1.x
23
23
  - You need Rails installed so that you can run the project generator.
24
24
  - Git
25
25
  - The weapon of choice for version control.
@@ -28,19 +28,12 @@ are locked using the pessimistic operator `~>` so you can be sure that everythin
28
28
  - Redis
29
29
  - Used as a sidekiq background worker and as the rails cache back end.
30
30
 
31
- ### Additional system dependencies for creating cookbooks
31
+ ### Additional system dependencies for ansible
32
32
 
33
- `orats` is smart enough to skip trying to create a cookbook if it cannot find the necessary dependencies to successfully
34
- create the cookbook, but to successfully create a cookbook you must fulfil the requirements below:
33
+ `orats` is smart enough to skip trying to create ansible related files if it cannot find the necessary dependencies to successfully
34
+ use them. To successfully create ansible content you must fulfil the requirements below:
35
35
 
36
- - Chef is installed and setup in such a way that `knife` is on your system path.
37
- - Berkshelf has been gem installed and you can run `berks` from anywhere.
38
-
39
- Not sure what chef or berkshelf is? No problem, learn about chef from these resources:
40
-
41
- - [Learn chef course](https://learnchef.opscode.com/)
42
- - [Berkshelf readme](http://www.berkshelf.com/)
43
- - [Berkshelf tutorial series](http://misheska.com/blog/2013/06/16/getting-started-writing-chef-cookbooks-the-berkshelf-way/)
36
+ - Ansible is installed and setup in such a way that `ansible` is on your system path.
44
37
 
45
38
  ## Contents
46
39
 
@@ -50,12 +43,10 @@ Not sure what chef or berkshelf is? No problem, learn about chef from these reso
50
43
  - Templates
51
44
  - [Base](#base)
52
45
  - [Authentication and authorization](#authentication-and-authorization)
53
- - [Cookbook](#cookbook)
54
- - [Overview](#the-cookbook-comes-with-the-following-features)
46
+ - [Playbook](#playbook)
47
+ - [Overview](#the-playbook-comes-with-the-following-features)
55
48
  - Sections
56
49
  - [Production tweaks](#production-tweaks)
57
- - Wikis
58
- - [Chef walk through](https://github.com/nickjj/orats/wiki/Chef-walk-through)
59
50
 
60
51
  ## orats
61
52
 
@@ -73,15 +64,15 @@ running `orats <command name> help` from your terminal. You can also type `orats
73
64
  - Configuration:
74
65
  - Optionally takes: `--pg-location [localhost]`
75
66
  - Optionally takes: `--pg-username [postgres]`
67
+ - Optionally takes: `--redis-password []`
76
68
  - Template features:
77
69
  - Optionally takes: `--auth [false]`
78
70
  - Project features:
79
- - Optionally takes: `--skip-cook [false]`
80
71
  - Optionally takes: `--skip-extras [false]`
81
72
  - Optionally takes: `--skip-foreman-start [false]`
82
73
 
83
- - Create a stand alone chef cookbook
84
- - `orats cook <APP_PATH>`
74
+ - Create an ansible playbook
75
+ - `orats play <PATH>`
85
76
 
86
77
  - Delete the directory and optionally all data associated to it
87
78
  - `orats nuke <APP_PATH>`
@@ -133,9 +124,7 @@ Everything has been added with proper git commits so you have a trail of changes
133
124
 
134
125
  ### Try it
135
126
 
136
- `orats new myapp --pg-password <development postgres db password> -C`
137
-
138
- *We are running the command with `-C` to ignore creating a cookbook so the installation is faster.*
127
+ `orats new myapp --pg-password <development postgres db password>`
139
128
 
140
129
  #### What's with the services directory?
141
130
 
@@ -161,6 +150,12 @@ aware that the `.env` file is not loaded in production, in fact it is not even s
161
150
  You can use the `.env` file as a guide so you know which values you need to write out as true ENV variables on your server
162
151
  using whatever server provisioning tools you use.
163
152
 
153
+ #### Project path
154
+
155
+ Make sure you have the project path set properly on your server. It is used by both puma and sidekiq to determine where
156
+ they should write out their pid, socket and log files. If this is not set correctly then you will not be able to start
157
+ your application properly in non-development mode.
158
+
164
159
  #### Puma
165
160
 
166
161
  You should set your puma min/max threads to 0 and 16 and use at least 2 workers if you want to do phased restarts. From
@@ -211,89 +206,69 @@ I feel like this is the cleanest way to disable registrations while still allowi
211
206
 
212
207
  ### Try it
213
208
 
214
- `orats new myauthapp --pg-password <development postgres db password> --auth -C`
215
-
216
- *We are running the command with `-C` to ignore creating a cookbook so the installation is faster.*
209
+ `orats new myauthapp --pg-password <development postgres db password> --auth`
217
210
 
218
- ## Cookbook
211
+ ## Playbook
219
212
 
220
213
  Building your application is only one piece of the puzzle. If you want to ship your application you have to host it somewhere.
221
214
  You have a few options when it comes to managed hosts like Heroku but they tend to be very expensive if you fall out of
222
215
  their free tier.
223
216
 
224
- The cookbook template creates a chef cookbook that will provision a **ubuntu 12.04 LTS server**. It can be hosted anywhere
225
- as there are no hard requirements on any specific host. Chef is a server management framework. This template uses the
226
- application cookbook pattern and depends on Berkshelf. Berkshelf is very similar to bundler but for chef cookbooks.
217
+ The playbook template creates an ansible playbook that will provision a **ubuntu 12.04 LTS server**. It can be hosted anywhere
218
+ as there are no hard requirements on any specific host.
227
219
 
228
- ### The cookbook comes with the following features
220
+ ### The playbook comes with the following features
229
221
 
230
222
  - Security
231
- - A random username is generated each time you generate a new cookbook.
232
- - A random ssh port is generated each time you generate a new cookbook.
233
223
  - Logging into the server is only possible with an SSH key.
234
224
  - fail2ban is setup.
235
- - ufw (firewall) is setup to block any ports not exposed.
225
+ - ufw (firewall) is setup to block any ports not exposed by you.
236
226
  - All stack specific processes are running with less privileges than root.
237
227
  - Stack specific processes that are installed and configured
238
228
  - Nginx
239
229
  - Postgres
240
230
  - Redis
241
231
  - Runtimes
242
- - Ruby 2.1.0 managed via rvm
232
+ - Ruby 2.1.x managed via rvm
243
233
  - Nodejs 0.10.x
244
- - Utils and features
245
- - htop for emergency live monitoring
246
- - logrotate with log rotation setup for anything that needs it.
247
- - git
248
- - A git repo in the deploy user's home directory which you can push to.
249
-
250
- ### Cookbook structure
251
-
252
- It is broken up into 5 recipes:
234
+ - Git
235
+ - Pull in app code from a remote repo of your choice.
253
236
 
254
- - Base
255
- - Database
256
- - Cache
257
- - Web
258
- - Default
237
+ All of this is provided by a series of ansible roles. You may also use these roles without orats. If you want to
238
+ check out each role then here's a link to their repos:
259
239
 
260
- With the application style cookbook pattern it is a good idea to only run one recipe on your node. The default recipe
261
- just composes the other 4 together. This makes it trivial to break out past one node in the future. If you wanted to
262
- put your web server on server A and the database/cache servers on server B all you would have to do is create a new recipe
263
- called something like `database_cache` (the name is arbitrary) and pull in both the database and cache recipes.
240
+ - https://github.com/nickjj/ansible-user
241
+ - https://github.com/nickjj/ansible-security
242
+ - https://github.com/nickjj/ansible-nginx
243
+ - https://github.com/nickjj/ansible-nodejs
244
+ - https://github.com/nickjj/ansible-ruby
245
+ - https://github.com/nickjj/ansible-rails
246
+ - https://github.com/nickjj/ansible-postgres
247
+ - https://github.com/DavidWittman/ansible-redis
264
248
 
265
- Then when you bootstrap the node you can tell it to use the new `database_cache` recipe. Awesome right? Yeah I know, chef rocks.
249
+ You will need to install the roles onto your workstation before you can use them. You can do that by running this command:
250
+ `ansible-galaxy install nickjj.user nickjj.security nickjj.postgres nickjj.ruby nickjj.nodejs nickjj.nginx nickjj.rails DavidWittman.redis --force`
266
251
 
267
252
  ### Try it
268
253
 
269
- `orats new mychefapp --pg-password <development postgres db password>`
270
-
271
- #### Why is the cookbooks directory plural?
272
-
273
- It is not uncommon for some projects to have multiple cookbooks. Of course that is completely out of scope for orats but
274
- at least it generates a directory structure capable of sustaining multiple cookbooks.
275
-
276
- ### Tweakable attributes and meta data
277
-
278
- You can quickly tweak a bunch of values by investigating the `attributes/default.rb` file. The values here are used in each
279
- recipe. They are also namespaced to match the recipe file that uses them.
254
+ `orats play myrailsapp`
280
255
 
281
- #### Are you experienced with chef?
256
+ Ansible is very powerful and flexible when it comes to managing infrastructure. If most of your rails apps have a similar stack
257
+ then you can use a single playbook to run all of your apps. You can customize the details for each one by adjusting the inventory
258
+ that gets generated for each app.
282
259
 
283
- Nice, then you should know what to do from this point. Setup your encrypted data bag and bootstrap the node.
260
+ ### The `inventory` and `secrets` directories
284
261
 
285
- #### Do you need a full blown walk through?
262
+ When you create a new orats app you'll get both of these directories added for you automatically unless you `--skip-extras`.
286
263
 
287
- If you have very little chef experience and want to go through the steps of creating a new orats project with a cookbook,
288
- pushing it to a free managed chef server solution and bootstrapping a node then check out the
289
- [chef walk through on the wiki](https://github.com/nickjj/orats/wiki/Chef-walk-through).
264
+ **The inventory directory** contains the files to setup your host addresses as well as configure your application using
265
+ the parameters exposed by the various ansible roles.
290
266
 
291
- ### The server is up but how do I deploy my application?
267
+ **The secrets directory** holds all of the passwords and sensitive information such as ssh keypairs or ssl certificates. They
268
+ are not added to version control and these files will be copied to your server when you run the playbook.
292
269
 
293
- This is another area where there are many options. You could use capistrano but you could also have chef manage the application
294
- deployment too. I have a few old capistrano 2.x scripts that work fine and I really do not have any intentions of porting
295
- them over to capistrano 3 scripts so they can be included as an orats template because I do not want to use capistrano anymore.
270
+ #### First things first
296
271
 
297
- I'm calling out to the community for help. Can a chef expert please leverage the `deploy` or `application` resources
298
- and provide us with a well documented solution to deploy a rails application with chef? Complete with runit scripts for
299
- ensuring puma and sidekiq are always running of course.
272
+ Once you have an app generated make sure you check out the `inventory/group_vars/all.yml` file. You will want to make all
273
+ of your configuration changes there. After that is up to you. If you want to learn more about ansible then check out the
274
+ [getting started with ansible guide](http://docs.ansible.com/intro_getting_started.html).
data/lib/orats/cli.rb CHANGED
@@ -6,13 +6,13 @@ module Orats
6
6
  option :pg_location, default: 'localhost'
7
7
  option :pg_username, default: 'postgres'
8
8
  option :pg_password, required: true
9
+ option :redis_password, default: ''
9
10
  option :auth, type: :boolean, default: false, aliases: '-a'
10
- option :skip_cook, type: :boolean, default: false, aliases: '-C'
11
11
  option :skip_extras, type: :boolean, default: false, aliases: '-E'
12
12
  option :skip_foreman_start, type: :boolean, default: false, aliases: '-F'
13
13
  desc 'new APP_PATH [options]', ''
14
14
  long_desc <<-D
15
- `orats new myapp --pg-password supersecret` will create a new orats project and it will also create a chef cookbook to go with it by default.
15
+ `orats new myapp --pg-password supersecret` will create a new rails project and it will also create an ansible inventory to go with it by default.
16
16
 
17
17
  You must supply at least this flag:
18
18
 
@@ -24,15 +24,15 @@ module Orats
24
24
 
25
25
  `--pg-username` to supply a custom postgres username [postgres]
26
26
 
27
+ `--redis-password` to supply your development redis password []
28
+
27
29
  Template features:
28
30
 
29
31
  `--auth` will include authentication and authorization [false]
30
32
 
31
33
  Project features:
32
34
 
33
- `--skip-cook` skip creating the cookbook [false]
34
-
35
- `--skip-extras` skip creating the services directory and cookbook [false]
35
+ `--skip-extras` skip creating the services directory and ansible inventory/secrets [false]
36
36
 
37
37
  `--skip-foreman-start` skip automatically running puma and sidekiq [false]
38
38
  D
@@ -40,12 +40,12 @@ module Orats
40
40
  Command.new(app_name, options).new
41
41
  end
42
42
 
43
- desc 'cook APP_PATH', ''
43
+ desc 'play PATH', ''
44
44
  long_desc <<-D
45
- `orats cook myapp` will create a stand alone cookbook.
45
+ `orats play path` will create an ansible playbook.
46
46
  D
47
- def cook(app_name)
48
- Command.new(app_name).cook
47
+ def play(app_name)
48
+ Command.new(app_name).play
49
49
  end
50
50
 
51
51
  option :skip_data, type: :boolean, default: false, aliases: '-D'
@@ -62,9 +62,9 @@ module Orats
62
62
  end
63
63
 
64
64
  desc 'version', ''
65
- long_desc <<-LONGDESC
65
+ long_desc <<-D
66
66
  `orats version` will print the current version.
67
- LONGDESC
67
+ D
68
68
  def version
69
69
  Command.new.version
70
70
  end
data/lib/orats/command.rb CHANGED
@@ -32,10 +32,24 @@ module Orats
32
32
  gsub_postgres_info
33
33
  git_commit 'Change the postgres information'
34
34
 
35
+ unless @options[:redis_password].empty?
36
+ gsub_redis_info
37
+ git_commit 'Add the redis password'
38
+ end
39
+
40
+ gsub_project_path
41
+ git_commit 'Add the development project path'
42
+
35
43
  bundle_install
36
44
  git_commit 'Add gem lock file'
37
45
 
38
- run_rake 'db:create:all db:migrate db:test:prepare'
46
+ bundle_binstubs
47
+ git_commit 'Add binstubs for the important gems'
48
+
49
+ spring_binstub
50
+ git_commit 'Springify all of the bins'
51
+
52
+ run_rake 'db:create:all db:migrate'
39
53
  git_commit 'Add the database schema file'
40
54
  end
41
55
 
@@ -45,16 +59,16 @@ module Orats
45
59
  end
46
60
  end
47
61
 
48
- unless @options[:skip_cook] || @options[:skip_extras]
49
- cook_app cookbooks_path(@app_name)
62
+ unless @options[:skip_extras]
63
+ ansible_init @app_name
50
64
  end
51
65
 
52
66
  @active_path = services_path(@app_name)
53
67
  foreman_init
54
68
  end
55
69
 
56
- def cook
57
- cook_app @app_name
70
+ def play
71
+ play_app @app_name
58
72
  end
59
73
 
60
74
  def nuke
@@ -79,15 +93,11 @@ module Orats
79
93
 
80
94
  private
81
95
  def active_project
82
- project_from_path(@active_path)
96
+ File.basename @active_path
83
97
  end
84
98
 
85
99
  def services_path(app_name)
86
100
  @options[:skip_extras] ? app_name : "#{app_name}/services/#{active_project}"
87
101
  end
88
-
89
- def cookbooks_path(app_name)
90
- "#{app_name}/cookbooks/#{active_project}"
91
- end
92
102
  end
93
103
  end
data/lib/orats/shell.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'securerandom'
2
+
1
3
  module Orats
2
4
  module Shell
3
5
  def run_from(path, command)
@@ -22,6 +24,19 @@ module Orats
22
24
  gsub_file "#{@active_path}/.env", ': supersecrets', ": #{@options[:pg_password]}"
23
25
  end
24
26
 
27
+ def gsub_redis_info
28
+ log_message 'root', 'Adding the redis password'
29
+
30
+ gsub_file "#{@active_path}/config/initializers/sidekiq.rb", '//', '//:#{ENV[\'TESTPROJ_CACHE_PASSWORD\']}@'
31
+ gsub_file "#{@active_path}/.env", ': greatsecurity', ": #{@options[:redis_password]}"
32
+ end
33
+
34
+ def gsub_project_path
35
+ log_message 'root', 'Changing the project path'
36
+
37
+ gsub_file "#{@active_path}/.env", ': /full/path/to/your/project', ": #{File.expand_path(@active_path)}"
38
+ end
39
+
25
40
  def run_rake(command)
26
41
  log_message 'shell', 'Running rake commands'
27
42
 
@@ -34,6 +49,18 @@ module Orats
34
49
  run_from @active_path, 'bundle install'
35
50
  end
36
51
 
52
+ def bundle_binstubs
53
+ log_message 'shell', 'Running bundle binstubs for a few gems'
54
+
55
+ run_from @active_path, 'bundle binstubs whenever puma sidekiq'
56
+ end
57
+
58
+ def spring_binstub
59
+ log_message 'shell', 'Running spring binstub'
60
+
61
+ run_from @active_path, 'bundle exec spring binstub --all'
62
+ end
63
+
37
64
  def nuke_warning
38
65
  puts
39
66
  say_status 'nuke', "\e[1mYou are about to permanently delete this directory:\e[0m", :red
@@ -52,7 +79,7 @@ module Orats
52
79
  rails_projects = []
53
80
 
54
81
  rails_directories.each do |rails_dir|
55
- rails_projects << project_from_path(rails_dir)
82
+ rails_projects << File.basename(rails_dir)
56
83
  end
57
84
 
58
85
  project_names = rails_projects.join(', ')
@@ -70,25 +97,20 @@ module Orats
70
97
  rails_directories.each do |directory|
71
98
  log_message 'root', 'Removing postgres databases'
72
99
  run_from directory, 'bundle exec rake db:drop:all'
73
- nuke_redis project_from_path(directory)
100
+ nuke_redis File.basename(directory)
74
101
  end
75
102
  end
76
103
 
77
- def can_cook?
78
- log_message 'shell', 'Checking for the cookbook system dependencies'
79
-
80
- has_knife = run('which knife', capture: true)
81
- has_berks = run('which berks', capture: true)
104
+ def can_play?
105
+ log_message 'shell', 'Checking for the ansible binary'
82
106
 
83
- dependency_error 'Cannot access knife',
84
- 'Are you sure you have chef setup correctly?',
85
- 'http://www.getchef.com/chef/install/`' if has_knife.empty?
107
+ has_ansible = run('which ansible', capture: true)
86
108
 
87
- dependency_error 'Cannot access berkshelf',
88
- 'Are you sure you have berkshelf installed correctly?',
89
- 'You can install it by running `gem install berkshelf`' if has_berks.empty?
109
+ dependency_error 'Cannot access ansible',
110
+ 'Are you sure you have ansible setup correctly?',
111
+ 'http://docs.ansible.com/intro_installation.html`' if has_ansible.empty?
90
112
 
91
- !has_knife.empty? && !has_berks.empty?
113
+ !has_ansible.empty?
92
114
  end
93
115
 
94
116
  def rails_template(command, flags = '')
@@ -99,15 +121,66 @@ module Orats
99
121
  yield if block_given?
100
122
  end
101
123
 
102
- def cook_app(app_path)
103
- return unless can_cook?
124
+ def play_app(path)
125
+ return unless can_play?
104
126
 
105
- @active_path = app_path
106
- rails_template 'cook'
127
+ @active_path = path
128
+ rails_template 'play'
129
+ end
130
+
131
+ def ansible_init(path)
132
+ log_message 'shell', 'Creating ansible inventory'
133
+ run "mkdir #{path}/inventory"
134
+ run "mkdir #{path}/inventory/group_vars"
135
+ copy_from_includes 'inventory/hosts', path
136
+ copy_from_includes 'inventory/group_vars/all.yml', path
137
+
138
+ secrets_path = "#{path}/secrets"
139
+ log_message 'shell', 'Creating ansible secrets'
140
+ run "mkdir #{secrets_path}"
141
+
142
+ save_secret_string "#{secrets_path}/postgres_password"
143
+ save_secret_string "#{secrets_path}/redis_password"
144
+ save_secret_string "#{secrets_path}/mail_password"
145
+ save_secret_string "#{secrets_path}/rails_token"
146
+ save_secret_string "#{secrets_path}/devise_token"
147
+ save_secret_string "#{secrets_path}/devise_pepper_token"
148
+
149
+ log_message 'shell', 'Modifying secrets path in group_vars/all.yml'
150
+ update_secrets_path secrets_path
151
+
152
+ log_message 'shell', 'Creating ssh keypair'
153
+ run "echo '' | echo '' | echo #{secrets_path}/id_rsa | ssh-keygen -t rsa"
154
+
155
+ log_message 'shell', 'Creating self signed ssl certificates'
156
+ # these are very insecure as I'm not generating new keys for everyone, this should only be used to test
157
+ # SSL on your web app before switching to signed keys from a trusted vendor
158
+ copy_from_includes 'secrets/sslcert.crt', path
159
+ copy_from_includes 'secrets/sslkey.key', path
107
160
  end
108
161
 
109
162
  private
110
163
 
164
+ def save_secret_string(file)
165
+ File.open(file, 'w+') { |f| f.write(SecureRandom.hex(64)) }
166
+ end
167
+
168
+ def update_secrets_path(secrets_path)
169
+ all_yaml_path = "#{secrets_path}/../inventory/group_vars/all.yml"
170
+
171
+ IO.write(all_yaml_path, File.open(all_yaml_path) do |f|
172
+ f.read.gsub('~/tmp/testproj/secrets/', secrets_path)
173
+ end
174
+ )
175
+ end
176
+
177
+ def copy_from_includes(file, destination_root_path)
178
+ base_path = "#{File.expand_path File.dirname(__FILE__)}/templates/includes"
179
+
180
+ log_message 'shell', "Creating #{file}"
181
+ run "cp #{base_path}/#{file} #{destination_root_path}/#{file}"
182
+ end
183
+
111
184
  def nuke_redis(namespace)
112
185
  log_message 'root', 'Removing redis keys'
113
186
 
@@ -154,9 +227,5 @@ module Orats
154
227
  exit 1
155
228
  end
156
229
  end
157
-
158
- def project_from_path(path)
159
- path.split('/').last
160
- end
161
230
  end
162
231
  end