Skip to content

two features #137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 96 additions & 11 deletions lib/capistrano-db-tasks/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class Base
DBCONFIG_END_FLAG = "__CAPISTRANODB_CONFIG_END_FLAG__".freeze

attr_accessor :config, :output_file
attr_reader :rvm_ruby

def initialize(cap_instance)
@cap = cap_instance
Expand All @@ -17,9 +18,8 @@ def postgresql?
%w(postgresql pg postgis chronomodel).include? @config['adapter']
end

def credentials
def credentials username = self.username
credential_params = ""
username = @config['username'] || @config['user']

if mysql?
credential_params << " -u #{username} " if username
Expand All @@ -40,6 +40,10 @@ def database
@config['database']
end

def username
@config['username'] || @config['user']
end

def current_time
Time.now.strftime("%Y-%m-%d-%H%M%S")
end
Expand All @@ -56,6 +60,28 @@ def compressor
end
end

def with_rvm?
@rvm_ruby ||= @cap.capture(:rvm, "current", '2>/dev/null')

!@rvm_ruby.empty?
end

def run_with_rvm run_string
if @cap.capture(:rvm, rvm_ruby, "do", "bin/rails -v", '2>/dev/null').size > 0
@cap.capture(:rvm, rvm_ruby, "do", "bin/rails #{run_string}")
else
@cap.capture(:rvm, rvm_ruby, "do", "rails", run_string, '2>/dev/null')
end
end

def run_plain run_string
if @cap.capture(:ruby, "bin/rails -v", '2>/dev/null').size > 0
@cap.capture(:ruby, "bin/rails #{run_string}")
else
@cap.capture(:rails, run_string, '2>/dev/null')
end
end

private

def pgpass
Expand Down Expand Up @@ -109,12 +135,7 @@ def initialize(cap_instance)
@cap.within @cap.current_path do
@cap.with rails_env: @cap.fetch(:rails_env) do
run_string = "runner \"puts '#{DBCONFIG_BEGIN_FLAG}' + ActiveRecord::Base.connection.instance_variable_get(:@config).to_yaml + '#{DBCONFIG_END_FLAG}'\""
dirty_config_content =
if @cap.capture(:ruby, "bin/rails -v", '2>/dev/null').size > 0
@cap.capture(:ruby, "bin/rails #{run_string}", '2>/dev/null')
else
@cap.capture(:rails, run_string, '2>/dev/null')
end
dirty_config_content = with_rvm? ? run_with_rvm(run_string) : run_plain(run_string)
# Remove all warnings, errors and artefacts produced by bunlder, rails and other useful tools
config_content = dirty_config_content.match(/#{DBCONFIG_BEGIN_FLAG}(.*?)#{DBCONFIG_END_FLAG}/m)[1]
@config = YAML.load(config_content).each_with_object({}) { |(k, v), h| h[k.to_s] = v }
Expand Down Expand Up @@ -160,6 +181,54 @@ def db_dump_dir
end
end

class RemoteFake < Base
def initialize(cap_instance)
super(cap_instance)
@cap.info "[db:remote] Loading remote database config"
@cap.within @cap.release_path do
@cap.with rails_env: @cap.fetch(:rails_env) do
string = 'ra = Rails::Application;rails_config = ra::Configuration.new(ra.find_root(ra.called_from)).database_configuration'
run_string = "runner \"#{string};puts rails_config['#{fetch :rails_env}'].to_yaml\""
config_content = with_rvm? ? run_with_rvm(run_string) : run_plain(run_string)

@config = YAML.load(config_content)
end
end
end

def createrole
if mysql?
@cap.execute("mysql-create-user #{target_username} #{@config['password']} || true")
elsif postgresql?
@cap.execute("createuser #{credentials} -dlrs #{target_username} #{with_password} || true")
end

self
end

def createdb
if mysql?
@cap.execute("mysql-grant-db #{target_username} #{database} || true")
elsif postgresql?
@cap.execute("createdb #{credentials(target_username)} #{database} || true")
end

self
end

def with_password
@config['password'] ? "-W <<< #{@config['password']}" : "-w"
end

def username
'postgres'
end

def target_username
@config['username'] || @config['user']
end
end

class Local < Base
def initialize(cap_instance)
super(cap_instance)
Expand Down Expand Up @@ -209,22 +278,38 @@ def execute(cmd)
end

class << self
def check(local_db, remote_db = nil)
def check(local_db = nil, remote_db = nil)
return if mysql_db_valid?(local_db, remote_db)
return if postgresql_db_valid?(local_db, remote_db)

raise 'Only mysql or postgresql on remote and local server is supported'
end

def mysql_db_valid?(local_db, remote_db)
local_db.mysql? && (remote_db.nil? || remote_db && remote_db.mysql?)
(local_db.nil? || local_db && local_db.mysql?) && (remote_db.nil? || remote_db && remote_db.mysql?)
end

def postgresql_db_valid?(local_db, remote_db)
local_db.postgresql? &&
(local_db.nil? || (local_db && local_db.postgresql?)) &&
(remote_db.nil? || (remote_db && remote_db.postgresql?))
end

def createrole(instance)
remote_db = Database::RemoteFake.new(instance)

check(nil, remote_db)

remote_db.createrole
end

def createdb(instance)
remote_db = Database::RemoteFake.new(instance)

check(nil, remote_db)

remote_db.createdb
end

def remote_to_local(instance)
local_db = Database::Local.new(instance)
remote_db = Database::Remote.new(instance)
Expand Down
14 changes: 14 additions & 0 deletions lib/capistrano-db-tasks/dbtasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@
end
end
end

desc 'Create rails DB role on remote server'
task :createrole do
on roles(:db) do
Database.createrole(self)
end
end

desc 'Create rails DB database on remote server'
task createdb: :createrole do
on roles(:db) do
Database.createdb(self)
end
end
end

namespace :local do
Expand Down