cosmos 5.0.2 → 5.0.3
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/data/config/microservice.yaml +47 -35
- data/data/config/plugins.yaml +3 -150
- data/data/config/target.yaml +70 -0
- data/data/config/tool.yaml +37 -31
- data/lib/cosmos/api/cmd_api.rb +11 -0
- data/lib/cosmos/api/tlm_api.rb +56 -32
- data/lib/cosmos/config/config_parser.rb +17 -20
- data/lib/cosmos/conversions/generic_conversion.rb +2 -2
- data/lib/cosmos/conversions/polynomial_conversion.rb +5 -8
- data/lib/cosmos/conversions/segmented_polynomial_conversion.rb +26 -9
- data/lib/cosmos/io/json_drb.rb +5 -1
- data/lib/cosmos/microservices/cleanup_microservice.rb +28 -29
- data/lib/cosmos/microservices/microservice.rb +1 -1
- data/lib/cosmos/models/gem_model.rb +1 -1
- data/lib/cosmos/models/scope_model.rb +0 -20
- data/lib/cosmos/models/target_model.rb +110 -3
- data/lib/cosmos/packets/packet.rb +23 -0
- data/lib/cosmos/packets/packet_config.rb +2 -2
- data/lib/cosmos/packets/packet_item.rb +57 -0
- data/lib/cosmos/packets/packet_item_limits.rb +14 -2
- data/lib/cosmos/packets/parsers/packet_item_parser.rb +1 -1
- data/lib/cosmos/packets/parsers/packet_parser.rb +1 -1
- data/lib/cosmos/packets/parsers/xtce_parser.rb +1 -1
- data/lib/cosmos/packets/structure_item.rb +10 -1
- data/lib/cosmos/script/api_shared.rb +30 -25
- data/lib/cosmos/script/commands.rb +5 -7
- data/lib/cosmos/script/script.rb +19 -39
- data/lib/cosmos/script/storage.rb +92 -105
- data/lib/cosmos/tools/table_manager/table_item.rb +1 -1
- data/lib/cosmos/topics/command_decom_topic.rb +4 -0
- data/lib/cosmos/topics/telemetry_decom_topic.rb +4 -0
- data/lib/cosmos/topics/topic.rb +10 -0
- data/lib/cosmos/utilities/logger.rb +1 -0
- data/lib/cosmos/utilities/s3.rb +61 -0
- data/lib/cosmos/utilities/store_autoload.rb +0 -10
- data/lib/cosmos/version.rb +5 -4
- data/templates/plugin-template/plugin.gemspec +0 -2
- metadata +3 -3
@@ -486,6 +486,63 @@ module Cosmos
|
|
486
486
|
config
|
487
487
|
end
|
488
488
|
|
489
|
+
def self.from_json(hash)
|
490
|
+
# Convert strings to symbols
|
491
|
+
endianness = hash['endianness'] ? hash['endianness'].intern : nil
|
492
|
+
data_type = hash['data_type'] ? hash['data_type'].intern : nil
|
493
|
+
overflow = hash['overflow'] ? hash['overflow'].intern : nil
|
494
|
+
item = PacketItem.new(hash['name'], hash['bit_offset'], hash['bit_size'],
|
495
|
+
data_type, endianness, hash['array_size'], overflow)
|
496
|
+
item.description = hash['description']
|
497
|
+
item.id_value = hash['id_value']
|
498
|
+
item.default = hash['default']
|
499
|
+
item.range = (hash['minimum']..hash['maximum']) if hash['minimum'] && hash['maximum']
|
500
|
+
item.required = hash['required']
|
501
|
+
item.format_string = hash['format_string']
|
502
|
+
item.units = hash['units']
|
503
|
+
item.units_full = hash['units_full']
|
504
|
+
if hash['states']
|
505
|
+
item.states = {}
|
506
|
+
item.hazardous = {}
|
507
|
+
item.state_colors = {}
|
508
|
+
hash['states'].each do |state_name, state|
|
509
|
+
item.states[state_name] = state['value']
|
510
|
+
item.hazardous[state_name] = state['hazardous']
|
511
|
+
item.state_colors[state_name] = state['color'].to_sym if state['color']
|
512
|
+
end
|
513
|
+
end
|
514
|
+
# Recreate COSMOS built-in conversions
|
515
|
+
if hash['read_conversion']
|
516
|
+
begin
|
517
|
+
item.read_conversion = Cosmos::const_get(hash['read_conversion']['class']).new(*hash['read_conversion']['params'])
|
518
|
+
rescue => error
|
519
|
+
Logger.instance.error "#{item.name} read_conversion of #{hash['read_conversion']} could not be instantiated due to #{error}"
|
520
|
+
end
|
521
|
+
end
|
522
|
+
if hash['write_conversion']
|
523
|
+
begin
|
524
|
+
item.write_conversion = Cosmos::const_get(hash['write_conversion']['class']).new(*hash['write_conversion']['params'])
|
525
|
+
rescue => error
|
526
|
+
Logger.instance.error "#{item.name} write_conversion of #{hash['write_conversion']} could not be instantiated due to #{error}"
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
if hash['limits']
|
531
|
+
item.limits = PacketItemLimits.new
|
532
|
+
# Delete these keys so the only ones left are limits sets
|
533
|
+
item.limits.persistence_setting = hash['limits'].delete('persistence_setting')
|
534
|
+
item.limits.enabled = true if hash['limits'].delete('enabled')
|
535
|
+
values = {}
|
536
|
+
hash['limits'].each do |set, items|
|
537
|
+
values[set.to_sym] = [items['red_low'], items['yellow_low'], items['yellow_high'], items['red_high']]
|
538
|
+
values[set.to_sym].concat([items['green_low'], items['green_high']]) if items['green_low'] && items['green_high']
|
539
|
+
end
|
540
|
+
item.limits.values = values
|
541
|
+
end
|
542
|
+
item.meta = hash['meta']
|
543
|
+
item
|
544
|
+
end
|
545
|
+
|
489
546
|
protected
|
490
547
|
|
491
548
|
def parameter_config
|
@@ -132,7 +132,7 @@ module Cosmos
|
|
132
132
|
end
|
133
133
|
alias dup clone
|
134
134
|
|
135
|
-
def
|
135
|
+
def as_json
|
136
136
|
hash = {}
|
137
137
|
hash['values'] = self.values
|
138
138
|
hash['enabled'] = self.enabled
|
@@ -146,5 +146,17 @@ module Cosmos
|
|
146
146
|
hash['persistence_count'] = self.persistence_count
|
147
147
|
hash
|
148
148
|
end
|
149
|
+
|
150
|
+
def self.from_json(hash)
|
151
|
+
limits = PacketItemLimits.new
|
152
|
+
limits.values = hash['values'].transform_keys(&:to_sym) if hash['values']
|
153
|
+
limits.enabled = hash['enabled']
|
154
|
+
limits.state = hash['state'] ? hash['state'].to_sym : nil
|
155
|
+
# Can't recreate a LimitsResponse class
|
156
|
+
# limits.response = hash['response']
|
157
|
+
limits.persistence_setting = hash['persistence_setting'] if hash['persistence_setting']
|
158
|
+
limits.persistence_count = hash['persistence_count'] if hash['persistence_count']
|
159
|
+
limits
|
160
|
+
end
|
149
161
|
end
|
150
|
-
end
|
162
|
+
end
|
@@ -56,7 +56,7 @@ module Cosmos
|
|
56
56
|
max_options = @usage.count("<")
|
57
57
|
# The last two options (description and endianness) are optional
|
58
58
|
@parser.verify_num_parameters(max_options - 2, max_options, @usage)
|
59
|
-
@parser.
|
59
|
+
@parser.verify_parameter_naming(1) # Item name is the 1st parameter
|
60
60
|
end
|
61
61
|
|
62
62
|
def create_packet_item(packet, cmd_or_tlm)
|
@@ -72,7 +72,7 @@ module Cosmos
|
|
72
72
|
def verify_parameters
|
73
73
|
@usage = "#{@parser.keyword} <TARGET NAME> <PACKET NAME> <ENDIANNESS: BIG_ENDIAN/LITTLE_ENDIAN> <DESCRIPTION (Optional)>"
|
74
74
|
@parser.verify_num_parameters(3, 4, @usage)
|
75
|
-
@parser.
|
75
|
+
@parser.verify_parameter_naming(2) # Packet name is the 2nd parameter
|
76
76
|
end
|
77
77
|
|
78
78
|
def create_command(target_name, commands, warnings)
|
@@ -293,7 +293,7 @@ module Cosmos
|
|
293
293
|
xtce_recurse_element(element) do |block_element|
|
294
294
|
if block_element.name == 'Term'
|
295
295
|
exponent = Float(block_element['exponent']).to_i
|
296
|
-
@current_type.conversion ||= PolynomialConversion.new(
|
296
|
+
@current_type.conversion ||= PolynomialConversion.new()
|
297
297
|
@current_type.conversion.coeffs[exponent] = Float(block_element['coefficient'])
|
298
298
|
@current_type.conversion.coeffs.each_with_index do |value, index|
|
299
299
|
@current_type.conversion.coeffs[index] = 0.0 if value.nil?
|
@@ -292,7 +292,16 @@ module Cosmos
|
|
292
292
|
end
|
293
293
|
alias dup clone
|
294
294
|
|
295
|
-
def
|
295
|
+
def self.from_json(hash)
|
296
|
+
# Convert strings to symbols
|
297
|
+
endianness = hash['endianness'] ? hash['endianness'].intern : nil
|
298
|
+
data_type = hash['data_type'] ? hash['data_type'].intern : nil
|
299
|
+
overflow = hash['overflow'] ? hash['overflow'].intern : nil
|
300
|
+
StructureItem.new(hash['name'], hash['bit_offset'], hash['bit_size'], data_type,
|
301
|
+
endianness, hash['array_size'], overflow)
|
302
|
+
end
|
303
|
+
|
304
|
+
def as_json
|
296
305
|
hash = {}
|
297
306
|
hash['name'] = self.name
|
298
307
|
hash['bit_offset'] = self.bit_offset
|
@@ -300,10 +300,10 @@ module Cosmos
|
|
300
300
|
#
|
301
301
|
# @param args [String|Array<String>] See the description for calling style
|
302
302
|
# @param type [Symbol] Telemetry type, :RAW, :CONVERTED (default), :FORMATTED, or :WITH_UNITS
|
303
|
-
def wait_check(*args, type: :CONVERTED, scope: $cosmos_scope, token: $cosmos_token)
|
303
|
+
def wait_check(*args, type: :CONVERTED, scope: $cosmos_scope, token: $cosmos_token, &block)
|
304
304
|
target_name, packet_name, item_name, comparison_to_eval, timeout, polling_rate = _wait_check_process_args(args, scope: scope, token: token)
|
305
305
|
start_time = Time.now.sys
|
306
|
-
success, value = cosmos_script_wait_implementation(target_name, packet_name, item_name, type, comparison_to_eval, timeout, polling_rate, scope: scope, token: token)
|
306
|
+
success, value = cosmos_script_wait_implementation(target_name, packet_name, item_name, type, comparison_to_eval, timeout, polling_rate, scope: scope, token: token, &block)
|
307
307
|
time = Time.now.sys - start_time
|
308
308
|
check_str = "CHECK: #{_upcase(target_name, packet_name, item_name)} #{comparison_to_eval}"
|
309
309
|
with_value_str = "with value == #{value} after waiting #{time} seconds"
|
@@ -321,8 +321,8 @@ module Cosmos
|
|
321
321
|
end
|
322
322
|
|
323
323
|
# @deprecated use wait_check with type: :RAW
|
324
|
-
def wait_check_raw(*args, scope: $cosmos_scope, token: $cosmos_token)
|
325
|
-
wait_check(*args, type: :RAW, scope: scope, token: token)
|
324
|
+
def wait_check_raw(*args, scope: $cosmos_scope, token: $cosmos_token, &block)
|
325
|
+
wait_check(*args, type: :RAW, scope: scope, token: token, &block)
|
326
326
|
end
|
327
327
|
|
328
328
|
# Wait for the value of a telmetry item to be within a tolerance of a value
|
@@ -334,7 +334,7 @@ module Cosmos
|
|
334
334
|
#
|
335
335
|
# @param args [String|Array<String>] See the description for calling style
|
336
336
|
# @param type [Symbol] Telemetry type, :RAW or :CONVERTED (default)
|
337
|
-
def wait_check_tolerance(*args, type: :CONVERTED, scope: $cosmos_scope, token: $cosmos_token)
|
337
|
+
def wait_check_tolerance(*args, type: :CONVERTED, scope: $cosmos_scope, token: $cosmos_token, &block)
|
338
338
|
raise "Invalid type '#{type}' for wait_check_tolerance" unless %i(RAW CONVERTED).include?(type)
|
339
339
|
|
340
340
|
target_name, packet_name, item_name, expected_value, tolerance, timeout, polling_rate = _wait_tolerance_process_args(args, scope: scope, token: token)
|
@@ -343,7 +343,7 @@ module Cosmos
|
|
343
343
|
if value.is_a?(Array)
|
344
344
|
expected_value, tolerance = array_tolerance_process_args(value.size, expected_value, tolerance, 'wait_check_tolerance', scope: scope, token: token)
|
345
345
|
|
346
|
-
success, value = cosmos_script_wait_implementation_array_tolerance(value.size, target_name, packet_name, item_name, type, expected_value, tolerance, timeout, polling_rate, scope: scope, token: token)
|
346
|
+
success, value = cosmos_script_wait_implementation_array_tolerance(value.size, target_name, packet_name, item_name, type, expected_value, tolerance, timeout, polling_rate, scope: scope, token: token, &block)
|
347
347
|
time = Time.now.sys - start_time
|
348
348
|
|
349
349
|
message = ""
|
@@ -388,8 +388,8 @@ module Cosmos
|
|
388
388
|
end
|
389
389
|
|
390
390
|
# @deprecated Use wait_check_tolerance with type: :RAW
|
391
|
-
def wait_check_tolerance_raw(*args, scope: $cosmos_scope, token: $cosmos_token)
|
392
|
-
wait_check_tolerance(*args, type: :RAW, scope: scope, token: token)
|
391
|
+
def wait_check_tolerance_raw(*args, scope: $cosmos_scope, token: $cosmos_token, &block)
|
392
|
+
wait_check_tolerance(*args, type: :RAW, scope: scope, token: token, &block)
|
393
393
|
end
|
394
394
|
|
395
395
|
# Wait on an expression to be true. On a timeout, the script will pause.
|
@@ -397,12 +397,12 @@ module Cosmos
|
|
397
397
|
timeout,
|
398
398
|
polling_rate = DEFAULT_TLM_POLLING_RATE,
|
399
399
|
context = nil,
|
400
|
-
scope: $cosmos_scope, token: $cosmos_token)
|
400
|
+
scope: $cosmos_scope, token: $cosmos_token, &block)
|
401
401
|
start_time = Time.now.sys
|
402
402
|
success = cosmos_script_wait_implementation_expression(exp_to_eval,
|
403
403
|
timeout,
|
404
404
|
polling_rate,
|
405
|
-
context, scope: scope, token: token)
|
405
|
+
context, scope: scope, token: token, &block)
|
406
406
|
time = Time.now.sys - start_time
|
407
407
|
if success
|
408
408
|
Logger.info "CHECK: #{exp_to_eval} is TRUE after waiting #{time} seconds"
|
@@ -691,15 +691,20 @@ module Cosmos
|
|
691
691
|
return [target_name, packet_name, item_name, comparison_to_eval, timeout, polling_rate]
|
692
692
|
end
|
693
693
|
|
694
|
-
def _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, scope: $cosmos_scope, token: $cosmos_token)
|
694
|
+
def _cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, exp_to_eval, scope: $cosmos_scope, token: $cosmos_token, &block)
|
695
695
|
end_time = Time.now.sys + timeout
|
696
|
-
exp_to_eval = yield
|
697
696
|
|
698
697
|
while true
|
699
698
|
work_start = Time.now.sys
|
700
699
|
value = tlm(target_name, packet_name, item_name, type: value_type, scope: scope, token: token)
|
701
|
-
if
|
702
|
-
|
700
|
+
if not block.nil?
|
701
|
+
if block.call(value)
|
702
|
+
return true, value
|
703
|
+
end
|
704
|
+
else
|
705
|
+
if eval(exp_to_eval)
|
706
|
+
return true, value
|
707
|
+
end
|
703
708
|
end
|
704
709
|
break if Time.now.sys >= end_time
|
705
710
|
|
@@ -724,25 +729,25 @@ module Cosmos
|
|
724
729
|
end
|
725
730
|
|
726
731
|
# Wait for a converted telemetry item to pass a comparison
|
727
|
-
def cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, comparison_to_eval, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token)
|
728
|
-
|
729
|
-
"value " + comparison_to_eval
|
732
|
+
def cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, comparison_to_eval, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token, &block)
|
733
|
+
if comparison_to_eval
|
734
|
+
exp_to_eval = "value " + comparison_to_eval
|
735
|
+
else
|
736
|
+
exp_to_eval = nil
|
730
737
|
end
|
738
|
+
_cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, exp_to_eval, scope: scope, token: token, &block)
|
731
739
|
end
|
732
740
|
|
733
|
-
def cosmos_script_wait_implementation_tolerance(target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token)
|
734
|
-
|
735
|
-
|
736
|
-
end
|
741
|
+
def cosmos_script_wait_implementation_tolerance(target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token, &block)
|
742
|
+
exp_to_eval = "((#{expected_value} - #{tolerance})..(#{expected_value} + #{tolerance})).include? value"
|
743
|
+
_cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, exp_to_eval, scope: scope, token: token, &block)
|
737
744
|
end
|
738
745
|
|
739
|
-
def cosmos_script_wait_implementation_array_tolerance(array_size, target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token)
|
746
|
+
def cosmos_script_wait_implementation_array_tolerance(array_size, target_name, packet_name, item_name, value_type, expected_value, tolerance, timeout, polling_rate = DEFAULT_TLM_POLLING_RATE, scope: $cosmos_scope, token: $cosmos_token, &block)
|
740
747
|
statements = []
|
741
748
|
array_size.times { |i| statements << "(((#{expected_value[i]} - #{tolerance[i]})..(#{expected_value[i]} + #{tolerance[i]})).include? value[#{i}])" }
|
742
749
|
exp_to_eval = statements.join(" && ")
|
743
|
-
_cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, scope: scope, token: token)
|
744
|
-
exp_to_eval
|
745
|
-
end
|
750
|
+
_cosmos_script_wait_implementation(target_name, packet_name, item_name, value_type, timeout, polling_rate, exp_to_eval, scope: scope, token: token, &block)
|
746
751
|
end
|
747
752
|
|
748
753
|
# Wait on an expression to be true.
|
@@ -112,13 +112,11 @@ module Cosmos
|
|
112
112
|
target_name, cmd_name, cmd_params = $api_server.method_missing(cmd, *args)
|
113
113
|
_log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
|
114
114
|
rescue HazardousError => e
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
retry unless prompt_for_script_abort()
|
121
|
-
end
|
115
|
+
# This opens a prompt at which point they can cancel and stop the script
|
116
|
+
# or say Yes and send the command. Thus we don't care about the return value.
|
117
|
+
prompt_for_hazardous(e.target_name, e.cmd_name, e.hazardous_description)
|
118
|
+
target_name, cmd_name, cmd_params = $api_server.method_missing(cmd_no_hazardous, *args)
|
119
|
+
_log_cmd(target_name, cmd_name, cmd_params, raw, no_range, no_hazardous)
|
122
120
|
end
|
123
121
|
end
|
124
122
|
end
|
data/lib/cosmos/script/script.rb
CHANGED
@@ -129,58 +129,38 @@ module Cosmos
|
|
129
129
|
message_box(string, *items, **options)
|
130
130
|
end
|
131
131
|
|
132
|
-
def _file_dialog(
|
132
|
+
def _file_dialog(title, message, filter:)
|
133
133
|
answer = ''
|
134
|
-
|
135
|
-
if
|
136
|
-
|
137
|
-
|
138
|
-
files.select! { |f| File.directory? f }
|
139
|
-
end
|
134
|
+
path = "./*"
|
135
|
+
path += filter if filter
|
136
|
+
files = Dir[path]
|
137
|
+
files.select! { |f| !File.directory? f }
|
140
138
|
while answer.empty?
|
141
|
-
print
|
139
|
+
print "#{title}\n#{message}\n#{files.join("\n")}\n<Type file name>:"
|
142
140
|
answer = gets
|
143
141
|
answer.chomp!
|
144
142
|
end
|
145
143
|
return answer
|
146
144
|
end
|
147
145
|
|
148
|
-
def
|
149
|
-
_file_dialog(
|
150
|
-
end
|
151
|
-
|
152
|
-
def open_file_dialog(directory, message = "Open File", filter = "*")
|
153
|
-
_file_dialog(message, directory, filter)
|
154
|
-
end
|
155
|
-
|
156
|
-
def open_files_dialog(directory, message = "Open File(s)", filter = "*")
|
157
|
-
_file_dialog(message, directory, filter)
|
146
|
+
def open_file_dialog(title, message = "Open File", filter:)
|
147
|
+
_file_dialog(title, message, filter)
|
158
148
|
end
|
159
149
|
|
160
|
-
def
|
161
|
-
_file_dialog(
|
150
|
+
def open_files_dialog(title, message = "Open File(s)", filter:)
|
151
|
+
_file_dialog(title, message, filter)
|
162
152
|
end
|
163
153
|
|
164
154
|
def prompt_for_hazardous(target_name, cmd_name, hazardous_description)
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def prompt_for_script_abort
|
178
|
-
print "Stop running script? (y,n): "
|
179
|
-
answer = gets.chomp
|
180
|
-
if answer.downcase == 'y'
|
181
|
-
exit
|
182
|
-
else
|
183
|
-
return false # Not aborted - Retry
|
155
|
+
loop do
|
156
|
+
message = "Warning: Command #{target_name} #{cmd_name} is Hazardous. "
|
157
|
+
message << "\n#{hazardous_description}\n" if hazardous_description
|
158
|
+
message << "Send? (y): "
|
159
|
+
print message
|
160
|
+
answer = gets.chomp
|
161
|
+
if answer.downcase == 'y'
|
162
|
+
return true
|
163
|
+
end
|
184
164
|
end
|
185
165
|
end
|
186
166
|
|
@@ -23,137 +23,124 @@ module Cosmos
|
|
23
23
|
module Script
|
24
24
|
private
|
25
25
|
|
26
|
-
#
|
26
|
+
# Delete a file on a target
|
27
|
+
#
|
28
|
+
# @param [String] Path to a file in a target directory
|
29
|
+
def delete_target_file(path, scope: $cosmos_scope)
|
30
|
+
begin
|
31
|
+
# Only delete from the targets_modified
|
32
|
+
delete_path = "#{scope}/targets_modified/#{path}"
|
33
|
+
endpoint = "/cosmos-api/storage/delete/#{delete_path}"
|
34
|
+
Cosmos::Logger.info "Deleting #{delete_path}"
|
35
|
+
response = $api_server.request('delete', endpoint, query: {bucket: 'config'})
|
36
|
+
if response.nil? || response.code != 200
|
37
|
+
raise "Failed to delete #{delete_path}. Note: #{scope}/targets is read-only."
|
38
|
+
end
|
39
|
+
rescue => error
|
40
|
+
raise "Failed deleting #{path} due to #{error.message}"
|
41
|
+
end
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
# Get a handle to write a target file
|
27
46
|
#
|
28
47
|
# @param path [String] Path to a file in a target directory
|
29
|
-
# @param
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
48
|
+
# @param io_or_string [Io or String] IO object
|
49
|
+
def put_target_file(path, io_or_string, scope: $cosmos_scope)
|
50
|
+
raise "Disallowed path modifier '..' found in #{path}" if path.include?('..')
|
51
|
+
upload_path = "#{scope}/targets_modified/#{path}"
|
52
|
+
endpoint = "/cosmos-api/storage/upload/#{upload_path}"
|
53
|
+
Cosmos::Logger.info "Writing #{upload_path}"
|
54
|
+
result = _get_presigned_request(endpoint)
|
34
55
|
|
35
|
-
#
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
endpoint = "/cosmos-api/storage/download/#{scope}/#{part}/#{path}"
|
44
|
-
Cosmos::Logger.info "Reading #{scope}/#{part}/#{path}"
|
45
|
-
if $cosmos_in_cluster
|
46
|
-
response = $api_server.request('get', endpoint, query: {bucket: 'config', internal: true})
|
47
|
-
else
|
48
|
-
response = $api_server.request('get', endpoint, query: {bucket: 'config'})
|
49
|
-
end
|
50
|
-
if response.nil? || response.code != 201
|
51
|
-
Cosmos::Logger.error "Failed Get Presigned URL for #{scope}/#{part}/#{path}"
|
52
|
-
if part == "targets_modified"
|
53
|
-
part = "targets"
|
54
|
-
redo
|
56
|
+
# Try to put the file
|
57
|
+
success = false
|
58
|
+
begin
|
59
|
+
uri = _get_uri(result['url'])
|
60
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
61
|
+
request = Net::HTTP::Put.new(uri, {'Content-Length' => io_or_string.length.to_s})
|
62
|
+
if String === io_or_string
|
63
|
+
request.body = io_or_string
|
55
64
|
else
|
56
|
-
|
65
|
+
request.body_stream = io_or_string
|
66
|
+
end
|
67
|
+
result = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
68
|
+
http.request(request)
|
57
69
|
end
|
70
|
+
return result
|
58
71
|
end
|
59
|
-
|
72
|
+
rescue => error
|
73
|
+
raise "Failed to write #{upload_path}"
|
74
|
+
end
|
75
|
+
nil
|
76
|
+
end
|
60
77
|
|
61
|
-
|
78
|
+
# Get a handle to access a target file
|
79
|
+
#
|
80
|
+
# @param path [String] Path to a file in a target directory, e.g. "INST/procedures/test.rb"
|
81
|
+
# @param original [Boolean] Whether to get the original or modified file
|
82
|
+
# @return [File|nil]
|
83
|
+
def get_target_file(path, original: false, scope: $cosmos_scope)
|
84
|
+
part = "targets"
|
85
|
+
part += "_modified" unless original
|
86
|
+
# Loop to allow redo when switching from modified to original
|
87
|
+
loop do
|
62
88
|
begin
|
63
|
-
|
64
|
-
uri = URI.parse("http://cosmos-minio:9000" + result['url'])
|
65
|
-
else
|
66
|
-
uri = URI.parse($api_server.generate_url + result['url'])
|
67
|
-
end
|
68
|
-
Net::HTTP.start(uri.host, uri.port) do |http|
|
69
|
-
request = Net::HTTP::Get.new uri
|
70
|
-
|
71
|
-
http.request request do |response|
|
72
|
-
response.read_body do |chunk|
|
73
|
-
puts chunk.length
|
74
|
-
file.write chunk
|
75
|
-
end
|
76
|
-
end
|
77
|
-
file.rewind
|
78
|
-
end
|
79
|
-
return file
|
89
|
+
return _get_storage_file("#{part}/#{path}", scope: scope)
|
80
90
|
rescue => error
|
81
|
-
Cosmos::Logger.info("#{scope}/#{part}/#{path} not found")
|
82
91
|
if part == "targets_modified"
|
83
92
|
part = "targets"
|
84
93
|
redo
|
85
94
|
else
|
86
|
-
raise
|
95
|
+
raise error
|
87
96
|
end
|
88
97
|
end
|
89
98
|
break
|
90
99
|
end
|
91
100
|
end
|
92
101
|
|
93
|
-
#
|
94
|
-
#
|
95
|
-
# @param path [String] Path to a file in a target directory
|
96
|
-
# @param io_or_string [Io or String] IO object
|
97
|
-
def put_target_file(path, io_or_string, scope: $cosmos_scope)
|
98
|
-
# Get presigned url
|
99
|
-
part = "targets_modified"
|
100
|
-
begin
|
101
|
-
endpoint = "/cosmos-api/storage/upload/#{scope}/#{part}/#{path}"
|
102
|
-
Cosmos::Logger.info "Writing #{scope}/#{part}/#{path}"
|
103
|
-
if $cosmos_in_cluster
|
104
|
-
response = $api_server.request('get', endpoint, query: {bucket: 'config', internal: true})
|
105
|
-
else
|
106
|
-
response = $api_server.request('get', endpoint, query: {bucket: 'config'})
|
107
|
-
end
|
108
|
-
if response.nil? || response.code != 201
|
109
|
-
Cosmos::Logger.error "Failed Get Presigned URL for #{scope}/#{part}/#{path}"
|
110
|
-
return nil
|
111
|
-
end
|
112
|
-
result = JSON.parse(response.body)
|
102
|
+
# These are helper methods ... should not be used directly
|
113
103
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
result = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
130
|
-
http.request(request)
|
131
|
-
end
|
132
|
-
return result
|
104
|
+
def _get_storage_file(path, scope: $cosmos_scope)
|
105
|
+
# Create Tempfile to store data
|
106
|
+
file = Tempfile.new('target', binmode: true)
|
107
|
+
|
108
|
+
endpoint = "/cosmos-api/storage/download/#{scope}/#{path}"
|
109
|
+
Cosmos::Logger.info "Reading #{scope}/#{path}"
|
110
|
+
result = _get_presigned_request(endpoint)
|
111
|
+
|
112
|
+
# Try to get the file
|
113
|
+
uri = _get_uri(result['url'])
|
114
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
115
|
+
request = Net::HTTP::Get.new uri
|
116
|
+
http.request request do |response|
|
117
|
+
response.read_body do |chunk|
|
118
|
+
file.write chunk
|
133
119
|
end
|
134
|
-
rescue => error
|
135
|
-
raise "Failed to write #{scope}/#{part}/#{path}"
|
136
120
|
end
|
121
|
+
file.rewind
|
137
122
|
end
|
138
|
-
|
123
|
+
return file
|
139
124
|
end
|
140
125
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
# Only delete from the targets_modified
|
147
|
-
endpoint = "/cosmos-api/storage/delete/#{scope}/targets_modified/#{path}"
|
148
|
-
Cosmos::Logger.info "Deleting #{scope}/targets_modified/#{path}"
|
149
|
-
response = $api_server.request('delete', endpoint, query: {bucket: 'config'})
|
150
|
-
if response.nil? || response.code != 200
|
151
|
-
raise "Failed to delete #{scope}/targets_modified/#{path}"
|
152
|
-
end
|
153
|
-
rescue => error
|
154
|
-
raise "Failed deleting #{path} due to #{error.message}"
|
126
|
+
def _get_uri(url)
|
127
|
+
if $cosmos_in_cluster
|
128
|
+
uri = URI.parse("http://cosmos-minio:9000" + url)
|
129
|
+
else
|
130
|
+
uri = URI.parse($api_server.generate_url + url)
|
155
131
|
end
|
156
|
-
|
132
|
+
end
|
133
|
+
|
134
|
+
def _get_presigned_request(endpoint)
|
135
|
+
if $cosmos_in_cluster
|
136
|
+
response = $api_server.request('get', endpoint, query: { bucket: 'config', internal: true })
|
137
|
+
else
|
138
|
+
response = $api_server.request('get', endpoint, query: { bucket: 'config' })
|
139
|
+
end
|
140
|
+
if response.nil? || response.code != 201
|
141
|
+
raise "Failed to get presigned URL for #{endpoint}"
|
142
|
+
end
|
143
|
+
JSON.parse(response.body)
|
157
144
|
end
|
158
145
|
end
|
159
146
|
end
|
@@ -21,6 +21,10 @@ require 'cosmos/topics/topic'
|
|
21
21
|
|
22
22
|
module Cosmos
|
23
23
|
class CommandDecomTopic < Topic
|
24
|
+
def self.topics(scope:)
|
25
|
+
super(scope, 'DECOMCMD')
|
26
|
+
end
|
27
|
+
|
24
28
|
def self.write_packet(packet, scope:)
|
25
29
|
topic = "#{scope}__DECOMCMD__{#{packet.target_name}}__#{packet.packet_name}"
|
26
30
|
msg_hash = { time: packet.received_time.to_nsec_from_epoch,
|
@@ -21,6 +21,10 @@ require 'cosmos/topics/topic'
|
|
21
21
|
|
22
22
|
module Cosmos
|
23
23
|
class TelemetryDecomTopic < Topic
|
24
|
+
def self.topics(scope:)
|
25
|
+
super(scope, 'DECOM')
|
26
|
+
end
|
27
|
+
|
24
28
|
def self.write_packet(packet, id: nil, scope:)
|
25
29
|
# Need to build a JSON hash of the decommutated data
|
26
30
|
# Support "downward typing"
|
data/lib/cosmos/topics/topic.rb
CHANGED
@@ -34,5 +34,15 @@ module Cosmos
|
|
34
34
|
Store.xtrim(topic, maxlen)
|
35
35
|
end
|
36
36
|
end
|
37
|
+
|
38
|
+
def self.topics(scope, key)
|
39
|
+
topics = []
|
40
|
+
loop do
|
41
|
+
token, streams = Store.scan(0, :match => "#{scope}__#{key}__*", :count => 1000)
|
42
|
+
topics.concat(streams)
|
43
|
+
break if token == 0
|
44
|
+
end
|
45
|
+
topics
|
46
|
+
end
|
37
47
|
end
|
38
48
|
end
|