capistrano-postgresql 4.9.2 → 5.0.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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +41 -20
- data/lib/capistrano/postgresql/helper_methods.rb +18 -2
- data/lib/capistrano/postgresql/password_helpers.rb +4 -4
- data/lib/capistrano/postgresql/psql_helpers.rb +15 -26
- data/lib/capistrano/postgresql/version.rb +1 -1
- data/lib/capistrano/tasks/postgresql.rake +35 -58
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62d90db3919f2557e6a3934726d251dac71b5abf48a2c7b1984dd32b3ee96852
|
4
|
+
data.tar.gz: 44cb5c724e536949afe34291907838a747fd8342e7c84bbbfad2cb61a2746a53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afd78f06f37d41d32da87073c979ede236aadcf9409ce7b4086ce5ecb232447efb0071007401cce4d556e6468e7af7743b4d4adaadf9f408e1882ce5767a8400
|
7
|
+
data.tar.gz: 41c442f96c4fb72594f9595d649a184e0447b1c168e114ea663d44cdc68d82e8393fd7c84f7ed5ae71d0816966fa7fb83b094b826cf8d16d5b5163e947e4ce6b
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
### master
|
4
4
|
|
5
|
+
## v5.0.0, 2018-06-05
|
6
|
+
- Code cleanup
|
7
|
+
- Removal of legacy add hstore method
|
8
|
+
- Using execute and test properly so we can see what the gem is doing in the STDOUT
|
9
|
+
- Expanded remove_all task to actually cover everything
|
10
|
+
- Added deploy config option pg_generate_random_password, instead of using it by default when pg_password is excluded
|
11
|
+
- issues/53: Bug fixed for updates to the archetype when using random password
|
12
|
+
- projects/1: Prep for RSPEC testing project
|
13
|
+
|
5
14
|
## v4.9.1, 2018-06-04
|
6
15
|
- Added back set :pg_ask_for_password, false and ask_for_or_generate_password
|
7
16
|
|
data/README.md
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
# Capistrano::PostgreSQL
|
2
2
|
|
3
|
-
**Note: this plugin works only with Capistrano 3.**
|
3
|
+
**Note: this plugin works only with Capistrano 3.** Please check the capistrano
|
4
4
|
gem version you're using before installing this gem:
|
5
5
|
`$ bundle show | grep capistrano`
|
6
|
-
|
7
|
-
Plugin for Capistrano 2 [is here](https://github.com/bruno-/capistrano2-postgresql).
|
6
|
+
The plugin for Capistrano 2 [is here](https://github.com/bruno-/capistrano2-postgresql).
|
8
7
|
|
9
8
|
### About
|
10
9
|
|
@@ -14,11 +13,9 @@ tasks for PostgreSQL when deploying rails apps.
|
|
14
13
|
Here are the specific things this plugin does for your capistrano deployment
|
15
14
|
process:
|
16
15
|
|
17
|
-
*
|
18
|
-
*
|
19
|
-
|
20
|
-
* zero-config
|
21
|
-
* support for multi-server setup: separate `db` and `app` nodes (from version 4.0)
|
16
|
+
* Creates a new PostgreSQL database and database user on the server
|
17
|
+
* Generates and populates `database.yml` file on all release nodes (using ssh)
|
18
|
+
* Support for multi-server setup: separate `db` and `app` nodes ( versions > 4.0 )
|
22
19
|
|
23
20
|
**Note**: gem version 4 introduces some breaking changes. If you installed gem
|
24
21
|
version 3 or below you might want to follow the
|
@@ -30,7 +27,7 @@ Put the following in your application's `Gemfile`:
|
|
30
27
|
|
31
28
|
group :development do
|
32
29
|
gem 'capistrano', '~> 3.2.0'
|
33
|
-
gem 'capistrano-postgresql', '~>
|
30
|
+
gem 'capistrano-postgresql', '~> 5.0.0'
|
34
31
|
end
|
35
32
|
|
36
33
|
Then:
|
@@ -39,31 +36,55 @@ Then:
|
|
39
36
|
|
40
37
|
### Usage
|
41
38
|
|
42
|
-
|
43
|
-
the following in `Capfile` file:
|
39
|
+
In a standard RAILS app, you need to do is put the following in `Capfile` file:
|
44
40
|
|
45
41
|
```
|
46
42
|
require 'capistrano/postgresql'
|
47
43
|
```
|
48
44
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
45
|
+
You need to include ONLY ONE of the following in your config/deploy/*.rb files:
|
46
|
+
|
47
|
+
```
|
48
|
+
set :pg_password, ENV['DATABASE_USER_PASSWORD']
|
49
|
+
set :pg_ask_for_password, true
|
50
|
+
set :pg_generate_random_password, true
|
51
|
+
```
|
52
|
+
|
53
|
+
Example config:
|
54
|
+
|
55
|
+
```
|
56
|
+
server 'growtrader.dev', user: 'growtrader', roles: %w{app db}
|
57
|
+
set :stage, :development
|
58
|
+
set :branch, 'development'
|
59
|
+
# ==================
|
60
|
+
# Postgresql setup
|
61
|
+
set :pg_without_sudo, false
|
62
|
+
set :pg_host, 'growtrader.dev'
|
63
|
+
set :pg_database, 'growtrader'
|
64
|
+
set :pg_username, 'growtrader'
|
65
|
+
#set :pg_generate_random_password, true
|
66
|
+
#set :pg_ask_for_password, true
|
67
|
+
set :pg_password, ENV['GROWTRADER_PGPASS']
|
68
|
+
set :pg_extensions, ['citext','hstore']
|
69
|
+
set :pg_encoding, 'UTF-8'
|
70
|
+
set :pg_pool, '100'
|
71
|
+
```
|
54
72
|
|
55
73
|
Finally, to setup the server(s), run:
|
56
74
|
|
57
75
|
$ bundle exec cap production setup
|
58
76
|
|
59
|
-
###
|
77
|
+
### Requirements
|
60
78
|
|
61
|
-
Be sure to remove `config/database.yml` from your application's version control.
|
79
|
+
* Be sure to remove `config/database.yml` from your application's version control.
|
80
|
+
* Your pg_hba.conf must include `local all all trust`
|
81
|
+
* Make sure the `deploy_to` path exists and has the right privileges on your servers. The ~ symbol (i.e. `~/myapp`) is not supported.
|
82
|
+
* Within your app/config/deploy/{env}.rb files, you need to specify at least one :app and one :db server.
|
83
|
+
* If you have multiple :db role hosts, it's necessary to specify `:primary => true` on the end of your primary :db server.
|
62
84
|
|
63
85
|
### How it works
|
64
86
|
|
65
87
|
[How the plugin works](https://github.com/capistrano-plugins/capistrano-postgresql/wiki/How-it-works)
|
66
|
-
wiki page contains a list of actions the plugin executes.
|
67
88
|
|
68
89
|
Read it only if you want to learn more about the plugin internals.
|
69
90
|
|
@@ -87,7 +108,7 @@ Check out [capistrano-plugins](https://github.com/capistrano-plugins) github org
|
|
87
108
|
|
88
109
|
Contributions and improvements are very welcome.
|
89
110
|
|
90
|
-
If something is not working for you, or you find a bug please report it.
|
111
|
+
If something is not working for you, or you find a bug, please report it.
|
91
112
|
|
92
113
|
### Thanks
|
93
114
|
|
@@ -4,6 +4,22 @@ module Capistrano
|
|
4
4
|
module Postgresql
|
5
5
|
module HelperMethods
|
6
6
|
|
7
|
+
def extension_exists?(extension)
|
8
|
+
psql 'test', fetch(:pg_system_db), '-tAc', %Q{"SELECT 1 FROM pg_extension WHERE extname='#{extension}';" | grep -q 1}
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove_extensions
|
12
|
+
if Array( fetch(:pg_extensions) ).any?
|
13
|
+
on roles :db do
|
14
|
+
# remove in reverse order if extension is present
|
15
|
+
Array( fetch(:pg_extensions) ).reverse.each do |ext|
|
16
|
+
next if [nil, false, ""].include?(ext)
|
17
|
+
psql 'execute', fetch(:pg_system_db), '-c', %Q{"DROP EXTENSION IF EXISTS #{ext};"} if extension_exists?(ext)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
7
23
|
def generate_database_yml_io(password=fetch(:pg_password))
|
8
24
|
StringIO.open do |s|
|
9
25
|
s.puts "#{fetch(:pg_env)}:"
|
@@ -26,10 +42,10 @@ module Capistrano
|
|
26
42
|
def pg_template(update=false,archetype_file=nil)
|
27
43
|
config_file = "#{fetch(:pg_templates_path)}/postgresql.yml.erb"
|
28
44
|
if update
|
29
|
-
raise('
|
45
|
+
raise('Regeneration of archetype database.yml need the original file to update from.') if archetype_file.nil?
|
30
46
|
raise('Cannot update a custom postgresql.yml.erb file.') if File.exists?(config_file) # Skip custom postgresql.yml.erb if we're updating. It's not supported
|
31
47
|
# Update yml file from settings
|
32
|
-
if fetch(:
|
48
|
+
if fetch(:pg_generate_random_password) || !fetch(:pg_password) # We need to prevent updating the archetype file if we've done a random or "ask"ed password
|
33
49
|
current_password = archetype_file.split("\n").grep(/password/)[0].split('password:')[1].strip
|
34
50
|
generate_database_yml_io(current_password)
|
35
51
|
else
|
@@ -8,15 +8,15 @@ module Capistrano
|
|
8
8
|
SecureRandom.hex(10)
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
def ask_for_or_generate_password
|
11
|
+
def pg_password_generate
|
13
12
|
if fetch(:pg_ask_for_password)
|
14
13
|
ask :pg_password, "Postgresql database password for the app: "
|
15
|
-
|
14
|
+
elsif fetch(:pg_generate_random_password)
|
16
15
|
set :pg_password, generate_random_password
|
16
|
+
else
|
17
|
+
set :pg_password, nil # Necessary for pg_template
|
17
18
|
end
|
18
19
|
end
|
19
|
-
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -2,39 +2,28 @@ module Capistrano
|
|
2
2
|
module Postgresql
|
3
3
|
module PsqlHelpers
|
4
4
|
|
5
|
-
def psql(*args)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
5
|
+
def psql(type, database, *args)
|
6
|
+
cmd = [ :psql, "-d #{database}", *args ]
|
7
|
+
if fetch(:pg_without_sudo)
|
8
|
+
args.unshift("-U #{fetch(:pg_system_user)}") # Add the :pg_system_user to psql command since we aren't using sudo anymore
|
9
|
+
else
|
10
|
+
cmd = [:sudo, "-i -u #{fetch(:pg_system_user)}", *cmd]
|
11
|
+
end
|
12
|
+
if type == 'test'
|
13
|
+
test *cmd.flatten
|
14
|
+
else
|
15
|
+
execute *cmd.flatten
|
16
|
+
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
19
|
+
def database_user_exists?
|
20
|
+
psql 'test', fetch(:pg_system_db),'-tAc', %Q{"SELECT 1 FROM pg_roles WHERE rolname='#{fetch(:pg_username)}';" | grep -q 1}
|
21
21
|
end
|
22
22
|
|
23
23
|
def database_exists?
|
24
|
-
|
24
|
+
psql 'test', fetch(:pg_system_db), '-tAc', %Q{"SELECT 1 FROM pg_database WHERE datname='#{fetch(:pg_database)}';" | grep -q 1}
|
25
25
|
end
|
26
26
|
|
27
|
-
private
|
28
|
-
|
29
|
-
def psql_on_db(db_name, *args)
|
30
|
-
args.unshift("-U #{fetch(:pg_system_user)}") if fetch(:pg_without_sudo) # Add the :pg_system_user to psql command since we aren't using sudo anymore
|
31
|
-
cmd = [ :psql, "-d #{db_name}", *args ]
|
32
|
-
cmd = [ :sudo, "-u #{fetch(:pg_system_user)}", *cmd ] unless fetch(:pg_without_sudo)
|
33
|
-
puts "Executing #{cmd.flatten}"
|
34
|
-
test *cmd.flatten
|
35
|
-
#test :sudo, "-u #{fetch(:pg_system_user)} psql -d #{db_name}", *args
|
36
|
-
end
|
37
|
-
|
38
27
|
end
|
39
28
|
end
|
40
29
|
end
|
@@ -13,8 +13,9 @@ namespace :load do
|
|
13
13
|
set :pg_database, -> { "#{fetch(:application)}_#{fetch(:stage)}" }
|
14
14
|
set :pg_pool, 5
|
15
15
|
set :pg_username, -> { fetch(:pg_database) }
|
16
|
-
set :
|
17
|
-
set :
|
16
|
+
set :pg_generate_random_password, nil
|
17
|
+
set :pg_ask_for_password, nil
|
18
|
+
set :pg_password, -> { pg_password_generate }
|
18
19
|
set :pg_socket, ''
|
19
20
|
set :pg_host, -> do # for multiple release nodes automatically use server hostname (IP?) in the database.yml
|
20
21
|
release_roles(:all).count == 1 && release_roles(:all).first == primary(:db) ? 'localhost' : primary(:db).hostname
|
@@ -44,86 +45,58 @@ namespace :postgresql do
|
|
44
45
|
# undocumented, for a reason: drops database. Use with care!
|
45
46
|
task :remove_all do
|
46
47
|
on release_roles :all do
|
47
|
-
if test "[ -e #{database_yml_file} ]"
|
48
|
-
execute :rm, database_yml_file
|
49
|
-
end
|
48
|
+
execute :rm, database_yml_file if test "[ -e #{database_yml_file} ]"
|
50
49
|
end
|
51
|
-
|
52
50
|
on primary :db do
|
53
|
-
if test "[ -e #{archetype_database_yml_file} ]"
|
54
|
-
execute :rm, archetype_database_yml_file
|
55
|
-
end
|
51
|
+
execute :rm, archetype_database_yml_file if test "[ -e #{archetype_database_yml_file} ]"
|
56
52
|
end
|
57
|
-
|
58
53
|
on roles :db do
|
59
|
-
psql '-c', %Q{"DROP database \\"#{fetch(:pg_database)}\\";"}
|
60
|
-
psql '-c', %Q{"DROP user \\"#{fetch(:pg_username)}\\";"}
|
54
|
+
psql'execute', fetch(:pg_system_db), '-c', %Q{"DROP database \\"#{fetch(:pg_database)}\\";"} if database_exists?
|
55
|
+
psql 'execute', fetch(:pg_system_db),'-c', %Q{"DROP user \\"#{fetch(:pg_username)}\\";"}if database_user_exists?
|
56
|
+
remove_extensions
|
61
57
|
end
|
58
|
+
puts 'Removed database.yml from all hosts, Database, Database User, and Removed Extensions'
|
62
59
|
end
|
63
60
|
|
64
61
|
task :remove_app_database_yml_files do
|
65
62
|
# We should never delete archetype files. The generate_database_yml_archetype task will handle updates
|
66
63
|
on release_roles :app do
|
67
|
-
|
68
|
-
execute :rm, database_yml_file
|
69
|
-
end
|
64
|
+
execute :rm, database_yml_file if test "[ -e #{database_yml_file} ]"
|
70
65
|
end
|
71
66
|
end
|
72
67
|
|
73
68
|
desc 'Remove pg_extension from postgresql db'
|
74
69
|
task :remove_extensions do
|
75
|
-
|
76
|
-
on roles :db do
|
77
|
-
# remove in reverse order if extension is present
|
78
|
-
Array( fetch(:pg_extensions) ).reverse.each do |ext|
|
79
|
-
psql_on_app_db '-c', %Q{"DROP EXTENSION IF EXISTS #{ext};"} unless [nil, false, ""].include?(ext)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
desc 'Add the hstore extension to postgresql'
|
85
|
-
task :add_hstore do
|
86
|
-
next unless fetch(:pg_use_hstore)
|
87
|
-
on roles :db do
|
88
|
-
psql_on_app_db '-c', %Q{"CREATE EXTENSION IF NOT EXISTS hstore;"}
|
89
|
-
end
|
70
|
+
remove_extensions
|
90
71
|
end
|
91
72
|
|
92
73
|
desc 'Add pg_extension to postgresql db'
|
93
74
|
task :add_extensions do
|
94
|
-
next unless Array( fetch(:pg_extensions) ).any?
|
95
75
|
on roles :db do
|
96
|
-
Array( fetch(:pg_extensions) ).
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
else
|
101
|
-
error "postgresql: adding extension #{ext} failed!"
|
102
|
-
exit 1
|
76
|
+
if Array( fetch(:pg_extensions) ).any?
|
77
|
+
Array( fetch(:pg_extensions) ).each do |ext|
|
78
|
+
next if [nil, false, ''].include?(ext)
|
79
|
+
psql 'execute', fetch(:pg_system_db), '-c', %Q{"CREATE EXTENSION IF NOT EXISTS #{ext};"}unless extension_exists?(ext)
|
103
80
|
end
|
104
81
|
end
|
105
82
|
end
|
106
83
|
end
|
107
84
|
|
108
|
-
desc 'Create database'
|
109
|
-
task :
|
85
|
+
desc 'Create pg_username in database'
|
86
|
+
task :create_database_user do
|
110
87
|
on roles :db do
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
exit 1
|
88
|
+
unless database_user_exists?
|
89
|
+
# 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.
|
90
|
+
psql 'execute', fetch(:pg_system_db), '-c', %Q{"CREATE USER \\"#{fetch(:pg_username)}\\" PASSWORD '#{fetch(:pg_password)}';"}
|
115
91
|
end
|
116
92
|
end
|
117
93
|
end
|
118
94
|
|
119
|
-
desc 'Create
|
120
|
-
task :
|
95
|
+
desc 'Create database'
|
96
|
+
task :create_database do
|
121
97
|
on roles :db do
|
122
|
-
|
123
|
-
|
124
|
-
unless psql_on_db fetch(:pg_system_db), '-c', %Q{"CREATE USER \\"#{fetch(:pg_username)}\\" PASSWORD '#{fetch(:pg_password)}';"}
|
125
|
-
error "postgresql: creating database user \"#{fetch(:pg_username)}\" failed!"
|
126
|
-
exit 1
|
98
|
+
unless database_exists?
|
99
|
+
psql 'execute', fetch(:pg_system_db), '-c', %Q{"CREATE DATABASE \\"#{fetch(:pg_database)}\\" OWNER \\"#{fetch(:pg_username)}\\";"}
|
127
100
|
end
|
128
101
|
end
|
129
102
|
end
|
@@ -148,7 +121,6 @@ namespace :postgresql do
|
|
148
121
|
on primary :db do
|
149
122
|
database_yml_contents = download! archetype_database_yml_file
|
150
123
|
end
|
151
|
-
|
152
124
|
on release_roles :all do
|
153
125
|
execute :mkdir, '-pv', File.dirname(database_yml_file)
|
154
126
|
Net::SCP.upload!(self.host.hostname, self.host.user, StringIO.new(database_yml_contents), database_yml_file)
|
@@ -163,26 +135,31 @@ namespace :postgresql do
|
|
163
135
|
|
164
136
|
desc 'Postgresql setup tasks'
|
165
137
|
task :setup do
|
166
|
-
puts "*
|
138
|
+
puts "* ===== Postgresql Setup ===== *\n"
|
139
|
+
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"
|
167
140
|
if release_roles(:app).empty?
|
168
|
-
|
141
|
+
warn " WARNING: There are no servers in your app/config/deploy/#{fetch(:rails_env)}.rb with a :app role... Skipping Postgresql setup."
|
169
142
|
else
|
170
143
|
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.
|
171
144
|
if release_roles(:db).empty? # Test to be sure we have a :db role host
|
172
|
-
|
145
|
+
warn " WARNING: There is no server in your app/config/deploy/#{fetch(:rails_env)}.rb with a :db role... Skipping Postgresql setup."
|
146
|
+
elsif !fetch(:pg_password) && !fetch(:pg_generate_random_password) && !fetch(:pg_ask_for_password)
|
147
|
+
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!"
|
148
|
+
elsif fetch(:pg_generate_random_password) && fetch(:pg_ask_for_password)
|
149
|
+
warn " WARNING: You cannot have both :pg_generate_random_password and :pg_ask_for_password enabled in app/config/deploy/#{fetch(:rails_env)}.rb."
|
173
150
|
else
|
174
|
-
invoke 'postgresql:
|
151
|
+
invoke 'postgresql:create_database_user'
|
175
152
|
invoke 'postgresql:create_database'
|
176
|
-
invoke 'postgresql:add_hstore'
|
177
153
|
invoke 'postgresql:add_extensions'
|
178
154
|
invoke 'postgresql:generate_database_yml_archetype'
|
179
155
|
invoke 'postgresql:generate_database_yml'
|
180
156
|
end
|
181
157
|
end
|
158
|
+
puts "* ============================= *"
|
182
159
|
end
|
183
160
|
end
|
184
161
|
|
185
162
|
desc 'Server setup tasks'
|
186
163
|
task :setup do
|
187
|
-
invoke
|
164
|
+
invoke 'postgresql:setup'
|
188
165
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano-postgresql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bruno Sutic
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-06-
|
12
|
+
date: 2018-06-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: capistrano
|