aspera-cli 4.26.2 → 4.27.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 +281 -21
- data/CONTRIBUTING.md +98 -7
- data/bin/ascli +3 -3
- data/docs/README.md +10757 -0
- data/docs/test-mcp-with-ai.md +202 -0
- data/lib/aspera/agent/base.rb +20 -6
- data/lib/aspera/agent/connect.rb +53 -16
- data/lib/aspera/agent/desktop.rb +52 -17
- data/lib/aspera/agent/direct.rb +26 -24
- data/lib/aspera/agent/httpgw.rb +1 -1
- data/lib/aspera/agent/node.rb +32 -0
- data/lib/aspera/agent/transferd.rb +39 -3
- data/lib/aspera/api/alee.rb +1 -1
- data/lib/aspera/api/aoc.rb +14 -16
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/faspex.rb +15 -14
- data/lib/aspera/api/httpgw.rb +4 -4
- data/lib/aspera/api/node.rb +26 -23
- data/lib/aspera/api/queries/bss_subscription_account.graphql +18 -0
- data/lib/aspera/api/queries/bss_subscription_usage.graphql +18 -0
- data/lib/aspera/ascmd.rb +21 -19
- data/lib/aspera/ascp/installation.rb +37 -38
- data/lib/aspera/ascp/management.rb +2 -3
- data/lib/aspera/cli/ascp_actions.rb +155 -0
- data/lib/aspera/cli/async_transfer_store.rb +81 -0
- data/lib/aspera/cli/bootstrapper.rb +197 -0
- data/lib/aspera/cli/command_registry.rb +145 -0
- data/lib/aspera/cli/command_spec.rb +138 -0
- data/lib/aspera/cli/context.rb +16 -3
- data/lib/aspera/cli/error.rb +16 -0
- data/lib/aspera/cli/extended_value.rb +2 -1
- data/lib/aspera/cli/formatter.rb +41 -27
- data/lib/aspera/cli/gem_checker.rb +65 -0
- data/lib/aspera/cli/hints.rb +2 -2
- data/lib/aspera/cli/http.rb +70 -19
- data/lib/aspera/cli/info.rb +2 -0
- data/lib/aspera/cli/mailer.rb +97 -0
- data/lib/aspera/cli/mcp_tool.rb +198 -0
- data/lib/aspera/cli/options.schema.yaml +364 -7
- data/lib/aspera/cli/{manager.rb → parser.rb} +334 -142
- data/lib/aspera/cli/plugins/alee.rb +20 -22
- data/lib/aspera/cli/plugins/aoc.rb +1166 -853
- data/lib/aspera/cli/plugins/ats.rb +200 -161
- data/lib/aspera/cli/plugins/base.rb +457 -100
- data/lib/aspera/cli/plugins/basic_auth.rb +14 -4
- data/lib/aspera/cli/plugins/config.rb +428 -754
- data/lib/aspera/cli/plugins/console.rb +106 -64
- data/lib/aspera/cli/plugins/cos.rb +44 -32
- data/lib/aspera/cli/plugins/factory.rb +4 -4
- data/lib/aspera/cli/plugins/faspex.rb +294 -257
- data/lib/aspera/cli/plugins/faspex5.rb +585 -357
- data/lib/aspera/cli/plugins/faspio.rb +49 -51
- data/lib/aspera/cli/plugins/httpgw.rb +18 -25
- data/lib/aspera/cli/plugins/mcp.rb +279 -0
- data/lib/aspera/cli/plugins/node.rb +998 -794
- data/lib/aspera/cli/plugins/oauth.rb +7 -10
- data/lib/aspera/cli/plugins/orchestrator.rb +111 -134
- data/lib/aspera/cli/plugins/preview.rb +180 -139
- data/lib/aspera/cli/plugins/server.rb +124 -79
- data/lib/aspera/cli/plugins/shares.rb +301 -107
- data/lib/aspera/cli/preset_actions.rb +139 -0
- data/lib/aspera/cli/preset_manager.rb +13 -12
- data/lib/aspera/cli/result.rb +61 -11
- data/lib/aspera/cli/runner.rb +275 -141
- data/lib/aspera/cli/secret_finder.rb +40 -0
- data/lib/aspera/cli/special_values.rb +1 -0
- data/lib/aspera/cli/sync_actions.rb +83 -59
- data/lib/aspera/cli/terminal_formatter.rb +1 -1
- data/lib/aspera/cli/transfer_actions.rb +83 -0
- data/lib/aspera/cli/transfer_agent.rb +116 -51
- data/lib/aspera/cli/transfer_progress.rb +3 -3
- data/lib/aspera/cli/vault_manager.rb +57 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +21 -20
- data/lib/aspera/command_line_builder.rb +22 -22
- data/lib/aspera/data_repository.rb +2 -1
- data/lib/aspera/dot_container.rb +4 -4
- data/lib/aspera/environment.rb +18 -11
- data/lib/aspera/exec_spec.rb +13 -0
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/faspex_postproc.rb +4 -3
- data/lib/aspera/graphql.rb +35 -0
- data/lib/aspera/hash_ext.rb +6 -0
- data/lib/aspera/json_rpc/client.rb +62 -0
- data/lib/aspera/json_rpc/version.rb +7 -0
- data/lib/aspera/keychain/encrypted_hash.rb +1 -1
- data/lib/aspera/keychain/factory.rb +3 -3
- data/lib/aspera/keychain/macos_security.rb +3 -3
- data/lib/aspera/link_header.rb +82 -0
- data/lib/aspera/log.rb +17 -3
- data/lib/aspera/markdown.rb +85 -2
- data/lib/aspera/node_simulator.rb +3 -1
- data/lib/aspera/oauth/base.rb +5 -5
- data/lib/aspera/oauth/boot.rb +2 -2
- data/lib/aspera/oauth/factory.rb +7 -5
- data/lib/aspera/oauth/jwt.rb +4 -4
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/persistency_action_once.rb +8 -8
- data/lib/aspera/persistency_folder.rb +10 -3
- data/lib/aspera/preview/file_types.rb +3 -3
- data/lib/aspera/preview/generator.rb +3 -3
- data/lib/aspera/preview/utils.rb +1 -1
- data/lib/aspera/products/connect.rb +1 -1
- data/lib/aspera/products/other.rb +1 -1
- data/lib/aspera/products/transferd.rb +1 -1
- data/lib/aspera/proxy_auto_config.rb +7 -6
- data/lib/aspera/rest.rb +10 -36
- data/lib/aspera/rest_error_analyzer.rb +3 -3
- data/lib/aspera/rest_errors_aspera.rb +0 -10
- data/lib/aspera/rest_list.rb +3 -3
- data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +1853 -510
- data/lib/aspera/schema/documentation.rb +57 -26
- data/lib/aspera/schema/reader.rb +59 -10
- data/lib/aspera/schema/registry.rb +39 -6
- data/lib/aspera/secret_hider.rb +7 -2
- data/lib/aspera/ssl.rb +4 -4
- data/lib/aspera/sync/conf.schema.yaml +2 -2
- data/lib/aspera/sync/operations.rb +10 -13
- data/lib/aspera/temp_file_manager.rb +1 -1
- data/lib/aspera/timer_limiter.rb +1 -1
- data/lib/aspera/transfer/faux_file.rb +24 -11
- data/lib/aspera/transfer/parameters.rb +23 -21
- data/lib/aspera/transfer/result.rb +74 -0
- data/lib/aspera/transfer/resumer.rb +6 -6
- data/lib/aspera/transfer/spec.rb +18 -1
- data/lib/aspera/transfer/spec.schema.yaml +12 -3
- data/lib/aspera/uri_reader.rb +2 -2
- data/lib/aspera/web_auth.rb +2 -2
- data/lib/aspera/web_server_simple.rb +8 -5
- data/lib/aspera/yaml.rb +2 -1
- data.tar.gz.sig +0 -0
- metadata +25 -3
- metadata.gz.sig +0 -0
- data/lib/aspera/json_rpc.rb +0 -52
|
@@ -15,23 +15,94 @@ module Aspera
|
|
|
15
15
|
# Access Aspera Transfer Service
|
|
16
16
|
# https://developer.ibm.com/aspera/docs/ats-api-reference/creating-ats-api-keys/
|
|
17
17
|
class Ats < Base
|
|
18
|
+
application_name 'Aspera Transfer Service'
|
|
18
19
|
# columns for list of cloud providers
|
|
19
20
|
CLOUD_TABLE = %w[id name].freeze
|
|
20
21
|
private_constant :CLOUD_TABLE
|
|
22
|
+
|
|
23
|
+
option :ibm_api_key, description: 'IBM API key, see https://cloud.ibm.com/iam/apikeys'
|
|
24
|
+
option :instance, description: 'ATS instance in ibm cloud'
|
|
25
|
+
option :ats_key, description: 'ATS key identifier (ats_xxx)'
|
|
26
|
+
option :ats_secret, description: 'ATS key secret'
|
|
27
|
+
option :cloud, description: 'Cloud provider'
|
|
28
|
+
option :region, description: 'Cloud region'
|
|
29
|
+
|
|
21
30
|
def initialize(api: nil, **base_args)
|
|
22
31
|
super(**base_args)
|
|
23
32
|
@ats_api_open = Api::Ats.new
|
|
24
33
|
@ats_api_auth = api
|
|
25
|
-
options.declare(:ibm_api_key, 'IBM API key, see https://cloud.ibm.com/iam/apikeys')
|
|
26
|
-
options.declare(:instance, 'ATS instance in ibm cloud')
|
|
27
|
-
options.declare(:ats_key, 'ATS key identifier (ats_xxx)')
|
|
28
|
-
options.declare(:ats_secret, 'ATS key secret')
|
|
29
|
-
options.declare(:cloud, 'Cloud provider')
|
|
30
|
-
options.declare(:region, 'Cloud region')
|
|
31
34
|
options.parse_options!
|
|
32
35
|
Node.declare_options(options)
|
|
33
36
|
end
|
|
34
37
|
|
|
38
|
+
# --- DSL ---
|
|
39
|
+
|
|
40
|
+
command :cluster, description: 'Display general ATS cluster information (public API, no auth)'
|
|
41
|
+
command :access_key, description: 'Manage ATS access keys'
|
|
42
|
+
command :api_key, description: 'Manage credential to access ATS API', condition: :api_key_available?
|
|
43
|
+
command :aws_trust_policy, description: 'Show AWS trust policy', action: lambda{Result::SingleObject.new(ats_api.read('aws/trustpolicy', {region: options.get_option(:region, mandatory: true)}))}
|
|
44
|
+
|
|
45
|
+
commands_under(:cluster) do
|
|
46
|
+
command :clouds, description: 'List cloud providers', action: lambda{Result::ObjectList.new(@ats_api_open.cloud_names.map{ |k, v| CLOUD_TABLE.zip([k, v]).to_h})}
|
|
47
|
+
command :list, description: 'List ATS servers', action: lambda{Result::ObjectList.new(@ats_api_open.all_servers, fields: %w[id cloud region])}
|
|
48
|
+
command :show, description: 'Show a specific server'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
commands_under(:access_key) do
|
|
52
|
+
command :create, description: 'Create an access key',
|
|
53
|
+
arguments: [{name: :params, type: Hash, mandatory: false, default: {}}]
|
|
54
|
+
command(:list, description: 'List access keys', action: lambda do
|
|
55
|
+
res = ats_api.read('access_keys', query_read_delete(default: {'offset' => 0, 'max_results' => 1000}))
|
|
56
|
+
Result::ObjectList.new(res['data'], fields: ['name', 'id', 'created.at', 'modified.at'])
|
|
57
|
+
end)
|
|
58
|
+
command :show, description: 'Show an access key',
|
|
59
|
+
arguments: [{name: :access_key_id, type: :identifier}],
|
|
60
|
+
action: ->(access_key_id:, **){Result::SingleObject.new(ats_api.read("access_keys/#{access_key_id}"))}
|
|
61
|
+
command :modify, description: 'Modify an access key',
|
|
62
|
+
arguments: [{name: :access_key_id, type: :identifier}, {name: :params, type: Hash}]
|
|
63
|
+
command :delete, description: 'Delete an access key',
|
|
64
|
+
arguments: [{name: :access_key_id, type: :identifier}]
|
|
65
|
+
command :node, description: 'Execute node commands via ATS access key',
|
|
66
|
+
arguments: [{name: :access_key_id, type: :identifier}],
|
|
67
|
+
setup: :setup_ak_node
|
|
68
|
+
command :cluster, description: 'Show cluster info for an access key',
|
|
69
|
+
arguments: [{name: :access_key_id, type: :identifier}]
|
|
70
|
+
command :entitlement, description: 'Show ATS entitlement for an access key',
|
|
71
|
+
arguments: [{name: :access_key_id, type: :identifier}]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
commands_under(%i[access_key node]) do
|
|
75
|
+
Node::COMMANDS_GEN4.each do |cmd|
|
|
76
|
+
command(cmd, description: "Node Gen4 #{cmd} command")
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
commands_under(:api_key) do
|
|
81
|
+
command(:instances, description: 'List ATS instances in IBM Cloud', action: lambda do
|
|
82
|
+
instances = ats_api_v2_auth_ibm.read('instances')
|
|
83
|
+
Log.log.warn{"more instances remaining: #{instances['remaining']}"} unless instances['remaining'].to_i.eql?(0)
|
|
84
|
+
Result::ValueList.new(instances['data'], name: 'instance')
|
|
85
|
+
end)
|
|
86
|
+
command :create, description: 'Create an ATS API key',
|
|
87
|
+
arguments: [{name: :params, type: Hash, mandatory: false, default: {}}],
|
|
88
|
+
action: ->(params:, **){Result::SingleObject.new(build_ats_ibm_api_with_instance.create('api_keys', params))}
|
|
89
|
+
command :list, description: 'List ATS API keys', action: lambda{Result::ValueList.new(build_ats_ibm_api_with_instance.read('api_keys', {'offset' => 0, 'max_results' => 1000})['data'], name: 'ats_id')}
|
|
90
|
+
command :show, description: 'Show an ATS API key',
|
|
91
|
+
arguments: [{name: :api_key_id, type: :identifier}],
|
|
92
|
+
action: ->(api_key_id:, **){Result::SingleObject.new(build_ats_ibm_api_with_instance.read("api_keys/#{api_key_id}"))}
|
|
93
|
+
command :delete, description: 'Delete an ATS API key',
|
|
94
|
+
arguments: [{name: :api_key_id, type: :identifier}]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# --- conditions ---
|
|
98
|
+
|
|
99
|
+
# api_key sub-tree is only available when authenticated via ATS key (not injected API)
|
|
100
|
+
def api_key_available?
|
|
101
|
+
@ats_api_auth.nil?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# --- helpers ---
|
|
105
|
+
|
|
35
106
|
def server_by_cloud_region
|
|
36
107
|
# TODO: provide list ?
|
|
37
108
|
cloud = options.get_option(:cloud, mandatory: true).upcase
|
|
@@ -52,113 +123,6 @@ module Aspera
|
|
|
52
123
|
)
|
|
53
124
|
end
|
|
54
125
|
|
|
55
|
-
def execute_action_access_key
|
|
56
|
-
commands = %i[create list show modify delete node cluster entitlement]
|
|
57
|
-
command = options.get_next_command(commands)
|
|
58
|
-
# those do not require access key id
|
|
59
|
-
access_key_id = options.instance_identifier unless %i[create list].include?(command)
|
|
60
|
-
case command
|
|
61
|
-
when :create
|
|
62
|
-
params = value_create_modify(command: command, default: {})
|
|
63
|
-
server_data = nil
|
|
64
|
-
# if transfer_server_id not provided, get it from command line options
|
|
65
|
-
if !params.key?('transfer_server_id')
|
|
66
|
-
server_data = server_by_cloud_region
|
|
67
|
-
params['transfer_server_id'] = server_data['id']
|
|
68
|
-
end
|
|
69
|
-
Log.log.debug{"using params: #{params}".bg_red.gray}
|
|
70
|
-
if params.key?('storage')
|
|
71
|
-
case params['storage']['type']
|
|
72
|
-
# here we need somehow to map storage type to field to get for auth end point
|
|
73
|
-
when 'ibm-s3'
|
|
74
|
-
server_data2 = nil
|
|
75
|
-
if server_data.nil?
|
|
76
|
-
server_data2 = @ats_api_open.all_servers.find{ |s| s['id'].eql?(params['transfer_server_id'])}
|
|
77
|
-
raise "no such transfer server id: #{params['transfer_server_id']}" if server_data2.nil?
|
|
78
|
-
else
|
|
79
|
-
server_data2 = @ats_api_open.all_servers.find do |s|
|
|
80
|
-
s['cloud'].eql?(server_data['cloud']) &&
|
|
81
|
-
s['region'].eql?(server_data['region']) &&
|
|
82
|
-
s.key?('s3_authentication_endpoint')
|
|
83
|
-
end
|
|
84
|
-
raise "no such transfer server id: #{params['transfer_server_id']}" if server_data2.nil?
|
|
85
|
-
# specific one do not have s3 end point in id
|
|
86
|
-
params['transfer_server_id'] = server_data2['id']
|
|
87
|
-
end
|
|
88
|
-
params['storage']['endpoint'] = server_data2['s3_authentication_endpoint'] if !params['storage'].key?('authentication_endpoint')
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
res = ats_api.create('access_keys', params)
|
|
92
|
-
return Result::SingleObject.new(res)
|
|
93
|
-
# TODO : action : modify, with "PUT"
|
|
94
|
-
when :list
|
|
95
|
-
params = query_read_delete(default: {'offset' => 0, 'max_results' => 1000})
|
|
96
|
-
res = ats_api.read('access_keys', params)
|
|
97
|
-
return Result::ObjectList.new(res['data'], fields: ['name', 'id', 'created.at', 'modified.at'])
|
|
98
|
-
when :show
|
|
99
|
-
res = ats_api.read("access_keys/#{access_key_id}")
|
|
100
|
-
return Result::SingleObject.new(res)
|
|
101
|
-
when :modify
|
|
102
|
-
params = value_create_modify(command: command)
|
|
103
|
-
params['id'] = access_key_id
|
|
104
|
-
ats_api.update("access_keys/#{access_key_id}", params)
|
|
105
|
-
return Result::Status.new('modified')
|
|
106
|
-
when :entitlement
|
|
107
|
-
ak = ats_api.read("access_keys/#{access_key_id}")
|
|
108
|
-
api_bss = Api::Alee.new(ak['license']['entitlement_id'], ak['license']['customer_id'])
|
|
109
|
-
return Result::SingleObject.new(api_bss.read('entitlement'))
|
|
110
|
-
when :delete
|
|
111
|
-
ats_api.delete("access_keys/#{access_key_id}")
|
|
112
|
-
return Result::Status.new("deleted #{access_key_id}")
|
|
113
|
-
when :node
|
|
114
|
-
ak_data = ats_api.read("access_keys/#{access_key_id}")
|
|
115
|
-
server_data = @ats_api_open.all_servers.find{ |i| i['id'].start_with?(ak_data['transfer_server_id'])}
|
|
116
|
-
raise Cli::Error, 'no such server found' if server_data.nil?
|
|
117
|
-
node_url = server_data['transfer_setup_url']
|
|
118
|
-
api_node = Api::Node.new(
|
|
119
|
-
base_url: node_url,
|
|
120
|
-
auth: {
|
|
121
|
-
type: :basic,
|
|
122
|
-
username: access_key_id,
|
|
123
|
-
password: config.lookup_secret(url: node_url, username: access_key_id)
|
|
124
|
-
}
|
|
125
|
-
)
|
|
126
|
-
command = options.get_next_command(Node::COMMANDS_GEN4)
|
|
127
|
-
return Node.new(context: context, api: api_node).execute_command_gen4(command, ak_data['root_file_id'])
|
|
128
|
-
when :cluster
|
|
129
|
-
ats_url = ats_api.base_url
|
|
130
|
-
api_ak_auth = Rest.new(
|
|
131
|
-
base_url: ats_url,
|
|
132
|
-
auth: {
|
|
133
|
-
type: :basic,
|
|
134
|
-
username: access_key_id,
|
|
135
|
-
password: config.lookup_secret(url: ats_url, username: access_key_id)
|
|
136
|
-
}
|
|
137
|
-
)
|
|
138
|
-
return Result::SingleObject.new(api_ak_auth.read('servers'))
|
|
139
|
-
else Aspera.error_unexpected_value(command)
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def execute_action_cluster_open
|
|
144
|
-
command = options.get_next_command(%i[clouds list show])
|
|
145
|
-
case command
|
|
146
|
-
when :clouds
|
|
147
|
-
return Result::ObjectList.new(@ats_api_open.cloud_names.map{ |k, v| CLOUD_TABLE.zip([k, v]).to_h})
|
|
148
|
-
when :list
|
|
149
|
-
return Result::ObjectList.new(@ats_api_open.all_servers, fields: %w[id cloud region])
|
|
150
|
-
when :show
|
|
151
|
-
if options.get_option(:cloud) || options.get_option(:region)
|
|
152
|
-
server_data = server_by_cloud_region
|
|
153
|
-
else
|
|
154
|
-
server_id = options.instance_identifier
|
|
155
|
-
server_data = @ats_api_open.all_servers.find{ |i| i['id'].eql?(server_id)}
|
|
156
|
-
raise BadIdentifier.new('server', server_id) if server_data.nil?
|
|
157
|
-
end
|
|
158
|
-
return Result::SingleObject.new(server_data)
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
126
|
def ats_api_v2_auth_ibm(rest_add_headers = {})
|
|
163
127
|
return Rest.new(
|
|
164
128
|
base_url: "#{Api::Ats::SERVICE_BASE_URL}/v2",
|
|
@@ -177,60 +141,135 @@ module Aspera
|
|
|
177
141
|
)
|
|
178
142
|
end
|
|
179
143
|
|
|
180
|
-
def
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
144
|
+
def action_cluster_show
|
|
145
|
+
if options.get_option(:cloud) || options.get_option(:region)
|
|
146
|
+
server_data = server_by_cloud_region
|
|
147
|
+
else
|
|
148
|
+
server_id = options.instance_identifier
|
|
149
|
+
server_data = @ats_api_open.all_servers.find{ |i| i['id'].eql?(server_id)}
|
|
150
|
+
raise BadIdentifier.new('server', server_id) if server_data.nil?
|
|
151
|
+
end
|
|
152
|
+
Result::SingleObject.new(server_data)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def action_access_key_create(params: {}, **)
|
|
156
|
+
server_data = nil
|
|
157
|
+
# if transfer_server_id not provided, get it from command line options
|
|
158
|
+
if !params.key?('transfer_server_id')
|
|
159
|
+
server_data = server_by_cloud_region
|
|
160
|
+
params['transfer_server_id'] = server_data['id']
|
|
161
|
+
end
|
|
162
|
+
Log.log.debug{"using params: #{params}".bg_red.gray}
|
|
163
|
+
if params.key?('storage')
|
|
164
|
+
case params['storage']['type']
|
|
165
|
+
# here we need somehow to map storage type to field to get for auth end point
|
|
166
|
+
when 'ibm-s3'
|
|
167
|
+
server_data2 = nil
|
|
168
|
+
if server_data.nil?
|
|
169
|
+
server_data2 = @ats_api_open.all_servers.find{ |s| s['id'].eql?(params['transfer_server_id'])}
|
|
170
|
+
raise "no such transfer server id: #{params['transfer_server_id']}" if server_data2.nil?
|
|
171
|
+
else
|
|
172
|
+
server_data2 = @ats_api_open.all_servers.find do |s|
|
|
173
|
+
s['cloud'].eql?(server_data['cloud']) &&
|
|
174
|
+
s['region'].eql?(server_data['region']) &&
|
|
175
|
+
s.key?('s3_authentication_endpoint')
|
|
176
|
+
end
|
|
177
|
+
raise "no such transfer server id: #{params['transfer_server_id']}" if server_data2.nil?
|
|
178
|
+
# specific one do not have s3 end point in id
|
|
179
|
+
params['transfer_server_id'] = server_data2['id']
|
|
180
|
+
end
|
|
181
|
+
params['storage']['endpoint'] = server_data2['s3_authentication_endpoint'] if !params['storage'].key?('authentication_endpoint')
|
|
190
182
|
end
|
|
191
|
-
rest_add_header = {'X-ATS-Service-Instance-Id' => instance}
|
|
192
183
|
end
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
184
|
+
res = ats_api.create('access_keys', params)
|
|
185
|
+
return Result::SingleObject.new(res)
|
|
186
|
+
# TODO : action : modify, with "PUT"
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def action_access_key_modify(params:, access_key_id:, **)
|
|
190
|
+
params['id'] = access_key_id
|
|
191
|
+
ats_api.update("access_keys/#{access_key_id}", params)
|
|
192
|
+
return Result::Status.new('modified')
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def action_access_key_delete(access_key_id:, **)
|
|
196
|
+
ats_api.delete("access_keys/#{access_key_id}")
|
|
197
|
+
Result::Status.new("deleted #{access_key_id}")
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def action_access_key_entitlement(access_key_id:, **)
|
|
201
|
+
ak = ats_api.read("access_keys/#{access_key_id}")
|
|
202
|
+
api_bss = Api::Alee.new(ak['license']['entitlement_id'], ak['license']['customer_id'])
|
|
203
|
+
return Result::SingleObject.new(api_bss.read('entitlement'))
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Build the Node plugin for an ATS access key.
|
|
207
|
+
# access_key_id: is already in ctx via arguments: on the :node command.
|
|
208
|
+
# @return [Hash] context hash containing :ak_node_plugin and :ak_root_file_id
|
|
209
|
+
def setup_ak_node(access_key_id:, **)
|
|
210
|
+
ak_data = ats_api.read("access_keys/#{access_key_id}")
|
|
211
|
+
server_data = @ats_api_open.all_servers.find{ |i| i['id'].start_with?(ak_data['transfer_server_id'])}
|
|
212
|
+
Aspera.assert(!server_data.nil?, type: Cli::Error){'no such server found'}
|
|
213
|
+
node_url = server_data['transfer_setup_url']
|
|
214
|
+
api_node = Api::Node.new(
|
|
215
|
+
base_url: node_url,
|
|
216
|
+
auth: {
|
|
217
|
+
type: :basic,
|
|
218
|
+
username: access_key_id,
|
|
219
|
+
password: context.secret_finder.lookup(url: node_url, username: access_key_id)
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
{
|
|
223
|
+
ak_node_plugin: Node.new(context: context, api: api_node),
|
|
224
|
+
ak_root_file_id: ak_data['root_file_id']
|
|
225
|
+
}
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# One handler per COMMANDS_GEN4 - delegates to the Node plugin's DSL registry.
|
|
229
|
+
Node::COMMANDS_GEN4.each do |cmd|
|
|
230
|
+
define_action_method([:access_key, :node, cmd]) do |ak_node_plugin:, ak_root_file_id:, **|
|
|
231
|
+
# For permission: the handler consumes the path first then re-dispatches to sub-commands.
|
|
232
|
+
# Calling dispatch_from_registry with skip_setup would bypass path consumption and fail.
|
|
233
|
+
next ak_node_plugin.send(:"action_access_keys_do_#{cmd}", do_root_file_id: ak_root_file_id) if cmd.eql?(:permission)
|
|
234
|
+
ak_node_plugin.dispatch_from_registry([:access_keys, :do, cmd], {do_root_file_id: ak_root_file_id}, skip_setup: true)
|
|
212
235
|
end
|
|
213
236
|
end
|
|
214
237
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
238
|
+
def action_api_key_instances
|
|
239
|
+
instances = ats_api_v2_auth_ibm.read('instances')
|
|
240
|
+
Log.log.warn{"more instances remaining: #{instances['remaining']}"} unless instances['remaining'].to_i.eql?(0)
|
|
241
|
+
Result::ValueList.new(instances['data'], name: 'instance')
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def action_api_key_delete(api_key_id:, **)
|
|
245
|
+
build_ats_ibm_api_with_instance.delete("api_keys/#{api_key_id}")
|
|
246
|
+
Result::Status.new("deleted #{api_key_id}")
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def action_access_key_cluster(access_key_id:, **)
|
|
250
|
+
ats_url = ats_api.base_url
|
|
251
|
+
api_ak_auth = Rest.new(
|
|
252
|
+
base_url: ats_url,
|
|
253
|
+
auth: {
|
|
254
|
+
type: :basic,
|
|
255
|
+
username: access_key_id,
|
|
256
|
+
password: context.secret_finder.lookup(url: ats_url, username: access_key_id)
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
return Result::SingleObject.new(api_ak_auth.read('servers'))
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
private
|
|
263
|
+
|
|
264
|
+
# Build the IBM Cloud ATS v2 API with an instance header.
|
|
265
|
+
# Reads instance from options; falls back to first available instance.
|
|
266
|
+
def build_ats_ibm_api_with_instance
|
|
267
|
+
instance = options.get_option(:instance)
|
|
268
|
+
if instance.nil?
|
|
269
|
+
instance = ats_api_v2_auth_ibm.read('instances')['data'].first
|
|
270
|
+
formatter.display_status("using first instance: #{instance}")
|
|
233
271
|
end
|
|
272
|
+
ats_api_v2_auth_ibm({'X-ATS-Service-Instance-Id' => instance})
|
|
234
273
|
end
|
|
235
274
|
end
|
|
236
275
|
end
|