deploy-agent 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/bin/deploy-agent +5 -0
- data/lib/deploy_agent.rb +14 -0
- data/lib/deploy_agent/agent.rb +36 -0
- data/lib/deploy_agent/certificate_manager.rb +85 -0
- data/lib/deploy_agent/cli.rb +100 -0
- data/lib/deploy_agent/destination_connection.rb +106 -0
- data/lib/deploy_agent/server_connection.rb +165 -0
- metadata +80 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b5fedd1d54542b1fa80f5f083698d4fac13200fd
|
4
|
+
data.tar.gz: f2783980bf24d0f54aeef1f2b7894c5f37b33cbb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 986c809ff4bc0655bc586599a14e84cc7708c4f9f2a7f77fec3b57054336af2ec4e0038847483687fb1a85a8bd06f69d9056d0394c67ce0552f9d99c46cca613
|
7
|
+
data.tar.gz: 9b3547acefee6e6bd3d4dca8c85baf15aaa791382e75796a413b4bec689cc147711083965bf1d70f3177d65e039fce67d76e9365b514cd7a440e4d76ddbccd0d
|
data/bin/deploy-agent
ADDED
data/lib/deploy_agent.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'deploy_agent/certificate_manager'
|
2
|
+
require 'deploy_agent/server_connection'
|
3
|
+
require 'deploy_agent/destination_connection'
|
4
|
+
require 'deploy_agent/cli'
|
5
|
+
require 'deploy_agent/agent'
|
6
|
+
|
7
|
+
module DeployAgent
|
8
|
+
CONFIG_PATH = File.expand_path('~/.deploy')
|
9
|
+
CERTIFICATE_PATH = File.expand_path('~/.deploy/agent.crt')
|
10
|
+
KEY_PATH = File.expand_path('~/.deploy/agent.key')
|
11
|
+
CA_PATH = File.expand_path('~/.deploy/ca.crt')
|
12
|
+
PID_PATH = File.expand_path('~/.deploy/agent.pid')
|
13
|
+
LOG_PATH = File.expand_path('~/.deploy/agent.log')
|
14
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
gem 'nio4r', '1.2.1'
|
2
|
+
require 'nio'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module DeployAgent
|
6
|
+
class Agent
|
7
|
+
|
8
|
+
def run
|
9
|
+
nio_selector = NIO::Selector.new
|
10
|
+
target = ENV['DEPLOY_AGENT_PROXY_IP'] || 'agent.deployhq.com'
|
11
|
+
ServerConnection.new(self, target, nio_selector, !ENV['DEPLOY_AGENT_NOVERIFY'])
|
12
|
+
|
13
|
+
loop do
|
14
|
+
nio_selector.select do |monitor|
|
15
|
+
monitor.value.rx_data if monitor.readable?
|
16
|
+
monitor.value.tx_data if monitor.writeable?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
rescue ServerConnection::ServerDisconnected
|
20
|
+
retry
|
21
|
+
end
|
22
|
+
|
23
|
+
def logger
|
24
|
+
@logger ||= begin
|
25
|
+
if $background
|
26
|
+
logger = Logger.new(LOG_PATH, 5, 10240)
|
27
|
+
logger.level = Logger::INFO
|
28
|
+
logger
|
29
|
+
else
|
30
|
+
Logger.new(STDOUT)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
gem 'rb-readline', '0.5.4'
|
2
|
+
require 'readline'
|
3
|
+
require 'net/https'
|
4
|
+
require 'json'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
module DeployAgent
|
8
|
+
class CertificateManager
|
9
|
+
|
10
|
+
def certificate_uri
|
11
|
+
URI(ENV['DEPLOY_AGENT_CERTIFICATE_URL'] || 'https://api.deployhq.com/api/v1/agents/create')
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate_certificate
|
15
|
+
puts 'This tool will assist you in generating a certificate for your Deploy agent.'
|
16
|
+
puts
|
17
|
+
if File.file?(CERTIFICATE_PATH)
|
18
|
+
puts "***************************** WARNING *****************************"
|
19
|
+
puts "The Deploy agent has already been configured. Are you sure you wish"
|
20
|
+
puts "to remove the existing certificate and generate a new one?"
|
21
|
+
puts
|
22
|
+
Readline.completion_proc = Proc.new {}
|
23
|
+
begin
|
24
|
+
response = Readline.readline("Remove existing certificate? [no]: ", true)
|
25
|
+
rescue Interrupt => e
|
26
|
+
puts
|
27
|
+
Process.exit(1)
|
28
|
+
end
|
29
|
+
unless response == 'yes'
|
30
|
+
Process.exit(1)
|
31
|
+
end
|
32
|
+
puts
|
33
|
+
end
|
34
|
+
puts 'Please enter a name for this agent.'
|
35
|
+
Readline.completion_proc = Proc.new {}
|
36
|
+
begin
|
37
|
+
name = Readline.readline("Agent Name: ", true)
|
38
|
+
rescue Interrupt => e
|
39
|
+
puts
|
40
|
+
Process.exit(1)
|
41
|
+
end
|
42
|
+
if name.length < 2
|
43
|
+
puts "Name must be at least 2 characters."
|
44
|
+
Process.exit(1)
|
45
|
+
else
|
46
|
+
uri = certificate_uri
|
47
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
|
48
|
+
request = Net::HTTP::Post.new(uri)
|
49
|
+
request.body = {:name => name}.to_json
|
50
|
+
request['Content-Type'] = 'application/json'
|
51
|
+
response = http.request request
|
52
|
+
response_hash = JSON.parse(response.body)
|
53
|
+
if response_hash['status'] == 'success'
|
54
|
+
FileUtils.mkdir_p(CONFIG_PATH)
|
55
|
+
File.write(CA_PATH, response_hash['data']['ca'])
|
56
|
+
File.write(CERTIFICATE_PATH, response_hash['data']['certificate'])
|
57
|
+
File.write(KEY_PATH, response_hash['data']['private_key'])
|
58
|
+
puts
|
59
|
+
puts "Certificate has been successfully generated and installed."
|
60
|
+
puts
|
61
|
+
puts "You can now associate this Agent with your Deploy account."
|
62
|
+
puts "Browse to Settings -> Agents in your account and enter the code below:"
|
63
|
+
puts
|
64
|
+
puts " >> #{response_hash['data']['claim_code']} <<"
|
65
|
+
puts
|
66
|
+
puts "You can start the agent using the following command:"
|
67
|
+
puts
|
68
|
+
puts " # deploy-agent start"
|
69
|
+
puts
|
70
|
+
else
|
71
|
+
puts
|
72
|
+
puts "An error occurred obtaining a certificate."
|
73
|
+
puts "Please contact support, quoting the debug information below:"
|
74
|
+
puts
|
75
|
+
puts response.inspect
|
76
|
+
puts response.body
|
77
|
+
puts
|
78
|
+
Process.exit(1)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module DeployAgent
|
2
|
+
class CLI
|
3
|
+
|
4
|
+
def dispatch(arguments)
|
5
|
+
methods = self.public_methods(false).delete_if { |n| n == :dispatch }.sort
|
6
|
+
if arguments[0] && methods.include?(arguments[0].to_sym)
|
7
|
+
public_send(arguments[0])
|
8
|
+
else
|
9
|
+
puts "Usage: deploy-agent [#{methods.join('|')}]"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup
|
14
|
+
CertificateManager.new.generate_certificate
|
15
|
+
end
|
16
|
+
|
17
|
+
def ensure_configured
|
18
|
+
unless File.file?(CERTIFICATE_PATH)
|
19
|
+
puts 'Deploy agent is not configured. Please run "deploy-agent setup" first.'
|
20
|
+
Process.exit(1)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def restart
|
25
|
+
stop
|
26
|
+
while(is_running?)
|
27
|
+
sleep 0.5
|
28
|
+
end
|
29
|
+
start
|
30
|
+
end
|
31
|
+
|
32
|
+
def start
|
33
|
+
if is_running?
|
34
|
+
puts "Deploy agent already running. Process ID #{pid_from_file}"
|
35
|
+
Process.exit(1)
|
36
|
+
else
|
37
|
+
ensure_configured
|
38
|
+
pid = fork do
|
39
|
+
$background = true
|
40
|
+
write_pid
|
41
|
+
run
|
42
|
+
end
|
43
|
+
puts "Deploy agent started. Process ID #{pid}"
|
44
|
+
Process.detach(pid)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def stop
|
49
|
+
if is_running?
|
50
|
+
pid = pid_from_file
|
51
|
+
Process.kill('TERM', pid)
|
52
|
+
puts "Deploy agent stopped. Process ID #{pid}"
|
53
|
+
else
|
54
|
+
puts "Deploy agent is not running"
|
55
|
+
Process.exit(1)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def status
|
60
|
+
if is_running?
|
61
|
+
puts "Deploy agent is running. PID #{pid_from_file}"
|
62
|
+
else
|
63
|
+
puts "Deploy agent is not running."
|
64
|
+
Process.exit(1)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def run
|
69
|
+
ensure_configured
|
70
|
+
Agent.new.run
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def is_running?
|
76
|
+
if pid = pid_from_file
|
77
|
+
Process.kill(0, pid)
|
78
|
+
true
|
79
|
+
else
|
80
|
+
false
|
81
|
+
end
|
82
|
+
rescue Errno::ESRCH
|
83
|
+
false
|
84
|
+
rescue Errno::EPERM
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
def pid_from_file
|
89
|
+
File.read(PID_PATH).to_i
|
90
|
+
rescue Errno::ENOENT
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def write_pid
|
95
|
+
File.open(PID_PATH, 'w') { |f| f.write Process.pid.to_s }
|
96
|
+
at_exit { File.delete(PID_PATH) if File.exists?(PID_PATH) }
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module DeployAgent
|
4
|
+
# The DestinationConnection class managea a connection to a backend server
|
5
|
+
class DestinationConnection
|
6
|
+
attr_reader :socket
|
7
|
+
|
8
|
+
# Create a connection to a backend server
|
9
|
+
def initialize(host, port, id, nio_selector, server_connection)
|
10
|
+
@agent = server_connection.agent
|
11
|
+
@id = id
|
12
|
+
@nio_selector = nio_selector
|
13
|
+
@server_connection = server_connection
|
14
|
+
|
15
|
+
# Check the IP address and create a socket
|
16
|
+
ipaddr = IPAddr.new(host)
|
17
|
+
if ipaddr.ipv4?
|
18
|
+
@tcp_socket = Socket.new(Socket::Constants::AF_INET, Socket::Constants::SOCK_STREAM, 0)
|
19
|
+
else
|
20
|
+
@tcp_socket = Socket.new(Socket::Constants::AF_INET6, Socket::Constants::SOCK_STREAM, 0)
|
21
|
+
end
|
22
|
+
# Begin the connection attempt in the background
|
23
|
+
@sockaddr = Socket.sockaddr_in(port.to_i, host.to_s)
|
24
|
+
begin
|
25
|
+
@tcp_socket.connect_nonblock(@sockaddr)
|
26
|
+
# We don't expect to get here, but it's OK if we do
|
27
|
+
@status = :connected
|
28
|
+
@nio_monitor = @nio_selector.register(@tcp_socket, :r)
|
29
|
+
rescue IO::WaitWritable
|
30
|
+
# This is expected, we will get a callback when the connection completes
|
31
|
+
@status = :connecting
|
32
|
+
@nio_monitor = @nio_selector.register(@tcp_socket, :w)
|
33
|
+
end
|
34
|
+
@nio_monitor.value = self
|
35
|
+
|
36
|
+
# Set up a send buffer
|
37
|
+
@tx_buffer = String.new.force_encoding('BINARY')
|
38
|
+
end
|
39
|
+
|
40
|
+
# Queue data to be send to the backend
|
41
|
+
def send_data(data)
|
42
|
+
@tx_buffer << data
|
43
|
+
@nio_monitor.interests = :rw
|
44
|
+
end
|
45
|
+
|
46
|
+
def tx_data
|
47
|
+
# This might get called when there's data to send, but also
|
48
|
+
# when a connections completes or fails.
|
49
|
+
if @status == :connecting
|
50
|
+
begin
|
51
|
+
@tcp_socket.connect_nonblock(@sockaddr)
|
52
|
+
rescue IO::WaitWritable
|
53
|
+
# This shouldn't happen. If it does, ignore it and
|
54
|
+
# wait a bit longer until the connection completes
|
55
|
+
return
|
56
|
+
rescue => e
|
57
|
+
@agent.logger.info "[#{@id}] Connection failed: #{e.message.to_s}"
|
58
|
+
# Something went wrong connecting, inform the Deploy Server
|
59
|
+
close
|
60
|
+
@server_connection.send_connection_error(@id, e.message.to_s)
|
61
|
+
return
|
62
|
+
end
|
63
|
+
@agent.logger.info "[#{@id}] Connected to destination"
|
64
|
+
@server_connection.send_connection_success(@id)
|
65
|
+
@status = :connected
|
66
|
+
end
|
67
|
+
if @status == :connected && @tx_buffer.bytesize > 0
|
68
|
+
bytes_sent = @tcp_socket.write_nonblock(@tx_buffer)
|
69
|
+
if bytes_sent >= @tx_buffer.bytesize
|
70
|
+
@tx_buffer = String.new.force_encoding('BINARY')
|
71
|
+
else
|
72
|
+
@tx_buffer = @tx_buffer[bytes_sent..-1]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
if @status == :connected && @tx_buffer.bytesize == 0
|
76
|
+
# Nothing more to send, wait for inbound data only
|
77
|
+
@nio_monitor.interests = :r
|
78
|
+
end
|
79
|
+
rescue Errno::ECONNRESET
|
80
|
+
# The backend has closed the connection. Inform the Deploy server.
|
81
|
+
@server_connection.send_connection_close(@id)
|
82
|
+
# Ensure everything is tidied up
|
83
|
+
close
|
84
|
+
end
|
85
|
+
|
86
|
+
def rx_data
|
87
|
+
# Received data from backend. Pass this along to the Deploy server
|
88
|
+
data = @tcp_socket.readpartial(10240)
|
89
|
+
@agent.logger.debug "[#{@id}] #{data.bytesize} bytes received from destination"
|
90
|
+
@server_connection.send_data(@id, data)
|
91
|
+
rescue EOFError, Errno::ECONNRESET
|
92
|
+
@agent.logger.info "[#{@id}] Destination closed connection"
|
93
|
+
# The backend has closed the connection. Inform the Deploy server.
|
94
|
+
@server_connection.send_connection_close(@id)
|
95
|
+
# Ensure everything is tidied up
|
96
|
+
close
|
97
|
+
end
|
98
|
+
|
99
|
+
def close
|
100
|
+
@nio_selector.deregister(@tcp_socket)
|
101
|
+
@server_connection.destination_connections.delete(@id)
|
102
|
+
@tcp_socket.close
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'ipaddr'
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
module DeployAgent
|
6
|
+
# The ServerConnection class deals with all communication with the Deploy server
|
7
|
+
class ServerConnection
|
8
|
+
class ServerDisconnected < StandardError;end
|
9
|
+
attr_reader :destination_connections, :agent
|
10
|
+
attr_writer :nio_monitor
|
11
|
+
|
12
|
+
# Create a secure TLS connection to the Deploy server
|
13
|
+
def initialize(agent, server_host, nio_selector, check_certificate=true)
|
14
|
+
@agent = agent
|
15
|
+
@agent.logger.info "Attempting to connect to #{server_host}"
|
16
|
+
@destination_connections = {}
|
17
|
+
@nio_selector = nio_selector
|
18
|
+
|
19
|
+
# Create a TCP socket to the Deploy server
|
20
|
+
@tcp_socket = TCPSocket.new(server_host, 7777)
|
21
|
+
|
22
|
+
# Configure an OpenSSL context with server vertification
|
23
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
24
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
25
|
+
# Load the agent certificate and key used to authenticate this agent
|
26
|
+
ctx.cert = OpenSSL::X509::Certificate.new(File.read(CERTIFICATE_PATH))
|
27
|
+
ctx.key = OpenSSL::PKey::RSA.new(File.read(KEY_PATH))
|
28
|
+
# Load the Deploy CA used to verify the server
|
29
|
+
ctx.ca_file = CA_PATH
|
30
|
+
|
31
|
+
# Create the secure connection
|
32
|
+
@socket = OpenSSL::SSL::SSLSocket.new(@tcp_socket, ctx)
|
33
|
+
@socket.connect
|
34
|
+
# Check the remote certificate
|
35
|
+
@socket.post_connection_check(server_host) if check_certificate
|
36
|
+
# Create send and receive buffers
|
37
|
+
@tx_buffer = String.new.force_encoding('BINARY')
|
38
|
+
@rx_buffer = String.new.force_encoding('BINARY')
|
39
|
+
|
40
|
+
@nio_monitor = @nio_selector.register(@tcp_socket, :r)
|
41
|
+
@nio_monitor.value = self
|
42
|
+
|
43
|
+
@agent.logger.info "Successfully connected to server"
|
44
|
+
rescue => e
|
45
|
+
@agent.logger.info "Something went wrong connecting to server."
|
46
|
+
# Sleep between 10 and 20 seconds
|
47
|
+
random_sleep = rand(10) + 10
|
48
|
+
@agent.logger.info "#{e.to_s} #{e.message}"
|
49
|
+
@agent.logger.info "Retrying in #{random_sleep} seconds."
|
50
|
+
sleep random_sleep
|
51
|
+
retry
|
52
|
+
end
|
53
|
+
|
54
|
+
# Receive and process packets from the control server
|
55
|
+
def rx_data
|
56
|
+
# Ensure all received data is read
|
57
|
+
@rx_buffer << @socket.readpartial(10240)
|
58
|
+
while(@socket.pending > 0)
|
59
|
+
@rx_buffer << @socket.readpartial(10240)
|
60
|
+
end
|
61
|
+
# Wait until we have a complete packet of data
|
62
|
+
while @rx_buffer.bytesize >=2 && @rx_buffer.bytesize >= @rx_buffer[0,2].unpack('n')[0]
|
63
|
+
length = @rx_buffer.slice!(0,2).unpack('n')[0]
|
64
|
+
# Extract the packet from the buffered stream
|
65
|
+
packet = @rx_buffer.slice!(0,length-2)
|
66
|
+
# Check what type of packet we have received
|
67
|
+
case packet.bytes[0]
|
68
|
+
when 1
|
69
|
+
# Process new connection request
|
70
|
+
id = packet[1,2].unpack('n')[0]
|
71
|
+
host, port = packet[3..-1].split('/', 2)
|
72
|
+
@agent.logger.info "[#{id}] Connection request from server: #{host}:#{port}"
|
73
|
+
begin
|
74
|
+
# Create conenction to the final destination and save info by id
|
75
|
+
@destination_connections[id] = DestinationConnection.new(host, port, id, @nio_selector, self)
|
76
|
+
rescue => e
|
77
|
+
# Something went wrong, inform the Deploy server
|
78
|
+
@agent.logger.error "An error occurred: #{e.message}"
|
79
|
+
@agent.logger.error e.backtrace
|
80
|
+
send_connection_error(id, e.message)
|
81
|
+
end
|
82
|
+
when 3
|
83
|
+
# Process a connection close request
|
84
|
+
id = packet[1,2].unpack('n')[0]
|
85
|
+
if @destination_connections[id]
|
86
|
+
@agent.logger.info "[#{id}] Close requested by server, closing"
|
87
|
+
@destination_connections[id].close
|
88
|
+
else
|
89
|
+
@agent.logger.info "[#{id}] Close requested by server, not open"
|
90
|
+
end
|
91
|
+
when 4
|
92
|
+
# Data incoming, send it to the backend
|
93
|
+
id = packet[1,2].unpack('n')[0]
|
94
|
+
@agent.logger.debug "[#{id}] #{packet.bytesize} bytes received from server"
|
95
|
+
@destination_connections[id].send_data(packet[3..-1])
|
96
|
+
when 5
|
97
|
+
# This is a shutdown request. Disconnect and don't re-attempt connection.
|
98
|
+
@agent.logger.warn "Server rejected connection. Shutting down."
|
99
|
+
@agent.logger.warn packet[1..-1]
|
100
|
+
Process.exit(0)
|
101
|
+
when 6
|
102
|
+
# This is a shutdown request. Disconnect and don't re-attempt connection.
|
103
|
+
@agent.logger.warn "Server requested reconnect. Closing connection."
|
104
|
+
close
|
105
|
+
end
|
106
|
+
end
|
107
|
+
rescue EOFError, Errno::ECONNRESET
|
108
|
+
close
|
109
|
+
end
|
110
|
+
|
111
|
+
# Notify server of successful connection
|
112
|
+
def send_connection_success(id)
|
113
|
+
send_packet([2, id, 0].pack('CnC'))
|
114
|
+
end
|
115
|
+
|
116
|
+
# Notify server of failed connection
|
117
|
+
def send_connection_error(id, reason)
|
118
|
+
send_packet([2, id, 1, reason].pack('CnCa*'))
|
119
|
+
end
|
120
|
+
|
121
|
+
# Notify server of closed connection
|
122
|
+
def send_connection_close(id)
|
123
|
+
send_packet([3, id].pack('Cn'))
|
124
|
+
end
|
125
|
+
|
126
|
+
# Proxy data (coming from the backend) to the Deploy server
|
127
|
+
def send_data(id, data)
|
128
|
+
send_packet([4, id, data].pack('Cna*'))
|
129
|
+
end
|
130
|
+
|
131
|
+
# Called by event loop to send all waiting packets to the Deploy server
|
132
|
+
def tx_data
|
133
|
+
bytes_sent = @socket.write_nonblock(@tx_buffer[0,1024])
|
134
|
+
# Send as much data as possible
|
135
|
+
if bytes_sent >= @tx_buffer.bytesize
|
136
|
+
@tx_buffer = String.new.force_encoding('BINARY')
|
137
|
+
@nio_monitor.interests = :r
|
138
|
+
else
|
139
|
+
# If we didn't manage to send all the data, leave
|
140
|
+
# the remaining data in the send buffer
|
141
|
+
@tx_buffer.slice!(0, bytes_sent)
|
142
|
+
end
|
143
|
+
rescue EOFError, Errno::ECONNRESET
|
144
|
+
close
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def close
|
150
|
+
@agent.logger.info "Server disconnected, terminating all connections"
|
151
|
+
@destination_connections.values.each{ |s| s.close }
|
152
|
+
@nio_selector.deregister(@tcp_socket)
|
153
|
+
@socket.close
|
154
|
+
@tcp_socket.close
|
155
|
+
raise ServerDisconnected
|
156
|
+
end
|
157
|
+
|
158
|
+
# Queue a packet of data to be sent to the Deploy server
|
159
|
+
def send_packet(data)
|
160
|
+
@tx_buffer << [data.bytesize+2, data].pack('na*')
|
161
|
+
@nio_monitor.interests = :rw
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deploy-agent
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- aTech Media
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nio4r
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.2.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.2.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rb-readline
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.5.4
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.5.4
|
41
|
+
description: This gem allows you to configure a secure proxy through which Deploy
|
42
|
+
can forward connections
|
43
|
+
email:
|
44
|
+
- support@deployhq.com
|
45
|
+
executables:
|
46
|
+
- deploy-agent
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- bin/deploy-agent
|
51
|
+
- lib/deploy_agent.rb
|
52
|
+
- lib/deploy_agent/agent.rb
|
53
|
+
- lib/deploy_agent/certificate_manager.rb
|
54
|
+
- lib/deploy_agent/cli.rb
|
55
|
+
- lib/deploy_agent/destination_connection.rb
|
56
|
+
- lib/deploy_agent/server_connection.rb
|
57
|
+
homepage: https://www.deployhq.com/
|
58
|
+
licenses: []
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 2.6.8
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: The Deploy agent
|
80
|
+
test_files: []
|