rest-ftp-daemon 0.104.5 → 0.200
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +24 -22
- data/bin/rest-ftp-daemon +50 -43
- data/config.ru +1 -1
- data/lib/rest-ftp-daemon/api/dashboard.rb +1 -1
- data/lib/rest-ftp-daemon/api/root.rb +2 -2
- data/lib/rest-ftp-daemon/config.rb +11 -0
- data/lib/rest-ftp-daemon/constants.rb +26 -15
- data/lib/rest-ftp-daemon/exceptions.rb +1 -0
- data/lib/rest-ftp-daemon/helpers.rb +2 -1
- data/lib/rest-ftp-daemon/job.rb +194 -115
- data/lib/rest-ftp-daemon/job_queue.rb +9 -4
- data/lib/rest-ftp-daemon/logger.rb +21 -4
- data/lib/rest-ftp-daemon/logger_pool.rb +3 -1
- data/lib/rest-ftp-daemon/notification.rb +44 -19
- data/lib/rest-ftp-daemon/views/dashboard.haml +2 -3
- data/lib/rest-ftp-daemon/views/dashboard_headers.haml +1 -1
- data/lib/rest-ftp-daemon/views/dashboard_jobs.haml +13 -16
- data/lib/rest-ftp-daemon/worker_pool.rb +62 -30
- data/rest-ftp-daemon.gemspec +0 -1
- data/rest-ftp-daemon.yml.sample +3 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e1fc48456791d2868a30a17e573aba066face90
|
4
|
+
data.tar.gz: 77471dd20a0e6fb263cff752821f8c0c9b156a27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79472b4ab9a4cea7c3a2437301fb6fd0b03a159b1ed2a1c384448b1a9c6e1ac41b9e192a072c7878cb39012fecb3a6011b89ff6d73076b1f92ebb9332170d1ff
|
7
|
+
data.tar.gz: a3b738c676e30f296b1e68e59298527f9b52e49e4e88268b32bf54fbedb8e551bc48b8e6389bc298b833b63cc85952d44e2d3886540e8bc7abbd0b8d6b904594
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rest-ftp-daemon (0.
|
4
|
+
rest-ftp-daemon (0.200)
|
5
5
|
double-bag-ftps
|
6
6
|
facter
|
7
7
|
grape
|
@@ -17,11 +17,11 @@ GEM
|
|
17
17
|
remote: http://rubygems.org/
|
18
18
|
specs:
|
19
19
|
CFPropertyList (2.2.8)
|
20
|
-
activesupport (4.
|
21
|
-
i18n (~> 0.
|
20
|
+
activesupport (4.2.0)
|
21
|
+
i18n (~> 0.7)
|
22
22
|
json (~> 1.7, >= 1.7.7)
|
23
23
|
minitest (~> 5.1)
|
24
|
-
thread_safe (~> 0.
|
24
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
25
25
|
tzinfo (~> 1.1)
|
26
26
|
axiom-types (0.1.1)
|
27
27
|
descendants_tracker (~> 0.0.4)
|
@@ -30,16 +30,16 @@ GEM
|
|
30
30
|
builder (3.2.2)
|
31
31
|
coercible (1.0.0)
|
32
32
|
descendants_tracker (~> 0.0.1)
|
33
|
-
daemons (1.1
|
33
|
+
daemons (1.2.1)
|
34
34
|
descendants_tracker (0.0.4)
|
35
35
|
thread_safe (~> 0.3, >= 0.3.1)
|
36
36
|
double-bag-ftps (0.1.2)
|
37
37
|
equalizer (0.0.9)
|
38
|
-
eventmachine (1.0.
|
39
|
-
facter (2.
|
38
|
+
eventmachine (1.0.7)
|
39
|
+
facter (2.4.1)
|
40
40
|
CFPropertyList (~> 2.2.6)
|
41
|
-
ffi (1.9.
|
42
|
-
grape (0.
|
41
|
+
ffi (1.9.8)
|
42
|
+
grape (0.11.0)
|
43
43
|
activesupport
|
44
44
|
builder
|
45
45
|
hashie (>= 2.1.0)
|
@@ -49,24 +49,24 @@ GEM
|
|
49
49
|
rack-accept
|
50
50
|
rack-mount
|
51
51
|
virtus (>= 1.0.0)
|
52
|
-
grape-entity (0.4.
|
52
|
+
grape-entity (0.4.5)
|
53
53
|
activesupport
|
54
54
|
multi_json (>= 1.3.2)
|
55
|
-
haml (4.0.
|
55
|
+
haml (4.0.6)
|
56
56
|
tilt
|
57
|
-
hashie (3.
|
58
|
-
i18n (0.
|
59
|
-
ice_nine (0.11.
|
60
|
-
json (1.8.
|
61
|
-
minitest (5.
|
62
|
-
multi_json (1.
|
57
|
+
hashie (3.4.0)
|
58
|
+
i18n (0.7.0)
|
59
|
+
ice_nine (0.11.1)
|
60
|
+
json (1.8.2)
|
61
|
+
minitest (5.5.1)
|
62
|
+
multi_json (1.11.0)
|
63
63
|
multi_xml (0.5.5)
|
64
|
-
rack (1.
|
64
|
+
rack (1.6.0)
|
65
65
|
rack-accept (0.4.5)
|
66
66
|
rack (>= 0.4)
|
67
67
|
rack-mount (0.8.3)
|
68
68
|
rack (>= 1.0.0)
|
69
|
-
rake (10.4.
|
69
|
+
rake (10.4.2)
|
70
70
|
settingslogic (2.0.9)
|
71
71
|
sys-cpu (0.7.1)
|
72
72
|
ffi (>= 1.0.0)
|
@@ -74,12 +74,14 @@ GEM
|
|
74
74
|
daemons (~> 1.0, >= 1.0.9)
|
75
75
|
eventmachine (~> 1.0)
|
76
76
|
rack (~> 1.0)
|
77
|
-
thread_safe (0.3.
|
77
|
+
thread_safe (0.3.5)
|
78
78
|
tilt (2.0.1)
|
79
|
-
timeout (0.0.
|
79
|
+
timeout (0.0.1)
|
80
|
+
timeout-extensions
|
81
|
+
timeout-extensions (0.0.0)
|
80
82
|
tzinfo (1.2.2)
|
81
83
|
thread_safe (~> 0.1)
|
82
|
-
virtus (1.0.
|
84
|
+
virtus (1.0.4)
|
83
85
|
axiom-types (~> 0.1)
|
84
86
|
coercible (~> 1.0)
|
85
87
|
descendants_tracker (~> 0.0, >= 0.0.3)
|
data/bin/rest-ftp-daemon
CHANGED
@@ -11,13 +11,13 @@ rescue LoadError
|
|
11
11
|
raise "EXITING: some of basic libs were not found: thin, optparse, socket, timeout"
|
12
12
|
end
|
13
13
|
|
14
|
+
|
14
15
|
# Load helpers and constants
|
15
16
|
[:constants, :helpers].each do |lib|
|
16
17
|
require File.expand_path("#{app_root}/lib/rest-ftp-daemon/#{lib.to_s}")
|
17
18
|
end
|
18
|
-
|
19
19
|
puts
|
20
|
-
|
20
|
+
|
21
21
|
|
22
22
|
# Detect options from ARGV
|
23
23
|
options = {}
|
@@ -33,75 +33,82 @@ parser = OptionParser.new do |opts|
|
|
33
33
|
opts.on("-P", "--pid FILE", "File to store PID") { |file| options["pidfile"] = file }
|
34
34
|
opts.on("-u", "--user NAME", "User to run daemon as (use with -g)") { |user| options["user"] = user }
|
35
35
|
opts.on("-g", "--group NAME", "Group to run daemon as (use with -u)"){ |group| options["group"] = group }
|
36
|
+
|
36
37
|
opts.on_tail("-h", "--help", "Show this message") { puts opts; exit }
|
37
38
|
opts.on_tail('-v', '--version', "Show version (#{APP_VER})") { puts APP_VER; exit }
|
38
39
|
end
|
40
|
+
|
41
|
+
|
42
|
+
# Parse options and check compliance
|
39
43
|
begin
|
40
44
|
parser.order!(ARGV)
|
41
45
|
command = ARGV.shift
|
42
|
-
unless ["start", "stop"].include? command
|
43
|
-
puts parser
|
44
|
-
exit 11
|
45
|
-
end
|
46
46
|
rescue OptionParser::InvalidOption => e
|
47
|
-
|
48
|
-
|
47
|
+
abort "EXITING: option parser: #{e.message}"
|
48
|
+
else
|
49
|
+
abort parser.to_s unless ["start", "stop"].include? command
|
49
50
|
end
|
50
51
|
|
52
|
+
|
51
53
|
# Build configuration file path from options
|
52
54
|
APP_CONF ||= File.expand_path "/etc/#{APP_NAME}.yml"
|
53
|
-
unless File.exists? APP_CONF
|
54
|
-
|
55
|
-
exit 13
|
56
|
-
end
|
55
|
+
abort "EXITING: cannot read configuration file: #{APP_CONF}" unless File.exists? APP_CONF
|
56
|
+
|
57
57
|
|
58
|
-
# Load
|
58
|
+
# Load config, and merge options from ARGV into settings
|
59
59
|
begin
|
60
60
|
require File.expand_path("#{app_root}/lib/rest-ftp-daemon/config")
|
61
61
|
Settings.merge!(options)
|
62
62
|
rescue Psych::SyntaxError => e
|
63
|
-
|
64
|
-
exit 16
|
63
|
+
abort "EXITING: config file syntax error: #{e.message}"
|
65
64
|
end
|
66
65
|
|
67
66
|
|
68
|
-
# Display compiled configuration
|
69
|
-
puts "--- #{APP_NAME} #{APP_VER}"
|
70
|
-
puts "Config file \t #{APP_CONF}"
|
71
|
-
puts "PID file \t #{Settings.pidfile}"
|
72
|
-
puts "Namespace \t #{Settings.namespace}"
|
73
|
-
puts "Network port \t #{Settings['port']}"
|
74
|
-
puts "Daemonize \t #{Settings['daemonize']}"
|
75
|
-
puts "User:group \t #{Settings['user']}:#{Settings['group']}"
|
76
|
-
puts
|
77
|
-
puts Settings.to_hash.to_yaml( :Indent => 4, :UseHeader => true, :UseVersion => false )
|
78
|
-
puts
|
79
|
-
|
80
67
|
# Validate network configuration
|
81
|
-
if
|
82
|
-
if Settings
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
puts "ABORTING: Network port #{Settings['port']} is already in use"
|
87
|
-
exit 15
|
68
|
+
if command == "start"
|
69
|
+
if !Settings.port
|
70
|
+
abort "ABORTING: Network port is missing"
|
71
|
+
elsif RestFtpDaemon::Helpers.local_port_used? Settings.port
|
72
|
+
abort "ABORTING: Network port #{Settings.port} is already in use"
|
88
73
|
end
|
89
74
|
end
|
90
75
|
|
91
|
-
|
76
|
+
|
77
|
+
# ARGV: build final
|
92
78
|
argv = []
|
93
79
|
argv << ["-e", Settings.namespace]
|
94
|
-
argv << ["-p", Settings
|
80
|
+
argv << ["-p", Settings.port.to_s] if Settings.port
|
95
81
|
argv << ["--pid", Settings.pidfile]
|
96
82
|
argv << ["--tag", "'#{APP_NAME}/#{Settings.namespace}'"]
|
97
|
-
argv << ["--log", Settings
|
98
|
-
argv << ["--daemonize"] if [1, true].include? Settings
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
83
|
+
argv << ["--log", Settings.at(:logs, :thin)]
|
84
|
+
argv << ["--daemonize"] if [1, true].include? Settings.daemonize
|
85
|
+
|
86
|
+
|
87
|
+
# ARGV: logging
|
88
|
+
if (logfile = Settings.at :logs, :thin)
|
89
|
+
argv << ["--log", logfile] if logfile
|
90
|
+
end
|
91
|
+
|
92
|
+
# ARGV: user and group
|
93
|
+
if Settings.user && Settings.group
|
94
|
+
argv << ["--user", Settings.user]
|
95
|
+
argv << ["--group", Settings.group]
|
103
96
|
end
|
104
|
-
|
97
|
+
|
98
|
+
|
99
|
+
# ARGV: add command
|
100
|
+
argv << command unless command.nil?
|
101
|
+
|
102
|
+
# Display final configuration
|
103
|
+
puts "--- #{APP_NAME} #{APP_VER}"
|
104
|
+
puts "Config file \t #{APP_CONF}"
|
105
|
+
puts "PID file \t #{Settings.pidfile}"
|
106
|
+
puts "Daemonize \t #{Settings.daemonize ? 'YES' : "no"}"
|
107
|
+
puts "Namespace \t #{Settings.namespace}"
|
108
|
+
puts "Network port \t #{Settings.port}"
|
109
|
+
puts "User:group \t #{Settings.user}:#{Settings.group}" if Settings.users || Setting.group
|
110
|
+
puts Settings.dump
|
111
|
+
puts
|
105
112
|
puts "--- Thin ARGV"
|
106
113
|
puts argv.flatten.join(' ')
|
107
114
|
puts
|
data/config.ru
CHANGED
@@ -5,7 +5,7 @@ require 'rest-ftp-daemon'
|
|
5
5
|
|
6
6
|
# Create queue and worker pool
|
7
7
|
$queue = RestFtpDaemon::JobQueue.new
|
8
|
-
$pool = RestFtpDaemon::WorkerPool.new(Settings
|
8
|
+
$pool = RestFtpDaemon::WorkerPool.new(Settings.workers || APP_WORKERS)
|
9
9
|
|
10
10
|
# Rack reloader
|
11
11
|
unless Settings.namespace == "production"
|
@@ -17,4 +17,15 @@ class Settings < Settingslogic
|
|
17
17
|
self["pidfile"] || "/tmp/#{APP_NAME}.port#{self['port'].to_s}.pid"
|
18
18
|
end
|
19
19
|
|
20
|
+
# Direct access to any depth
|
21
|
+
def at *path
|
22
|
+
#put "Settings.nested: wrong path [#{path.inspect}]" unless path.is_a? Hash
|
23
|
+
path.reduce(Settings) {|m,key| m && m[key.to_s] }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Dump whole settings set to readable YAML
|
27
|
+
def dump
|
28
|
+
self.to_hash.to_yaml( :Indent => 4, :UseHeader => true, :UseVersion => false )
|
29
|
+
end
|
30
|
+
|
20
31
|
end
|
@@ -1,23 +1,34 @@
|
|
1
1
|
# Terrific constants
|
2
2
|
APP_NAME = "rest-ftp-daemon"
|
3
|
-
APP_VER = "0.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
IDENT_RANDOM_LEN = 8
|
9
|
-
IDENT_TEMPFILE_LEN = 8
|
10
|
-
DEFAULT_LOGS_PIPE_LEN = 12
|
3
|
+
APP_VER = "0.200"
|
4
|
+
|
5
|
+
|
6
|
+
# Logging
|
7
|
+
DEFAULT_LOGS_PIPE_LEN = 10
|
11
8
|
DEFAULT_LOGS_ID_LEN = 8
|
9
|
+
DEFAULT_LOGS_TRIM_LINE = 80
|
10
|
+
|
11
|
+
|
12
|
+
# Jobs identifiers length
|
13
|
+
JOB_RANDOM_LEN = 8
|
14
|
+
JOB_TEMPFILE_LEN = 8
|
15
|
+
JOB_IDENT_LEN = 4
|
16
|
+
|
17
|
+
|
18
|
+
# Jobs
|
19
|
+
JOB_UPDATE_KB = 2048
|
20
|
+
JOB_STATUS_UPLOADING = :uploading
|
21
|
+
JOB_STATUS_FINISHED = :finished
|
22
|
+
JOB_STATUS_QUEUED = :queued
|
23
|
+
|
24
|
+
# Notifications
|
25
|
+
NOTIFY_PREFIX = "rftpd"
|
26
|
+
NOTIFY_USERAGENT = "#{APP_NAME} - #{APP_VER}"
|
27
|
+
NOTIFY_IDENTIFIER_LEN = 4
|
12
28
|
|
13
|
-
# Some defaults
|
14
|
-
DEFAULT_CONNECT_TIMEOUT_SEC = 30
|
15
|
-
DEFAULT_UPDATE_EVERY_KB = 2048
|
16
|
-
DEFAULT_WORKERS = 1
|
17
29
|
|
18
|
-
# Initialize
|
30
|
+
# Initialize defaults
|
19
31
|
APP_STARTED = Time.now
|
20
32
|
APP_LIBS = File.dirname(__FILE__)
|
33
|
+
APP_WORKERS = 1
|
21
34
|
|
22
|
-
# Debugging
|
23
|
-
DEBUG_FTP_COMMANDS = false
|
@@ -13,6 +13,7 @@ module RestFtpDaemon
|
|
13
13
|
class JobAssertionFailed < RestFtpDaemonException; end
|
14
14
|
class JobMissingAttribute < RestFtpDaemonException; end
|
15
15
|
class JobSourceNotFound < RestFtpDaemonException; end
|
16
|
+
class JobSourceNotReadable < RestFtpDaemonException; end
|
16
17
|
class JobTargetUnsupported < RestFtpDaemonException; end
|
17
18
|
class JobTargetUnparseable < RestFtpDaemonException; end
|
18
19
|
class JobTargetFileExists < RestFtpDaemonException; end
|