morpheus-cli 3.4.1.10 → 3.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/morpheus/api/api_client.rb +4 -0
- data/lib/morpheus/api/cypher_interface.rb +55 -0
- data/lib/morpheus/api/storage_providers_interface.rb +113 -0
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/cli/archives_command.rb +5 -6
- data/lib/morpheus/cli/cli_command.rb +10 -1
- data/lib/morpheus/cli/clouds.rb +1 -0
- data/lib/morpheus/cli/cypher_command.rb +412 -0
- data/lib/morpheus/cli/echo_command.rb +1 -1
- data/lib/morpheus/cli/library_option_lists_command.rb +109 -30
- data/lib/morpheus/cli/policies_command.rb +208 -118
- data/lib/morpheus/cli/set_prompt_command.rb +1 -1
- data/lib/morpheus/cli/shell.rb +3 -2
- data/lib/morpheus/cli/storage_providers_command.rb +788 -5
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/terminal.rb +1 -1
- metadata +5 -3
data/lib/morpheus/cli/shell.rb
CHANGED
@@ -80,8 +80,8 @@ class Morpheus::Cli::Shell
|
|
80
80
|
end
|
81
81
|
# cleanup empty brackets caused by var value
|
82
82
|
@calculated_prompt = @calculated_prompt.gsub("[]", "").gsub("<>", "").gsub("{}", "")
|
83
|
-
|
84
|
-
@calculated_prompt = "#{@calculated_prompt}#{reset} "
|
83
|
+
#@calculated_prompt = @calculated_prompt.strip
|
84
|
+
# @calculated_prompt = "#{@calculated_prompt}#{reset} "
|
85
85
|
@calculated_prompt
|
86
86
|
end
|
87
87
|
|
@@ -211,6 +211,7 @@ class Morpheus::Cli::Shell
|
|
211
211
|
input = input.strip
|
212
212
|
|
213
213
|
result = execute(input)
|
214
|
+
print reset
|
214
215
|
end
|
215
216
|
end
|
216
217
|
|
@@ -12,7 +12,17 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
12
12
|
set_command_name :'storage-providers'
|
13
13
|
|
14
14
|
register_subcommands :list, :get, :add, :update, :remove
|
15
|
-
|
15
|
+
# file commands
|
16
|
+
register_subcommands :'list-files' => :list_files
|
17
|
+
register_subcommands :'ls' => :ls
|
18
|
+
#register_subcommands :'file' => :get_file
|
19
|
+
# register_subcommands :'history' => :file_history
|
20
|
+
register_subcommands :'upload' => :upload_file
|
21
|
+
register_subcommands :'download' => :download_file
|
22
|
+
register_subcommands :'read' => :read_file
|
23
|
+
register_subcommands :'remove-file' => :remove_file
|
24
|
+
register_subcommands :'rm' => :remove_file
|
25
|
+
|
16
26
|
# set_default_subcommand :list
|
17
27
|
|
18
28
|
def initialize()
|
@@ -39,6 +49,11 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
39
49
|
opts.footer = "List storage providers."
|
40
50
|
end
|
41
51
|
optparse.parse!(args)
|
52
|
+
if args.count != 0
|
53
|
+
print_error Morpheus::Terminal.angry_prompt
|
54
|
+
puts_error "wrong number of arguments, expected 0 and got #{args.count}\n#{optparse}"
|
55
|
+
return 1
|
56
|
+
end
|
42
57
|
connect(options)
|
43
58
|
begin
|
44
59
|
params.merge!(parse_list_options(options))
|
@@ -158,6 +173,7 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
158
173
|
def add(args)
|
159
174
|
options = {}
|
160
175
|
ip_range_list = nil
|
176
|
+
create_bucket = nil
|
161
177
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
162
178
|
opts.banner = subcommand_usage()
|
163
179
|
opts.on('--name VALUE', String, "Name for this storage provider") do |val|
|
@@ -181,6 +197,9 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
181
197
|
opts.on('--copy-to-store [on|off]', String, "Archive Snapshots") do |val|
|
182
198
|
options['copyToStore'] = val.to_s == 'on' || val.to_s == 'true'
|
183
199
|
end
|
200
|
+
#opts.on('--create-bucket [on|off]', String, "Create Bucket") do |val|
|
201
|
+
# create_bucket = val.to_s == 'on' || val.to_s == 'true' || val.nil?
|
202
|
+
#end
|
184
203
|
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
185
204
|
opts.footer = "Create a new storage provider." + "\n" +
|
186
205
|
"[name] is required and can be passed as --name instead."
|
@@ -244,14 +263,17 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
244
263
|
{'fieldContext' => 'config', 'fieldName' => 'accessKey', 'fieldLabel' => 'Access Key', 'type' => 'text', 'required' => true, 'description' => ''},
|
245
264
|
{'fieldContext' => 'config', 'fieldName' => 'secretKey', 'fieldLabel' => 'Secret Key', 'type' => 'password', 'required' => true, 'description' => ''},
|
246
265
|
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''},
|
247
|
-
{'
|
266
|
+
{'fieldName' => 'createBucket', 'fieldLabel' => 'Create Bucket', 'type' => 'checkbox', 'required' => false, 'defaultValue' => false, 'description' => 'Create the bucket if it does not exist.'},
|
267
|
+
{'fieldContext' => 'config', 'fieldName' => 'region', 'fieldLabel' => 'Region', 'type' => 'text', 'required' => false, 'description' => 'Optional Amazon region if creating a new bucket.'},
|
268
|
+
{'fieldContext' => 'config', 'fieldName' => 'endpoint', 'fieldLabel' => 'Endpoint URL', 'type' => 'text', 'required' => false, 'description' => 'Optional endpoint URL if pointing to an object store other than amazon that mimics the Amazon S3 APIs.'}
|
248
269
|
]
|
249
270
|
elsif storage_provider_type_code == 'azure'
|
250
271
|
# print_h2 "Azure Options"
|
251
272
|
provider_type_option_types = [
|
252
273
|
{'fieldContext' => 'config', 'fieldName' => 'storageAccount', 'fieldLabel' => 'Storage Account', 'type' => 'text', 'required' => true, 'description' => ''},
|
253
274
|
{'fieldContext' => 'config', 'fieldName' => 'storageKey', 'fieldLabel' => 'Storage Key', 'type' => 'password', 'required' => true, 'description' => ''},
|
254
|
-
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''}
|
275
|
+
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''},
|
276
|
+
{'fieldName' => 'createBucket', 'fieldLabel' => 'Create Bucket', 'type' => 'checkbox', 'required' => false, 'defaultValue' => false, 'description' => 'Create the bucket if it does not exist.'},
|
255
277
|
]
|
256
278
|
elsif storage_provider_type_code == 'cifs'
|
257
279
|
# print_h2 "CIFS Options"
|
@@ -281,6 +303,7 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
281
303
|
{'fieldContext' => 'config', 'fieldName' => 'apiKey', 'fieldLabel' => 'API Key', 'type' => 'password', 'required' => true, 'description' => ''},
|
282
304
|
{'fieldContext' => 'config', 'fieldName' => 'region', 'fieldLabel' => 'Region', 'type' => 'text', 'required' => true, 'description' => ''},
|
283
305
|
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''},
|
306
|
+
{'fieldName' => 'createBucket', 'fieldLabel' => 'Create Bucket', 'type' => 'checkbox', 'required' => false, 'defaultValue' => false, 'description' => 'Create the bucket if it does not exist.'},
|
284
307
|
{'fieldContext' => 'config', 'fieldName' => 'identityUrl', 'fieldLabel' => 'Identity URL', 'type' => 'text', 'required' => true, 'description' => ''},
|
285
308
|
]
|
286
309
|
elsif storage_provider_type_code == 'rackspace'
|
@@ -289,6 +312,7 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
289
312
|
{'fieldContext' => 'config', 'fieldName' => 'accessKey', 'fieldLabel' => 'Access Key', 'type' => 'text', 'required' => true, 'description' => ''},
|
290
313
|
{'fieldContext' => 'config', 'fieldName' => 'secretKey', 'fieldLabel' => 'Secret Key', 'type' => 'password', 'required' => true, 'description' => ''},
|
291
314
|
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''},
|
315
|
+
{'fieldName' => 'createBucket', 'fieldLabel' => 'Create Bucket', 'type' => 'checkbox', 'required' => false, 'defaultValue' => false, 'description' => 'Create the bucket if it does not exist.'},
|
292
316
|
{'fieldContext' => 'config', 'fieldName' => 'endpoint', 'fieldLabel' => 'Endpoint URL', 'type' => 'text', 'required' => true, 'description' => 'Optional endpoint URL if pointing to an object store other than amazon that mimics the Amazon S3 APIs.'},
|
293
317
|
]
|
294
318
|
else
|
@@ -330,7 +354,12 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
330
354
|
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultVirtualImageTarget', 'fieldLabel' => 'Default Virtual Image Store', 'type' => 'checkbox', 'required' => false, 'description' => '', 'defaultValue' => 'off'}], options)
|
331
355
|
payload['storageProvider']['defaultVirtualImageTarget'] = (v_prompt['defaultVirtualImageTarget'].to_s == 'on') unless v_prompt['defaultVirtualImageTarget'].nil?
|
332
356
|
end
|
333
|
-
|
357
|
+
#if create_bucket
|
358
|
+
# payload['createBucket'] = true
|
359
|
+
#end
|
360
|
+
if payload['storageProvider']['createBucket'] == 'on'
|
361
|
+
payload['storageProvider']['createBucket'] = true
|
362
|
+
end
|
334
363
|
end
|
335
364
|
|
336
365
|
|
@@ -440,6 +469,9 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
440
469
|
payload['storageProvider']['defaultVirtualImageTarget'] = options['defaultVirtualImageTarget']
|
441
470
|
end
|
442
471
|
|
472
|
+
if payload['storageProvider']['createBucket'] == 'on'
|
473
|
+
payload['storageProvider']['createBucket'] = true
|
474
|
+
end
|
443
475
|
end
|
444
476
|
|
445
477
|
if options[:dry_run]
|
@@ -465,7 +497,7 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
465
497
|
options = {}
|
466
498
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
467
499
|
opts.banner = subcommand_usage("[storage-provider]")
|
468
|
-
build_common_options(opts, options, [:
|
500
|
+
build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
|
469
501
|
opts.footer = "Delete a storage provider." + "\n" +
|
470
502
|
"[storage-provider] is required. This is the name or id of a storage provider."
|
471
503
|
end
|
@@ -504,6 +536,686 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
504
536
|
end
|
505
537
|
end
|
506
538
|
|
539
|
+
def list_files(args)
|
540
|
+
options = {}
|
541
|
+
params = {}
|
542
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
543
|
+
opts.banner = subcommand_usage("[provider:/path]")
|
544
|
+
opts.on('-a', '--all', "Show all files, including subdirectories under the /path.") do
|
545
|
+
params[:fullTree] = true
|
546
|
+
end
|
547
|
+
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run])
|
548
|
+
opts.footer = "List files in a storage provider. \nInclude [/path] to show files under a directory."
|
549
|
+
end
|
550
|
+
optparse.parse!(args)
|
551
|
+
if args.count < 1 || args.count > 2
|
552
|
+
print_error Morpheus::Terminal.angry_prompt
|
553
|
+
puts_error "#{command_name} list-files expects 1-2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
554
|
+
return 1
|
555
|
+
end
|
556
|
+
storage_provider_id, search_file_path = parse_storage_provider_id_and_file_path(args[0], args[1])
|
557
|
+
connect(options)
|
558
|
+
begin
|
559
|
+
storage_provider = find_storage_provider_by_name_or_id(storage_provider_id)
|
560
|
+
return 1 if storage_provider.nil?
|
561
|
+
params.merge!(parse_list_options(options))
|
562
|
+
[:fullTree].each do |k|
|
563
|
+
params[k] = options[k] unless options[k].nil?
|
564
|
+
end
|
565
|
+
if options[:dry_run]
|
566
|
+
print_dry_run @storage_providers_interface.dry.list_files(storage_provider['id'], search_file_path, params)
|
567
|
+
return
|
568
|
+
end
|
569
|
+
json_response = @storage_providers_interface.list_files(storage_provider['id'], search_file_path, params)
|
570
|
+
storage_files = json_response['storageFiles']
|
571
|
+
# storage_provider = json_response['storageProvider']
|
572
|
+
if options[:json]
|
573
|
+
print JSON.pretty_generate(json_response)
|
574
|
+
return
|
575
|
+
end
|
576
|
+
if options[:json]
|
577
|
+
puts as_json(json_response, options, "storageFiles")
|
578
|
+
return 0
|
579
|
+
elsif options[:yaml]
|
580
|
+
puts as_yaml(json_response, options, "storageFiles")
|
581
|
+
return 0
|
582
|
+
elsif options[:csv]
|
583
|
+
puts records_as_csv(json_response['storageFiles'], options)
|
584
|
+
return 0
|
585
|
+
end
|
586
|
+
print_h1 "Storage Files", ["#{storage_provider['name']}:#{search_file_path}"]
|
587
|
+
print cyan
|
588
|
+
description_cols = {
|
589
|
+
"ID" => 'id',
|
590
|
+
"Name" => 'name',
|
591
|
+
# "Bucket Name" => 'bucketName',
|
592
|
+
#"Path" => lambda {|it| search_file_path }
|
593
|
+
}
|
594
|
+
#print_description_list(description_cols, storage_provider)
|
595
|
+
#print "\n"
|
596
|
+
#print_h2 "Path: #{search_file_path}"
|
597
|
+
# print "Directory: #{search_file_path}"
|
598
|
+
if storage_files && storage_files.size > 0
|
599
|
+
print_storage_files_table(storage_files, {fullTree: params[:fullTree]})
|
600
|
+
#print_results_pagination(json_response, {:label => "file", :n_label => "files"})
|
601
|
+
print reset, "\n"
|
602
|
+
return 0
|
603
|
+
else
|
604
|
+
# puts "No files found for path #{search_file_path}"
|
605
|
+
if search_file_path.empty? || search_file_path == "/"
|
606
|
+
puts "This storage provider has no files."
|
607
|
+
print reset,"\n"
|
608
|
+
return 0
|
609
|
+
else
|
610
|
+
puts "No files found for path #{search_file_path}"
|
611
|
+
print reset,"\n"
|
612
|
+
return 1
|
613
|
+
end
|
614
|
+
end
|
615
|
+
rescue RestClient::Exception => e
|
616
|
+
print_rest_exception(e, options)
|
617
|
+
return 1
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
def ls(args)
|
622
|
+
options = {}
|
623
|
+
params = {}
|
624
|
+
do_one_file_per_line = false
|
625
|
+
do_long_format = false
|
626
|
+
do_human_bytes = false
|
627
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
628
|
+
opts.banner = subcommand_usage("[provider/path]")
|
629
|
+
opts.on('-a', '--all', "Show all files, including subdirectories under the /path.") do
|
630
|
+
params[:fullTree] = true
|
631
|
+
do_one_file_per_line = true
|
632
|
+
end
|
633
|
+
opts.on('-l', '--long', "Lists files in the long format, which contains lots of useful information, e.g. the exact size of the file, the file type, and when it was last modified.") do
|
634
|
+
do_long_format = true
|
635
|
+
do_one_file_per_line
|
636
|
+
end
|
637
|
+
opts.on('-H', '--human', "Humanized file sizes. The default is just the number of bytes.") do
|
638
|
+
do_human_bytes = true
|
639
|
+
end
|
640
|
+
opts.on('-1', '--oneline', "One file per line. The default delimiter is a single space.") do
|
641
|
+
do_one_file_per_line = true
|
642
|
+
end
|
643
|
+
build_common_options(opts, options, [:list, :json, :fields, :dry_run])
|
644
|
+
opts.footer = "Print filenames for a given location.\nPass storage location in the format provider/path."
|
645
|
+
end
|
646
|
+
optparse.parse!(args)
|
647
|
+
if args.count < 1 || args.count > 2
|
648
|
+
print_error Morpheus::Terminal.angry_prompt
|
649
|
+
puts_error "#{command_name} ls expects 1-2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
650
|
+
return 1
|
651
|
+
end
|
652
|
+
storage_provider_id, search_file_path = parse_storage_provider_id_and_file_path(args[0], args[1])
|
653
|
+
connect(options)
|
654
|
+
begin
|
655
|
+
storage_provider = find_storage_provider_by_name_or_id(storage_provider_id)
|
656
|
+
return 1 if storage_provider.nil?
|
657
|
+
params.merge!(parse_list_options(options))
|
658
|
+
[:fullTree].each do |k|
|
659
|
+
params[k] = options[k] unless options[k].nil?
|
660
|
+
end
|
661
|
+
if options[:dry_run]
|
662
|
+
print_dry_run @storage_providers_interface.dry.list_files(storage_provider['id'], search_file_path, params)
|
663
|
+
return 0
|
664
|
+
end
|
665
|
+
json_response = @storage_providers_interface.list_files(storage_provider['id'], search_file_path, params)
|
666
|
+
if options[:json]
|
667
|
+
puts as_json(json_response, options, "storageFiles")
|
668
|
+
# no files is an error condition for this command
|
669
|
+
if !json_response['storageFiles'] || json_response['storageFiles'].size == 0
|
670
|
+
return 1
|
671
|
+
end
|
672
|
+
return 0
|
673
|
+
end
|
674
|
+
#storage_provider = json_response['storageProvider'] # yep, this is returned too
|
675
|
+
storage_files = json_response['storageFiles']
|
676
|
+
# print_h2 "Directory: #{search_file_path}"
|
677
|
+
# print "Directory: #{search_file_path}"
|
678
|
+
if storage_files && storage_files.size > 0
|
679
|
+
if do_long_format
|
680
|
+
# ls long format
|
681
|
+
# owner groups filesize type filename
|
682
|
+
now = Time.now
|
683
|
+
storage_files.each do |storage_file|
|
684
|
+
# -rw-r--r-- 1 jdickson staff 1361 Oct 23 08:00 voltron_2.10.log
|
685
|
+
file_color = cyan # reset
|
686
|
+
if storage_file['isDirectory']
|
687
|
+
file_color = blue
|
688
|
+
end
|
689
|
+
file_info = []
|
690
|
+
# Number of links
|
691
|
+
# file_info << file["linkCount"].to_i + 1
|
692
|
+
# Owner
|
693
|
+
owner_str = ""
|
694
|
+
if storage_file['owner']
|
695
|
+
owner_str = storage_file['owner']['name']
|
696
|
+
elsif storage_provider['owner']
|
697
|
+
owner_str = storage_provider['owner']['name']
|
698
|
+
else
|
699
|
+
owner_str = "noone"
|
700
|
+
end
|
701
|
+
#file_info << truncate_string(owner_str, 15).ljust(15, " ")
|
702
|
+
# Group (Tenants)
|
703
|
+
groups_str = ""
|
704
|
+
if storage_file['visibility'] == 'public'
|
705
|
+
# this is confusing because of Public URL (isPublic) setting
|
706
|
+
groups_str = "public"
|
707
|
+
else
|
708
|
+
if storage_file['accounts'].instance_of?(Array) && storage_file['accounts'].size > 0
|
709
|
+
# groups_str = storage_file['accounts'].collect {|it| it['name'] }.join(',')
|
710
|
+
groups_str = (storage_file['accounts'].size == 1) ? "#{storage_file['accounts'][0]['name']}" : "#{storage_file['accounts'].size} tenants"
|
711
|
+
elsif storage_provider['accounts'].instance_of?(Array) && storage_provider['accounts'].size > 0
|
712
|
+
# groups_str = storage_provider['accounts'].collect {|it| it['name'] }.join(',')
|
713
|
+
groups_str = (storage_provider['accounts'].size == 1) ? "#{storage_provider['accounts'][0]['name']}" : "#{storage_provider['accounts'].size} tenants"
|
714
|
+
else
|
715
|
+
groups_str = owner_str
|
716
|
+
end
|
717
|
+
end
|
718
|
+
#file_info << truncate_string(groups_str, 15).ljust(15, " ")
|
719
|
+
# File Type
|
720
|
+
content_type = storage_file['contentType'].to_s
|
721
|
+
if storage_file['isDirectory']
|
722
|
+
content_type = "directory"
|
723
|
+
else
|
724
|
+
content_type = storage_file['contentType'].to_s
|
725
|
+
end
|
726
|
+
file_info << content_type.ljust(25, " ")
|
727
|
+
filesize_str = ""
|
728
|
+
if do_human_bytes
|
729
|
+
# filesize_str = format_bytes(storage_file['contentLength'])
|
730
|
+
filesize_str = format_bytes_short(storage_file['contentLength'])
|
731
|
+
else
|
732
|
+
filesize_str = storage_file['contentLength'].to_i.to_s
|
733
|
+
end
|
734
|
+
# file_info << filesize_str.ljust(12, " ")
|
735
|
+
file_info << filesize_str.ljust(7, " ")
|
736
|
+
mtime = ""
|
737
|
+
last_updated = parse_time(storage_file['dateModified'])
|
738
|
+
if last_updated
|
739
|
+
if last_updated.year == now.year
|
740
|
+
mtime = format_local_dt(last_updated, {format: "%b %e %H:%M"})
|
741
|
+
else
|
742
|
+
mtime = format_local_dt(last_updated, {format: "%b %e %Y"})
|
743
|
+
end
|
744
|
+
end
|
745
|
+
file_info << mtime.ljust(12, " ")
|
746
|
+
fn = format_filename(storage_file['name'], {fullTree: params[:fullTree]})
|
747
|
+
file_info << file_color + fn.to_s + cyan
|
748
|
+
print cyan, file_info.join(" "), reset, "\n"
|
749
|
+
end
|
750
|
+
else
|
751
|
+
file_names = storage_files.collect do |storage_file|
|
752
|
+
file_color = cyan # reset
|
753
|
+
if storage_file['isDirectory']
|
754
|
+
file_color = blue
|
755
|
+
end
|
756
|
+
fn = format_filename(storage_file['name'], {fullTree: params[:fullTree]})
|
757
|
+
file_color + fn.to_s + reset
|
758
|
+
end
|
759
|
+
if do_one_file_per_line
|
760
|
+
print file_names.join("\n")
|
761
|
+
else
|
762
|
+
print file_names.join("\t")
|
763
|
+
end
|
764
|
+
print "\n"
|
765
|
+
end
|
766
|
+
else
|
767
|
+
print_error yellow, "No files found for path: #{search_file_path}", reset, "\n"
|
768
|
+
return 1
|
769
|
+
end
|
770
|
+
|
771
|
+
return 0
|
772
|
+
rescue RestClient::Exception => e
|
773
|
+
print_rest_exception(e, options)
|
774
|
+
return 1
|
775
|
+
end
|
776
|
+
end
|
777
|
+
|
778
|
+
# def get_file(args)
|
779
|
+
# todo...
|
780
|
+
# end
|
781
|
+
|
782
|
+
def upload_file(args)
|
783
|
+
options = {}
|
784
|
+
query_params = {}
|
785
|
+
do_recursive = false
|
786
|
+
ignore_regexp = nil
|
787
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
788
|
+
opts.banner = subcommand_usage("[local-file] [provider:/path]")
|
789
|
+
# opts.on('--filename FILEPATH', String, "Remote file path for the file or folder being uploaded, this is an alternative to [remote-file-path]." ) do |val|
|
790
|
+
# options['type'] = val
|
791
|
+
# end
|
792
|
+
opts.on( '-R', '--recursive', "Upload a directory and all of its files. This must be passed if [local-file] is a directory." ) do
|
793
|
+
do_recursive = true
|
794
|
+
end
|
795
|
+
opts.on('--ignore-files PATTERN', String, "Pattern of files to be ignored when uploading a directory." ) do |val|
|
796
|
+
ignore_regexp = /#{Regexp.escape(val)}/
|
797
|
+
end
|
798
|
+
opts.footer = "Upload a local file or folder to a storage provider. " +
|
799
|
+
"\nThe first argument [local-file] should be the path of a local file or directory." +
|
800
|
+
"\nThe second argument [provider:/path] should contain the name or id of the provider." +
|
801
|
+
"\nThe [:/path] component is optional and can be used to specify the destination of the uploaded file or folder." +
|
802
|
+
"\nThe default destination is the same name as the [local-file], under the root directory '/'. " +
|
803
|
+
"\nThis will overwrite any existing remote files that match the destination /path."
|
804
|
+
build_common_options(opts, options, [:auto_confirm, :json, :dry_run])
|
805
|
+
end
|
806
|
+
optparse.parse!(args)
|
807
|
+
|
808
|
+
if args.count != 2
|
809
|
+
print_error Morpheus::Terminal.angry_prompt
|
810
|
+
puts_error "#{command_name} upload expects 2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
811
|
+
return 1
|
812
|
+
end
|
813
|
+
# validate local file path
|
814
|
+
local_file_path = File.expand_path(args[0].squeeze('/'))
|
815
|
+
if local_file_path == "" || local_file_path == "/" || local_file_path == "."
|
816
|
+
print_error Morpheus::Terminal.angry_prompt
|
817
|
+
puts_error "#{command_name} missing argument: [local-file]\n#{optparse}"
|
818
|
+
return 1
|
819
|
+
end
|
820
|
+
if !File.exists?(local_file_path)
|
821
|
+
print_error Morpheus::Terminal.angry_prompt
|
822
|
+
puts_error "#{command_name} bad argument: [local-file]\nFile '#{local_file_path}' was not found.\n#{optparse}"
|
823
|
+
return 1
|
824
|
+
end
|
825
|
+
|
826
|
+
# validate provider:/path
|
827
|
+
storage_provider_id, remote_file_path = parse_storage_provider_id_and_file_path(args[1], args[2])
|
828
|
+
|
829
|
+
# if local_file_path.include?('../') # || options[:yes]
|
830
|
+
# raise_command_error "Sorry, you may not use relative paths in your local filepath."
|
831
|
+
# end
|
832
|
+
|
833
|
+
# validate provider name (or id)
|
834
|
+
if !storage_provider_id
|
835
|
+
print_error Morpheus::Terminal.angry_prompt
|
836
|
+
puts_error "#{command_name} missing argument: [provider]\n#{optparse}"
|
837
|
+
return 1
|
838
|
+
end
|
839
|
+
|
840
|
+
# strip leading slash of remote name
|
841
|
+
# if remote_file_path[0].chr == "/"
|
842
|
+
# remote_file_path = remote_file_path[1..-1]
|
843
|
+
# end
|
844
|
+
|
845
|
+
if remote_file_path.include?('./') # || options[:yes]
|
846
|
+
raise_command_error "Sorry, you may not use relative paths in your remote filepath."
|
847
|
+
end
|
848
|
+
|
849
|
+
# if !options[:yes]
|
850
|
+
scary_local_paths = ["/", "/root", "C:\\"]
|
851
|
+
if scary_local_paths.include?(local_file_path)
|
852
|
+
unless Morpheus::Cli::OptionTypes.confirm("Are you sure you want to upload all the files in local directory '#{local_file_path}' !?")
|
853
|
+
return 9, "aborted command"
|
854
|
+
end
|
855
|
+
end
|
856
|
+
# end
|
857
|
+
|
858
|
+
connect(options)
|
859
|
+
begin
|
860
|
+
storage_provider = find_storage_provider_by_name_or_id(storage_provider_id)
|
861
|
+
return 1 if storage_provider.nil?
|
862
|
+
|
863
|
+
# how many files we dealing with?
|
864
|
+
files_to_upload = []
|
865
|
+
if File.directory?(local_file_path)
|
866
|
+
# upload directory
|
867
|
+
if !do_recursive
|
868
|
+
print_error Morpheus::Terminal.angry_prompt
|
869
|
+
puts_error "bad argument: '#{local_file_path}' is a directory. Use -R or --recursive to upload a directory.\n#{optparse}"
|
870
|
+
return 1
|
871
|
+
end
|
872
|
+
found_files = Dir.glob("#{local_file_path}/**/*")
|
873
|
+
# note: api call for directories is not needed
|
874
|
+
found_files = found_files.select {|file| File.file?(file) }
|
875
|
+
if ignore_regexp
|
876
|
+
found_files = found_files.reject {|it| it =~ ignore_regexp}
|
877
|
+
end
|
878
|
+
files_to_upload = found_files
|
879
|
+
|
880
|
+
if files_to_upload.size == 0
|
881
|
+
print_error Morpheus::Terminal.angry_prompt
|
882
|
+
puts_error "bad argument: Local directory '#{local_file_path}' contains 0 files."
|
883
|
+
return 1
|
884
|
+
end
|
885
|
+
|
886
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to upload directory #{local_file_path} (#{files_to_upload.size} files) to #{storage_provider['name']}:#{remote_file_path}?")
|
887
|
+
return 9, "aborted command"
|
888
|
+
end
|
889
|
+
|
890
|
+
if !options[:yes]
|
891
|
+
if files_to_upload.size > 100
|
892
|
+
unless Morpheus::Cli::OptionTypes.confirm("Are you REALLY sure you want to upload #{files_to_upload.size} files ?")
|
893
|
+
return 9, "aborted command"
|
894
|
+
end
|
895
|
+
end
|
896
|
+
end
|
897
|
+
|
898
|
+
# local_dirname = File.dirname(local_file_path)
|
899
|
+
# local_basename = File.basename(local_file_path)
|
900
|
+
upload_file_list = []
|
901
|
+
files_to_upload.each do |file|
|
902
|
+
destination = file.sub(local_file_path, (remote_file_path || "")).squeeze('/')
|
903
|
+
upload_file_list << {file: file, destination: destination}
|
904
|
+
end
|
905
|
+
|
906
|
+
if options[:dry_run]
|
907
|
+
# print_h1 "DRY RUN"
|
908
|
+
print "\n",cyan, bold, "Uploading #{upload_file_list.size} Files...", reset, "\n"
|
909
|
+
upload_file_list.each do |obj|
|
910
|
+
file, destination = obj[:file], obj[:destination]
|
911
|
+
#print cyan,bold, " - Uploading #{file} to #{storage_provider_id}:#{destination} DRY RUN", reset, "\n"
|
912
|
+
print_dry_run @storage_providers_interface.dry.upload_file(storage_provider['id'], file, destination)
|
913
|
+
print "\n"
|
914
|
+
end
|
915
|
+
return 0
|
916
|
+
end
|
917
|
+
|
918
|
+
print "\n",cyan, bold, "Uploading #{upload_file_list.size} Files...", reset, "\n"
|
919
|
+
bad_upload_responses = []
|
920
|
+
upload_file_list.each do |obj|
|
921
|
+
file, destination = obj[:file], obj[:destination]
|
922
|
+
print cyan,bold, " - Uploading #{file} to #{storage_provider_id}:#{destination}", reset
|
923
|
+
upload_response = @storage_providers_interface.upload_file(storage_provider['id'], file, destination)
|
924
|
+
if upload_response['success']
|
925
|
+
print bold," #{green}SUCCESS#{reset}"
|
926
|
+
else
|
927
|
+
print bold," #{red}ERROR#{reset}"
|
928
|
+
if upload_response['msg']
|
929
|
+
bad_upload_responses << upload_response
|
930
|
+
print " #{upload_response['msg']}#{reset}"
|
931
|
+
end
|
932
|
+
end
|
933
|
+
print "\n"
|
934
|
+
end
|
935
|
+
if bad_upload_responses.size > 0
|
936
|
+
print cyan, bold, "Completed Upload of #{upload_file_list.size} Files. #{red}#{bad_upload_responses.size} Errors!", reset, "\n"
|
937
|
+
else
|
938
|
+
print cyan, bold, "Completed Upload of #{upload_file_list.size} Files!", reset, "\n"
|
939
|
+
end
|
940
|
+
|
941
|
+
else
|
942
|
+
|
943
|
+
# upload file
|
944
|
+
if !File.exists?(local_file_path) && !File.file?(local_file_path)
|
945
|
+
print_error Morpheus::Terminal.angry_prompt
|
946
|
+
puts_error "#{command_name} bad argument: [local-file]\nFile '#{local_file_path}' was not found.\n#{optparse}"
|
947
|
+
return 1
|
948
|
+
end
|
949
|
+
|
950
|
+
# local_dirname = File.dirname(local_file_path)
|
951
|
+
# local_basename = File.basename(local_file_path)
|
952
|
+
|
953
|
+
file = local_file_path
|
954
|
+
destination = File.basename(file)
|
955
|
+
if remote_file_path[-1].chr == "/"
|
956
|
+
# work like `cp`, and place into the directory
|
957
|
+
destination = remote_file_path + File.basename(file)
|
958
|
+
elsif remote_file_path
|
959
|
+
# renaming file
|
960
|
+
destination = remote_file_path
|
961
|
+
end
|
962
|
+
destination = destination.squeeze('/')
|
963
|
+
|
964
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to upload #{local_file_path} to #{storage_provider['name']}:#{destination}?")
|
965
|
+
return 9, "aborted command"
|
966
|
+
end
|
967
|
+
|
968
|
+
if options[:dry_run]
|
969
|
+
#print cyan,bold, " - Uploading #{file} to #{storage_provider_id}:#{destination} DRY RUN", reset, "\n"
|
970
|
+
# print_h1 "DRY RUN"
|
971
|
+
print_dry_run @storage_providers_interface.dry.upload_file(storage_provider['id'], file, destination)
|
972
|
+
print "\n"
|
973
|
+
return 0
|
974
|
+
end
|
975
|
+
|
976
|
+
print cyan,bold, " - Uploading #{file} to #{storage_provider_id}:#{destination}", reset
|
977
|
+
upload_response = @storage_providers_interface.upload_file(storage_provider['id'], file, destination)
|
978
|
+
if upload_response['success']
|
979
|
+
print bold," #{green}Success#{reset}"
|
980
|
+
else
|
981
|
+
print bold," #{red}Error#{reset}"
|
982
|
+
if upload_response['msg']
|
983
|
+
print " #{upload_response['msg']}#{reset}"
|
984
|
+
end
|
985
|
+
end
|
986
|
+
print "\n"
|
987
|
+
|
988
|
+
end
|
989
|
+
#print cyan, bold, "Upload Complete!", reset, "\n"
|
990
|
+
|
991
|
+
return 0
|
992
|
+
rescue RestClient::Exception => e
|
993
|
+
print_rest_exception(e, options)
|
994
|
+
return 1
|
995
|
+
end
|
996
|
+
end
|
997
|
+
|
998
|
+
def download_file(args)
|
999
|
+
full_command_string = "#{command_name} download #{args.join(' ')}".strip
|
1000
|
+
options = {}
|
1001
|
+
outfile = nil
|
1002
|
+
do_overwrite = false
|
1003
|
+
do_mkdir = false
|
1004
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1005
|
+
opts.banner = subcommand_usage("[provider:/path] [local-file]")
|
1006
|
+
opts.on( '-f', '--force', "Overwrite existing [local-file] if it exists." ) do
|
1007
|
+
do_overwrite = true
|
1008
|
+
# do_mkdir = true
|
1009
|
+
end
|
1010
|
+
opts.on( '-p', '--mkdir', "Create missing directories for [local-file] if they do not exist." ) do
|
1011
|
+
do_mkdir = true
|
1012
|
+
end
|
1013
|
+
build_common_options(opts, options, [:dry_run, :quiet])
|
1014
|
+
opts.footer = "Download a file or directory.\n" +
|
1015
|
+
"[provider:/path] is required. This is the name or id of the provider and /path the file or folder to be downloaded.\n" +
|
1016
|
+
"[local-file] is required. This is the full local filepath for the downloaded file.\n" +
|
1017
|
+
"Directories will be downloaded as a .zip file, so you'll want to specify a [local-file] with a .zip extension."
|
1018
|
+
end
|
1019
|
+
optparse.parse!(args)
|
1020
|
+
if args.count < 2 || args.count > 3
|
1021
|
+
print_error Morpheus::Terminal.angry_prompt
|
1022
|
+
puts_error "#{command_name} download expects 2-3 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
1023
|
+
return 1
|
1024
|
+
end
|
1025
|
+
storage_provider_id = nil
|
1026
|
+
local = nil
|
1027
|
+
outfile = nil
|
1028
|
+
if args.count == 3
|
1029
|
+
storage_provider_id, file_path = parse_storage_provider_id_and_file_path(args[0], args[1])
|
1030
|
+
outfile = args[2]
|
1031
|
+
else
|
1032
|
+
storage_provider_id, file_path = parse_storage_provider_id_and_file_path(args[0])
|
1033
|
+
outfile = args[1]
|
1034
|
+
end
|
1035
|
+
connect(options)
|
1036
|
+
begin
|
1037
|
+
storage_provider = find_storage_provider_by_name_or_id(storage_provider_id)
|
1038
|
+
return 1 if storage_provider.nil?
|
1039
|
+
|
1040
|
+
file_path = file_path.squeeze('/')
|
1041
|
+
outfile = File.expand_path(outfile)
|
1042
|
+
if Dir.exists?(outfile)
|
1043
|
+
outfile = File.join(outfile, File.basename(file_path))
|
1044
|
+
end
|
1045
|
+
if Dir.exists?(outfile)
|
1046
|
+
print_red_alert "[local-file] is invalid. It is the name of an existing directory: #{outfile}"
|
1047
|
+
return 1
|
1048
|
+
end
|
1049
|
+
destination_dir = File.dirname(outfile)
|
1050
|
+
if !Dir.exists?(destination_dir)
|
1051
|
+
if do_mkdir
|
1052
|
+
print cyan,"Creating local directory #{destination_dir}",reset,"\n"
|
1053
|
+
FileUtils.mkdir_p(destination_dir)
|
1054
|
+
else
|
1055
|
+
print_red_alert "[local-file] is invalid. Directory not found: #{destination_dir}"
|
1056
|
+
return 1
|
1057
|
+
end
|
1058
|
+
end
|
1059
|
+
if File.exists?(outfile)
|
1060
|
+
if do_overwrite
|
1061
|
+
# uhh need to be careful wih the passed filepath here..
|
1062
|
+
# don't delete, just overwrite.
|
1063
|
+
# File.delete(outfile)
|
1064
|
+
else
|
1065
|
+
print_error Morpheus::Terminal.angry_prompt
|
1066
|
+
puts_error "[local-file] is invalid. File already exists: #{outfile}", "Use -f to overwrite the existing file."
|
1067
|
+
# puts_error optparse
|
1068
|
+
return 1
|
1069
|
+
end
|
1070
|
+
end
|
1071
|
+
begin
|
1072
|
+
if options[:dry_run]
|
1073
|
+
print_dry_run @storage_providers_interface.dry.download_file_chunked(storage_provider['id'], file_path, outfile), full_command_string
|
1074
|
+
return 0
|
1075
|
+
end
|
1076
|
+
if !options[:quiet]
|
1077
|
+
print cyan + "Downloading archive file #{storage_provider['name']}:#{file_path} to #{outfile} ... "
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
http_response = @storage_providers_interface.download_file_chunked(storage_provider['id'], file_path, outfile)
|
1081
|
+
|
1082
|
+
# FileUtils.chmod(0600, outfile)
|
1083
|
+
success = http_response.code.to_i == 200
|
1084
|
+
if success
|
1085
|
+
if !options[:quiet]
|
1086
|
+
print green + "SUCCESS" + reset + "\n"
|
1087
|
+
end
|
1088
|
+
return 0
|
1089
|
+
else
|
1090
|
+
if !options[:quiet]
|
1091
|
+
print red + "ERROR" + reset + " HTTP #{http_response.code}" + "\n"
|
1092
|
+
end
|
1093
|
+
# F it, just remove a bad result
|
1094
|
+
if File.exists?(outfile) && File.file?(outfile)
|
1095
|
+
Morpheus::Logging::DarkPrinter.puts "Deleting bad file download: #{outfile}" if Morpheus::Logging.debug?
|
1096
|
+
File.delete(outfile)
|
1097
|
+
end
|
1098
|
+
if options[:debug]
|
1099
|
+
puts_error http_response.inspect
|
1100
|
+
end
|
1101
|
+
return 1
|
1102
|
+
end
|
1103
|
+
rescue RestClient::Exception => e
|
1104
|
+
# this is not reached
|
1105
|
+
if e.response && e.response.code == 404
|
1106
|
+
print_red_alert "Storage file not found by path #{file_path}"
|
1107
|
+
return nil
|
1108
|
+
else
|
1109
|
+
raise e
|
1110
|
+
end
|
1111
|
+
end
|
1112
|
+
rescue RestClient::Exception => e
|
1113
|
+
print_rest_exception(e, options)
|
1114
|
+
return 1
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
end
|
1118
|
+
|
1119
|
+
def read_file(args)
|
1120
|
+
full_command_string = "#{command_name} read #{args.join(' ')}".strip
|
1121
|
+
options = {}
|
1122
|
+
outfile = nil
|
1123
|
+
do_overwrite = false
|
1124
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1125
|
+
opts.banner = subcommand_usage("[provider:/path]")
|
1126
|
+
build_common_options(opts, options, [:dry_run])
|
1127
|
+
opts.footer = "Print the contents of a storage file.\n" +
|
1128
|
+
"[provider:/path] is required. This is the name or id of the provider and /path the file or folder to be downloaded.\n" +
|
1129
|
+
"This confirmation can be skipped with the -y option."
|
1130
|
+
end
|
1131
|
+
optparse.parse!(args)
|
1132
|
+
if args.count < 1 || args.count > 2
|
1133
|
+
print_error Morpheus::Terminal.angry_prompt
|
1134
|
+
puts_error "#{command_name} read expects 1-2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
1135
|
+
return 1
|
1136
|
+
end
|
1137
|
+
connect(options)
|
1138
|
+
begin
|
1139
|
+
storage_provider_id, file_path = parse_storage_provider_id_and_file_path(args[0], args[1])
|
1140
|
+
storage_provider = find_storage_provider_by_name_or_id(storage_provider_id)
|
1141
|
+
return 1 if storage_provider.nil?
|
1142
|
+
|
1143
|
+
file_path = file_path.squeeze('/')
|
1144
|
+
|
1145
|
+
if options[:dry_run]
|
1146
|
+
print_dry_run @storage_providers_interface.dry.download_file(storage_provider['id'], file_path), full_command_string
|
1147
|
+
return 1
|
1148
|
+
end
|
1149
|
+
file_response = @storage_providers_interface.download_file(storage_provider['id'], file_path)
|
1150
|
+
puts file_response.body.to_s
|
1151
|
+
return 0
|
1152
|
+
rescue RestClient::Exception => e
|
1153
|
+
print_rest_exception(e, options)
|
1154
|
+
return 1
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
end
|
1158
|
+
|
1159
|
+
def remove_file(args)
|
1160
|
+
options = {}
|
1161
|
+
query_params = {}
|
1162
|
+
do_recursive = false
|
1163
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
1164
|
+
opts.banner = subcommand_usage("[provider:/path]")
|
1165
|
+
opts.on( '-R', '--recursive', "Delete a directory and all of its files. This must be passed if specifying a directory." ) do
|
1166
|
+
do_recursive = true
|
1167
|
+
end
|
1168
|
+
build_common_options(opts, options, [:auto_confirm, :json, :dry_run])
|
1169
|
+
opts.footer = "Delete a storage file or directory."
|
1170
|
+
end
|
1171
|
+
optparse.parse!(args)
|
1172
|
+
# consider only allowing args.count == 1 here in the format [provider:/path]
|
1173
|
+
if args.count < 1 || args.count > 2
|
1174
|
+
print_error Morpheus::Terminal.angry_prompt
|
1175
|
+
puts_error "#{command_name} remove-file expects 1-2 arguments and received #{args.count}: #{args.join(' ')}\n#{optparse}"
|
1176
|
+
return 1
|
1177
|
+
end
|
1178
|
+
storage_provider_id, file_path = parse_storage_provider_id_and_file_path(args[0], args[1])
|
1179
|
+
connect(options)
|
1180
|
+
begin
|
1181
|
+
|
1182
|
+
storage_file = find_storage_file_by_bucket_and_path(storage_provider_id, file_path)
|
1183
|
+
return 1 if storage_file.nil?
|
1184
|
+
if storage_file['isDirectory']
|
1185
|
+
if !do_recursive
|
1186
|
+
print_error Morpheus::Terminal.angry_prompt
|
1187
|
+
puts_error "bad argument: '#{file_path}' is a directory. Use -R or --recursive to delete a directory.\n#{optparse}"
|
1188
|
+
return 1
|
1189
|
+
end
|
1190
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the directory: #{args[0]}?")
|
1191
|
+
return 9, "aborted command"
|
1192
|
+
end
|
1193
|
+
else
|
1194
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the file: #{args[0]}?")
|
1195
|
+
return 9, "aborted command"
|
1196
|
+
end
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
if options[:dry_run]
|
1200
|
+
print_dry_run @storage_files_interface.dry.destroy(storage_file['id'], query_params)
|
1201
|
+
return 0
|
1202
|
+
end
|
1203
|
+
json_response = @storage_files_interface.destroy(storage_file['id'], query_params)
|
1204
|
+
if options[:json]
|
1205
|
+
print JSON.pretty_generate(json_response)
|
1206
|
+
print "\n"
|
1207
|
+
else
|
1208
|
+
print_green_success "Removed file #{args[0]}"
|
1209
|
+
end
|
1210
|
+
return 0
|
1211
|
+
|
1212
|
+
rescue RestClient::Exception => e
|
1213
|
+
print_rest_exception(e, options)
|
1214
|
+
return 1
|
1215
|
+
end
|
1216
|
+
|
1217
|
+
end
|
1218
|
+
|
507
1219
|
private
|
508
1220
|
|
509
1221
|
|
@@ -573,4 +1285,75 @@ class Morpheus::Cli::StorageProvidersCommand
|
|
573
1285
|
storage_provider['providerType'].to_s.capitalize
|
574
1286
|
end
|
575
1287
|
|
1288
|
+
# parse_storage_provider_id_and_file_path() provides flexible argument formats for provider and path
|
1289
|
+
# it looks for [provider:/path] or [provider] [path]
|
1290
|
+
# @param delim [String] Default is a comma and any surrounding white space.
|
1291
|
+
# @return [Array] 2 elements, provider name (or id) and the file path.
|
1292
|
+
# The default file path is "/".
|
1293
|
+
# Examples:
|
1294
|
+
# parse_storage_provider_id_and_file_path("test") == ["test", "/"]
|
1295
|
+
# parse_storage_provider_id_and_file_path("test:/global.cfg") == ["test", "/global.cfg"]
|
1296
|
+
# parse_storage_provider_id_and_file_path("test:/node1/node.cfg") == ["test", "/node1/node.cfg"]
|
1297
|
+
# parse_storage_provider_id_and_file_path("test/node1/node.cfg") == ["test", "/node1/node.cfg"]
|
1298
|
+
# parse_storage_provider_id_and_file_path("test", "node1/node.cfg") == ["test", "/node1/node.cfg"]
|
1299
|
+
#
|
1300
|
+
def parse_storage_provider_id_and_file_path(*args)
|
1301
|
+
if args.size < 1 || args.size > 2
|
1302
|
+
return nil, nil
|
1303
|
+
end
|
1304
|
+
if !args[0]
|
1305
|
+
return nil, nil
|
1306
|
+
end
|
1307
|
+
full_path = args[0].to_s
|
1308
|
+
if args[1]
|
1309
|
+
if full_path.include?(":")
|
1310
|
+
full_path = "#{full_path}/#{args[1]}"
|
1311
|
+
else
|
1312
|
+
full_path = "#{full_path}:#{args[1]}"
|
1313
|
+
end
|
1314
|
+
end
|
1315
|
+
# ok fine, allow just id/filePath, without a colon.
|
1316
|
+
if !full_path.include?(":") && full_path.include?("/")
|
1317
|
+
path_elements = full_path.split("/")
|
1318
|
+
full_path = path_elements[0] + ":" + path_elements[1..-1].join("/")
|
1319
|
+
end
|
1320
|
+
uri_elements = full_path.split(":")
|
1321
|
+
storage_provider_id = uri_elements[0]
|
1322
|
+
file_path = uri_elements[1..-1].join("/") # [1]
|
1323
|
+
file_path = "/#{file_path}".squeeze("/")
|
1324
|
+
return storage_provider_id, file_path
|
1325
|
+
end
|
1326
|
+
|
1327
|
+
def format_filename(filename, options={})
|
1328
|
+
if options[:fullTree]
|
1329
|
+
filename.to_s
|
1330
|
+
else
|
1331
|
+
filename.to_s.split('/').last()
|
1332
|
+
end
|
1333
|
+
end
|
1334
|
+
|
1335
|
+
def print_storage_files_table(storage_files, options={})
|
1336
|
+
table_color = options[:color] || cyan
|
1337
|
+
rows = storage_files.collect do |storage_file|
|
1338
|
+
{
|
1339
|
+
id: storage_file['id'],
|
1340
|
+
name: format_filename(storage_file['name'], options),
|
1341
|
+
type: storage_file['isDirectory'] ? 'directory' : (storage_file['contentType']),
|
1342
|
+
size: storage_file['isDirectory'] ? '' : format_bytes(storage_file['contentLength']),
|
1343
|
+
lastUpdated: format_local_dt(storage_file['dateModified'])
|
1344
|
+
}
|
1345
|
+
end
|
1346
|
+
columns = [
|
1347
|
+
# :id,
|
1348
|
+
{:name => {:display_name => "File".upcase} },
|
1349
|
+
:type,
|
1350
|
+
:size,
|
1351
|
+
# {:dateCreated => {:display_name => "Date Created"} },
|
1352
|
+
{:lastUpdated => {:display_name => "Last Modified".upcase} }
|
1353
|
+
]
|
1354
|
+
print table_color
|
1355
|
+
print as_pretty_table(rows, columns, options)
|
1356
|
+
print reset
|
1357
|
+
end
|
1358
|
+
|
576
1359
|
end
|