hsume2-cap-taffy 0.0.2 → 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/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
|