-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathpostgresql.rake
More file actions
199 lines (184 loc) · 8.37 KB
/
Copy pathpostgresql.rake
File metadata and controls
199 lines (184 loc) · 8.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
require 'capistrano/postgresql/helper_methods'
require 'capistrano/postgresql/password_helpers'
require 'capistrano/postgresql/psql_helpers'
include Capistrano::Postgresql::HelperMethods
include Capistrano::Postgresql::PasswordHelpers
include Capistrano::Postgresql::PsqlHelpers
namespace :load do
task :defaults do
# Options necessary for database.yml creation (pg_template|helper_methods.rb)
set :pg_env, -> { fetch(:rails_env) || fetch(:stage) }
set :pg_encoding, 'unicode'
set :pg_database, -> { "#{fetch(:application)}_#{fetch(:stage)}" }
set :pg_pool, 5
set :pg_username, -> { fetch(:pg_database) }
set :pg_generate_random_password, nil
set :pg_ask_for_password, nil
set :pg_password, -> { pg_password_generate }
set :pg_socket, ''
set :pg_host, -> do # for multiple release nodes automatically use server hostname (IP?) in the database.yml
release_roles(:all).count == 1 && release_roles(:all).first == primary(:db) ? 'localhost' : primary(:db).hostname
end
set :pg_port, 5432
set :pg_timeout, 5000 # 5 seconds (rails default)
# General settings
set :pg_without_sudo, false # issues/22 | Contributed by snake66
set :pg_system_user, 'postgres'
set :pg_system_db, 'postgres'
set :pg_use_hstore, false
set :pg_extensions, []
set :pg_templates_path, 'config/deploy/templates'
end
end
namespace :postgresql do
desc 'Steps to upgrade the gem to version 4.0'
task :upgrade4 do
on roles :db do
execute :mkdir, '-pv', File.dirname(archetype_database_yml_file)
execute :cp, database_yml_file, archetype_database_yml_file
end
end
# undocumented, for a reason: drops database. Use with care!
task :remove_all do
on release_roles :all do
execute :rm, database_yml_file if test "[ -e #{database_yml_file} ]"
end
on primary :db do
execute :rm, archetype_database_yml_file if test "[ -e #{archetype_database_yml_file} ]"
end
on roles :db do
psql'execute', fetch(:pg_system_db), "-p #{fetch(:pg_port)} -c", %Q{"DROP database \\"#{fetch(:pg_database)}\\";"} if database_exists?
psql 'execute', fetch(:pg_system_db),"-p #{fetch(:pg_port)} -c", %Q{"DROP user \\"#{fetch(:pg_username)}\\";"}if database_user_exists?
remove_extensions
end
puts 'Removed database.yml from all hosts, Database, Database User, and Removed Extensions'
end
task :remove_app_database_yml_files do
# We should never delete archetype files. The generate_database_yml_archetype task will handle updates
on release_roles :app do
execute :rm, database_yml_file if test "[ -e #{database_yml_file} ]"
end
end
desc 'Remove pg_extension from postgresql db'
task :remove_extensions do
remove_extensions
end
desc 'Add pg_extension to postgresql db'
task :add_extensions do
on roles :db do
if Array( fetch(:pg_extensions) ).any?
Array( fetch(:pg_extensions) ).each do |ext|
next if [nil, false, ''].include?(ext)
psql 'execute', fetch(:pg_database), "-p #{fetch(:pg_port)} -c", %Q{"CREATE EXTENSION IF NOT EXISTS #{ext};"}unless extension_exists?(ext)
end
end
end
end
desc 'Create or update pg_username in database'
task :create_database_user do
on roles :db do
unless database_user_exists?
# If you use CREATE USER instead of CREATE ROLE the LOGIN right is granted automatically; otherwise you must specify it in the WITH clause of the CREATE statement.
psql 'execute', fetch(:pg_system_db), "-p #{fetch(:pg_port)} -c", %Q{"CREATE USER \\"#{fetch(:pg_username)}\\" PASSWORD}, redact("'#{fetch(:pg_password)}'"), %Q{;"}
end
if database_user_password_different?
# Ensure updating the password in your deploy/ENV.rb files updates the user, server side
psql 'execute', fetch(:pg_system_db), "-p #{fetch(:pg_port)} -c", %Q{"ALTER USER \\"#{fetch(:pg_username)}\\" WITH PASSWORD}, redact("'#{fetch(:pg_password)}'"), %Q{;"}
end
end
end
desc 'Create database'
task :create_database do
on roles :db do
unless database_exists?
psql 'execute', fetch(:pg_system_db), "-p #{fetch(:pg_port)} -c", %Q{"CREATE DATABASE \\"#{fetch(:pg_database)}\\" OWNER \\"#{fetch(:pg_username)}\\";"}
end
end
end
# This task creates the archetype database.yml file on the primary db server. This is done once when a new DB user is created.
desc 'Generate database.yml archetype'
task :generate_database_yml_archetype do
on primary :db do
if test "[ -e #{archetype_database_yml_file} ]" # Archetype already exists. Just update values that changed. Make sure we don't overwrite it to protect generated passwords.
upload!(
StringIO.new(pg_template(true, download!(archetype_database_yml_file))),
archetype_database_yml_file
)
# Net::SCP.upload!(
# self.host.hostname,
# self.host.user,
# StringIO.new(pg_template(true, download!(archetype_database_yml_file))),
# archetype_database_yml_file,
# ssh: { port: self.host.port }
# )
else
execute :mkdir, '-pv', File.dirname(archetype_database_yml_file)
upload!(
StringIO.new(pg_template),
archetype_database_yml_file
)
# Net::SCP.upload!(
# self.host.hostname,
# self.host.user,
# StringIO.new(pg_template),
# archetype_database_yml_file,
# ssh: { port: self.host.port }
# )
end
end
end
# This task copies the archetype database file on the primary db server to all clients. This is done on every setup, to ensure new servers get a copy as well.
desc 'Copy archetype database.yml from primary db server to clients'
task :generate_database_yml do
database_yml_contents = nil
on primary :db do
database_yml_contents = download! archetype_database_yml_file
end
on release_roles :all do
execute :mkdir, '-pv', File.dirname(database_yml_file)
upload!(
StringIO.new(database_yml_contents),
database_yml_file
)
# Net::SCP.upload!(
# self.host.hostname,
# self.host.user,
# StringIO.new(database_yml_contents),
# database_yml_file,
# ssh: { port: self.host.port }
# )
end
end
task :database_yml_symlink do
set :linked_files, fetch(:linked_files, []).push('config/database.yml')
end
after 'deploy:started', 'postgresql:database_yml_symlink'
desc 'Postgresql setup tasks'
task :setup do
puts "* ===== Postgresql Setup ===== *\n"
puts " All psql commands will be run #{fetch(:pg_without_sudo) ? 'without sudo' : 'with sudo'}\n You can modify this in your app/config/deploy/#{fetch(:rails_env)}.rb by setting the pg_without_sudo boolean.\n"
if release_roles(:app).empty?
warn " WARNING: There are no servers in your app/config/deploy/#{fetch(:rails_env)}.rb with a :app role... Skipping Postgresql setup."
else
if release_roles(:db).empty? # Test to be sure we have a :db role host
warn " WARNING: There is no server in your app/config/deploy/#{fetch(:rails_env)}.rb with a :db role... Skipping Postgresql setup."
elsif !fetch(:pg_password) && !fetch(:pg_generate_random_password) && !fetch(:pg_ask_for_password)
warn " WARNING: There is no :pg_password set in your app/config/deploy/#{fetch(:rails_env)}.rb.\n If you don't wish to set it, 'set :pg_generate_random_password, true' or 'set :pg_ask_for_password, true' are available!"
elsif fetch(:pg_generate_random_password) && fetch(:pg_ask_for_password)
warn " WARNING: You cannot have both :pg_generate_random_password and :pg_ask_for_password enabled in app/config/deploy/#{fetch(:rails_env)}.rb."
else
invoke 'postgresql:remove_app_database_yml_files' # Deletes old yml files from all servers. Allows you to avoid having to manually delete the files on your app servers to get a new pool size for example. Don't touch the archetype file to avoid deleting generated passwords.
invoke 'postgresql:create_database_user'
invoke 'postgresql:create_database'
invoke 'postgresql:add_extensions'
invoke 'postgresql:generate_database_yml_archetype'
invoke 'postgresql:generate_database_yml'
end
end
puts "* ============================= *"
end
end
desc 'Server setup tasks'
task :setup do
invoke 'postgresql:setup'
end