rest-ftp-daemon 0.423.3 → 0.424.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +30 -0
  3. data/Gemfile.lock +9 -8
  4. data/README.md +1 -5
  5. data/bin/rest-ftp-daemon +11 -5
  6. data/defaults.yml +16 -10
  7. data/lib/rest-ftp-daemon.rb +14 -10
  8. data/lib/rest-ftp-daemon/api/jobs.rb +42 -18
  9. data/lib/rest-ftp-daemon/api/root.rb +5 -1
  10. data/lib/rest-ftp-daemon/constants.rb +0 -1
  11. data/lib/rest-ftp-daemon/{api/entities → entities}/job.rb +0 -0
  12. data/lib/rest-ftp-daemon/{api/entities → entities}/location.rb +0 -0
  13. data/lib/rest-ftp-daemon/{api/entities → entities}/options.rb +0 -0
  14. data/lib/rest-ftp-daemon/exceptions.rb +1 -0
  15. data/lib/rest-ftp-daemon/helpers/views.rb +7 -2
  16. data/lib/rest-ftp-daemon/initialize.rb +3 -0
  17. data/lib/rest-ftp-daemon/job.rb +3 -0
  18. data/lib/rest-ftp-daemon/jobs/transfer.rb +4 -4
  19. data/lib/rest-ftp-daemon/location.rb +5 -0
  20. data/lib/rest-ftp-daemon/remote/base.rb +76 -0
  21. data/lib/rest-ftp-daemon/remote/ftp.rb +144 -0
  22. data/lib/rest-ftp-daemon/remote/s3.rb +78 -0
  23. data/lib/rest-ftp-daemon/remote/sftp.rb +147 -0
  24. data/lib/rest-ftp-daemon/static/images/feature_reload.png +0 -0
  25. data/lib/rest-ftp-daemon/static/images/feature_rollbar.png +0 -0
  26. data/lib/rest-ftp-daemon/static/swagger/css/print.css +2 -2
  27. data/lib/rest-ftp-daemon/static/swagger/css/screen.css +2 -2
  28. data/lib/rest-ftp-daemon/views/dashboard_footer.haml +3 -2
  29. data/lib/rest-ftp-daemon/views/dashboard_jobs.haml +3 -3
  30. data/lib/rest-ftp-daemon/views/dashboard_table.haml +5 -4
  31. data/lib/rest-ftp-daemon/workers/reporter.rb +2 -2
  32. data/rest-ftp-daemon.gemspec +4 -7
  33. metadata +28 -25
  34. data/lib/rest-ftp-daemon/remote.rb +0 -74
  35. data/lib/rest-ftp-daemon/remote_ftp.rb +0 -142
  36. data/lib/rest-ftp-daemon/remote_s3.rb +0 -76
  37. data/lib/rest-ftp-daemon/remote_sftp.rb +0 -145
@@ -0,0 +1,76 @@
1
+ # Handles transfers for Job class
2
+ module RestFtpDaemon
3
+ module Remote
4
+ class RemoteBase
5
+ include BmcDaemonLib::LoggerHelper
6
+
7
+ # Class options
8
+ attr_reader :logger
9
+ attr_reader :log_prefix
10
+ attr_accessor :job
11
+
12
+ # Delegate set_info info to Job
13
+ delegate :set_info, to: :job
14
+
15
+ def initialize target, log_prefix, debug = false, ftpes = false
16
+ # Init
17
+ @target = target
18
+ @ftpes = ftpes
19
+ @debug = !!debug
20
+
21
+ # Build and empty job to protect set_info delegation
22
+ @job = Job.new(nil, {})
23
+
24
+ # Logger
25
+ @log_prefix = log_prefix || {}
26
+ @logger = BmcDaemonLib::LoggerPool.instance.get :transfer
27
+
28
+ # Annnounce object
29
+ log_info "Remote.initialize debug[#{debug}] target[#{target.path}] "
30
+
31
+ # Prepare real object
32
+ prepare
33
+ end
34
+
35
+ def prepare
36
+ end
37
+
38
+ def connect
39
+ # Debug mode ?
40
+ return unless @debug
41
+ puts
42
+ puts "-------------------- SESSION STARTING -------------------------"
43
+ puts "class\t #{myname}"
44
+ puts "host\t #{@target.host}"
45
+ puts "user\t #{@target.user}"
46
+ puts "port\t #{@target.port}"
47
+ puts "---------------------------------------------------------------"
48
+ end
49
+
50
+ def chdir_or_create directory, mkdir = false
51
+ end
52
+
53
+ def remove! target
54
+ end
55
+
56
+ def close
57
+ # Debug mode ?
58
+ return unless @debug
59
+ puts "-------------------- SESSION CLOSING --------------------------"
60
+ end
61
+
62
+ private
63
+
64
+ def extract_parent path
65
+ return unless path.is_a? String
66
+ m = path.match(/^(.*)\/([^\/]+)\/?$/)
67
+ return m[1], m[2] unless m.nil?
68
+ end
69
+
70
+ def myname
71
+ self.class.to_s
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,144 @@
1
+ require "net/ftp"
2
+ require "double_bag_ftps"
3
+
4
+ # Handle FTP and FTPeS transfers for Remote class
5
+ module RestFtpDaemon
6
+ module Remote
7
+ class RemoteFTP < RemoteBase
8
+
9
+ # Class options
10
+ attr_reader :ftp
11
+
12
+ def prepare
13
+ # Create FTP object
14
+ if @ftpes
15
+ prepare_ftpes
16
+ else
17
+ prepare_ftp
18
+ end
19
+ @ftp.passive = true
20
+ @ftp.debug_mode = @debug
21
+
22
+ # Config
23
+ @chunk_size = DEFAULT_FTP_CHUNK.to_i * 1024
24
+
25
+ # Announce object
26
+ log_debug "Remote::RemoteFTP.prepare chunk_size:#{@chunk_size}"
27
+ end
28
+
29
+ def connect
30
+ super
31
+
32
+ # Connect remote server
33
+ @ftp.connect @target.host, @target.port
34
+ @ftp.login @target.user, @target.password
35
+ end
36
+
37
+ def present? target
38
+ size = @ftp.size target.path
39
+ log_debug "Remote::RemoteFTP.present? [#{target.name}]"
40
+
41
+ rescue Net::FTPPermError
42
+ return false
43
+ else
44
+ return size
45
+ end
46
+
47
+ def remove! target
48
+ @ftp.delete target.path
49
+ rescue Net::FTPPermError
50
+ log_debug "Remote::RemoteFTP.remove! [#{target.name}] not found"
51
+ else
52
+ log_debug "Remote::RemoteFTP.remove! [#{target.name}] removed"
53
+ end
54
+
55
+ def mkdir directory
56
+ log_debug "Remote::RemoteFTP.mkdir [#{directory}]"
57
+ @ftp.mkdir directory
58
+
59
+ rescue StandardError => ex
60
+ raise TargetPermissionError, ex.message
61
+ end
62
+
63
+ def chdir_or_create directory, mkdir = false
64
+ # Init, extract my parent name and my own name
65
+ log_debug "Remote::RemoteFTP.chdir_or_create mkdir[#{mkdir}] dir[#{directory}]"
66
+ parent, current = extract_parent(directory)
67
+
68
+ #dirname, _current = extract_parent(directory)
69
+
70
+
71
+ # Access this directory
72
+ begin
73
+ @ftp.chdir "/#{directory}"
74
+
75
+ rescue Net::FTPPermError => _e
76
+ # If not allowed to create path, that's over, we're stuck
77
+ return false unless mkdir
78
+ chdir_or_create parent, mkdir
79
+
80
+ # Now I was able to chdir into my parent, create the current directory
81
+ mkdir current
82
+
83
+ # Finally retry the chdir
84
+ retry
85
+ else
86
+ return true
87
+ end
88
+ end
89
+
90
+ def upload source, target, use_temp_name = false, &callback
91
+ # Push init
92
+ raise RestFtpDaemon::AssertionFailed, "upload/ftp" if @ftp.nil?
93
+
94
+ # Temp file if needed
95
+ dest = target.clone
96
+ if use_temp_name
97
+ dest.generate_temp_name!
98
+ end
99
+
100
+ # Move to the directory
101
+ log_debug "Remote::RemoteFTP.upload chdir [#{dest.dir}]"
102
+ @ftp.chdir "/#{dest.dir}"
103
+
104
+ # Do the transfer
105
+ log_debug "Remote::RemoteFTP.upload putbinaryfile [#{dest.name}]"
106
+ @ftp.putbinaryfile source.path, dest.name, @chunk_size do |data|
107
+ # Update job status after this block transfer
108
+ yield data.bytesize, dest.name
109
+ end
110
+
111
+ # Move the file back to its original name
112
+ if use_temp_name
113
+ log_debug "Remote::RemoteFTP.upload rename [#{dest.name}] > [#{target.name}]"
114
+ @ftp.rename dest.name, target.name
115
+ end
116
+ end
117
+
118
+ def close
119
+ # Close init
120
+ super
121
+
122
+ # Close FTP connexion and free up memory
123
+ @ftp.close
124
+ end
125
+
126
+ def connected?
127
+ !@ftp.welcome.nil?
128
+ end
129
+
130
+ private
131
+
132
+ def prepare_ftp
133
+ @ftp = Net::FTP.new
134
+ end
135
+
136
+ def prepare_ftpes
137
+ @ftp = DoubleBagFTPS.new
138
+ @ftp.ssl_context = DoubleBagFTPS.create_ssl_context(verify_mode: OpenSSL::SSL::VERIFY_NONE)
139
+ @ftp.ftps_mode = DoubleBagFTPS::EXPLICIT
140
+ end
141
+
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,78 @@
1
+ require 'aws-sdk-resources'
2
+
3
+ # Handle sFTP transfers for Remote class
4
+ module RestFtpDaemon
5
+ module Remote
6
+ class RemoteS3 < RemoteBase
7
+
8
+ MULTIPART_THRESHOLD_MB = 4
9
+
10
+ # Class options
11
+ attr_reader :client
12
+ attr_reader :target
13
+
14
+ def prepare
15
+ @multipart_threshold = MULTIPART_THRESHOLD_MB.to_i * 1024 * 1024
16
+ log_debug "Remote::RemoteS3.prepare target[#{@target.inspect}] #{@multipart_threshold}"
17
+ end
18
+
19
+ def connect
20
+ super
21
+
22
+ # Connect init
23
+ log_debug "Remote::RemoteS3.connect region[#{target.aws_region}] id[#{target.aws_id}]"
24
+
25
+ # Connect remote server
26
+ @client = Aws::S3::Resource.new(
27
+ region: @target.aws_region,
28
+ credentials: Aws::Credentials.new(@target.aws_id, @target.aws_secret),
29
+ http_wire_trace: @debug
30
+ )
31
+ #s3 = Aws::S3::Client.new(http_wire_trace: true)
32
+ end
33
+
34
+ def upload source, target, use_temp_name = false, &callback
35
+ # Push init
36
+ raise RestFtpDaemon::AssertionFailed, "upload/client" if @client.nil?
37
+ log_debug "Remote::RemoteS3.upload bucket[#{target.aws_bucket}] name[#{target.name}]"
38
+
39
+ # Update progress before
40
+ #yield 0, target.name
41
+ # Point to the right bucket and object
42
+ bucket = @client.bucket(target.aws_bucket)
43
+ object = bucket.object(target.name)
44
+
45
+ # Do the transfer
46
+ object.upload_file(source.path, {
47
+ multipart_threshold: @multipart_threshold
48
+ })
49
+
50
+ # Wait for transfer to complete
51
+ object.wait_until_exists do |waiter|
52
+ # waiter.delay = 1
53
+ # # log_debug "- progress[#{progress}] total[#{total}]"
54
+ # waiter.before_wait do |attempts, response|
55
+ # puts "#{attempts} made"
56
+ # puts response.error.inspect
57
+ # puts response.data.inspect
58
+ # end
59
+ # log_debug "- progress[] #{waiter.inspect}"
60
+ end
61
+
62
+ # Update progress after
63
+ #yield target.size, target.name
64
+
65
+ # Dump information about this file
66
+ log_debug "Remote::RemoteS3.upload url[#{object.public_url}]"
67
+ log_debug "Remote::RemoteS3.upload etag[#{object.etag}]"
68
+ set_info :target_aws_public_url, object.public_url
69
+ set_info :target_aws_etag, object.etag
70
+ end
71
+
72
+ def connected?
73
+ !@client.nil?
74
+ end
75
+
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,147 @@
1
+ require "net/sftp"
2
+
3
+ # Handle sFTP transfers for Remote class
4
+ module RestFtpDaemon
5
+ module Remote
6
+ class RemoteSFTP < RemoteBase
7
+
8
+ # Class options
9
+ attr_reader :sftp
10
+
11
+ def prepare
12
+ end
13
+
14
+ def connect
15
+ super
16
+
17
+ # Connect init
18
+ log_debug "Remote::RemoteSFTP.connect [#{@target.user}]@[#{@target.host}]:[#{@target.port}]"
19
+
20
+ # Debug level
21
+ verbosity = @debug ? Logger::DEBUG : false
22
+
23
+ # Connect remote server
24
+ @sftp = Net::SFTP.start(@target.host.to_s, @target.user.to_s,
25
+ password: @target.password.to_s,
26
+ verbose: verbosity,
27
+ port: @target.port,
28
+ non_interactive: true,
29
+ timeout: DEFAULT_SFTP_TIMEOUT
30
+ )
31
+ end
32
+
33
+ def present? target
34
+ log_debug "Remote::RemoteSFTP.present? [#{target.name}]"
35
+ stat = @sftp.stat! target.path
36
+
37
+ rescue Net::SFTP::StatusException
38
+ return false
39
+ else
40
+ return stat.size
41
+ end
42
+
43
+ def remove! target
44
+ log_debug "Remote::RemoteSFTP.remove! [#{target.name}]"
45
+ @sftp.remove target.path
46
+
47
+ rescue Net::SFTP::StatusException
48
+ log_debug "#{LOG_INDENT}[#{target.name}] file not found"
49
+ else
50
+ log_debug "#{LOG_INDENT}[#{target.name}] removed"
51
+ end
52
+
53
+ def mkdir directory
54
+ log_debug "Remote::RemoteSFTP.mkdir [#{directory}]"
55
+ @sftp.mkdir! directory
56
+
57
+ rescue StandardError => ex
58
+ raise TargetPermissionError, ex.message
59
+ end
60
+
61
+ def chdir_or_create directory, mkdir = false
62
+ # Init, extract my parent name and my own name
63
+ log_debug "Remote::RemoteSFTP.chdir_or_create mkdir[#{mkdir}] dir[#{directory}]"
64
+ parent, _current = extract_parent(directory)
65
+
66
+ # Access this directory
67
+ begin
68
+ #log_debug "chdir [/#{directory}]"
69
+ @sftp.opendir! directory
70
+
71
+ rescue Net::SFTP::StatusException => _e
72
+ # If not allowed to create path, that's over, we're stuck
73
+ return false unless mkdir
74
+
75
+ # Recurse upward
76
+ chdir_or_create parent, mkdir
77
+
78
+ # Now I was able to chdir into my parent, create the current directory
79
+ mkdir directory
80
+
81
+ # Finally retry the chdir
82
+ retry
83
+ else
84
+ return true
85
+ end
86
+
87
+ # We should never get here
88
+ raise JobTargetShouldBeDirectory
89
+ end
90
+
91
+ def upload source, target, use_temp_name = false, &callback
92
+ # Push init
93
+ raise RestFtpDaemon::AssertionFailed, "upload/sftp" if @sftp.nil?
94
+
95
+ # Temp file if needed
96
+ dest = target.clone
97
+ if use_temp_name
98
+ dest.generate_temp_name!
99
+ end
100
+
101
+ # Do the transfer
102
+ log_debug "Remote::RemoteSFTP.upload temp[#{use_temp_name}] name[#{dest.name}]"
103
+ @sftp.upload! source.path, dest.path do |event, _uploader, *args|
104
+ case event
105
+ when :open then
106
+ # args[0] : file metadata
107
+ when :put then
108
+ # args[0] : file metadata
109
+ # args[1] : byte offset in remote file
110
+ # args[2] : data being written (as string)
111
+ # puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
112
+
113
+ # Update job status after this block transfer
114
+ yield args[2].length, dest.name
115
+
116
+ when :close then
117
+ # args[0] : file metadata
118
+ when :mkdir
119
+ # args[0] : remote path name
120
+ when :finish
121
+ end
122
+
123
+ end
124
+
125
+ # Move the file back to its original name
126
+ if use_temp_name
127
+ flags = 0x00000001
128
+ log_debug "Remote::RemoteSFTP.upload rename [#{dest.name}] > [#{target.name}]"
129
+ @sftp.rename! dest.path, target.path, flags
130
+ end
131
+
132
+ # progress:
133
+ # Net::SFTP::StatusException
134
+ end
135
+
136
+ def close
137
+ # Close init
138
+ super
139
+ end
140
+
141
+ def connected?
142
+ @sftp && !@sftp.closed?
143
+ end
144
+
145
+ end
146
+ end
147
+ end