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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2dc9b254c8fd0d0bd4c7fee8d03705c1fe054577addaacf874286bfb32d0a2a
4
- data.tar.gz: b995b1b64aa3bca01392fcf874eaf71a7fae58bf0a5d0da54cc1e42269ed0499
3
+ metadata.gz: d3589dd2164df71a6b980010ec03dc41416932e611f9b4b4ec1af4eb6d242015
4
+ data.tar.gz: 77616c26926b0ef95615f775f06fae452e875c752fbe1f4d3acf26f46e059dd9
5
5
  SHA512:
6
- metadata.gz: 734fc97cfe75c7c0af39b2fb65db31dc6fe7d8355995fd339c7ec3808ffb2ee2f01de2b4852753b8ad45acde92a508126eef475725db2327c2482721c0a3b1d2
7
- data.tar.gz: 108749ea87986e3af08ef7f392b381880a5b391f44a3e86c237620c52a60c67bd591c8784d59a27c8b75ac88e3016ebb4987d0bb33054b28d7712312d705f357
6
+ metadata.gz: 69805ee76d46065bb43d7b9d986221616c5ea58448acebcfbdc239556d54a254ba02e5824563d4cf9114fed2e939b41117574c2d5eaf6cd4bb528d354d704adc
7
+ data.tar.gz: 9400d94168b212a455450a52a5b8160899b619cb8ad549b20f84b3446cbc72b23b25fed6699e2a13db2d5f31e16e68a4bf79b4748f1f709fef35f3027653b9d8
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.8
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Potluck
4
+ class Postgres < Service
5
+ VERSION = '0.0.8'
6
+ end
7
+ end
@@ -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
- # A Ruby interface for controlling and connecting to Postgres. Uses
28
- # [Sequel](https://github.com/jeremyevans/sequel) to connect and perform automatic role and database
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/.freeze
33
- DATABASE_NOT_FOUND_REGEX = /database .* does not exist/.freeze
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
- STARTING_UP_TIMEOUT = 30
31
+ STARTING_UP_TRIES = 30
37
32
 
38
33
  CONNECTION_REFUSED_STRING = 'connection refused'
39
- CONNECTION_REFUSED_TIMEOUT = 3
34
+ CONNECTION_REFUSED_TRIES = 3
40
35
 
41
36
  attr_reader(:database)
42
37
 
43
- ##
44
- # Creates a new instance.
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
- # * +config+ - Configuration hash to pass to <tt>Sequel.connect</tt>.
47
- # * +args+ - Arguments to pass to Potluck::Service.new (optional).
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
- def initialize(config, **args)
50
- super(**args)
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 < STARTING_UP_TIMEOUT
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 < CONNECTION_REFUSED_TIMEOUT
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
- # Runs database migrations by way of Sequel's migration extension. Migration files must use the
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
- # * +dir+ - Directory where migration files are located.
120
- # * +steps+ - Number of steps forward or backward to migrate from the current migration, otherwise will
121
- # migrate to latest (optional).
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
- # Attempts to connect to the 'postgres' database as the system user with no password and create the
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
- # Attempts to connect to the 'postgres' database with the configured user and password and create the
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 to "\
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
- # Grants appropriate permissions for the configured database role.
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("Failed to grant database permissions for role "\
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
- # Returns a configuration hash for connecting to Postgres to perform administrative tasks (i.e. role and
242
- # database creation). Uses the system user as the username and no password.
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['USER']
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.6
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: 2022-01-21 00:00:00.000000000 Z
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.6
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.6
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: 6.0.0
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.11.2
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: 6.0.0
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
- allowed_push_host: https://rubygems.org
105
- homepage_uri: https://github.com/npickens/potluck/tree/master/potluck-postgres
106
- source_code_uri: https://github.com/npickens/potluck/tree/master/potluck-postgres
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: 2.5.8
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: '0'
127
+ version: 2.0.0
121
128
  requirements: []
122
- rubygems_version: 3.2.32
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: []