Skip to content

Commit

Permalink
[CLI] Moves DB settings to config/environments
Browse files Browse the repository at this point in the history
Currently database settings reside in the config/database.yml this is
redundant since Amber has settings per environment.

This PR removes the `config/database.yml` and uses the environment yamls
files to load the database settings.

There is a couple of benefits for doing this:
1. Database settings are loaded per environment.
2. It is more intuitive to know where to put DB settings.

[ENV LOADER] Add database settings to environment_loader

- Adds database property to Amber::Settings
- Adds database property to spec test.yml
- Load database settings from environment yml
- Updates settings specs to check for database settings
- Updates environment loader specs to check for database settings

[CLI] Updates init spec file

- Updates amber spec file to check for database key
- Tidy init_spec connection string validation
- Add `expected_db_url(db_key, env)` method to cleanup specs
  • Loading branch information
Elias J. Perez authored and eliasjpr committed Nov 18, 2017
1 parent ecac84f commit f3f15bd
Show file tree
Hide file tree
Showing 15 changed files with 119 additions and 125 deletions.
2 changes: 1 addition & 1 deletion spec/amber/amber_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ describe Amber do
expected_session = {:key => "amber.session", :store => :signed_cookie, :expires => 0}
settings.session.should eq expected_session
settings.port.should_not eq 3000
settings.database.should eq "mysql://root@localhost:3306/amber_test_app_test"
expected_secrets = {
description: "Store your test secrets credentials and settings here.",
database: "mysql://root@localhost:3306/amber_test_app_test",
}
settings.secrets.should eq expected_secrets
settings.secret_key_base.should eq "mV6kTmG3k1yVFh-fPYpugSn0wbZveDvrvfQuv88DPF8"
Expand Down
2 changes: 1 addition & 1 deletion spec/amber/cli/build_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module Amber::CLI

prepare_yaml(Dir.current)

prepare_db_yml if ENV["CI"]? == "true"
prepare_db_yml(CLIHelper::BASE_ENV_PATH) if ENV["CI"]? == "true"

puts "====== START Creating database for #{TEST_APP_NAME} ======"
MainCommand.run ["db", "drop"]
Expand Down
48 changes: 35 additions & 13 deletions spec/amber/cli/commands/database_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,47 @@ include CLIFixtures
module Amber::CLI
describe "database" do
describe "sqlite" do
env = ENV["AMBER_ENV"]
cleanup
scaffold_app(TESTING_APP, "-d", "sqlite")
db_filename = db_yml("./")["sqlite"]["database"].to_s.sub("sqlite3:", "")

it "does not create the database when `db create`" do
MainCommand.run ["db", "create"]
File.exists?(db_filename).should be_false
end
context env do
env_yml = environment_yml(env, path: CLIHelper::BASE_ENV_PATH)
db_filename = env_yml["database"].to_s.gsub("sqlite3:", "")

it "has connection settings in config/environments/env.yml" do
env_yml["database"].should eq expected_db_url("sqlite3", env)
end

it "does not create the database when `db create`" do
MainCommand.run ["db", "create"]
File.exists?(db_filename).should be_false
end

it "does create the database when `db migrate`" do
MainCommand.run ["generate", "model", "Post"]
MainCommand.run ["db", "migrate"]
p db_filename
File.exists?(db_filename).should be_true
File.stat(db_filename).size.should_not eq 0
end

it "does create the database when `db migrate`" do
MainCommand.run ["generate", "model", "Post"]
MainCommand.run ["db", "migrate"]
File.exists?(db_filename).should be_true
File.stat(db_filename).size.should_not eq 0
it "deletes the database when `db drop`" do
MainCommand.run ["db", "drop"]
File.exists?(db_filename).should be_false
end
end
end

describe "postgres" do
cleanup
scaffold_app(TESTING_APP, "-d", "pg")
env = ENV["AMBER_ENV"]

it "deletes the database when `db drop`" do
MainCommand.run ["db", "drop"]
File.exists?(db_filename).should be_false
context "when #{env} environment" do
it "has #{env} environment connection settings" do
environment_yml(env, path: CLIHelper::BASE_ENV_PATH)["database"].should eq expected_db_url("pg", env)
end
end
end
end
Expand Down
47 changes: 11 additions & 36 deletions spec/amber/cli/commands/init_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -68,43 +68,18 @@ module Amber::CLI
cleanup
MainCommand.run ["new", TESTING_APP, "-d", db]

describe "database.yml config for #{db}" do
db_key = db == "sqlite" ? "sqlite3" : db
db_url = db_yml[db]["database"].as_s
db_name = db_name(db_url)

it "adds #{db} section" do
db_yml[db].should_not be_nil
end

it "sets #{db} shards dependencies" do
shard_yml["dependencies"][db_key].should_not be_nil
end

it "has a database url" do
db_url.should_not be_nil
db_url.should_not eq ""
end

it "has correct db name" do
db_name.should_not contain "-"
db_name.should contain "development"
end

context "when environment" do
%w(development test).each do |env|
context "is #{env.upcase}" do
env_db_url = environment_yml(env)["secrets"]["database"].as_s
env_db_name = db_name(env_db_url)

it "has a database url" do
env_db_url.should contain env
end
describe "#{db}" do
%w(development test).each do |env|
db_key = db == "sqlite" ? "sqlite3" : db
db_url = environment_yml(env)["database"].as_s

context "is #{env.upcase}" do
it "sets #{db} shards dependencies" do
shard_yml["dependencies"][db_key].should_not be_nil
end

it "hass correct name" do
env_db_name.should contain env
env_db_name.should_not contain "-"
end
it "has correct database connection string" do
db_url.should eq expected_db_url(db_key, env)
end
end
end
Expand Down
6 changes: 4 additions & 2 deletions spec/amber/scripts/environment_loader_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ describe Amber::Server do
@log = ::Logger.new(STDOUT).tap{|l| l.level = ::Logger::INFO}
@color = true
@redis_url = "\#{ENV[%(REDIS_URL)]? || %(redis://localhost:6379)}"
@database = "mysql://root@localhost:3306/amber_test_app_test"
@port = (ENV["PORT"] ||= "3000").to_i
@host = "0.0.0.0"
@secret_key_base = "mV6kTmG3k1yVFh-fPYpugSn0wbZveDvrvfQuv88DPF8"
@session = {
:key => "amber.session",
:store => :signed_cookie,
:expires => 0,
:expires => 0,
}
getter secrets = {"description": "Store your test secrets credentials and settings here.", "database": "mysql://root@localhost:3306/amber_test_app_test"}
getter secrets = {"description": "Store your test secrets credentials and settings here."}
EXP
{{run("../../../src/amber/scripts/environment_loader.cr", "test").stringify}}.should eq expected
Expand All @@ -32,6 +33,7 @@ describe Amber::Server do
@log = ::Logger.new(STDOUT).tap{|l| l.level = ::Logger::INFO}
@color = true
@redis_url = "redis://localhost:6379"
@database = ""
@port = 3000
@host = "127.0.0.1"
@session = {:key => "amber.session", :store => :signed_cookie, :expires => 0}
Expand Down
2 changes: 1 addition & 1 deletion spec/amber/server/settings_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ describe Amber::Settings do
settings.name.should eq "amber_test_app"
settings.port_reuse.should eq true
settings.redis_url.should eq "#{ENV["REDIS_URL"]? || "redis://localhost:6379"}"
settings.database = ""
settings.port.should eq 3000
settings.color.should eq true
settings.secret_key_base.should eq "mV6kTmG3k1yVFh-fPYpugSn0wbZveDvrvfQuv88DPF8"
expected_session = {:key => "amber.session", :store => :signed_cookie, :expires => 0}
settings.session.should eq expected_session
expected_secrets = {
description: "Store your test secrets credentials and settings here.",
database: "mysql://root@localhost:3306/amber_test_app_test",
}
settings.secrets.should eq expected_secrets
end
Expand Down
4 changes: 2 additions & 2 deletions spec/support/config/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ host: 0.0.0.0
ssl_key_file:
ssl_cert_file:
redis_url: "#{ENV[%(REDIS_URL)]? || %(redis://localhost:6379)}"
database: mysql://root@localhost:3306/amber_test_app_test
session:
key: "amber.session"
store: :signed_cookie
expires: 0
secrets:
description: Store your test secrets credentials and settings here.
database: mysql://root@localhost:3306/amber_test_app_test
description: Store your test secrets credentials and settings here.
33 changes: 24 additions & 9 deletions spec/support/helpers/cli_helper.cr
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
module CLIHelper
BASE_ENV_PATH = "./config/environments/"
ENV_CONFIG_PATH = "#{TESTING_APP}/config/environments/"
CURRENT_ENVIRONMENT = ENV["AMBER_ENV"] ||= "test"
ENVIRONMENTS = %w(development test)

def cleanup
puts "cleaning up..."
Dir.cd CURRENT_DIR
`rm -rf #{TESTING_APP}`
`rm -rf ./tmp/`
end

def dirs(for app)
gen_dirs = Dir.glob("#{app}/**/*").select { |e| Dir.exists? e }
gen_dirs.map { |dir| dir[(app.size + 1)..-1] }
end

def expected_db_url(db_key, env)
case db_key
when "pg"
expected_db_url = "postgres://postgres:@localhost:5432/#{TEST_APP_NAME}_#{env}"
when "mysql"
expected_db_url = "#{db_key}://root@localhost:3306/#{TEST_APP_NAME}_#{env}"
else
expected_db_url = "#{db_key}:./db/#{TEST_APP_NAME}_#{env}.db"
end
end

def db_name(db_url : String) : String
db_name(URI.parse(db_url))
end
Expand All @@ -19,8 +35,8 @@ module CLIHelper
path ? path.split('/').last : ""
end

def db_yml(path = TESTING_APP)
YAML.parse(File.read("#{path}/config/database.yml"))
def db_yml(path = CURRENT_ENV_PATH)
YAML.parse(File.read(path))
end

def amber_yml(path = TESTING_APP)
Expand All @@ -31,8 +47,8 @@ module CLIHelper
YAML.parse(File.read("#{path}/shard.yml"))
end

def environment_yml(environment : String)
YAML.parse(File.read("#{TESTING_APP}/config/environments/#{environment}.yml"))
def environment_yml(environment : String, path = ENV_CONFIG_PATH)
YAML.parse(File.read("#{path}#{environment}.yml"))
end

def development_yml
Expand All @@ -57,11 +73,10 @@ module CLIHelper
File.write("#{path}/shard.yml", shard)
end

def prepare_db_yml
yml_path = "./config/database.yml"
db_yml = File.read(yml_path)
def prepare_db_yml(path = ENV_CONFIG_PATH)
db_yml = File.read("#{path}#{CURRENT_ENVIRONMENT}.yml")
db_yml = db_yml.gsub("@localhost:5432", "@db:5432")
File.write(yml_path, db_yml)
File.write("#{path}#{CURRENT_ENVIRONMENT}.yml", db_yml)
end

def scaffold_app(app_name, *options)
Expand Down
39 changes: 13 additions & 26 deletions src/amber/cli/commands/database.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ require "sqlite3"

module Amber::CLI
class MainCommand < ::Cli::Supercommand
AMBER_ENV = (ENV["AMBER_ENV"] ||= "development")
ENV_CONFIG_PATH = "./config/environments/#{AMBER_ENV}.yml"

command "db", aliased: "database"

class Database < ::Cli::Command
Expand Down Expand Up @@ -45,19 +48,16 @@ module Amber::CLI
Micrate::Cli.print_help
end
rescue e : Micrate::UnorderedMigrationsException
Micrate::Cli.report_unordered_migrations(e.versions)
exit 1
exit! Micrate::Cli.report_unordered_migrations(e.versions), error: true
rescue e : DB::ConnectionRefused
puts "Connection refused: #{Micrate::DB.connection_url}"
exit 1
exit! "Connection refused: #{Micrate::DB.connection_url}", error: true
rescue e : Exception
puts e.message
exit 1
exit! e.message, error: true
end
end
end

def drop_database
private def drop_database
url = Micrate::DB.connection_url.to_s
if url.starts_with? "sqlite3:"
path = url.gsub("sqlite3:", "")
Expand All @@ -66,13 +66,13 @@ module Amber::CLI
else
name = set_database_to_schema url
Micrate::DB.connect do |db|
db.exec "DROP DATABASE #{name};"
db.exec "DROP DATABASE IF EXISTS #{name};"
end
puts "Dropped database #{name}"
end
end

def create_database
private def create_database
url = Micrate::DB.connection_url.to_s
if url.starts_with? "sqlite3:"
puts "For sqlite3, the database will be created during the first migration."
Expand All @@ -85,7 +85,7 @@ module Amber::CLI
end
end

def set_database_to_schema(url)
private def set_database_to_schema(url)
uri = URI.parse(url)
if path = uri.path
Micrate::DB.connection_url = url.gsub(path, "/#{uri.scheme}")
Expand All @@ -95,24 +95,11 @@ module Amber::CLI
end
end

def database_url
private def database_url
ENV["DATABASE_URL"]? || begin
yaml_file = File.read("config/database.yml")
yaml_file = File.read(ENV_CONFIG_PATH)
yaml = YAML.parse(yaml_file)
db = yaml.first.to_s
settings = yaml[db]
env(settings["database"].to_s)
end
end

private def env(url)
regex = /\$\{(.*?)\}/
if regex.match(url)
url = url.gsub(regex) do |match|
ENV[match.gsub("${", "").gsub("}", "")]
end
else
return url
yaml["database"].to_s
end
end
end
Expand Down
9 changes: 0 additions & 9 deletions src/amber/cli/templates/app/config/database.yml.ecr

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ process_count: (ENV[%(AMBER_PROCESS_COUNT)]? || 1).to_i
ssl_key_file:
ssl_cert_file:
redis_url: "redis://localhost:6379"
<%case @database
when "mysql" -%>
database: mysql://root@localhost:3306/<%= database_name_base %>_development
<%when "pg" -%>
database: postgres://postgres:@localhost:5432/<%= database_name_base %>_development
<%when "sqlite" -%>
database: sqlite3:./db/<%= database_name_base %>_development.db
<%end -%>
session:
key: amber.session
store: :signed_cookie
expires: 0
secrets:
description: Store your development secrets credentials and settings here.
<%case @database
when "mysql" -%>
database: mysql://root@localhost:3306/<%= database_name_base %>_development
<%when "pg" -%>
database: postgres://postgres:@localhost:5432/<%= database_name_base %>_development
<%when "sqlite" -%>
database: sqlite3:./db/<%= database_name_base %>_development.db
<%end -%>
Loading

0 comments on commit f3f15bd

Please sign in to comment.