bleib 0.0.7
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 +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:
|