aspera-cli 4.27.3 → 4.27.5
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +118 -0
- data/CONTRIBUTING.md +5 -2
- data/bin/ascli +1 -0
- data/docs/README.md +224 -42
- data/lib/aspera/agent/base.rb +7 -2
- data/lib/aspera/agent/connect.rb +0 -4
- data/lib/aspera/agent/desktop.rb +0 -4
- data/lib/aspera/agent/direct.rb +49 -21
- data/lib/aspera/agent/node.rb +6 -5
- data/lib/aspera/agent/transferd.rb +2 -2
- data/lib/aspera/api/faspex.rb +2 -0
- data/lib/aspera/api/httpgw.rb +1 -2
- data/lib/aspera/api/node.rb +3 -3
- data/lib/aspera/ascp/installation.rb +1 -1
- data/lib/aspera/cli/async_transfer_store.rb +10 -9
- data/lib/aspera/cli/bootstrapper.rb +3 -1
- data/lib/aspera/cli/command_registry.rb +69 -7
- data/lib/aspera/cli/command_spec.rb +1 -1
- data/lib/aspera/cli/extended_value.rb +4 -3
- data/lib/aspera/cli/formatter.rb +10 -8
- data/lib/aspera/cli/http.rb +8 -20
- data/lib/aspera/cli/option_types.rb +3 -1
- data/lib/aspera/cli/option_value.rb +16 -19
- data/lib/aspera/cli/options.schema.yaml +86 -10
- data/lib/aspera/cli/parser.rb +30 -18
- data/lib/aspera/cli/plugins/aoc.rb +133 -156
- data/lib/aspera/cli/plugins/ats.rb +1 -7
- data/lib/aspera/cli/plugins/base.rb +40 -34
- data/lib/aspera/cli/plugins/config.rb +24 -11
- data/lib/aspera/cli/plugins/console.rb +1 -1
- data/lib/aspera/cli/plugins/faspex5.rb +30 -11
- data/lib/aspera/cli/plugins/faspio.rb +1 -1
- data/lib/aspera/cli/plugins/node.rb +26 -19
- data/lib/aspera/cli/plugins/orchestrator.rb +73 -44
- data/lib/aspera/cli/plugins/preview.rb +21 -19
- data/lib/aspera/cli/plugins/server.rb +3 -4
- data/lib/aspera/cli/plugins/shares.rb +21 -24
- data/lib/aspera/cli/preset_actions.rb +28 -18
- data/lib/aspera/cli/preset_manager.rb +34 -19
- data/lib/aspera/cli/prompt.rb +2 -1
- data/lib/aspera/cli/result.rb +33 -22
- data/lib/aspera/cli/runner.rb +1 -5
- data/lib/aspera/cli/sync_actions.rb +17 -16
- data/lib/aspera/cli/transfer_actions.rb +14 -3
- data/lib/aspera/cli/transfer_agent.rb +6 -4
- data/lib/aspera/cli/transfer_progress.rb +290 -55
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +1 -1
- data/lib/aspera/coverage.rb +0 -1
- data/lib/aspera/environment.rb +29 -5
- data/lib/aspera/keychain/encrypted_hash.rb +1 -1
- data/lib/aspera/keychain/factory.rb +2 -1
- data/lib/aspera/log.rb +25 -2
- data/lib/aspera/node_emulator.rb +759 -0
- data/lib/aspera/oauth/base.rb +2 -1
- data/lib/aspera/oauth/factory.rb +6 -3
- data/lib/aspera/oauth/json_credentials.rb +34 -0
- data/lib/aspera/oauth/jwt.rb +3 -4
- data/lib/aspera/oauth.rb +1 -0
- data/lib/aspera/persistency_folder.rb +1 -3
- data/lib/aspera/preview/generator.rb +4 -1
- data/lib/aspera/preview/options.schema.yaml +119 -0
- data/lib/aspera/rest/aspera_errors.rb +12 -0
- data/lib/aspera/rest/client.rb +28 -19
- data/lib/aspera/rest/list.rb +14 -8
- data/lib/aspera/rest/parameters.rb +2 -2
- data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +0 -20
- data/lib/aspera/schema/IBM Aspera Orchestrator API-v1.yaml +1784 -0
- data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +1230 -137
- data/lib/aspera/schema/IBM_Aspera_Shares.yaml +14 -13
- data/lib/aspera/schema/reader.rb +12 -18
- data/lib/aspera/schema/registry.rb +6 -1
- data.tar.gz.sig +0 -0
- metadata +5 -3
- metadata.gz.sig +0 -0
- data/lib/aspera/node_simulator.rb +0 -345
- data/lib/aspera/preview/options.rb +0 -45
|
@@ -8,8 +8,6 @@ require 'aspera/schema/registry'
|
|
|
8
8
|
require 'aspera/schema/validator'
|
|
9
9
|
require 'aspera/log'
|
|
10
10
|
require 'aspera/assert'
|
|
11
|
-
require 'aspera/rainbow'
|
|
12
|
-
using Rainbow
|
|
13
11
|
|
|
14
12
|
module Aspera
|
|
15
13
|
module Cli
|
|
@@ -19,7 +17,7 @@ module Aspera
|
|
|
19
17
|
attr_reader :option
|
|
20
18
|
# [Array<Class>, nil] List of allowed types, `nil` for no validation
|
|
21
19
|
attr_reader :types
|
|
22
|
-
# [Symbol] How values are converted: :flag, :boolean, :integer, :enum, :enum_list, :string_list, :other
|
|
20
|
+
# [Symbol] How values are converted: :flag, :boolean, :integer, :float, :enum, :enum_list, :string_list, :other
|
|
23
21
|
attr_reader :kind
|
|
24
22
|
# [Symbol, nil] `OptionSource` of current value, `nil` if never set
|
|
25
23
|
attr_reader :source
|
|
@@ -59,8 +57,8 @@ module Aspera
|
|
|
59
57
|
@shorthand = shorthand
|
|
60
58
|
@source = nil
|
|
61
59
|
@value = nil
|
|
62
|
-
@on_set
|
|
63
|
-
|
|
60
|
+
Aspera.assert(on_set.nil? || on_set.respond_to?(:call)) { "#{@option}: on_set callback must respond to call" }
|
|
61
|
+
@on_set = on_set
|
|
64
62
|
@types = nil
|
|
65
63
|
@values = nil
|
|
66
64
|
@kind = :other
|
|
@@ -68,19 +66,6 @@ module Aspera
|
|
|
68
66
|
apply_allowed(allowed) unless allowed.nil?
|
|
69
67
|
end
|
|
70
68
|
|
|
71
|
-
# Set the `on_set` callback, called with the new value each time the value is set.
|
|
72
|
-
# Safe to call after construction: used by `Parser#on_set` for a target object created after declaration.
|
|
73
|
-
# The callback is called with the current value, if any.
|
|
74
|
-
# @param callback [#call] e.g. a `Method` or a lambda
|
|
75
|
-
# @return [nil]
|
|
76
|
-
def bind_on_set(callback)
|
|
77
|
-
Aspera.assert(callback.respond_to?(:call)) { "#{@option}: on_set callback must respond to call" }
|
|
78
|
-
@on_set = callback
|
|
79
|
-
Log.log.trace1 { "bind_on_set: #{@option}".green }
|
|
80
|
-
@on_set.call(@value) unless @value.nil?
|
|
81
|
-
nil
|
|
82
|
-
end
|
|
83
|
-
|
|
84
69
|
# @return [String] description of the option: explicit one, or first line of schema description
|
|
85
70
|
def description
|
|
86
71
|
return @description unless @description.nil?
|
|
@@ -232,6 +217,7 @@ module Aspera
|
|
|
232
217
|
@kind =
|
|
233
218
|
if allowed.sort_by(&:name).eql?(Type::BOOLEAN) then :boolean
|
|
234
219
|
elsif allowed.eql?(Type::INTEGER) then :integer
|
|
220
|
+
elsif allowed.eql?(Type::FLOAT) then :float
|
|
235
221
|
elsif allowed.eql?(Type::STRING_ARRAY) then :string_list
|
|
236
222
|
else :other
|
|
237
223
|
end
|
|
@@ -256,7 +242,18 @@ module Aspera
|
|
|
256
242
|
when :boolean
|
|
257
243
|
BoolValue.true?(value.is_a?(String) ? Parser.get_from_list(value, @option, BoolValue::ALL) : value)
|
|
258
244
|
when :integer
|
|
259
|
-
|
|
245
|
+
# Decimal, also with leading zeros (e.g. `08`)
|
|
246
|
+
if value.is_a?(String)
|
|
247
|
+
Integer(value, 10, exception: false).tap { |i| raise BadArgument, "Option #{@option}: invalid integer: #{value}" if i.nil? }
|
|
248
|
+
else
|
|
249
|
+
value.nil? ? value : Integer(value)
|
|
250
|
+
end
|
|
251
|
+
when :float
|
|
252
|
+
if value.is_a?(String)
|
|
253
|
+
Float(value, exception: false).tap { |f| raise BadArgument, "Option #{@option}: invalid number: #{value}" if f.nil? }
|
|
254
|
+
else
|
|
255
|
+
value.nil? ? value : Float(value)
|
|
256
|
+
end
|
|
260
257
|
when :string_list
|
|
261
258
|
value.is_a?(String) ? [value] : value
|
|
262
259
|
when :enum_list
|
|
@@ -102,7 +102,10 @@ components:
|
|
|
102
102
|
default: true
|
|
103
103
|
quiet:
|
|
104
104
|
type: boolean
|
|
105
|
-
description:
|
|
105
|
+
description: >-
|
|
106
|
+
Suppress the `ascp` progress bar display.
|
|
107
|
+
|
|
108
|
+
If `false`, the progress bar of option `progress_bar` is not displayed, unless that option is set.
|
|
106
109
|
default: true
|
|
107
110
|
file_list:
|
|
108
111
|
type: boolean
|
|
@@ -595,18 +598,20 @@ components:
|
|
|
595
598
|
Token expiry timestamp in ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`).
|
|
596
599
|
Computed automatically from `_validity` when absent.
|
|
597
600
|
example: "2030-01-01T00:00:00Z"
|
|
598
|
-
|
|
601
|
+
NodeEmulatorOptions:
|
|
599
602
|
type: object
|
|
600
603
|
description: >-
|
|
601
|
-
Configuration for the embedded Node API
|
|
602
|
-
The
|
|
603
|
-
`/ops/transfers/{id}
|
|
604
|
-
|
|
604
|
+
Configuration for the embedded Node API emulator (`node emulator`), for testing without HSTS.
|
|
605
|
+
The emulator starts a local web server that answers a subset of the Node API:
|
|
606
|
+
`/info`, `/ops/transfers` (list, start), `/ops/transfers/{id}` (show, modify, cancel) and `/files/browse`.
|
|
607
|
+
Transfers are executed by the Transfer Daemon (`transferd`), started by the emulator.
|
|
608
|
+
Clients authenticate with HTTP Basic when `username` and `password` are set.
|
|
609
|
+
additionalProperties: false
|
|
605
610
|
properties:
|
|
606
611
|
url:
|
|
607
612
|
type: string
|
|
608
613
|
description: >-
|
|
609
|
-
Address and port the
|
|
614
|
+
Address and port the emulator listens on.
|
|
610
615
|
Use `https://` with `cert`/`key` for TLS.
|
|
611
616
|
default: http://localhost:8080
|
|
612
617
|
cert:
|
|
@@ -624,13 +629,29 @@ components:
|
|
|
624
629
|
type: string
|
|
625
630
|
description: Path to the PEM certificate chain file (appended as extra chain certificates).
|
|
626
631
|
example: /path/to/chain.pem
|
|
627
|
-
|
|
632
|
+
docroot:
|
|
628
633
|
type: string
|
|
629
634
|
description: >-
|
|
630
|
-
|
|
631
|
-
|
|
635
|
+
Local folder of the node files.
|
|
636
|
+
Paths of `/files/browse` and local paths of transfers (sources of `send`, destination of `receive`) are relative to it, and confined in it.
|
|
632
637
|
Defaults to the current working directory.
|
|
633
638
|
example: /data/aspera
|
|
639
|
+
retention_sec:
|
|
640
|
+
type: integer
|
|
641
|
+
minimum: 1
|
|
642
|
+
description: Time in seconds a transfer stays in the list of transfers after it ended (completed, failed or canceled, and no more retried).
|
|
643
|
+
default: 86400
|
|
644
|
+
username:
|
|
645
|
+
type: string
|
|
646
|
+
description: >-
|
|
647
|
+
Username expected from clients in HTTP Basic authentication.
|
|
648
|
+
Set together with `password`.
|
|
649
|
+
When not set, requests are accepted without authentication.
|
|
650
|
+
example: node_user
|
|
651
|
+
password:
|
|
652
|
+
type: string
|
|
653
|
+
description: Password expected from clients in HTTP Basic authentication, for the above `username`.
|
|
654
|
+
example: my_password
|
|
634
655
|
NodeTelemetryOptions:
|
|
635
656
|
type: object
|
|
636
657
|
description: >-
|
|
@@ -685,6 +706,61 @@ components:
|
|
|
685
706
|
Name of the output variable of `step` returned as result.
|
|
686
707
|
Requires `step`, and implies `synchronous`.
|
|
687
708
|
example: Complete_status_message
|
|
709
|
+
OrchestratorInitiateParameters:
|
|
710
|
+
type: object
|
|
711
|
+
description: >-
|
|
712
|
+
Input parameters for the workflow (key-value pairs).
|
|
713
|
+
Valid keys are defined by the workflow's input specification.
|
|
714
|
+
Use `orchestrator workflows inputs WORKFLOW_ID` to discover required parameters.
|
|
715
|
+
additionalProperties: true
|
|
716
|
+
OrchestratorImportWorkflow:
|
|
717
|
+
type: object
|
|
718
|
+
description: Workflow definition to import into Orchestrator.
|
|
719
|
+
required:
|
|
720
|
+
- name
|
|
721
|
+
properties:
|
|
722
|
+
name:
|
|
723
|
+
type: string
|
|
724
|
+
description: Workflow name.
|
|
725
|
+
example: My Workflow
|
|
726
|
+
description:
|
|
727
|
+
type: string
|
|
728
|
+
description: Workflow description.
|
|
729
|
+
example: This is a sample workflow
|
|
730
|
+
workflow_data:
|
|
731
|
+
type: object
|
|
732
|
+
description: Complete workflow definition.
|
|
733
|
+
OrchestratorImportWithConstraints:
|
|
734
|
+
type: object
|
|
735
|
+
description: Workflow definition to import with constraint resolution mappings.
|
|
736
|
+
required:
|
|
737
|
+
- workflow_data
|
|
738
|
+
- constraints
|
|
739
|
+
properties:
|
|
740
|
+
workflow_data:
|
|
741
|
+
type: object
|
|
742
|
+
description: Complete workflow definition to import.
|
|
743
|
+
constraints:
|
|
744
|
+
type: object
|
|
745
|
+
description: Constraint resolution mappings for conflicting resources.
|
|
746
|
+
example:
|
|
747
|
+
resource_pools: {}
|
|
748
|
+
queues: {}
|
|
749
|
+
monitors: {}
|
|
750
|
+
OrchestratorReloadPluginSet:
|
|
751
|
+
type: object
|
|
752
|
+
description: Set of plugins to reload.
|
|
753
|
+
required:
|
|
754
|
+
- plugin_names
|
|
755
|
+
properties:
|
|
756
|
+
plugin_names:
|
|
757
|
+
type: array
|
|
758
|
+
description: List of plugin names to reload.
|
|
759
|
+
items:
|
|
760
|
+
type: string
|
|
761
|
+
example:
|
|
762
|
+
- soap_requests
|
|
763
|
+
- frameio_operations
|
|
688
764
|
TableOptions:
|
|
689
765
|
type: object
|
|
690
766
|
description: Terminal table rendering options.
|
data/lib/aspera/cli/parser.rb
CHANGED
|
@@ -97,7 +97,7 @@ module Aspera
|
|
|
97
97
|
when 'true', BoolValue::YES_SYM.to_s then true
|
|
98
98
|
when 'false', BoolValue::NO_SYM.to_s then false
|
|
99
99
|
else
|
|
100
|
-
Integer(value, exception: false) ||
|
|
100
|
+
Integer(value, 10, exception: false) ||
|
|
101
101
|
Float(value, exception: false) ||
|
|
102
102
|
ExtendedValue.instance.evaluate(value, context: 'dotted expression')
|
|
103
103
|
end
|
|
@@ -228,14 +228,15 @@ module Aspera
|
|
|
228
228
|
|
|
229
229
|
# Resource identifier as positional parameter
|
|
230
230
|
#
|
|
231
|
-
# @param description [String]
|
|
232
|
-
# @param
|
|
233
|
-
# @
|
|
231
|
+
# @param description [String] description of the identifier
|
|
232
|
+
# @param multiple [Boolean] `true`: read a list of IDs (bulk operation)
|
|
233
|
+
# @param block [Proc] block to search for identifier based on attribute value
|
|
234
|
+
# @return [String, Array<String>] identifier or list of IDs (if `multiple`)
|
|
234
235
|
# @yieldparam field [String] The field name from percent selector
|
|
235
236
|
# @yieldparam value [String] The value from percent selector
|
|
236
237
|
# @yieldreturn [String] Resolved identifier
|
|
237
|
-
def instance_identifier(description: 'identifier', &block)
|
|
238
|
-
res_id = get_next_argument(description, multiple:
|
|
238
|
+
def instance_identifier(description: 'identifier', multiple: false, &block)
|
|
239
|
+
res_id = get_next_argument(description, multiple: multiple)
|
|
239
240
|
# Can be an Array
|
|
240
241
|
if res_id.is_a?(String) && (m = Parser.percent_selector(res_id))
|
|
241
242
|
Aspera.assert(block_given?, type: Cli::BadArgument) { "Percent syntax for #{description} not supported in this context" }
|
|
@@ -312,16 +313,6 @@ module Aspera
|
|
|
312
313
|
option_def(option_symbol).clear
|
|
313
314
|
end
|
|
314
315
|
|
|
315
|
-
# Bind (or re-bind) an `on_set` callback to an already-declared option, for a target object created after declaration.
|
|
316
|
-
# The callback is called with the current value, if any.
|
|
317
|
-
# @param option_symbol [Symbol] name of the already-declared option
|
|
318
|
-
# @param callback [#call] called with the new value each time the value is set (e.g. a `Method`)
|
|
319
|
-
# @return [nil]
|
|
320
|
-
def on_set(option_symbol, callback)
|
|
321
|
-
Aspera.assert_type(option_symbol, Symbol)
|
|
322
|
-
option_def(option_symbol).bind_on_set(callback)
|
|
323
|
-
end
|
|
324
|
-
|
|
325
316
|
# Adds each of the keys of specified hash as an option.
|
|
326
317
|
# Values are applied by the next parse, and never override a value from env or command line.
|
|
327
318
|
# @param preset_hash [Hash] Options to add
|
|
@@ -354,6 +345,14 @@ module Aspera
|
|
|
354
345
|
@command_line.pending_arguments.empty?
|
|
355
346
|
end
|
|
356
347
|
|
|
348
|
+
# Check the next pending positional argument, without consuming it
|
|
349
|
+
# @param values [Array<String>] values to compare with
|
|
350
|
+
# @return [Boolean] true if the next pending positional argument is one of values
|
|
351
|
+
def next_argument_in?(values)
|
|
352
|
+
ensure_parsed
|
|
353
|
+
values.include?(@command_line.pending_arguments.first)
|
|
354
|
+
end
|
|
355
|
+
|
|
357
356
|
# Check for unprocessed options or arguments error messages
|
|
358
357
|
# @return [Array<String>] list of error messages for unprocessed tokens
|
|
359
358
|
def final_errors
|
|
@@ -410,6 +409,18 @@ module Aspera
|
|
|
410
409
|
Log.log.trace1 { "unprocessed options: #{@command_line.pending_options}" }
|
|
411
410
|
end
|
|
412
411
|
|
|
412
|
+
# Execute the block with interactive input of missing mandatory options and arguments, as with `--interactive=yes`.
|
|
413
|
+
# The previous state is restored afterwards, so that interactive input does not leak to the rest of the command.
|
|
414
|
+
# @param enabled [Boolean] `false`: execute the block with current state
|
|
415
|
+
# @return [Object] result of the block
|
|
416
|
+
def with_interactive(enabled: true)
|
|
417
|
+
previous = @ask_missing_mandatory
|
|
418
|
+
@ask_missing_mandatory = true if enabled
|
|
419
|
+
yield
|
|
420
|
+
ensure
|
|
421
|
+
@ask_missing_mandatory = previous
|
|
422
|
+
end
|
|
423
|
+
|
|
413
424
|
# Prompt user for missing option or argument, or raise if not interactive
|
|
414
425
|
# @param descr [String] option name, or argument description
|
|
415
426
|
# @param multiple [Boolean, String] `true` if multiple values expected
|
|
@@ -428,7 +439,7 @@ module Aspera
|
|
|
428
439
|
end
|
|
429
440
|
# Ask interactively
|
|
430
441
|
result = []
|
|
431
|
-
puts(' (one per line, end with empty line)') if multiple
|
|
442
|
+
$stderr.puts(' (one per line, end with empty line)') if multiple # rubocop:disable Style/StderrPuts
|
|
432
443
|
loop do
|
|
433
444
|
prompt = default_prompt
|
|
434
445
|
prompt = "#{accept_list.join(' ')}\n#{default_prompt}" if accept_list
|
|
@@ -527,7 +538,7 @@ module Aspera
|
|
|
527
538
|
# if value comes from JSON/YAML, it may come as Integer
|
|
528
539
|
return value.to_s if value.is_a?(Integer) && validation.eql?(Type::STRING)
|
|
529
540
|
return value unless value.is_a?(String) && validation.eql?(Type::INTEGER)
|
|
530
|
-
Integer(value, exception: false).tap { |i| raise Cli::BadArgument, "Invalid integer: #{value}" if i.nil? }
|
|
541
|
+
Integer(value, 10, exception: false).tap { |i| raise Cli::BadArgument, "Invalid integer: #{value}" if i.nil? }
|
|
531
542
|
end
|
|
532
543
|
|
|
533
544
|
# Validate a single argument value.
|
|
@@ -554,6 +565,7 @@ module Aspera
|
|
|
554
565
|
when :flag then nil
|
|
555
566
|
when :boolean then 'yes|no'
|
|
556
567
|
when :integer then 'INT'
|
|
568
|
+
when :float then 'FLOAT'
|
|
557
569
|
when :enum
|
|
558
570
|
opt.values&.any? && opt.values.length <= 4 ? opt.values.join('|') : 'ENUM'
|
|
559
571
|
else
|