orats 0.2.0 → 0.3.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: d6bad42dd6b612594bb115996f943c6343ed6aac
4
- data.tar.gz: 39d518e79e1f5ab96f67c13989e969e83dd9372b
3
+ metadata.gz: 0a6c0e8dbdf731aa4475b5146b8e7816d42dd9db
4
+ data.tar.gz: 2574c41229f58b27670a7d6caff9af1a6b4cc2a7
5
5
  SHA512:
6
- metadata.gz: c80b52eb4bc604a7841b5eabacc6ddba6ac1d12404b3a96bffadec0a3e164e044445d7fc61fd450a3815a3168007706afca8ca946aec27ded2c7ac0ee0409e3b
7
- data.tar.gz: 3df85308dc2ec16d8fdf5a2838605fc45110a796c25c228c13bf59fdebe25fa978a60a6d41664e6484ef9bb2e2afc31687b672b904178f0495c0a1cfcf568650
6
+ metadata.gz: e0629f4d2632b7697ea66880de7723762ac23714a110f770b4a221e22f7ac0d293eda935cc7e6a29b27179a3ca6dce448d1c5cdb7dfcc6d4b63e88f360c5cd3f
7
+ data.tar.gz: 30eaf60bafff537a7ed5931d15715addde4e548955286fedb51258e6af4135d4f71d79530933e205c947b9e4e89df0c286f3f0d2ed0455ac90a10e48fc29d1a6
data/Gemfile.lock CHANGED
@@ -1,13 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- orats (0.2.0)
4
+ orats (0.3.0)
5
5
  thor (~> 0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- rake (10.1.1)
10
+ rake (0.9.6)
11
11
  thor (0.18.1)
12
12
 
13
13
  PLATFORMS
@@ -16,4 +16,4 @@ PLATFORMS
16
16
  DEPENDENCIES
17
17
  bundler (~> 1.5)
18
18
  orats!
19
- rake
19
+ rake (~> 0)
data/README.md CHANGED
@@ -1,12 +1,10 @@
1
1
  ## What is orats and what problem does it solve?
2
2
 
3
- It stands for opinionated rails application templates. This repository has a collection of opinionated templates
4
- to get you up and going with a modern rails application stack. They are accessed through the [orats gem](#installation).
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.
5
6
 
6
- I noticed I kept making the same changes to every single rails app I made and it actually takes quite a bit of time to
7
- setup all of this manually each time you make an app.
8
-
9
- It is clearly a problem that can be automated so I sat down and started to create a few templates to do just that.
7
+ Everything is accessed through the [orats gem](#installation).
10
8
 
11
9
  ## What version of Rails and Ruby are you targeting?
12
10
 
@@ -15,14 +13,14 @@ It is clearly a problem that can be automated so I sat down and started to creat
15
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
16
14
  are locked using the pessimistic operator `~>` so you can be sure that everything plays nice as long as rubygems.org is up!
17
15
 
18
- ## System dependencies that apply to every template
16
+ ## System dependencies that you must have on your dev box
19
17
 
20
18
  - [The orats gem](#installation)
21
19
  - To download each rails template and automate running certain tasks.
22
20
  - Ruby 2.1.x
23
21
  - Yep, you really need Ruby to run Ruby modules.
24
22
  - Rails 4.0.x
25
- - You also need Rails installed so that you can run the project generator.
23
+ - You need Rails installed so that you can run the project generator.
26
24
  - Git
27
25
  - The weapon of choice for version control.
28
26
  - Postgres
@@ -30,19 +28,34 @@ are locked using the pessimistic operator `~>` so you can be sure that everythin
30
28
  - Redis
31
29
  - Used as a sidekiq background worker and as the rails cache back end.
32
30
 
31
+ ### Additional system dependencies for creating cookbooks
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:
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/)
44
+
33
45
  ## Contents
34
46
 
35
47
  - orats
36
48
  - [Installation](#installation)
37
49
  - [Commands](#commands)
38
50
  - Templates
39
- - [Base](#base-template)
51
+ - [Base](#base)
40
52
  - [Authentication and authorization](#authentication-and-authorization)
41
- - [Application deployment](#application-deployment)
42
- - [Server provisioning](#server-provisioning)
53
+ - [Cookbook](#cookbook)
54
+ - [Overview](#the-cookbook-comes-with-the-following-features)
43
55
  - Sections
44
- - [Expanding beyond the base template](#expanding-beyond-the-base-template)
45
56
  - [Production tweaks](#production-tweaks)
57
+ - Wikis
58
+ - [Chef walk through](https://github.com/nickjj/orats/wiki/Chef-walk-through)
46
59
 
47
60
  ## orats
48
61
 
@@ -50,36 +63,38 @@ are locked using the pessimistic operator `~>` so you can be sure that everythin
50
63
 
51
64
  `gem install orats`
52
65
 
53
-
54
66
  ### Commands
55
67
 
56
- #### Application tasks
68
+ Here is an overview of the available commands. You can find out more information about each command and flag by simply
69
+ running `orats <command name> help` from your terminal. You can also type `orats` on its own to see a list of all commands.
57
70
 
58
- - Create a new rails application using the base template.
59
- - `orats base <app name> --postgres-password <insert your development postgres db password>`
60
- - Optionally takes `--postgres-location [localhost]`
61
- - Optionally takes `--postgres-username [postgres]`
71
+ - Create a new orats project
72
+ - `orats new <APP_PATH> --pg-password <development postgres db password>`
73
+ - Configuration:
74
+ - Optionally takes: `--pg-location [localhost]`
75
+ - Optionally takes: `--pg-username [postgres]`
76
+ - Template features:
77
+ - Optionally takes: `--auth [false]`
78
+ - Project features:
79
+ - Optionally takes: `--skip-cook [false]`
80
+ - Optionally takes: `--skip-extras [false]`
62
81
 
63
- - Create a new rails application with authentication/authorization.
64
- - `orats auth <app name> --postgres-password <insert your development postgres db password>`
65
- - Optionally takes `--postgres-location [localhost]`
66
- - Optionally takes `--postgres-username [postgres]`
82
+ - Create a stand alone chef cookbook
83
+ - `orats cook <APP_PATH>`
67
84
 
68
- - Delete an application and optionally its postgres databases and redis namespace.
69
- - `orats nuke <app name>`
70
- - Optionally takes `--delete-data [true]`
85
+ - Delete the directory and optionally all data associated to it
86
+ - `orats nuke <APP_PATH>`
87
+ - Optionally takes `--skip-data [false]`
71
88
 
72
89
  #### Why is it asking me for my development postgres password?
73
90
 
74
- The password is it asking for is only for your development database. It will **never** ask for your production passwords.
75
-
76
91
  In order to automate certain tasks such as running database migrations the script must be able to talk to your database.
77
92
  It cannot talk to your database without knowing the location, username and password for postgres. In most cases the
78
93
  location will be `localhost` and the username will be `postgres` so these values are provided by default.
79
94
 
80
- If you are curious about the implementation details feel free to [take a look](https://github.com/nickjj/orats/blob/master/orats.thor#L127).
95
+ Remember, this is only your development postgres password. It will **never** ask for your production passwords.
81
96
 
82
- ## Base template
97
+ ## Base
83
98
 
84
99
  This is the starter template that every other template will append to. I feel like when I make a new project, 95% of the time
85
100
  it includes these features and when I do not want a specific thing it is much quicker to remove it than add it.
@@ -117,7 +132,20 @@ Everything has been added with proper git commits so you have a trail of changes
117
132
 
118
133
  ### Try it
119
134
 
120
- `orats base myapp --postgres-password <development postgres db password>`
135
+ `orats new myapp --pg-password <development postgres db password> -C`
136
+
137
+ *We are running the command with `-C` to ignore creating a cookbook so the installation is faster.*
138
+
139
+ #### What's with the services directory?
140
+
141
+ It is just a naming convention that I like to apply, you can name it whatever you want later or remove it with a flag. My thought
142
+ process was you might have multiple services which when put together create your web application. In many cases your web
143
+ application might just be a single rails app, but maybe not.
144
+
145
+ What if you introduced a Go service to do something which your rails application talks to for a certain area of your site?
146
+ Perhaps you have 2 rails applications too. One of them for your admin app and the other for the public facing app.
147
+
148
+ Long story short the extra directory is probably worth it in the long run and it's simple to remove if you don't like it.
121
149
 
122
150
  ### All I see is the default rails page
123
151
 
@@ -182,18 +210,125 @@ I feel like this is the cleanest way to disable registrations while still allowi
182
210
 
183
211
  ### Try it
184
212
 
185
- `orats auth myapp --postgres-password <development postgres db password>`
213
+ `orats new myauthapp --pg-password <development postgres db password> --auth -C`
214
+
215
+ *We are running the command with `-C` to ignore creating a cookbook so the installation is faster.*
216
+
217
+ ## Cookbook
218
+
219
+ Building your application is only one piece of the puzzle. If you want to ship your application you have to host it somewhere.
220
+ 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
221
+ their free tier.
222
+
223
+ The cookbook template creates a chef cookbook that will provision a **ubuntu 12.04 LTS server**. It can be hosted anywhere
224
+ as there are no hard requirements on any specific host. Chef is a server management framework. This template uses the
225
+ application cookbook pattern and depends on Berkshelf. Berkshelf is very similar to bundler but for chef cookbooks.
226
+
227
+ ### The cookbook comes with the following features
228
+
229
+ - Security
230
+ - A random username is generated each time you generate a new cookbook.
231
+ - A random ssh port is generated each time you generate a new cookbook.
232
+ - Logging into the server is only possible with an SSH key.
233
+ - fail2ban is setup.
234
+ - ufw (firewall) is setup to block any ports not exposed.
235
+ - All stack specific processes are running with less privileges than root.
236
+ - Stack specific processes that are installed and configured
237
+ - Nginx
238
+ - Postgres
239
+ - Redis
240
+ - Runtimes
241
+ - Ruby 2.1.0 managed via rvm
242
+ - Nodejs 0.10.x
243
+ - Utils and features
244
+ - htop for emergency live monitoring
245
+ - logrotate with log rotation setup for anything that needs it.
246
+ - git
247
+ - A git repo in the deploy user's home directory which you can push to.
248
+
249
+ ### Cookbook structure
250
+
251
+ It is broken up into 5 recipes:
252
+
253
+ - Base
254
+ - Database
255
+ - Cache
256
+ - Web
257
+ - Default
258
+
259
+ With the application style cookbook pattern it is a good idea to only run one recipe on your node. The default recipe
260
+ just composes the other 4 together. This makes it trivial to break out past one node in the future. If you wanted to
261
+ 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
262
+ called something like `database_cache` (the name is arbitrary) and pull in both the database and cache recipes.
263
+
264
+ Then when you bootstrap the node you can tell it to use the new `database_cache` recipe. Awesome right? Yeah I know, chef rocks.
265
+
266
+ ### Try it
267
+
268
+ `orats new mychefapp --pg-password <development postgres db password>`
269
+
270
+ #### Why is the cookbooks directory plural?
271
+
272
+ It is not uncommon for some projects to have multiple cookbooks. Of course that is completely out of scope for orats but
273
+ at least it generates a directory structure capable of sustaining multiple cookbooks.
274
+
275
+ ### Tweakable attributes and meta data
276
+
277
+ You can quickly tweak a bunch of values by investigating the `attributes/default.rb` file. The values here are used in each
278
+ recipe. They are also namespaced to match the recipe file that uses them.
279
+
280
+ It is important that you change all of these values to match your setup. The only non-obvious one might be the SSH key. You
281
+ should use the key inside of your `.ssh/id_rsa.pub` file. It is the key that ends with your work station's username@hostname. Make
282
+ sure you do not include the trailing line break too.
283
+
284
+ You should also edit the details in the `metadata.rb` file.
285
+
286
+ ### Encrypted values
287
+
288
+ Chef has this notion of encrypted data bags. They are used to protect sensitive information like passwords or secret tokens.
289
+ You can check out the `data_bags/<app_name>_secrets/production.json` file to know which fields you need to fill out later.
290
+
291
+ Please keep in mind that you should never input your real passwords/etc. in this file, it is only here to remind you which
292
+ settings are in your bag. This file is checked into version control. We will cover setting up the data bag with your real
293
+ information in [chef walk through on the wiki](https://github.com/nickjj/orats/wiki/Chef-walk-through).
294
+
295
+ ### Workflow for customizing the cookbook
296
+
297
+ This cookbook is designed to be a generic base to get you started. It is highly encouraged to change the cookbook to suite your
298
+ exact needs. A typical workflow for making changes to the cookbook is this:
299
+
300
+ - Edit any files that you want to change.
301
+ - Bump the version in the `metadata.rb` file. *Never forget to do this step!*
302
+ - Run `berks upload` which sends the cookbooks up to your hosted chef server.
303
+
304
+ If you need to add new cookbooks then add them to `metadata.rb` and run `berks install`. If you need to pull in a cookbook
305
+ from a git repo or your local file system then put them in your `Berksfile` and also place them in `metadata.rb`. Check the
306
+ berkshelf documentation for more details.
307
+
308
+ #### Applying the cookbook changes on your server
309
+
310
+ This step is highly dependent but you have a few options. The first option is to ssh into your node and run `sudo chef-client`.
311
+ Replace ssh with capistrano if you want but the idea is the same. You would be manually invoking the `chef-client` command
312
+ which tells your node to contact the hosted chef server and pull in the changes.
313
+
314
+ The second option would be to setup a cronjob to run `chef-client` automatically at whatever interval you want. By default
315
+ I did not include this because by default chef does not do this.
316
+
317
+ Chef is idempotent so it will not re-run tasks that result in nothing changing so feel free to make changes whenever you
318
+ see fit.
319
+
320
+ ### The server is up but how do I deploy my application?
186
321
 
187
- ## Server provisioning
322
+ This is another area where there are many options. You could use capistrano but you could also have chef manage the application
323
+ deployment too. I have a few old capistrano 2.x scripts that work fine and I really do not have any intentions of porting
324
+ them over to capistrano 3 scripts so they can be included as an orats template because I do not want to use capistrano anymore.
188
325
 
189
- I really like chef and I think at some point there might be a template which creates an application cookbook which provisions
190
- every dependency required to setup this stack using **ubuntu server 12.04 LTS**.
326
+ I'm calling out to the community for help. Can a chef expert please leverage the `deploy` or `application` resources
327
+ and provide us with a well documented solution to deploy a rails application with chef? Complete with runit scripts for
328
+ ensuring puma and sidekiq are always running of course.
191
329
 
192
- I don't think it will ever get too advanced because deployment is very specific to each application but it can at least
193
- dump out a ~200 line cookbook that configures everything to get a server up and running and all you would have to do is
194
- change a few settings in the chef attributes file and setup an encrypted data bag like usual.
330
+ ### Walk through
195
331
 
196
- Right now I have a template in the works that will get you from an empty ubuntu server to a fully working server that
197
- can do everything but handle deploying your rails application. Normally I use capistrano to deploy my app but I want to
198
- move away from that and let chef handle it but I do not have the chef chops to do this yet. I will gladly accept any pull
199
- requests to add this functionality in.
332
+ If you have very little chef experience and want to go through the steps of creating a new orats project with a cookbook,
333
+ pushing it to a free managed chef server solution and bootstrapping a server on a local virtual machine then check out the
334
+ [chef walk through on the wiki](https://github.com/nickjj/orats/wiki/Chef-walk-through).
data/lib/orats/cli.rb CHANGED
@@ -8,78 +8,128 @@ module Orats
8
8
  include Shell
9
9
  include Server
10
10
 
11
- attr_accessor :app_name, :app_name_only
11
+ attr_accessor :active_path, :active_project
12
12
 
13
- class_option :postgres_location, default: 'localhost'
14
- class_option :postgres_username, default: 'postgres'
13
+ option :pg_location, default: 'localhost'
14
+ option :pg_username, default: 'postgres'
15
+ option :pg_password, required: true
16
+ option :auth, type: :boolean, default: false, aliases: '-a'
17
+ option :skip_cook, type: :boolean, default: false, aliases: '-C'
18
+ option :skip_extras, type: :boolean, default: false, aliases: '-E'
19
+ desc 'new APP_PATH [options]', ''
20
+ long_desc <<-LONGDESC
21
+ `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
22
 
16
- option :postgres_password, required: true
17
- desc 'base APP_NAME', 'Create a new rails application using the base template.'
18
- def base(app_name)
19
- @app_name = app_name
23
+ You must supply at least this flag:
20
24
 
21
- run "rails new #{@app_name} --skip-bundle --template #{File.expand_path File.dirname(__FILE__)}/templates/commands/base.rb"
25
+ `--pg-password` to supply your development postgres password so the rails application can run database migrations
22
26
 
23
- gsub_postgres_info options
24
- git_commit 'Change the postgres information'
27
+ Configuration:
25
28
 
26
- bundle_install
27
- git_commit 'Add gem lock file'
29
+ `--pg-location` to supply a custom postgres location [localhost]
28
30
 
29
- run_rake 'db:create:all db:migrate db:test:prepare'
30
- git_commit 'Add the database schema file'
31
+ `--pg-username` to supply a custom postgres username [postgres]
31
32
 
32
- foreman_start unless invoked?
33
- end
33
+ Template features:
34
+
35
+ `--auth` will include authentication and authorization [false]
34
36
 
35
- option :postgres_password, required: true
36
- desc 'auth APP_NAME', 'Create a new rails application with authentication/authorization.'
37
- def auth(app_name)
38
- @app_name = app_name
37
+ Project features:
39
38
 
40
- invoke :base
39
+ `--skip-cook` skip creating the cookbook [false]
41
40
 
42
- run "rails new #{@app_name} --skip --skip-bundle --template #{File.expand_path File.dirname(__FILE__)}/templates/commands/auth.rb"
41
+ `--skip-extras` skip creating the services directory and cookbook [false]
42
+ LONGDESC
43
+ def new(app_name)
44
+ @options = options
45
+ @active_path = app_name
43
46
 
44
- run_rake 'db:migrate db:seed'
47
+ @active_path = services_path(app_name)
48
+ rails_template 'base' do
49
+ gsub_postgres_info
50
+
51
+ bundle_install
52
+ git_commit 'Change the postgres information'
53
+ git_commit 'Add gem lock file'
54
+
55
+ run_rake 'db:create:all db:migrate db:test:prepare'
56
+ git_commit 'Add the database schema file'
57
+ end
58
+
59
+ if options[:auth]
60
+ rails_template 'auth', '--skip ' do
61
+ run_rake 'db:migrate db:seed'
62
+ end
63
+ end
64
+
65
+ unless options[:skip_cook] || options[:skip_extras]
66
+ cook_app cookbooks_path(app_name)
67
+ end
45
68
 
69
+ @active_path = services_path(app_name)
46
70
  foreman_start unless invoked?
47
71
  end
48
72
 
49
- desc 'nuke APP_NAME', 'Delete an application and optionally its postgres databases and redis namespace.'
50
- option :postgres_password, required: false
51
- option :delete_data, type: :boolean, default: true
73
+ desc 'cook APP_PATH', ''
74
+ long_desc <<-LONGDESC
75
+ `orats cook myapp` will create a stand alone cookbook.
76
+ LONGDESC
77
+ def cook(app_name)
78
+ @options = options
79
+ @active_path = app_name
80
+
81
+ cook_app app_name
82
+ end
83
+
84
+ option :skip_data, type: :boolean, default: false, aliases: '-S'
85
+ desc 'nuke APP_PATH [options]', ''
86
+ long_desc <<-LONGDESC
87
+ `orats nuke myapp` will delete the directory and optionally all data associated to it.
88
+
89
+ Options:
90
+
91
+ `--skip-data` will skip deleting app specific postgres databases and redis namespaces [false]
92
+ LONGDESC
52
93
  def nuke(app_name)
53
- @app_name = app_name
94
+ @active_path = app_name
54
95
 
55
96
  puts
56
97
  say_status 'nuke', "\e[1mYou are about to permanently delete this directory:\e[0m", :red
57
- say_status 'path', "#{File.expand_path(app_name)}", :yellow
98
+ say_status 'path', "#{File.expand_path(@active_path)}", :yellow
58
99
 
59
- if options[:delete_data]
100
+ unless options[:skip_data]
60
101
  puts
61
102
  say_status 'nuke', "\e[1mYou are about to permanently delete these postgres databases:\e[0m", :red
62
- say_status 'databases', "#{app_name_only} and #{app_name_only}_test", :yellow
103
+ say_status 'databases', "#{active_project} and #{active_project}_test", :yellow
63
104
  puts
64
105
  say_status 'nuke', "\e[1mYou are about to permanently delete this redis namespace:\e[0m", :red
65
- say_status 'namespace', app_name_only, :yellow
106
+ say_status 'namespace', active_project, :yellow
66
107
  end
67
108
  puts
68
109
 
69
110
  confirmed_to_delete = yes?('Are you sure? (y/N)', :cyan)
70
111
 
71
112
  if confirmed_to_delete
72
- if options[:delete_data]
113
+ unless options[:skip_data]
73
114
  run_rake 'db:drop:all'
74
115
  nuke_redis
75
- nuke_directory
76
116
  end
117
+
118
+ nuke_directory
77
119
  end
78
120
  end
79
121
 
80
122
  private
81
- def app_name_only
82
- @app_name.split('/').last
123
+ def active_project
124
+ @active_path.split('/').last
125
+ end
126
+
127
+ def services_path(app_name)
128
+ options[:skip_extras] ? app_name : "#{app_name}/services/#{active_project}"
129
+ end
130
+
131
+ def cookbooks_path(app_name)
132
+ "#{app_name}/cookbooks/#{active_project}"
83
133
  end
84
134
 
85
135
  def invoked?
data/lib/orats/server.rb CHANGED
@@ -6,7 +6,7 @@ module Orats
6
6
  def foreman_start
7
7
  puts '', '='*80
8
8
  say_status 'action', "\e[1mStarting server with the following commands:\e[0m", :cyan
9
- say_status 'command', "cd #{@app_name}", :magenta
9
+ say_status 'command', "cd #{@active_path}", :magenta
10
10
  say_status 'command', 'bundle exec foreman start', :magenta
11
11
  puts '='*80, ''
12
12
 
@@ -25,7 +25,8 @@ module Orats
25
25
  end
26
26
 
27
27
  puts
28
- run_with_cd 'bundle exec foreman start'
28
+
29
+ run_from @active_path, 'bundle exec foreman start'
29
30
  end
30
31
 
31
32
  def port_taken?
data/lib/orats/shell.rb CHANGED
@@ -1,7 +1,13 @@
1
1
  module Orats
2
2
  module Shell
3
- def run_with_cd(command)
4
- run "cd #{@app_name} && #{command} && cd -"
3
+ def run_from(path, command)
4
+ run "cd #{path} && #{command} && cd -"
5
+ end
6
+
7
+ def cd_inside(path, &block)
8
+ run "cd #{path}"
9
+ yield
10
+ run 'cd -'
5
11
  end
6
12
 
7
13
  def log_message(type, message)
@@ -11,39 +17,105 @@ module Orats
11
17
  end
12
18
 
13
19
  def git_commit(message)
14
- run_with_cd "git add . && git commit -m '#{message}'"
20
+ run_from @active_path, "git add . && git commit -m '#{message}'"
15
21
  end
16
22
 
17
- def gsub_postgres_info(options)
23
+ def gsub_postgres_info
18
24
  log_message 'root', 'Changing the postgres information'
19
25
 
20
- gsub_file "#{@app_name}/.env", ': localhost', ": #{options[:postgres_location]}"
21
- gsub_file "#{@app_name}/.env", ': postgres', ": #{options[:postgres_username]}"
22
- gsub_file "#{@app_name}/.env", ': supersecrets', ": #{options[:postgres_password]}"
26
+ gsub_file "#{@active_path}/.env", ': localhost', ": #{@options[:pg_location]}"
27
+ gsub_file "#{@active_path}/.env", ': postgres', ": #{@options[:pg_username]}"
28
+ gsub_file "#{@active_path}/.env", ': supersecrets', ": #{@options[:pg_password]}"
23
29
  end
24
30
 
25
31
  def run_rake(command)
26
32
  log_message 'shell', 'Running rake commands'
27
33
 
28
- run_with_cd "bundle exec rake #{command}"
34
+ run_from @active_path, "bundle exec rake #{command}"
29
35
  end
30
36
 
31
37
  def bundle_install
32
38
  log_message 'shell', 'Running bundle install, this may take a while'
33
39
 
34
- run "cd #{@app_name} && bundle install && cd -"
40
+ run_from @active_path, 'bundle install'
35
41
  end
36
42
 
37
43
  def nuke_redis
38
44
  log_message 'root', 'Removing redis keys'
39
45
 
40
- run "redis-cli KEYS '#{@app_name_only}:*' | xargs --delim='\n' redis-cli DEL"
46
+ run "redis-cli KEYS '#{active_project}:*' | xargs --delim='\n' redis-cli DEL"
41
47
  end
42
48
 
43
49
  def nuke_directory
44
50
  log_message 'root', 'Deleting directory'
45
51
 
46
- run "rm -rf #{@app_name}"
52
+ run "rm -rf #{@active_path}"
53
+ end
54
+
55
+ def exit_if_exists
56
+ log_message 'shell', 'Checking if a file or directory already exists'
57
+
58
+ if Dir.exist?(@active_path) || File.exist?(@active_path)
59
+ puts
60
+ say_status 'aborting', "\e[1mA file or directory already exists at this location:\e[0m", :red
61
+ say_status 'location', @active_path, :yellow
62
+ puts '-'*80
63
+ puts
64
+
65
+ exit 1
66
+ end
67
+ end
68
+
69
+ def exit_if_cannot_cook
70
+ log_message 'shell', 'Checking for the cookbook system dependencies'
71
+
72
+ has_knife = run('which knife', capture: true)
73
+ has_berks = run('which berks', capture: true)
74
+
75
+ dependency_error 'Cannot access knife',
76
+ 'Are you sure you have chef setup correctly?',
77
+ 'http://www.getchef.com/chef/install/`' if has_knife.empty?
78
+
79
+
80
+ dependency_error 'Cannot access berkshelf',
81
+ 'Are you sure you have berkshelf installed correctly?',
82
+ 'You can install it by running `gem install berkshelf`' if has_berks.empty?
83
+ end
84
+
85
+ def exit_if_cannot_rails
86
+ log_message 'shell', 'Checking for rails'
87
+
88
+ has_rails = run('which rails', capture: true)
89
+
90
+ dependency_error 'Cannot access rails',
91
+ 'Are you sure you have rails setup correctly?',
92
+ 'You can install it by running `gem install rails`' if has_rails.empty?
93
+ end
94
+
95
+ def dependency_error(message, question, answer)
96
+ puts
97
+ say_status 'error', "\e[1m#{message}\e[0m", :red
98
+ say_status 'question', question, :yellow
99
+ say_status 'answer', answer, :cyan
100
+ puts '-'*80
101
+ puts
102
+
103
+ exit 1
104
+ end
105
+
106
+ def rails_template(command, flags = '', &block)
107
+ exit_if_cannot_rails
108
+ exit_if_exists unless flags.index(/--skip /)
109
+
110
+ run "rails new #{@active_path} #{flags}--skip-bundle --template #{File.expand_path File.dirname(__FILE__)}/templates/#{command}.rb"
111
+ yield if block_given?
112
+ end
113
+
114
+ def cook_app(app_path)
115
+ exit_if_cannot_cook
116
+
117
+ @active_path = app_path
118
+ rails_template 'cook'
47
119
  end
48
120
  end
49
121
  end
File without changes
@@ -11,7 +11,7 @@ def generate_token
11
11
  end
12
12
 
13
13
  def from_gem(source, destination = nil)
14
- base_path = "#{File.expand_path File.dirname(__FILE__)}/../includes"
14
+ base_path = "#{File.expand_path File.dirname(__FILE__)}/includes"
15
15
  file_name = source.split('/').last
16
16
 
17
17
  if destination.present? && file_name != destination
@@ -0,0 +1,630 @@
1
+ # =====================================================================================================
2
+ # Template for generating a chef cookbook
3
+ # =====================================================================================================
4
+
5
+ # ----- Helper functions and variables ----------------------------------------------------------------
6
+
7
+ require 'securerandom'
8
+
9
+ def generate_token
10
+ SecureRandom.hex(64)
11
+ end
12
+
13
+ def git_config(field)
14
+ command = "git config --global user.#{field}"
15
+ git_field_value = run(command, capture: true).gsub("\n", '')
16
+ default_value = "YOUR_#{field.upcase}"
17
+
18
+ git_field_value.to_s.empty? ? default_value : git_field_value
19
+ end
20
+
21
+ app_name_upper = app_name.upcase
22
+ app_name_class = app_name.humanize
23
+
24
+ author_name = git_config 'name'
25
+ author_email = git_config 'email'
26
+
27
+ # ----- Nuke all of the rails code --------------------------------------------------------------------
28
+
29
+ puts
30
+ say_status 'shell', 'Removing all of the generated rails code...', :yellow
31
+ puts '-'*80, ''; sleep 0.25
32
+
33
+ run 'rm -rf * .git .gitignore'
34
+
35
+ # ----- Install berkshelf -----------------------------------------------------------------------------
36
+
37
+ puts
38
+ say_status 'tool', 'Gem installing berkshelf, this may take a while...', :yellow
39
+ puts '-'*80, ''; sleep 0.25
40
+
41
+ run 'gem install berkshelf'
42
+
43
+ # ----- Create cookbook -------------------------------------------------------------------------------
44
+
45
+ puts
46
+ say_status 'init', 'Creating skeleton cookbook...', :yellow
47
+ puts '-'*80, ''; sleep 0.25
48
+
49
+ run "berks cookbook #{app_name}"
50
+
51
+ # ----- Move cookbook back one directory --------------------------------------------------------------
52
+
53
+ puts
54
+ say_status 'shell', 'Moving cookbook back one directory...', :yellow
55
+ puts '-'*80, ''; sleep 0.25
56
+
57
+ run "mv #{app_name}/* ."
58
+ run "rm -rf #{app_name}"
59
+
60
+ # ----- Create the git repo ---------------------------------------------------------------------------
61
+
62
+ puts
63
+ say_status 'git', 'Creating initial commit...', :yellow
64
+ puts '-'*80, ''; sleep 0.25
65
+
66
+ git :init
67
+ git add: '.'
68
+ git commit: "-m 'Initial commit'"
69
+
70
+ # ----- Create the license ----------------------------------------------------------------------------
71
+
72
+ puts
73
+ say_status 'root', 'Creating the license', :yellow
74
+ puts '-'*80, ''; sleep 0.25
75
+
76
+ run 'rm -rf LICENSE'
77
+
78
+ file 'LICENSE' do <<-TEXT
79
+ The MIT License (MIT)
80
+
81
+ Copyright (c) #{Time.now.year} #{author_name} <#{author_email}>
82
+
83
+ Permission is hereby granted, free of charge, to any person obtaining
84
+ a copy of this software and associated documentation files (the
85
+ 'Software'), to deal in the Software without restriction, including
86
+ without limitation the rights to use, copy, modify, merge, publish,
87
+ distribute, sublicense, and/or sell copies of the Software, and to
88
+ permit persons to whom the Software is furnished to do so, subject to
89
+ the following conditions:
90
+
91
+ The above copyright notice and this permission notice shall be
92
+ included in all copies or substantial portions of the Software.
93
+
94
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
95
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
96
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
97
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
98
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
99
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
100
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
101
+ TEXT
102
+ end
103
+
104
+ git add: '.'
105
+ git commit: "-m 'Add MIT license'"
106
+
107
+ # ----- Customize meta data ---------------------------------------------------------------------------
108
+
109
+ puts
110
+ say_status 'root', 'Changing metadata file', :yellow
111
+ puts '-'*80, ''; sleep 0.25
112
+
113
+ puts author_name
114
+ puts author_email
115
+
116
+ gsub_file 'metadata.rb', 'YOUR_NAME', author_name
117
+ gsub_file 'metadata.rb', 'YOUR_EMAIL', author_email
118
+ gsub_file 'metadata.rb', 'All rights reserved', 'MIT LICENSE'
119
+
120
+ git add: '.'
121
+ git commit: "-m 'Change meta data in the metadata.rb file'"
122
+
123
+ # ----- Add application dependencies ------------------------------------------------------------------
124
+
125
+ puts
126
+ say_status 'root', 'Adding application dependencies...', :yellow
127
+ puts '-'*80, ''; sleep 0.25
128
+
129
+ append_file 'Berksfile' do <<-CODE
130
+ cookbook 'postgresql', git: 'git://github.com/phlipper/chef-postgresql.git'
131
+ cookbook 'rvm', git: 'git://github.com/fnichol/chef-rvm'
132
+ CODE
133
+ end
134
+
135
+ git add: '.'
136
+ git commit: "-m 'Add dependencies to the Berksfile'"
137
+
138
+ append_file 'metadata.rb' do <<-CODE
139
+ # base
140
+ depends 'openssh', '~> 1.3.2'
141
+ depends 'user', '~> 0.3.0'
142
+ depends 'sudo', '~> 2.3.0'
143
+ depends 'fail2ban', '~> 2.1.2'
144
+ depends 'ufw', '~> 0.7.4'
145
+ depends 'swap', '~> 0.3.6'
146
+
147
+ # database
148
+ depends 'postgresql', '~> 0.13.0'
149
+
150
+ # cache
151
+ depends 'redisio', '~> 1.7.0'
152
+
153
+ # web
154
+ depends 'git', '~> 2.9.0'
155
+ depends 'rvm', '~> 0.9.1'
156
+ depends 'nodejs', '~> 1.3.0'
157
+ depends 'nginx', '~> 2.2.0'
158
+ depends 'logrotate', '~> 1.4.0'
159
+ CODE
160
+ end
161
+
162
+ git add: '.'
163
+ git commit: "-m 'Add dependencies to the metadata file'"
164
+
165
+ # ----- Install cookbooks locally ---------------------------------------------------------------------
166
+
167
+ puts
168
+ say_status 'tool', 'Berks installing the cookbooks, this may take a while...', :yellow
169
+ puts '-'*80, ''; sleep 0.25
170
+
171
+ run 'berks install'
172
+
173
+ git add: '.'
174
+ git commit: "-m 'Change meta data in the metadata.rb file'"
175
+
176
+ # ----- Configure attributes file ---------------------------------------------------------------------
177
+
178
+ puts
179
+ say_status 'attr', 'Modifying the attributes file...', :yellow
180
+ puts '-'*80, ''; sleep 0.25
181
+
182
+ random_ssh_port = rand(11000..55000)
183
+ random_username = SecureRandom.hex[0...8]
184
+
185
+ file 'attributes/default.rb' do <<-CODE
186
+ default[:#{app_name}][:base][:ssh_port] = '#{random_ssh_port}'
187
+ default[:#{app_name}][:base][:username] = '#{random_username}'
188
+ default[:#{app_name}][:base][:swap_size] = 1024 # MBs
189
+ default[:#{app_name}][:base][:ssh_key] = 'INSERT_YOUR_PUBLIC_SSH_KEY_HERE'
190
+
191
+ default[:#{app_name}][:database][:host] = 'localhost'
192
+ default[:#{app_name}][:database][:pool] = '25'
193
+ default[:#{app_name}][:database][:timeout] = '5000'
194
+
195
+ default[:#{app_name}][:cache][:host] = 'localhost'
196
+ default[:#{app_name}][:cache][:port] = '6379'
197
+ default[:#{app_name}][:cache][:database] = '0'
198
+ default[:#{app_name}][:cache][:sidekiq_concurrency] = '25'
199
+
200
+ default[:#{app_name}][:web][:ruby_version] = '2.1.0'
201
+ default[:#{app_name}][:web][:puma_threads_min] = '0'
202
+ default[:#{app_name}][:web][:puma_threads_max] = '16'
203
+ default[:#{app_name}][:web][:puma_workers] = '2'
204
+ default[:#{app_name}][:web][:mail_address] = 'smtp.#{app_name}.com'
205
+ default[:#{app_name}][:web][:mail_port] = '25'
206
+ default[:#{app_name}][:web][:mail_domain] = '#{app_name}.com'
207
+ default[:#{app_name}][:web][:mail_username] = 'info@#{app_name}.com'
208
+ default[:#{app_name}][:web][:mail_auth] = 'plain'
209
+ default[:#{app_name}][:web][:mail_startttls_auto] = 'true'
210
+ default[:#{app_name}][:web][:action_mailer_host] = 'www.#{app_name}.com'
211
+ default[:#{app_name}][:web][:action_mailer_default_email] = 'info@#{app_name}.com'
212
+ default[:#{app_name}][:web][:action_mailer_devise_default_email] = 'info@#{app_name}.com'
213
+ CODE
214
+ end
215
+
216
+ git add: '.'
217
+ git commit: "-m 'Add tweakable settings to the attributes file'"
218
+
219
+ # ----- Create dummy data for the encrypted data bag --------------------------------------------------
220
+
221
+ puts
222
+ say_status 'data_bags', 'Creating dummy encrypted data bag...', :yellow
223
+ puts '-'*80, ''; sleep 0.25
224
+
225
+ data_bag_path = "data_bags/#{app_name}_secrets"
226
+
227
+ run "mkdir -p #{data_bag_path}"
228
+
229
+ file "#{data_bag_path}/production.json" do <<-JSON
230
+ {
231
+ "id": "production",
232
+ "database_password": "<real password is protected>",
233
+ "cache_password": "<real password is protected>",
234
+ "mail_password": "<real password is protected>",
235
+ "token_rails_secret": "<real token is protected>",
236
+ "token_devise_secret": "<real token is protected>",
237
+ "token_devise_pepper": "<real token is protected>"
238
+ }
239
+ JSON
240
+ end
241
+
242
+ git add: '.'
243
+ git commit: "-m 'Add the dummy data bag as a point of reference'"
244
+
245
+ # ----- Create nginx config ---------------------------------------------------------------------------
246
+
247
+ puts
248
+ say_status 'files', 'Creating nginx config...', :yellow
249
+ puts '-'*80, ''; sleep 0.25
250
+
251
+ file "files/default/nginx_virtualhost.conf" do <<-CONF
252
+ upstream #{app_name} {
253
+ server unix:///tmp/#{app_name}.sock;
254
+ }
255
+
256
+ # redirect non-www to www (remove this block if you do not want to do this)
257
+ server {
258
+ listen 80;
259
+ server_name #{app_name}.com;
260
+ return 301 $scheme://www.#{app_name}.com$request_uri;
261
+ }
262
+
263
+ server {
264
+ listen 80;
265
+ server_name www.#{app_name}.com;
266
+ root /home/#{random_username}/www/#{app_name}/current/public;
267
+
268
+ error_page 404 /404.html;
269
+ error_page 500 /500.html;
270
+ error_page 502 503 504 /502.html;
271
+
272
+ location ~ ^/(system|assets)/ {
273
+ root /home/#{random_username}/www/#{app_name}/current/public;
274
+ gzip_static on;
275
+ expires 1y;
276
+ add_header Cache-Control public;
277
+ add_header ETag "";
278
+ break;
279
+ }
280
+
281
+ try_files $uri @puma;
282
+
283
+ location @puma {
284
+ proxy_set_header X-Real-IP $remote_addr;
285
+ proxy_set_header X-Forwarded-Proto http;
286
+ proxy_set_header Host $http_host;
287
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
288
+ proxy_redirect off;
289
+
290
+ proxy_pass http://#{app_name};
291
+ break;
292
+ }
293
+ }
294
+ CONF
295
+ end
296
+
297
+ git add: '.'
298
+ git commit: "-m 'Add the nginx virtualhost config'"
299
+
300
+ # ----- Create system wide profile -------------------------------------------------------------------------
301
+
302
+ puts
303
+ say_status 'templates', 'Creating system wide profile config', :yellow
304
+ puts '-'*80, ''; sleep 0.25
305
+
306
+ file 'templates/default/profile.erb' do <<-CONF
307
+ # /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
308
+ # and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
309
+
310
+ if [ "$PS1" ]; then
311
+ if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ]; then
312
+ # The file bash.bashrc already sets the default PS1.
313
+ # PS1='\h:\w\$ '
314
+ if [ -f /etc/bash.bashrc ]; then
315
+ . /etc/bash.bashrc
316
+ fi
317
+ else
318
+ if [ "`id -u`" -eq 0 ]; then
319
+ PS1='# '
320
+ else
321
+ PS1='$ '
322
+ fi
323
+ fi
324
+ fi
325
+
326
+ # The default umask is now handled by pam_umask.
327
+ # See pam_umask(8) and /etc/login.defs.
328
+
329
+ if [ -d /etc/profile.d ]; then
330
+ for i in /etc/profile.d/*.sh; do
331
+ if [ -r $i ]; then
332
+ . $i
333
+ fi
334
+ done
335
+ unset i
336
+ fi
337
+
338
+ export <%= @cookbook_name.upcase %>_TOKEN_RAILS_SECRET='<%= @token_rails_secret %>'
339
+ export <%= @cookbook_name.upcase %>_TOKEN_DEVISE_SECRET='<%= @token_devise_secret %>'
340
+ export <%= @cookbook_name.upcase %>_TOKEN_DEVISE_PEPPER='<%= @token_devise_pepper %>'
341
+
342
+ export <%= @cookbook_name.upcase %>_SMTP_ADDRESS='<%= node[:#{app_name}][:web][:mail_address] %>'
343
+ export <%= @cookbook_name.upcase %>_SMTP_PORT='<%= node[:#{app_name}][:web][:mail_port] %>'
344
+ export <%= @cookbook_name.upcase %>_SMTP_DOMAIN='<%= node[:#{app_name}][:web][:mail_domain] %>'
345
+ export <%= @cookbook_name.upcase %>_SMTP_USERNAME='<%= node[:#{app_name}][:web][:mail_username] %>'
346
+ export <%= @cookbook_name.upcase %>_SMTP_PASSWORD='<%= @mail_password %>'
347
+ export <%= @cookbook_name.upcase %>_SMTP_AUTH='<%= node[:#{app_name}][:web][:mail_auth] %>'
348
+ export <%= @cookbook_name.upcase %>_SMTP_STARTTTLS_AUTO='<%= node[:#{app_name}][:web][:mail_startttls_auto] %>'
349
+
350
+ export <%= @cookbook_name.upcase %>_ACTION_MAILER_HOST='<%= node[:#{app_name}][:web][:action_mailer_host] %>'
351
+ export <%= @cookbook_name.upcase %>_ACTION_MAILER_DEFAULT_EMAIL='<%= node[:#{app_name}][:web][:action_mailer_default_email] %>'
352
+ export <%= @cookbook_name.upcase %>_ACTION_MAILER_DEVISE_DEFAULT_EMAIL='<%= node[:#{app_name}][:web][:action_mailer_devise_default_email] %>'
353
+
354
+ export <%= @cookbook_name.upcase %>_DATABASE_HOST='<%= node[:#{app_name}][:database][:host] %>'
355
+ export <%= @cookbook_name.upcase %>_DATABASE_NAME='<%= @cookbook_name.downcase %>'
356
+ export <%= @cookbook_name.upcase %>_DATABASE_USERNAME='postgres'
357
+ export <%= @cookbook_name.upcase %>_DATABASE_PASSWORD='<%= @database_password %>'
358
+ export <%= @cookbook_name.upcase %>_DATABASE_POOL='<%= node[:#{app_name}][:database][:pool] %>'
359
+ export <%= @cookbook_name.upcase %>_DATABASE_TIMEOUT='<%= node[:#{app_name}][:database][:timeout] %>'
360
+
361
+ export <%= @cookbook_name.upcase %>_CACHE_HOST='<%= node[:#{app_name}][:cache][:host] %>'
362
+ export <%= @cookbook_name.upcase %>_CACHE_DATABASE='<%= node[:#{app_name}][:cache][:database] %>'
363
+ export <%= @cookbook_name.upcase %>_CACHE_USERNAME='redis'
364
+ export <%= @cookbook_name.upcase %>_CACHE_PASSWORD='<%= @cache_password %>'
365
+
366
+ export <%= @cookbook_name.upcase %>_SIDEKIQ_CONCURRENCY='<%= node[:#{app_name}][:cache][:sidekiq_concurrency] %>'
367
+
368
+ export <%= @cookbook_name.upcase %>_PUMA_THREADS_MIN='<%= node[:#{app_name}][:web][:puma_threads_min] %>'
369
+ export <%= @cookbook_name.upcase %>_PUMA_THREADS_MAX='<%= node[:#{app_name}][:web][:puma_threads_max] %>'
370
+ export <%= @cookbook_name.upcase %>_PUMA_WORKERS='<%= node[:#{app_name}][:web][:puma_workers] %>'
371
+ CONF
372
+ end
373
+
374
+ git add: '.'
375
+ git commit: "-m 'Add the system wide profile config'"
376
+
377
+ # ----- Create base recipe ----------------------------------------------------------------------------
378
+
379
+ puts
380
+ say_status 'recipes', 'Creating base recipe...', :yellow
381
+ puts '-'*80, ''; sleep 0.25
382
+
383
+ file 'recipes/base.rb' do <<-'CODE'
384
+ # openssh
385
+
386
+ node.override[:openssh][:server][:port] = node[:app_name][:base][:ssh_port]
387
+ node.override[:openssh][:server][:password_authentication] = 'no'
388
+ node.override[:openssh][:server][:permit_root_login] = 'no'
389
+ include_recipe 'openssh'
390
+
391
+ # user
392
+
393
+ include_recipe 'user'
394
+
395
+ user_account node[:app_name][:base][:username] do
396
+ ssh_keys [ node[:app_name][:base][:ssh_key] ]
397
+ end
398
+
399
+ # sudo
400
+
401
+ node.override[:authorization][:sudo][:users] = [ node[:app_name][:base][:username] ]
402
+ node.override[:authorization][:sudo][:passwordless] = true
403
+
404
+ include_recipe 'sudo'
405
+
406
+ # fail2ban
407
+
408
+ include_recipe 'fail2ban'
409
+
410
+ # ufw
411
+
412
+ node.override[:firewall][:rules] = [
413
+ {
414
+ 'ssh' => {
415
+ 'port'=> node[:app_name][:base][:ssh_port]
416
+ }
417
+ },
418
+ {
419
+ 'http' => {
420
+ 'port'=> '80'
421
+ }
422
+ }
423
+ ]
424
+ include_recipe 'ufw'
425
+
426
+ # swapfile
427
+ swap_file '/mnt/swap' do
428
+ size node[:app_name][:base][:swap_size]
429
+ end
430
+
431
+ # htop
432
+ package 'htop'
433
+ CODE
434
+ end
435
+
436
+ gsub_file 'recipes/base.rb', 'app_name', app_name
437
+
438
+ git add: '.'
439
+ git commit: "-m 'Add the base recipe'"
440
+
441
+ # ----- Create database recipe ------------------------------------------------------------------------
442
+
443
+ puts
444
+ say_status 'recipes', 'Creating database recipe...', :yellow
445
+ puts '-'*80, ''; sleep 0.25
446
+
447
+ file 'recipes/database.rb' do <<-CODE
448
+ # This is where you will store a copy of your key on the chef-client
449
+ secret = Chef::EncryptedDataBagItem.load_secret('/etc/chef/encrypted_data_bag_secret')
450
+
451
+ # This decrypts the data bag contents of "#{app_name}_secrets/production.json" and uses the key defined at variable "secret"
452
+ encrypted_data_bag = Chef::EncryptedDataBagItem.load('#{app_name}_secrets', 'production', secret)
453
+
454
+ include_recipe '#{app_name}::base'
455
+ include_recipe 'postgresql'
456
+ include_recipe 'postgresql::client'
457
+ include_recipe 'postgresql::server'
458
+ include_recipe 'postgresql::libpq'
459
+
460
+ pg_user 'postgres' do
461
+ privileges superuser: true, createdb: true, login: true
462
+ password encrypted_data_bag['database_password']
463
+ end
464
+ CODE
465
+ end
466
+
467
+ git add: '.'
468
+ git commit: "-m 'Add the database recipe'"
469
+
470
+ # ----- Create cache recipe ---------------------------------------------------------------------------
471
+
472
+ puts
473
+ say_status 'recipes', 'Creating cache recipe...', :yellow
474
+ puts '-'*80, ''; sleep 0.25
475
+
476
+ file 'recipes/cache.rb' do <<-CODE
477
+ include_recipe '#{app_name}::base'
478
+
479
+ node.override[:redisio][:mirror] = 'http://download.redis.io/releases'
480
+ node.override[:redisio][:version] = '2.8.3'
481
+ include_recipe 'redisio::install'
482
+ include_recipe 'redisio::enable'
483
+ CODE
484
+ end
485
+
486
+ git add: '.'
487
+ git commit: "-m 'Add the cache recipe'"
488
+
489
+ # ----- Create web recipe -----------------------------------------------------------------------------
490
+
491
+ puts
492
+ say_status 'recipes', 'Creating web recipe...', :yellow
493
+ puts '-'*80, ''; sleep 0.25
494
+
495
+ file 'recipes/web.rb' do <<-'CODE'
496
+ secret = Chef::EncryptedDataBagItem.load_secret('/etc/chef/encrypted_data_bag_secret')
497
+ encrypted_data_bag = Chef::EncryptedDataBagItem.load('app_name_secrets', 'production', secret)
498
+
499
+ include_recipe 'app_name::base'
500
+
501
+ # environment variables
502
+
503
+ template '/etc/profile' do
504
+ source 'profile.erb'
505
+ variables({
506
+ :cookbook_name => cookbook_name,
507
+ :database_password => encrypted_data_bag['database_password'],
508
+ :cache_password => encrypted_data_bag['cache_password'],
509
+ :mail_password => encrypted_data_bag['mail_password'],
510
+ :token_rails_secret => encrypted_data_bag['token_rails_secret'],
511
+ :token_devise_secret => encrypted_data_bag['token_devise_secret'],
512
+ :token_devise_pepper => encrypted_data_bag['token_devise_pepper']
513
+ })
514
+ end
515
+
516
+ # git
517
+
518
+ apt_repository 'git' do
519
+ uri 'http://ppa.launchpad.net/git-core/ppa/ubuntu'
520
+ distribution node[:lsb][:codename]
521
+ components %w[main]
522
+ keyserver 'keyserver.ubuntu.com'
523
+ key 'E1DF1F24'
524
+ action :add
525
+ end
526
+
527
+ include_recipe 'git'
528
+
529
+ repo_path = "/home/#{node[:app_name][:base][:username]}/#{cookbook_name}.git"
530
+
531
+ directory repo_path do
532
+ owner node[:app_name][:base][:username]
533
+ group node[:app_name][:base][:username]
534
+ mode 0755
535
+ end
536
+
537
+ execute 'initialize new bare git repo' do
538
+ user node[:app_name][:base][:username]
539
+ group node[:app_name][:base][:username]
540
+ command "cd #{repo_path} && git init --bare"
541
+ only_if { !File.exists? "#{repo_path}/HEAD" }
542
+ end
543
+
544
+ # node
545
+
546
+ node.override[:nodejs][:install_method] = 'binary'
547
+ node.override[:nodejs][:version] = '0.10.24'
548
+ node.override[:nodejs][:checksum] = 'fb6487e72d953451d55e28319c446151c1812ed21919168b82ab1664088ecf46'
549
+ node.override[:nodejs][:checksum_linux_x64] = '423018f6a60b18d0dddf3007c325e0cc8cf55099'
550
+ node.override[:nodejs][:checksum_linux_x86] = 'fb6487e72d953451d55e28319c446151c1812ed21919168b82ab1664088ecf46'
551
+ include_recipe 'nodejs::install_from_binary'
552
+
553
+ # ruby
554
+
555
+ node.override[:rvm][:default_ruby] = node[:app_name][:web][:ruby_version]
556
+ node.override[:rvm][:global_gems] = [ { 'name' => 'bundler', 'version' => '1.5.1' } ]
557
+ node.override[:rvm][:group_users] = [ node[:app_name][:base][:username] ]
558
+
559
+ include_recipe 'rvm::system'
560
+
561
+ # nginx
562
+
563
+ apt_repository 'nginx' do
564
+ uri 'http://ppa.launchpad.net/nginx/stable/ubuntu'
565
+ distribution node[:lsb][:codename]
566
+ components %w[main]
567
+ keyserver 'keyserver.ubuntu.com'
568
+ key 'C300EE8C'
569
+ action :add
570
+ end
571
+
572
+ node.override[:nginx][:gzip_comp_level] = '4'
573
+
574
+ include_recipe 'nginx'
575
+
576
+ cookbook_file 'nginx_virtualhost.conf' do
577
+ path "#{node[:nginx][:dir]}/sites-available/#{cookbook_name}.conf"
578
+ group node[:nginx][:user]
579
+ owner node[:nginx][:user]
580
+ mode '0644'
581
+ end
582
+
583
+ nginx_site "#{cookbook_name}.conf"
584
+
585
+ include_recipe 'logrotate'
586
+
587
+ logrotate_app 'nginx' do
588
+ cookbook 'logrotate'
589
+ path ["#{node[:nginx][:log_dir]}/access.log", "#{node[:nginx][:log_dir]}/error.log"]
590
+ options ['missingok', 'notifempty']
591
+ frequency 'daily'
592
+ create '0644 root adm'
593
+ rotate 365
594
+ end
595
+ CODE
596
+ end
597
+
598
+ gsub_file 'recipes/web.rb', 'app_name', app_name
599
+
600
+ git add: '.'
601
+ git commit: "-m 'Add the web recipe'"
602
+
603
+ # ----- Create default recipe -------------------------------------------------------------------------
604
+
605
+ puts
606
+ say_status 'recipes', 'Creating default recipe...', :yellow
607
+ puts '-'*80, ''; sleep 0.25
608
+
609
+ run 'rm -f recipes/default.rb'
610
+ file 'recipes/default.rb' do <<-CODE
611
+ include_recipe '#{app_name}::database'
612
+ include_recipe '#{app_name}::cache'
613
+ include_recipe '#{app_name}::web'
614
+ CODE
615
+ end
616
+
617
+ git add: '.'
618
+ git commit: "-m 'Add the default recipe'"
619
+
620
+ # ----- Installation complete message -----------------------------------------------------------------
621
+
622
+ puts
623
+ say_status 'success', "\e[1m\Everything has been setup successfully\e[0m", :cyan
624
+ puts
625
+ say_status 'question', 'Are you new to chef and berkshelf?', :yellow
626
+ say_status 'answer', 'Check the orats wiki for the walk through', :white
627
+ puts
628
+ say_status 'question', 'Are you somewhat experienced with chef?', :yellow
629
+ say_status 'answer', 'Setup your encrypted data bag and bootstrap the node', :white
630
+ puts '-'*80
data/lib/orats/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Orats
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orats
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Janetakis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-11 00:00:00.000000000 Z
11
+ date: 2014-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -72,8 +72,9 @@ files:
72
72
  - lib/orats/cli.rb
73
73
  - lib/orats/server.rb
74
74
  - lib/orats/shell.rb
75
- - lib/orats/templates/commands/auth.rb
76
- - lib/orats/templates/commands/base.rb
75
+ - lib/orats/templates/auth.rb
76
+ - lib/orats/templates/base.rb
77
+ - lib/orats/templates/cook.rb
77
78
  - lib/orats/templates/includes/Gemfile
78
79
  - lib/orats/version.rb
79
80
  - orats.gemspec