Skip to content

Commit 045cebf

Browse files
authored
CCAP-295: Updated how database credentials are read. (#8)
* Updated onedrive destination documentation to note potential issues with omitting the filename parameter. * Updated database documentation.
1 parent 8f01253 commit 045cebf

File tree

15 files changed

+146
-25
lines changed

15 files changed

+146
-25
lines changed

.pryrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ require_relative 'lib/config/application'
66
require_relative 'lib/model'
77

88
config = DocumentTransfer::Config::Application.from_environment
9-
Sequel.connect(config.database_url)
9+
Sequel.connect(config.database_credentials)
1010

1111
DocumentTransfer::Model.load
1212

1313
color = "\e[1;32m"
1414
color = "\e[1;31m" if config.prod?
1515
color = "\e[1;33m" if config.prod_like?
1616

17-
Pry.config.prompt_name = "document_transfer(#{config.environment})"
17+
Pry.config.prompt_name = "document-transfer(#{config.environment})"
1818
Pry.config.prompt = Pry::Prompt.new(
1919
:document_transfer,
2020
'Document transfer console prompt',

CODEOWNER renamed to CODEOWNERS

File renamed without changes.

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,9 @@ recommend using a virtual environment manager such as [RVM] to manage your Ruby
7373
installations. The required version of Ruby is defined in the
7474
[`.ruby-version`][ruby-version] file.
7575

76-
You will also need a database for the service to store data. The service is
77-
designed to work with a PostgreSQL database. You can configure the database
78-
using the `DATABASE_URL` environment variable. The `sample.env` file assumes
79-
you can connect to a database at `localhost:5432`. You can update this in your
80-
`.env` file.
76+
You will also need a database for the service to store data. Please review the
77+
[database documentation][database] for more information on how to configure the
78+
service to connect to your database before proceeding.
8179

8280
With ruby installed and the database configured, install gem dependencies and
8381
set up the database with the following:
@@ -129,6 +127,7 @@ service.
129127
[.env]: ./sample.env
130128
[api]: ./doc/api.md
131129
[create-key]: ./doc/runbooks/create_auth_key.md
130+
[database]: ./doc/database.md
132131
[destination]: ./doc/destinations.md
133132
[Dockerfile]: ./Dockerfile
134133
[docker compose]: ./docker-compose.yaml

config.ru

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ require_relative 'lib/model'
1616

1717
# Connect to the database.
1818
config = DocumentTransfer::Config::Application.from_environment
19-
Sequel.connect(config.database_url)
19+
Sequel.connect(config.database_credentials)
2020

2121
# Load all models.
2222
DocumentTransfer::Model.load

doc/database.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Database
2+
3+
The Document Transfer service is designed to work with a PostgreSQL database.
4+
5+
## Configuration
6+
7+
You can configure the database using the environment variables below. The
8+
`sample.env` file assumes that you can connect to a database at
9+
`localhost:5432`. You can update this in your `.env` file.
10+
11+
| Name | Description | Default | Required |
12+
|---------------------|-------------------------------------------------------------------------------|---------------------|----------|
13+
| `BASE_DATABASE` | The base database to use when the expected database has not yet been created. | `postgres` | no |
14+
| `DATABASE_ADAPTER` | The adapter to use for the database connection. | `postgresql` | no |
15+
| `DATABASE_HOST` | The host of the database server. | `localhost` | no |
16+
| `DATABASE_NAME` | The name of the database to connect to. | `document_transfer` | no |
17+
| `DATABASE_PASSWORD` | The password for the database user. | `""` | no |
18+
| `DATABASE_PORT` | The port of the database server. | `5432` | no |
19+
| `DATABASE_USER` | The user to connect to the database as. | `postgres` | no |
20+
21+
Note that while the adapted can be changed, the service is designed to work with
22+
PostgreSQL, and therefore only bundles the `pg` gem by default in production.
23+
`sqlite3` is included in test environments for testing purposes, and is not
24+
supported for production use.
25+
26+
## Creating, updating, and dropping the database
27+
28+
Once you have the database configured, you can use the included [rake] commands
29+
to manage the database.
30+
31+
To create the database, run the following command. If the database exists, this
32+
command will still exit 0 without making any changes, making it safe to run
33+
repeatedly.
34+
35+
```bash
36+
bundle exec rake db:create
37+
```
38+
39+
To update the schema by running [migrations]:
40+
41+
```bash
42+
bundle exec rake db:migrate
43+
```
44+
45+
You can also run these steps together:
46+
47+
```bash
48+
bundle exec rake db:setup
49+
```
50+
51+
You can restore the database to its initial state with the command below. This
52+
will drop all existing tables and recreate the schema.
53+
54+
```bash
55+
bundle exec rake db:reset
56+
````
57+
58+
Finally, you can drop the entire database with:
59+
60+
```bash
61+
bundle exec rake db:drop
62+
```
63+
64+
Note that both `db:reset` and `db:drop` will refuse to run in production.
65+
66+
## Schema and migrations
67+
68+
The service uses the [sequel] gem to manage the database schema via
69+
[migrations][sequel-migrations]. These migrations are stored in the
70+
[`db/migrate`][migrate] directory and are prefixed with a timestamp to ensure
71+
they run in proper order and avoid collisions.
72+
73+
Migrations can be run using the following command:
74+
75+
```bash
76+
bundle exec rake db:migrate
77+
```
78+
79+
You can migrate to a specific version (up or down) by passing the version
80+
number:
81+
82+
```bash
83+
bundle exec rake db:migrate\[202407082156]
84+
```
85+
86+
[migrate]: ./db/migrate
87+
[migrations]: #schema-and-migrations
88+
[rake]: https://ruby.github.io/rake/
89+
[sequel]: https://sequel.jeremyevans.net/
90+
[sequel-migrations]: https://sequel.jeremyevans.net/rdoc/files/doc/migration_rdoc.html

doc/destinations.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ The following environment variables must be set on the service:
4040
| filename | The path in the drive to upload the file to. | `string` | `source.filename` | NO |
4141
| path | The path in the drive to upload the file to. | `string` | `""` | NO |
4242

43+
If the `filename` parameter is not provided, the service will use the filename
44+
from the source. If the source URL does not contain a filename, such as when
45+
using an S3 presigned url, this may result in your transfer failing.
46+
4347
### Example request
4448

4549
```json

docker-compose.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ services:
44
depends_on:
55
db:
66
condition: service_healthy
7+
restart: always
78
environment:
89
ONEDRIVE_CLIENT_ID: ${ONEDRIVE_CLIENT_ID}
910
ONEDRIVE_CLIENT_SECRET: ${ONEDRIVE_CLIENT_SECRET}
1011
ONEDRIVE_DRIVE_ID: ${ONEDRIVE_DRIVE_ID}
1112
ONEDRIVE_TENANT_ID: ${ONEDRIVE_TENANT_ID}
12-
DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@db/${POSTGRES_DB:-document_transfer}
13+
DATABASE_USER: ${DATABASE_USER:-postgres}
14+
DATABASE_PASSWORD: ${DATABASE_PASSWORD:-postgres}
15+
DATABASE_HOST: db
16+
DATABASE_NAME: ${POSTGRES_DB:-document_transfer}
1317
volumes:
1418
- .:/opt/app
1519
ports:

lib/config/application.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,26 @@ module Config
77
# Configuration for the document transfer application.
88
class Application < Base
99
option :base_database, type: String, default: 'postgres'
10-
option :database_url, type: String, required: true
10+
option :database_adapter, type: String, default: 'postgresql'
11+
option :database_host, type: String, default: 'localhost'
12+
option :database_name, type: String, default: 'document_transfer'
13+
option :database_password, type: String, default: ''
14+
option :database_port, type: Integer, default: 5432
15+
option :database_user, type: String, default: 'postgres'
1116
option :environment, type: String, default: 'development',
1217
env_variable: 'RACK_ENV'
1318

19+
def database_credentials
20+
{
21+
adapter: database_adapter,
22+
database: database_name,
23+
host: database_host,
24+
password: database_password,
25+
port: database_port,
26+
user: database_user
27+
}
28+
end
29+
1430
def prod?
1531
%w[production prod].include?(environment)
1632
end

lib/config/dsl.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ def respond_to_missing?(name, include_private = false)
2626
def format_value(option, value)
2727
return value if value.is_a?(options[option][:type])
2828

29-
case options[option][:type].name
30-
when 'Symbol' then value.to_sym
31-
when 'String' then value.to_s
29+
case options[option][:type].name.to_sym
30+
when :Integer then value.to_i
31+
when :Symbol then value.to_sym
32+
when :String then value.to_s
3233
else value
3334
end
3435
end

lib/destination/one_drive.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ module Destination
88
# Microsoft OneDrive destination.
99
class OneDrive < Base
1010
def transfer(source)
11-
result = service.upload(source, path: @config.path, filename: @config.filename)
11+
service.upload(source, path: @config.path, filename: @config.filename)
1212

13-
{ path: File.join(@config.path, result.name) }
13+
{ path: File.join(@config.path, @config.filename) }
1414
rescue Microsoft::Graph::Error => e
1515
raise DestinationError, "Failed to upload to OneDrive: #{e.message}"
1616
end

lib/rake/database/base.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,14 @@ class Base < Rake::Base
1515
#
1616
# @return [String]
1717
def db_name
18-
url = URI.parse(config.database_url)
19-
url.path[1..] || ''
18+
config.database_name
2019
end
2120

2221
# Connect to the database for the duration of the provided block.
2322
#
2423
# @yieldparam [Sequel::Database]
2524
def db_connection(&)
26-
Sequel.connect(config.database_url, &)
25+
Sequel.connect(config.database_credentials, &)
2726
end
2827

2928
# Connect to the base database for the duration of the provided block.
@@ -32,9 +31,10 @@ def db_connection(&)
3231
#
3332
# @yieldparam [Sequel::Database]
3433
def base_db_connection(&)
35-
url = URI.parse(config.database_url)
36-
url.path = "/#{config.base_database}"
37-
Sequel.connect(url.to_s, &)
34+
Sequel.connect(
35+
config.database_credentials.merge(database: config.base_database),
36+
&
37+
)
3838
end
3939
end
4040
end

lib/rake/database/migrate.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def define(args, &task_block)
2020
version = task_args.to_a.first if task_args
2121
db_connection do |db|
2222
yield(*[self, :pre, task_args].slice(0, task_block.arity)) if task_block
23-
Sequel::Migrator.run(db, 'db/migrations', target: version)
23+
Sequel::Migrator.run(db, 'db/migrations', target: version&.to_i)
2424
yield(*[self, :post, task_args].slice(0, task_block.arity)) if task_block
2525
end
2626
end

lib/rake/database/reset.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ def initialize(name = :reset, *args, &)
1616
def define(args, &task_block)
1717
desc 'Reset the database'
1818
task(name, *args) do |_, _task_args|
19+
raise EnvironmentError, 'Cannot drop the production database' if config.prod?
20+
1921
::Rake::Task['db:drop'].invoke(task_block)
2022
::Rake::Task['db:setup'].invoke(task_block)
2123
end

sample.env

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ export COVERAGE=1
22
export RACK_ENV=development
33

44
# Update to match your local database configuration, if necessary.
5-
export DATABASE_URL="postgresql://localhost:5432/document_transfer"
5+
export DATABASE_USER=""
6+
export DATABASE_PASSWORD=""
7+
export DATABASE_HOST="localhost"
8+
export DATABASE_PORT="5432"
9+
export DATABASE_NAME="document_transfer"
610

711
# Uncomment and set to the name of your AWS profile to use the aws cli.
812
#export AWS_PROFILE=

spec/spec_helper.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919
end
2020

2121
# Connect to a test database and run migrations.
22-
ENV['DATABASE_URL'] = 'sqlite://memory'
22+
ENV['DATABASE_ADAPTER'] = 'sqlite'
23+
ENV['DATABASE_NAME'] = ':memory:'
2324
ENV['BASE_DATABASE'] = ''
2425
Sequel.extension :migration
25-
db = Sequel.connect(ENV.fetch('DATABASE_URL'))
26+
db = Sequel.connect('sqlite::memory:')
2627
Sequel::Migrator.run(db, 'db')
2728

2829
# We need to build a Rack app for testing. This ensures that we're including the

0 commit comments

Comments
 (0)