Skip to content

Commit 727ad86

Browse files
authored
Validate Rclone remotes in initializer (#2952)
Validates by trying to query in parallel with a timeout of 6s. Disabled by default, enable by setting OOD_REMOTE_FILES_VALIDATION.
1 parent 20ba34c commit 727ad86

File tree

6 files changed

+44
-3
lines changed

6 files changed

+44
-3
lines changed

apps/dashboard/config/configuration_singleton.rb

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def boolean_configs
4444
:bc_clean_old_dirs => false,
4545
:per_cluster_dataroot => false,
4646
:remote_files_enabled => false,
47+
:remote_files_validation => false,
4748
:host_based_profiles => false,
4849
:disable_bc_shell => false,
4950
:cancel_session_enabled => false,

apps/dashboard/config/initializers/rclone.rb

+13-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,21 @@
33
Rails.application.config.after_initialize do
44
next unless Configuration.remote_files_enabled?
55

6-
remotes = RcloneUtil.list_remotes.map { |r| FavoritePath.new('', title: r, filesystem: r) }
6+
remotes = RcloneUtil.list_remotes
7+
8+
if Configuration.remote_files_validation?
9+
# Query remotes in parallel
10+
mutex = Mutex.new
11+
remotes.map do |remote|
12+
Thread.new do
13+
valid = RcloneUtil.valid?(remote)
14+
mutex.synchronize { remotes.delete(remote) } unless valid
15+
end
16+
end.each(&:join)
17+
end
718

819
OodFilesApp.candidate_favorite_paths.tap do |paths|
9-
paths.concat(remotes)
20+
paths.concat(remotes.map { |r| FavoritePath.new('', title: r, filesystem: r) })
1021
end
1122
rescue => e
1223
Rails.logger.error("Cannot add rclone favorite paths because #{e.message}")

apps/dashboard/lib/rclone_util.rb

+15
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,21 @@ def list_remotes
237237
end
238238
end
239239

240+
# Check if remote can be accessed (responds to directory listing request).
241+
def valid?(remote)
242+
# This gives a total max duration of 6s (2s * 3 attempts)
243+
_, _, s = rclone(
244+
'lsd', "#{remote}:",
245+
'--contimeout', '2s',
246+
'--timeout', '2s',
247+
'--low-level-retries', '1',
248+
'--retries', '1'
249+
)
250+
s.success?
251+
rescue StandardError
252+
false
253+
end
254+
240255
def rclone_cmd
241256
# TODO: Make this configurable
242257
"rclone"

apps/dashboard/test/fixtures/config/ondemand.d/booleans.yml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ bc_simple_auto_accounts: true
55
per_cluster_dataroot: true
66
file_navigator: true
77
remote_files_enabled: true
8+
remote_files_validation: true
89
host_based_profiles: true
910
disable_bc_shell: true
1011
cancel_session_enabled: true

apps/dashboard/test/fixtures/config/rclone/rclone.conf

+5
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,8 @@ env_auth = false
55
access_key_id =
66
secret_access_key =
77
acl = private
8+
9+
# S3 always tried to query endpoint, use swift for testing invalid remotes.
10+
[missing_auth]
11+
type = swift
12+
env_auth = false

apps/dashboard/test/unit/rclone_util_test.rb

+9-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
class RcloneUtilTest < ActiveSupport::TestCase
66
test "list_remotes handles rclone.conf and env" do
77
with_rclone_conf("/") do
8-
assert_equal ["alias_remote", "local_remote", "s3"], RcloneUtil.list_remotes
8+
assert_equal ["alias_remote", "local_remote", "missing_auth", "s3"], RcloneUtil.list_remotes
99
end
1010
end
1111

@@ -14,4 +14,12 @@ class RcloneUtilTest < ActiveSupport::TestCase
1414
assert_equal [], RcloneUtil.list_remotes
1515
end
1616
end
17+
18+
test 'missing remote or missing auth is considered invalid' do
19+
with_rclone_conf('/') do
20+
refute RcloneUtil.valid?('missing_remote')
21+
refute RcloneUtil.valid?('missing_auth')
22+
assert RcloneUtil.valid?('local_remote')
23+
end
24+
end
1725
end

0 commit comments

Comments
 (0)