delayed_job-ssh_remote_worker 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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +77 -0
- data/Rakefile +2 -0
- data/delayed_job-ssh_remote_worker.gemspec +29 -0
- data/lib/delayed/ssh_remote_worker.rb +116 -0
- data/lib/delayed/ssh_remote_worker/railtie.rb +16 -0
- data/lib/delayed/ssh_remote_worker/tasks.rb +60 -0
- data/lib/delayed/ssh_remote_worker/version.rb +7 -0
- data/lib/delayed_job-ssh_remote_worker.rb +2 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f194bed80798938fa56694242c4b189775a1cb9c
|
4
|
+
data.tar.gz: 8781173a79be3b715016a9aecf1c6aaeca650172
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d1f1e47cc0c9106a5eb0138acf79288b9a55f6bd3eac58ae7d689a8382151cc98a817386908df2fb8c6f9a105a900f4e45e0f6135018ceaf0b1e101581b61020
|
7
|
+
data.tar.gz: d8848fd43a2e81f200840b552bf9f7bf8a29ce2a0a3b7dd03cac8f9c56a1c4b258e064e174c40340ef85ca122657ba811c6c117761110a7d8310918d6cfbf619
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Alex McHale
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# DelayedJob::SshRemoteWorker
|
2
|
+
|
3
|
+
This gem provides a rake task for executing DelayedJob backed by ActiveRecord
|
4
|
+
remotely over an SSH connection.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'delayed_job-ssh_remote_worker'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install delayed_job-ssh_remote_worker
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
Require the gem and either create a `config/remote_database.yml` file that
|
23
|
+
contains a record such as below:
|
24
|
+
|
25
|
+
```yaml
|
26
|
+
production:
|
27
|
+
ssh_hostname: "example.com"
|
28
|
+
ssh_username: "app"
|
29
|
+
adapter: "postgresql"
|
30
|
+
encoding: "unicode"
|
31
|
+
database: "dbname"
|
32
|
+
username: "dbuser"
|
33
|
+
password: "pa$$word"
|
34
|
+
```
|
35
|
+
|
36
|
+
Alternatively, the `ssh_hostname` and `ssh_username` can be simply added to an
|
37
|
+
entry in `config/database.yml`. You may specify the SSH port number as `ssh_port`.
|
38
|
+
|
39
|
+
The `config/remote_database.yml` top level keys can have names other than your
|
40
|
+
`Rails.env`. For example:
|
41
|
+
|
42
|
+
```yaml
|
43
|
+
fast_server:
|
44
|
+
ssh_hostname: "example.com"
|
45
|
+
ssh_username: "app"
|
46
|
+
ssh_port: 20022
|
47
|
+
adapter: "postgresql"
|
48
|
+
encoding: "unicode"
|
49
|
+
database: "dbname"
|
50
|
+
username: "dbuser"
|
51
|
+
password: "pa$$word"
|
52
|
+
|
53
|
+
slow_server:
|
54
|
+
ssh_hostname: "example2.com"
|
55
|
+
ssh_username: "app"
|
56
|
+
adapter: "mysql"
|
57
|
+
encoding: "unicode"
|
58
|
+
database: "dbname"
|
59
|
+
username: "dbuser"
|
60
|
+
password: "pa$$word"
|
61
|
+
```
|
62
|
+
|
63
|
+
The key can then be specified in `ENV['REMOTE_ENV']` thusly:
|
64
|
+
|
65
|
+
```bash
|
66
|
+
RAILS_ENV=production REMOTE_ENV=fast_server bundle exec rake jobs:remote_workoff
|
67
|
+
```
|
68
|
+
|
69
|
+
If `ENV['REMOTE_ENV']` is not set, `delayed_job-ssh_remote_worker` will default to `Rails.env`.
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
1. Fork it ( https://github.com/alexmchale/delayed_job-ssh_remote_worker/fork )
|
74
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
75
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
76
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
77
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'delayed/ssh_remote_worker/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
|
9
|
+
spec.name = "delayed_job-ssh_remote_worker"
|
10
|
+
spec.version = DelayedJob::SshRemoteWorker::VERSION
|
11
|
+
spec.authors = ["Alex McHale"]
|
12
|
+
spec.email = ["alex@anticlever.com"]
|
13
|
+
spec.summary = %q{Run DelayedJob queues over SSH in a remote database}
|
14
|
+
spec.description = %q{Provides a few rake tasks to run DelayedJob jobs on a remote server over SSH}
|
15
|
+
spec.homepage = "http://github.com/alexmchale/delayed_job-ssh_remote_worker"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0")
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_runtime_dependency "delayed_job_active_record", ">= 3.0.0", "< 4.2.0"
|
24
|
+
spec.add_runtime_dependency "net-ssh-gateway", "~> 1.2"
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.3"
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require "delayed/ssh_remote_worker/version"
|
2
|
+
require "net/ssh/gateway"
|
3
|
+
|
4
|
+
module Delayed
|
5
|
+
class SshRemoteWorker
|
6
|
+
|
7
|
+
attr_reader :remote_ssh_username, :remote_ssh_hostname, :remote_ssh_port
|
8
|
+
attr_reader :remote_db_hostname, :remote_db_port
|
9
|
+
attr_reader :local_db_hostname, :local_db_port
|
10
|
+
attr_reader :gateway_ssh, :gateway_port
|
11
|
+
attr_reader :gateway_in_rd, :gateway_in_wr
|
12
|
+
attr_reader :gateway_out_rd, :gateway_out_wr
|
13
|
+
attr_reader :child
|
14
|
+
attr_reader :config
|
15
|
+
|
16
|
+
def initialize(config)
|
17
|
+
@config = Hash[config.map { |k, v| [ k.to_sym, v ] }]
|
18
|
+
@debug = !!@config[:ssh_debug]
|
19
|
+
|
20
|
+
@remote_ssh_username = @config[:ssh_username]
|
21
|
+
@remote_ssh_hostname = @config[:ssh_hostname]
|
22
|
+
@remote_ssh_port = @config[:ssh_port].to_i
|
23
|
+
@remote_ssh_port = 22 if remote_ssh_port <= 0
|
24
|
+
|
25
|
+
@remote_db_hostname = @config[:host].to_s.strip
|
26
|
+
@remote_db_hostname = "localhost" if remote_db_hostname == ""
|
27
|
+
@remote_db_port = @config[:port].to_i
|
28
|
+
@remote_db_port = default_port_number(@config[:adapter]) if remote_db_port <= 0
|
29
|
+
|
30
|
+
@local_db_hostname = "127.0.0.1"
|
31
|
+
@local_db_port = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_port_tunnel
|
35
|
+
# Create two pipes - one will be used to get the port number from the child
|
36
|
+
# process, the other will be used to tell the child process when it's time
|
37
|
+
# to exit.
|
38
|
+
( @gateway_in_rd , @gateway_in_wr ) = IO.pipe
|
39
|
+
( @gateway_out_rd , @gateway_out_wr ) = IO.pipe
|
40
|
+
|
41
|
+
# The child process will establish the SSH connection to the database server.
|
42
|
+
@child = fork {
|
43
|
+
debug "CHILD: Tunneling to #{ remote_db_hostname }:#{ remote_db_port } on #{ remote_ssh_username }@#{ remote_ssh_hostname }:#{ remote_ssh_port }."
|
44
|
+
|
45
|
+
@gateway_ssh = Net::SSH::Gateway.new(remote_ssh_hostname, remote_ssh_username, port: remote_ssh_port)
|
46
|
+
@gateway_port = gateway_ssh.open(remote_db_hostname, remote_db_port)
|
47
|
+
|
48
|
+
debug "CHILD: Notifying parent process of gateway port number #{ gateway_port }."
|
49
|
+
|
50
|
+
gateway_out_rd.close
|
51
|
+
gateway_out_wr.write(gateway_port.to_s)
|
52
|
+
gateway_out_wr.close
|
53
|
+
|
54
|
+
debug "CHILD: Waiting for parent to close pipe."
|
55
|
+
|
56
|
+
gateway_in_wr.close
|
57
|
+
gateway_in_rd.read
|
58
|
+
gateway_in_rd.close
|
59
|
+
|
60
|
+
debug "CHILD: Parent closed pipe. Exiting."
|
61
|
+
|
62
|
+
gateway_ssh.shutdown!
|
63
|
+
}
|
64
|
+
|
65
|
+
# Get the port number back from the child process once the SSH connection is established.
|
66
|
+
debug "PARENT: Reading port number from child."
|
67
|
+
gateway_out_wr.close
|
68
|
+
@local_db_port = Integer(gateway_out_rd.read)
|
69
|
+
gateway_out_rd.close
|
70
|
+
|
71
|
+
# Log and proceed with the next task.
|
72
|
+
debug "PARENT: Received port number #{ gateway_port } from child. Proceeding with execution."
|
73
|
+
end
|
74
|
+
|
75
|
+
def connect_to_tunneled_database
|
76
|
+
# Load just ActiveRecord. Do this before any part of the native Rails project is loaded.
|
77
|
+
require "active_record"
|
78
|
+
|
79
|
+
# Connect to the remote Postgres database.
|
80
|
+
ActiveRecord::Base.establish_connection(activerecord_config)
|
81
|
+
|
82
|
+
# Log a simple query just to verify that we actually have a connection.
|
83
|
+
debug "Connected to remote Postgres. Found #{ User.count } users in the remote database."
|
84
|
+
end
|
85
|
+
|
86
|
+
def destroy_port_tunnel
|
87
|
+
# Close the pipe with the gateway, indicating that it should close.
|
88
|
+
debug "PARENT: Closing pipe with child to terminate gateway."
|
89
|
+
gateway_in_wr.close
|
90
|
+
gateway_in_rd.close
|
91
|
+
Process.wait(child)
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def default_port_number(adapter)
|
97
|
+
case adapter.to_s.strip
|
98
|
+
when /mysql/i then 3306
|
99
|
+
when /postgres/i then 5432
|
100
|
+
else raise "no known default port number for adapter #{ adapter.inspect }"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def activerecord_config
|
105
|
+
config.merge({
|
106
|
+
:host => local_db_hostname ,
|
107
|
+
:port => local_db_port ,
|
108
|
+
})
|
109
|
+
end
|
110
|
+
|
111
|
+
def debug(message)
|
112
|
+
@debug and puts(message)
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'delayed/ssh_remote_worker'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module Delayed
|
5
|
+
class SshRemoteWorker
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
|
8
|
+
railtie_name :delayed_job_ssh_remote_worker
|
9
|
+
|
10
|
+
rake_tasks do
|
11
|
+
load "delayed/ssh_remote_worker/tasks.rb"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
namespace :jobs do
|
2
|
+
|
3
|
+
task :create_port_tunnel do
|
4
|
+
load_yaml = -> filename {
|
5
|
+
filename =
|
6
|
+
if defined?(Rails)
|
7
|
+
Rails.root.join("config", filename)
|
8
|
+
else
|
9
|
+
File.join("config", filename)
|
10
|
+
end
|
11
|
+
|
12
|
+
if File.file? filename
|
13
|
+
YAML.load File.read filename
|
14
|
+
end
|
15
|
+
}
|
16
|
+
|
17
|
+
get_hash = -> hash, key {
|
18
|
+
hash2 = hash[key.to_s.strip]
|
19
|
+
|
20
|
+
if hash2.kind_of? Hash
|
21
|
+
hash2
|
22
|
+
else
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
}
|
26
|
+
|
27
|
+
config = load_yaml["remote_database.yml"] || load_yaml["database.yml"]
|
28
|
+
config = get_hash[config, ENV["REMOTE_ENV"]]
|
29
|
+
config = get_hash[config, Rails.env.to_s]
|
30
|
+
|
31
|
+
$ssh_remote_worker = Delayed::SshRemoteWorker.new(config)
|
32
|
+
$ssh_remote_worker and $ssh_remote_worker.create_port_tunnel
|
33
|
+
end
|
34
|
+
|
35
|
+
task :connect_to_tunneled_database do
|
36
|
+
$ssh_remote_worker and $ssh_remote_worker.connect_to_tunneled_database
|
37
|
+
end
|
38
|
+
|
39
|
+
task :destroy_port_tunnel do
|
40
|
+
$ssh_remote_worker and $ssh_remote_worker.destroy_port_tunnel
|
41
|
+
$ssh_remote_worker = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Start a remote delayed_job worker"
|
45
|
+
task :remote_work => %w(
|
46
|
+
jobs:create_port_tunnel
|
47
|
+
jobs:connect_to_tunneled_database
|
48
|
+
jobs:work
|
49
|
+
jobs:destroy_port_tunnel
|
50
|
+
)
|
51
|
+
|
52
|
+
desc "Start a remote delayed_job worker and exit when all available jobs are complete"
|
53
|
+
task :remote_workoff => %w(
|
54
|
+
jobs:create_port_tunnel
|
55
|
+
jobs:connect_to_tunneled_database
|
56
|
+
jobs:workoff
|
57
|
+
jobs:destroy_port_tunnel
|
58
|
+
)
|
59
|
+
|
60
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: delayed_job-ssh_remote_worker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alex McHale
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: delayed_job_active_record
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.0.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 4.2.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.0.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 4.2.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: net-ssh-gateway
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.2'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.2'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: bundler
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.6'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.6'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rake
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '10.3'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '10.3'
|
75
|
+
description: Provides a few rake tasks to run DelayedJob jobs on a remote server over
|
76
|
+
SSH
|
77
|
+
email:
|
78
|
+
- alex@anticlever.com
|
79
|
+
executables: []
|
80
|
+
extensions: []
|
81
|
+
extra_rdoc_files: []
|
82
|
+
files:
|
83
|
+
- ".gitignore"
|
84
|
+
- Gemfile
|
85
|
+
- LICENSE.txt
|
86
|
+
- README.md
|
87
|
+
- Rakefile
|
88
|
+
- delayed_job-ssh_remote_worker.gemspec
|
89
|
+
- lib/delayed/ssh_remote_worker.rb
|
90
|
+
- lib/delayed/ssh_remote_worker/railtie.rb
|
91
|
+
- lib/delayed/ssh_remote_worker/tasks.rb
|
92
|
+
- lib/delayed/ssh_remote_worker/version.rb
|
93
|
+
- lib/delayed_job-ssh_remote_worker.rb
|
94
|
+
homepage: http://github.com/alexmchale/delayed_job-ssh_remote_worker
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.2.2
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Run DelayedJob queues over SSH in a remote database
|
118
|
+
test_files: []
|