hsume2-cap-taffy 0.0.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +1 -5
- data/README.md +4 -20
- data/Rakefile +0 -1
- data/cap-taffy.gemspec +3 -6
- data/lib/cap-taffy/db.rb +9 -70
- data/lib/cap-taffy/parse.rb +3 -7
- data/lib/cap-taffy.rb +1 -1
- data/spec/cap-taffy/db_spec.rb +47 -52
- data/spec/cap-taffy_spec.rb +3 -0
- data/spec/spec_helper.rb +39 -84
- metadata +3 -16
- data/lib/cap-taffy/ssh.rb +0 -18
- data/spec/cap-taffy/ssh_spec.rb +0 -37
data/History.txt
CHANGED
data/README.md
CHANGED
@@ -7,7 +7,6 @@ Features
|
|
7
7
|
------------------------------------------------
|
8
8
|
|
9
9
|
* Adds database transfer recipes (via [`Taps`]("http://github.com/ricardochimal/taps"))
|
10
|
-
* Authorize SSH access
|
11
10
|
* Manage `database.yml` (Soon.)
|
12
11
|
|
13
12
|
[`Taps`]("http://github.com/ricardochimal/taps") is great, but having to SSH into my deployment to run the `Taps` server, as well as
|
@@ -21,9 +20,11 @@ Installation
|
|
21
20
|
|
22
21
|
gem install cap-taffy
|
23
22
|
|
24
|
-
|
23
|
+
Usage
|
25
24
|
------------------------------------------------
|
26
25
|
|
26
|
+
### `Taffy`: Database Transfer
|
27
|
+
|
27
28
|
> _Dependency:_ The [`Taps`]("http://github.com/ricardochimal/taps") gem is required on any server(s) you'll be transferring databases to (`:app` role) including your development machine (where you'll be running `cap` tasks from). Run:
|
28
29
|
|
29
30
|
> gem install taps
|
@@ -32,8 +33,6 @@ Database Transfer
|
|
32
33
|
|
33
34
|
> gem install heroku
|
34
35
|
|
35
|
-
### Usage
|
36
|
-
|
37
36
|
To start, add the following to your `Capfile`
|
38
37
|
|
39
38
|
require 'cap-taffy/db'
|
@@ -59,22 +58,7 @@ Then you can use:
|
|
59
58
|
> > ssh -N -L4321:127.0.0.1:4321 henry@load-test
|
60
59
|
> > cap db:push -s taps_port=4321 -s local=true
|
61
60
|
|
62
|
-
|
63
|
-
------------------------------------------------
|
64
|
-
|
65
|
-
#### Usage
|
66
|
-
|
67
|
-
Add the following to your `Capfile`
|
68
|
-
|
69
|
-
require 'cap-taffy/ssh'
|
70
|
-
|
71
|
-
Using a public key generated from `ssh-keygen` (e.g. `ssh-keygen -t rsa`), to authorize access:
|
72
|
-
|
73
|
-
cap ssh:authorize # authorizes local public key for SSH access to remote server(s)
|
74
|
-
|
75
|
-
|
76
|
-
Managing `database.yml`
|
77
|
-
------------------------------------------------
|
61
|
+
### Managing `database.yml`
|
78
62
|
|
79
63
|
> Much needed and coming soon.
|
80
64
|
|
data/Rakefile
CHANGED
@@ -26,7 +26,6 @@ PROJ.version = CapTaffy::VERSION
|
|
26
26
|
PROJ.rubyforge.name = 'cap-taffy'
|
27
27
|
PROJ.readme_file = "README.md"
|
28
28
|
PROJ.gem.dependencies = ['heroku', 'taps', 'capistrano']
|
29
|
-
PROJ.gem.development_dependencies << ["mocha"]
|
30
29
|
PROJ.description = "Capistrano recipes for deploying databases and other common tasks."
|
31
30
|
PROJ.summary = "Capistrano recipes for deploying databases (managing database.yml, importing/exporting/transfering databases, etc.)"
|
32
31
|
PROJ.ignore_file = '.gitignore'
|
data/cap-taffy.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{cap-taffy}
|
5
|
-
s.version = "0.0
|
5
|
+
s.version = "1.0.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Henry Hsu"]
|
9
|
-
s.date = %q{2009-09-
|
9
|
+
s.date = %q{2009-09-14}
|
10
10
|
s.description = %q{Capistrano recipes for deploying databases and other common tasks.}
|
11
11
|
s.email = %q{henry@qlane.com}
|
12
12
|
s.extra_rdoc_files = ["History.txt"]
|
13
|
-
s.files = ["History.txt", "README.md", "Rakefile", "cap-taffy.gemspec", "lib/cap-taffy.rb", "lib/cap-taffy/db.rb", "lib/cap-taffy/parse.rb", "
|
13
|
+
s.files = ["History.txt", "README.md", "Rakefile", "cap-taffy.gemspec", "lib/cap-taffy.rb", "lib/cap-taffy/db.rb", "lib/cap-taffy/parse.rb", "spec/cap-taffy/db_spec.rb", "spec/cap-taffy/parse_spec.rb", "spec/cap-taffy_spec.rb", "spec/spec.opts", "spec/spec_helper.rb"]
|
14
14
|
s.homepage = %q{http://by.qlane.com}
|
15
15
|
s.rdoc_options = ["--main", "README.md"]
|
16
16
|
s.require_paths = ["lib"]
|
@@ -27,19 +27,16 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_runtime_dependency(%q<taps>, [">= 0"])
|
28
28
|
s.add_runtime_dependency(%q<capistrano>, [">= 0"])
|
29
29
|
s.add_development_dependency(%q<bones>, [">= 2.5.1"])
|
30
|
-
s.add_development_dependency(%q<mocha>, [">= 0"])
|
31
30
|
else
|
32
31
|
s.add_dependency(%q<heroku>, [">= 0"])
|
33
32
|
s.add_dependency(%q<taps>, [">= 0"])
|
34
33
|
s.add_dependency(%q<capistrano>, [">= 0"])
|
35
34
|
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
36
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
37
35
|
end
|
38
36
|
else
|
39
37
|
s.add_dependency(%q<heroku>, [">= 0"])
|
40
38
|
s.add_dependency(%q<taps>, [">= 0"])
|
41
39
|
s.add_dependency(%q<capistrano>, [">= 0"])
|
42
40
|
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
43
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
44
41
|
end
|
45
42
|
end
|
data/lib/cap-taffy/db.rb
CHANGED
@@ -6,49 +6,30 @@ rescue LoadError
|
|
6
6
|
error "Install the Taps gem to use db commands. On most systems this will be:\nsudo gem install taps"
|
7
7
|
end
|
8
8
|
|
9
|
-
require File.join(File.dirname(__FILE__), %w[.. cap-taffy]) unless defined?(CapTaffy)
|
10
9
|
require File.join(File.dirname(__FILE__), 'parse')
|
11
10
|
require 'digest/sha1'
|
12
11
|
|
13
12
|
module CapTaffy::Db
|
14
13
|
extend self
|
15
14
|
|
16
|
-
|
17
|
-
#
|
18
|
-
# Looks for <tt>config/database.yml</tt>.
|
19
|
-
def local_database_url(env)
|
15
|
+
def local(env)
|
20
16
|
return "" unless File.exists?(Dir.pwd + '/config/database.yml')
|
21
17
|
db_config = YAML.load(File.read(Dir.pwd + '/config/database.yml'))
|
22
18
|
|
23
19
|
CapTaffy::Parse.database_url(db_config, env)
|
24
20
|
end
|
25
21
|
|
26
|
-
|
27
|
-
#
|
28
|
-
# Looks for <tt>config/database.yml</tt> in the +current_path+.
|
29
|
-
def remote_database_url(instance, env)
|
22
|
+
def remote(instance, env)
|
30
23
|
db_yml = instance.capture "cat #{instance.current_path}/config/database.yml"
|
31
24
|
db_config = YAML::load(db_yml)
|
32
25
|
|
33
26
|
CapTaffy::Parse.database_url(db_config, env)
|
34
27
|
end
|
35
28
|
|
36
|
-
# The default server port the Taps server is started on.
|
37
29
|
def default_server_port
|
38
30
|
5000
|
39
31
|
end
|
40
32
|
|
41
|
-
# Generates the remote url used by Taps push/pull.
|
42
|
-
#
|
43
|
-
# ==== Parameters
|
44
|
-
#
|
45
|
-
# * <tt>:login, :password, :host, :port</tt> - See #run.
|
46
|
-
#
|
47
|
-
# ==== Examples
|
48
|
-
#
|
49
|
-
# login = fetch(:user)
|
50
|
-
# password = tmp_pass(login) # returns asdkf239udjhdaks (for example)
|
51
|
-
# remote_url(:login => login, :password => password, :host => 'load-test') # returns http://henry:asdkf239udjhdaks@load-test:5000
|
52
33
|
def remote_url(options={})
|
53
34
|
host = options[:host]
|
54
35
|
port = options[:port] || default_server_port
|
@@ -58,15 +39,11 @@ module CapTaffy::Db
|
|
58
39
|
url.sub(/\/$/, '')
|
59
40
|
end
|
60
41
|
|
61
|
-
# Generates a temporary password to be used for the Taps server command.
|
62
42
|
def tmp_pass(user)
|
63
43
|
Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{user}--")
|
64
44
|
end
|
65
45
|
|
66
|
-
|
67
|
-
#
|
68
|
-
# <tt>local_database_url</tt> and <tt>remote_url</tt> refer to the options for the Taps gem (see #run).
|
69
|
-
def taps_client(local_database_url, remote_url, &blk) # :yields: client
|
46
|
+
def taps_client(local_database_url, remote_url, &blk)
|
70
47
|
Taps::Config.chunksize = 1000
|
71
48
|
Taps::Config.database_url = local_database_url
|
72
49
|
Taps::Config.remote_url = remote_url
|
@@ -77,11 +54,7 @@ module CapTaffy::Db
|
|
77
54
|
end
|
78
55
|
end
|
79
56
|
|
80
|
-
#
|
81
|
-
#
|
82
|
-
# ==== Parameters
|
83
|
-
# * <tt>:remote_database_url, :login, :password</tt> - See #run.
|
84
|
-
# * <tt>:port</tt> - The +port+ the Taps server is on. If given and different from #default_server_port, appends <tt>--port=[port]</tt> to command.
|
57
|
+
# server <local_database_url> <login> <password> [--port=N]
|
85
58
|
def server_command(options={})
|
86
59
|
remote_database_url, login, password, port = options[:remote_database_url], options[:login], options[:password], options[:port]
|
87
60
|
port_argument = ''
|
@@ -90,37 +63,7 @@ module CapTaffy::Db
|
|
90
63
|
"taps server #{remote_database_url} #{login} #{password}#{port_argument}"
|
91
64
|
end
|
92
65
|
|
93
|
-
|
94
|
-
#
|
95
|
-
# 1. Runs the <tt>taps</tt> taps command to start the Taps server (assuming Sinatra is running on Thin)
|
96
|
-
# 2. Wait until the server is ready
|
97
|
-
# 3. Execute block on Taps client
|
98
|
-
# 4. Close the connection(s) and bid farewell.
|
99
|
-
#
|
100
|
-
# ==== Parameters
|
101
|
-
# * <tt>:remote_database_url</tt> - Refers to local database url in the options for the Taps server command (see Taps Options).
|
102
|
-
# * <tt>:login</tt> - The login for +host+. Usually what's in <tt>set :user, "the user"</tt> in <tt>deploy.rb</tt>
|
103
|
-
# * <tt>:password</tt> - The temporary password for the Taps server.
|
104
|
-
# * <tt>:port</tt> - The +port+ the Taps server is on. If not given, defaults to #default_server_port.
|
105
|
-
# * <tt>:local_database_url</tt> - Refers to the local database url in the options for Taps client commands (see Taps Options).
|
106
|
-
#
|
107
|
-
# ==== Taps Options
|
108
|
-
#
|
109
|
-
# <tt>taps</tt>
|
110
|
-
# server <local_database_url> <login> <password> [--port=N] Start a taps database import/export server
|
111
|
-
# pull <local_database_url> <remote_url> [--chunksize=N] Pull a database from a taps server
|
112
|
-
# push <local_database_url> <remote_url> [--chunksize=N] Push a database to a taps server
|
113
|
-
#
|
114
|
-
# ==== Examples
|
115
|
-
#
|
116
|
-
# task :push do
|
117
|
-
# login = fetch(:user)
|
118
|
-
# password = Time.now.to_s
|
119
|
-
# CapTaffy.Db.run(self, { :login => login, :password => password, :remote_database_url => "sqlite://test_production", :local_database_url => "sqlite://test_development" }) do |client|
|
120
|
-
# client.cmd_send
|
121
|
-
# end
|
122
|
-
# end
|
123
|
-
def run(instance, options = {} , &blk) # :yields: client
|
66
|
+
def run(instance, options = {} , &blk)
|
124
67
|
options[:port] ||= default_server_port
|
125
68
|
remote_database_url, login, password, port, local_database_url = options[:remote_database_url], options[:login], options[:password], options[:port], options[:local_database_url]
|
126
69
|
force_local = options.delete(:local)
|
@@ -143,16 +86,12 @@ module CapTaffy::Db
|
|
143
86
|
end
|
144
87
|
end
|
145
88
|
|
146
|
-
class InvalidURL < RuntimeError
|
147
|
-
end
|
89
|
+
class InvalidURL < RuntimeError; end
|
148
90
|
end
|
149
91
|
|
150
92
|
Capistrano::Configuration.instance.load do
|
151
93
|
namespace :db do
|
152
|
-
|
153
|
-
# If this is a dry run, any raised exceptions will be caught and +returning+ is returned.
|
154
|
-
# If this is not a dry run, any exceptions will be raised as expected.
|
155
|
-
def dry_run_safe(returning = nil, &block) # :yields:
|
94
|
+
def dry_run_safe(returning = nil, &block)
|
156
95
|
begin
|
157
96
|
yield
|
158
97
|
rescue Exception => e
|
@@ -162,8 +101,8 @@ Capistrano::Configuration.instance.load do
|
|
162
101
|
end
|
163
102
|
|
164
103
|
task :detect, :roles => :app do
|
165
|
-
@remote_database_url = dry_run_safe('') { CapTaffy::Db.
|
166
|
-
@local_database_url = dry_run_safe('') { CapTaffy::Db.
|
104
|
+
@remote_database_url = dry_run_safe('') { CapTaffy::Db.remote(self, 'production') }
|
105
|
+
@local_database_url = dry_run_safe('') { CapTaffy::Db.local('development') }
|
167
106
|
end
|
168
107
|
|
169
108
|
desc <<-DESC
|
data/lib/cap-taffy/parse.rb
CHANGED
@@ -13,8 +13,6 @@ module CapTaffy
|
|
13
13
|
attr_accessor :instance
|
14
14
|
|
15
15
|
# Modified from :parse_database_yml in heroku/command/db.rb
|
16
|
-
#
|
17
|
-
# Accepts a complete +db_config+ hash and +env+ and parses for a database_url accordingly.
|
18
16
|
def database_url(db_config, env)
|
19
17
|
raise Invalid, "please pass me a valid Hash loaded from a database YAML file" unless db_config
|
20
18
|
conf = db_config[env]
|
@@ -35,19 +33,17 @@ module CapTaffy
|
|
35
33
|
end
|
36
34
|
end
|
37
35
|
|
38
|
-
|
39
|
-
def initialize # :nodoc:
|
36
|
+
def initialize
|
40
37
|
|
41
38
|
end
|
42
39
|
|
43
|
-
#
|
40
|
+
# Do nothing
|
44
41
|
def escape(string)
|
45
42
|
string
|
46
43
|
end
|
47
44
|
|
48
45
|
public :uri_hash_to_url, :conf_to_uri_hash
|
49
46
|
|
50
|
-
class Invalid < RuntimeError
|
51
|
-
end
|
47
|
+
class Invalid < RuntimeError; end
|
52
48
|
end
|
53
49
|
end
|
data/lib/cap-taffy.rb
CHANGED
data/spec/cap-taffy/db_spec.rb
CHANGED
@@ -22,69 +22,64 @@ module CapTaffy
|
|
22
22
|
load 'lib/cap-taffy/db.rb'
|
23
23
|
end
|
24
24
|
|
25
|
-
for_task :detect, :roles => :app, :
|
26
|
-
@
|
27
|
-
@
|
25
|
+
for_task :detect, :roles => :app, :it => "should be defined" do
|
26
|
+
@db_mod.expects(:remote).returns("remote_db_url")
|
27
|
+
@db_mod.expects(:local).returns("local_db_url")
|
28
28
|
|
29
29
|
load 'lib/cap-taffy/db.rb'
|
30
30
|
|
31
|
-
@
|
32
|
-
@
|
31
|
+
@namespace_db.instance_variable_get(:@remote_database_url).should == "remote_db_url"
|
32
|
+
@namespace_db.instance_variable_get(:@local_database_url).should == "local_db_url"
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
|
-
with_logger do
|
37
|
-
load 'lib/cap-taffy/db.rb'
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
for_task :push, :roles => :app, :in => :Db, :it => "should send taps client cmd_send" do
|
35
|
+
for_task :push, :roles => :app, :it => "should send taps client cmd_send" do
|
42
36
|
options = {:remote_database_url => "remote", :local_database_url => "local", :port => nil, :login => "a_user", :password => "a_pass"}
|
43
|
-
@
|
37
|
+
@namespace_db.expects(:detect)
|
44
38
|
namespace_with_variables(:taps_port => nil)
|
45
|
-
|
46
|
-
|
47
|
-
@
|
39
|
+
namespace_with_expected_options(options)
|
40
|
+
|
41
|
+
@db_mod.expects(:tmp_pass).with(@namespace_db.fetch(:user)).returns(options[:password])
|
42
|
+
@db_mod.expects(:run).with(@namespace_db, options).yields(taps_client_who(:expects, :cmd_send))
|
48
43
|
|
49
|
-
|
44
|
+
load_taffy
|
50
45
|
end
|
51
46
|
|
52
|
-
for_task :push, :roles => :app, :
|
47
|
+
for_task :push, :roles => :app, :it => "should use cli argument for port" do
|
53
48
|
options = {:remote_database_url => "remote", :local_database_url => "local", :port => 1234, :login => "a_user", :password => "a_pass"}
|
54
|
-
@
|
49
|
+
@namespace_db.expects(:detect)
|
55
50
|
namespace_with_variables(:taps_port => 1234)
|
56
|
-
|
57
|
-
@
|
58
|
-
@
|
51
|
+
namespace_with_expected_options(options)
|
52
|
+
@db_mod.expects(:tmp_pass).with(@namespace_db.fetch(:user)).returns(options[:password])
|
53
|
+
@db_mod.expects(:run).with(@namespace_db, options)
|
59
54
|
|
60
|
-
|
55
|
+
load_taffy
|
61
56
|
end
|
62
57
|
|
63
|
-
for_task :push, :roles => :app, :
|
58
|
+
for_task :push, :roles => :app, :it => "should force 127.0.0.1 (local) for ssh local forwarding" do
|
64
59
|
options = {:remote_database_url => "remote", :local_database_url => "local", :port => 1234, :login => "a_user", :password => "a_pass"}
|
65
|
-
@
|
60
|
+
@namespace_db.expects(:detect)
|
66
61
|
namespace_with_variables(:taps_port => 1234, :local => true)
|
67
|
-
|
68
|
-
@
|
69
|
-
@
|
62
|
+
namespace_with_expected_options(options)
|
63
|
+
@db_mod.expects(:tmp_pass).with(@namespace_db.fetch(:user)).returns(options[:password])
|
64
|
+
@db_mod.expects(:run).with(@namespace_db, options.merge(:local => true))
|
70
65
|
|
71
|
-
|
66
|
+
load_taffy
|
72
67
|
end
|
73
68
|
|
74
|
-
for_task :pull, :roles => :app, :
|
69
|
+
for_task :pull, :roles => :app, :it => "should send taps client cmd_receive" do
|
75
70
|
options = {:remote_database_url => "remote", :local_database_url => "local", :port => nil, :login => "a_user", :password => "a_pass"}
|
76
|
-
@
|
71
|
+
@namespace_db.expects(:detect)
|
77
72
|
namespace_with_variables(:taps_port => nil)
|
78
|
-
|
79
|
-
@mod.expects(:tmp_pass).with(@namespace.fetch(:user)).returns(options[:password])
|
80
|
-
@mod.expects(:run).with(@namespace, options).yields(taps_client_who(:expects, :cmd_receive))
|
73
|
+
namespace_with_expected_options(options)
|
81
74
|
|
82
|
-
|
75
|
+
@db_mod.expects(:tmp_pass).with(@namespace_db.fetch(:user)).returns(options[:password])
|
76
|
+
@db_mod.expects(:run).with(@namespace_db, options).yields(taps_client_who(:expects, :cmd_receive))
|
77
|
+
|
78
|
+
load_taffy
|
83
79
|
end
|
84
80
|
end
|
85
81
|
|
86
82
|
context "after capistrano" do
|
87
|
-
include CapistranoHelpers
|
88
83
|
include TaffyHelpers
|
89
84
|
|
90
85
|
before do
|
@@ -112,7 +107,7 @@ module CapTaffy
|
|
112
107
|
env = 'test'
|
113
108
|
Parse.expects(:database_url).with(@conf, env)
|
114
109
|
|
115
|
-
Db.
|
110
|
+
Db.local(env)
|
116
111
|
end
|
117
112
|
|
118
113
|
it "should detect remote database url" do
|
@@ -123,7 +118,7 @@ module CapTaffy
|
|
123
118
|
env = 'test'
|
124
119
|
Parse.expects(:database_url).with(@conf, env)
|
125
120
|
|
126
|
-
Db.
|
121
|
+
Db.remote(instance, env)
|
127
122
|
end
|
128
123
|
|
129
124
|
it "should create temporary password from time and user" do
|
@@ -179,12 +174,12 @@ module CapTaffy
|
|
179
174
|
parser = mock()
|
180
175
|
Parse.expects(:new).at_least_once.returns(parser)
|
181
176
|
parser.expects(:uri_hash_to_url).
|
182
|
-
with('username' => login, 'password' => password, 'host' => host, 'scheme' => 'http', 'path' => '')
|
177
|
+
with('username' => login, 'password' => password, 'host' => host, 'scheme' => 'http', 'path' => '').returns("remote_url")
|
183
178
|
end
|
184
179
|
|
185
180
|
it "should build remote url (with some help)" do
|
186
181
|
@options[:host] = "127.0.0.1"
|
187
|
-
parser_expects_uri_hash_to_url_with(@options[:login], @options[:password], "#{@options[:host]}:#{Db.default_server_port}")
|
182
|
+
parser_expects_uri_hash_to_url_with(@options[:login], @options[:password], "#{@options[:host]}:#{Db.default_server_port}")
|
188
183
|
|
189
184
|
Db.remote_url(@options)
|
190
185
|
end
|
@@ -192,7 +187,7 @@ module CapTaffy
|
|
192
187
|
it "should build remote url with different port" do
|
193
188
|
@options[:host] = "127.0.0.1"
|
194
189
|
@options[:port] = 1234
|
195
|
-
parser_expects_uri_hash_to_url_with(@options[:login], @options[:password], "#{@options[:host]}:#{@options[:port]}")
|
190
|
+
parser_expects_uri_hash_to_url_with(@options[:login], @options[:password], "#{@options[:host]}:#{@options[:port]}")
|
196
191
|
|
197
192
|
Db.remote_url(@options)
|
198
193
|
end
|
@@ -204,15 +199,15 @@ module CapTaffy
|
|
204
199
|
Db.remote_url(@options).should == "remote_url"
|
205
200
|
end
|
206
201
|
|
207
|
-
|
208
|
-
|
202
|
+
running_taffy_it "should run with capistrano" do
|
203
|
+
run_capistrano_with(Db.server_command(@options))
|
209
204
|
|
210
205
|
Db.run(@capistrano, @options)
|
211
206
|
end
|
212
207
|
|
213
|
-
|
208
|
+
running_taffy_it "should do something to taps client" do
|
214
209
|
channel, stream, data = simulating_run_loop_with :data => ">> Listening on 0.0.0.0:5000, CTRL+C to stop\r\n" do
|
215
|
-
|
210
|
+
run_capistrano_with(Db.server_command(@options))
|
216
211
|
end
|
217
212
|
channel.expects(:close)
|
218
213
|
|
@@ -225,11 +220,11 @@ module CapTaffy
|
|
225
220
|
channel[:status].should == 0
|
226
221
|
end
|
227
222
|
|
228
|
-
|
223
|
+
running_taffy_it "should run taffy on different port" do
|
229
224
|
@options[:port] = 1234
|
230
225
|
|
231
226
|
channel, stream, data = simulating_run_loop_with :data => ">> Listening on 0.0.0.0:1234, CTRL+C to stop\r\n" do
|
232
|
-
|
227
|
+
run_capistrano_with(Db.server_command(@options))
|
233
228
|
end
|
234
229
|
channel.expects(:close)
|
235
230
|
Db.expects(:remote_url).with(@options.merge(:host => channel[:host])).returns("remote_url")
|
@@ -242,9 +237,9 @@ module CapTaffy
|
|
242
237
|
channel[:status].should == 0
|
243
238
|
end
|
244
239
|
|
245
|
-
|
240
|
+
running_taffy_it "should not do anything until taps sinatra server is running" do
|
246
241
|
simulating_run_loop_with :data => "asdfasdf" do
|
247
|
-
|
242
|
+
run_capistrano_with(Db.server_command(@options))
|
248
243
|
end
|
249
244
|
|
250
245
|
client = mock()
|
@@ -255,7 +250,7 @@ module CapTaffy
|
|
255
250
|
end
|
256
251
|
|
257
252
|
channel, stream, data = simulating_run_loop_with :data => ">> Listening on 0.0.0.0:5000, CTRL+C to stop\r\n" do
|
258
|
-
|
253
|
+
run_capistrano_with(Db.server_command(@options))
|
259
254
|
end
|
260
255
|
channel.expects(:close)
|
261
256
|
Db.expects(:remote_url).with(@options.merge(:host => channel[:host], :port => 5000)).returns("remote_url")
|
@@ -268,9 +263,9 @@ module CapTaffy
|
|
268
263
|
channel[:status].should == 0
|
269
264
|
end
|
270
265
|
|
271
|
-
|
266
|
+
running_taffy_it "should force 127.0.0.1 (local) for remote url" do
|
272
267
|
channel, stream, data = simulating_run_loop_with :data => ">> Listening on 0.0.0.0:5000, CTRL+C to stop\r\n" do
|
273
|
-
|
268
|
+
run_capistrano_with(Db.server_command(@options))
|
274
269
|
end
|
275
270
|
channel.expects(:close)
|
276
271
|
|
data/spec/cap-taffy_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib cap-taffy]))
|
2
2
|
|
3
|
-
module Capistrano
|
3
|
+
module Capistrano
|
4
4
|
end
|
5
5
|
|
6
6
|
Spec::Runner.configure do |config|
|
@@ -34,19 +34,12 @@ Capistrano::Configuration.class_eval do
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
class String # :nodoc:
|
38
|
-
def demodulize
|
39
|
-
gsub(/^.*::/, '')
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
37
|
module CapistranoHelpers
|
44
|
-
def self.included(base)
|
38
|
+
def self.included(base)
|
45
39
|
base.extend CapistranoHelpers::ClassMethods
|
46
40
|
end
|
47
41
|
|
48
|
-
|
49
|
-
def with_logger(&blk) # :yields:
|
42
|
+
def with_logger(&blk)
|
50
43
|
logger_class = Class.new
|
51
44
|
logger = mock()
|
52
45
|
logger.stub_everything
|
@@ -57,83 +50,41 @@ module CapistranoHelpers
|
|
57
50
|
Capistrano.send(:remove_const, "Logger") rescue nil
|
58
51
|
end
|
59
52
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@namespace.instance_variable_set(:@local_database_url, options[:local_database_url])
|
53
|
+
def load_taffy
|
54
|
+
with_logger do
|
55
|
+
load 'lib/cap-taffy/db.rb'
|
56
|
+
end
|
65
57
|
end
|
66
58
|
|
67
|
-
|
68
|
-
|
69
|
-
@
|
59
|
+
def namespace_with_expected_options(options)
|
60
|
+
@namespace_db.stubs(:fetch).with(:user).returns(options[:login])
|
61
|
+
@namespace_db.instance_variable_set(:@remote_database_url, options[:remote_database_url])
|
62
|
+
@namespace_db.instance_variable_set(:@local_database_url, options[:local_database_url])
|
70
63
|
end
|
71
64
|
|
72
|
-
|
73
|
-
|
74
|
-
instance.expects(:run).with(*args)
|
65
|
+
def namespace_with_variables(variables)
|
66
|
+
@namespace_db.stubs(:variables).returns(variables)
|
75
67
|
end
|
76
68
|
|
77
|
-
# The Capistrano <tt>:run</tt> action loops with <tt>channel</tt>, <tt>stream</tt>, and <tt>data</tt> until the channel is closed.
|
78
|
-
#
|
79
|
-
# Passing in a <tt>:run</tt> expectation, modifies the expectation such that each subsequent invocation ("loop") yields <tt>channel</tt>, <tt>stream</tt>, and <tt>data</tt>
|
80
|
-
#
|
81
|
-
# ==== Parameters
|
82
|
-
#
|
83
|
-
# * <tt>:channel</tt> - A hash containing <tt>:host</tt>.
|
84
|
-
# * <tt>:stream</tt> - A stream object.
|
85
|
-
# * <tt>:data</tt> - A data object, usually a String.
|
86
|
-
def simulating_run_loop_with(options={}, &blk) # :yields:
|
87
|
-
channel = options[:channel] || {:host => "192.168.1.20"}
|
88
|
-
stream = options[:stream]
|
89
|
-
data = options[:data]
|
90
|
-
|
91
|
-
blk.call.then.yields(channel, stream, data)
|
92
|
-
[channel, stream, data]
|
93
|
-
end
|
94
69
|
|
95
70
|
module ClassMethods
|
96
|
-
|
97
|
-
|
98
|
-
#
|
99
|
-
# Code defined in the task will be executed automatically on load. (Note the <tt>yields</tt>, see Mocha#yields[http://mocha.rubyforge.org/classes/Mocha/Expectation.html#M000043])
|
100
|
-
#
|
101
|
-
# ==== Parameters
|
102
|
-
#
|
103
|
-
# * <tt>:it</tt> - The description for the current example group.
|
104
|
-
# * <tt>:in</tt> - Specifies the module under test (as well as the namespace the task is defined in). The namespace will be deduced with the downcase of <tt>:in</tt>
|
105
|
-
#
|
106
|
-
# ==== Examples
|
107
|
-
#
|
108
|
-
# for_task :detect, :roles => :app, :in => :Somewhere, :it => "should so something" do
|
109
|
-
# @namespace # refers to the current task under test (in Capistrano tasks are executed on Capistrano::Namespaces::Namespace instances)
|
110
|
-
# @mod # refers to module CapTaffy::Somewhere
|
111
|
-
# end
|
112
|
-
def for_task(task_name, options, &block)
|
113
|
-
description = options.delete(:it)
|
114
|
-
namespace = options.delete(:in)
|
115
|
-
|
71
|
+
def for_task(task_name, options = {}, &block)
|
72
|
+
message = options.delete(:it)
|
116
73
|
context ":#{task_name.to_s} task" do
|
117
74
|
before do
|
118
|
-
@
|
119
|
-
@
|
120
|
-
@
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
@namespace.expects(:task).with(task_name).yields
|
126
|
-
end
|
127
|
-
|
128
|
-
@mod = Module.new # The module under test
|
129
|
-
CapTaffy.const_set(namespace, @mod)
|
75
|
+
@namespace_db = Capistrano::Configuration.instance.namespaces[:db] = mock()
|
76
|
+
@namespace_db.stubs(:desc)
|
77
|
+
@namespace_db.stubs(:task)
|
78
|
+
@namespace_db.expects(:task).with(task_name, options).yields
|
79
|
+
|
80
|
+
@db_mod = Module.new
|
81
|
+
CapTaffy.const_set("Db", @db_mod)
|
130
82
|
end
|
131
83
|
|
132
|
-
it
|
84
|
+
it message, &block
|
133
85
|
|
134
86
|
after do
|
135
|
-
|
136
|
-
CapTaffy.send(:remove_const, const_name)
|
87
|
+
CapTaffy.send(:remove_const, "Db")
|
137
88
|
end
|
138
89
|
end
|
139
90
|
end
|
@@ -141,14 +92,10 @@ module CapistranoHelpers
|
|
141
92
|
end
|
142
93
|
|
143
94
|
module TaffyHelpers
|
144
|
-
def self.included(base)
|
95
|
+
def self.included(base)
|
145
96
|
base.extend TaffyHelpers::ClassMethods
|
146
97
|
end
|
147
98
|
|
148
|
-
# A simple helper for mocking a quick object
|
149
|
-
#
|
150
|
-
# Usage:
|
151
|
-
# taps_client_who(:expects, :do_something)
|
152
99
|
def taps_client_who(method_symbol, *args)
|
153
100
|
client = mock()
|
154
101
|
client.send(method_symbol, *args)
|
@@ -156,16 +103,24 @@ module TaffyHelpers
|
|
156
103
|
end
|
157
104
|
|
158
105
|
module ClassMethods
|
159
|
-
|
160
|
-
|
161
|
-
context "when running db" do
|
106
|
+
def running_taffy_it(message, &blk)
|
107
|
+
context "when running taffy" do
|
162
108
|
before do
|
163
109
|
@capistrano = mock()
|
164
110
|
end
|
165
111
|
|
166
|
-
|
167
|
-
|
168
|
-
|
112
|
+
def run_capistrano_with(*args)
|
113
|
+
@capistrano.expects(:run).with(*args)
|
114
|
+
end
|
115
|
+
|
116
|
+
# invokes one loop of block, passing in channel, stream, data as arguments
|
117
|
+
def simulating_run_loop_with(options={}, &blk)
|
118
|
+
channel = options[:channel] || {:host => "192.168.1.20"}
|
119
|
+
stream = options[:stream]
|
120
|
+
data = options[:data]
|
121
|
+
|
122
|
+
blk.call.then.yields(channel, stream, data)
|
123
|
+
[channel, stream, data]
|
169
124
|
end
|
170
125
|
|
171
126
|
it message, &blk
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hsume2-cap-taffy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henry Hsu
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-09-
|
12
|
+
date: 2009-09-14 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -52,16 +52,6 @@ dependencies:
|
|
52
52
|
- !ruby/object:Gem::Version
|
53
53
|
version: 2.5.1
|
54
54
|
version:
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: mocha
|
57
|
-
type: :development
|
58
|
-
version_requirement:
|
59
|
-
version_requirements: !ruby/object:Gem::Requirement
|
60
|
-
requirements:
|
61
|
-
- - ">="
|
62
|
-
- !ruby/object:Gem::Version
|
63
|
-
version: "0"
|
64
|
-
version:
|
65
55
|
description: Capistrano recipes for deploying databases and other common tasks.
|
66
56
|
email: henry@qlane.com
|
67
57
|
executables: []
|
@@ -78,16 +68,13 @@ files:
|
|
78
68
|
- lib/cap-taffy.rb
|
79
69
|
- lib/cap-taffy/db.rb
|
80
70
|
- lib/cap-taffy/parse.rb
|
81
|
-
- lib/cap-taffy/ssh.rb
|
82
71
|
- spec/cap-taffy/db_spec.rb
|
83
72
|
- spec/cap-taffy/parse_spec.rb
|
84
|
-
- spec/cap-taffy/ssh_spec.rb
|
85
73
|
- spec/cap-taffy_spec.rb
|
86
74
|
- spec/spec.opts
|
87
75
|
- spec/spec_helper.rb
|
88
76
|
has_rdoc: false
|
89
77
|
homepage: http://by.qlane.com
|
90
|
-
licenses:
|
91
78
|
post_install_message:
|
92
79
|
rdoc_options:
|
93
80
|
- --main
|
@@ -109,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
96
|
requirements: []
|
110
97
|
|
111
98
|
rubyforge_project: cap-taffy
|
112
|
-
rubygems_version: 1.
|
99
|
+
rubygems_version: 1.2.0
|
113
100
|
signing_key:
|
114
101
|
specification_version: 3
|
115
102
|
summary: Capistrano recipes for deploying databases (managing database.yml, importing/exporting/transfering databases, etc.)
|
data/lib/cap-taffy/ssh.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), %w[.. cap-taffy]) unless defined?(CapTaffy)
|
2
|
-
|
3
|
-
module CapTaffy::SSH
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
Capistrano::Configuration.instance.load do
|
8
|
-
namespace :ssh do
|
9
|
-
desc <<-DESC
|
10
|
-
Authorize SSH access for local computer on remote computers(s).
|
11
|
-
DESC
|
12
|
-
task :authorize do
|
13
|
-
public_key = File.read(File.expand_path(File.join(%w[~/ .ssh id_rsa.pub]))).chop
|
14
|
-
|
15
|
-
run %Q[if [ ! -f ~/.ssh/authorized_keys ]; then mkdir -p ~/.ssh && touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys; fi && if [ -z "$(grep "^#{public_key}$" ~/.ssh/authorized_keys)" ]; then echo "#{public_key}" >> ~/.ssh/authorized_keys && echo "Public key on '$CAPISTRANO:HOST$' authorized at '#{Time.now.to_s}'"; else echo "Public key on '$CAPISTRANO:HOST$' is already authorized."; fi]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/spec/cap-taffy/ssh_spec.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
-
|
3
|
-
module CapTaffy
|
4
|
-
describe 'SSH' do
|
5
|
-
include CapistranoHelpers
|
6
|
-
|
7
|
-
before do
|
8
|
-
CapTaffy.send(:remove_const, "SSH") rescue nil
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should load in capistrano configuration instance" do;
|
12
|
-
Capistrano::Configuration.instance.expects(:load)
|
13
|
-
|
14
|
-
load 'lib/cap-taffy/ssh.rb'
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should define :db namespace" do
|
18
|
-
Capistrano::Configuration.instance.expects(:namespace).with(:ssh)
|
19
|
-
|
20
|
-
load 'lib/cap-taffy/ssh.rb'
|
21
|
-
end
|
22
|
-
|
23
|
-
def simulating_line(line, &blk)
|
24
|
-
blk.call.then.yields(line)
|
25
|
-
line
|
26
|
-
end
|
27
|
-
|
28
|
-
for_task :authorize, :in => :SSH, :it => "should authorize on each server" do
|
29
|
-
public_key = "ssh-key2\n"
|
30
|
-
File.expects(:read).with(File.expand_path(File.join(%w[~/ .ssh id_rsa.pub]))).returns(public_key)
|
31
|
-
|
32
|
-
run_with(@namespace, anything) # Don't rly wna test bash scripts
|
33
|
-
|
34
|
-
load 'lib/cap-taffy/ssh.rb'
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|