pgchief 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -1
- data/README.md +7 -3
- data/config/pgchief.toml +6 -0
- data/lib/pgchief/command/base.rb +2 -0
- data/lib/pgchief/command/config_create.rb +5 -1
- data/lib/pgchief/command/database_backup.rb +53 -0
- data/lib/pgchief/command/s3_upload.rb +40 -0
- data/lib/pgchief/config/s3.rb +58 -0
- data/lib/pgchief/config.rb +41 -8
- data/lib/pgchief/prompt/backup_database.rb +15 -0
- data/lib/pgchief/prompt/database_management.rb +7 -2
- data/lib/pgchief/version.rb +1 -1
- data/lib/pgchief.rb +5 -0
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df59b4bbe15540e5d3b587f98c98ef71f2724f028299e88961766e2b6225ac2c
|
4
|
+
data.tar.gz: f5b0f578ac0c0610e2f020f740f207826a1f4cd05de16e27e5da7c1af860a408
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2e9611feb5db3d76d8e13ca3b153d1a0a387c90faadd249590c115b94d696da5d0b4d5b712db6d7a739b8f9b933fea1f40f9e6dc102fb064098b6ff3b568f58
|
7
|
+
data.tar.gz: 863b4f71e694fb3e8ebde4d4b020d446d96a582a24b4e457d0d8cd42bc474780956d874a02944ea959ac689a3d33870374565871c19deea2bc31c750349aff8a
|
data/CHANGELOG.md
CHANGED
@@ -13,6 +13,22 @@ and this project will try its best to adhere to [Semantic Versioning](https://se
|
|
13
13
|
|
14
14
|
### Fixes
|
15
15
|
|
16
|
+
## [0.4.0]
|
17
|
+
|
18
|
+
### Changes
|
19
|
+
|
20
|
+
* Clean up the config object
|
21
|
+
|
22
|
+
### Additions
|
23
|
+
|
24
|
+
* Back up option for databases: save to local filesystem or S3.
|
25
|
+
|
26
|
+
### Fixes
|
27
|
+
|
28
|
+
* Capture error where the config file does not exist and provide some guidance.
|
29
|
+
* Make a `PG::ConnectionBad` error a little less scary(?)
|
30
|
+
* Do not inherit the base `Command` class in `ConfigCreate`. It doesn't need to connect to the DB.
|
31
|
+
|
16
32
|
## [0.3.1]
|
17
33
|
|
18
34
|
### Changes
|
@@ -75,7 +91,9 @@ and this project will try its best to adhere to [Semantic Versioning](https://se
|
|
75
91
|
- Drop user ✅
|
76
92
|
- List databases ✅
|
77
93
|
|
78
|
-
[Unreleased]: https://github.com/jayroh/pgchief/compare/v0.
|
94
|
+
[Unreleased]: https://github.com/jayroh/pgchief/compare/v0.4.0...HEAD
|
95
|
+
[0.4.0]: https://github.com/jayroh/pgchief/releases/tag/v0.4.0
|
96
|
+
[0.3.1]: https://github.com/jayroh/pgchief/releases/tag/v0.3.1
|
79
97
|
[0.3.0]: https://github.com/jayroh/pgchief/releases/tag/v0.3.0
|
80
98
|
[0.2.0]: https://github.com/jayroh/pgchief/releases/tag/v0.2.0
|
81
99
|
[0.1.0]: https://github.com/jayroh/pgchief/releases/tag/v0.1.0
|
data/README.md
CHANGED
@@ -41,7 +41,7 @@ pgchief
|
|
41
41
|
|
42
42
|
## Config
|
43
43
|
|
44
|
-
Format of `~/.pgchief.toml`
|
44
|
+
Format of `~/.config/pgchief/config.toml`
|
45
45
|
|
46
46
|
```toml
|
47
47
|
# Connection string to superuser account at your PG instance
|
@@ -130,5 +130,9 @@ Give "rando-username" access to database(s):
|
|
130
130
|
* [x] Give user permissions to use database
|
131
131
|
* [x] Initialize toml file
|
132
132
|
* [x] Display connection information
|
133
|
-
* [
|
134
|
-
* [
|
133
|
+
* [x] Back up database locally
|
134
|
+
* [x] Back up database to S3
|
135
|
+
* [ ] Restore local database
|
136
|
+
* [ ] Restore remote database @ S3
|
137
|
+
* [ ] Quickly back up via command line option
|
138
|
+
* [ ] Quickly restore via command line option
|
data/config/pgchief.toml
CHANGED
@@ -8,3 +8,9 @@ backup_dir = "~/.config/pgchief/backups"
|
|
8
8
|
|
9
9
|
# Location of saved database connection strings
|
10
10
|
# credentials_file = "~/.config/pgchief/credentials"
|
11
|
+
|
12
|
+
# S3 config - if present, will back up to S3 instead of local filesystem
|
13
|
+
# s3_key = ""
|
14
|
+
# s3_secret = ""
|
15
|
+
# s3_region = "us-east-1"
|
16
|
+
# s3_path_prefix = "s3://bucket-name/database-backups/"
|
data/lib/pgchief/command/base.rb
CHANGED
@@ -5,7 +5,11 @@ require "fileutils"
|
|
5
5
|
module Pgchief
|
6
6
|
module Command
|
7
7
|
# Create a configuration file at $HOME
|
8
|
-
class ConfigCreate
|
8
|
+
class ConfigCreate
|
9
|
+
def self.call(dir: "#{Dir.home}/.config/pgchief")
|
10
|
+
new.call(dir: dir)
|
11
|
+
end
|
12
|
+
|
9
13
|
def call(dir: "#{Dir.home}/.config/pgchief")
|
10
14
|
return if File.exist?("#{dir}/config.toml")
|
11
15
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
module Pgchief
|
6
|
+
module Command
|
7
|
+
# Command object to drop a database
|
8
|
+
class DatabaseBackup < Base
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def_delegators :@uploader, :configured?, :upload!, :s3_location
|
12
|
+
|
13
|
+
attr_reader :database
|
14
|
+
|
15
|
+
def call
|
16
|
+
@database = params.first
|
17
|
+
@uploader = Pgchief::Command::S3Upload.new(local_location)
|
18
|
+
raise Pgchief::Errors::DatabaseMissingError unless db_exists?
|
19
|
+
|
20
|
+
backup!
|
21
|
+
upload! if configured?
|
22
|
+
|
23
|
+
"Database '#{database}' backed up to #{location}"
|
24
|
+
rescue PG::Error => e
|
25
|
+
"Error: #{e.message}"
|
26
|
+
ensure
|
27
|
+
conn.close
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def backup!
|
33
|
+
`pg_dump -Fc #{database} -f #{local_location}`
|
34
|
+
end
|
35
|
+
|
36
|
+
def db_exists?
|
37
|
+
query = "SELECT 1 FROM pg_database WHERE datname = '#{database}'"
|
38
|
+
conn.exec(query).any?
|
39
|
+
end
|
40
|
+
|
41
|
+
def location
|
42
|
+
configured? ? s3_location : local_location
|
43
|
+
end
|
44
|
+
|
45
|
+
def local_location
|
46
|
+
@local_location ||= begin
|
47
|
+
timestamp = Time.now.strftime("%Y%m%d%H%M%S")
|
48
|
+
"#{Pgchief::Config.backup_dir}#{database}-#{timestamp}.dump"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pgchief
|
4
|
+
module Command
|
5
|
+
# Class to upload a file to S3
|
6
|
+
class S3Upload
|
7
|
+
attr_reader :local_location, :file_name, :bucket, :path
|
8
|
+
|
9
|
+
def initialize(local_location)
|
10
|
+
@local_location = local_location
|
11
|
+
@file_name = File.basename(local_location)
|
12
|
+
end
|
13
|
+
|
14
|
+
def upload!
|
15
|
+
s3.client.put_object(
|
16
|
+
bucket: s3.bucket,
|
17
|
+
key: "#{s3.path}#{file_name}",
|
18
|
+
body: File.open(local_location, "rb"),
|
19
|
+
acl: "private",
|
20
|
+
content_type: "application/octet-stream"
|
21
|
+
)
|
22
|
+
FileUtils.rm(local_location)
|
23
|
+
end
|
24
|
+
|
25
|
+
def s3_location
|
26
|
+
"s3://#{s3.bucket}/#{s3.path}#{file_name}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def configured?
|
30
|
+
s3.configured?
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def s3
|
36
|
+
Pgchief::Config.s3
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
module Pgchief
|
6
|
+
class Config
|
7
|
+
# Class to store s3 configuration settings
|
8
|
+
class S3
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def_delegators \
|
12
|
+
:config,
|
13
|
+
:s3_key,
|
14
|
+
:s3_secret,
|
15
|
+
:s3_region,
|
16
|
+
:s3_path_prefix
|
17
|
+
|
18
|
+
PREFIX_REGEX = %r{\As3://(?<bucket>(\w|-)*)/(?<path>(\w|/)*/)\z}
|
19
|
+
|
20
|
+
attr_reader :config
|
21
|
+
|
22
|
+
def initialize(config)
|
23
|
+
@config = config
|
24
|
+
end
|
25
|
+
|
26
|
+
def client
|
27
|
+
@client ||= Aws::S3::Client.new(
|
28
|
+
access_key_id: s3_key,
|
29
|
+
secret_access_key: s3_secret,
|
30
|
+
region: s3_region
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def bucket
|
35
|
+
s3_match[:bucket]
|
36
|
+
end
|
37
|
+
|
38
|
+
def path
|
39
|
+
s3_match[:path]
|
40
|
+
end
|
41
|
+
|
42
|
+
def configured?
|
43
|
+
[
|
44
|
+
s3_key,
|
45
|
+
s3_secret,
|
46
|
+
s3_region,
|
47
|
+
s3_path_prefix
|
48
|
+
].none?(&:nil?)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def s3_match
|
54
|
+
@s3_match ||= s3_path_prefix.match(PREFIX_REGEX)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/pgchief/config.rb
CHANGED
@@ -7,30 +7,63 @@ module Pgchief
|
|
7
7
|
class Config
|
8
8
|
class << self
|
9
9
|
attr_accessor \
|
10
|
-
:
|
11
|
-
:
|
10
|
+
:s3_key,
|
11
|
+
:s3_secret,
|
12
|
+
:s3_region
|
12
13
|
|
13
14
|
attr_writer :pgurl
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
attr_reader \
|
17
|
+
:s3_path_prefix,
|
18
|
+
:backup_dir,
|
19
|
+
:credentials_file
|
20
|
+
|
21
|
+
def load_config!(toml_file = "#{Dir.home}/.config/pgchief/config.toml") # rubocop:disable Metrics/AbcSize
|
22
|
+
config = TomlRB.load_file(toml_file, symbolize_keys: true)
|
23
|
+
self.backup_dir = config[:backup_dir]
|
24
|
+
self.credentials_file = config[:credentials_file]
|
25
|
+
self.pgurl = config[:pgurl]
|
26
|
+
self.s3_key = config[:s3_key]
|
27
|
+
self.s3_secret = config[:s3_secret]
|
28
|
+
self.s3_region = config[:s3_region]
|
29
|
+
self.s3_path_prefix = config[:s3_path_prefix]
|
30
|
+
rescue Errno::ENOENT
|
31
|
+
puts config_missing_error(toml_file)
|
32
|
+
end
|
17
33
|
|
18
|
-
|
19
|
-
@
|
20
|
-
@pgurl = config[:pgurl]
|
34
|
+
def s3
|
35
|
+
@s3 ||= Pgchief::Config::S3.new(self)
|
21
36
|
end
|
22
37
|
|
23
38
|
def pgurl
|
24
39
|
ENV.fetch("DATABASE_URL", @pgurl)
|
25
40
|
end
|
26
41
|
|
42
|
+
def backup_dir=(value)
|
43
|
+
@backup_dir = value ? "#{value.chomp("/")}/".gsub("~", Dir.home) : "/tmp/"
|
44
|
+
end
|
45
|
+
|
46
|
+
def s3_path_prefix=(value)
|
47
|
+
@s3_path_prefix = value ? "#{value.chomp("/")}/" : nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def credentials_file=(value)
|
51
|
+
@credentials_file = value&.gsub("~", Dir.home)
|
52
|
+
end
|
53
|
+
|
27
54
|
def set_up_file_structure!
|
28
55
|
FileUtils.mkdir_p(backup_dir)
|
29
|
-
|
30
56
|
return unless credentials_file && !File.exist?(credentials_file)
|
31
57
|
|
32
58
|
FileUtils.touch(credentials_file)
|
33
59
|
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def config_missing_error(toml_file)
|
64
|
+
"You must create a config file at #{toml_file}.\n" \
|
65
|
+
"run `pgchief --init` to create it."
|
66
|
+
end
|
34
67
|
end
|
35
68
|
end
|
36
69
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pgchief
|
4
|
+
module Prompt
|
5
|
+
# Class to prompt for which database to drop
|
6
|
+
class BackupDatabase < Base
|
7
|
+
def call
|
8
|
+
database = prompt.select("Which database needs backing up?", Pgchief::Database.all)
|
9
|
+
result = Pgchief::Command::DatabaseBackup.call(database)
|
10
|
+
|
11
|
+
prompt.say result
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -6,8 +6,13 @@ module Pgchief
|
|
6
6
|
class DatabaseManagement < Base
|
7
7
|
def call
|
8
8
|
prompt = TTY::Prompt.new
|
9
|
-
result = prompt.select("Database management", [
|
10
|
-
|
9
|
+
result = prompt.select("Database management", [
|
10
|
+
"Create database",
|
11
|
+
"Drop database",
|
12
|
+
"Database List",
|
13
|
+
"Backup database"
|
14
|
+
])
|
15
|
+
scope = result == "Database List" ? "command" : "prompt"
|
11
16
|
|
12
17
|
klassify(scope, result).call
|
13
18
|
end
|
data/lib/pgchief/version.rb
CHANGED
data/lib/pgchief.rb
CHANGED
@@ -3,9 +3,11 @@
|
|
3
3
|
require "pg"
|
4
4
|
require "tty-prompt"
|
5
5
|
require "tty-option"
|
6
|
+
require "aws-sdk-s3"
|
6
7
|
|
7
8
|
require "pgchief/cli"
|
8
9
|
require "pgchief/config"
|
10
|
+
require "pgchief/config/s3"
|
9
11
|
require "pgchief/connection_string"
|
10
12
|
require "pgchief/version"
|
11
13
|
require "pgchief/database"
|
@@ -13,6 +15,7 @@ require "pgchief/user"
|
|
13
15
|
|
14
16
|
require "pgchief/prompt/base"
|
15
17
|
require "pgchief/prompt/start"
|
18
|
+
require "pgchief/prompt/backup_database"
|
16
19
|
require "pgchief/prompt/create_database"
|
17
20
|
require "pgchief/prompt/create_user"
|
18
21
|
require "pgchief/prompt/database_management"
|
@@ -25,11 +28,13 @@ require "pgchief/prompt/view_database_connection_string"
|
|
25
28
|
require "pgchief/command"
|
26
29
|
require "pgchief/command/base"
|
27
30
|
require "pgchief/command/config_create"
|
31
|
+
require "pgchief/command/database_backup"
|
28
32
|
require "pgchief/command/database_create"
|
29
33
|
require "pgchief/command/database_drop"
|
30
34
|
require "pgchief/command/database_list"
|
31
35
|
require "pgchief/command/database_privileges_grant"
|
32
36
|
require "pgchief/command/retrieve_connection_string"
|
37
|
+
require "pgchief/command/s3_upload"
|
33
38
|
require "pgchief/command/store_connection_string"
|
34
39
|
require "pgchief/command/user_create"
|
35
40
|
require "pgchief/command/user_drop"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pgchief
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Oliveira
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk-s3
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: pg
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -89,19 +103,23 @@ files:
|
|
89
103
|
- lib/pgchief/command.rb
|
90
104
|
- lib/pgchief/command/base.rb
|
91
105
|
- lib/pgchief/command/config_create.rb
|
106
|
+
- lib/pgchief/command/database_backup.rb
|
92
107
|
- lib/pgchief/command/database_create.rb
|
93
108
|
- lib/pgchief/command/database_drop.rb
|
94
109
|
- lib/pgchief/command/database_list.rb
|
95
110
|
- lib/pgchief/command/database_privileges_grant.rb
|
96
111
|
- lib/pgchief/command/retrieve_connection_string.rb
|
112
|
+
- lib/pgchief/command/s3_upload.rb
|
97
113
|
- lib/pgchief/command/store_connection_string.rb
|
98
114
|
- lib/pgchief/command/user_create.rb
|
99
115
|
- lib/pgchief/command/user_drop.rb
|
100
116
|
- lib/pgchief/command/user_list.rb
|
101
117
|
- lib/pgchief/config.rb
|
118
|
+
- lib/pgchief/config/s3.rb
|
102
119
|
- lib/pgchief/connection_string.rb
|
103
120
|
- lib/pgchief/database.rb
|
104
121
|
- lib/pgchief/prompt.rb
|
122
|
+
- lib/pgchief/prompt/backup_database.rb
|
105
123
|
- lib/pgchief/prompt/base.rb
|
106
124
|
- lib/pgchief/prompt/create_database.rb
|
107
125
|
- lib/pgchief/prompt/create_user.rb
|
@@ -139,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
157
|
- !ruby/object:Gem::Version
|
140
158
|
version: '0'
|
141
159
|
requirements: []
|
142
|
-
rubygems_version: 3.
|
160
|
+
rubygems_version: 3.5.21
|
143
161
|
signing_key:
|
144
162
|
specification_version: 4
|
145
163
|
summary: A simple ruby script to manage postgresql databases and users
|