pushapp 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a90bcaeac4b94c006852afa1b39a6a6e47fac27f
4
- data.tar.gz: 8c252eb2cf6063b113b125194e918b43d096ec88
3
+ metadata.gz: 6087f97376d51ff71653aa1e8bae7d43fad3996f
4
+ data.tar.gz: 3bf44bdfe73b940d6aa433a3fc38f623c61e83d4
5
5
  SHA512:
6
- metadata.gz: fc6c2a10d4e21936629acc2ac1d3077d1a189040d5dd88e6050196c3f9ce784ac705251cba3c1076fa56ee9cc2aa12eb144f1fc8d80d0f1c2b191b82d542183b
7
- data.tar.gz: 717c1c269b6153a34d652565871d1e31e575918de16e0222ffc0886f3fbc60317c482b94dfb123c87c25d237a20e463063a22253515327ad34dc01c771d5126d
6
+ metadata.gz: dc18dcdb79729f45675bee73c64242ed9de16a614a5d4b99a9c18d06636d1bd8b56968d38c7c56f31f8a222875c1fecbad345d1d4d3c250a99c421bb4b0ae635
7
+ data.tar.gz: d51bbec53b29f95e312ea6eaa44c0f42e48a98552bf6862956a23d9db481736a06668e5b296b38658ffc4716433f0f533d68700edfd8fc97744e0b3101bdd465
@@ -1,5 +1,6 @@
1
1
  require 'thor'
2
2
  require 'pushapp/commands'
3
+ require 'pushapp/generators'
3
4
 
4
5
  module Pushapp
5
6
  class CLI < Thor
@@ -66,5 +67,8 @@ module Pushapp
66
67
  def ssh(remote=nil)
67
68
  Pushapp::Commands.run(:ssh, remote: remote, options: options)
68
69
  end
70
+
71
+ desc "generate MODULE REMOTE", "bootstrapp app with varios optimizaed configs"
72
+ subcommand "generate", Generators
69
73
  end
70
74
  end
@@ -0,0 +1,258 @@
1
+ require 'thor'
2
+ require 'awesome_print'
3
+ require 'json'
4
+
5
+ module Pushapp
6
+ class Generators < Thor
7
+ include Thor::Actions
8
+
9
+ source_root Pushapp::TEMPLATE_ROOT
10
+
11
+ class_option :file, default: Pushapp::DEFAULT_CONFIG_LOCATION,
12
+ type: :string, aliases: '-f', banner: 'Specify a pushapp configuration file'
13
+
14
+ desc 'unicorn-nginx REMOTE', 'generates nginx config for unicorn'
15
+ method_option :host, desc: 'Nginx host, will use remote host as default.'
16
+ method_option :env, desc: "unicorn env, will use remote RAILS_ENV as default."
17
+ method_option :listen, default: '80', desc: "Nginx port to listen. Default: 80"
18
+
19
+ def unicorn_nginx(remote)
20
+ options[:remote] = remote
21
+ template 'unicorn_nginx.conf.erb', "config/deploys/#{app_name}.nginx.conf"
22
+ end
23
+
24
+ desc "unicorn-upstart", "generates unicorn binary for upstart/foreman"
25
+ def unicorn_upstart
26
+ template 'unicorn_upstart.erb', 'bin/unicorn_upstart'
27
+ chmod 'bin/unicorn_upstart', 'a+x'
28
+ end
29
+
30
+ desc "unicorn REMOTE", "generates unicorn config"
31
+ def unicorn(remote)
32
+ options[:remote] = remote
33
+ template 'unicorn.rb.erb', 'config/unicorn.rb'
34
+ end
35
+
36
+ desc "chef-solor REMOTE", "generates chef-solor with knife-solo configs"
37
+ method_option :database,
38
+ type: :string,
39
+ default: 'postgresql',
40
+ desc: 'mysql or postgresql',
41
+ aliases: '-d'
42
+
43
+ method_option :ssh_pub_key,
44
+ type: :string,
45
+ default: "#{ENV['HOME']}/.ssh/id_rsa.pub"
46
+
47
+ method_option :vagrant_box,
48
+ type: :string,
49
+ default: "opscode_ubuntu-12.04-i386_chef-11.4.4"
50
+
51
+ method_option :vagrant_box_url,
52
+ type: :string,
53
+ default: "https://opscode-vm.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04-i386_chef-11.4.4.box"
54
+
55
+ method_option :db_password,
56
+ type: :string,
57
+ default: 'password1'
58
+
59
+ method_option :ruby,
60
+ type: :string,
61
+ default: '2.0.0-p0'
62
+
63
+ def chef_solo(remote)
64
+ options[:remote] = remote
65
+
66
+ template 'Cheffile.erb', 'config/deploys/chef/Cheffile'
67
+ template 'Vagrantfile.erb', 'config/deploys/chef/Vagrantfile'
68
+ template 'node.json.erb', "config/deploys/chef/nodes/#{app_host}.json"
69
+ template 'user.json.erb', "config/deploys/chef/data_bags/users/#{app_user}.json"
70
+
71
+ template 'chef.gitignore', 'config/deploys/chef/.gitignore'
72
+ end
73
+
74
+ private
75
+
76
+ def app_name
77
+ remote.path.split('/').last
78
+ end
79
+
80
+ def app_user
81
+ remote.user
82
+ end
83
+
84
+ def app_host
85
+ options[:host] || remote.host || '127.0.0.1'
86
+ end
87
+
88
+ def app_path
89
+ remote.path
90
+ end
91
+
92
+ def app_env
93
+ remote.env['RACK_ENV'] || remote.env['RAILS_ENV'] || 'production'
94
+ end
95
+
96
+ def remote
97
+ @remote ||= config.remotes_named_by(options[:remote]).first
98
+ end
99
+
100
+ def config
101
+ @config ||= Pushapp::Config.parse(options[:file])
102
+ end
103
+
104
+ def mysql?
105
+ options[:database] == 'mysql'
106
+ end
107
+
108
+ def postgresql?
109
+ options[:database] == 'postgresql'
110
+ end
111
+
112
+ def postgresql_config
113
+ {
114
+ config: {
115
+ listen_addresses: "*",
116
+ port: "5432"
117
+ },
118
+ pg_hba: [
119
+ {
120
+ type: "local",
121
+ db: "postgres",
122
+ user: "postgres",
123
+ addr: nil,
124
+ method: "trust"
125
+ },
126
+ {
127
+ type: "host",
128
+ db: "all",
129
+ user: "all",
130
+ addr: "0.0.0.0/0",
131
+ method: "md5"
132
+ },
133
+ {
134
+ type: "host",
135
+ db: "all",
136
+ user: "all",
137
+ addr: "::1/0",
138
+ method: "md5"
139
+ }
140
+ ],
141
+ password: {
142
+ postgres: options[:db_password]
143
+ }
144
+ }
145
+ end
146
+
147
+ def mysql_config
148
+ {
149
+ :server_root_password => options[:db_password],
150
+ :server_repl_password => options[:db_password],
151
+ :server_debian_password => options[:db_password],
152
+ :service_name => "mysql",
153
+ :basedir => "/usr",
154
+ :data_dir => "/var/lib/mysql",
155
+ :root_group => "root",
156
+ :mysqladmin_bin => "/usr/bin/mysqladmin",
157
+ :mysql_bin => "/usr/bin/mysql",
158
+ :conf_dir => "/etc/mysql",
159
+ :confd_dir => "/etc/mysql/conf.d",
160
+ :socket => "/var/run/mysqld/mysqld.sock",
161
+ :pid_file => "/var/run/mysqld/mysqld.pid",
162
+ :grants_path => "/etc/mysql/grants.sql"
163
+ }
164
+ end
165
+
166
+ def authorization_config
167
+ {
168
+ sudo: {
169
+ users: [app_user],
170
+ passwordless: true
171
+ }
172
+ }
173
+ end
174
+
175
+ def common_config
176
+ cfg = {
177
+ nginx: {
178
+ dir: "/etc/nginx",
179
+ log_dir: "/var/log/nginx",
180
+ binary: "/usr/sbin/nginx",
181
+ user: "www-data",
182
+ pid: "/var/run/nginx.pid",
183
+ worker_connections: "1024"
184
+ },
185
+ git: {
186
+ prefix: "/usr/local"
187
+ },
188
+ }
189
+ cfg[:mysql] = mysql_config if mysql?
190
+ cfg[:postgresql] = postgresql_config if postgresql?
191
+ cfg
192
+ end
193
+
194
+ def chef_config
195
+ common_config.merge({
196
+ authorization: authorization_config,
197
+ rbenv: rbenv_config(app_user)
198
+ })
199
+ end
200
+
201
+ def config_json
202
+ chef_config.merge({
203
+ run_list: run_list
204
+ })
205
+ end
206
+
207
+ def vagrant_config
208
+ # common_config.merge({
209
+ # rbenv: rbenv_config('vagrant')
210
+ # })
211
+ chef_config
212
+ end
213
+
214
+ def run_list
215
+ [
216
+ "apt",
217
+ "chef-solo-search",
218
+ "locale",
219
+ "users::sysadmins",
220
+ "sudo",
221
+ "runit",
222
+ mysql? ? "mysql::server" : nil,
223
+ postgresql? ? "postgresql::server" : nil,
224
+ "imagemagick",
225
+ "ruby_build",
226
+ "rbenv::user",
227
+ "nginx::repo",
228
+ "nginx",
229
+ "git"
230
+ ].compact
231
+ end
232
+
233
+ def user_json
234
+ {
235
+ id: app_user,
236
+ comment: "Application User",
237
+ ssh_keys: [File.read(options[:ssh_pub_key])],
238
+ groups: ["sysadmin", "sudo", "staff"],
239
+ shell: "/bin/bash"
240
+ }
241
+ end
242
+
243
+
244
+ def rbenv_config(user)
245
+ {
246
+ user_installs: [{
247
+ user: user,
248
+ rubies: [ options[:ruby] ],
249
+ global: options[:ruby],
250
+ environment: { CFLAGS: "-march=native -O2 -pipe" },
251
+ gems: {
252
+ options[:ruby] => [{name: "bundler", version: "1.3.5"}]
253
+ }
254
+ }]
255
+ }
256
+ end
257
+ end
258
+ end
@@ -1,3 +1,3 @@
1
1
  module Pushapp
2
- VERSION = '0.0.6'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency 'thor'
22
+ spec.add_dependency 'awesome_print'
22
23
 
23
24
  spec.add_development_dependency 'bundler', '~> 1.3'
24
25
  spec.add_development_dependency 'rake'
@@ -0,0 +1,17 @@
1
+ site 'http://community.opscode.com/api/v1'
2
+
3
+ cookbook "apt"
4
+ <% if options[:database] == 'mysql' %>
5
+ cookbook "mysql", {}
6
+ <% elsif options[:database] == 'postgresql' %>
7
+ cookbook "postgresql", {}
8
+ <% end %>
9
+ cookbook "sudo", {:gihub => "patcon/chef-sudo"}
10
+ cookbook "locale", {:github => "yury/hw-chef-locale"}
11
+ cookbook "imagemagick"
12
+ cookbook "chef-solo-search", {:github => "edelight/chef-solo-search"}
13
+ cookbook "users"
14
+ cookbook "ruby_build", {:github=>"fnichol/chef-ruby_build", :ref=>"v0.7.2"}
15
+ cookbook "rbenv", {:github=>"fnichol/chef-rbenv"}
16
+ cookbook "nginx", {:github=> "opscode-cookbooks/nginx"}
17
+ cookbook "git", {}
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ # -*- mode: ruby -*-
4
+ # vi: set ft=ruby :
5
+
6
+ Vagrant::Config.run do |config|
7
+
8
+ config.vm.box = "<%= options[:vagrant_box] %>"
9
+ config.vm.box_url = "<%= options[:vagrant_box_url] %>"
10
+ # config.ssh.forward_agent = true
11
+
12
+ config.vm.provision :chef_solo do |chef|
13
+ chef.cookbooks_path = ["cookbooks"]
14
+ chef.data_bags_path = "data_bags"
15
+ <% run_list.each do |recipe| -%>
16
+ chef.add_recipe '<%= recipe %>'
17
+ <% end -%>
18
+ chef.json = <%= AwesomePrint::Inspector.new(plain: true, index: false, indent: -2).awesome(vagrant_config).gsub("\n", "\n ") %>
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ .vagrant
2
+ tmp
3
+ cookbooks
@@ -0,0 +1 @@
1
+ <%= JSON.pretty_generate(config_json) %>
@@ -0,0 +1,70 @@
1
+ # Sample configuration file for Unicorn (not Rack)
2
+ #
3
+ # See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
4
+ # documentation.
5
+ env ||= ENV["RACK_ENV"] || "development"
6
+ root = File.expand_path('../..', __FILE__)
7
+ # Use at least one worker per core if you're on a dedicated server,
8
+ # more will usually help for _short_ waits on databases/caches.
9
+ worker_processes 4
10
+
11
+ # Help ensure your application will always spawn in the symlinked
12
+ # "current" directory that Capistrano sets up.
13
+ working_directory root # available in 0.94.0+
14
+
15
+ # listen on both a Unix domain socket and a TCP port,
16
+ # we use a shorter backlog for quicker failover when busy
17
+ listen "/tmp/unicorn.<%= app_name %>.#{app_env}.sock", :backlog => 64
18
+
19
+ # nuke workers after 60 seconds (the default)
20
+ timeout 60
21
+
22
+ # feel free to point this anywhere accessible on the filesystem
23
+ pid "#{root}/tmp/pids/unicorn.pid"
24
+
25
+ # some applications/frameworks log to stderr or stdout, so prevent
26
+ # them from going to /dev/null when daemonized here:
27
+ stderr_path "#{root}/log/unicorn.stderr.log"
28
+ stdout_path "#{root}/log/unicorn.stdout.log"
29
+
30
+ # combine REE with "preload_app true" for memory savings
31
+ # http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
32
+ preload_app true
33
+ GC.respond_to?(:copy_on_write_friendly=) and
34
+ GC.copy_on_write_friendly = true
35
+
36
+ before_fork do |server, worker|
37
+ Kernel.rand
38
+ # the following is highly recomended for Rails + "preload_app true"
39
+ # as there's no need for the master process to hold a connection
40
+ defined?(ActiveRecord::Base) and
41
+ ActiveRecord::Base.connection.disconnect!
42
+
43
+ # The following is only recommended for memory/DB-constrained
44
+ # installations. It is not needed if your system can house
45
+ # twice as many worker_processes as you have configured.
46
+ #
47
+ # # This allows a new master process to incrementally
48
+ # # phase out the old master process with SIGTTOU to avoid a
49
+ # # thundering herd (especially in the "preload_app false" case)
50
+ # # when doing a transparent upgrade. The last worker spawned
51
+ # # will then kill off the old master process with a SIGQUIT.
52
+ old_pid = "#{server.config[:pid]}.oldbin"
53
+ if old_pid != server.pid
54
+ begin
55
+ sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
56
+ Process.kill(sig, File.read(old_pid).to_i)
57
+ rescue Errno::ENOENT, Errno::ESRCH
58
+ end
59
+ end
60
+ #
61
+ # # *optionally* throttle the master from forking too quickly by sleeping
62
+ sleep 1
63
+ end
64
+
65
+ after_fork do |server, worker|
66
+ Kernel.rand
67
+ # the following is *required* for Rails + "preload_app true",
68
+ defined?(ActiveRecord::Base) and
69
+ ActiveRecord::Base.establish_connection
70
+ end
@@ -0,0 +1,40 @@
1
+ upstream <%= app_name %>-unicorn {
2
+ server unix:/tmp/unicorn.<%= app_name %>.<%= app_env %>.sock fail_timeout=0;
3
+ }
4
+
5
+ server {
6
+ listen <%= options[:listen] %>;
7
+ server_name www.<%= app_host %>;
8
+ rewrite ^(.*) http://<%= app_host %>$1 permanent;
9
+ }
10
+
11
+ server {
12
+ listen <%= options[:listen] %>;
13
+ server_name <%= app_host %>;
14
+
15
+ root <%=app_path%>/public;
16
+
17
+ location /assets {
18
+ location ~ \.(js|css|otf|ttf|eot|woff|svg)$ {
19
+ gzip_static on; # to serve pre-gzipped version
20
+ }
21
+
22
+ expires max;
23
+ add_header Cache-Control public;
24
+ }
25
+
26
+ try_files $uri/index.html $uri.html $uri @app;
27
+
28
+ location @app {
29
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
30
+ proxy_set_header Host $http_host;
31
+ add_header X-UA-Compatible IE=Edge,chrome=1;
32
+ add_header imagetoolbar no;
33
+ proxy_redirect off;
34
+ proxy_pass http://<%= app_name %>-unicorn;
35
+ }
36
+
37
+ error_page 500 502 503 504 /500.html;
38
+ client_max_body_size 4G;
39
+ keepalive_timeout 10;
40
+ }
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+
3
+ if [ -f tmp/pids/unicorn.pid ]; then
4
+ unicorn_pid_file=tmp/pids/unicorn.pid
5
+ # Someone restarted the master; wait for the new master to exit.
6
+ PID=`cat $unicorn_pid_file`
7
+
8
+ while kill -0 $PID; do
9
+ sleep 2
10
+ PID=`cat $unicorn_pid_file`
11
+ done
12
+
13
+ # If we get here, the master has exited, either because someone restarted
14
+ # it again (in which case there's already a new master running), or
15
+ # it died for real (in which case we'll need to start a new process).
16
+ # The sleep above is a tradeoff between polling load and mimizing the
17
+ # restart delay when the master dies for real (which should hopefully be
18
+ # rare).
19
+ rm $unicorn_pid_file
20
+ else
21
+ # Run the unicorn master process (this won't return until it exits).
22
+ bundle exec unicorn -E $RAILS_ENV -c config/unicorn.rb
23
+ fi
@@ -0,0 +1 @@
1
+ <%= JSON.pretty_generate(user_json) %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pushapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yury Korolev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-02 00:00:00.000000000 Z
11
+ date: 2013-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: awesome_print
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -85,6 +99,7 @@ files:
85
99
  - lib/pushapp/cli.rb
86
100
  - lib/pushapp/commands.rb
87
101
  - lib/pushapp/config.rb
102
+ - lib/pushapp/generators.rb
88
103
  - lib/pushapp/git.rb
89
104
  - lib/pushapp/hook.rb
90
105
  - lib/pushapp/logger.rb
@@ -99,12 +114,20 @@ files:
99
114
  - lib/pushapp/tasks/upstart.rb
100
115
  - lib/pushapp/version.rb
101
116
  - pushapp.gemspec
117
+ - templates/Cheffile.erb
118
+ - templates/Vagrantfile.erb
119
+ - templates/chef.gitignore
102
120
  - templates/config.rb.erb
103
121
  - templates/hook/base.erb
104
122
  - templates/hook/bundler.erb
105
123
  - templates/hook/git-reset.erb
106
124
  - templates/hook/setup.erb
107
125
  - templates/hook/tasks.erb
126
+ - templates/node.json.erb
127
+ - templates/unicorn.rb.erb
128
+ - templates/unicorn_nginx.conf.erb
129
+ - templates/unicorn_upstart.erb
130
+ - templates/user.json.erb
108
131
  - test/fixtures/empty_config.rb
109
132
  - test/pushapp/cli_test.rb
110
133
  - test/pushapp/config_test.rb