aspera-cli 4.6.0 → 4.7.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
- data/README.md +427 -300
- data/bin/ascli +2 -1
- data/bin/asession +1 -0
- data/docs/test_env.conf +2 -0
- data/examples/aoc.rb +4 -3
- data/examples/faspex4.rb +21 -19
- data/examples/proxy.pac +1 -1
- data/examples/transfer.rb +15 -15
- data/lib/aspera/aoc.rb +135 -124
- data/lib/aspera/ascmd.rb +85 -75
- data/lib/aspera/ats_api.rb +11 -10
- data/lib/aspera/cli/basic_auth_plugin.rb +13 -14
- data/lib/aspera/cli/extended_value.rb +42 -33
- data/lib/aspera/cli/formater.rb +138 -111
- data/lib/aspera/cli/info.rb +17 -0
- data/lib/aspera/cli/listener/line_dump.rb +3 -2
- data/lib/aspera/cli/listener/logger.rb +2 -1
- data/lib/aspera/cli/listener/progress.rb +16 -18
- data/lib/aspera/cli/listener/progress_multi.rb +13 -16
- data/lib/aspera/cli/main.rb +122 -130
- data/lib/aspera/cli/manager.rb +146 -154
- data/lib/aspera/cli/plugin.rb +38 -34
- data/lib/aspera/cli/plugins/alee.rb +6 -6
- data/lib/aspera/cli/plugins/aoc.rb +273 -276
- data/lib/aspera/cli/plugins/ats.rb +82 -76
- data/lib/aspera/cli/plugins/bss.rb +14 -16
- data/lib/aspera/cli/plugins/config.rb +350 -306
- data/lib/aspera/cli/plugins/console.rb +23 -19
- data/lib/aspera/cli/plugins/cos.rb +18 -18
- data/lib/aspera/cli/plugins/faspex.rb +180 -159
- data/lib/aspera/cli/plugins/faspex5.rb +64 -54
- data/lib/aspera/cli/plugins/node.rb +147 -140
- data/lib/aspera/cli/plugins/orchestrator.rb +68 -66
- data/lib/aspera/cli/plugins/preview.rb +92 -96
- data/lib/aspera/cli/plugins/server.rb +79 -75
- data/lib/aspera/cli/plugins/shares.rb +23 -24
- data/lib/aspera/cli/plugins/sync.rb +20 -22
- data/lib/aspera/cli/transfer_agent.rb +40 -39
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/colors.rb +35 -27
- data/lib/aspera/command_line_builder.rb +48 -34
- data/lib/aspera/cos_node.rb +29 -21
- data/lib/aspera/data_repository.rb +3 -2
- data/lib/aspera/environment.rb +50 -45
- data/lib/aspera/fasp/agent_base.rb +22 -20
- data/lib/aspera/fasp/agent_connect.rb +13 -11
- data/lib/aspera/fasp/agent_direct.rb +48 -59
- data/lib/aspera/fasp/agent_httpgw.rb +33 -39
- data/lib/aspera/fasp/agent_node.rb +15 -13
- data/lib/aspera/fasp/agent_trsdk.rb +12 -14
- data/lib/aspera/fasp/error.rb +2 -1
- data/lib/aspera/fasp/error_info.rb +68 -52
- data/lib/aspera/fasp/installation.rb +106 -94
- data/lib/aspera/fasp/listener.rb +1 -0
- data/lib/aspera/fasp/parameters.rb +83 -92
- data/lib/aspera/fasp/parameters.yaml +305 -249
- data/lib/aspera/fasp/resume_policy.rb +11 -14
- data/lib/aspera/fasp/transfer_spec.rb +26 -0
- data/lib/aspera/fasp/uri.rb +22 -21
- data/lib/aspera/faspex_gw.rb +55 -90
- data/lib/aspera/hash_ext.rb +4 -3
- data/lib/aspera/id_generator.rb +8 -7
- data/lib/aspera/keychain/encrypted_hash.rb +17 -16
- data/lib/aspera/keychain/macos_security.rb +6 -10
- data/lib/aspera/log.rb +25 -20
- data/lib/aspera/nagios.rb +13 -12
- data/lib/aspera/node.rb +30 -22
- data/lib/aspera/oauth.rb +175 -226
- data/lib/aspera/open_application.rb +4 -3
- data/lib/aspera/persistency_action_once.rb +6 -6
- data/lib/aspera/persistency_folder.rb +5 -9
- data/lib/aspera/preview/file_types.rb +6 -5
- data/lib/aspera/preview/generator.rb +25 -24
- data/lib/aspera/preview/options.rb +16 -14
- data/lib/aspera/preview/utils.rb +98 -98
- data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
- data/lib/aspera/proxy_auto_config.rb +111 -20
- data/lib/aspera/rest.rb +115 -113
- data/lib/aspera/rest_call_error.rb +2 -2
- data/lib/aspera/rest_error_analyzer.rb +23 -25
- data/lib/aspera/rest_errors_aspera.rb +15 -14
- data/lib/aspera/ssh.rb +12 -10
- data/lib/aspera/sync.rb +42 -41
- data/lib/aspera/temp_file_manager.rb +18 -14
- data/lib/aspera/timer_limiter.rb +2 -1
- data/lib/aspera/uri_reader.rb +7 -5
- data/lib/aspera/web_auth.rb +79 -76
- metadata +64 -21
- data/docs/Makefile +0 -65
- data/docs/README.erb.md +0 -4424
- data/docs/README.md +0 -13
- data/docs/diagrams.txt +0 -49
- data/docs/doc_tools.rb +0 -58
- data/lib/aspera/cli/plugins/shares2.rb +0 -114
- data/lib/aspera/fasp/default.rb +0 -17
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'aspera/cli/basic_auth_plugin'
|
|
2
3
|
require 'aspera/cli/extended_value'
|
|
4
|
+
require 'aspera/cli/version'
|
|
3
5
|
require 'aspera/fasp/installation'
|
|
4
6
|
require 'aspera/fasp/parameters'
|
|
5
|
-
require 'aspera/
|
|
6
|
-
require 'aspera/
|
|
7
|
+
require 'aspera/fasp/transfer_spec'
|
|
8
|
+
require 'aspera/fasp/error_info'
|
|
7
9
|
require 'aspera/proxy_auto_config'
|
|
8
|
-
require 'aspera/
|
|
9
|
-
require 'aspera/rest'
|
|
10
|
+
require 'aspera/open_application'
|
|
10
11
|
require 'aspera/persistency_action_once'
|
|
11
12
|
require 'aspera/id_generator'
|
|
12
13
|
require 'aspera/keychain/encrypted_hash'
|
|
13
14
|
require 'aspera/keychain/macos_security'
|
|
15
|
+
require 'aspera/aoc'
|
|
16
|
+
require 'aspera/rest'
|
|
14
17
|
require 'xmlsimple'
|
|
15
18
|
require 'base64'
|
|
16
19
|
require 'net/smtp'
|
|
@@ -32,7 +35,7 @@ module Aspera
|
|
|
32
35
|
CONF_PRESET_VERSION='version'
|
|
33
36
|
CONF_PRESET_DEFAULT='default'
|
|
34
37
|
CONF_PRESET_GLOBAL='global_common_defaults'
|
|
35
|
-
CONF_PRESET_SECRETS='default_secrets'
|
|
38
|
+
CONF_PRESET_SECRETS='default_secrets' # pragma: allowlist secret
|
|
36
39
|
CONF_PLUGIN_SYM = :config # Plugins::Config.name.split('::').last.downcase.to_sym
|
|
37
40
|
CONF_GLOBAL_SYM = :config
|
|
38
41
|
# old tool name
|
|
@@ -54,19 +57,19 @@ module Aspera
|
|
|
54
57
|
DEMO='demo'
|
|
55
58
|
DEMO_SERVER_PRESET='demoserver'
|
|
56
59
|
AOC_PATH_API_CLIENTS='admin/api-clients'
|
|
57
|
-
EMAIL_TEST_TEMPLATE
|
|
58
|
-
From: <%=from_name%> <<%=from_email%>>
|
|
59
|
-
To: <<%=to%>>
|
|
60
|
-
Subject: Amelia email test
|
|
60
|
+
EMAIL_TEST_TEMPLATE=<<~END_OF_TEMPLATE
|
|
61
|
+
From: <%=from_name%> <<%=from_email%>>
|
|
62
|
+
To: <<%=to%>>
|
|
63
|
+
Subject: Amelia email test
|
|
61
64
|
|
|
62
|
-
It worked !
|
|
63
|
-
END_OF_TEMPLATE
|
|
65
|
+
It worked !
|
|
66
|
+
END_OF_TEMPLATE
|
|
64
67
|
# special extended values
|
|
65
|
-
EXTV_INCLUDE_PRESETS
|
|
66
|
-
EXTV_PRESET
|
|
68
|
+
EXTV_INCLUDE_PRESETS=:incps
|
|
69
|
+
EXTV_PRESET=:preset
|
|
67
70
|
PRESET_DIG_SEPARATOR='.'
|
|
68
71
|
DEFAULT_CHECK_NEW_VERSION_DAYS=7
|
|
69
|
-
DEFAULT_PRIV_KEY_FILENAME='aspera_aoc_key'
|
|
72
|
+
DEFAULT_PRIV_KEY_FILENAME='aspera_aoc_key' # pragma: allowlist secret
|
|
70
73
|
DEFAULT_PRIVKEY_LENGTH=4096
|
|
71
74
|
private_constant :DEFAULT_CONFIG_FILENAME,:CONF_PRESET_CONFIG,:CONF_PRESET_VERSION,:CONF_PRESET_DEFAULT,
|
|
72
75
|
:CONF_PRESET_GLOBAL,:PROGRAM_NAME_V1,:PROGRAM_NAME_V2,:DEFAULT_REDIRECT,:ASPERA_PLUGINS_FOLDERNAME,
|
|
@@ -74,93 +77,103 @@ END_OF_TEMPLATE
|
|
|
74
77
|
:TRANSFER_SDK_ARCHIVE_URL,:AOC_PATH_API_CLIENTS,:DEMO_SERVER_PRESET,:EMAIL_TEST_TEMPLATE,:EXTV_INCLUDE_PRESETS,
|
|
75
78
|
:EXTV_PRESET,:DEFAULT_CHECK_NEW_VERSION_DAYS,:DEFAULT_PRIV_KEY_FILENAME,:SERVER_COMMAND,:CONF_PRESET_SECRETS,
|
|
76
79
|
:PRESET_DIG_SEPARATOR
|
|
77
|
-
def
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
case value
|
|
81
|
-
when String
|
|
82
|
-
self.options.add_option_preset(preset_by_name(value))
|
|
83
|
-
when Hash
|
|
84
|
-
self.options.add_option_preset(value)
|
|
85
|
-
else
|
|
86
|
-
raise 'Preset definition must be a String for name, or Hash for value'
|
|
87
|
-
end
|
|
88
|
-
nil
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def initialize(env,tool_name,help_url,version,main_folder)
|
|
80
|
+
def initialize(env,params)
|
|
81
|
+
raise 'env and params must be Hash' unless env.is_a?(Hash) && params.is_a?(Hash)
|
|
82
|
+
raise 'missing param' unless [:name,:help,:version,:gem].sort.eql?(params.keys.sort)
|
|
92
83
|
super(env)
|
|
84
|
+
@info=params
|
|
85
|
+
@main_folder=default_app_main_folder
|
|
93
86
|
@plugins={}
|
|
94
87
|
@plugin_lookup_folders=[]
|
|
95
88
|
@use_plugin_defaults=true
|
|
96
89
|
@config_presets=nil
|
|
97
90
|
@connect_versions=nil
|
|
98
91
|
@vault=nil
|
|
99
|
-
@program_version=version
|
|
100
|
-
@tool_name=tool_name
|
|
101
|
-
@help_url=help_url
|
|
102
|
-
@main_folder=main_folder
|
|
103
92
|
@conf_file_default=File.join(@main_folder,DEFAULT_CONFIG_FILENAME)
|
|
104
93
|
@option_config_file=@conf_file_default
|
|
105
|
-
|
|
94
|
+
@pac_exec=nil
|
|
95
|
+
Log.log.debug("#{@info[:name]} folder: #{@main_folder}")
|
|
106
96
|
# set folder for FASP SDK
|
|
107
97
|
add_plugin_lookup_folder(self.class.gem_plugins_folder)
|
|
108
98
|
add_plugin_lookup_folder(File.join(@main_folder,ASPERA_PLUGINS_FOLDERNAME))
|
|
109
99
|
# do file parameter first
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
100
|
+
options.set_obj_attr(:config_file,self,:option_config_file)
|
|
101
|
+
options.add_opt_simple(:config_file,"read parameters from file in YAML format, current=#{@option_config_file}")
|
|
102
|
+
options.parse_options!
|
|
113
103
|
# read correct file
|
|
114
104
|
read_config_file
|
|
115
105
|
# add preset handler (needed for smtp)
|
|
116
106
|
ExtendedValue.instance.set_handler(EXTV_PRESET,:reader,lambda{|v|preset_by_name(v)})
|
|
117
107
|
ExtendedValue.instance.set_handler(EXTV_INCLUDE_PRESETS,:decoder,lambda{|v|expanded_with_preset_includes(v)})
|
|
118
108
|
# load defaults before it can be overriden
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
109
|
+
add_plugin_default_preset(CONF_GLOBAL_SYM)
|
|
110
|
+
options.parse_options!
|
|
111
|
+
options.set_obj_attr(:ascp_path,Fasp::Installation.instance,:ascp_path)
|
|
112
|
+
options.set_obj_attr(:sdk_folder,Fasp::Installation.instance,:sdk_folder)
|
|
113
|
+
options.set_obj_attr(:use_product,self,:option_use_product)
|
|
114
|
+
options.set_obj_attr(:preset,self,:option_preset)
|
|
115
|
+
options.set_obj_attr(:plugin_folder,self,:option_plugin_folder)
|
|
116
|
+
options.add_opt_switch(:no_default,'-N','do not load default configuration for plugin') { @use_plugin_defaults=false }
|
|
117
|
+
options.add_opt_boolean(:override,'Wizard: override existing value')
|
|
118
|
+
options.add_opt_boolean(:use_generic_client,'Wizard: AoC: use global or org specific jwt client id')
|
|
119
|
+
options.add_opt_boolean(:default,'Wizard: set as default configuration for specified plugin (also: update)')
|
|
120
|
+
options.add_opt_boolean(:test_mode,'Wizard: skip private key check step')
|
|
121
|
+
options.add_opt_simple(:preset,'-PVALUE','load the named option preset from current config file')
|
|
122
|
+
options.add_opt_simple(:pkeypath,'Wizard: path to private key for JWT')
|
|
123
|
+
options.add_opt_simple(:ascp_path,'path to ascp')
|
|
124
|
+
options.add_opt_simple(:use_product,'use ascp from specified product')
|
|
125
|
+
options.add_opt_simple(:smtp,'smtp configuration (extended value: hash)')
|
|
126
|
+
options.add_opt_simple(:fpac,'proxy auto configuration script')
|
|
127
|
+
options.add_opt_simple(:secret,'default secret')
|
|
128
|
+
options.add_opt_simple(:secrets,'secret vault')
|
|
129
|
+
options.add_opt_simple(:sdk_url,'URL to get SDK')
|
|
130
|
+
options.add_opt_simple(:sdk_folder,'SDK folder path')
|
|
131
|
+
options.add_opt_simple(:notif_to,'email recipient for notification of transfers')
|
|
132
|
+
options.add_opt_simple(:notif_template,'email ERB template for notification of transfers')
|
|
133
|
+
options.add_opt_simple(:version_check_days,Integer,'period in days to check new version (zero to disable)')
|
|
134
|
+
options.add_opt_simple(:plugin_folder,'folder where to find additional plugins')
|
|
135
|
+
options.set_option(:use_generic_client,true)
|
|
136
|
+
options.set_option(:test_mode,false)
|
|
137
|
+
options.set_option(:default,true)
|
|
138
|
+
options.set_option(:version_check_days,DEFAULT_CHECK_NEW_VERSION_DAYS)
|
|
139
|
+
options.set_option(:sdk_url,TRANSFER_SDK_ARCHIVE_URL)
|
|
140
|
+
options.set_option(:sdk_folder,File.join(@main_folder,'sdk'))
|
|
141
|
+
options.set_option(:override,:no)
|
|
142
|
+
options.parse_options!
|
|
143
|
+
pac_script=options.get_option(:fpac,:optional)
|
|
144
|
+
# create PAC executor
|
|
145
|
+
@pac_exec=Aspera::ProxyAutoConfig.new(pac_script).register_uri_generic unless pac_script.nil?
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# env var name to override the app's main folder
|
|
149
|
+
# default main folder is $HOME/<vendor main app folder>/<program name>
|
|
150
|
+
def conf_dir_env_var
|
|
151
|
+
return "#{@info[:name]}_home".upcase
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def default_app_main_folder
|
|
155
|
+
# find out application main folder
|
|
156
|
+
app_folder=ENV[conf_dir_env_var]
|
|
157
|
+
# if env var undefined or empty
|
|
158
|
+
if app_folder.nil? || app_folder.empty?
|
|
159
|
+
user_home_folder=Dir.home
|
|
160
|
+
raise CliError,"Home folder does not exist: #{user_home_folder}. Check your user environment or use #{conf_dir_env_var}." unless Dir.exist?(user_home_folder)
|
|
161
|
+
app_folder=File.join(user_home_folder,ASPERA_HOME_FOLDER_NAME,@info[:name])
|
|
162
|
+
end
|
|
163
|
+
return app_folder
|
|
153
164
|
end
|
|
154
165
|
|
|
155
166
|
def check_gem_version
|
|
156
|
-
this_gem_name=File.basename(File.dirname(self.class.gem_root)).gsub(/-[0-9].*$/,'')
|
|
157
167
|
latest_version=begin
|
|
158
|
-
Rest.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{
|
|
159
|
-
rescue
|
|
168
|
+
Rest.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{@info[:gem]}/latest.json")[:data]['version']
|
|
169
|
+
rescue StandardError
|
|
160
170
|
Log.log.warn('Could not retrieve latest gem version on rubygems.')
|
|
161
171
|
'0'
|
|
162
172
|
end
|
|
163
|
-
|
|
173
|
+
if Gem::Version.new(Environment.ruby_version) < Gem::Version.new(RUBY_FUTURE_MINIMUM_VERSION)
|
|
174
|
+
Log.log.warn("Note that a future version will require Ruby version #{RUBY_FUTURE_MINIMUM_VERSION} at minimum, you are using #{Environment.ruby_version}")
|
|
175
|
+
end
|
|
176
|
+
return {name: @info[:gem], current: Aspera::Cli::VERSION, latest: latest_version, need_update: Gem::Version.new(Aspera::Cli::VERSION) < Gem::Version.new(latest_version)}
|
|
164
177
|
end
|
|
165
178
|
|
|
166
179
|
def periodic_check_newer_gem_version
|
|
@@ -168,30 +181,29 @@ END_OF_TEMPLATE
|
|
|
168
181
|
delay_days=options.get_option(:version_check_days,:mandatory)
|
|
169
182
|
Log.log.info("check days: #{delay_days}")
|
|
170
183
|
# check only if not zero day
|
|
171
|
-
if
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
Log.log.debug("days elapsed: #{last_check_date.is_a?(Date) ? current_date - last_check_date : last_check_date.class.name}")
|
|
186
|
-
if last_check_date.nil? or (current_date - last_check_date) > delay_days
|
|
187
|
-
last_check_array[0]=current_date.strftime('%Y/%m/%d')
|
|
188
|
-
check_date_persist.save
|
|
189
|
-
check_data=check_gem_version
|
|
190
|
-
if check_data[:need_update]
|
|
191
|
-
Log.log.warn("A new version is available: #{check_data[:latest]}. You have #{check_data[:current]}. Upgrade with: gem update #{check_data[:name]}")
|
|
192
|
-
end
|
|
193
|
-
end
|
|
184
|
+
return if delay_days.eql?(0)
|
|
185
|
+
# get last date from persistency
|
|
186
|
+
last_check_array=[]
|
|
187
|
+
check_date_persist=PersistencyActionOnce.new(
|
|
188
|
+
manager: persistency,
|
|
189
|
+
data: last_check_array,
|
|
190
|
+
id: 'version_last_check')
|
|
191
|
+
# get persisted date or nil
|
|
192
|
+
current_date=Date.today
|
|
193
|
+
last_check_days = begin
|
|
194
|
+
current_date-Date.strptime(last_check_array.first, '%Y/%m/%d')
|
|
195
|
+
rescue StandardError
|
|
196
|
+
# negative value will force check
|
|
197
|
+
-1
|
|
194
198
|
end
|
|
199
|
+
Log.log.debug("days elapsed: #{last_check_days}")
|
|
200
|
+
return if last_check_days < delay_days
|
|
201
|
+
# generate timestamp
|
|
202
|
+
last_check_array[0]=current_date.strftime('%Y/%m/%d')
|
|
203
|
+
check_date_persist.save
|
|
204
|
+
# compare this version and the one on internet
|
|
205
|
+
check_data=check_gem_version
|
|
206
|
+
Log.log.warn("A new version is available: #{check_data[:latest]}. You have #{check_data[:current]}. Upgrade with: gem update #{check_data[:name]}") if check_data[:need_update]
|
|
195
207
|
end
|
|
196
208
|
|
|
197
209
|
# retrieve structure from cloud (CDN) with all versions available
|
|
@@ -218,9 +230,10 @@ END_OF_TEMPLATE
|
|
|
218
230
|
def add_plugin_default_preset(plugin_name_sym)
|
|
219
231
|
default_config_name=get_plugin_default_config_name(plugin_name_sym)
|
|
220
232
|
Log.log.debug("add_plugin_default_preset:#{plugin_name_sym}:#{default_config_name}")
|
|
221
|
-
|
|
233
|
+
options.add_option_preset(preset_by_name(default_config_name),:unshift) unless default_config_name.nil?
|
|
222
234
|
return nil
|
|
223
235
|
end
|
|
236
|
+
|
|
224
237
|
private
|
|
225
238
|
|
|
226
239
|
def generate_rsa_private_key(private_key_path,length)
|
|
@@ -231,32 +244,40 @@ END_OF_TEMPLATE
|
|
|
231
244
|
nil
|
|
232
245
|
end
|
|
233
246
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
247
|
+
class << self
|
|
248
|
+
# folder containing plugins in the gem's main folder
|
|
249
|
+
def gem_plugins_folder
|
|
250
|
+
File.dirname(File.expand_path(__FILE__))
|
|
251
|
+
end
|
|
238
252
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
253
|
+
# name of englobin module
|
|
254
|
+
# @return "Aspera::Cli::Plugins"
|
|
255
|
+
def module_full_name
|
|
256
|
+
return Module.nesting[2].to_s
|
|
257
|
+
end
|
|
244
258
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
259
|
+
# @return main folder where code is, i.e. .../lib
|
|
260
|
+
# go up as many times as englobing modules (not counting class, as it is a file)
|
|
261
|
+
def gem_src_root
|
|
262
|
+
File.expand_path(module_full_name.gsub('::','/').gsub(%r{[^/]+},'..'),gem_plugins_folder)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# instanciate a plugin
|
|
266
|
+
# plugins must be Capitalized
|
|
267
|
+
def plugin_class(plugin_name_sym)
|
|
268
|
+
# Module.nesting[2] is Aspera::Cli::Plugins
|
|
269
|
+
return Object.const_get("#{module_full_name}::#{plugin_name_sym.to_s.capitalize}")
|
|
270
|
+
end
|
|
251
271
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
272
|
+
def flatten_all_config(t)
|
|
273
|
+
r=[]
|
|
274
|
+
t.each do |k,v|
|
|
275
|
+
v.each do |kk,vv|
|
|
276
|
+
r.push({'config'=>k,'parameter'=>kk,'value'=>vv})
|
|
277
|
+
end
|
|
257
278
|
end
|
|
279
|
+
return r
|
|
258
280
|
end
|
|
259
|
-
return r
|
|
260
281
|
end
|
|
261
282
|
|
|
262
283
|
# set parameter and value in global config
|
|
@@ -281,8 +302,7 @@ END_OF_TEMPLATE
|
|
|
281
302
|
|
|
282
303
|
# $HOME/.aspera/`program_name`
|
|
283
304
|
attr_reader :main_folder
|
|
284
|
-
attr_reader :gem_url
|
|
285
|
-
attr_reader :plugins
|
|
305
|
+
attr_reader :gem_url, :plugins
|
|
286
306
|
attr_accessor :option_config_file
|
|
287
307
|
|
|
288
308
|
# @return the hash from name (also expands possible includes)
|
|
@@ -299,8 +319,8 @@ END_OF_TEMPLATE
|
|
|
299
319
|
raise CliError,"no such config preset: #{include_path}" if nil?
|
|
300
320
|
end
|
|
301
321
|
case current
|
|
302
|
-
when Hash
|
|
303
|
-
when String
|
|
322
|
+
when Hash then return expanded_with_preset_includes(current,include_path)
|
|
323
|
+
when String then return ExtendedValue.instance.evaluate(current)
|
|
304
324
|
else return current
|
|
305
325
|
end
|
|
306
326
|
end
|
|
@@ -316,7 +336,7 @@ END_OF_TEMPLATE
|
|
|
316
336
|
memory.delete(EXTV_INCLUDE_PRESETS)
|
|
317
337
|
hash_val={}
|
|
318
338
|
raise "#{EXTV_INCLUDE_PRESETS} must be an Array" unless includes.is_a?(Array)
|
|
319
|
-
raise "#{EXTV_INCLUDE_PRESETS} must contain names" unless includes.map
|
|
339
|
+
raise "#{EXTV_INCLUDE_PRESETS} must contain names" unless includes.map(&:class).uniq.eql?([String])
|
|
320
340
|
includes.each do |preset_name|
|
|
321
341
|
hash_val.merge!(preset_by_name(preset_name,include_path))
|
|
322
342
|
end
|
|
@@ -325,26 +345,18 @@ END_OF_TEMPLATE
|
|
|
325
345
|
return hash_val
|
|
326
346
|
end
|
|
327
347
|
|
|
328
|
-
def option_ascp_path=(new_value)
|
|
329
|
-
Fasp::Installation.instance.ascp_path=new_value
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
def option_ascp_path
|
|
333
|
-
Fasp::Installation.instance.path(:ascp)
|
|
334
|
-
end
|
|
335
|
-
|
|
336
348
|
def option_use_product=(value)
|
|
337
349
|
Fasp::Installation.instance.use_ascp_from_product(value)
|
|
338
350
|
end
|
|
339
351
|
|
|
340
352
|
def option_use_product
|
|
341
|
-
'write-only value'
|
|
353
|
+
'write-only option, see value of ascp_path'
|
|
342
354
|
end
|
|
343
355
|
|
|
344
356
|
def option_plugin_folder=(value)
|
|
345
357
|
case value
|
|
346
|
-
when String
|
|
347
|
-
when Array
|
|
358
|
+
when String then add_plugin_lookup_folder(value)
|
|
359
|
+
when Array then value.each{|f|add_plugin_lookup_folder(f)}
|
|
348
360
|
else raise "folder shall be Array or String, not #{value.class}"
|
|
349
361
|
end
|
|
350
362
|
end
|
|
@@ -353,6 +365,19 @@ END_OF_TEMPLATE
|
|
|
353
365
|
return @plugin_lookup_folders
|
|
354
366
|
end
|
|
355
367
|
|
|
368
|
+
def option_preset; 'write-only option'; end
|
|
369
|
+
|
|
370
|
+
def option_preset=(value)
|
|
371
|
+
case value
|
|
372
|
+
when String
|
|
373
|
+
options.add_option_preset(preset_by_name(value))
|
|
374
|
+
when Hash
|
|
375
|
+
options.add_option_preset(value)
|
|
376
|
+
else
|
|
377
|
+
raise 'Preset definition must be a String for name, or Hash for value'
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
356
381
|
def convert_preset_path(old_name,new_name,files_to_copy)
|
|
357
382
|
old_subpath=File.join('',ASPERA_HOME_FOLDER_NAME,old_name,'')
|
|
358
383
|
new_subpath=File.join('',ASPERA_HOME_FOLDER_NAME,new_name,'')
|
|
@@ -361,7 +386,7 @@ END_OF_TEMPLATE
|
|
|
361
386
|
preset.values.select{|v|v.is_a?(String) and v.include?(old_subpath)}.each do |value|
|
|
362
387
|
old_val=value.clone
|
|
363
388
|
included_path=File.expand_path(old_val.gsub(/^@file:/,''))
|
|
364
|
-
files_to_copy.push(included_path) unless files_to_copy.include?(included_path)
|
|
389
|
+
files_to_copy.push(included_path) unless files_to_copy.include?(included_path) || !File.exist?(included_path)
|
|
365
390
|
value.gsub!(old_subpath,new_subpath)
|
|
366
391
|
Log.log.warn("Converted config value: #{old_val} -> #{value}")
|
|
367
392
|
end
|
|
@@ -369,11 +394,11 @@ END_OF_TEMPLATE
|
|
|
369
394
|
end
|
|
370
395
|
|
|
371
396
|
def convert_preset_plugin_name(old_name,new_name)
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
397
|
+
default_preset=@config_presets[CONF_PRESET_DEFAULT]
|
|
398
|
+
return unless default_preset.is_a?(Hash) && default_preset.has_key?(old_name)
|
|
399
|
+
default_preset[new_name]=default_preset[old_name]
|
|
400
|
+
default_preset.delete(old_name)
|
|
401
|
+
Log.log.warn("Converted plugin default: #{old_name} -> #{new_name}")
|
|
377
402
|
end
|
|
378
403
|
|
|
379
404
|
# read config file and validate format
|
|
@@ -390,11 +415,11 @@ END_OF_TEMPLATE
|
|
|
390
415
|
# find first existing file (or nil)
|
|
391
416
|
conf_file_to_load=search_files.select{|f| File.exist?(f)}.first
|
|
392
417
|
# require save if old version of file
|
|
393
|
-
save_required
|
|
418
|
+
save_required= !@option_config_file.eql?(conf_file_to_load)
|
|
394
419
|
# if no file found, create default config
|
|
395
420
|
if conf_file_to_load.nil?
|
|
396
421
|
Log.log.warn("No config file found. Creating empty configuration file: #{@option_config_file}")
|
|
397
|
-
@config_presets={CONF_PRESET_CONFIG=>{CONF_PRESET_VERSION=>@
|
|
422
|
+
@config_presets={CONF_PRESET_CONFIG=>{CONF_PRESET_VERSION=>@info[:version]}}
|
|
398
423
|
else
|
|
399
424
|
Log.log.debug("loading #{@option_config_file}")
|
|
400
425
|
@config_presets=YAML.load_file(conf_file_to_load)
|
|
@@ -431,14 +456,15 @@ END_OF_TEMPLATE
|
|
|
431
456
|
config_tested_version='1.0'
|
|
432
457
|
if Gem::Version.new(version) <= Gem::Version.new(config_tested_version)
|
|
433
458
|
convert_preset_plugin_name(AOC_COMMAND_V2,AOC_COMMAND_V3)
|
|
434
|
-
convert_preset_path(PROGRAM_NAME_V2,@
|
|
459
|
+
convert_preset_path(PROGRAM_NAME_V2,@info[:name],files_to_copy)
|
|
435
460
|
version=@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=config_tested_version
|
|
436
461
|
save_required=true
|
|
437
462
|
end
|
|
463
|
+
Log.log.debug("conf version: #{version}")
|
|
438
464
|
# Place new compatibility code here
|
|
439
465
|
if save_required
|
|
440
466
|
Log.log.warn('Saving automatic conversion.')
|
|
441
|
-
@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=@
|
|
467
|
+
@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=@info[:version]
|
|
442
468
|
save_presets_to_config_file
|
|
443
469
|
Log.log.warn('Copying referenced files')
|
|
444
470
|
files_to_copy.each do |file|
|
|
@@ -449,9 +475,9 @@ END_OF_TEMPLATE
|
|
|
449
475
|
rescue Psych::SyntaxError => e
|
|
450
476
|
Log.log.error('YAML error in config file')
|
|
451
477
|
raise e
|
|
452
|
-
rescue => e
|
|
478
|
+
rescue StandardError => e
|
|
453
479
|
Log.log.debug("-> #{e}")
|
|
454
|
-
new_name="#{@option_config_file}.pre#{@
|
|
480
|
+
new_name="#{@option_config_file}.pre#{@info[:version]}.manual_conversion_needed"
|
|
455
481
|
File.rename(@option_config_file,new_name)
|
|
456
482
|
Log.log.warn("Renamed config file to #{new_name}.")
|
|
457
483
|
Log.log.warn('Manual Conversion is required. Next time, a new empty file will be created.')
|
|
@@ -462,12 +488,11 @@ END_OF_TEMPLATE
|
|
|
462
488
|
# find plugins in defined paths
|
|
463
489
|
def add_plugins_from_lookup_folders
|
|
464
490
|
@plugin_lookup_folders.each do |folder|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
end
|
|
491
|
+
next unless File.directory?(folder)
|
|
492
|
+
#TODO: add gem root to load path ? and require short folder ?
|
|
493
|
+
#$LOAD_PATH.push(folder) if i[:add_path]
|
|
494
|
+
Dir.entries(folder).select{|file|file.end_with?(RUBY_FILE_EXT)}.each do |source|
|
|
495
|
+
add_plugin_info(File.join(folder,source))
|
|
471
496
|
end
|
|
472
497
|
end
|
|
473
498
|
end
|
|
@@ -489,36 +514,42 @@ END_OF_TEMPLATE
|
|
|
489
514
|
|
|
490
515
|
def identify_plugin_for_url(url)
|
|
491
516
|
plugins.each do |plugin_name_sym,plugin_info|
|
|
517
|
+
# no detection for internal plugin
|
|
492
518
|
next if plugin_name_sym.eql?(CONF_PLUGIN_SYM)
|
|
519
|
+
# load plugin class
|
|
493
520
|
require plugin_info[:require_stanza]
|
|
494
521
|
c=self.class.plugin_class(plugin_name_sym)
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
522
|
+
next unless c.respond_to?(:detect)
|
|
523
|
+
current_url=url
|
|
524
|
+
detection_info=nil
|
|
525
|
+
# first try : direct
|
|
526
|
+
begin
|
|
527
|
+
detection_info=c.detect(current_url)
|
|
528
|
+
rescue StandardError => e
|
|
529
|
+
Log.log.debug("Cannot detect #{plugin_name_sym} : #{e.message}")
|
|
530
|
+
end
|
|
531
|
+
# second try : is there a redirect ?
|
|
532
|
+
if detection_info.nil?
|
|
502
533
|
begin
|
|
503
|
-
#
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
res=c.send(:detect,current_url)
|
|
509
|
-
return res.merge(product: plugin_name_sym, url: current_url) unless res.nil?
|
|
534
|
+
# TODO: check if redirect ?
|
|
535
|
+
new_url=Rest.new(base_url: url).call(operation: 'GET',subpath: '',redirect_max: 1)[:http].uri.to_s
|
|
536
|
+
unless url.eql?(new_url)
|
|
537
|
+
detection_info=c.detect(new_url)
|
|
538
|
+
current_url=new_url
|
|
510
539
|
end
|
|
511
|
-
rescue
|
|
540
|
+
rescue StandardError => e
|
|
541
|
+
Log.log.debug("Cannot detect #{plugin_name_sym} : #{e.message}")
|
|
512
542
|
end
|
|
513
543
|
end
|
|
514
|
-
|
|
544
|
+
return detection_info.merge(product: plugin_name_sym, url: current_url) unless detection_info.nil?
|
|
545
|
+
end # loop
|
|
515
546
|
raise "No known application found at #{url}"
|
|
516
547
|
end
|
|
517
548
|
|
|
518
549
|
def execute_connect_action
|
|
519
|
-
command=
|
|
550
|
+
command=options.get_next_command([:list,:info,:version])
|
|
520
551
|
if [:info,:version].include?(command)
|
|
521
|
-
connect_id=
|
|
552
|
+
connect_id=options.get_next_argument('id or title')
|
|
522
553
|
one_res=connect_versions.select{|i|i['id'].eql?(connect_id) || i['title'].eql?(connect_id)}.first
|
|
523
554
|
raise CliNoSuchId.new(:connect,connect_id) if one_res.nil?
|
|
524
555
|
end
|
|
@@ -530,24 +561,24 @@ END_OF_TEMPLATE
|
|
|
530
561
|
return {type: :single_object, data: one_res}
|
|
531
562
|
when :version # shows files used
|
|
532
563
|
all_links=one_res['links']
|
|
533
|
-
command=
|
|
564
|
+
command=options.get_next_command([:list,:download,:open])
|
|
534
565
|
if [:download,:open].include?(command)
|
|
535
|
-
link_title=
|
|
566
|
+
link_title=options.get_next_argument('title or rel')
|
|
536
567
|
one_link=all_links.select {|i| i['title'].eql?(link_title) or i['rel'].eql?(link_title)}.first
|
|
537
|
-
raise
|
|
568
|
+
raise 'no such value' if one_link.nil?
|
|
538
569
|
end
|
|
539
570
|
case command
|
|
540
571
|
when :list # shows files used
|
|
541
572
|
return {type: :object_list, data: all_links}
|
|
542
|
-
when :download
|
|
543
|
-
folder_dest=
|
|
573
|
+
when :download
|
|
574
|
+
folder_dest=transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE)
|
|
544
575
|
#folder_dest=self.options.get_next_argument('destination folder')
|
|
545
576
|
api_connect_cdn=Rest.new({base_url: CONNECT_WEB_URL})
|
|
546
577
|
fileurl = one_link['href']
|
|
547
578
|
filename=fileurl.gsub(%r{.*/},'')
|
|
548
579
|
api_connect_cdn.call({operation: 'GET',subpath: fileurl,save_to_file: File.join(folder_dest,filename)})
|
|
549
580
|
return Main.result_status("Downloaded: #{filename}")
|
|
550
|
-
when :open
|
|
581
|
+
when :open
|
|
551
582
|
OpenApplication.instance.uri(one_link['href'])
|
|
552
583
|
return Main.result_status("Opened: #{one_link['href']}")
|
|
553
584
|
end
|
|
@@ -555,12 +586,12 @@ END_OF_TEMPLATE
|
|
|
555
586
|
end
|
|
556
587
|
|
|
557
588
|
def execute_action_ascp
|
|
558
|
-
command=
|
|
589
|
+
command=options.get_next_command([:connect,:use,:show,:products,:info,:install,:spec,:errors])
|
|
559
590
|
case command
|
|
560
591
|
when :connect
|
|
561
592
|
return execute_connect_action
|
|
562
593
|
when :use
|
|
563
|
-
ascp_path=
|
|
594
|
+
ascp_path=options.get_next_argument('path to ascp')
|
|
564
595
|
ascp_version=Fasp::Installation.instance.get_ascp_version(ascp_path)
|
|
565
596
|
self.format.display_status("ascp version: #{ascp_version}")
|
|
566
597
|
preset_name=set_global_default(:ascp_path,ascp_path)
|
|
@@ -568,46 +599,51 @@ END_OF_TEMPLATE
|
|
|
568
599
|
when :show # shows files used
|
|
569
600
|
return {type: :status, data: Fasp::Installation.instance.path(:ascp)}
|
|
570
601
|
when :info # shows files used
|
|
571
|
-
data=Fasp::Installation::FILES.
|
|
602
|
+
data=Fasp::Installation::FILES.each_with_object({}) do |v,m|
|
|
572
603
|
m[v.to_s]=Fasp::Installation.instance.path(v) rescue 'Not Found'
|
|
573
|
-
m
|
|
574
604
|
end
|
|
575
605
|
# read PATHs from ascp directly, and pvcl modules as well
|
|
576
|
-
Open3.popen3(Fasp::Installation.instance.path(:ascp),'-DDL-') do |
|
|
606
|
+
Open3.popen3(Fasp::Installation.instance.path(:ascp),'-DDL-') do |_stdin, _stdout, stderr, thread|
|
|
577
607
|
last_line=''
|
|
578
|
-
while line=stderr.gets
|
|
608
|
+
while (line=stderr.gets)
|
|
579
609
|
line.chomp!
|
|
580
610
|
last_line=line
|
|
581
611
|
case line
|
|
582
|
-
when %r{^DBG Path ([^ ]+) (dir|file) +: (.*)$}
|
|
583
|
-
when %r{^DBG Added module group:"([^"]+)" name:"([^"]+)", version:"([^"]+)" interface:"([^"]+)"$}
|
|
584
|
-
when %r{^DBG License result \(/license/(\S+)\): (.+)$}
|
|
585
|
-
when %r{^LOG (.+) version ([0-9.]+)$}
|
|
586
|
-
when %r{^LOG Initializing FASP version ([^,]+),}
|
|
612
|
+
when %r{^DBG Path ([^ ]+) (dir|file) +: (.*)$} then data[Regexp.last_match(1)]=Regexp.last_match(3)
|
|
613
|
+
when %r{^DBG Added module group:"([^"]+)" name:"([^"]+)", version:"([^"]+)" interface:"([^"]+)"$} then data[Regexp.last_match(2)]=Regexp.last_match(4)
|
|
614
|
+
when %r{^DBG License result \(/license/(\S+)\): (.+)$} then data[Regexp.last_match(1)]=Regexp.last_match(2)
|
|
615
|
+
when %r{^LOG (.+) version ([0-9.]+)$} then data['product_name']=Regexp.last_match(1);data['product_version']=Regexp.last_match(2)
|
|
616
|
+
when %r{^LOG Initializing FASP version ([^,]+),} then data['ascp_version']=Regexp.last_match(1)
|
|
587
617
|
end
|
|
588
618
|
end
|
|
589
|
-
if !thread.value.exitstatus.eql?(1)
|
|
619
|
+
if !thread.value.exitstatus.eql?(1) && !data.has_key?('root')
|
|
590
620
|
raise last_line
|
|
591
621
|
end
|
|
592
622
|
end
|
|
593
623
|
data['keypass']=Fasp::Installation.instance.bypass_pass
|
|
594
624
|
return {type: :single_object, data: data}
|
|
595
625
|
when :products
|
|
596
|
-
command=
|
|
626
|
+
command=options.get_next_command([:list,:use])
|
|
597
627
|
case command
|
|
598
628
|
when :list
|
|
599
629
|
return {type: :object_list, data: Fasp::Installation.instance.installed_products, fields: ['name','app_root']}
|
|
600
630
|
when :use
|
|
601
|
-
default_product=
|
|
631
|
+
default_product=options.get_next_argument('product name')
|
|
602
632
|
Fasp::Installation.instance.use_ascp_from_product(default_product)
|
|
603
633
|
preset_name=set_global_default(:ascp_path,Fasp::Installation.instance.path(:ascp))
|
|
604
634
|
return Main.result_status("Saved to default global preset #{preset_name}")
|
|
605
635
|
end
|
|
606
636
|
when :install
|
|
607
|
-
v=Fasp::Installation.instance.install_sdk(
|
|
637
|
+
v=Fasp::Installation.instance.install_sdk(options.get_option(:sdk_url,:mandatory))
|
|
608
638
|
return Main.result_status("Installed version #{v}")
|
|
609
639
|
when :spec
|
|
610
|
-
return {type: :object_list, data: Fasp::Parameters.man_table, fields: ['name','type',Fasp::Parameters::SUPPORTED_AGENTS_SHORT.map
|
|
640
|
+
return {type: :object_list, data: Fasp::Parameters.man_table, fields: ['name','type',Fasp::Parameters::SUPPORTED_AGENTS_SHORT.map(&:to_s),'description'].flatten}
|
|
641
|
+
when :errors
|
|
642
|
+
error_data=[]
|
|
643
|
+
Fasp::ERROR_INFO.each_pair do |code,prop|
|
|
644
|
+
error_data.push(code: code, mnemonic: prop[:c], retry: prop[:r], info: prop[:a])
|
|
645
|
+
end
|
|
646
|
+
return {type: :object_list, data: error_data}
|
|
611
647
|
end
|
|
612
648
|
raise "unexpected case: #{command}"
|
|
613
649
|
end
|
|
@@ -621,10 +657,10 @@ END_OF_TEMPLATE
|
|
|
621
657
|
PRESET_ALL_ACTIONS=[PRESET_GBL_ACTIONS,PRESET_INSTANCE_ACTIONS].flatten.freeze
|
|
622
658
|
|
|
623
659
|
def execute_file_action(action,config_name)
|
|
624
|
-
action=
|
|
625
|
-
config_name=instance_identifier() if config_name.nil?
|
|
660
|
+
action=options.get_next_command(PRESET_ALL_ACTIONS) if action.nil?
|
|
661
|
+
config_name=instance_identifier() if config_name.nil? && PRESET_INSTANCE_ACTIONS.include?(action)
|
|
626
662
|
# those operations require existing option
|
|
627
|
-
raise "no such preset: #{config_name}" if PRESET_EXST_ACTIONS.include?(action)
|
|
663
|
+
raise "no such preset: #{config_name}" if PRESET_EXST_ACTIONS.include?(action) && !@config_presets.has_key?(config_name)
|
|
628
664
|
selected_preset=@config_presets[config_name]
|
|
629
665
|
case action
|
|
630
666
|
when :list
|
|
@@ -639,21 +675,21 @@ END_OF_TEMPLATE
|
|
|
639
675
|
save_presets_to_config_file
|
|
640
676
|
return Main.result_status("Deleted: #{config_name}")
|
|
641
677
|
when :get
|
|
642
|
-
param_name=
|
|
678
|
+
param_name=options.get_next_argument('parameter name')
|
|
643
679
|
value=selected_preset[param_name]
|
|
644
680
|
raise "no such option in preset #{config_name} : #{param_name}" if value.nil?
|
|
645
681
|
case value
|
|
646
|
-
when Numeric,String
|
|
682
|
+
when Numeric,String then return {type: :text, data: ExtendedValue.instance.evaluate(value.to_s)}
|
|
647
683
|
end
|
|
648
684
|
return {type: :single_object, data: value}
|
|
649
685
|
when :unset
|
|
650
|
-
param_name=
|
|
686
|
+
param_name=options.get_next_argument('parameter name')
|
|
651
687
|
selected_preset.delete(param_name)
|
|
652
688
|
save_presets_to_config_file
|
|
653
689
|
return Main.result_status("Removed: #{config_name}: #{param_name}")
|
|
654
690
|
when :set
|
|
655
|
-
param_name=
|
|
656
|
-
param_value=
|
|
691
|
+
param_name=options.get_next_argument('parameter name')
|
|
692
|
+
param_value=options.get_next_argument('parameter value')
|
|
657
693
|
if !@config_presets.has_key?(config_name)
|
|
658
694
|
Log.log.debug("no such config name: #{config_name}, initializing")
|
|
659
695
|
selected_preset=@config_presets[config_name]={}
|
|
@@ -665,7 +701,7 @@ END_OF_TEMPLATE
|
|
|
665
701
|
save_presets_to_config_file
|
|
666
702
|
return Main.result_status("Updated: #{config_name}: #{param_name} <- #{param_value}")
|
|
667
703
|
when :initialize
|
|
668
|
-
config_value=
|
|
704
|
+
config_value=options.get_next_argument('extended value (Hash)')
|
|
669
705
|
if @config_presets.has_key?(config_name)
|
|
670
706
|
Log.log.warn("configuration already exists: #{config_name}, overwriting")
|
|
671
707
|
end
|
|
@@ -674,7 +710,7 @@ END_OF_TEMPLATE
|
|
|
674
710
|
return Main.result_status("Modified: #{@option_config_file}")
|
|
675
711
|
when :update
|
|
676
712
|
# get unprocessed options
|
|
677
|
-
theopts=
|
|
713
|
+
theopts=options.get_options_table
|
|
678
714
|
Log.log.debug("opts=#{theopts}")
|
|
679
715
|
@config_presets[config_name]||={}
|
|
680
716
|
@config_presets[config_name].merge!(theopts)
|
|
@@ -683,10 +719,10 @@ END_OF_TEMPLATE
|
|
|
683
719
|
save_presets_to_config_file
|
|
684
720
|
return Main.result_status("Updated: #{config_name}")
|
|
685
721
|
when :ask
|
|
686
|
-
|
|
722
|
+
options.ask_missing_mandatory=:yes
|
|
687
723
|
@config_presets[config_name]||={}
|
|
688
|
-
|
|
689
|
-
option_value=
|
|
724
|
+
options.get_next_argument('option names',:multiple).each do |optionname|
|
|
725
|
+
option_value=options.get_interactive(:option,optionname)
|
|
690
726
|
@config_presets[config_name][optionname]=option_value
|
|
691
727
|
end
|
|
692
728
|
save_presets_to_config_file
|
|
@@ -694,95 +730,98 @@ END_OF_TEMPLATE
|
|
|
694
730
|
end
|
|
695
731
|
end
|
|
696
732
|
|
|
697
|
-
ACTIONS=[PRESET_GBL_ACTIONS,:id,:preset,:open,:documentation,:genkey,:
|
|
733
|
+
ACTIONS=[PRESET_GBL_ACTIONS,:id,:preset,:open,:documentation,:genkey,:gem,:plugin,:flush_tokens,:echo,:wizard,:export_to_cli,:detect,:coffee,:ascp,:email_test,
|
|
734
|
+
:smtp_settings,:proxy_check,:folder,:file,:check_update,:initdemo,:vault].flatten.freeze
|
|
698
735
|
|
|
699
736
|
# "config" plugin
|
|
700
737
|
def execute_action
|
|
701
|
-
action=
|
|
738
|
+
action=options.get_next_command(ACTIONS)
|
|
702
739
|
case action
|
|
703
740
|
when *PRESET_GBL_ACTIONS # older syntax
|
|
704
741
|
return execute_file_action(action,nil)
|
|
705
742
|
when :id # older syntax
|
|
706
|
-
return execute_file_action(nil,
|
|
743
|
+
return execute_file_action(nil,options.get_next_argument('config name'))
|
|
707
744
|
when :preset # newer syntax
|
|
708
745
|
return execute_file_action(nil,nil)
|
|
709
746
|
when :open
|
|
710
|
-
OpenApplication.instance.uri(
|
|
747
|
+
OpenApplication.instance.uri(@option_config_file.to_s) #file://
|
|
711
748
|
return Main.result_nothing
|
|
712
749
|
when :documentation
|
|
713
750
|
section=options.get_next_argument('private key file path',:single,:optional)
|
|
714
751
|
section='#'+section unless section.nil?
|
|
715
|
-
OpenApplication.instance.uri("#{@
|
|
752
|
+
OpenApplication.instance.uri("#{@info[:help]}#{section}")
|
|
716
753
|
return Main.result_nothing
|
|
717
754
|
when :genkey # generate new rsa key
|
|
718
|
-
private_key_path=
|
|
755
|
+
private_key_path=options.get_next_argument('private key file path')
|
|
719
756
|
generate_rsa_private_key(private_key_path,DEFAULT_PRIVKEY_LENGTH)
|
|
720
757
|
return Main.result_status('Generated key: '+private_key_path)
|
|
721
758
|
when :echo # display the content of a value given on command line
|
|
722
|
-
result={type: :other_struct, data:
|
|
759
|
+
result={type: :other_struct, data: options.get_next_argument('value')}
|
|
723
760
|
# special for csv
|
|
724
|
-
result[:type]=:object_list if result[:data].is_a?(Array)
|
|
761
|
+
result[:type]=:object_list if result[:data].is_a?(Array) && result[:data].first.is_a?(Hash)
|
|
725
762
|
return result
|
|
726
763
|
when :flush_tokens
|
|
727
764
|
deleted_files=Oauth.flush_tokens
|
|
728
765
|
return {type: :value_list, data: deleted_files, name: 'file'}
|
|
729
766
|
when :plugin
|
|
730
|
-
case
|
|
767
|
+
case options.get_next_command([:list,:create])
|
|
731
768
|
when :list
|
|
732
|
-
return {type: :object_list, data: @plugins.keys.map { |i| { 'plugin' => i.to_s, 'path' => @plugins[i][:source] } }
|
|
769
|
+
return {type: :object_list, data: @plugins.keys.map { |i| { 'plugin' => i.to_s, 'path' => @plugins[i][:source] } }, fields: ['plugin','path']}
|
|
733
770
|
when :create
|
|
734
771
|
plugin_name=options.get_next_argument('name',:single,:mandatory).downcase
|
|
735
772
|
plugin_folder=options.get_next_argument('folder',:single,:optional) || File.join(@main_folder,ASPERA_PLUGINS_FOLDERNAME)
|
|
736
773
|
plugin_file=File.join(plugin_folder,"#{plugin_name}.rb")
|
|
737
|
-
content
|
|
738
|
-
require 'aspera/cli/plugin'
|
|
739
|
-
module Aspera
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
end # Aspera
|
|
749
|
-
|
|
774
|
+
content=<<~END_OF_PLUGIN_CODE
|
|
775
|
+
require 'aspera/cli/plugin'
|
|
776
|
+
module Aspera
|
|
777
|
+
module Cli
|
|
778
|
+
module Plugins
|
|
779
|
+
class #{plugin_name.capitalize} < Plugin
|
|
780
|
+
ACTIONS=[]
|
|
781
|
+
def execute_action; return Main.result_status('You called plugin #{plugin_name}'); end
|
|
782
|
+
end # #{plugin_name.capitalize}
|
|
783
|
+
end # Plugins
|
|
784
|
+
end # Cli
|
|
785
|
+
end # Aspera
|
|
786
|
+
END_OF_PLUGIN_CODE
|
|
750
787
|
File.write(plugin_file,content)
|
|
751
788
|
return Main.result_status("Created #{plugin_file}")
|
|
752
789
|
end
|
|
753
790
|
when :wizard
|
|
754
791
|
# interactive mode
|
|
755
|
-
|
|
792
|
+
options.ask_missing_mandatory=true
|
|
756
793
|
# register url option
|
|
757
794
|
BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
|
|
758
795
|
# get from option, or ask
|
|
759
|
-
instance_url=
|
|
796
|
+
instance_url=options.get_option(:url,:mandatory)
|
|
760
797
|
# allow user to tell the preset name
|
|
761
|
-
preset_name=
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
798
|
+
preset_name=options.get_option(:id,:optional)
|
|
799
|
+
# allow user to specify type of application
|
|
800
|
+
application=options.get_option(:value,:optional)
|
|
801
|
+
application=application.nil? ? identify_plugin_for_url(instance_url)[:product] : application.to_sym
|
|
802
|
+
plugin_name='<replace per app>'
|
|
803
|
+
test_args='<replace per app>'
|
|
804
|
+
case application
|
|
766
805
|
when :aoc
|
|
767
806
|
self.format.display_status('Detected: Aspera on Cloud'.bold)
|
|
768
807
|
plugin_name=AOC_COMMAND_CURRENT
|
|
769
|
-
organization
|
|
808
|
+
organization=AoC.parse_url(instance_url).first
|
|
770
809
|
# if not defined by user, generate name
|
|
771
|
-
preset_name=[
|
|
810
|
+
preset_name=[application,organization].join('_') if preset_name.nil?
|
|
772
811
|
self.format.display_status("Preparing preset: #{preset_name}")
|
|
773
812
|
# init defaults if necessary
|
|
774
813
|
@config_presets[CONF_PRESET_DEFAULT]||={}
|
|
775
|
-
option_override=
|
|
776
|
-
option_default=
|
|
814
|
+
option_override=options.get_option(:override,:mandatory)
|
|
815
|
+
option_default=options.get_option(:default,:mandatory)
|
|
777
816
|
Log.log.error("override=#{option_override} -> #{option_override.class}")
|
|
778
|
-
raise CliError,"A default configuration already exists for plugin '#{plugin_name}' (use --override=yes or --default=no)" if !option_override
|
|
779
|
-
raise CliError,"Preset already exists: #{preset_name} (use --override=yes or --id=<name>)" if !option_override
|
|
817
|
+
raise CliError,"A default configuration already exists for plugin '#{plugin_name}' (use --override=yes or --default=no)" if !option_override && option_default && @config_presets[CONF_PRESET_DEFAULT].has_key?(plugin_name)
|
|
818
|
+
raise CliError,"Preset already exists: #{preset_name} (use --override=yes or --id=<name>)" if !option_override && @config_presets.has_key?(preset_name)
|
|
780
819
|
# lets see if path to priv key is provided
|
|
781
|
-
private_key_path=
|
|
820
|
+
private_key_path=options.get_option(:pkeypath,:optional)
|
|
782
821
|
# give a chance to provide
|
|
783
822
|
if private_key_path.nil?
|
|
784
823
|
self.format.display_status('Please provide path to your private RSA key, or empty to generate one:')
|
|
785
|
-
private_key_path=
|
|
824
|
+
private_key_path=options.get_option(:pkeypath,:mandatory).to_s
|
|
786
825
|
end
|
|
787
826
|
# else generate path
|
|
788
827
|
if private_key_path.empty?
|
|
@@ -800,74 +839,73 @@ _EOF_
|
|
|
800
839
|
# declare command line options for AoC
|
|
801
840
|
require 'aspera/cli/plugins/aoc'
|
|
802
841
|
# make username mandatory for jwt, this triggers interactive input
|
|
803
|
-
|
|
842
|
+
options.get_option(:username,:mandatory)
|
|
804
843
|
# instanciate AoC plugin, so that command line options are known
|
|
805
|
-
|
|
806
|
-
aoc_api=files_plugin.get_api
|
|
844
|
+
aoc_api=self.class.plugin_class(plugin_name).new(@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path})).aoc_api
|
|
807
845
|
auto_set_pub_key=false
|
|
808
846
|
auto_set_jwt=false
|
|
809
847
|
use_browser_authentication=false
|
|
810
|
-
if
|
|
848
|
+
if options.get_option(:use_generic_client)
|
|
811
849
|
self.format.display_status('Using global client_id.')
|
|
812
850
|
self.format.display_status('Please Login to your Aspera on Cloud instance.'.red)
|
|
813
851
|
self.format.display_status('Navigate to your "Account Settings"'.red)
|
|
814
852
|
self.format.display_status('Check or update the value of "Public Key" to be:'.red.blink)
|
|
815
|
-
self.format.display_status(
|
|
816
|
-
if !
|
|
853
|
+
self.format.display_status(pub_key_pem.to_s)
|
|
854
|
+
if !options.get_option(:test_mode)
|
|
817
855
|
self.format.display_status('Once updated or validated, press enter.')
|
|
818
856
|
OpenApplication.instance.uri(instance_url)
|
|
819
|
-
|
|
857
|
+
$stdin.gets
|
|
820
858
|
end
|
|
821
859
|
else
|
|
822
860
|
self.format.display_status('Using organization specific client_id.')
|
|
823
|
-
if
|
|
861
|
+
if options.get_option(:client_id,:optional).nil? || options.get_option(:client_secret,:optional).nil?
|
|
824
862
|
self.format.display_status('Please login to your Aspera on Cloud instance.'.red)
|
|
825
863
|
self.format.display_status('Go to: Apps->Admin->Organization->Integrations')
|
|
826
864
|
self.format.display_status('Create or check if there is an existing integration named:')
|
|
827
|
-
self.format.display_status("- name: #{@
|
|
865
|
+
self.format.display_status("- name: #{@info[:name]}")
|
|
828
866
|
self.format.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
|
|
829
867
|
self.format.display_status('- origin: localhost')
|
|
830
868
|
self.format.display_status('Once created or identified,')
|
|
831
869
|
self.format.display_status('Please enter:'.red)
|
|
832
870
|
end
|
|
833
871
|
OpenApplication.instance.uri("#{instance_url}/#{AOC_PATH_API_CLIENTS}")
|
|
834
|
-
|
|
835
|
-
|
|
872
|
+
options.get_option(:client_id,:mandatory)
|
|
873
|
+
options.get_option(:client_secret,:mandatory)
|
|
836
874
|
use_browser_authentication=true
|
|
837
875
|
end
|
|
838
876
|
if use_browser_authentication
|
|
839
877
|
self.format.display_status('We will use web authentication to bootstrap.')
|
|
840
878
|
auto_set_pub_key=true
|
|
841
879
|
auto_set_jwt=true
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
880
|
+
aoc_api.oauth.params[:crtype]=:web
|
|
881
|
+
aoc_api.oauth.params[:web][:redirect_uri]=DEFAULT_REDIRECT
|
|
882
|
+
aoc_api.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
|
|
845
883
|
end
|
|
846
884
|
myself=aoc_api.read('self')[:data]
|
|
847
885
|
if auto_set_pub_key
|
|
848
|
-
raise CliError,'Public key is already set in profile (use --override=yes)'
|
|
886
|
+
raise CliError,'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? || option_override
|
|
849
887
|
self.format.display_status('Updating profile with new key')
|
|
850
888
|
aoc_api.update("users/#{myself['id']}",{'public_key'=>pub_key_pem})
|
|
851
889
|
end
|
|
852
890
|
if auto_set_jwt
|
|
853
891
|
self.format.display_status('Enabling JWT for client')
|
|
854
|
-
aoc_api.update("clients/#{
|
|
892
|
+
aoc_api.update("clients/#{options.get_option(:client_id)}",{'jwt_grant_enabled'=>true,'explicit_authorization_required'=>false})
|
|
855
893
|
end
|
|
856
894
|
self.format.display_status("Creating new config preset: #{preset_name}")
|
|
857
895
|
@config_presets[preset_name]={
|
|
858
|
-
:url.to_s =>
|
|
896
|
+
:url.to_s =>options.get_option(:url),
|
|
859
897
|
:username.to_s =>myself['email'],
|
|
860
898
|
:auth.to_s =>:jwt.to_s,
|
|
861
|
-
:private_key.to_s =>'@file:'+private_key_path
|
|
899
|
+
:private_key.to_s =>'@file:'+private_key_path
|
|
862
900
|
}
|
|
863
901
|
# set only if non nil
|
|
864
902
|
[:client_id,:client_secret].each do |s|
|
|
865
|
-
o=
|
|
903
|
+
o=options.get_option(s)
|
|
866
904
|
@config_presets[preset_name][s.to_s] = o unless o.nil?
|
|
867
905
|
end
|
|
868
906
|
test_args="#{plugin_name} user profile show"
|
|
869
907
|
else
|
|
870
|
-
raise CliBadArgument,"Supports only: aoc. Detected: #{
|
|
908
|
+
raise CliBadArgument,"Supports only: aoc. Detected: #{application}"
|
|
871
909
|
end # product
|
|
872
910
|
if option_default
|
|
873
911
|
self.format.display_status("Setting config preset as default for #{plugin_name}")
|
|
@@ -877,29 +915,29 @@ _EOF_
|
|
|
877
915
|
end
|
|
878
916
|
self.format.display_status('Saving config file.')
|
|
879
917
|
save_presets_to_config_file
|
|
880
|
-
return Main.result_status("Done.\nYou can test with:\n#{@
|
|
918
|
+
return Main.result_status("Done.\nYou can test with:\n#{@info[:name]} #{test_args}")
|
|
881
919
|
when :export_to_cli
|
|
882
920
|
self.format.display_status('Exporting: Aspera on Cloud')
|
|
883
921
|
require 'aspera/cli/plugins/aoc'
|
|
884
922
|
# need url / username
|
|
885
923
|
add_plugin_default_preset(AOC_COMMAND_V3.to_sym)
|
|
886
924
|
# instanciate AoC plugin
|
|
887
|
-
|
|
888
|
-
url=
|
|
925
|
+
self.class.plugin_class(AOC_COMMAND_CURRENT).new(@agents) # TODO: is this line needed ? get options ?
|
|
926
|
+
url=options.get_option(:url,:mandatory)
|
|
889
927
|
cli_conf_file=Fasp::Installation.instance.cli_conf_file
|
|
890
928
|
data=JSON.parse(File.read(cli_conf_file))
|
|
891
929
|
organization,instance_domain=AoC.parse_url(url)
|
|
892
930
|
key_basename='org_'+organization+'.pem'
|
|
893
931
|
key_file=File.join(File.dirname(File.dirname(cli_conf_file)),'etc',key_basename)
|
|
894
|
-
File.write(key_file,
|
|
932
|
+
File.write(key_file,options.get_option(:private_key,:mandatory))
|
|
895
933
|
new_conf={
|
|
896
934
|
'organization' => organization,
|
|
897
935
|
'hostname' => [organization,instance_domain].join('.'),
|
|
898
936
|
'privateKeyFilename' => key_basename,
|
|
899
|
-
'username' =>
|
|
937
|
+
'username' => options.get_option(:username,:mandatory)
|
|
900
938
|
}
|
|
901
|
-
new_conf['clientId']=
|
|
902
|
-
new_conf['clientSecret']=
|
|
939
|
+
new_conf['clientId']=options.get_option(:client_id,:optional)
|
|
940
|
+
new_conf['clientSecret']=options.get_option(:client_secret,:optional)
|
|
903
941
|
if new_conf['clientId'].nil?
|
|
904
942
|
new_conf['clientId'],new_conf['clientSecret']=AoC.get_client_info()
|
|
905
943
|
end
|
|
@@ -916,14 +954,18 @@ _EOF_
|
|
|
916
954
|
when :detect
|
|
917
955
|
# need url / username
|
|
918
956
|
BasicAuthPlugin.new(@agents)
|
|
919
|
-
return
|
|
957
|
+
return {type: :single_object, data: identify_plugin_for_url(options.get_option(:url,:mandatory))}
|
|
920
958
|
when :coffee
|
|
921
959
|
OpenApplication.instance.uri('https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg')
|
|
922
960
|
return Main.result_nothing
|
|
923
961
|
when :ascp
|
|
924
962
|
execute_action_ascp
|
|
925
|
-
when :
|
|
926
|
-
|
|
963
|
+
when :gem
|
|
964
|
+
case options.get_next_command([:path,:version,:name])
|
|
965
|
+
when :path then return Main.result_status(self.class.gem_src_root)
|
|
966
|
+
when :version then return Main.result_status(Aspera::Cli::VERSION)
|
|
967
|
+
when :name then return Main.result_status(@info[:gem])
|
|
968
|
+
end
|
|
927
969
|
when :folder
|
|
928
970
|
return Main.result_status(@main_folder)
|
|
929
971
|
when :file
|
|
@@ -934,9 +976,10 @@ _EOF_
|
|
|
934
976
|
when :smtp_settings
|
|
935
977
|
return {type: :single_object, data: email_settings}
|
|
936
978
|
when :proxy_check
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
979
|
+
# ensure fpac was provided
|
|
980
|
+
options.get_option(:fpac,:mandatory)
|
|
981
|
+
server_url=options.get_next_argument('server url')
|
|
982
|
+
return Main.result_status(@pac_exec.find_proxy_for_url(server_url))
|
|
940
983
|
when :check_update
|
|
941
984
|
return {type: :single_object, data: check_gem_version}
|
|
942
985
|
when :initdemo
|
|
@@ -944,7 +987,8 @@ _EOF_
|
|
|
944
987
|
Log.log.warn("Demo server preset already present: #{DEMO_SERVER_PRESET}")
|
|
945
988
|
else
|
|
946
989
|
Log.log.info("Creating Demo server preset: #{DEMO_SERVER_PRESET}")
|
|
947
|
-
@config_presets[DEMO_SERVER_PRESET]=
|
|
990
|
+
@config_presets[DEMO_SERVER_PRESET]=
|
|
991
|
+
{'url'=>'ssh://'+DEMO+'.asperasoft.com:33001','username'=>AOC_COMMAND_V2,'ssAP'.downcase.reverse+'drow'.reverse=>DEMO+AOC_COMMAND_V2}
|
|
948
992
|
end
|
|
949
993
|
@config_presets[CONF_PRESET_DEFAULT]||={}
|
|
950
994
|
if @config_presets[CONF_PRESET_DEFAULT].has_key?(SERVER_COMMAND)
|
|
@@ -957,13 +1001,13 @@ _EOF_
|
|
|
957
1001
|
save_presets_to_config_file
|
|
958
1002
|
return Main.result_status('Done')
|
|
959
1003
|
when :vault
|
|
960
|
-
command=
|
|
1004
|
+
command=options.get_next_command([:init,:list,:get,:set,:delete])
|
|
961
1005
|
case command
|
|
962
1006
|
when :init
|
|
963
|
-
type=
|
|
1007
|
+
type=options.get_option(:value,:optional)
|
|
964
1008
|
case type
|
|
965
1009
|
when 'config',NilClass
|
|
966
|
-
raise
|
|
1010
|
+
raise 'default secrets already exists' if @config_presets.has_key?(CONF_PRESET_SECRETS)
|
|
967
1011
|
@config_presets[CONF_PRESET_SECRETS]={}
|
|
968
1012
|
set_global_default(:secrets,"@preset:#{CONF_PRESET_SECRETS}")
|
|
969
1013
|
else raise 'no such vault type'
|
|
@@ -974,26 +1018,26 @@ _EOF_
|
|
|
974
1018
|
when :set
|
|
975
1019
|
# register url option
|
|
976
1020
|
BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
|
|
977
|
-
username=
|
|
978
|
-
url=
|
|
979
|
-
description=
|
|
980
|
-
secret=
|
|
1021
|
+
username=options.get_option(:username,:mandatory)
|
|
1022
|
+
url=options.get_option(:url,:mandatory)
|
|
1023
|
+
description=options.get_option(:value,:optional)
|
|
1024
|
+
secret=options.get_next_argument('secret')
|
|
981
1025
|
vault.set(username: username, url: url, description: description, secret: secret)
|
|
982
1026
|
save_presets_to_config_file if vault.is_a?(Keychain::EncryptedHash)
|
|
983
1027
|
return Main.result_status('Done')
|
|
984
1028
|
when :get
|
|
985
1029
|
# register url option
|
|
986
1030
|
BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
|
|
987
|
-
username=
|
|
988
|
-
url=
|
|
1031
|
+
username=options.get_option(:username,:mandatory)
|
|
1032
|
+
url=options.get_option(:url,:optional)
|
|
989
1033
|
result=vault.get(username: username, url: url)
|
|
990
1034
|
return {type: :single_object, data: result}
|
|
991
1035
|
when :delete
|
|
992
1036
|
# register url option
|
|
993
1037
|
BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
|
|
994
|
-
username=
|
|
995
|
-
url=
|
|
996
|
-
|
|
1038
|
+
username=options.get_option(:username,:mandatory)
|
|
1039
|
+
url=options.get_option(:url,:optional)
|
|
1040
|
+
vault.delete(username: username, url: url)
|
|
997
1041
|
return Main.result_status('Done')
|
|
998
1042
|
end
|
|
999
1043
|
else raise 'INTERNAL ERROR: wrong case'
|
|
@@ -1002,9 +1046,9 @@ _EOF_
|
|
|
1002
1046
|
|
|
1003
1047
|
# @return email server setting with defaults if not defined
|
|
1004
1048
|
def email_settings
|
|
1005
|
-
smtp=
|
|
1049
|
+
smtp=options.get_option(:smtp,:mandatory)
|
|
1006
1050
|
# change string keys into symbol keys
|
|
1007
|
-
smtp=smtp.keys.
|
|
1051
|
+
smtp=smtp.keys.each_with_object({}){|v,m|m[v.to_sym]=smtp[v];}
|
|
1008
1052
|
# defaults
|
|
1009
1053
|
smtp[:tls]||=true
|
|
1010
1054
|
smtp[:port]||=smtp[:tls]?587:25
|
|
@@ -1034,7 +1078,7 @@ _EOF_
|
|
|
1034
1078
|
raise "Missing email parameter: #{n}" unless vars.has_key?(n)
|
|
1035
1079
|
end
|
|
1036
1080
|
start_options=[mail_conf[:domain]]
|
|
1037
|
-
start_options.push(mail_conf[:username],mail_conf[:password],:login) if mail_conf.has_key?(:username)
|
|
1081
|
+
start_options.push(mail_conf[:username],mail_conf[:password],:login) if mail_conf.has_key?(:username) && mail_conf.has_key?(:password)
|
|
1038
1082
|
# create a binding with only variables defined in vars
|
|
1039
1083
|
template_binding=empty_binding
|
|
1040
1084
|
# add variables to binding
|
|
@@ -1047,8 +1091,8 @@ _EOF_
|
|
|
1047
1091
|
Log.dump(:msg_with_headers,msg_with_headers)
|
|
1048
1092
|
smtp = Net::SMTP.new(mail_conf[:server], mail_conf[:port])
|
|
1049
1093
|
smtp.enable_starttls if mail_conf[:tls]
|
|
1050
|
-
smtp.start(*start_options) do |
|
|
1051
|
-
|
|
1094
|
+
smtp.start(*start_options) do |smtp_session|
|
|
1095
|
+
smtp_session.send_message(msg_with_headers, vars[:from_email], vars[:to])
|
|
1052
1096
|
end
|
|
1053
1097
|
end
|
|
1054
1098
|
|
|
@@ -1062,16 +1106,16 @@ _EOF_
|
|
|
1062
1106
|
# returns [String] name if config_presets has default
|
|
1063
1107
|
# returns nil if there is no config or bypass default params
|
|
1064
1108
|
def get_plugin_default_config_name(plugin_sym)
|
|
1065
|
-
raise
|
|
1109
|
+
raise 'internal error: config_presets shall be defined' if @config_presets.nil?
|
|
1066
1110
|
if !@use_plugin_defaults
|
|
1067
1111
|
Log.log.debug('skip default config')
|
|
1068
1112
|
return nil
|
|
1069
1113
|
end
|
|
1070
|
-
if @config_presets.has_key?(CONF_PRESET_DEFAULT)
|
|
1114
|
+
if @config_presets.has_key?(CONF_PRESET_DEFAULT) &&
|
|
1071
1115
|
@config_presets[CONF_PRESET_DEFAULT].has_key?(plugin_sym.to_s)
|
|
1072
1116
|
default_config_name=@config_presets[CONF_PRESET_DEFAULT][plugin_sym.to_s]
|
|
1073
1117
|
if !@config_presets.has_key?(default_config_name)
|
|
1074
|
-
Log.log.error("Default config name [#{default_config_name}] specified for plugin [#{plugin_sym
|
|
1118
|
+
Log.log.error("Default config name [#{default_config_name}] specified for plugin [#{plugin_sym}], but it does not exist in config file.\nPlease fix the issue: either create preset with one parameter (#{@info[:name]} config id #{default_config_name} init @json:'{}') or remove default (#{@info[:name]} config id default remove #{plugin_sym}).")
|
|
1075
1119
|
end
|
|
1076
1120
|
raise CliError,"Config name [#{default_config_name}] must be a hash, check config file." if !@config_presets[default_config_name].is_a?(Hash)
|
|
1077
1121
|
return default_config_name
|
|
@@ -1081,7 +1125,7 @@ _EOF_
|
|
|
1081
1125
|
|
|
1082
1126
|
def vault
|
|
1083
1127
|
if @vault.nil?
|
|
1084
|
-
vault_info=
|
|
1128
|
+
vault_info=options.get_option(:secrets,:optional)
|
|
1085
1129
|
case vault_info
|
|
1086
1130
|
when Hash
|
|
1087
1131
|
@vault=Keychain::EncryptedHash.new(vault_info)
|
|
@@ -1091,8 +1135,8 @@ _EOF_
|
|
|
1091
1135
|
when Environment::OS_X
|
|
1092
1136
|
@vault=Keychain::MacosSecurity.new(name)
|
|
1093
1137
|
when Environment::OS_WINDOWS,Environment::OS_LINUX,Environment::OS_AIX
|
|
1094
|
-
raise
|
|
1095
|
-
else raise
|
|
1138
|
+
raise 'not implemented'
|
|
1139
|
+
else raise 'Error'
|
|
1096
1140
|
end
|
|
1097
1141
|
when NilClass
|
|
1098
1142
|
# keep nil
|
|
@@ -1100,18 +1144,18 @@ _EOF_
|
|
|
1100
1144
|
raise CliBadArgument,'secrets shall be Hash'
|
|
1101
1145
|
end
|
|
1102
1146
|
end
|
|
1103
|
-
raise
|
|
1147
|
+
raise 'No vault defined' if @vault.nil?
|
|
1104
1148
|
@vault
|
|
1105
1149
|
end
|
|
1106
1150
|
|
|
1107
1151
|
def get_secret(options)
|
|
1108
|
-
raise
|
|
1109
|
-
raise
|
|
1152
|
+
raise 'options shall be Hash' unless options.is_a?(Hash)
|
|
1153
|
+
raise 'options shall have username' unless options.has_key?(:username)
|
|
1110
1154
|
secret=self.options.get_option(:secret,:optional)
|
|
1111
1155
|
if secret.nil?
|
|
1112
1156
|
secret=vault.get(options) rescue nil
|
|
1113
1157
|
# mandatory by default
|
|
1114
|
-
raise "please provide secret for #{options[:username]}" if secret.nil?
|
|
1158
|
+
raise "please provide secret for #{options[:username]}" if secret.nil? && (options[:mandatory].nil? || options[:mandatory])
|
|
1115
1159
|
end
|
|
1116
1160
|
return secret
|
|
1117
1161
|
end
|