potluck-postgres 0.0.4 → 0.0.5
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/lib/potluck/postgres.rb +100 -36
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 667d6b357e4b021bba60a415b90f8623d9b72683ed3b5869ce87f2e43e033325
|
4
|
+
data.tar.gz: 656fd69e5541b414c9e67f750daabaf072c94fbf1237042424a3a5848cfedfa8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03b852e0ce06ed33d0c7010779eb5bd6d1804e0151df4814a3ad218a50ffcaa27daebf47e7b7288ac7755c75ef4c11b003a82516f6a383e724dbbcdc4269759c
|
7
|
+
data.tar.gz: c3cfc79e9c846ca36e2da1015871cac23928bca1291bb7ee7c05ec8b459c71c4918bf057f70516da5dec9a6ab6942a4fc9d1428af970ab79bbfb20936039f5d9
|
data/lib/potluck/postgres.rb
CHANGED
@@ -4,6 +4,30 @@ require('potluck')
|
|
4
4
|
require('sequel')
|
5
5
|
|
6
6
|
module Potluck
|
7
|
+
##
|
8
|
+
# Error class used to wrap errors encountered while connecting to or setting up a database.
|
9
|
+
#
|
10
|
+
class PostgresError < ServiceError
|
11
|
+
attr_reader(:wrapped_error)
|
12
|
+
|
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).
|
18
|
+
#
|
19
|
+
def initialize(message, wrapped_error = nil)
|
20
|
+
super(message)
|
21
|
+
|
22
|
+
@wrapped_error = wrapped_error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
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
|
+
#
|
7
31
|
class Postgres < Service
|
8
32
|
ROLE_NOT_FOUND_REGEX = /role .* does not exist/.freeze
|
9
33
|
DATABASE_NOT_FOUND_REGEX = /database .* does not exist/.freeze
|
@@ -16,12 +40,29 @@ module Potluck
|
|
16
40
|
|
17
41
|
attr_reader(:database)
|
18
42
|
|
43
|
+
##
|
44
|
+
# Creates a new instance.
|
45
|
+
#
|
46
|
+
# * +config+ - Configuration hash to pass to <tt>Sequel.connect</tt>.
|
47
|
+
# * +args+ - Arguments to pass to Potluck::Service.new (optional).
|
48
|
+
#
|
19
49
|
def initialize(config, **args)
|
20
50
|
super(**args)
|
21
51
|
|
22
52
|
@config = config
|
23
53
|
end
|
24
54
|
|
55
|
+
##
|
56
|
+
# Disconnects and stops the Postgres process.
|
57
|
+
#
|
58
|
+
def stop
|
59
|
+
disconnect
|
60
|
+
super
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Connects to the configured Postgres database.
|
65
|
+
#
|
25
66
|
def connect
|
26
67
|
(tries ||= 0) && (tries += 1)
|
27
68
|
@database = Sequel.connect(@config, logger: @logger)
|
@@ -47,49 +88,27 @@ module Potluck
|
|
47
88
|
sleep(1)
|
48
89
|
retry
|
49
90
|
elsif message.include?(CONNECTION_REFUSED_STRING)
|
50
|
-
|
91
|
+
raise(PostgresError.new(e.message.strip, e))
|
51
92
|
else
|
52
|
-
|
93
|
+
raise
|
53
94
|
end
|
54
95
|
end
|
55
96
|
|
97
|
+
##
|
98
|
+
# Disconnects from the database if a connection was made.
|
99
|
+
#
|
56
100
|
def disconnect
|
57
101
|
@database&.disconnect
|
58
102
|
end
|
59
103
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
database.execute("CREATE ROLE #{@config[:username]} WITH LOGIN CREATEDB REPLICATION PASSWORD "\
|
69
|
-
"'#{@config[:password]}'")
|
70
|
-
end
|
71
|
-
rescue => e
|
72
|
-
@logger.error("#{e.class}: #{e.message.strip}\n #{e.backtrace.join("\n ")}\n")
|
73
|
-
abort("Could not create role '#{@config[:username]}'. Make sure database user '#{ENV['USER']}' "\
|
74
|
-
'has permission to do so, or create it manually.')
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def create_database
|
79
|
-
tmp_config = @config.dup
|
80
|
-
tmp_config[:database] = 'postgres'
|
81
|
-
|
82
|
-
begin
|
83
|
-
Sequel.connect(tmp_config, logger: @logger) do |database|
|
84
|
-
database.execute("CREATE DATABASE #{@config[:database]}")
|
85
|
-
end
|
86
|
-
rescue => e
|
87
|
-
@logger.error("#{e.class}: #{e.message.strip}\n #{e.backtrace.join("\n ")}\n")
|
88
|
-
abort("Could not create database '#{@config[:database]}'. Make sure database user "\
|
89
|
-
"'#{@config[:username]}' has permission to do so, or create it manually.")
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
104
|
+
##
|
105
|
+
# Runs database migrations by way of Sequel's migration extension. Migration files must use the
|
106
|
+
# timestamp naming strategy as opposed to integers.
|
107
|
+
#
|
108
|
+
# * +dir+ - Directory where migration files are located.
|
109
|
+
# * +steps+ - Number of steps forward or backward to migrate from the current migration, otherwise will
|
110
|
+
# migrate to latest (optional).
|
111
|
+
#
|
93
112
|
def migrate(dir, steps = nil)
|
94
113
|
return unless File.directory?(dir)
|
95
114
|
|
@@ -97,7 +116,7 @@ module Potluck
|
|
97
116
|
|
98
117
|
# Suppress Sequel schema migration table queries.
|
99
118
|
original_level = @logger.level
|
100
|
-
@logger.level = Logger::WARN
|
119
|
+
@logger.level = Logger::WARN if @logger.level == Logger::INFO
|
101
120
|
|
102
121
|
args = [Sequel::Model.db, dir, {allow_missing_migration_files: true}]
|
103
122
|
migrator = Sequel::TimestampMigrator.new(*args)
|
@@ -120,10 +139,55 @@ module Potluck
|
|
120
139
|
migrator = Sequel::TimestampMigrator.new(*args)
|
121
140
|
@logger.level = original_level
|
122
141
|
migrator.run
|
142
|
+
ensure
|
143
|
+
@logger.level = original_level if original_level
|
123
144
|
end
|
124
145
|
|
125
146
|
private
|
126
147
|
|
148
|
+
##
|
149
|
+
# Attempts to connect to the 'postgres' database as the system user with no password and create the
|
150
|
+
# configured role. Useful in development.
|
151
|
+
#
|
152
|
+
def create_database_role
|
153
|
+
tmp_config = @config.dup
|
154
|
+
tmp_config[:database] = 'postgres'
|
155
|
+
tmp_config[:username] = ENV['USER']
|
156
|
+
tmp_config[:password] = nil
|
157
|
+
|
158
|
+
begin
|
159
|
+
Sequel.connect(tmp_config, logger: @logger) do |database|
|
160
|
+
database.execute("CREATE ROLE #{@config[:username]} WITH LOGIN CREATEDB REPLICATION PASSWORD "\
|
161
|
+
"'#{@config[:password]}'")
|
162
|
+
end
|
163
|
+
rescue => e
|
164
|
+
raise(PostgresError.new("Database role #{@config[:username].inspect} could not be created using "\
|
165
|
+
"system user #{tmp_config[:username].inspect}. Please create the role manually.", e))
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Attempts to connect to the 'postgres' database with the configured user and password and create the
|
171
|
+
# configured database. Useful in development.
|
172
|
+
#
|
173
|
+
def create_database
|
174
|
+
tmp_config = @config.dup
|
175
|
+
tmp_config[:database] = 'postgres'
|
176
|
+
|
177
|
+
begin
|
178
|
+
Sequel.connect(tmp_config, logger: @logger) do |database|
|
179
|
+
database.execute("CREATE DATABASE #{@config[:database]}")
|
180
|
+
end
|
181
|
+
rescue => e
|
182
|
+
raise(PostgresError.new("Database #{@config[:database].inspect} could not be created by "\
|
183
|
+
"connecting to system database #{tmp_config[:database].inspect}. Please create the database "\
|
184
|
+
'manually.', e))
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
##
|
189
|
+
# Content of the launchctl plist file.
|
190
|
+
#
|
127
191
|
def self.plist
|
128
192
|
super(
|
129
193
|
<<~EOS
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nate Pickens
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-12-
|
11
|
+
date: 2021-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: potluck
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.0.
|
19
|
+
version: 0.0.5
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.0.
|
26
|
+
version: 0.0.5
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: pg
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|