heroku-api-postgres 0.10.0 → 0.13.0
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/.example.env +2 -1
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/ci.yml +23 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +5 -1
- data/.ruby-version +1 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile +11 -0
- data/README.md +38 -16
- data/Rakefile +2 -0
- data/bin/console +1 -0
- data/docs/services.md +8 -8
- data/heroku-api-postgres.gemspec +11 -8
- data/lib/heroku/api/postgres/backups.rb +22 -22
- data/lib/heroku/api/postgres/client.rb +45 -8
- data/lib/heroku/api/postgres/credentials.rb +34 -0
- data/lib/heroku/api/postgres/databases.rb +9 -12
- data/lib/heroku/api/postgres/version.rb +3 -1
- data/lib/heroku/api/postgres.rb +3 -0
- metadata +18 -111
- data/.travis.yml +0 -7
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile.lock +0 -82
- data/LICENSE.txt +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96105ebed19f8f800dfb2dc71a8ce22d58feac51f07e7ea6963b64558c7eaea9
|
4
|
+
data.tar.gz: 34aea14eb3bf6b0639f3f66f93b9a42862e564e8d106b4c1de7fa8fb00c2561c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9006afb4de11724c4f3b57fb9ecb19cc09b51361cdc1dd9d157fd3123f339f83321bbc8be1ce9f2dc1ee17d2398ca9f23edbe67cec940caa1b8a63bd262568cb
|
7
|
+
data.tar.gz: 80e566c5ee325a112cec56a3af719ef996759482f165122b059d743389dbf1292b0f30c41d2c70f1625fa09a678778f80f3eca54240fe47c05ff55cdaa527911
|
data/.example.env
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
HEROKU_OAUTH_TOKEN=a_valid_oauth_token
|
2
2
|
VALID_APP_ID_WITH_DATABASE=valid_app_id_with_database
|
3
3
|
VALID_DATABASE_ID_WITH_SCHEDULES=a_valid_database_id_with_a_schedule
|
4
|
-
|
4
|
+
VALID_APP_ID_WITH_DB_IN_PRO_PLAN=a_valid_app_id_with_database_in_pro_plan
|
5
|
+
VALID_DATABASE_ID_WITH_PRO_PLAN=a_valid_database_id_in_pro_plan
|
5
6
|
VALID_APP_ID=valid_app_id
|
6
7
|
VALID_DUMP_URL=valid_dump_public_url
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
github: [coorasse]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
lint:
|
8
|
+
runs-on: ubuntu-24.04
|
9
|
+
steps:
|
10
|
+
- name: Checkout code
|
11
|
+
uses: actions/checkout@v4
|
12
|
+
|
13
|
+
- name: Set up Ruby
|
14
|
+
uses: ruby/setup-ruby@v1
|
15
|
+
with:
|
16
|
+
ruby-version: 3.2
|
17
|
+
bundler-cache: true
|
18
|
+
|
19
|
+
- name: Setup env variables
|
20
|
+
run: cp .example.env .env
|
21
|
+
|
22
|
+
- name: Tests
|
23
|
+
run: bin/check
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.2.7
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
## 0.13.0
|
2
|
+
|
3
|
+
* Update of dependencies and minimum ruby version set to 3.2.7. ([@coorasse][])
|
4
|
+
* Allow to connect using an API Key. ([@coorasse][])
|
5
|
+
|
6
|
+
## 0.12.0
|
7
|
+
|
8
|
+
* [#18](https://github.com/coorasse/heroku-api-postgres/pull/18): Support ruby 3.0. ([@louism517][])
|
9
|
+
* [#15](https://github.com/coorasse/heroku-api-postgres/pull/15): Return latest backup if backup_num is not provided. ([@deepakmahakale][])
|
10
|
+
* [#14](https://github.com/coorasse/heroku-api-postgres/pull/14): Add support for rotating credentials. ([@avokhmin][])
|
11
|
+
* [#13](https://github.com/coorasse/heroku-api-postgres/pull/13): Allow to use hour and timezone when scheduling backups. ([@avokhmin][])
|
12
|
+
|
13
|
+
[@avokhmin]: https://github.com/avokhmin
|
14
|
+
[@deepakmahakale]: https://github.com/deepakmahakale
|
15
|
+
[@louism517]: https://github.com/louism517
|
16
|
+
[@coorasse]: https://github.com/coorasse
|
data/Gemfile
CHANGED
@@ -1,6 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
6
|
|
5
7
|
# Specify your gem's dependencies in heroku-api-postgres.gemspec
|
6
8
|
gemspec
|
9
|
+
|
10
|
+
gem 'bundler', '~> 2'
|
11
|
+
gem 'dotenv'
|
12
|
+
gem 'pry'
|
13
|
+
gem 'rake', '~> 13.0'
|
14
|
+
gem 'rspec', '~> 3.0'
|
15
|
+
gem 'rubocop', '1.74.0'
|
16
|
+
gem 'vcr', '~> 6.3'
|
17
|
+
gem 'webmock', '~> 3.25'
|
data/README.md
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
# Heroku::Api::Postgres
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
**This gem has been extracted from https://db-backups.com.**
|
4
|
+
|
5
|
+
**Your "one click" backup solution for Heroku apps.**
|
5
6
|
|
6
|
-
|
7
|
-
[
|
7
|
+
Ruby library to invoke Heroku Postgres APIs.
|
8
|
+
An extension to the official [Platform API](https://github.com/heroku/platform-api) gem to introduce the missing APIs for Postgres.
|
8
9
|
|
9
10
|
**This gem is not officialy supported**. We use the same APIs that the offical Heroku Toolbelt uses,
|
10
11
|
therefore is unrealistic that a breaking change in the APIs would break it, since it means it would break
|
11
12
|
both this gem and the official Heroku CLI.
|
12
13
|
|
14
|
+
|
13
15
|
Not all APIs are implemented at the moment but we are working hard on implementing all of them.
|
14
16
|
|
15
17
|
Please check the [list of implemented and not implemented services](docs/services.md).
|
@@ -34,7 +36,13 @@ Or install it yourself as:
|
|
34
36
|
|
35
37
|
## Usage
|
36
38
|
|
37
|
-
This gem client needs to be instantiated in a similar way to the PlatformAPI
|
39
|
+
This gem client needs to be instantiated in a similar way to the [PlatformAPI](https://github.com/heroku/platform-api).
|
40
|
+
You can use the same oauth key or API key that you use for the PlatformAPI.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
postgres_api_client = Heroku::Api::Postgres.connect(ENV['HEROKU_API_KEY'])
|
44
|
+
```
|
45
|
+
|
38
46
|
|
39
47
|
```ruby
|
40
48
|
postgres_api_client = Heroku::Api::Postgres.connect_oauth(ENV['HEROKU_OAUTH_TOKEN'])
|
@@ -52,7 +60,7 @@ databases_client = postgres_api_client.databases
|
|
52
60
|
---
|
53
61
|
|
54
62
|
```ruby
|
55
|
-
database_info = databases_client.info(database_id)
|
63
|
+
database_info = databases_client.info(app_id, database_id)
|
56
64
|
```
|
57
65
|
|
58
66
|
returns a [Database](docs/models.md#database).
|
@@ -60,13 +68,27 @@ returns a [Database](docs/models.md#database).
|
|
60
68
|
---
|
61
69
|
|
62
70
|
```ruby
|
63
|
-
database = postgres_api_client.databases.wait(database_id, wait_interval: 5)
|
71
|
+
database = postgres_api_client.databases.wait(app_id, database_id, wait_interval: 5)
|
64
72
|
```
|
65
73
|
|
66
74
|
Waits for the given database to be ready.
|
67
75
|
|
68
76
|
Polls every `wait_interval` seconds (default 3).
|
69
77
|
|
78
|
+
### Credentials
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
credentials_client = postgres_api_client.credentials
|
82
|
+
```
|
83
|
+
|
84
|
+
---
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
credentials_client.rotate(app_id, database_id)
|
88
|
+
```
|
89
|
+
|
90
|
+
Rotate the database credentials.
|
91
|
+
|
70
92
|
### Backups
|
71
93
|
|
72
94
|
```ruby
|
@@ -93,6 +115,9 @@ The app_id can be either the name of your heroku app or the id.
|
|
93
115
|
|
94
116
|
[Check official API](https://devcenter.heroku.com/articles/platform-api-reference#app)
|
95
117
|
|
118
|
+
To retrieve the APP_ID and DATABASE_ID needed to run the tests you can use the name of the app as APP_ID and execute:
|
119
|
+
`heroku addons --json --app YOUR_APP` to retrieve the DATABASE_ID.
|
120
|
+
|
96
121
|
---
|
97
122
|
|
98
123
|
```ruby
|
@@ -163,20 +188,24 @@ end
|
|
163
188
|
You can obtain a database id by calling the Heroku Platform API
|
164
189
|
|
165
190
|
```ruby
|
191
|
+
heroku = PlatformAPI.connect_oauth(ENV['HEROKU_OAUTH_TOKEN'])
|
166
192
|
addons = heroku.addon.list
|
167
193
|
databases = addons.select { |addon| addon['addon_service']['name'] == 'heroku-postgresql' }
|
168
194
|
databases_ids = databases.map{ |addon| addon['id'] }
|
169
195
|
```
|
170
196
|
|
171
|
-
Check also the [
|
197
|
+
Check also the [Official API](https://devcenter.heroku.com/articles/platform-api-reference#add-on)
|
172
198
|
|
173
199
|
## Development
|
174
200
|
|
175
201
|
After checking out the repo, run `bin/setup` to install dependencies.
|
176
|
-
Then, run `rake spec` to run the tests.
|
202
|
+
Then, run `rake spec` to run the tests.
|
177
203
|
You can run `bin/check` to run linter and the tests together.
|
178
204
|
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
179
205
|
|
206
|
+
You need some app and database ids to run the tests and record the cassettes.
|
207
|
+
In particular you need an app with a postgres database on the free plan and one with a database on a pro plan.
|
208
|
+
|
180
209
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
181
210
|
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
|
182
211
|
which will create a git tag for the version, push git commits and tags,
|
@@ -185,14 +214,7 @@ and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
185
214
|
## Contributing
|
186
215
|
|
187
216
|
Bug reports and pull requests are welcome on GitHub at https://github.com/coorasse/heroku-api-postgres.
|
188
|
-
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to
|
189
|
-
the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
190
217
|
|
191
218
|
## License
|
192
219
|
|
193
220
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
194
|
-
|
195
|
-
## Code of Conduct
|
196
|
-
|
197
|
-
Everyone interacting in the Heroku::Api::Postgres project’s codebases, issue trackers, chat rooms and mailing lists is
|
198
|
-
expected to follow the [code of conduct](https://github.com/coorasse/heroku-api-postgres/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
data/docs/services.md
CHANGED
@@ -3,13 +3,13 @@
|
|
3
3
|
This list contains all postgres commands supported by the official CLI.
|
4
4
|
Source: https://devcenter.heroku.com/articles/heroku-cli-commands
|
5
5
|
|
6
|
-
- [x] pg --> `client.databases.info(database_id)`
|
6
|
+
- [x] pg --> `client.databases.info(app_id, database_id)`
|
7
7
|
|
8
8
|
- [x] pg:backups --> `client.backups.list(app_id)`
|
9
9
|
|
10
10
|
- [ ] pg:backups:cancel
|
11
11
|
|
12
|
-
- [x] pg:backups:capture ---> `client.backups.capture(database_id)`
|
12
|
+
- [x] pg:backups:capture ---> `client.backups.capture(app_id, database_id)`
|
13
13
|
The command returns immediately, without waiting for the capture to be completed.
|
14
14
|
`--wait-interval` not implemented. `--snapshot` not implemented.
|
15
15
|
|
@@ -19,16 +19,16 @@ The command returns immediately, without waiting for the capture to be completed
|
|
19
19
|
|
20
20
|
- [x] pg:backups:info --> `client.backups.info(app_id, backup_id)`
|
21
21
|
|
22
|
-
- [x] pg:backups:restore --> `client.backups.restore(database_id, dump_url)`
|
22
|
+
- [x] pg:backups:restore --> `client.backups.restore(app_id, database_id, dump_url)`
|
23
23
|
The command works only with public URLs. It does not support all the features of the original
|
24
24
|
`heroku pg:backups:restore` command, like restoring directly from another database.
|
25
25
|
The command returns immediately, without waiting for the capture to be completed.
|
26
26
|
You can use the command `client.backups.wait(app_id, restore[:num])` to wait for it to be ready.
|
27
27
|
|
28
|
-
- [x] pg:backups:schedule --> `client.backups.schedule(database_id)`
|
28
|
+
- [x] pg:backups:schedule --> `client.backups.schedule(app_id, database_id)`
|
29
29
|
|
30
30
|
|
31
|
-
- [x] pg:backups:schedules --> `client.backups.schedules(database_id)`
|
31
|
+
- [x] pg:backups:schedules --> `client.backups.schedules(app_id, database_id)`
|
32
32
|
|
33
33
|
- [ ] pg:backups:unschedule
|
34
34
|
|
@@ -46,13 +46,13 @@ You can use the command `client.backups.wait(app_id, restore[:num])` to wait for
|
|
46
46
|
|
47
47
|
- [ ] pg:credentials:repair-default
|
48
48
|
|
49
|
-
- [
|
49
|
+
- [x] pg:credentials:rotate --> `client.credentials.rotate(app_id, database_id)`
|
50
50
|
|
51
51
|
- [ ] pg:credentials:url
|
52
52
|
|
53
53
|
- [ ] pg:diagnose
|
54
54
|
|
55
|
-
- [x] pg:info --> `client.databases.info(database_id)`
|
55
|
+
- [x] pg:info --> `client.databases.info(app_id, database_id)`
|
56
56
|
|
57
57
|
- [ ] pg:kill
|
58
58
|
|
@@ -96,5 +96,5 @@ You can use the command `client.backups.wait(app_id, restore[:num])` to wait for
|
|
96
96
|
|
97
97
|
- [ ] pg:upgrade
|
98
98
|
|
99
|
-
- [x] pg:wait --> `client.wait(database_id)`
|
99
|
+
- [x] pg:wait --> `client.wait(app_id, database_id)`
|
100
100
|
Waits for a database to be ready.
|
data/heroku-api-postgres.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
lib = File.expand_path('lib', __dir__)
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
5
|
require 'heroku/api/postgres/version'
|
@@ -13,19 +15,20 @@ Gem::Specification.new do |spec|
|
|
13
15
|
spec.homepage = 'https://github.com/coorasse/heroku-api-postgres'
|
14
16
|
spec.license = 'MIT'
|
15
17
|
|
16
|
-
spec.
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
19
|
+
spec.metadata['source_code_uri'] = 'https://github.com/coorasse/heroku-api-postgres'
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/coorasse/heroku-api-postgres/blob/main/CHANGELOG.md'
|
21
|
+
spec.metadata['funding_uri'] = 'https://github.com/sponsors/coorasse'
|
22
|
+
|
23
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
24
|
f.match(%r{^(test|spec|features)/})
|
18
25
|
end
|
19
26
|
spec.bindir = 'exe'
|
20
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
28
|
spec.require_paths = ['lib']
|
29
|
+
spec.required_ruby_version = '>= 3.2.0'
|
22
30
|
|
23
31
|
spec.add_dependency 'platform-api'
|
24
|
-
|
25
|
-
spec.
|
26
|
-
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
|
-
spec.add_development_dependency 'rubocop', '0.60.0'
|
29
|
-
spec.add_development_dependency 'vcr', '~> 4.0.0'
|
30
|
-
spec.add_development_dependency 'webmock', '~> 3.3.0'
|
32
|
+
|
33
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
31
34
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'net/http'
|
2
4
|
require 'json'
|
3
5
|
require 'platform-api'
|
@@ -23,21 +25,30 @@ module Heroku
|
|
23
25
|
|
24
26
|
def schedules(app_id, database_id)
|
25
27
|
@client.perform_get_request("/client/v11/databases/#{database_id}/transfer-schedules",
|
26
|
-
host: db_host(app_id))
|
28
|
+
host: db_host(app_id, database_id))
|
27
29
|
end
|
28
30
|
|
29
|
-
def schedule(app_id, database_id)
|
31
|
+
def schedule(app_id, database_id, hour: 0o0, timezone: 'UTC')
|
30
32
|
@client.perform_post_request("/client/v11/databases/#{database_id}/transfer-schedules",
|
31
|
-
{ hour:
|
32
|
-
timezone:
|
33
|
-
schedule_name: 'DATABASE_URL' }, host: db_host(app_id))
|
33
|
+
{ hour: hour,
|
34
|
+
timezone: timezone,
|
35
|
+
schedule_name: 'DATABASE_URL' }, host: db_host(app_id, database_id))
|
34
36
|
end
|
35
37
|
|
36
|
-
def capture(app_id, database_id)
|
37
|
-
@client.perform_post_request("/client/v11/databases/#{database_id}/backups",
|
38
|
+
def capture(app_id, database_id, options = {})
|
39
|
+
@client.perform_post_request("/client/v11/databases/#{database_id}/backups",
|
40
|
+
options,
|
41
|
+
host: db_host(app_id, database_id))
|
38
42
|
end
|
39
43
|
|
40
|
-
def url(app_id, backup_num)
|
44
|
+
def url(app_id, backup_num = nil)
|
45
|
+
unless backup_num
|
46
|
+
transfers = list(app_id)
|
47
|
+
last_transfer =
|
48
|
+
transfers.select { |t| t[:succeeded] && t[:to_type] == 'gof3r' }
|
49
|
+
.max_by { |t| t[:created_at] }
|
50
|
+
backup_num = last_transfer[:num]
|
51
|
+
end
|
41
52
|
@client.perform_post_request("/client/v11/apps/#{app_id}/transfers/#{backup_num}/actions/public-url")
|
42
53
|
end
|
43
54
|
|
@@ -55,24 +66,13 @@ module Heroku
|
|
55
66
|
|
56
67
|
def restore(app_id, database_id, backup_url)
|
57
68
|
@client.perform_post_request("/client/v11/databases/#{database_id}/restores",
|
58
|
-
{ backup_url: backup_url }, host: db_host(app_id))
|
69
|
+
{ backup_url: backup_url }, host: db_host(app_id, database_id))
|
59
70
|
end
|
60
71
|
|
61
72
|
private
|
62
73
|
|
63
|
-
def
|
64
|
-
@
|
65
|
-
end
|
66
|
-
|
67
|
-
def db_host(app_id)
|
68
|
-
database = heroku_client.addon.list_by_app(app_id).find do |addon|
|
69
|
-
addon['addon_service']['name'] == 'heroku-postgresql'
|
70
|
-
end
|
71
|
-
databases.host_for(database)
|
72
|
-
end
|
73
|
-
|
74
|
-
def heroku_client
|
75
|
-
@heroku_client ||= PlatformAPI.connect_oauth(@client.oauth_client_key)
|
74
|
+
def db_host(app_id, database_id)
|
75
|
+
@client.db_host(app_id, database_id)
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
@@ -1,16 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Heroku
|
2
4
|
module Api
|
3
5
|
module Postgres
|
4
|
-
def self.
|
5
|
-
Client.new
|
6
|
+
def self.connect(api_key = ENV.fetch('HEROKU_API_KEY', nil))
|
7
|
+
Client.new.tap do |c|
|
8
|
+
c.api_key = api_key
|
9
|
+
c.heroku_client = PlatformAPI.connect(api_key)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.connect_oauth(oauth_client_key = ENV.fetch('HEROKU_OAUTH_TOKEN', nil))
|
14
|
+
Client.new.tap do |c|
|
15
|
+
c.oauth_client_key = oauth_client_key
|
16
|
+
c.heroku_client = PlatformAPI.connect_oauth(oauth_client_key)
|
17
|
+
end
|
6
18
|
end
|
7
19
|
|
8
20
|
class Client
|
9
|
-
|
21
|
+
STARTER_HOST = 'https://postgres-starter-api.heroku.com'
|
22
|
+
PRO_HOST = 'https://postgres-api.heroku.com'
|
23
|
+
|
24
|
+
attr_accessor :api_key, :oauth_client_key, :heroku_client
|
10
25
|
|
11
|
-
def initialize
|
12
|
-
@
|
13
|
-
@basic_url = Databases::STARTER_HOST
|
26
|
+
def initialize
|
27
|
+
@basic_url = STARTER_HOST
|
14
28
|
end
|
15
29
|
|
16
30
|
def backups
|
@@ -21,8 +35,23 @@ module Heroku
|
|
21
35
|
@databases ||= Databases.new(self)
|
22
36
|
end
|
23
37
|
|
38
|
+
def credentials
|
39
|
+
@credentials ||= Credentials.new(self)
|
40
|
+
end
|
41
|
+
|
42
|
+
# the database id matches the field `id` in pro plans and the field addon_service.id in free plans
|
43
|
+
def db_host(app_id, database_id)
|
44
|
+
all_addons = heroku_client.addon.list_by_app(app_id)
|
45
|
+
database_json = all_addons.find do |addon|
|
46
|
+
[addon['id'], addon['addon_service']['id']].include?(database_id)
|
47
|
+
end
|
48
|
+
return STARTER_HOST if database_json.nil?
|
49
|
+
|
50
|
+
host_for(database_json)
|
51
|
+
end
|
52
|
+
|
24
53
|
def perform_get_request(path, options = {})
|
25
|
-
url = build_uri(path, options)
|
54
|
+
url = build_uri(path, **options)
|
26
55
|
req = Net::HTTP::Get.new(url)
|
27
56
|
add_auth_headers(req)
|
28
57
|
response = start_request(req, url)
|
@@ -30,7 +59,7 @@ module Heroku
|
|
30
59
|
end
|
31
60
|
|
32
61
|
def perform_post_request(path, params = {}, options = {})
|
33
|
-
url = build_uri(path, options)
|
62
|
+
url = build_uri(path, **options)
|
34
63
|
req = Net::HTTP::Post.new(url)
|
35
64
|
add_auth_headers(req)
|
36
65
|
req.body = params.to_json
|
@@ -40,6 +69,14 @@ module Heroku
|
|
40
69
|
|
41
70
|
private
|
42
71
|
|
72
|
+
def host_for(database_json)
|
73
|
+
starter_plan?(database_json) ? STARTER_HOST : PRO_HOST
|
74
|
+
end
|
75
|
+
|
76
|
+
def starter_plan?(database)
|
77
|
+
database['plan']['name'].match(/(dev|basic)$/)
|
78
|
+
end
|
79
|
+
|
43
80
|
def build_uri(path, host: @basic_url)
|
44
81
|
URI.join(host, path)
|
45
82
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'json'
|
5
|
+
require 'platform-api'
|
6
|
+
|
7
|
+
module Heroku
|
8
|
+
module Api
|
9
|
+
module Postgres
|
10
|
+
class Credentials
|
11
|
+
def initialize(client)
|
12
|
+
@client = client
|
13
|
+
end
|
14
|
+
|
15
|
+
# Public: Rotate the database credentials.
|
16
|
+
#
|
17
|
+
# @param app_id [String] the application name.
|
18
|
+
# @param database_id [String] the database UUID.
|
19
|
+
# @param name [String] the credential name to be rotated (default: `default`).
|
20
|
+
def rotate(app_id, database_id, name: 'default')
|
21
|
+
path = "/postgres/v0/databases/#{database_id}/credentials" \
|
22
|
+
"/#{URI.encode_www_form_component(name)}/credentials_rotation"
|
23
|
+
@client.perform_post_request(path, {}, host: db_host(app_id, database_id))
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def db_host(app_id, database_id)
|
29
|
+
@client.db_host(app_id, database_id)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'net/http'
|
2
4
|
require 'json'
|
3
5
|
|
@@ -5,19 +7,16 @@ module Heroku
|
|
5
7
|
module Api
|
6
8
|
module Postgres
|
7
9
|
class Databases
|
8
|
-
STARTER_HOST = 'https://postgres-starter-api.heroku.com'.freeze
|
9
|
-
PRO_HOST = 'https://postgres-api.heroku.com'.freeze
|
10
|
-
|
11
10
|
def initialize(client)
|
12
11
|
@client = client
|
13
12
|
end
|
14
13
|
|
15
14
|
# original call returns simply a database object, therefore I call the info API.
|
16
15
|
# perform_get_request "/client/v11/databases/#{database_id}/wait_status"
|
17
|
-
def wait(database_id, options = { wait_interval: 3 })
|
16
|
+
def wait(app_id, database_id, options = { wait_interval: 3 })
|
18
17
|
waiting = true
|
19
18
|
while waiting
|
20
|
-
database = info(database_id)
|
19
|
+
database = info(app_id, database_id)
|
21
20
|
break unless database[:waiting?]
|
22
21
|
|
23
22
|
sleep(options[:wait_interval])
|
@@ -25,16 +24,14 @@ module Heroku
|
|
25
24
|
database
|
26
25
|
end
|
27
26
|
|
28
|
-
def info(database_id)
|
29
|
-
@client.perform_get_request("/client/v11/databases/#{database_id}")
|
27
|
+
def info(app_id, database_id)
|
28
|
+
@client.perform_get_request("/client/v11/databases/#{database_id}", host: db_host(app_id, database_id))
|
30
29
|
end
|
31
30
|
|
32
|
-
|
33
|
-
starter_plan?(database) ? STARTER_HOST : PRO_HOST
|
34
|
-
end
|
31
|
+
private
|
35
32
|
|
36
|
-
def
|
37
|
-
|
33
|
+
def db_host(app_id, database_id)
|
34
|
+
@client.db_host(app_id, database_id)
|
38
35
|
end
|
39
36
|
end
|
40
37
|
end
|
data/lib/heroku/api/postgres.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heroku-api-postgres
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Rodi
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: platform-api
|
@@ -24,104 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bundler
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '1.17'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '1.17'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: dotenv
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rake
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '10.0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '10.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rspec
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '3.0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '3.0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rubocop
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - '='
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: 0.60.0
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - '='
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: 0.60.0
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: vcr
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: 4.0.0
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: 4.0.0
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: webmock
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 3.3.0
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: 3.3.0
|
125
27
|
description: Ruby library to invoke Heroku Postgres APIs
|
126
28
|
email:
|
127
29
|
- coorasse@gmail.com
|
@@ -130,14 +32,14 @@ extensions: []
|
|
130
32
|
extra_rdoc_files: []
|
131
33
|
files:
|
132
34
|
- ".example.env"
|
35
|
+
- ".github/FUNDING.yml"
|
36
|
+
- ".github/workflows/ci.yml"
|
133
37
|
- ".gitignore"
|
134
38
|
- ".rspec"
|
135
39
|
- ".rubocop.yml"
|
136
|
-
- ".
|
137
|
-
-
|
40
|
+
- ".ruby-version"
|
41
|
+
- CHANGELOG.md
|
138
42
|
- Gemfile
|
139
|
-
- Gemfile.lock
|
140
|
-
- LICENSE.txt
|
141
43
|
- README.md
|
142
44
|
- Rakefile
|
143
45
|
- bin/check
|
@@ -149,13 +51,19 @@ files:
|
|
149
51
|
- lib/heroku/api/postgres.rb
|
150
52
|
- lib/heroku/api/postgres/backups.rb
|
151
53
|
- lib/heroku/api/postgres/client.rb
|
54
|
+
- lib/heroku/api/postgres/credentials.rb
|
152
55
|
- lib/heroku/api/postgres/databases.rb
|
153
56
|
- lib/heroku/api/postgres/version.rb
|
154
57
|
homepage: https://github.com/coorasse/heroku-api-postgres
|
155
58
|
licenses:
|
156
59
|
- MIT
|
157
|
-
metadata:
|
158
|
-
|
60
|
+
metadata:
|
61
|
+
homepage_uri: https://github.com/coorasse/heroku-api-postgres
|
62
|
+
source_code_uri: https://github.com/coorasse/heroku-api-postgres
|
63
|
+
changelog_uri: https://github.com/coorasse/heroku-api-postgres/blob/main/CHANGELOG.md
|
64
|
+
funding_uri: https://github.com/sponsors/coorasse
|
65
|
+
rubygems_mfa_required: 'true'
|
66
|
+
post_install_message:
|
159
67
|
rdoc_options: []
|
160
68
|
require_paths:
|
161
69
|
- lib
|
@@ -163,16 +71,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
163
71
|
requirements:
|
164
72
|
- - ">="
|
165
73
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
74
|
+
version: 3.2.0
|
167
75
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
76
|
requirements:
|
169
77
|
- - ">="
|
170
78
|
- !ruby/object:Gem::Version
|
171
79
|
version: '0'
|
172
80
|
requirements: []
|
173
|
-
|
174
|
-
|
175
|
-
signing_key:
|
81
|
+
rubygems_version: 3.4.19
|
82
|
+
signing_key:
|
176
83
|
specification_version: 4
|
177
84
|
summary: Ruby library to invoke Heroku Postgres APIs
|
178
85
|
test_files: []
|
data/.travis.yml
DELETED
data/CODE_OF_CONDUCT.md
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
# Contributor Covenant Code of Conduct
|
2
|
-
|
3
|
-
## Our Pledge
|
4
|
-
|
5
|
-
In the interest of fostering an open and welcoming environment, we as
|
6
|
-
contributors and maintainers pledge to making participation in our project and
|
7
|
-
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
-
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
-
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
-
orientation.
|
11
|
-
|
12
|
-
## Our Standards
|
13
|
-
|
14
|
-
Examples of behavior that contributes to creating a positive environment
|
15
|
-
include:
|
16
|
-
|
17
|
-
* Using welcoming and inclusive language
|
18
|
-
* Being respectful of differing viewpoints and experiences
|
19
|
-
* Gracefully accepting constructive criticism
|
20
|
-
* Focusing on what is best for the community
|
21
|
-
* Showing empathy towards other community members
|
22
|
-
|
23
|
-
Examples of unacceptable behavior by participants include:
|
24
|
-
|
25
|
-
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
-
advances
|
27
|
-
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
-
* Public or private harassment
|
29
|
-
* Publishing others' private information, such as a physical or electronic
|
30
|
-
address, without explicit permission
|
31
|
-
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
-
professional setting
|
33
|
-
|
34
|
-
## Our Responsibilities
|
35
|
-
|
36
|
-
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
-
behavior and are expected to take appropriate and fair corrective action in
|
38
|
-
response to any instances of unacceptable behavior.
|
39
|
-
|
40
|
-
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
-
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
-
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
-
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
-
threatening, offensive, or harmful.
|
45
|
-
|
46
|
-
## Scope
|
47
|
-
|
48
|
-
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
-
when an individual is representing the project or its community. Examples of
|
50
|
-
representing a project or community include using an official project e-mail
|
51
|
-
address, posting via an official social media account, or acting as an appointed
|
52
|
-
representative at an online or offline event. Representation of a project may be
|
53
|
-
further defined and clarified by project maintainers.
|
54
|
-
|
55
|
-
## Enforcement
|
56
|
-
|
57
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
-
reported by contacting the project team at alessandro.rodi@renuo.ch. All
|
59
|
-
complaints will be reviewed and investigated and will result in a response that
|
60
|
-
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
-
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
-
Further details of specific enforcement policies may be posted separately.
|
63
|
-
|
64
|
-
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
-
faith may face temporary or permanent repercussions as determined by other
|
66
|
-
members of the project's leadership.
|
67
|
-
|
68
|
-
## Attribution
|
69
|
-
|
70
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
-
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
-
|
73
|
-
[homepage]: http://contributor-covenant.org
|
74
|
-
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile.lock
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
heroku-api-postgres (0.10.0)
|
5
|
-
platform-api
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
addressable (2.5.2)
|
11
|
-
public_suffix (>= 2.0.2, < 4.0)
|
12
|
-
ast (2.4.0)
|
13
|
-
crack (0.4.3)
|
14
|
-
safe_yaml (~> 1.0.0)
|
15
|
-
diff-lcs (1.3)
|
16
|
-
dotenv (2.5.0)
|
17
|
-
erubis (2.7.0)
|
18
|
-
excon (0.62.0)
|
19
|
-
hashdiff (0.3.7)
|
20
|
-
heroics (0.0.25)
|
21
|
-
erubis (~> 2.0)
|
22
|
-
excon
|
23
|
-
moneta
|
24
|
-
multi_json (>= 1.9.2)
|
25
|
-
jaro_winkler (1.5.1)
|
26
|
-
moneta (1.0.0)
|
27
|
-
multi_json (1.13.1)
|
28
|
-
parallel (1.12.1)
|
29
|
-
parser (2.5.3.0)
|
30
|
-
ast (~> 2.4.0)
|
31
|
-
platform-api (2.2.0)
|
32
|
-
heroics (~> 0.0.25)
|
33
|
-
moneta (~> 1.0.0)
|
34
|
-
powerpack (0.1.2)
|
35
|
-
public_suffix (3.0.3)
|
36
|
-
rainbow (3.0.0)
|
37
|
-
rake (10.5.0)
|
38
|
-
rspec (3.8.0)
|
39
|
-
rspec-core (~> 3.8.0)
|
40
|
-
rspec-expectations (~> 3.8.0)
|
41
|
-
rspec-mocks (~> 3.8.0)
|
42
|
-
rspec-core (3.8.0)
|
43
|
-
rspec-support (~> 3.8.0)
|
44
|
-
rspec-expectations (3.8.2)
|
45
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
46
|
-
rspec-support (~> 3.8.0)
|
47
|
-
rspec-mocks (3.8.0)
|
48
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
49
|
-
rspec-support (~> 3.8.0)
|
50
|
-
rspec-support (3.8.0)
|
51
|
-
rubocop (0.60.0)
|
52
|
-
jaro_winkler (~> 1.5.1)
|
53
|
-
parallel (~> 1.10)
|
54
|
-
parser (>= 2.5, != 2.5.1.1)
|
55
|
-
powerpack (~> 0.1)
|
56
|
-
rainbow (>= 2.2.2, < 4.0)
|
57
|
-
ruby-progressbar (~> 1.7)
|
58
|
-
unicode-display_width (~> 1.4.0)
|
59
|
-
ruby-progressbar (1.10.0)
|
60
|
-
safe_yaml (1.0.4)
|
61
|
-
unicode-display_width (1.4.0)
|
62
|
-
vcr (4.0.0)
|
63
|
-
webmock (3.3.0)
|
64
|
-
addressable (>= 2.3.6)
|
65
|
-
crack (>= 0.3.2)
|
66
|
-
hashdiff
|
67
|
-
|
68
|
-
PLATFORMS
|
69
|
-
ruby
|
70
|
-
|
71
|
-
DEPENDENCIES
|
72
|
-
bundler (~> 1.17)
|
73
|
-
dotenv
|
74
|
-
heroku-api-postgres!
|
75
|
-
rake (~> 10.0)
|
76
|
-
rspec (~> 3.0)
|
77
|
-
rubocop (= 0.60.0)
|
78
|
-
vcr (~> 4.0.0)
|
79
|
-
webmock (~> 3.3.0)
|
80
|
-
|
81
|
-
BUNDLED WITH
|
82
|
-
1.17.1
|
data/LICENSE.txt
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2018 Alessandro Rodi
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|