potluck-postgres 0.0.6 → 0.0.8
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/VERSION +1 -0
- data/lib/potluck/postgres/version.rb +7 -0
- data/lib/potluck/postgres.rb +110 -82
- metadata +29 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3589dd2164df71a6b980010ec03dc41416932e611f9b4b4ec1af4eb6d242015
|
4
|
+
data.tar.gz: 77616c26926b0ef95615f775f06fae452e875c752fbe1f4d3acf26f46e059dd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69805ee76d46065bb43d7b9d986221616c5ea58448acebcfbdc239556d54a254ba02e5824563d4cf9114fed2e939b41117574c2d5eaf6cd4bb528d354d704adc
|
7
|
+
data.tar.gz: 9400d94168b212a455450a52a5b8160899b619cb8ad549b20f84b3446cbc72b23b25fed6699e2a13db2d5f31e16e68a4bf79b4748f1f709fef35f3027653b9d8
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.8
|
data/lib/potluck/postgres.rb
CHANGED
@@ -2,20 +2,17 @@
|
|
2
2
|
|
3
3
|
require('potluck')
|
4
4
|
require('sequel')
|
5
|
+
require_relative('postgres/version')
|
5
6
|
|
6
7
|
module Potluck
|
7
|
-
|
8
|
-
# Error class used to wrap errors encountered while connecting to or setting up a database.
|
9
|
-
#
|
8
|
+
# Public: Error class used to wrap errors encountered while connecting to or setting up a database.
|
10
9
|
class PostgresError < ServiceError
|
11
10
|
attr_reader(:wrapped_error)
|
12
11
|
|
13
|
-
|
14
|
-
# Creates a new instance.
|
15
|
-
#
|
16
|
-
# * +message+ - Error message.
|
17
|
-
# * +wrapped_error+ - Original error that was rescued and is being wrapped by this one (optional).
|
12
|
+
# Public: Create a new instance.
|
18
13
|
#
|
14
|
+
# message - String error message.
|
15
|
+
# wrapped_error - Original Exception that was rescued and is being wrapped by this one.
|
19
16
|
def initialize(message, wrapped_error = nil)
|
20
17
|
super(message)
|
21
18
|
|
@@ -23,46 +20,91 @@ module Potluck
|
|
23
20
|
end
|
24
21
|
end
|
25
22
|
|
26
|
-
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# creation, as well as for utility methods such as database schema migration.
|
30
|
-
#
|
23
|
+
# Public: A Ruby interface for controlling and connecting to Postgres. Uses the Sequel gem to connect and
|
24
|
+
# perform automatic role and database creation, as well as for utility methods such as database schema
|
25
|
+
# migration.
|
31
26
|
class Postgres < Service
|
32
|
-
ROLE_NOT_FOUND_REGEX = /role .* does not exist
|
33
|
-
DATABASE_NOT_FOUND_REGEX = /database .* does not exist
|
27
|
+
ROLE_NOT_FOUND_REGEX = /role .* does not exist/
|
28
|
+
DATABASE_NOT_FOUND_REGEX = /database .* does not exist/
|
34
29
|
|
35
30
|
STARTING_UP_STRING = 'the database system is starting up'
|
36
|
-
|
31
|
+
STARTING_UP_TRIES = 30
|
37
32
|
|
38
33
|
CONNECTION_REFUSED_STRING = 'connection refused'
|
39
|
-
|
34
|
+
CONNECTION_REFUSED_TRIES = 3
|
40
35
|
|
41
36
|
attr_reader(:database)
|
42
37
|
|
43
|
-
|
44
|
-
#
|
38
|
+
# Public: Get the content of the launchctl plist file.
|
39
|
+
#
|
40
|
+
# Returns the String content.
|
41
|
+
def self.plist
|
42
|
+
dir = postgres_dir
|
43
|
+
|
44
|
+
super(
|
45
|
+
<<~XML
|
46
|
+
<key>EnvironmentVariables</key>
|
47
|
+
<dict>
|
48
|
+
<key>LC_ALL</key>
|
49
|
+
<string>C</string>
|
50
|
+
</dict>
|
51
|
+
<key>ProgramArguments</key>
|
52
|
+
<array>
|
53
|
+
<string>#{Potluck.config.homebrew_prefix}/opt/#{dir}/bin/postgres</string>
|
54
|
+
<string>-D</string>
|
55
|
+
<string>#{Potluck.config.homebrew_prefix}/var/#{dir}</string>
|
56
|
+
</array>
|
57
|
+
<key>WorkingDirectory</key>
|
58
|
+
<string>#{Potluck.config.homebrew_prefix}</string>
|
59
|
+
<key>StandardOutPath</key>
|
60
|
+
<string>#{Potluck.config.homebrew_prefix}/var/log/#{dir}.log</string>
|
61
|
+
<key>StandardErrorPath</key>
|
62
|
+
<string>#{Potluck.config.homebrew_prefix}/var/log/#{dir}.log</string>
|
63
|
+
XML
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Public: Get the directory of the latest Homebrew-installed Postgres version.
|
45
68
|
#
|
46
|
-
#
|
47
|
-
#
|
69
|
+
# Returns the String path.
|
70
|
+
# Raises PostgresError if no Homebrew Postgres installation is found.
|
71
|
+
def self.postgres_dir
|
72
|
+
versions = Dir[File.join(Potluck.config.homebrew_prefix, 'opt', 'postgresql@*')].sort_by do |path|
|
73
|
+
path.split('@').last.to_f
|
74
|
+
end
|
75
|
+
|
76
|
+
if versions.empty?
|
77
|
+
raise(PostgresError, 'No Postgres installation found (try running `brew install postgresql@X`)')
|
78
|
+
end
|
79
|
+
|
80
|
+
File.basename(versions.last)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Public: Create a new instance.
|
48
84
|
#
|
49
|
-
|
50
|
-
|
85
|
+
# config - Configuration Hash to pass to Sequel.connect.
|
86
|
+
# kwargs - Hash of keyword arguments to pass to Service.new.
|
87
|
+
def initialize(config, **kwargs)
|
88
|
+
super(**kwargs)
|
51
89
|
|
52
90
|
@config = config
|
53
91
|
end
|
54
92
|
|
55
|
-
|
56
|
-
# Disconnects and stops the Postgres process.
|
93
|
+
# Public: Disconnect and stop the Postgres process.
|
57
94
|
#
|
95
|
+
# Returns nothing.
|
58
96
|
def stop
|
59
97
|
disconnect
|
60
98
|
super
|
61
99
|
end
|
62
100
|
|
63
|
-
|
64
|
-
# Connects to the configured Postgres database.
|
101
|
+
# Public: Connect to the configured Postgres database.
|
65
102
|
#
|
103
|
+
# Returns nothing.
|
104
|
+
# Raises Sequel::DatabaseConnectionError if connecting fails.
|
105
|
+
# Raises PostgresError if role creation was attempted and failed.
|
106
|
+
# Raises PostgresError if database creation was attempted and failed.
|
107
|
+
# Raises PostgresError if permission grant was attempted and failed.
|
66
108
|
def connect
|
67
109
|
role_created = false
|
68
110
|
database_created = false
|
@@ -86,14 +128,12 @@ module Potluck
|
|
86
128
|
database_created = true
|
87
129
|
create_database
|
88
130
|
retry
|
89
|
-
elsif message.include?(STARTING_UP_STRING) && tries <
|
131
|
+
elsif message.include?(STARTING_UP_STRING) && tries < STARTING_UP_TRIES
|
90
132
|
sleep(1)
|
91
133
|
retry
|
92
|
-
elsif message.include?(CONNECTION_REFUSED_STRING) && tries <
|
134
|
+
elsif message.include?(CONNECTION_REFUSED_STRING) && tries < CONNECTION_REFUSED_TRIES
|
93
135
|
sleep(1)
|
94
136
|
retry
|
95
|
-
elsif message.include?(CONNECTION_REFUSED_STRING)
|
96
|
-
raise(PostgresError.new(e.message.strip, e))
|
97
137
|
else
|
98
138
|
raise
|
99
139
|
end
|
@@ -105,22 +145,27 @@ module Potluck
|
|
105
145
|
grant_permissions if role_created && !database_created
|
106
146
|
end
|
107
147
|
|
108
|
-
|
109
|
-
# Disconnects from the database if a connection was made.
|
148
|
+
# Public: Disconnect from the database if a connection was made.
|
110
149
|
#
|
150
|
+
# Returns nothing.
|
111
151
|
def disconnect
|
112
152
|
@database&.disconnect
|
113
153
|
end
|
114
154
|
|
115
|
-
|
116
|
-
#
|
117
|
-
# timestamp naming strategy as opposed to integers.
|
155
|
+
# Deprecated: Run database migrations by way of Sequel's migration extension. Migration files must use
|
156
|
+
# the timestamp naming strategy as opposed to integers.
|
118
157
|
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
158
|
+
# dir - String directory where migration files are located.
|
159
|
+
# steps - Integer number of steps forward or backward to migrate from the current migration (if omitted,
|
160
|
+
# will migrate forward to latest migration).
|
122
161
|
#
|
162
|
+
# Returns nothing.
|
123
163
|
def migrate(dir, steps = nil)
|
164
|
+
location = caller_locations(1, 1).first
|
165
|
+
|
166
|
+
warn("#{location.path}:#{location.lineno}: #{self.class.name}#migrate is deprecated and will be " \
|
167
|
+
"removed soon. Please use Sequel's migration extension directly instead.")
|
168
|
+
|
124
169
|
return unless File.directory?(dir)
|
125
170
|
|
126
171
|
Sequel.extension(:migration)
|
@@ -141,7 +186,7 @@ module Potluck
|
|
141
186
|
|
142
187
|
return if applied.empty? && steps <= 0
|
143
188
|
|
144
|
-
index = [[0, (all.index(current) || -1) + steps].max, all.size].min
|
189
|
+
index = [[0, (all.index(current) || -1) + steps].max, all.size - 1].min
|
145
190
|
file = all[index]
|
146
191
|
|
147
192
|
args.last[:target] = migrator.send(:migration_version_from_file, file)
|
@@ -154,54 +199,34 @@ module Potluck
|
|
154
199
|
@logger.level = original_level if original_level
|
155
200
|
end
|
156
201
|
|
157
|
-
##
|
158
|
-
# Content of the launchctl plist file.
|
159
|
-
#
|
160
|
-
def self.plist
|
161
|
-
super(
|
162
|
-
<<~EOS
|
163
|
-
<key>ProgramArguments</key>
|
164
|
-
<array>
|
165
|
-
<string>/usr/local/opt/postgresql/bin/postgres</string>
|
166
|
-
<string>-D</string>
|
167
|
-
<string>/usr/local/var/postgres</string>
|
168
|
-
</array>
|
169
|
-
<key>WorkingDirectory</key>
|
170
|
-
<string>/usr/local</string>
|
171
|
-
<key>StandardOutPath</key>
|
172
|
-
<string>/usr/local/var/log/postgres.log</string>
|
173
|
-
<key>StandardErrorPath</key>
|
174
|
-
<string>/usr/local/var/log/postgres.log</string>
|
175
|
-
EOS
|
176
|
-
)
|
177
|
-
end
|
178
|
-
|
179
202
|
private
|
180
203
|
|
181
|
-
|
182
|
-
#
|
183
|
-
# configured role. Useful in development.
|
204
|
+
# Internal: Attempt to connect to the 'postgres' database as the system user with no password and create
|
205
|
+
# the configured role. Useful in development environments.
|
184
206
|
#
|
207
|
+
# Returns nothing.
|
208
|
+
# Raises PostgresError if the role could not be created.
|
185
209
|
def create_role
|
186
210
|
tmp_config = admin_database_config
|
187
211
|
tmp_config[:database] = 'postgres'
|
188
212
|
|
189
213
|
begin
|
190
214
|
Sequel.connect(tmp_config, logger: @logger) do |database|
|
191
|
-
database.execute("CREATE ROLE \"#{@config[:username]}\" WITH LOGIN CREATEDB REPLICATION"\
|
215
|
+
database.execute("CREATE ROLE \"#{@config[:username]}\" WITH LOGIN CREATEDB REPLICATION" \
|
192
216
|
"#{" PASSWORD '#{@config[:password]}'" if @config[:password]}")
|
193
217
|
end
|
194
218
|
rescue => e
|
195
|
-
raise(PostgresError.new("Failed to create database role #{@config[:username].inspect} by "\
|
196
|
-
"connecting to database #{tmp_config[:database].inspect} as role "\
|
219
|
+
raise(PostgresError.new("Failed to create database role #{@config[:username].inspect} by " \
|
220
|
+
"connecting to database #{tmp_config[:database].inspect} as role " \
|
197
221
|
"#{tmp_config[:username].inspect}. Please create the role manually.", e))
|
198
222
|
end
|
199
223
|
end
|
200
224
|
|
201
|
-
|
202
|
-
#
|
203
|
-
# configured database. Useful in development.
|
225
|
+
# Internal: Attempt to connect to the 'postgres' database with the configured user and password and
|
226
|
+
# create the configured database. Useful in development environments.
|
204
227
|
#
|
228
|
+
# Returns nothing.
|
229
|
+
# Raises PostgresError if the database could not be created.
|
205
230
|
def create_database
|
206
231
|
tmp_config = @config.dup
|
207
232
|
tmp_config[:database] = 'postgres'
|
@@ -211,15 +236,17 @@ module Potluck
|
|
211
236
|
database.execute("CREATE DATABASE \"#{@config[:database]}\"")
|
212
237
|
end
|
213
238
|
rescue => e
|
214
|
-
raise(PostgresError.new("Failed to create database #{@config[:database].inspect} by connecting
|
215
|
-
"database #{tmp_config[:database].inspect} as role #{tmp_config[:username].inspect}. "\
|
239
|
+
raise(PostgresError.new("Failed to create database #{@config[:database].inspect} by connecting " \
|
240
|
+
"to database #{tmp_config[:database].inspect} as role #{tmp_config[:username].inspect}. " \
|
216
241
|
'Please create the database manually.', e))
|
217
242
|
end
|
218
243
|
end
|
219
244
|
|
220
|
-
|
221
|
-
#
|
245
|
+
# Internal: Grant appropriate permissions for the configured database role. Useful in development
|
246
|
+
# environments.
|
222
247
|
#
|
248
|
+
# Returns nothing.
|
249
|
+
# Raises PostgresError if permissions could not be granted.
|
223
250
|
def grant_permissions
|
224
251
|
tmp_config = admin_database_config
|
225
252
|
|
@@ -227,23 +254,24 @@ module Potluck
|
|
227
254
|
Sequel.connect(tmp_config, logger: @logger) do |db|
|
228
255
|
db.execute("GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"#{@config[:username]}\"")
|
229
256
|
db.execute("GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO \"#{@config[:username]}\"")
|
230
|
-
db.execute("ALTER DEFAULT PRIVILEGES FOR ROLE \"#{@config[:username]}\" IN SCHEMA public GRANT "\
|
257
|
+
db.execute("ALTER DEFAULT PRIVILEGES FOR ROLE \"#{@config[:username]}\" IN SCHEMA public GRANT " \
|
231
258
|
"ALL PRIVILEGES ON TABLES TO \"#{@config[:username]}\"")
|
232
259
|
end
|
233
260
|
rescue => e
|
234
|
-
raise(PostgresError.new(
|
235
|
-
"#{@config[:username].inspect} by connecting as role #{tmp_config[:username].inspect}. Please "\
|
261
|
+
raise(PostgresError.new('Failed to grant database permissions for role ' \
|
262
|
+
"#{@config[:username].inspect} by connecting as role #{tmp_config[:username].inspect}. Please " \
|
236
263
|
'grant appropriate permissions manually.', e))
|
237
264
|
end
|
238
265
|
end
|
239
266
|
|
240
|
-
|
241
|
-
#
|
242
|
-
#
|
267
|
+
# Internal: Return a configuration hash for connecting to Postgres to perform administrative tasks
|
268
|
+
# (role and database creation). Uses the system user as the username and no password. Useful in
|
269
|
+
# development environments
|
243
270
|
#
|
271
|
+
# Returns the configuration Hash.
|
244
272
|
def admin_database_config
|
245
273
|
config = @config.dup
|
246
|
-
config[:username] = ENV
|
274
|
+
config[:username] = ENV.fetch('USER')
|
247
275
|
config[:password] = nil
|
248
276
|
|
249
277
|
config
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: potluck-postgres
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nate Pickens
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-19 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: potluck
|
@@ -16,14 +15,14 @@ dependencies:
|
|
16
15
|
requirements:
|
17
16
|
- - '='
|
18
17
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.0.
|
18
|
+
version: 0.0.8
|
20
19
|
type: :runtime
|
21
20
|
prerelease: false
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
23
22
|
requirements:
|
24
23
|
- - '='
|
25
24
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.0.
|
25
|
+
version: 0.0.8
|
27
26
|
- !ruby/object:Gem::Dependency
|
28
27
|
name: pg
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,41 +69,49 @@ dependencies:
|
|
70
69
|
name: minitest
|
71
70
|
requirement: !ruby/object:Gem::Requirement
|
72
71
|
requirements:
|
73
|
-
- - "
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: 5.11.2
|
76
|
-
- - "<"
|
72
|
+
- - "~>"
|
77
73
|
- !ruby/object:Gem::Version
|
78
|
-
version:
|
74
|
+
version: '5.24'
|
79
75
|
type: :development
|
80
76
|
prerelease: false
|
81
77
|
version_requirements: !ruby/object:Gem::Requirement
|
82
78
|
requirements:
|
83
|
-
- - "
|
79
|
+
- - "~>"
|
84
80
|
- !ruby/object:Gem::Version
|
85
|
-
version: 5.
|
86
|
-
|
81
|
+
version: '5.24'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: minitest-reporters
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '1.7'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
87
94
|
- !ruby/object:Gem::Version
|
88
|
-
version:
|
95
|
+
version: '1.7'
|
89
96
|
description: An extension to the Potluck gem that provides some basic utilities for
|
90
97
|
setting up and connecting to Postgres databases, as well as control over the Postgres
|
91
98
|
process.
|
92
|
-
email:
|
93
99
|
executables: []
|
94
100
|
extensions: []
|
95
101
|
extra_rdoc_files: []
|
96
102
|
files:
|
97
103
|
- LICENSE
|
98
104
|
- README.md
|
105
|
+
- VERSION
|
99
106
|
- lib/potluck/postgres.rb
|
107
|
+
- lib/potluck/postgres/version.rb
|
100
108
|
homepage: https://github.com/npickens/potluck/tree/master/potluck-postgres
|
101
109
|
licenses:
|
102
110
|
- MIT
|
103
111
|
metadata:
|
104
|
-
|
105
|
-
|
106
|
-
source_code_uri: https://github.com/npickens/potluck/tree/
|
107
|
-
post_install_message:
|
112
|
+
bug_tracker_uri: https://github.com/npickens/potluck/issues
|
113
|
+
documentation_uri: https://github.com/npickens/potluck/blob/0.0.8/potluck-postgres/README.md
|
114
|
+
source_code_uri: https://github.com/npickens/potluck/tree/0.0.8/potluck-postgres
|
108
115
|
rdoc_options: []
|
109
116
|
require_paths:
|
110
117
|
- lib
|
@@ -112,15 +119,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
119
|
requirements:
|
113
120
|
- - ">="
|
114
121
|
- !ruby/object:Gem::Version
|
115
|
-
version:
|
122
|
+
version: 3.0.0
|
116
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
124
|
requirements:
|
118
125
|
- - ">="
|
119
126
|
- !ruby/object:Gem::Version
|
120
|
-
version:
|
127
|
+
version: 2.0.0
|
121
128
|
requirements: []
|
122
|
-
rubygems_version: 3.
|
123
|
-
signing_key:
|
129
|
+
rubygems_version: 3.6.6
|
124
130
|
specification_version: 4
|
125
131
|
summary: A Ruby manager for Postgres.
|
126
132
|
test_files: []
|