aspera-cli 4.27.5 → 4.28.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +160 -4
- data/CONTRIBUTING.md +4 -2
- data/README.md +1 -1
- data/bin/asession +1 -1
- data/docs/README.md +1086 -331
- data/docs/test-mcp-with-ai.md +5 -3
- data/lib/aspera/agent/direct.rb +15 -4
- data/lib/aspera/agent/factory.rb +2 -1
- data/lib/aspera/agent/node.rb +1 -1
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/faspex.rb +1 -1
- data/lib/aspera/api/node.rb +6 -2
- data/lib/aspera/ascp/installation.rb +47 -11
- data/lib/aspera/ascp/management.rb +89 -43
- data/lib/aspera/cli/ascp_actions.rb +5 -19
- data/lib/aspera/cli/bootstrapper.rb +1 -2
- data/lib/aspera/cli/command_registry.rb +43 -3
- data/lib/aspera/cli/command_spec.rb +3 -0
- data/lib/aspera/cli/completion/ascli.bash +39 -5
- data/lib/aspera/cli/completion/ascli.fish +16 -8
- data/lib/aspera/cli/completion/ascli.ps1 +41 -0
- data/lib/aspera/cli/completion/ascli.zsh +20 -4
- data/lib/aspera/cli/completion_actions.rb +360 -0
- data/lib/aspera/cli/error.rb +42 -0
- data/lib/aspera/cli/extended_value.rb +30 -5
- data/lib/aspera/cli/formatter.rb +118 -56
- data/lib/aspera/cli/hints.rb +0 -1
- data/lib/aspera/cli/http.rb +6 -5
- data/lib/aspera/cli/info.rb +10 -4
- data/lib/aspera/cli/mailer.rb +1 -1
- data/lib/aspera/cli/mcp/http_servlet.rb +156 -0
- data/lib/aspera/cli/mcp/secrets.rb +143 -0
- data/lib/aspera/cli/mcp/tool.rb +231 -0
- data/lib/aspera/cli/option_value.rb +9 -1
- data/lib/aspera/cli/options.schema.yaml +390 -39
- data/lib/aspera/cli/parser.rb +14 -5
- data/lib/aspera/cli/plugins/aoc.rb +8 -11
- data/lib/aspera/cli/plugins/base.rb +36 -15
- data/lib/aspera/cli/plugins/config.rb +15 -44
- data/lib/aspera/cli/plugins/console.rb +3 -1
- data/lib/aspera/cli/plugins/factory.rb +1 -1
- data/lib/aspera/cli/plugins/faspex5.rb +9 -19
- data/lib/aspera/cli/plugins/faspio.rb +36 -5
- data/lib/aspera/cli/plugins/httpgw.rb +1 -0
- data/lib/aspera/cli/plugins/mcp.rb +177 -118
- data/lib/aspera/cli/plugins/node.rb +14 -8
- data/lib/aspera/cli/plugins/orchestrator.rb +351 -38
- data/lib/aspera/cli/plugins/server.rb +3 -1
- data/lib/aspera/cli/plugins/shares.rb +205 -35
- data/lib/aspera/cli/preset_actions.rb +15 -7
- data/lib/aspera/cli/preset_manager.rb +24 -2
- data/lib/aspera/cli/prompt.rb +3 -1
- data/lib/aspera/cli/result.rb +17 -4
- data/lib/aspera/cli/runner.rb +133 -43
- data/lib/aspera/cli/security.rb +134 -0
- data/lib/aspera/cli/table_fitter.rb +116 -0
- data/lib/aspera/cli/terminal_formatter.rb +23 -34
- data/lib/aspera/cli/transfer_agent.rb +4 -1
- data/lib/aspera/cli/vault_manager.rb +6 -5
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/web_secret.html.erb +61 -0
- data/lib/aspera/cli/web_secret.rb +220 -0
- data/lib/aspera/cli/wizard.rb +19 -9
- data/lib/aspera/command_line_builder.rb +26 -0
- data/lib/aspera/data_repository.rb +38 -24
- data/lib/aspera/duration.rb +42 -0
- data/lib/aspera/environment.rb +88 -24
- data/lib/aspera/exec_spec.rb +6 -5
- data/lib/aspera/faspex_gw.rb +98 -32
- data/lib/aspera/faspex_postproc.rb +187 -44
- data/lib/aspera/formatter_interface.rb +0 -1
- data/lib/aspera/id_generator.rb +2 -1
- data/lib/aspera/json_rpc/client.rb +51 -32
- data/lib/aspera/json_rpc/version.rb +1 -0
- data/lib/aspera/keychain/base.rb +5 -0
- data/lib/aspera/keychain/encrypted_hash.rb +6 -2
- data/lib/aspera/keychain/factory.rb +2 -3
- data/lib/aspera/keychain/hashicorp_vault.rb +7 -4
- data/lib/aspera/keychain/macos_security.rb +119 -13
- data/lib/aspera/keychain/one_password_api.rb +8 -3
- data/lib/aspera/keychain/one_password_base.rb +14 -9
- data/lib/aspera/keychain/one_password_cli.rb +4 -2
- data/lib/aspera/log.rb +3 -6
- data/lib/aspera/markdown.rb +152 -115
- data/lib/aspera/mime.rb +6 -0
- data/lib/aspera/nagios.rb +3 -1
- data/lib/aspera/node_emulator.rb +98 -101
- data/lib/aspera/oauth/{base.rb → client/base.rb} +5 -4
- data/lib/aspera/oauth/{boot.rb → client/boot.rb} +3 -2
- data/lib/aspera/oauth/{factory.rb → client/factory.rb} +7 -0
- data/lib/aspera/oauth/{generic.rb → client/generic.rb} +1 -1
- data/lib/aspera/oauth/{json_credentials.rb → client/json_credentials.rb} +1 -1
- data/lib/aspera/oauth/{jwt.rb → client/jwt.rb} +1 -1
- data/lib/aspera/oauth/{url_json.rb → client/url_json.rb} +1 -1
- data/lib/aspera/oauth/{web.rb → client/web.rb} +2 -2
- data/lib/aspera/oauth/server/authorize.html.erb +34 -0
- data/lib/aspera/oauth/server/pkce.rb +426 -0
- data/lib/aspera/orchestrator_workflow_checker.rb +561 -0
- data/lib/aspera/preview/terminal.rb +3 -2
- data/lib/aspera/rainbow.rb +27 -1
- data/lib/aspera/rest/aspera_errors.rb +51 -59
- data/lib/aspera/rest/client.rb +21 -14
- data/lib/aspera/rest/error_analyzer.rb +9 -0
- data/lib/aspera/rest/list.rb +6 -6
- data/lib/aspera/rest/util.rb +7 -1
- data/lib/aspera/rest.rb +0 -1
- data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +0 -2
- data/lib/aspera/schema/IBM Aspera Orchestrator API-v1-enhanced.yaml +4001 -0
- data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0-enhanced.yaml +1097 -0
- data/lib/aspera/schema/IBM Aspera on Cloud Automation API-1.0.5-enhanced.yaml +35 -35
- data/lib/aspera/schema/IBM_Aspera_Shares.yaml +819 -7
- data/lib/aspera/schema/documentation.rb +50 -78
- data/lib/aspera/schema/reader.rb +39 -11
- data/lib/aspera/schema/registry.rb +8 -2
- data/lib/aspera/secret_hider.rb +94 -15
- data/lib/aspera/secret_strength.rb +114 -0
- data/lib/aspera/servlet_helpers.rb +111 -0
- data/lib/aspera/sync/args.schema.yaml +3 -1
- data/lib/aspera/sync/conf.schema.yaml +16 -6
- data/lib/aspera/sync/operations.rb +21 -1
- data/lib/aspera/temp_file_manager.rb +79 -20
- data/lib/aspera/transfer/parameters.rb +5 -0
- data/lib/aspera/transfer/spec.rb +52 -12
- data/lib/aspera/transfer/spec.schema.yaml +8 -5
- data/lib/aspera/web_auth/index.html.erb +16 -0
- data/lib/aspera/web_auth/server.rb +18 -10
- data/lib/aspera/web_page.html.erb +262 -0
- data/lib/aspera/web_page.rb +61 -0
- data/lib/aspera/web_server_simple.rb +76 -10
- data.tar.gz.sig +0 -0
- metadata +47 -32
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/mcp_tool.rb +0 -189
- data/lib/aspera/oauth.rb +0 -9
- data/lib/aspera/schema/IBM Aspera Orchestrator API-v1.yaml +0 -1784
- data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0.yaml +0 -249
- data/lib/aspera/web_auth/index.html +0 -147
|
@@ -7,6 +7,7 @@ require 'aspera/cli/result'
|
|
|
7
7
|
require 'aspera/cli/command_registry'
|
|
8
8
|
require 'aspera/cli/option_declarator'
|
|
9
9
|
require 'aspera/cli/special_values'
|
|
10
|
+
require 'aspera/rest/list'
|
|
10
11
|
require 'aspera/schema/registry'
|
|
11
12
|
|
|
12
13
|
module Aspera
|
|
@@ -104,12 +105,26 @@ module Aspera
|
|
|
104
105
|
# @param entity [String, Symbol] REST sub-path, or ctx key Symbol resolved at runtime
|
|
105
106
|
# @param operations [Array<Symbol>] Verbs to expose; defaults to Operations::ALL
|
|
106
107
|
# @param name [String, nil] Singular display name; defaults to last segment of entity (static only)
|
|
107
|
-
# @param lookup [Symbol, nil]
|
|
108
|
+
# @param lookup [Symbol, Proc, Array<String>, nil] Percent-selector resolution: instance method, lambda,
|
|
109
|
+
# or fields with unique values, looked up in the list of entities (plain Array of Hash)
|
|
108
110
|
# @param id_name [Symbol, nil] Name of identifier argument; defaults to <name>_id, or id_as_arg field, or :id
|
|
111
|
+
# @param schema_entity [String, nil] REST sub-path in the API schema (body_component), when entity is a ctx key Symbol
|
|
109
112
|
# @param kwargs [Hash] Shared params forwarded to every per-verb method
|
|
110
|
-
def crud_commands(api:, entity:, operations: nil, name: nil, lookup: nil, id_name: nil, **kwargs)
|
|
113
|
+
def crud_commands(api:, entity:, operations: nil, name: nil, lookup: nil, id_name: nil, schema_entity: nil, **kwargs)
|
|
111
114
|
name ||= entity_noun(entity, singular: !kwargs[:is_singleton]) unless entity.is_a?(Symbol)
|
|
112
115
|
operations ||= Operations::ALL
|
|
116
|
+
schema_entity ||= entity if entity.is_a?(String)
|
|
117
|
+
if lookup.is_a?(Array)
|
|
118
|
+
unique_fields = lookup
|
|
119
|
+
# `%id:<id>` is the id itself (no lookup), other fields are looked up in the list of entities
|
|
120
|
+
lookup = lambda do |field, value, **ctx|
|
|
121
|
+
return value if field.eql?('id')
|
|
122
|
+
resolved_entity = entity.is_a?(Symbol) ? ctx.fetch(entity) : entity
|
|
123
|
+
label = name || resolved_entity
|
|
124
|
+
Aspera.assert_values(field, unique_fields, type: Cli::BadArgument) { "#{label} search field" }
|
|
125
|
+
Rest::List.lookup_entity_generic(field: field, value: value, entity: label) { crud_api(api).read(resolved_entity) }['id']
|
|
126
|
+
end
|
|
127
|
+
end
|
|
113
128
|
# Body argument is named after the entity, e.g. <access_key>, and passed as data: to entity_<verb>
|
|
114
129
|
data_name = name ? name.downcase.tr(' ', '_').to_sym : :data
|
|
115
130
|
# Identifier argument is named after the entity, e.g. <access_key_id>, and passed as id: to entity_<verb>
|
|
@@ -121,10 +136,10 @@ module Aspera
|
|
|
121
136
|
operations.each do |verb|
|
|
122
137
|
id_arg = ({name: id_name, type: :identifier, lookup: lookup} if Operations::INSTANCE.include?(verb) && !kwargs[:is_singleton])
|
|
123
138
|
schema_val =
|
|
124
|
-
if kwargs[:body_component] &&
|
|
139
|
+
if kwargs[:body_component] && schema_entity
|
|
125
140
|
case verb
|
|
126
|
-
when :create then Schema::Registry.req_body(kwargs[:body_component], "#{
|
|
127
|
-
when :modify then Schema::Registry.req_body(kwargs[:body_component], "#{
|
|
141
|
+
when :create then Schema::Registry.req_body(kwargs[:body_component], "#{schema_entity}.post")
|
|
142
|
+
when :modify then Schema::Registry.req_body(kwargs[:body_component], "#{schema_entity}/{id}.put")
|
|
128
143
|
end
|
|
129
144
|
end
|
|
130
145
|
args =
|
|
@@ -139,18 +154,10 @@ module Aspera
|
|
|
139
154
|
id_arg ? [id_arg] : nil
|
|
140
155
|
end
|
|
141
156
|
action_proc = lambda do |**ctx|
|
|
142
|
-
resolved_api =
|
|
143
|
-
if api.is_a?(Symbol)
|
|
144
|
-
api.to_s.start_with?('@') ? instance_variable_get(api) : send(api)
|
|
145
|
-
elsif api.is_a?(Proc)
|
|
146
|
-
instance_exec(&api)
|
|
147
|
-
else
|
|
148
|
-
api
|
|
149
|
-
end
|
|
150
157
|
resolved_entity = entity.is_a?(Symbol) ? ctx.fetch(entity) : entity
|
|
151
158
|
ctx = ctx.merge(data: ctx[data_name]) if ctx.key?(data_name)
|
|
152
159
|
ctx = ctx.merge(id: ctx[id_name]) if ctx.key?(id_name)
|
|
153
|
-
send(:"entity_#{verb}", api:
|
|
160
|
+
send(:"entity_#{verb}", api: crud_api(api), entity: resolved_entity, **kwargs, **ctx)
|
|
154
161
|
end
|
|
155
162
|
cmd_attrs = {description: operation_description(verb, name || entity.inspect), action: action_proc}
|
|
156
163
|
cmd_attrs[:arguments] = args if args
|
|
@@ -555,7 +562,8 @@ module Aspera
|
|
|
555
562
|
validation: arg_spec.type,
|
|
556
563
|
accept_list: arg_spec.allowed,
|
|
557
564
|
default: arg_spec.interactive ? nil : arg_spec.default,
|
|
558
|
-
schema: arg_spec.schema
|
|
565
|
+
schema: arg_spec.schema,
|
|
566
|
+
raw: arg_spec.raw
|
|
559
567
|
)
|
|
560
568
|
end
|
|
561
569
|
end
|
|
@@ -603,6 +611,19 @@ module Aspera
|
|
|
603
611
|
)
|
|
604
612
|
end
|
|
605
613
|
|
|
614
|
+
# Resolve the `api:` reference given to `crud_commands`.
|
|
615
|
+
# @param api [Symbol, Proc, Object] `:@ivar`, method name, Proc (instance_exec), or the API object itself
|
|
616
|
+
# @return [Rest::Client]
|
|
617
|
+
def crud_api(api)
|
|
618
|
+
if api.is_a?(Symbol)
|
|
619
|
+
api.to_s.start_with?('@') ? instance_variable_get(api) : send(api)
|
|
620
|
+
elsif api.is_a?(Proc)
|
|
621
|
+
instance_exec(&api)
|
|
622
|
+
else
|
|
623
|
+
api
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
606
627
|
# --- Per-verb entity action methods ---
|
|
607
628
|
# Each method handles exactly one CRUD verb.
|
|
608
629
|
# The resource id (when needed) is received as `id:` from ctx — it must be
|
|
@@ -14,6 +14,7 @@ require 'aspera/cli/wizard'
|
|
|
14
14
|
require 'aspera/cli/sync_actions'
|
|
15
15
|
require 'aspera/cli/ascp_actions'
|
|
16
16
|
require 'aspera/cli/preset_actions'
|
|
17
|
+
require 'aspera/cli/completion_actions'
|
|
17
18
|
require 'aspera/cli/vault_manager'
|
|
18
19
|
require 'aspera/cli/transfer_actions'
|
|
19
20
|
require 'aspera/cli/gem_checker'
|
|
@@ -28,7 +29,7 @@ require 'aspera/persistency_action_once'
|
|
|
28
29
|
require 'aspera/id_generator'
|
|
29
30
|
require 'aspera/data_repository'
|
|
30
31
|
require 'aspera/rest'
|
|
31
|
-
require 'aspera/oauth/jwt'
|
|
32
|
+
require 'aspera/oauth/client/jwt'
|
|
32
33
|
require 'aspera/log'
|
|
33
34
|
require 'aspera/assert'
|
|
34
35
|
require 'aspera/string_ext'
|
|
@@ -48,6 +49,7 @@ module Aspera
|
|
|
48
49
|
include AscpActions
|
|
49
50
|
include PresetActions
|
|
50
51
|
include TransferActions
|
|
52
|
+
include CompletionActions
|
|
51
53
|
|
|
52
54
|
class << self
|
|
53
55
|
# Folder containing plugins in the gem's main folder
|
|
@@ -62,11 +64,6 @@ module Aspera
|
|
|
62
64
|
File.expand_path(Module.nesting[2].to_s.gsub('::', '/').gsub(%r{[^/]+}, '..'), gem_plugins_folder)
|
|
63
65
|
end
|
|
64
66
|
|
|
65
|
-
# Deep clone hash so that it does not get modified in case of display and secret hide
|
|
66
|
-
def deep_clone(val)
|
|
67
|
-
return Marshal.load(Marshal.dump(val))
|
|
68
|
-
end
|
|
69
|
-
|
|
70
67
|
# @return [String] product family folder (~/.aspera)
|
|
71
68
|
def module_family_folder
|
|
72
69
|
user_home_folder = Dir.home
|
|
@@ -83,16 +80,13 @@ module Aspera
|
|
|
83
80
|
end
|
|
84
81
|
|
|
85
82
|
DEFAULT_CHECK_NEW_VERSION_DAYS = 7
|
|
86
|
-
|
|
87
|
-
COMPLETION_SHELLS = %i[bash zsh fish].freeze
|
|
88
|
-
COMPLETION_FOLDER = File.expand_path('../completion', __dir__)
|
|
89
|
-
private_constant :DEFAULT_CHECK_NEW_VERSION_DAYS, :COMPLETION_SHELLS, :COMPLETION_FOLDER
|
|
83
|
+
private_constant :DEFAULT_CHECK_NEW_VERSION_DAYS
|
|
90
84
|
|
|
91
85
|
option :preset, description: 'Load the named option preset from current config file', short: 'P', on_set: :load_preset
|
|
92
86
|
option :version_check_days, description: 'Period in days to check new version (zero to disable)', allowed: Type::INTEGER, default: DEFAULT_CHECK_NEW_VERSION_DAYS
|
|
93
87
|
option :plugin_folder, description: 'Folder where to find additional plugins', on_set: :add_plugin_folders
|
|
94
88
|
option :sdk_url, description: 'Ascp: URL to get Aspera Transfer Executables', default: SpecialValues::DEF
|
|
95
|
-
option :locations_url, description: 'Ascp:
|
|
89
|
+
option :locations_url, description: 'Ascp: URLs to get download locations of Aspera Transfer Daemon', allowed: Type::STRING_ARRAY, default: Ascp::Installation.instance.transferd_urls, on_set: Ascp::Installation.instance.method(:transferd_urls=)
|
|
96
90
|
option :sdk_folder, description: 'Ascp: Path to folder with ascp (or product with "product:")', on_set: Ascp::Installation.instance.method(:sdk_folder=)
|
|
97
91
|
option :smtp, schema: Schema::Registry::SMTP_OPTIONS
|
|
98
92
|
option :notify_to, description: 'Email: Recipient for notification of transfers'
|
|
@@ -244,7 +238,7 @@ module Aspera
|
|
|
244
238
|
command :delete, description: 'Delete a secret by label (or id)',
|
|
245
239
|
arguments: [{name: :label}, {name: :id, mandatory: false, default: nil}]
|
|
246
240
|
command(
|
|
247
|
-
:password, description: '
|
|
241
|
+
:password, description: 'Set a new password for the vault',
|
|
248
242
|
arguments: [{name: :new_password}],
|
|
249
243
|
action: lambda do |new_password:, **|
|
|
250
244
|
Aspera.assert(vault_required.respond_to?(:change_password), 'Vault does not support password change')
|
|
@@ -335,8 +329,9 @@ module Aspera
|
|
|
335
329
|
action: ->(version: nil, **) { install_transfer_sdk(version: version) }
|
|
336
330
|
command(
|
|
337
331
|
:spec, description: 'Show the transfer spec schema',
|
|
338
|
-
|
|
339
|
-
|
|
332
|
+
arguments: [{name: :agent_name, allowed: Agent::Factory::ALL.keys + [Transfer::Spec::DOC_OVERVIEW], mandatory: false, default: nil}],
|
|
333
|
+
action: lambda do |agent_name: nil, **|
|
|
334
|
+
builder = Schema::Documentation.new(TerminalFormatter, Transfer::Spec::SCHEMA, **Transfer::Spec.doc_options(agent_name)).build
|
|
340
335
|
Result::ObjectList.new(builder.rows, fields: builder.columns)
|
|
341
336
|
end
|
|
342
337
|
)
|
|
@@ -393,7 +388,7 @@ module Aspera
|
|
|
393
388
|
command(
|
|
394
389
|
:spec, description: 'Show the sync configuration schema',
|
|
395
390
|
action: lambda do |**|
|
|
396
|
-
builder = Schema::Documentation.new(TerminalFormatter, Sync::Operations::CONF_SCHEMA,
|
|
391
|
+
builder = Schema::Documentation.new(TerminalFormatter, Sync::Operations::CONF_SCHEMA, annotate: CommandLineBuilder.method(:doc_lines)).build
|
|
397
392
|
Result::ObjectList.new(builder.rows, fields: builder.columns)
|
|
398
393
|
end
|
|
399
394
|
)
|
|
@@ -429,9 +424,11 @@ module Aspera
|
|
|
429
424
|
|
|
430
425
|
# completion sub-commands
|
|
431
426
|
commands_under :completion do
|
|
432
|
-
command :words, description: 'List words that can follow the given words
|
|
433
|
-
arguments: [{name: :words, multiple: true, mandatory: false}]
|
|
434
|
-
|
|
427
|
+
command :words, description: 'List words that can follow the given words',
|
|
428
|
+
arguments: [{name: :words, multiple: true, mandatory: false, raw: true}]
|
|
429
|
+
command :candidates, description: 'Complete the last word, with descriptions and a directive for the shell (used by completion scripts)',
|
|
430
|
+
arguments: [{name: :words, multiple: true, mandatory: false, raw: true}]
|
|
431
|
+
COMPLETION_SHELLS.each_key do |shell|
|
|
435
432
|
command shell, description: "Generate #{shell} completion script, to evaluate in shell",
|
|
436
433
|
action: ->(**) { completion_script(shell) }
|
|
437
434
|
end
|
|
@@ -635,32 +632,6 @@ module Aspera
|
|
|
635
632
|
Result::ObjectList.new(rows, fields: %w[option description allowed deprecated replacement])
|
|
636
633
|
end
|
|
637
634
|
|
|
638
|
-
def action_completion_words(words: nil, **)
|
|
639
|
-
if words.nil? || words.empty?
|
|
640
|
-
# Level 0: propose plugin names
|
|
641
|
-
Plugins::Factory.instance.plugin_list.each { |p| puts p }
|
|
642
|
-
else
|
|
643
|
-
plugin_sym = words.first.to_sym
|
|
644
|
-
plugin_class = begin
|
|
645
|
-
Plugins::Factory.instance.plugin_class(plugin_sym)
|
|
646
|
-
rescue StandardError
|
|
647
|
-
Process.exit(0)
|
|
648
|
-
end
|
|
649
|
-
# Navigate into the registry using remaining words as path
|
|
650
|
-
path = words[1..].map(&:to_sym)
|
|
651
|
-
plugin_class.command_registry.children_of(path).each_key { |k| puts k }
|
|
652
|
-
end
|
|
653
|
-
Process.exit(0)
|
|
654
|
-
end
|
|
655
|
-
|
|
656
|
-
# Display the completion script for the given shell.
|
|
657
|
-
# Raw output, not formatted, so that it can be evaluated by the shell.
|
|
658
|
-
# @param shell [Symbol] One of `COMPLETION_SHELLS`
|
|
659
|
-
def completion_script(shell)
|
|
660
|
-
$stdout.write(File.read(File.join(COMPLETION_FOLDER, "#{Info::CMD_NAME}.#{shell}")))
|
|
661
|
-
Process.exit(0)
|
|
662
|
-
end
|
|
663
|
-
|
|
664
635
|
# Folder in $HOME for application files (~/.aspera)
|
|
665
636
|
ASPERA_HOME_FOLDER_NAME = '.aspera'
|
|
666
637
|
# Default config file name
|
|
@@ -57,10 +57,12 @@ module Aspera
|
|
|
57
57
|
# @param app_url [String] Tested URL
|
|
58
58
|
# @return [Hash] :preset_value, :test_args
|
|
59
59
|
def wizard(wizard, app_url)
|
|
60
|
+
username = options.get_option(:username, mandatory: true)
|
|
60
61
|
return {
|
|
62
|
+
preset_ids: [username],
|
|
61
63
|
preset_value: {
|
|
62
64
|
url: app_url,
|
|
63
|
-
username:
|
|
65
|
+
username: username,
|
|
64
66
|
password: options.get_option(:password, mandatory: true)
|
|
65
67
|
},
|
|
66
68
|
test_args: 'transfer current list'
|
|
@@ -42,7 +42,7 @@ module Aspera
|
|
|
42
42
|
next unless File.directory?(folder)
|
|
43
43
|
# TODO: add gem root to load path ? and require short folder ?
|
|
44
44
|
# $LOAD_PATH.push(folder) if i[:add_path]
|
|
45
|
-
Dir.
|
|
45
|
+
Dir.children(folder).each do |source|
|
|
46
46
|
next unless source.end_with?(Environment::RB_EXT)
|
|
47
47
|
path = File.join(folder, source)
|
|
48
48
|
plugin_symbol = File.basename(path, Environment::RB_EXT).to_sym
|
|
@@ -69,7 +69,7 @@ module Aspera
|
|
|
69
69
|
formatter.display_status('Ask the ascli client id and secret to your Administrator.'.red)
|
|
70
70
|
formatter.display_status("Log in as an admin user at: #{app_url}")
|
|
71
71
|
Environment.instance.open_uri(app_url)
|
|
72
|
-
|
|
72
|
+
wizard.display_navigation(Environment.char('𓃑'), 'Admin', 'Configurations', 'API clients')
|
|
73
73
|
formatter.display_status('Create an API client with:')
|
|
74
74
|
formatter.display_status('- name: ascli')
|
|
75
75
|
formatter.display_status('- JWT: enabled')
|
|
@@ -82,9 +82,10 @@ module Aspera
|
|
|
82
82
|
private_key_path = wizard.ask_private_key(
|
|
83
83
|
user: wiz_username,
|
|
84
84
|
url: app_url,
|
|
85
|
-
page: '👤
|
|
85
|
+
page: [Environment.char('👤'), 'Account Settings', 'Preferences', 'Public Key in PEM']
|
|
86
86
|
)
|
|
87
87
|
return {
|
|
88
|
+
preset_ids: [wiz_username, client_id].compact,
|
|
88
89
|
preset_value: {
|
|
89
90
|
url: app_url,
|
|
90
91
|
username: wiz_username,
|
|
@@ -321,8 +322,7 @@ module Aspera
|
|
|
321
322
|
)
|
|
322
323
|
# well, we asked a TS for connect, but we actually want a generic one
|
|
323
324
|
transfer_spec.delete('authentication')
|
|
324
|
-
Runner.
|
|
325
|
-
return Result::SingleObject.new(package)
|
|
325
|
+
return Runner.result_object_transfer(package, transfer.start(transfer_spec))
|
|
326
326
|
else
|
|
327
327
|
# send from remote shared folder
|
|
328
328
|
if (m = Parser.percent_selector(shared_folder))
|
|
@@ -529,9 +529,9 @@ module Aspera
|
|
|
529
529
|
command :user, description: 'Manage current user'
|
|
530
530
|
command :shared_folders, description: 'Browse shared folders'
|
|
531
531
|
command :gateway, description: 'Start Faspex 4 gateway emulation',
|
|
532
|
-
arguments: [{name: :parameters, type: Hash, mandatory: false, default: {}}]
|
|
532
|
+
arguments: [{name: :parameters, type: Hash, mandatory: false, default: {}, schema: Schema::Registry::GATEWAY_OPTIONS}]
|
|
533
533
|
command :postprocessing, description: 'Start Faspex 4 post-processing server',
|
|
534
|
-
arguments: [{name: :parameters, type: Hash, mandatory: false, default: {}}]
|
|
534
|
+
arguments: [{name: :parameters, type: Hash, mandatory: false, default: {}, schema: Schema::Registry::POSTPROC_OPTIONS}]
|
|
535
535
|
command :invitations, description: 'Manage invitations'
|
|
536
536
|
|
|
537
537
|
commands_under :invitations do
|
|
@@ -978,24 +978,14 @@ module Aspera
|
|
|
978
978
|
|
|
979
979
|
def action_gateway(parameters: {}, **)
|
|
980
980
|
require 'aspera/faspex_gw'
|
|
981
|
-
parameters
|
|
982
|
-
uri = URI.parse(parameters.delete(:url) { WebServerSimple::DEFAULT_URL })
|
|
983
|
-
server = WebServerSimple.new(uri, **parameters.slice(*WebServerSimple::PARAMS))
|
|
984
|
-
Aspera.assert(parameters.except(*WebServerSimple::PARAMS).empty?) { "unexpected parameters: #{parameters.except(*WebServerSimple::PARAMS).keys}" }
|
|
985
|
-
server.mount(uri.path, Faspex4GWServlet, api_v5, nil)
|
|
986
|
-
server.start
|
|
981
|
+
Faspex4GWServlet.serve(parameters.symbolize_keys, type: Cli::BadArgument) { [api_v5, nil] }
|
|
987
982
|
Result::Status.new('Gateway terminated')
|
|
988
983
|
end
|
|
989
984
|
|
|
990
985
|
def action_postprocessing(parameters: {}, **)
|
|
991
986
|
require 'aspera/faspex_postproc' # cspell:disable-line
|
|
992
|
-
parameters
|
|
993
|
-
|
|
994
|
-
parameters[:root] = uri.path
|
|
995
|
-
server = WebServerSimple.new(uri, **parameters.slice(*WebServerSimple::PARAMS))
|
|
996
|
-
server.mount(uri.path, Faspex4PostProcServlet, parameters.except(*WebServerSimple::PARAMS))
|
|
997
|
-
server.start
|
|
998
|
-
Result::Status.new('Gateway terminated')
|
|
987
|
+
Faspex4PostProcServlet.serve(parameters.symbolize_keys, type: Cli::BadArgument)
|
|
988
|
+
Result::Status.new('Post-processing terminated')
|
|
999
989
|
end
|
|
1000
990
|
ACCOUNT_TYPES = %w{local_user saml_user self_registered_user external_user}.freeze
|
|
1001
991
|
WORKGROUP_TYPES = %w{workgroup shared_inbox}.freeze
|
|
@@ -29,23 +29,48 @@ module Aspera
|
|
|
29
29
|
# @param app_url [String] Tested URL
|
|
30
30
|
# @return [Hash] :preset_value, :test_args
|
|
31
31
|
def wizard(wizard, app_url)
|
|
32
|
+
auth_type = options.get_option(:auth, mandatory: wizard.required) || :basic
|
|
33
|
+
preset_value = {
|
|
34
|
+
url: app_url,
|
|
35
|
+
auth: auth_type.to_s
|
|
36
|
+
}
|
|
37
|
+
preset_ids = []
|
|
38
|
+
case auth_type
|
|
39
|
+
when :none
|
|
40
|
+
# No credentials needed
|
|
41
|
+
when :basic
|
|
42
|
+
username = options.get_option(:username, mandatory: true)
|
|
43
|
+
preset_value[:username] = username
|
|
44
|
+
preset_value[:password] = options.get_option(:password, mandatory: true)
|
|
45
|
+
preset_ids.push(username)
|
|
46
|
+
when :jwt
|
|
47
|
+
client_id = options.get_option(:client_id, mandatory: true)
|
|
48
|
+
preset_value[:client_id] = client_id
|
|
49
|
+
key_path = options.get_option(:key_path)
|
|
50
|
+
preset_value[:private_key] = key_path ? "@file:#{key_path}" : options.get_option(:private_key, mandatory: true)
|
|
51
|
+
passphrase = options.get_option(:passphrase)
|
|
52
|
+
preset_value[:passphrase] = passphrase unless passphrase.nil?
|
|
53
|
+
preset_ids.push(client_id)
|
|
54
|
+
end
|
|
32
55
|
return {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
},
|
|
56
|
+
preset_ids: preset_ids,
|
|
57
|
+
preset_value: preset_value,
|
|
36
58
|
test_args: 'bridges list'
|
|
37
59
|
}
|
|
38
60
|
end
|
|
39
61
|
|
|
40
|
-
command :health,
|
|
62
|
+
command :health, description: 'Check faspio Gateway health'
|
|
63
|
+
command :metrics, description: 'Get Prometheus metrics'
|
|
41
64
|
|
|
42
65
|
commands_under :bridges do
|
|
43
66
|
crud_commands entity: 'bridges',
|
|
44
67
|
api: :build_api,
|
|
68
|
+
operations: %i[create list show delete],
|
|
69
|
+
lookup: %w[name],
|
|
45
70
|
body_component: Schema::Registry::FASPIO
|
|
46
71
|
end
|
|
47
72
|
|
|
48
|
-
option :auth, description: '
|
|
73
|
+
option :auth, description: 'Type of authentication', allowed: %i[basic jwt none]
|
|
49
74
|
option :client_id, description: 'OAuth client identifier'
|
|
50
75
|
option :private_key, description: 'OAuth JWT RSA private key PEM **value**'
|
|
51
76
|
option :passphrase, description: 'OAuth JWT RSA private key passphrase'
|
|
@@ -55,6 +80,8 @@ module Aspera
|
|
|
55
80
|
def build_api
|
|
56
81
|
base_url = options.get_option(:url, mandatory: true)
|
|
57
82
|
case options.get_option(:auth, mandatory: true)
|
|
83
|
+
when :none
|
|
84
|
+
Rest::Client.new(base_url: base_url)
|
|
58
85
|
when :basic
|
|
59
86
|
basic_auth_api
|
|
60
87
|
when :jwt
|
|
@@ -94,6 +121,10 @@ module Aspera
|
|
|
94
121
|
end
|
|
95
122
|
Result::ObjectList.new(nagios.status_list)
|
|
96
123
|
end
|
|
124
|
+
|
|
125
|
+
def action_metrics(**)
|
|
126
|
+
Result::Text.new(build_api.read('metrics', headers: {'Accept' => 'text/plain'}))
|
|
127
|
+
end
|
|
97
128
|
end
|
|
98
129
|
end
|
|
99
130
|
end
|