cappy-taffy 1.0.0
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.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/cappy-taffy.gemspec +21 -0
- data/lib/cappy-taffy.rb +5 -0
- data/lib/cappy-taffy/db.rb +125 -0
- data/lib/cappy-taffy/parse.rb +84 -0
- data/lib/cappy-taffy/version.rb +5 -0
- metadata +75 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
data/cappy-taffy.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "cappy-taffy/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "cappy-taffy"
|
7
|
+
s.version = Cappy::Taffy::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Eric Boehs"]
|
10
|
+
s.email = ["ericboehs@gmail.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Capistrano task to pull production database to local using taps}
|
13
|
+
s.description = %q{Cappy Taffy is based on cap taffy which uses the heroku gem to generate the database and taps urls; this gem however does not depend on the heroku gem.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "cappy-taffy"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
data/lib/cappy-taffy.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
begin
|
3
|
+
gem 'taps', '>= 0.2.8'
|
4
|
+
rescue LoadError
|
5
|
+
error "Install the Taps gem to use db commands."
|
6
|
+
end
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), 'parse')
|
9
|
+
require 'digest/sha1'
|
10
|
+
|
11
|
+
module CappyTaffy::Db
|
12
|
+
extend self
|
13
|
+
|
14
|
+
# Detects the local database url for +env+.
|
15
|
+
def local_database_url(env)
|
16
|
+
# return "" unless File.exists?(Dir.pwd + '/config/database.yml')
|
17
|
+
# db_config = YAML.load(File.read(Dir.pwd + '/config/database.yml'))
|
18
|
+
|
19
|
+
CappyTaffy::Parse.database_url(env)
|
20
|
+
end
|
21
|
+
|
22
|
+
# The default server port the Taps server is started on.
|
23
|
+
def default_server_port
|
24
|
+
5000
|
25
|
+
end
|
26
|
+
|
27
|
+
# Gets the taps host from the config
|
28
|
+
def taps_host
|
29
|
+
return YAML.load(File.read(Dir.pwd + '/config/database.yml'))['production']['taps_host']
|
30
|
+
end
|
31
|
+
|
32
|
+
# Generates the remote url used by Taps push/pull.
|
33
|
+
def remote_taps_url(options={})
|
34
|
+
host = options[:taps_host] || taps_host
|
35
|
+
port = options[:port] || default_server_port
|
36
|
+
|
37
|
+
url = CappyTaffy::Parse.uri_hash_to_url(
|
38
|
+
'username' => options[:login],
|
39
|
+
'password' => options[:password],
|
40
|
+
'host' => host,
|
41
|
+
'port' => port,
|
42
|
+
'scheme' => 'http',
|
43
|
+
'path' => ''
|
44
|
+
)
|
45
|
+
|
46
|
+
return url.sub(/\/$/, '')
|
47
|
+
end
|
48
|
+
|
49
|
+
# Generates a temporary password to be used for the Taps server command.
|
50
|
+
def tmp_pass(user)
|
51
|
+
pass = YAML.load(File.read(Dir.pwd + '/config/database.yml'))['production']['taps_pass']
|
52
|
+
pass = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{user}--") unless pass
|
53
|
+
|
54
|
+
return pass
|
55
|
+
end
|
56
|
+
|
57
|
+
def run(instance, options = {})
|
58
|
+
remote_taps_url = CappyTaffy::Db.remote_taps_url(options)
|
59
|
+
exec("taps #{options[:direction]} #{options[:local_database_url]} #{remote_taps_url}")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
Capistrano::Configuration.instance.load do
|
64
|
+
namespace :db do
|
65
|
+
task :detect, :roles => :app do
|
66
|
+
@remote_taps_url = CappyTaffy::Db.remote_taps_url
|
67
|
+
@local_database_url = CappyTaffy::Db.local_database_url('development')
|
68
|
+
end
|
69
|
+
|
70
|
+
desc <<-DESC
|
71
|
+
Push a local database into the app's remote database.
|
72
|
+
|
73
|
+
Performs push from local development database to remote production database.
|
74
|
+
Opens a Taps server on port 5000. (Ensure port is opened on the remote server).
|
75
|
+
|
76
|
+
# alternately, specify a different port
|
77
|
+
cap db:push -s taps_port=4321
|
78
|
+
|
79
|
+
For the security conscious:
|
80
|
+
|
81
|
+
# use ssh local forwarding (ensure [port] is available on both endpoints)
|
82
|
+
ssh -N -L[port]:127.0.0.1:[port] [user]@[remote-server]
|
83
|
+
|
84
|
+
# then push locally
|
85
|
+
cap db:push -s taps_port=[port] -s local=true
|
86
|
+
DESC
|
87
|
+
# task :push do
|
88
|
+
# detect
|
89
|
+
#
|
90
|
+
# login = fetch(:user)
|
91
|
+
# password = CappyTaffy::Db.tmp_pass(login)
|
92
|
+
#
|
93
|
+
# logger = Capistrano::Logger.new
|
94
|
+
# logger.important "Auto-detected remote database: #{@remote_taps_url}" if @remote_taps_url != ''
|
95
|
+
# logger.important "Auto-detected local database: #{@local_database_url}" if @local_database_url != ''
|
96
|
+
#
|
97
|
+
# options = {:direction => "push",:remote_taps_url => @remote_taps_url, :login => login, :password => password, :local_database_url => @local_database_url, :port => variables[:taps_port]}
|
98
|
+
#
|
99
|
+
# CappyTaffy::Db.run(self, options)
|
100
|
+
# end
|
101
|
+
|
102
|
+
desc <<-DESC
|
103
|
+
Pull the app's database into a local database.
|
104
|
+
|
105
|
+
Performs pull from remote production database to local development database.
|
106
|
+
|
107
|
+
# alternately, specify a different port (default 5000)
|
108
|
+
cap db:pull -s taps_port=4321
|
109
|
+
DESC
|
110
|
+
task :pull do
|
111
|
+
detect
|
112
|
+
|
113
|
+
login = fetch(:user)
|
114
|
+
password = CappyTaffy::Db.tmp_pass(login)
|
115
|
+
|
116
|
+
logger = Capistrano::Logger.new
|
117
|
+
logger.important "Auto-detected remote database: #{@remote_taps_url}" if @remote_taps_url != ''
|
118
|
+
logger.important "Auto-detected local database: #{@local_database_url}" if @local_database_url != ''
|
119
|
+
|
120
|
+
options = {:direction => "pull",:remote_taps_url => @remote_taps_url, :login => login, :password => password, :local_database_url => @local_database_url, :port => variables[:taps_port]}
|
121
|
+
|
122
|
+
CappyTaffy::Db.run(self, options)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'yaml'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module CappyTaffy
|
6
|
+
class Parse
|
7
|
+
class << self
|
8
|
+
attr_accessor :instance
|
9
|
+
|
10
|
+
# Modified from :parse_database_yml in heroku/command/db.rb
|
11
|
+
def database_url(environment=nil)
|
12
|
+
cwd = Dir.pwd
|
13
|
+
#TODO: Remove static cwd
|
14
|
+
# cwd = '/Users/ericboehs/Dropbox/Projects/Digimedia/digistore_new/administrators'
|
15
|
+
|
16
|
+
return "" unless File.exists?(cwd + '/config/database.yml')
|
17
|
+
|
18
|
+
unless environment
|
19
|
+
environment = ENV['RAILS_ENV'] || ENV['MERB_ENV'] || ENV['RACK_ENV']
|
20
|
+
environment = 'development' if environment.nil? or environment.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
conf = YAML.load(File.read(cwd + '/config/database.yml'))[environment]
|
24
|
+
case conf['adapter']
|
25
|
+
when 'sqlite3'
|
26
|
+
return "sqlite://#{conf['database']}"
|
27
|
+
when 'postgresql'
|
28
|
+
uri_hash = conf_to_uri_hash(conf)
|
29
|
+
uri_hash['scheme'] = 'postgres'
|
30
|
+
return uri_hash_to_url(uri_hash)
|
31
|
+
else
|
32
|
+
return uri_hash_to_url(conf_to_uri_hash(conf))
|
33
|
+
end
|
34
|
+
rescue Exception => ex
|
35
|
+
puts "Error parsing database.yml: #{ex.message}"
|
36
|
+
puts ex.backtrace
|
37
|
+
""
|
38
|
+
end
|
39
|
+
|
40
|
+
# Part of heroku/command/db.rb
|
41
|
+
def conf_to_uri_hash(conf)
|
42
|
+
uri = {}
|
43
|
+
uri['scheme'] = conf['adapter']
|
44
|
+
uri['username'] = conf['user'] || conf['username']
|
45
|
+
uri['password'] = conf['password']
|
46
|
+
uri['host'] = conf['host'] || conf['hostname']
|
47
|
+
uri['port'] = conf['port']
|
48
|
+
uri['path'] = conf['database']
|
49
|
+
|
50
|
+
conf['encoding'] = 'utf8' if conf['encoding'] == 'unicode' or conf['encoding'].nil?
|
51
|
+
uri['query'] = "encoding=#{conf['encoding']}"
|
52
|
+
|
53
|
+
uri
|
54
|
+
end
|
55
|
+
|
56
|
+
# Part of heroku/command/db.rb
|
57
|
+
def userinfo_from_uri(uri)
|
58
|
+
username = uri['username'].to_s
|
59
|
+
password = uri['password'].to_s
|
60
|
+
return nil if username == ''
|
61
|
+
|
62
|
+
userinfo = ""
|
63
|
+
userinfo << username
|
64
|
+
userinfo << ":" << password if password.length > 0
|
65
|
+
userinfo
|
66
|
+
end
|
67
|
+
|
68
|
+
# Part of heroku/command/db.rb
|
69
|
+
def uri_hash_to_url(uri)
|
70
|
+
uri_parts = {
|
71
|
+
:scheme => uri['scheme'],
|
72
|
+
:userinfo => userinfo_from_uri(uri),
|
73
|
+
:password => uri['password'],
|
74
|
+
:host => uri['host'] || '127.0.0.1',
|
75
|
+
:port => uri['port'],
|
76
|
+
:path => "/%s" % uri['path'],
|
77
|
+
:query => uri['query'],
|
78
|
+
}
|
79
|
+
|
80
|
+
URI::Generic.build(uri_parts).to_s
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cappy-taffy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Eric Boehs
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-31 00:00:00 -06:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Cappy Taffy is based on cap taffy which uses the heroku gem to generate the database and taps urls; this gem however does not depend on the heroku gem.
|
23
|
+
email:
|
24
|
+
- ericboehs@gmail.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- Gemfile
|
34
|
+
- Rakefile
|
35
|
+
- cappy-taffy.gemspec
|
36
|
+
- lib/cappy-taffy.rb
|
37
|
+
- lib/cappy-taffy/db.rb
|
38
|
+
- lib/cappy-taffy/parse.rb
|
39
|
+
- lib/cappy-taffy/version.rb
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: ""
|
42
|
+
licenses: []
|
43
|
+
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
hash: 3
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
hash: 3
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project: cappy-taffy
|
70
|
+
rubygems_version: 1.4.2
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: Capistrano task to pull production database to local using taps
|
74
|
+
test_files: []
|
75
|
+
|