dbcp 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e37c2566e5ac25d166c8fd27df6209e2f83863f1
4
- data.tar.gz: 0960077bc0488bd979f3b97b751a940b3e6f11c4
3
+ metadata.gz: 9c641bd106b4541cdac1d446c797ba2c4ff3f9d5
4
+ data.tar.gz: 0dccc3c0a43466de4d64091afc3c3abb2ad3a386
5
5
  SHA512:
6
- metadata.gz: 0d8b2f092e45700399fbfda1e91cdb0c80205ecf9670b07c5b5996d153ddf9570df48c57278a8427e7ec32350d11148356864f3a0c427d74dc462a45b0747ff0
7
- data.tar.gz: fdde59cd6bd19e060aefd6a1c5999087ebeab62aa2c08c5f4135fadb320979bffb0e8b514256258fc65767646a990b16ec498bbd686aee5741af50b491d70bec
6
+ metadata.gz: 2784736ffcbae106f94c4563e720e6812dc103db3edd75918104ccc9ee089db2957fd16371b99fe5f816887403b730ce91dccc0cc7e8be631cc39b96ef37ee4b
7
+ data.tar.gz: 0de40673b043e993bc02d203f4f73b496afa813bcd0c2369f7edc62196f9d050925882843b00af7e4a85f011c10e221579fd633b214517fa597c1bd7ecd76a33
data/README.md CHANGED
@@ -74,24 +74,33 @@ You can use a database URI in place of an environment name as follows:
74
74
 
75
75
  $ dbcp postgres://my_username:my_pass@db.example.com/my_database development
76
76
 
77
+ ### Capistrano v3
78
+
79
+ If you deploy your application via Capistrano, `dbcp` will lookup and invoke for a matching task name in your capistrano configuration to read the remote ssh and path information for the primary `:db` server role. It will ssh to that server both to read the remote remote `#{deploy_to}/current/config/database.yml` and execute the database export from.
80
+
81
+ Example, with `config/deploy/staging.rb`
82
+
83
+ ```ruby
84
+ server 'staging.example.com', user: 'staging', roles: %w{web app db}
85
+ set :deploy_to, '/www/staging.example.com'
86
+ ```
87
+
88
+ and separately defined `development` environment will allow you to run:
89
+
90
+ $ cap staging development
91
+
77
92
  ## Roadmap
78
93
 
79
94
  The following features are pending:
80
95
 
81
96
  Providers:
82
97
 
83
- - Capistrano task
84
98
  - Heroku, environment name inferred from git remotes
85
99
 
86
- Features:
87
-
88
- - Definable per-tool specific options, e.g. to allow pg_dump to provide a table exclusion list
89
- - URI Provider: specify an remote ssh execution host, perhaps using '@@' as a URI separator?
90
-
91
100
  Refactors:
92
101
 
93
102
  - Handle pg_restore warnings
94
103
  - Better logging
95
104
  - Better help
96
105
 
97
- [Open an issue](https://github.com/gabetax/dbcp/issues) if there's something else you'd like to see supported.
106
+ Please [open an issue](https://github.com/gabetax/dbcp/issues) or send a pull request if you see a weird error, a database or environment definition you want supported, or anything you want to see improved.
data/dbcp.gemspec CHANGED
@@ -22,8 +22,11 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency "net-ssh", "~> 2.8.0"
23
23
  spec.add_dependency "net-sftp", "~> 2.1.2"
24
24
  spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "capistrano", "~> 3.1"
25
26
  spec.add_development_dependency "rspec"
26
27
  spec.add_development_dependency "codeclimate-test-reporter"
27
- spec.add_development_dependency "rake"
28
+ # Rake 10.2.0 conflicts with `TypeError: no implicit conversion of Rake::Task into String`
29
+ # https://github.com/capistrano/capistrano/pull/983
30
+ spec.add_development_dependency "rake", "10.1.1"
28
31
  spec.add_development_dependency "pry"
29
32
  end
@@ -5,8 +5,9 @@ module Dbcp
5
5
  class Environment
6
6
  ENVIRONMENT_PROVIDERS = [
7
7
  DatabaseYamlEnvironmentProvider.new('config/database.yml'),
8
- UriEnvironmentProvider.new
9
- ]
8
+ UriEnvironmentProvider.new,
9
+ (Capistrano3EnvironmentProvider.new if defined?(Capistrano3EnvironmentProvider.new))
10
+ ].compact
10
11
 
11
12
  class << self
12
13
  def find(environment_name)
@@ -0,0 +1,64 @@
1
+ begin
2
+ # Capistrano 3 is built on rake. Capistrano 2 has a totally different API
3
+ gem 'capistrano', '~> 3.0'
4
+ require 'capistrano/all'
5
+
6
+ module Dbcp
7
+ class Capistrano3EnvironmentProvider
8
+ REMOTE_YAML_PATH = 'config/database.yml'
9
+
10
+ # @return [Environment, nil]
11
+ def find(environment_name)
12
+ task = capistrano_application.lookup environment_name
13
+ if task
14
+ build_environment environment_name, task
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ # Capistrano and rake both use a lot of global state. `load_rakefile`
21
+ # loads _ONLY_ to the global `Rake.application` instance. If you load
22
+ # the Capfile twice, the second time comes back empty.
23
+ def capistrano_application
24
+ @@capistrano_application ||= load_capistrano_application
25
+ end
26
+
27
+ def load_capistrano_application
28
+ original_application = Rake.application
29
+
30
+ Rake.application = Capistrano::Application.new
31
+ Rake.application.init
32
+ Rake.application.load_rakefile
33
+
34
+ Rake.application
35
+ end
36
+
37
+
38
+ def build_environment(environment_name, task)
39
+ execution_host = execution_host_from_task task
40
+ Environment.new({
41
+ environment_name: environment_name,
42
+ database: execution_host.remote_database('current/config/database.yml', environment_name),
43
+ execution_host: execution_host
44
+ })
45
+ end
46
+
47
+ def execution_host_from_task(task)
48
+ task.invoke
49
+ cap_env = Capistrano::Configuration.env
50
+ server = Capistrano::Configuration.env.primary(:db)
51
+
52
+ SshExecutionHost.new({
53
+ host: server.hostname,
54
+ port: server.port,
55
+ username: server.user,
56
+ path: cap_env.fetch(:deploy_to)
57
+ })
58
+ end
59
+ end
60
+ end
61
+
62
+ rescue LoadError
63
+ # Class won't exist. Make sure to check `if defined?(Dbcp::CapistranoEnvironmentProvider)`
64
+ end
@@ -33,7 +33,7 @@ module Dbcp
33
33
  database = Database.build(environment_hash)
34
34
  rescue Database::BlankDatabaseDefinition => e
35
35
  if execution_host.remote?
36
- database = Database.build fetch_remote_environment_hash(execution_host)[environment_name]
36
+ database = execution_host.remote_database
37
37
  else
38
38
  raise e
39
39
  end
@@ -46,9 +46,5 @@ module Dbcp
46
46
  })
47
47
  end
48
48
 
49
- def fetch_remote_environment_hash(execution_host)
50
- YAML.load execution_host.download "#{execution_host.path}/#{@database_yaml_path}"
51
- end
52
-
53
49
  end
54
50
  end
@@ -77,5 +77,13 @@ module Dbcp
77
77
  return ssh.upload! source_path, destination_path
78
78
  end
79
79
  end
80
+
81
+ def remote_database(database_yaml_path, environment_name)
82
+ Database.build remote_yaml(database_yaml_path)[environment_name]
83
+ end
84
+
85
+ def remote_yaml(remote_yaml_path)
86
+ YAML.load download("#{path}/#{remote_yaml_path}")
87
+ end
80
88
  end
81
89
  end
data/lib/dbcp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Dbcp
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/dbcp.rb CHANGED
@@ -5,8 +5,9 @@ require 'dbcp/cli'
5
5
  require 'dbcp/database'
6
6
  require 'dbcp/databases/mysql_database'
7
7
  require 'dbcp/databases/postgres_database'
8
- require 'dbcp/environment_providers/uri_environment_provider'
8
+ require 'dbcp/environment_providers/capistrano_3_environment_provider'
9
9
  require 'dbcp/environment_providers/database_yaml_environment_provider'
10
+ require 'dbcp/environment_providers/uri_environment_provider'
10
11
  require 'dbcp/execution_host'
11
12
  require 'dbcp/execution_hosts/local_execution_host'
12
13
  require 'dbcp/execution_hosts/ssh_execution_host'
@@ -0,0 +1,25 @@
1
+ # Load DSL and Setup Up Stages
2
+ require 'capistrano/setup'
3
+
4
+ # Includes default deployment tasks
5
+ require 'capistrano/deploy'
6
+
7
+ # Includes tasks from other gems included in your Gemfile
8
+ #
9
+ # For documentation on these, see for example:
10
+ #
11
+ # https://github.com/capistrano/rvm
12
+ # https://github.com/capistrano/rbenv
13
+ # https://github.com/capistrano/chruby
14
+ # https://github.com/capistrano/bundler
15
+ # https://github.com/capistrano/rails
16
+ #
17
+ # require 'capistrano/rvm'
18
+ # require 'capistrano/rbenv'
19
+ # require 'capistrano/chruby'
20
+ # require 'capistrano/bundler'
21
+ # require 'capistrano/rails/assets'
22
+ # require 'capistrano/rails/migrations'
23
+
24
+ # Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
25
+ Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }
@@ -0,0 +1,10 @@
1
+ # Simple Role Syntax
2
+ # ==================
3
+ # Supports bulk-adding hosts to roles, the primary
4
+ # server in each group is considered to be the first
5
+ # unless any hosts have the primary property set.
6
+ # Don't declare `role :all`, it's a meta role
7
+ role :app, %w{staging_user@app.example.com}
8
+ role :web, %w{staging_user@web.example.com}
9
+ role :db, %w{staging_user@db.example.com}
10
+ set :deploy_to, '/www/staging.example.com/current'
@@ -0,0 +1,58 @@
1
+ # config valid only for Capistrano 3.1
2
+ lock '3.1.0'
3
+
4
+ set :application, 'my_app_name'
5
+ set :repo_url, 'git@example.com:me/my_repo.git'
6
+
7
+ # Default branch is :master
8
+ # ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }
9
+
10
+ # Default deploy_to directory is /var/www/my_app
11
+ # set :deploy_to, '/var/www/my_app'
12
+
13
+ # Default value for :scm is :git
14
+ # set :scm, :git
15
+
16
+ # Default value for :format is :pretty
17
+ # set :format, :pretty
18
+
19
+ # Default value for :log_level is :debug
20
+ # set :log_level, :debug
21
+
22
+ # Default value for :pty is false
23
+ # set :pty, true
24
+
25
+ # Default value for :linked_files is []
26
+ # set :linked_files, %w{config/database.yml}
27
+
28
+ # Default value for linked_dirs is []
29
+ # set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
30
+
31
+ # Default value for default_env is {}
32
+ # set :default_env, { path: "/opt/ruby/bin:$PATH" }
33
+
34
+ # Default value for keep_releases is 5
35
+ # set :keep_releases, 5
36
+
37
+ namespace :deploy do
38
+
39
+ desc 'Restart application'
40
+ task :restart do
41
+ on roles(:app), in: :sequence, wait: 5 do
42
+ # Your restart mechanism here, for example:
43
+ # execute :touch, release_path.join('tmp/restart.txt')
44
+ end
45
+ end
46
+
47
+ after :publishing, :restart
48
+
49
+ after :restart, :clear_cache do
50
+ on roles(:web), in: :groups, limit: 3, wait: 10 do
51
+ # Here we can do anything such as:
52
+ # within release_path do
53
+ # execute :rake, 'cache:clear'
54
+ # end
55
+ end
56
+ end
57
+
58
+ end
@@ -4,9 +4,6 @@ describe Dbcp::Cli do
4
4
  subject { Dbcp::Cli.new silent_stdout }
5
5
  let(:silent_stdout) { '/dev/null' }
6
6
 
7
- extend ExecuteInDirectory
8
- execute_in_directory(File.expand_path('../../../fixtures', __FILE__))
9
-
10
7
  describe "#start" do
11
8
  context "success" do
12
9
  let(:source) { double 'Dbcp::Environment', database: double(adapter: 'postgres'), environment_name: 'staging' }
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dbcp::Capistrano3EnvironmentProvider do
4
+ subject { Dbcp::Capistrano3EnvironmentProvider.new }
5
+
6
+ describe "#find" do
7
+ context "when task exists" do
8
+ let(:remote_database) { double 'Database' }
9
+ it "returns an environment" do
10
+ allow_any_instance_of(Dbcp::SshExecutionHost).to receive(:remote_database) { remote_database }
11
+ environment = subject.find 'staging'
12
+ expect(environment).to be_a Dbcp::Environment
13
+ expect(environment.environment_name).to eq 'staging'
14
+ expect(environment.execution_host).to be_a Dbcp::SshExecutionHost
15
+ expect(environment.execution_host.host).to eq 'db.example.com'
16
+ expect(environment.execution_host.username).to eq 'staging_user'
17
+ expect(environment.execution_host.path).to eq '/www/staging.example.com/current'
18
+ expect(environment.database).to eq remote_database
19
+ end
20
+ end
21
+
22
+ context "when task doesn't exist" do
23
+ specify do
24
+ expect(subject.find('doesnt-exist')).to be_nil
25
+ end
26
+ end
27
+
28
+ context "Capfile does't exist" do
29
+ let(:path) { 'doesnt-exist' }
30
+ specify do
31
+ expect(subject.find('production')).to be_nil
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+ end
@@ -4,9 +4,6 @@ describe Dbcp::DatabaseYamlEnvironmentProvider do
4
4
  subject { Dbcp::DatabaseYamlEnvironmentProvider.new path }
5
5
  let(:path) { 'config/database.yml' }
6
6
 
7
- extend ExecuteInDirectory
8
- execute_in_directory(File.expand_path('../../../../fixtures', __FILE__))
9
-
10
7
  describe "#find" do
11
8
  context "when environment exists" do
12
9
  it "returns an environment" do
@@ -37,15 +34,11 @@ describe Dbcp::DatabaseYamlEnvironmentProvider do
37
34
  end
38
35
 
39
36
  context "without database definition, but with ssh_uri" do
40
- let(:remote_yaml) { File.read remote_yaml_path }
41
- let(:remote_yaml_path) { File.expand_path('../../../../fixtures/config/remote_database.yml', __FILE__) }
37
+ let(:remote_database) { double 'Dbcp::Database' }
42
38
  it "fetches database definition from database.yml on remote host" do
43
- allow_any_instance_of(Dbcp::SshExecutionHost).to receive(:download).with('/www/staging.example.com/current/config/database.yml') { remote_yaml }
39
+ allow_any_instance_of(Dbcp::SshExecutionHost).to receive(:remote_database) { remote_database }
44
40
  environment = subject.find 'staging_ssh_only'
45
- expect(environment.database).to be_a Dbcp::PostgresDatabase
46
- expect(environment.database.database).to eq 'remote_staging_database'
47
- expect(environment.database.username).to eq 'remote_staging_username'
48
- expect(environment.database.password).to eq 'remote_staging_password'
41
+ expect(environment.database).to eq remote_database
49
42
  end
50
43
  end
51
44
  end
@@ -41,5 +41,23 @@ describe Dbcp::SshExecutionHost do
41
41
  end
42
42
  end
43
43
 
44
+ context "remote yaml" do
45
+ let(:local_yaml_path) { File.expand_path('../../../../fixtures/config/remote_database.yml', __FILE__) }
46
+ before { allow(subject).to receive(:download) { File.read local_yaml_path } }
47
+
48
+ describe "#remote_database" do
49
+ it "downloads and parses the YAML" do
50
+ database = subject.remote_database 'config/database.yml', 'staging_ssh_only'
51
+ expect(database).to be_a Dbcp::Database
52
+ expect(database.database).to eq 'remote_staging_database'
53
+ end
54
+ end
55
+
56
+ describe "#remote_yaml" do
57
+ it "downloads and parses the YAML" do
58
+ expect(subject.remote_yaml 'config/database.yml').to have_key('staging_ssh_only')
59
+ end
60
+ end
61
+ end
44
62
 
45
63
  end
data/spec/spec_helper.rb CHANGED
@@ -7,3 +7,6 @@ require_relative '../lib/dbcp'
7
7
 
8
8
  Dir[File.expand_path("../support/**/*.rb", __FILE__)].sort.each { |f| require f }
9
9
 
10
+ RSpec.configure do |config|
11
+ config.before(:suite) { Dir.chdir File.expand_path('../fixtures', __FILE__) }
12
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabe Martin-Dempesy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-09 00:00:00.000000000 Z
11
+ date: 2014-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: virtus
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: capistrano
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '3.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '3.1'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -98,16 +112,16 @@ dependencies:
98
112
  name: rake
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
- - - '>='
115
+ - - '='
102
116
  - !ruby/object:Gem::Version
103
- version: '0'
117
+ version: 10.1.1
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
- - - '>='
122
+ - - '='
109
123
  - !ruby/object:Gem::Version
110
- version: '0'
124
+ version: 10.1.1
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: pry
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -145,19 +159,24 @@ files:
145
159
  - lib/dbcp/databases/mysql_database.rb
146
160
  - lib/dbcp/databases/postgres_database.rb
147
161
  - lib/dbcp/environment.rb
162
+ - lib/dbcp/environment_providers/capistrano_3_environment_provider.rb
148
163
  - lib/dbcp/environment_providers/database_yaml_environment_provider.rb
149
164
  - lib/dbcp/environment_providers/uri_environment_provider.rb
150
165
  - lib/dbcp/execution_host.rb
151
166
  - lib/dbcp/execution_hosts/local_execution_host.rb
152
167
  - lib/dbcp/execution_hosts/ssh_execution_host.rb
153
168
  - lib/dbcp/version.rb
169
+ - spec/fixtures/Capfile
154
170
  - spec/fixtures/config/database.yml
171
+ - spec/fixtures/config/deploy.rb
172
+ - spec/fixtures/config/deploy/staging.rb
155
173
  - spec/fixtures/config/remote_database.yml
156
174
  - spec/lib/dbcp/cli_spec.rb
157
175
  - spec/lib/dbcp/database_snapshot_file_spec.rb
158
176
  - spec/lib/dbcp/database_spec.rb
159
177
  - spec/lib/dbcp/databases/mysql_database_spec.rb
160
178
  - spec/lib/dbcp/databases/postgres_database_spec.rb
179
+ - spec/lib/dbcp/environment_providers/capistrano_3_environment_provider_spec.rb
161
180
  - spec/lib/dbcp/environment_providers/database_yaml_environment_provider_spec.rb
162
181
  - spec/lib/dbcp/environment_providers/uri_environment_provider_spec.rb
163
182
  - spec/lib/dbcp/environment_spec.rb
@@ -166,7 +185,6 @@ files:
166
185
  - spec/lib/dbcp/execution_hosts/ssh_execution_host_spec.rb
167
186
  - spec/spec_helper.rb
168
187
  - spec/support/.keep
169
- - spec/support/execute_in_directory.rb
170
188
  homepage: https://github.com/gabetax/dbcp
171
189
  licenses:
172
190
  - MIT
@@ -192,13 +210,17 @@ signing_key:
192
210
  specification_version: 4
193
211
  summary: ''
194
212
  test_files:
213
+ - spec/fixtures/Capfile
195
214
  - spec/fixtures/config/database.yml
215
+ - spec/fixtures/config/deploy.rb
216
+ - spec/fixtures/config/deploy/staging.rb
196
217
  - spec/fixtures/config/remote_database.yml
197
218
  - spec/lib/dbcp/cli_spec.rb
198
219
  - spec/lib/dbcp/database_snapshot_file_spec.rb
199
220
  - spec/lib/dbcp/database_spec.rb
200
221
  - spec/lib/dbcp/databases/mysql_database_spec.rb
201
222
  - spec/lib/dbcp/databases/postgres_database_spec.rb
223
+ - spec/lib/dbcp/environment_providers/capistrano_3_environment_provider_spec.rb
202
224
  - spec/lib/dbcp/environment_providers/database_yaml_environment_provider_spec.rb
203
225
  - spec/lib/dbcp/environment_providers/uri_environment_provider_spec.rb
204
226
  - spec/lib/dbcp/environment_spec.rb
@@ -207,4 +229,3 @@ test_files:
207
229
  - spec/lib/dbcp/execution_hosts/ssh_execution_host_spec.rb
208
230
  - spec/spec_helper.rb
209
231
  - spec/support/.keep
210
- - spec/support/execute_in_directory.rb
@@ -1,10 +0,0 @@
1
- module ExecuteInDirectory
2
- def execute_in_directory(path)
3
- around(:each) do |example|
4
- old = Dir.pwd
5
- Dir.chdir path
6
- example.run
7
- Dir.chdir old
8
- end
9
- end
10
- end