bleib 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/bleib.rb +10 -0
- data/lib/bleib/configuration.rb +94 -0
- data/lib/bleib/database.rb +73 -0
- data/lib/bleib/migrations.rb +71 -0
- data/lib/bleib/railtie.rb +7 -0
- data/lib/bleib/version.rb +3 -0
- data/lib/tasks/bleib.rake +14 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1a34d27aee38f1710132dd474bc51bf4e2653b0b
|
4
|
+
data.tar.gz: 99174d377d7b00fbcafbcb2e834131926de04b73
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ce8c1536ee576b3d8b3fe5448e01ea0f92558688af1c746234e7042795be081a7c1329a768634c82d3ea13b4aa348d524e4893fafd47d73c317e668448d6e508
|
7
|
+
data.tar.gz: 88ad1141821e37b1575c4e0aa4a17f6e42815a8acf34950175ac3563d19e846cce271a043dcc293b0c7665c2d3f2f8be906a2425226c237d15b438c71300e4fa
|
data/lib/bleib.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module Bleib
|
2
|
+
class Configuration
|
3
|
+
class UnsupportedAdapterException < Exception; end
|
4
|
+
class DatabaseYmlNotFoundException < Exception; end
|
5
|
+
|
6
|
+
attr_reader :database, :check_database_interval, :check_migrations_interval
|
7
|
+
|
8
|
+
DEFAULT_CHECK_DATABASE_INTERVAL = 5 # Seconds
|
9
|
+
DEFAULT_CHECK_MIGRATIONS_INTERVAL = 5 # Seconds
|
10
|
+
DEFAULT_DATABASE_YML_PATH = 'config/database'
|
11
|
+
|
12
|
+
def self.from_environment
|
13
|
+
check_database_interval = interval_or_default(
|
14
|
+
ENV['BLEIB_CHECK_DATABASE_INTERVAL'],
|
15
|
+
DEFAULT_CHECK_DATABASE_INTERVAL
|
16
|
+
)
|
17
|
+
check_migrations_interval = interval_or_default(
|
18
|
+
ENV['BLEIB_CHECK_MIGRATIONS_INTERVAL'],
|
19
|
+
DEFAULT_CHECK_MIGRATIONS_INTERVAL
|
20
|
+
)
|
21
|
+
|
22
|
+
database_yml_path = ENV['BLEIB_DATABASE_YML_PATH']
|
23
|
+
database_yml_path ||= File.expand_path('config/database.yml')
|
24
|
+
ensure_database_yml!(database_yml_path)
|
25
|
+
|
26
|
+
rails_env = ENV['RAILS_ENV'] || 'development'
|
27
|
+
|
28
|
+
new(
|
29
|
+
rails_database(database_yml_path, rails_env),
|
30
|
+
check_database_interval: check_database_interval.to_i,
|
31
|
+
check_migrations_interval: check_migrations_interval.to_i
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(database_configuration,
|
36
|
+
check_database_interval: DEFAULT_CHECK_DATABASE_INTERVAL,
|
37
|
+
check_migrations_interval: DEFAULT_CHECK_MIGRATIONS_INTERVAL)
|
38
|
+
# To be 100% sure which connection the
|
39
|
+
# active record pool creates, returns or removes.
|
40
|
+
only_one_connection = { 'pool' => 1 }
|
41
|
+
|
42
|
+
@database = database_configuration.merge(only_one_connection)
|
43
|
+
|
44
|
+
@check_database_interval = check_database_interval
|
45
|
+
@check_migrations_interval = check_migrations_interval
|
46
|
+
|
47
|
+
check!
|
48
|
+
end
|
49
|
+
|
50
|
+
def logger
|
51
|
+
return @logger unless @logger.nil?
|
52
|
+
|
53
|
+
@logger = Logger.new(STDOUT)
|
54
|
+
@logger.level = if ENV['BLEIB_LOG_LEVEL'] == 'debug'
|
55
|
+
Logger::DEBUG
|
56
|
+
else
|
57
|
+
Logger::INFO
|
58
|
+
end
|
59
|
+
@logger
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def self.interval_or_default(string, default)
|
65
|
+
given = string.to_i
|
66
|
+
given <= 0 ? default : given
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.ensure_database_yml!(path)
|
70
|
+
return if File.exist?(path)
|
71
|
+
|
72
|
+
fail DatabaseYmlNotFoundException,
|
73
|
+
'database.yml not found, set or fix' \
|
74
|
+
' BLEIB_DATABASE_YML_PATH or execute me' \
|
75
|
+
' from the rails root.'
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.rails_database(database_yml_path, rails_env)
|
79
|
+
contents = File.read(database_yml_path)
|
80
|
+
config = YAML.load(ERB.new(contents).result)
|
81
|
+
config[rails_env]
|
82
|
+
end
|
83
|
+
|
84
|
+
def check!
|
85
|
+
# We should add clean rescue statements to
|
86
|
+
# `Bleib::Database#database_down?`to support
|
87
|
+
# other adapters.
|
88
|
+
if @database['adapter'] != 'postgresql'
|
89
|
+
fail UnsupportedAdapterException,
|
90
|
+
"Unknown database adapter #{@database['adapter']}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Bleib
|
2
|
+
# Finds out if a database is running and accessible.
|
3
|
+
#
|
4
|
+
# Does so by using ActiveRecord without a booted rails
|
5
|
+
# environment (because a non-accessible database can
|
6
|
+
# cause the bootup to fail).
|
7
|
+
class Database
|
8
|
+
def initialize(configuration)
|
9
|
+
@configuration = configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
def wait_for_connection
|
13
|
+
logger.info('Waiting for connection to database')
|
14
|
+
|
15
|
+
wait while database_down?
|
16
|
+
|
17
|
+
logger.info('Connection to database established')
|
18
|
+
|
19
|
+
# Nobody else shall use our single-connection pool.
|
20
|
+
remove_connection
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def wait
|
26
|
+
duration = @configuration.check_database_interval
|
27
|
+
|
28
|
+
logger.debug "Waiting for #{duration} seconds"
|
29
|
+
|
30
|
+
sleep(duration)
|
31
|
+
end
|
32
|
+
|
33
|
+
def database_down?
|
34
|
+
logger.debug('Checking database')
|
35
|
+
|
36
|
+
# Adopted from the default OpenShift readiness check for postgresql.
|
37
|
+
ActiveRecord::Base.establish_connection(@configuration.database)
|
38
|
+
ActiveRecord::Base.connection.execute('SELECT 1;')
|
39
|
+
|
40
|
+
logger.debug('Database check succeeded')
|
41
|
+
|
42
|
+
false
|
43
|
+
rescue PG::ConnectionBad => e
|
44
|
+
# On stopped database:
|
45
|
+
# PG::ConnectionBad: could not connect to server: Connection refused
|
46
|
+
# Is the server running on host "127.0.0.1" and accepting
|
47
|
+
# TCP/IP connections on port 5432?
|
48
|
+
# On wrong/missing user:
|
49
|
+
# PG::ConnectionBad: FATAL: password authentication failed for user "wrong"
|
50
|
+
# On wrong password:
|
51
|
+
# PG::ConnectionBad: FATAL: password authentication failed for user "user"
|
52
|
+
|
53
|
+
logger.debug("Database check failed: #{e}")
|
54
|
+
|
55
|
+
true
|
56
|
+
rescue ActiveRecord::NoDatabaseError
|
57
|
+
# On missing database:
|
58
|
+
# ActiveRecord::NoDatabaseError: FATAL: database "wrong" does not exist
|
59
|
+
|
60
|
+
logger.debug("Database check failed: #{e}")
|
61
|
+
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
def remove_connection
|
66
|
+
ActiveRecord::Base.remove_connection
|
67
|
+
end
|
68
|
+
|
69
|
+
def logger
|
70
|
+
@configuration.logger
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Bleib
|
2
|
+
# Finds out if all migrations are up.
|
3
|
+
#
|
4
|
+
# Knows how to handle multitenancy with Apartment, if used.
|
5
|
+
class Migrations
|
6
|
+
def initialize(configuration)
|
7
|
+
@configuration = configuration
|
8
|
+
end
|
9
|
+
|
10
|
+
def wait_until_done
|
11
|
+
logger.info('Waiting for migrations' \
|
12
|
+
' (Also checking apartment tenants:' \
|
13
|
+
" #{apartment_gem? ? 'yes' : 'no'})")
|
14
|
+
|
15
|
+
wait while pending_migrations?
|
16
|
+
|
17
|
+
logger.info('All migrations are up')
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def wait
|
23
|
+
duration = @configuration.check_migrations_interval
|
24
|
+
|
25
|
+
logger.debug "Waiting for #{@configuration.check_migrations_interval} seconds"
|
26
|
+
|
27
|
+
sleep(duration)
|
28
|
+
end
|
29
|
+
|
30
|
+
def pending_migrations?
|
31
|
+
logger.debug('Checking migrations')
|
32
|
+
|
33
|
+
if apartment_gem?
|
34
|
+
in_all_tenant_contexts { check_migrations! }
|
35
|
+
else
|
36
|
+
check_migrations!
|
37
|
+
end
|
38
|
+
|
39
|
+
logger.debug('Migrations check succeeded.')
|
40
|
+
|
41
|
+
false
|
42
|
+
rescue ActiveRecord::PendingMigrationError
|
43
|
+
logger.debug('Migrations pending, check failed')
|
44
|
+
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def apartment_gem?
|
49
|
+
defined?(Apartment::Tenant)
|
50
|
+
end
|
51
|
+
|
52
|
+
def check_migrations!
|
53
|
+
ActiveRecord::Migration.check_pending!
|
54
|
+
end
|
55
|
+
|
56
|
+
def in_all_tenant_contexts
|
57
|
+
tenants = ['public']
|
58
|
+
Apartment::Tenant.each { |tenant| tenants << tenant }
|
59
|
+
|
60
|
+
tenants.each do |tenant|
|
61
|
+
Apartment::Tenant.switch(tenant) do
|
62
|
+
yield
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def logger
|
68
|
+
@configuration.logger
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
namespace :bleib do
|
2
|
+
desc 'Waits for database access'
|
3
|
+
task :wait_for_database do
|
4
|
+
configuration = Bleib::Configuration.from_environment
|
5
|
+
Bleib::Database.new(configuration).wait_for_connection
|
6
|
+
end
|
7
|
+
|
8
|
+
desc 'Waits for database access and migrations'
|
9
|
+
task wait_for_migrations: [:wait_for_database, :environment] do
|
10
|
+
configuration = Bleib::Configuration.from_environment
|
11
|
+
|
12
|
+
Bleib::Migrations.new(configuration).wait_until_done
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bleib
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Puzzle ITC
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-04 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Intended for use in containerized setups whereanother component takes
|
14
|
+
care of migrating the database.
|
15
|
+
email: raez@puzzle.ch
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/bleib.rb
|
21
|
+
- lib/bleib/configuration.rb
|
22
|
+
- lib/bleib/database.rb
|
23
|
+
- lib/bleib/migrations.rb
|
24
|
+
- lib/bleib/railtie.rb
|
25
|
+
- lib/bleib/version.rb
|
26
|
+
- lib/tasks/bleib.rake
|
27
|
+
homepage: http://rubygems.org/gems/bleib
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata:
|
31
|
+
source_code_uri: https://github.com/puzzle/bleib
|
32
|
+
documentation_uri: https://github.com/puzzle/bleib
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 2.4.8
|
50
|
+
signing_key:
|
51
|
+
specification_version: 4
|
52
|
+
summary: Use a rake task to wait on database and migrations.
|
53
|
+
test_files: []
|
54
|
+
has_rdoc:
|