deploify 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +36 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +2 -0
  6. data/Rakefile +1 -0
  7. data/deploify.gemspec +29 -0
  8. data/lib/deploify/capistrano_extensions.rb +189 -0
  9. data/lib/deploify/recipes/deploify.rb +171 -0
  10. data/lib/deploify/recipes/mongodb.rb +15 -0
  11. data/lib/deploify/recipes/monit.rb +84 -0
  12. data/lib/deploify/recipes/mysql.rb +85 -0
  13. data/lib/deploify/recipes/nginx.rb +122 -0
  14. data/lib/deploify/recipes/passenger.rb +130 -0
  15. data/lib/deploify/recipes/puma.rb +15 -0
  16. data/lib/deploify/recipes/rails.rb +221 -0
  17. data/lib/deploify/recipes/thin.rb +104 -0
  18. data/lib/deploify/recipes.rb +13 -0
  19. data/lib/deploify/templates/monit/monit.conf.erb +5 -0
  20. data/lib/deploify/templates/nginx/logrotate.conf.erb +12 -0
  21. data/lib/deploify/templates/nginx/vhost_http_force_ssl.conf.erb +79 -0
  22. data/lib/deploify/templates/nginx/vhost_http_only.conf.erb +66 -0
  23. data/lib/deploify/templates/nginx/vhost_http_with_ssl.conf.erb +131 -0
  24. data/lib/deploify/templates/passenger/logrotate.conf.erb +12 -0
  25. data/lib/deploify/templates/passenger/passengerctl-lib.erb +68 -0
  26. data/lib/deploify/templates/passenger/passengerctl.erb +10 -0
  27. data/lib/deploify/templates/thin/logrotate.conf.erb +0 -0
  28. data/lib/deploify/templates/thin/thinctl-lib.erb +84 -0
  29. data/lib/deploify/templates/thin/thinctl.erb +9 -0
  30. data/lib/deploify/version.rb +12 -0
  31. data/lib/deploify.rb +7 -0
  32. data/lib/plugins/all.rb +20 -0
  33. data/lib/plugins/apt.rb +94 -0
  34. data/lib/plugins/std.rb +203 -0
  35. metadata +196 -0
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in deploify.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ deploify (0.2.0)
5
+ bundler (>= 1.0.21)
6
+ capistrano (~> 2.13.5)
7
+ rvm-capistrano (~> 1.2.7)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ capistrano (2.13.5)
13
+ highline
14
+ net-scp (>= 1.0.0)
15
+ net-sftp (>= 2.0.0)
16
+ net-ssh (>= 2.0.14)
17
+ net-ssh-gateway (>= 1.1.0)
18
+ highline (1.6.15)
19
+ net-scp (1.0.4)
20
+ net-ssh (>= 1.99.1)
21
+ net-sftp (2.0.5)
22
+ net-ssh (>= 2.0.9)
23
+ net-ssh (2.6.2)
24
+ net-ssh-gateway (1.1.0)
25
+ net-ssh (>= 1.99.1)
26
+ rvm-capistrano (1.2.7)
27
+ capistrano (>= 2.0.0)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ bundler (>= 1.0.21)
34
+ capistrano (~> 2.13.5)
35
+ deploify!
36
+ rvm-capistrano (~> 1.2.7)
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Richard Říman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ deploify - capistrano based and deprec inspired deploy gem
2
+ ================================================================================
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/deploify.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'deploify/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "deploify"
8
+ gem.version = Deploify::VERSION
9
+ gem.authors = ["Richard R\314\214i\314\201man"]
10
+ gem.email = ["riman.richard@gmail.com"]
11
+ gem.description = "deploify - capistrano based and deprec inspired deploy solution served as a gem"
12
+ gem.summary = "capistrano based and deprec inspired deploy gem"
13
+ gem.homepage = "https://github.com/richardriman/deploify"
14
+
15
+ gem.required_ruby_version = ">= 1.8.7"
16
+
17
+ gem.add_development_dependency "bundler", ">= 1.0.21"
18
+ gem.add_development_dependency "capistrano", "~> 2.13.5"
19
+ gem.add_development_dependency "rvm-capistrano", "~> 1.2.7"
20
+
21
+ gem.add_dependency "bundler", ">= 1.0.21"
22
+ gem.add_dependency "capistrano", "~> 2.13.5"
23
+ gem.add_dependency "rvm-capistrano", "~> 1.2.7"
24
+
25
+ gem.files = `git ls-files`.split($/)
26
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
27
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
28
+ gem.require_paths = ["lib"]
29
+ end
@@ -0,0 +1,189 @@
1
+ require "capistrano"
2
+
3
+ module Deploify
4
+
5
+ DEPLOIFY_TEMPLATES_BASE = File.join(File.dirname(__FILE__), "templates")
6
+
7
+ # Render template (usually a config file)
8
+ #
9
+ # Usually we render it to a file on the local filesystem.
10
+ # This way, we keep a copy of the config file under source control.
11
+ # We can make manual changes if required and push to new hosts.
12
+ #
13
+ # If the options hash contains :path then it's written to that path.
14
+ # If it contains :remote => true, the file will instead be written to remote targets
15
+ # If options[:path] and options[:remote] are missing, it just returns the rendered
16
+ # template as a string (good for debugging).
17
+ #
18
+ # XXX I would like to get rid of :render_template_to_file
19
+ # XXX Perhaps pass an option to this function to write to remote
20
+ #
21
+ def render_template(app, options={})
22
+ template = options[:template]
23
+ path = options[:path] || nil
24
+ remote = options[:remote] || false
25
+ mode = options[:mode] || 0755
26
+ owner = options[:owner] || nil
27
+ stage = exists?(:stage) ? fetch(:stage).to_s : ''
28
+ # replace this with a check for the file
29
+ unless template
30
+ puts "render_template() requires a value for the template!"
31
+ return false
32
+ end
33
+
34
+ # If local copies of deploifyy templates exist they will be used
35
+ # If you don't specify the location with the local_template_dir option
36
+ # it defaults to config/templates.
37
+ # e.g. config/templates/nginx/nginx.conf.erb
38
+ local_template = File.join(local_template_dir, app.to_s, template)
39
+ if File.exists?(local_template)
40
+ puts
41
+ puts "Using local template (#{local_template})"
42
+ template = ERB.new(IO.read(local_template), nil, '-')
43
+ else
44
+ template = ERB.new(IO.read(File.join(DEPLOIFY_TEMPLATES_BASE, app.to_s, template)), nil, '-')
45
+ end
46
+ rendered_template = template.result(binding)
47
+
48
+ if remote
49
+ # render to remote machine
50
+ puts 'You need to specify a path to render the template to!' unless path
51
+ exit unless path
52
+ sudo "test -d #{File.dirname(path)} || #{sudo} mkdir -p #{File.dirname(path)}"
53
+ std.su_put rendered_template, path, '/tmp/', :mode => mode
54
+ sudo "chown #{owner} #{path}" if defined?(owner)
55
+ elsif path
56
+ # render to local file
57
+ full_path = File.join('config', stage, app.to_s, path)
58
+ path_dir = File.dirname(File.expand_path(full_path))
59
+ if File.exists?(full_path)
60
+ if IO.read(full_path) == rendered_template
61
+ puts "[skip] Identical file exists (#{full_path})."
62
+ return false
63
+ elsif overwrite?(full_path, rendered_template)
64
+ File.delete(full_path)
65
+ else
66
+ puts "[skip] Not overwriting #{full_path}"
67
+ return false
68
+ end
69
+ end
70
+ FileUtils.mkdir_p "#{path_dir}" unless File.directory?(path_dir)
71
+ # added line above to make windows compatible
72
+ # system "mkdir -p #{path_dir}" if ! File.directory?(path_dir)
73
+ File.open(File.expand_path(full_path), 'w') { |f| f.write rendered_template }
74
+ puts "[done] #{full_path} written"
75
+ else
76
+ # render to string
77
+ return rendered_template
78
+ end
79
+ end
80
+
81
+ # Copy configs to server(s). Note there is no :pull task. No changes should
82
+ # be made to configs on the servers so why would you need to pull them back?
83
+ def push_configs(app, files)
84
+ app = app.to_s
85
+ stage = exists?(:stage) ? fetch(:stage).to_s : ''
86
+
87
+ files.each do |file|
88
+ full_local_path = File.join('config', stage, app, file[:path])
89
+ if File.exists?(full_local_path)
90
+ # If the file path is relative we will prepend a path to this projects
91
+ # own config directory for this service.
92
+ if file[:path][0, 1] != '/'
93
+ full_remote_path = File.join(deploy_to, app, file[:path])
94
+ else
95
+ full_remote_path = file[:path]
96
+ end
97
+ sudo "test -d #{File.dirname(full_remote_path)} || #{sudo} mkdir -p #{File.dirname(full_remote_path)}"
98
+ std.su_put File.read(full_local_path), full_remote_path, '/tmp/', :mode => file[:mode]
99
+ sudo "chown #{file[:owner]} #{full_remote_path}"
100
+ else
101
+ # Render directly to remote host.
102
+ render_template(app, file.merge(:remote => true))
103
+ end
104
+ end
105
+ end
106
+
107
+ def overwrite?(full_path, rendered_template)
108
+ if defined?(overwrite_all)
109
+ return overwrite_all ? true : false
110
+ end
111
+
112
+ puts
113
+ response = Capistrano::CLI.ui.ask "File exists (#{full_path}).
114
+ Overwrite? ([y]es, [n]o, [d]iff)" do |q|
115
+ q.default = 'n'
116
+ end
117
+
118
+ case response
119
+ when 'y'
120
+ return true
121
+ when 'n'
122
+ return false
123
+ when 'd'
124
+ require 'tempfile'
125
+ tf = Tempfile.new("deprec_diff")
126
+ tf.puts(rendered_template)
127
+ tf.close
128
+ puts
129
+ puts "Running diff -u current_file new_file_if_you_overwrite"
130
+ puts
131
+ system "diff -u #{full_path} #{tf.path} | less"
132
+ puts
133
+ overwrite?(full_path, rendered_template)
134
+ end
135
+ end
136
+
137
+ # create new user account on target system
138
+ def useradd(user, options={})
139
+ options[:shell] ||= "/bin/bash" # new accounts on ubuntu have been getting /bin/sh
140
+ switches = ''
141
+ switches += " --shell=#{options[:shell]} " if options[:shell]
142
+ unless options[:homedir] == false
143
+ switches += " --create-home "
144
+ switches += " --home #{options[:homedir]} " if options[:homedir]
145
+ end
146
+ switches += " --gid #{options[:group]} " unless options[:group].nil?
147
+ invoke_command "#{sudo} mkdir -p #{File.dirname(options[:homedir])}" if options[:homedir]
148
+ invoke_command "grep '^#{user}:' /etc/passwd || #{sudo} /usr/sbin/useradd #{switches} #{user}", :via => run_method
149
+ end
150
+
151
+ # create a new group on target system
152
+ def groupadd(group, options={})
153
+ via = options.delete(:via) || run_method
154
+ invoke_command "grep '#{group}:' /etc/group || #{sudo} /usr/sbin/groupadd #{group}", :via => via
155
+ end
156
+
157
+ # add group to the list of groups this user belongs to
158
+ def add_user_to_group(user, group)
159
+ invoke_command "groups #{user} | grep ' #{group} ' || #{sudo} /usr/sbin/usermod -G #{group} -a #{user}", :via => run_method
160
+ end
161
+
162
+ # create directory if it doesn't already exist
163
+ # set permissions and ownership
164
+ # XXX move mode, path and
165
+ def mkdir(path, options={})
166
+ via = options.delete(:via) || :run
167
+ # XXX need to make sudo commands wrap the whole command (sh -c ?)
168
+ # XXX removed the extra 'sudo' from after the '||' - need something else
169
+ invoke_command "test -d #{path} || #{sudo if via == :sudo} mkdir -p #{path}"
170
+ invoke_command "chmod #{sprintf("%3o",options[:mode] || 0755)} #{path}", :via => via if options[:mode]
171
+ invoke_command "chown -R #{options[:owner]} #{path}", :via => via if options[:owner]
172
+ groupadd(options[:group], :via => via) if options[:group]
173
+ invoke_command "chgrp -R #{options[:group]} #{path}", :via => via if options[:group]
174
+ end
175
+
176
+ def install_deps(packages=[])
177
+ apt.install({:base => Array(packages)}, :stable)
178
+ end
179
+
180
+ def teardown_connections
181
+ sessions.keys.each do |server|
182
+ sessions[server].close
183
+ sessions.delete(server)
184
+ end
185
+ end
186
+
187
+ end
188
+
189
+ Capistrano.plugin :_deploify, Deploify
@@ -0,0 +1,171 @@
1
+ # Copyright 2012 by Richard Riman. All rights reserved.
2
+
3
+ require "bundler/capistrano"
4
+ require "rvm/capistrano"
5
+
6
+ Capistrano::Configuration.instance(:must_exist).load do
7
+
8
+ # Set the value if not already set
9
+ # This method is accessible to all recipe files
10
+ # Defined and used by capistrano/deploy tasks
11
+ def _cset(name, *args, &block)
12
+ unless exists?(name)
13
+ set(name, *args, &block)
14
+ end
15
+ end
16
+
17
+ alias :default :_cset
18
+
19
+ # we allways use bundler, so change rake call
20
+ _cset :rake, lambda { "#{fetch(:bundle_cmd, "bundle")} exec rake" }
21
+
22
+ default_run_options[:pty] = true
23
+
24
+ set :local_template_dir, File.join("config", "templates")
25
+
26
+ # The following two Constants contain details of the configuration
27
+ # files used by each service. They're used when generating config
28
+ # files from templates and when configs files are pushed out to servers.
29
+ #
30
+ # They are populated by the recipe file for each service
31
+ #
32
+ SYSTEM_CONFIG_FILES = {} # e.g. httpd.conf
33
+ PROJECT_CONFIG_FILES = {} # e.g. projectname-httpd-vhost.conf
34
+
35
+ # deploify defines some generic recipes for common services
36
+ # including web, app and database servers
37
+ #
38
+ # They default to my current favourites which you can override
39
+ #
40
+ # Service options
41
+ CHOICES_WEBSERVER = [:nginx]
42
+ CHOICES_APPSERVER = [:passenger, :thin] # :puma, :unicorn
43
+ CHOICES_DATABASE = [:mysql] # :mongodb
44
+ #
45
+ # Service defaults
46
+ set :web_server_type, :nginx
47
+ set :app_server_type, :passenger
48
+ set :db_server_type, :mysql
49
+
50
+ # we always use RMV, but we must set :system, because RVM default is :user
51
+ set :rvm_type, :system
52
+ set(:rvm_ruby_string) do
53
+ Capistrano::CLI.ui.choose do |menu|
54
+ menu.prompt = "Please choose RVM Ruby version for this application"
55
+ menu.choices("1.8.6", "1.8.7", "ree", "1.9.2", "1.9.3")
56
+ end
57
+ end
58
+
59
+ set :use_monit, true
60
+
61
+ # Prompt user for missing values if not supplied
62
+ set(:application) do
63
+ Capistrano::CLI.ui.ask "Enter name of project (no spaces)" do |q|
64
+ q.validate = /^[0-9a-z_]*$/
65
+ end
66
+ end
67
+
68
+ set(:domain) do
69
+ Capistrano::CLI.ui.ask "Enter domain name for project" do |q|
70
+ q.validate = /^[0-9a-z_\-\.]*$/
71
+ end
72
+ end
73
+
74
+ # some tasks run commands requiring special user privileges on remote servers
75
+ # these tasks will run the commands with:
76
+ # :invoke_command "command", :via => run_method
77
+ # override this value if sudo is not an option
78
+ # in that case, your use will need the correct privileges
79
+ set :run_method, :sudo
80
+
81
+ # deploy from TAG stuff
82
+
83
+ set :deployable_without_tag, false # only used WITHOUT multi-staging
84
+ set :stages, %w(production staging) # default stages (only used WITH multi-staging)
85
+ set :stages_deployable_without_tag, %w(staging) # only used WITH multi-staging
86
+
87
+ set(:branch) do
88
+ unless exists?(:stage)
89
+ # single stage configuration
90
+ if deployable_without_tag
91
+ tag = `git branch | grep '*' | awk '{ print $2 }'`.split[0]
92
+ else
93
+ tag = Capistrano::CLI.ui.ask("TAG to deploy (make sure to push the tag first): ")
94
+ end
95
+ else
96
+ # multi-staging configuration
97
+ if stages_deployable_without_tag.include?(fetch(:stage).to_s)
98
+ tag = `git branch | grep '*' | awk '{ print $2 }'`.split[0]
99
+ else
100
+ tag = Capistrano::CLI.ui.ask("TAG from which we deploy on stage '#{fetch(:stage)}' (make sure to push the tag first): ")
101
+ end
102
+ end
103
+ end
104
+
105
+ # rails deploy stuff
106
+ set :apps_root, "/var/www" # parent dir for apps
107
+ set(:deploy_to) { File.join(apps_root, application) } # dir for current app
108
+ set(:current_path) { File.join(deploy_to, "current") }
109
+ set(:shared_path) { File.join(deploy_to, "shared") }
110
+
111
+ # more rails deploy stuff
112
+ set :user, "deploy" # user who is deploying
113
+ set :group, "deploy" # deployment group
114
+ set(:web_server_aliases) { domain.match(/^www/) ? [] : ["www.#{domain}"] }
115
+
116
+ # rails deploy GIT stuff
117
+ set :scm, :git
118
+ set :deploy_via, :remote_cache
119
+ set :copy_exclude, ['.git', '.rvmrc']
120
+ set(:repository) do
121
+ Capistrano::CLI.ui.ask "Enter repository URL for project"
122
+ end
123
+
124
+ # webserver stuff
125
+ set :force_domain_with_www, false
126
+
127
+ on :load, "deploify:connect_canonical_tasks"
128
+
129
+ namespace :deploify do
130
+
131
+ task :connect_canonical_tasks do
132
+ # link application specific recipes into canonical task names
133
+ # e.g. deprec:web:restart => deprec:nginx:restart
134
+ namespaces_to_connect = {
135
+ :web => :web_server_type,
136
+ :app => :app_server_type,
137
+ :db => :db_server_type
138
+ }
139
+ metaclass = class << self; self; end
140
+ namespaces_to_connect.each do |server, choice|
141
+ server_type = send(choice).to_sym
142
+ if server_type != :none
143
+ metaclass.send(:define_method, server) { namespaces[server] }
144
+ namespaces[server] = deploify.send(server_type)
145
+ end
146
+ end
147
+ end
148
+
149
+ end # namespace :deploify
150
+
151
+ namespace :deploy do
152
+
153
+ task :start, :roles => :app, :except => { :no_release => true } do
154
+ run "#{sudo} service #{app_server_type}-#{application} start"
155
+ end
156
+
157
+ task :stop, :roles => :app, :except => { :no_release => true } do
158
+ run "#{sudo} service #{app_server_type}-#{application} stop"
159
+ end
160
+
161
+ task :restart, :roles => :app, :except => { :no_release => true } do
162
+ run "#{sudo} service #{app_server_type}-#{application} graceful"
163
+ end
164
+
165
+ task :force_restart, :roles => :app, :except => { :no_release => true } do
166
+ run "#{sudo} service #{app_server_type}-#{application} restart"
167
+ end
168
+
169
+ end # namespace :deploy
170
+
171
+ end
@@ -0,0 +1,15 @@
1
+ # Copyright 2012 by Richard Riman. All rights reserved.
2
+
3
+ Capistrano::Configuration.instance(:must_exist).load do
4
+
5
+ namespace :deploify do
6
+
7
+ namespace :mongodb do
8
+
9
+
10
+
11
+ end # namespace :mongodb
12
+
13
+ end # namespace :deploify
14
+
15
+ end
@@ -0,0 +1,84 @@
1
+ # Copyright 2012 by Richard Riman. All rights reserved.
2
+
3
+ Capistrano::Configuration.instance(:must_exist).load do
4
+
5
+ # we use monit primary to control passenger processes so the tasks
6
+ # are restricted to :app. You may use it for other processes.
7
+ # In this case, specify HOSTS=hostname on the command line or use:
8
+ # for_roles(:role_name) { top.deploify.monit.task_name }
9
+ # in your recipes.
10
+
11
+ set :monit_timeout_interval, 120
12
+ set :monit_conf_dir, "/etc/monit/conf.d"
13
+ # TODO
14
+ # set :monit_alert_recipients, %w(monitoring@example.com)
15
+ # set :monit_timeout_recipients, %w(monitoring@example.com)
16
+
17
+ namespace :deploify do
18
+
19
+ namespace :monit do
20
+
21
+ PROJECT_CONFIG_FILES[:monit] = [
22
+ { :template => "monit.conf.erb",
23
+ :path => "monit.conf",
24
+ :mode => 0644,
25
+ :owner => "root:root" }
26
+ ]
27
+
28
+ desc <<-DESC
29
+ Generate monit application config from template. Note that this does not
30
+ push the config to the server, it merely generates required
31
+ configuration files. These should be kept under source control.
32
+ DESC
33
+ task :config_gen_project do
34
+ PROJECT_CONFIG_FILES[:monit].each do |file|
35
+ _deploify.render_template(:monit, file)
36
+ end
37
+ end
38
+
39
+ desc "Push application monit config files to server"
40
+ task :config_project, :roles => :app do
41
+ _deploify.push_configs(:monit, PROJECT_CONFIG_FILES[:monit])
42
+ end
43
+
44
+ desc "Start Monit"
45
+ task :start, :roles => :app do
46
+ send(run_method, "service monit start")
47
+ end
48
+
49
+ task :activate do
50
+ top.deploify.monit.activate_project
51
+ end
52
+
53
+ desc "Activate application monit config and reload monit"
54
+ task :activate_project, :roles => :app do
55
+ run "#{sudo} ln -sf #{deploy_to}/monit/monit.conf #{monit_conf_dir}/#{application}"
56
+ top.deploify.monit.reload
57
+ end
58
+
59
+ desc "Dectivate application monit config and reload monit"
60
+ task :deactivate_project, :roles => :app do
61
+ run "#{sudo} rm -f #{monit_conf_dir}/#{application}; exit 0"
62
+ top.deploify.monit.reload
63
+ end
64
+
65
+ desc "Stop Monit"
66
+ task :stop, :roles => :app do
67
+ send(run_method, "service monit stop")
68
+ end
69
+
70
+ desc "Restart Monit"
71
+ task :restart, :roles => :app do
72
+ send(run_method, "service monit restart")
73
+ end
74
+
75
+ desc "Reload Monit"
76
+ task :reload, :roles => :app do
77
+ send(run_method, "service monit restart")
78
+ end
79
+
80
+ end # namespace :monit
81
+
82
+ end # namespace :deploify
83
+
84
+ end
@@ -0,0 +1,85 @@
1
+ # Copyright 2006-2008 by Mike Bailey. All rights reserved.
2
+ # Copyright 2012 by Richard Riman. All rights reserved.
3
+
4
+ Capistrano::Configuration.instance(:must_exist).load do
5
+
6
+ set :mysql_admin_user, "deploy"
7
+ set(:mysql_admin_pass) { Capistrano::CLI.password_prompt "Enter database password for '#{mysql_admin_user}':" }
8
+
9
+ namespace :deploify do
10
+
11
+ namespace :mysql do
12
+
13
+ desc "Start Mysql"
14
+ task :start, :roles => :db do
15
+ send(run_method, "service mysql start")
16
+ end
17
+
18
+ desc "Stop Mysql"
19
+ task :stop, :roles => :db do
20
+ send(run_method, "service mysql stop")
21
+ end
22
+
23
+ desc "Restart Mysql"
24
+ task :restart, :roles => :db do
25
+ send(run_method, "service mysql restart")
26
+ end
27
+
28
+ desc "Reload Mysql"
29
+ task :reload, :roles => :db do
30
+ send(run_method, "service mysql reload")
31
+ end
32
+
33
+ desc "Create a database"
34
+ task :create_database, :roles => :db do
35
+ cmd = "CREATE DATABASE IF NOT EXISTS #{db_name}"
36
+ run "mysql -u #{mysql_admin_user} -p -e '#{cmd}'" do |channel, stream, data|
37
+ if data =~ /^Enter password:/
38
+ channel.send_data "#{mysql_admin_pass}\n"
39
+ end
40
+ end
41
+ end
42
+
43
+ desc "Grant user access to database"
44
+ task :grant_user_access_to_database, :roles => :db do
45
+ cmd = "GRANT ALL PRIVILEGES ON #{db_name}.* TO '#{db_user}'@localhost IDENTIFIED BY '#{db_password}';"
46
+ run "mysql -u #{mysql_admin_user} -p #{db_name} -e \"#{cmd}\"" do |channel, stream, data|
47
+ if data =~ /^Enter password:/
48
+ channel.send_data "#{mysql_admin_pass}\n"
49
+ end
50
+ end
51
+ end
52
+
53
+ end # namespace :mysql
54
+
55
+ end # namespace :deploify
56
+
57
+ end
58
+
59
+ #
60
+ # Setup replication
61
+ #
62
+
63
+ # setup user for repl
64
+ # GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.yourdomain.com' IDENTIFIED BY 'slavepass';
65
+
66
+ # get current position of binlog
67
+ # mysql> FLUSH TABLES WITH READ LOCK;
68
+ # Query OK, 0 rows affected (0.00 sec)
69
+ #
70
+ # mysql> SHOW MASTER STATUS;
71
+ # +------------------+----------+--------------+------------------+
72
+ # | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
73
+ # +------------------+----------+--------------+------------------+
74
+ # | mysql-bin.000012 | 296 | | |
75
+ # +------------------+----------+--------------+------------------+
76
+ # 1 row in set (0.00 sec)
77
+ #
78
+ # # get current data
79
+ # mysqldump --all-databases --master-data >dbdump.db
80
+ #
81
+ # UNLOCK TABLES;
82
+
83
+
84
+ # Replication Features and Issues
85
+ # http://dev.mysql.com/doc/refman/5.0/en/replication-features.html