capistrano-postgresql 4.9.2 → 5.0.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
  SHA256:
3
- metadata.gz: 80305e773c32e2e4eeaa17fc94f06554747d9e8b4e1d62475098873ee32888d6
4
- data.tar.gz: 59444fe5adfceb315f3752aa5051f414c91f73372029e5af637453b4bdef7b54
3
+ metadata.gz: 62d90db3919f2557e6a3934726d251dac71b5abf48a2c7b1984dd32b3ee96852
4
+ data.tar.gz: 44cb5c724e536949afe34291907838a747fd8342e7c84bbbfad2cb61a2746a53
5
5
  SHA512:
6
- metadata.gz: abca2321498fde096259461b5573b483d3b046ac9c7cb2d297f23256b816e1daf78df99f1fb51bf680547294d4eb6a9d4c3f50d0a7d09f2be46ec00fa941c5e7
7
- data.tar.gz: 99860d8f90dda9c524c8996601bfb7cfecf49b6dc63951bcb28b1313e8bfe937bfd595bd7f82657686e23d92d940379c959bb056dcc4af144034f0e73f044ce7
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.** Plase check the capistrano
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
- * creates a new PostgreSQL database and database user on the server
18
- * generates and populates `database.yml` file on all release nodes
19
- (no need to ssh to the server and do this manually!)
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', '~> 4.8.0'
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
- If you're deploying a standard rails app, all you need to do is put
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
- * Make sure the `deploy_to` path exists and has the right privileges on the
50
- server (i.e. `/var/www/myapp`). Warning: The ~ symbol (i.e. `~/myapp`) is not supported.
51
- * Within your app/config/deploy/{env}.rb files, you need to specify at least one :app and one :db server.
52
- * It's also suggested to specify `:primary => true` on the end of your primary :db server line.
53
- * Optionally, you can run psql commands WITHOUT sudo if needed. Set the following (which defaults to false): `set :pg_without_sudo, true`
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
- ### Gotchas
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('Updates need the original file to update from.') if archetype_file.nil?
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(:pg_password).nil? && fetch(:pg_ask_for_password) == false # User isn't generating a random password or wanting to set it manually from prompt
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
- # This method is invoked only if :pg_password is not already set in config/#{:stage}/deploy.rb. Directly setting :pg_password has precedence.
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
- else
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
- # Reminder: -u #{fetch(:pg_system_user)} seen below differs slightly from -U, an option on the psql command: https://www.postgresql.org/docs/9.6/static/app-psql.html
7
- 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
8
- # test :sudo, "-u #{fetch(:pg_system_user)} psql", *args
9
- cmd = [ :psql, *args ]
10
- cmd = [ :sudo, "-u #{fetch(:pg_system_user)}", *cmd ] unless fetch(:pg_without_sudo)
11
- test *cmd.flatten
12
- end
13
-
14
- # Runs psql on the application database
15
- def psql_on_app_db(*args)
16
- psql_on_db(fetch(:pg_database), *args)
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 db_user_exists?
20
- psql_on_db fetch(:pg_system_db),'-tAc', %Q{"SELECT 1 FROM pg_roles WHERE rolname='#{fetch(:pg_username)}';" | grep -q 1}
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
- psql_on_db fetch(:pg_system_db), '-tAc', %Q{"SELECT 1 FROM pg_database WHERE datname='#{fetch(:pg_database)}';" | grep -q 1}
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
@@ -1,5 +1,5 @@
1
1
  module Capistrano
2
2
  module Postgresql
3
- VERSION = '4.9.2'
3
+ VERSION = '5.0.0'
4
4
  end
5
5
  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 :pg_ask_for_password, false
17
- set :pg_password, -> { ask_for_or_generate_password }
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
- if test "[ -e #{database_yml_file} ]"
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
- next unless Array( fetch(:pg_extensions) ).any?
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) ).each do |ext|
97
- next if [nil, false, ''].include?(ext)
98
- if psql_on_app_db '-c', %Q{"CREATE EXTENSION IF NOT EXISTS #{ext};"}
99
- puts "- Added extension #{ext} to #{fetch(:pg_database)}"
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 :create_database do
85
+ desc 'Create pg_username in database'
86
+ task :create_database_user do
110
87
  on roles :db do
111
- next if database_exists?
112
- unless psql_on_db fetch(:pg_system_db), '-c', %Q{"CREATE DATABASE \\"#{fetch(:pg_database)}\\" OWNER \\"#{fetch(:pg_username)}\\";"}
113
- error 'postgresql: creating database failed!'
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 DB user'
120
- task :create_db_user do
95
+ desc 'Create database'
96
+ task :create_database do
121
97
  on roles :db do
122
- next if db_user_exists?
123
- # 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.
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 "* ============================= * \n 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* ============================= *"
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
- puts "There are no servers in your app/config/deploy/#{fetch(:rails_env)}.rb with a :app role... Skipping Postgresql setup."
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
- puts "There is no server in your app/config/deploy/#{fetch(:rails_env)}.rb with a :db role... Skipping Postgresql setup."
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:create_db_user'
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 "postgresql:setup"
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.9.2
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-05 00:00:00.000000000 Z
12
+ date: 2018-06-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: capistrano