openc3 5.7.2 → 5.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/data/config/widgets.yaml +6 -6
- data/lib/openc3/api/cmd_api.rb +29 -0
- data/lib/openc3/api/limits_api.rb +31 -1
- data/lib/openc3/api/tlm_api.rb +5 -7
- data/lib/openc3/core_ext/faraday.rb +8 -0
- data/lib/openc3/core_ext.rb +1 -1
- data/lib/openc3/io/json_api_object.rb +24 -12
- data/lib/openc3/io/json_drb_object.rb +3 -7
- data/lib/openc3/logs/buffered_packet_log_writer.rb +20 -12
- data/lib/openc3/logs/log_writer.rb +12 -7
- data/lib/openc3/logs/packet_log_writer.rb +9 -6
- data/lib/openc3/microservices/decom_microservice.rb +4 -0
- data/lib/openc3/microservices/interface_decom_common.rb +32 -0
- data/lib/openc3/microservices/reducer_microservice.rb +15 -11
- data/lib/openc3/models/cvt_model.rb +10 -5
- data/lib/openc3/models/gem_model.rb +0 -1
- data/lib/openc3/models/scope_model.rb +0 -3
- data/lib/openc3/models/target_model.rb +7 -7
- data/lib/openc3/models/timeline_model.rb +0 -1
- data/lib/openc3/models/trigger_group_model.rb +0 -1
- data/lib/openc3/script/metadata.rb +7 -7
- data/lib/openc3/script/screen.rb +5 -5
- data/lib/openc3/script/script_runner.rb +17 -17
- data/lib/openc3/script/storage.rb +2 -2
- data/lib/openc3/topics/config_topic.rb +1 -6
- data/lib/openc3/topics/decom_interface_topic.rb +62 -0
- data/lib/openc3/topics/telemetry_decom_topic.rb +0 -9
- data/lib/openc3/topics/topic.rb +4 -11
- data/lib/openc3/utilities/authentication.rb +4 -4
- data/lib/openc3/utilities/bucket_require.rb +65 -0
- data/lib/openc3/utilities/bucket_utilities.rb +38 -5
- data/lib/openc3/utilities/open_telemetry.rb +4 -4
- data/lib/openc3/utilities/process_manager.rb +4 -2
- data/lib/openc3/utilities/ruby_lex_utils.rb +62 -36
- data/lib/openc3/utilities/store_autoload.rb +7 -28
- data/lib/openc3/version.rb +6 -6
- data/lib/openc3.rb +1 -1
- data/templates/widget/package.json +7 -7
- data/templates/widget/yarn.lock +46 -47
- metadata +55 -38
@@ -135,7 +135,6 @@ module OpenC3
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def deploy_unknown_commandlog_microservice(gem_path, variables, parent)
|
138
|
-
Topic.initialize_streams(["#{@scope}__COMMAND__{UNKNOWN}__UNKNOWN"])
|
139
138
|
microservice_name = "#{@scope}__COMMANDLOG__UNKNOWN"
|
140
139
|
microservice = MicroserviceModel.new(
|
141
140
|
name: microservice_name,
|
@@ -158,7 +157,6 @@ module OpenC3
|
|
158
157
|
end
|
159
158
|
|
160
159
|
def deploy_unknown_packetlog_microservice(gem_path, variables, parent)
|
161
|
-
Topic.initialize_streams(["#{@scope}__TELEMETRY__{UNKNOWN}__UNKNOWN"])
|
162
160
|
microservice_name = "#{@scope}__PACKETLOG__UNKNOWN"
|
163
161
|
microservice = MicroserviceModel.new(
|
164
162
|
name: microservice_name,
|
@@ -211,7 +209,6 @@ module OpenC3
|
|
211
209
|
|
212
210
|
def deploy(gem_path, variables)
|
213
211
|
seed_database()
|
214
|
-
ConfigTopic.initialize_stream(@scope)
|
215
212
|
|
216
213
|
# Create UNKNOWN target for display of unknown data
|
217
214
|
model = TargetModel.new(name: "UNKNOWN", scope: @scope)
|
@@ -527,7 +527,13 @@ module OpenC3
|
|
527
527
|
data = ERB.new(data, trim_mode: "-").result(binding.set_variables(variables)) if data.is_printable? and File.basename(filename)[0] != '_'
|
528
528
|
end
|
529
529
|
rescue => error
|
530
|
-
|
530
|
+
# ERB error parsing a screen is just a logger error because life can go on
|
531
|
+
# With cmd/tlm or scripts this is a serious error and we raise
|
532
|
+
if (filename.include?('/screens/'))
|
533
|
+
Logger.error("ERB error parsing #{key} due to #{error.message}")
|
534
|
+
else
|
535
|
+
raise "ERB error parsing #{key} due to #{error.message}"
|
536
|
+
end
|
531
537
|
end
|
532
538
|
local_path = File.join(temp_dir, @name, target_folder_path)
|
533
539
|
FileUtils.mkdir_p(File.dirname(local_path))
|
@@ -965,12 +971,6 @@ module OpenC3
|
|
965
971
|
rescue
|
966
972
|
# No telemetry packets for this target
|
967
973
|
end
|
968
|
-
# It's ok to call initialize_streams with an empty array
|
969
|
-
Topic.initialize_streams(command_topic_list)
|
970
|
-
Topic.initialize_streams(decom_command_topic_list)
|
971
|
-
Topic.initialize_streams(packet_topic_list)
|
972
|
-
Topic.initialize_streams(decom_topic_list)
|
973
|
-
Topic.initialize_streams(reduced_topic_list)
|
974
974
|
|
975
975
|
@parent = nil
|
976
976
|
%w(DECOM COMMANDLOG DECOMCMDLOG PACKETLOG DECOMLOG REDUCER CLEANUP).each do |type|
|
@@ -172,7 +172,6 @@ module OpenC3
|
|
172
172
|
def deploy
|
173
173
|
topics = ["#{@scope}__openc3_autonomic"]
|
174
174
|
if MicroserviceModel.get_model(name: @microservice_name, scope: @scope).nil?
|
175
|
-
AutonomicTopic.initialize_streams(topics)
|
176
175
|
create_microservice(topics: topics)
|
177
176
|
end
|
178
177
|
end
|
@@ -35,7 +35,7 @@ module OpenC3
|
|
35
35
|
def metadata_all(limit: 100, scope: $openc3_scope)
|
36
36
|
response = $api_server.request('get', "/openc3-api/metadata", query: { limit: limit }, scope: scope)
|
37
37
|
# Non-existant just returns nil
|
38
|
-
return nil if response.nil? || response.
|
38
|
+
return nil if response.nil? || response.status != 200
|
39
39
|
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
40
40
|
end
|
41
41
|
alias all_metadata metadata_all
|
@@ -50,7 +50,7 @@ module OpenC3
|
|
50
50
|
response = $api_server.request('get', "/openc3-api/metadata/latest", scope: scope)
|
51
51
|
end
|
52
52
|
# Non-existant just returns nil
|
53
|
-
return nil if response.nil? || response.
|
53
|
+
return nil if response.nil? || response.status != 200
|
54
54
|
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
55
55
|
end
|
56
56
|
alias get_metadata metadata_get
|
@@ -70,11 +70,11 @@ module OpenC3
|
|
70
70
|
data[:start] = start.iso8601 unless start.nil?
|
71
71
|
response = $api_server.request('post', '/openc3-api/metadata', data: data, json: true, scope: scope)
|
72
72
|
if response.nil?
|
73
|
-
raise "Failed to set metadata due to #{response.
|
74
|
-
elsif response.
|
73
|
+
raise "Failed to set metadata due to #{response.status}"
|
74
|
+
elsif response.status == 409
|
75
75
|
raise "Metadata overlaps existing metadata. Did you metadata_set within 1s of another?"
|
76
|
-
elsif response.
|
77
|
-
raise "Failed to set metadata due to #{response.
|
76
|
+
elsif response.status != 201
|
77
|
+
raise "Failed to set metadata due to #{response.status}"
|
78
78
|
end
|
79
79
|
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
80
80
|
end
|
@@ -101,7 +101,7 @@ module OpenC3
|
|
101
101
|
data = { :color => color, :metadata => metadata }
|
102
102
|
data[:start] = Time.at(start).iso8601
|
103
103
|
response = $api_server.request('put', "/openc3-api/metadata/#{start}", data: data, json: true, scope: scope)
|
104
|
-
if response.nil? || response.
|
104
|
+
if response.nil? || response.status != 200
|
105
105
|
raise "Failed to update metadata"
|
106
106
|
end
|
107
107
|
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
data/lib/openc3/script/screen.rb
CHANGED
@@ -25,7 +25,7 @@ module OpenC3
|
|
25
25
|
endpoint = "/openc3-api/screens"
|
26
26
|
# Pass the name of the ENV variable name where we pull the actual bucket name
|
27
27
|
response = $api_server.request('get', endpoint, scope: scope)
|
28
|
-
if response.nil? || response.
|
28
|
+
if response.nil? || response.status != 200
|
29
29
|
raise "Unexpected response to get_screen_list: #{response.inspect}"
|
30
30
|
end
|
31
31
|
screen_list = {}
|
@@ -50,7 +50,7 @@ module OpenC3
|
|
50
50
|
response = $api_server.request('get', endpoint, headers: {
|
51
51
|
Accept: 'text/plain',
|
52
52
|
}, scope: scope)
|
53
|
-
if response.nil? || response.
|
53
|
+
if response.nil? || response.status != 200
|
54
54
|
raise "Screen definition not found: #{target_name} #{screen_name}"
|
55
55
|
end
|
56
56
|
return response.body
|
@@ -67,8 +67,8 @@ module OpenC3
|
|
67
67
|
"screen" => screen_name,
|
68
68
|
"text" => definition
|
69
69
|
}
|
70
|
-
response = $api_server.request('post', endpoint, :data => data, scope: scope)
|
71
|
-
if response.nil? || response.
|
70
|
+
response = $api_server.request('post', endpoint, :data => data, :json => true, scope: scope)
|
71
|
+
if response.nil? || response.status != 200
|
72
72
|
if response
|
73
73
|
parsed = JSON.parse(response)
|
74
74
|
raise "create_screen error: #{parsed['error']}"
|
@@ -86,7 +86,7 @@ module OpenC3
|
|
86
86
|
begin
|
87
87
|
endpoint = "/openc3-api/screen/#{target_name.upcase}/#{screen_name.upcase}"
|
88
88
|
response = $api_server.request('delete', endpoint, scope: scope)
|
89
|
-
if response.nil? || response.
|
89
|
+
if response.nil? || response.status != 200
|
90
90
|
if response
|
91
91
|
parsed = JSON.parse(response)
|
92
92
|
raise "delete_screen error: #{parsed['error']}"
|
@@ -22,7 +22,7 @@ module OpenC3
|
|
22
22
|
|
23
23
|
def _script_response_error(response, message, scope: $openc3_scope)
|
24
24
|
if response
|
25
|
-
raise "#{message} (#{response.
|
25
|
+
raise "#{message} (#{response.status}): #{response.body}"
|
26
26
|
else
|
27
27
|
raise "#{message}: No Response"
|
28
28
|
end
|
@@ -31,7 +31,7 @@ module OpenC3
|
|
31
31
|
def script_list(scope: $openc3_scope)
|
32
32
|
endpoint = "/script-api/scripts"
|
33
33
|
response = $script_runner_api_server.request('get', endpoint, scope: scope)
|
34
|
-
if response.nil? || response.
|
34
|
+
if response.nil? || response.status != 200
|
35
35
|
_script_response_error(response, "Script list request failed", scope: scope)
|
36
36
|
else
|
37
37
|
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
@@ -41,7 +41,7 @@ module OpenC3
|
|
41
41
|
def script_syntax_check(script, scope: $openc3_scope)
|
42
42
|
endpoint = "/script-api/scripts/syntax"
|
43
43
|
response = $script_runner_api_server.request('post', endpoint, json: true, data: script, scope: scope)
|
44
|
-
if response.nil? || response.
|
44
|
+
if response.nil? || response.status != 200
|
45
45
|
_script_response_error(response, "Script syntax check request failed", scope: scope)
|
46
46
|
else
|
47
47
|
result = JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
@@ -56,7 +56,7 @@ module OpenC3
|
|
56
56
|
def script_body(filename, scope: $openc3_scope)
|
57
57
|
endpoint = "/script-api/scripts/#{filename}"
|
58
58
|
response = $script_runner_api_server.request('get', endpoint, scope: scope)
|
59
|
-
if response.nil? || response.
|
59
|
+
if response.nil? || response.status != 200
|
60
60
|
_script_response_error(response, "Failed to get #{filename}", scope: scope)
|
61
61
|
else
|
62
62
|
script = response.body
|
@@ -82,7 +82,7 @@ module OpenC3
|
|
82
82
|
end
|
83
83
|
# NOTE: json: true causes json_api_object to JSON generate and set the Content-Type to json
|
84
84
|
response = $script_runner_api_server.request('post', endpoint, json: true, data: { environment: env_data }, scope: scope)
|
85
|
-
if response.nil? || response.
|
85
|
+
if response.nil? || response.status != 200
|
86
86
|
_script_response_error(response, "Failed to run #{filename}", scope: scope)
|
87
87
|
else
|
88
88
|
script_id = Integer(response.body)
|
@@ -93,7 +93,7 @@ module OpenC3
|
|
93
93
|
def script_delete(filename, scope: $openc3_scope)
|
94
94
|
endpoint = "/script-api/scripts/#{filename}/delete"
|
95
95
|
response = $script_runner_api_server.request('post', endpoint, scope: scope)
|
96
|
-
if response.nil? || response.
|
96
|
+
if response.nil? || response.status != 200
|
97
97
|
_script_response_error(response, "Failed to delete #{filename}", scope: scope)
|
98
98
|
else
|
99
99
|
return true
|
@@ -103,7 +103,7 @@ module OpenC3
|
|
103
103
|
def script_lock(filename, scope: $openc3_scope)
|
104
104
|
endpoint = "/script-api/scripts/#{filename}/lock"
|
105
105
|
response = $script_runner_api_server.request('post', endpoint, scope: scope)
|
106
|
-
if response.nil? || response.
|
106
|
+
if response.nil? || response.status != 200
|
107
107
|
_script_response_error(response, "Failed to lock #{filename}", scope: scope)
|
108
108
|
else
|
109
109
|
return true
|
@@ -113,7 +113,7 @@ module OpenC3
|
|
113
113
|
def script_unlock(filename, scope: $openc3_scope)
|
114
114
|
endpoint = "/script-api/scripts/#{filename}/unlock"
|
115
115
|
response = $script_runner_api_server.request('post', endpoint, scope: scope)
|
116
|
-
if response.nil? || response.
|
116
|
+
if response.nil? || response.status != 200
|
117
117
|
_script_response_error(response, "Failed to unlock #{filename}", scope: scope)
|
118
118
|
else
|
119
119
|
return true
|
@@ -123,7 +123,7 @@ module OpenC3
|
|
123
123
|
def script_instrumented(filename, script, scope: $openc3_scope)
|
124
124
|
endpoint = "/script-api/scripts/#{filename}/instrumented"
|
125
125
|
response = $script_runner_api_server.request('post', endpoint, json: true, data: script, scope: scope)
|
126
|
-
if response.nil? || response.
|
126
|
+
if response.nil? || response.status != 200
|
127
127
|
_script_response_error(response, "Script instrumented request failed", scope: scope)
|
128
128
|
else
|
129
129
|
result = JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
@@ -139,7 +139,7 @@ module OpenC3
|
|
139
139
|
def script_create(filename, script, breakpoints = [], scope: $openc3_scope)
|
140
140
|
endpoint = "/script-api/scripts/#{filename}"
|
141
141
|
response = $script_runner_api_server.request('post', endpoint, json: true, data: { text: script, breakpoints: breakpoints }, scope: scope)
|
142
|
-
if response.nil? || response.
|
142
|
+
if response.nil? || response.status != 200
|
143
143
|
_script_response_error(response, "Script create request failed", scope: scope)
|
144
144
|
else
|
145
145
|
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
@@ -149,7 +149,7 @@ module OpenC3
|
|
149
149
|
def script_delete_all_breakpoints(scope: $openc3_scope)
|
150
150
|
endpoint = "/script-api/breakpoints/delete/all"
|
151
151
|
response = $script_runner_api_server.request('delete', endpoint, scope: scope)
|
152
|
-
if response.nil? || response.
|
152
|
+
if response.nil? || response.status != 200
|
153
153
|
_script_response_error(response, "Script delete all breakpoints failed", scope: scope)
|
154
154
|
else
|
155
155
|
return true
|
@@ -159,7 +159,7 @@ module OpenC3
|
|
159
159
|
def running_script_list(scope: $openc3_scope)
|
160
160
|
endpoint = "/script-api/running-script"
|
161
161
|
response = $script_runner_api_server.request('get', endpoint, scope: scope)
|
162
|
-
if response.nil? || response.
|
162
|
+
if response.nil? || response.status != 200
|
163
163
|
_script_response_error(response, "Running script list request failed", scope: scope)
|
164
164
|
else
|
165
165
|
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
@@ -169,7 +169,7 @@ module OpenC3
|
|
169
169
|
def running_script_get(id, scope: $openc3_scope)
|
170
170
|
endpoint = "/script-api/running-script/#{id}"
|
171
171
|
response = $script_runner_api_server.request('get', endpoint, scope: scope)
|
172
|
-
if response.nil? || response.
|
172
|
+
if response.nil? || response.status != 200
|
173
173
|
_script_response_error(response, "Running script show request failed", scope: scope)
|
174
174
|
else
|
175
175
|
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
@@ -179,7 +179,7 @@ module OpenC3
|
|
179
179
|
def _running_script_action(id, action_name, scope: $openc3_scope)
|
180
180
|
endpoint = "/script-api/running-script/#{id}/#{action_name}"
|
181
181
|
response = $script_runner_api_server.request('post', endpoint, scope: scope)
|
182
|
-
if response.nil? || response.
|
182
|
+
if response.nil? || response.status != 200
|
183
183
|
_script_response_error(response, "Running script #{action_name} request failed", scope: scope)
|
184
184
|
else
|
185
185
|
return true
|
@@ -217,7 +217,7 @@ module OpenC3
|
|
217
217
|
def running_script_debug(id, debug_code, scope: $openc3_scope)
|
218
218
|
endpoint = "/script-api/running-script/#{id}/debug"
|
219
219
|
response = $script_runner_api_server.request('post', endpoint, json: true, data: {'args' => debug_code}, scope: scope)
|
220
|
-
if response.nil? || response.
|
220
|
+
if response.nil? || response.status != 200
|
221
221
|
_script_response_error(response, "Running script debug request failed", scope: scope)
|
222
222
|
else
|
223
223
|
return true
|
@@ -231,7 +231,7 @@ module OpenC3
|
|
231
231
|
else
|
232
232
|
response = $script_runner_api_server.request('post', endpoint, json: true, data: {'method' => method_name, 'answer' => answer, 'prompt_id' => prompt_id}, scope: scope)
|
233
233
|
end
|
234
|
-
if response.nil? || response.
|
234
|
+
if response.nil? || response.status != 200
|
235
235
|
_script_response_error(response, "Running script prompt request failed", scope: scope)
|
236
236
|
else
|
237
237
|
return true
|
@@ -241,7 +241,7 @@ module OpenC3
|
|
241
241
|
def completed_script_list(scope: $openc3_scope)
|
242
242
|
endpoint = "/script-api/completed-scripts"
|
243
243
|
response = $script_runner_api_server.request('get', endpoint, scope: scope)
|
244
|
-
if response.nil? || response.
|
244
|
+
if response.nil? || response.status != 200
|
245
245
|
_script_response_error(response, "Completed script list request failed", scope: scope)
|
246
246
|
else
|
247
247
|
return JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
@@ -40,7 +40,7 @@ module OpenC3
|
|
40
40
|
OpenC3::Logger.info "Deleting #{delete_path}"
|
41
41
|
# Pass the name of the ENV variable name where we pull the actual bucket name
|
42
42
|
response = $api_server.request('delete', endpoint, query: { bucket: 'OPENC3_CONFIG_BUCKET' }, scope: scope)
|
43
|
-
if response.nil? || response.
|
43
|
+
if response.nil? || response.status != 200
|
44
44
|
raise "Failed to delete #{delete_path}"
|
45
45
|
end
|
46
46
|
rescue => error
|
@@ -181,7 +181,7 @@ module OpenC3
|
|
181
181
|
else
|
182
182
|
response = $api_server.request('get', endpoint, query: { bucket: 'OPENC3_CONFIG_BUCKET' }, scope: scope)
|
183
183
|
end
|
184
|
-
if response.nil? || response.
|
184
|
+
if response.nil? || response.status != 201
|
185
185
|
raise "Failed to get presigned URL for #{endpoint}"
|
186
186
|
end
|
187
187
|
JSON.parse(response.body, :allow_nan => true, :create_additions => true)
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# All changes Copyright 2022, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
|
-
# This file may also be used under the terms of a commercial license
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/topics/topic'
|
@@ -26,11 +26,6 @@ module OpenC3
|
|
26
26
|
class ConfigTopic < Topic
|
27
27
|
PRIMARY_KEY = "__CONFIG"
|
28
28
|
|
29
|
-
# Helper method to initialize the stream and ensure a consistent key
|
30
|
-
def self.initialize_stream(scope)
|
31
|
-
self.initialize_streams(["#{scope}#{PRIMARY_KEY}"])
|
32
|
-
end
|
33
|
-
|
34
29
|
# Write a configuration change to the topic
|
35
30
|
# @param config [Hash] Hash with required keys 'kind', 'name', 'type'
|
36
31
|
def self.write(config, scope:)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2023 OpenC3, Inc.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
|
16
|
+
# This file may also be used under the terms of a commercial license
|
17
|
+
# if purchased from OpenC3, Inc.
|
18
|
+
|
19
|
+
require 'openc3/topics/topic'
|
20
|
+
|
21
|
+
module OpenC3
|
22
|
+
class DecomInterfaceTopic < Topic
|
23
|
+
def self.build_cmd(target_name, cmd_name, cmd_params, range_check, raw, scope:)
|
24
|
+
data = {}
|
25
|
+
data['target_name'] = target_name.to_s.upcase
|
26
|
+
data['cmd_name'] = cmd_name.to_s.upcase
|
27
|
+
data['cmd_params'] = cmd_params
|
28
|
+
data['range_check'] = range_check
|
29
|
+
data['raw'] = raw
|
30
|
+
# DecomMicroservice is listening to the DECOMINTERFACE topic and is responsible
|
31
|
+
# for actually building the command. This was deliberate to allow this to work
|
32
|
+
# with or without an interface.
|
33
|
+
decom_id = Topic.write_topic("#{scope}__DECOMINTERFACE__{#{target_name}}",
|
34
|
+
{ 'build_cmd' => JSON.generate(data, allow_nan: true) }, '*', 100)
|
35
|
+
timeout = 5 # Arbitrary 5s timeout
|
36
|
+
ack_topic = "{#{scope}__ACKCMD}TARGET__#{target_name}"
|
37
|
+
time = Time.now
|
38
|
+
while (Time.now - time) < timeout
|
39
|
+
Topic.read_topics([ack_topic]) do |topic, msg_id, msg_hash, redis|
|
40
|
+
if msg_hash["id"] == decom_id
|
41
|
+
if msg_hash["result"] == "SUCCESS"
|
42
|
+
return msg_hash
|
43
|
+
else
|
44
|
+
raise msg_hash["message"]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
raise "Timeout of #{timeout}s waiting for cmd ack. Does target '#{target_name}' exist?"
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, scope:)
|
53
|
+
data = {}
|
54
|
+
data['target_name'] = target_name.to_s.upcase
|
55
|
+
data['packet_name'] = packet_name.to_s.upcase
|
56
|
+
data['item_hash'] = item_hash
|
57
|
+
data['type'] = type
|
58
|
+
Topic.write_topic("#{scope}__DECOMINTERFACE__{#{target_name}}",
|
59
|
+
{ 'inject_tlm' => JSON.generate(data, allow_nan: true) }, '*', 100)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -56,14 +56,5 @@ module OpenC3
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
59
|
-
|
60
|
-
def self.inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, scope:)
|
61
|
-
data = {}
|
62
|
-
data['target_name'] = target_name.to_s.upcase
|
63
|
-
data['packet_name'] = packet_name.to_s.upcase
|
64
|
-
data['item_hash'] = item_hash
|
65
|
-
data['type'] = type
|
66
|
-
Topic.write_topic("#{scope}__DECOMINTERFACE__{#{target_name}}", { 'inject_tlm' => JSON.generate(data, allow_nan: true) }, '*', 100)
|
67
|
-
end
|
68
59
|
end
|
69
60
|
end
|
data/lib/openc3/topics/topic.rb
CHANGED
@@ -17,23 +17,16 @@
|
|
17
17
|
# All changes Copyright 2022, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
|
-
# This file may also be used under the terms of a commercial license
|
20
|
+
# This file may also be used under the terms of a commercial license
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/utilities/store'
|
24
24
|
|
25
25
|
module OpenC3
|
26
26
|
class Topic
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
EphemeralStore.public_send(message, *args, &block)
|
31
|
-
end
|
32
|
-
else
|
33
|
-
# Delegate all unknown class methods to delegate to the EphemeralStore
|
34
|
-
def self.method_missing(message, *args, **kwargs, &block)
|
35
|
-
EphemeralStore.public_send(message, *args, **kwargs, &block)
|
36
|
-
end
|
27
|
+
# Delegate all unknown class methods to delegate to the EphemeralStore
|
28
|
+
def self.method_missing(message, *args, **kwargs, &block)
|
29
|
+
EphemeralStore.public_send(message, *args, **kwargs, &block)
|
37
30
|
end
|
38
31
|
|
39
32
|
def self.clear_topics(topics, maxlen = 0)
|
@@ -14,19 +14,18 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2023, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/version'
|
24
|
+
require 'faraday'
|
24
25
|
|
25
26
|
module OpenC3
|
26
|
-
|
27
27
|
# Basic exception for known errors
|
28
28
|
class OpenC3AuthenticationError < StandardError; end
|
29
|
-
|
30
29
|
class OpenC3AuthenticationRetryableError < OpenC3AuthenticationError; end
|
31
30
|
|
32
31
|
# OpenC3 base / open source authentication code
|
@@ -71,6 +70,7 @@ module OpenC3
|
|
71
70
|
@refresh_expires_at = nil
|
72
71
|
@token = nil
|
73
72
|
@log = [nil, nil]
|
73
|
+
@http = Faraday.new
|
74
74
|
end
|
75
75
|
|
76
76
|
# Load the token from the environment
|
@@ -150,7 +150,7 @@ module OpenC3
|
|
150
150
|
STDOUT.puts @log[0] if JsonDRb.debug?
|
151
151
|
saved_verbose = $VERBOSE; $VERBOSE = nil
|
152
152
|
begin
|
153
|
-
resp =
|
153
|
+
resp = @http.post(uri, data, headers)
|
154
154
|
ensure
|
155
155
|
$VERBOSE = saved_verbose
|
156
156
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2022 OpenC3, Inc.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# This file may also be used under the terms of a commercial license
|
17
|
+
# if purchased from OpenC3, Inc.
|
18
|
+
|
19
|
+
require 'openc3'
|
20
|
+
require 'openc3/utilities/bucket_utilities'
|
21
|
+
|
22
|
+
OpenC3.disable_warnings do
|
23
|
+
def require(*args, **kw_args)
|
24
|
+
begin
|
25
|
+
return super(*args, **kw_args)
|
26
|
+
rescue LoadError
|
27
|
+
begin
|
28
|
+
@bucket_require_cache ||= {}
|
29
|
+
if @bucket_require_cache[args[0]]
|
30
|
+
return false
|
31
|
+
else
|
32
|
+
scope = nil
|
33
|
+
if kw_args[:scope]
|
34
|
+
scope = kw_args[:scope]
|
35
|
+
else
|
36
|
+
scope = $openc3_scope
|
37
|
+
end
|
38
|
+
OpenC3::BucketUtilities.bucket_load(*args, scope: scope)
|
39
|
+
@bucket_require_cache[args[0]] = true
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
rescue Exception => err
|
43
|
+
raise LoadError, "#{err.class}:#{err.message}", err.backtrace
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def load(*args, **kw_args)
|
49
|
+
begin
|
50
|
+
super(*args, **kw_args)
|
51
|
+
rescue LoadError
|
52
|
+
begin
|
53
|
+
scope = nil
|
54
|
+
if kw_args[:scope]
|
55
|
+
scope = kw_args[:scope]
|
56
|
+
else
|
57
|
+
scope = $openc3_scope
|
58
|
+
end
|
59
|
+
OpenC3::BucketUtilities.bucket_load(*args, scope: scope)
|
60
|
+
rescue Exception
|
61
|
+
raise LoadError, "#{err.class}:#{err.message}", err.backtrace
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -21,6 +21,7 @@
|
|
21
21
|
# if purchased from OpenC3, Inc.
|
22
22
|
|
23
23
|
require 'openc3/utilities/bucket'
|
24
|
+
require 'openc3/utilities/target_file'
|
24
25
|
require 'openc3/models/reducer_model'
|
25
26
|
require 'zlib'
|
26
27
|
|
@@ -29,6 +30,26 @@ module OpenC3
|
|
29
30
|
FILE_TIMESTAMP_FORMAT = "%Y%m%d%H%M%S%N"
|
30
31
|
DIRECTORY_TIMESTAMP_FORMAT = "%Y%m%d"
|
31
32
|
|
33
|
+
def self.bucket_load(*args, scope: $openc3_scope)
|
34
|
+
path = args[0]
|
35
|
+
|
36
|
+
# Only support TARGET files
|
37
|
+
if path[0] == '/' or path.split('/')[0].to_s.upcase != path.split('/')[0]
|
38
|
+
raise LoadError
|
39
|
+
end
|
40
|
+
extension = File.extname(path)
|
41
|
+
path = path + '.rb' if extension == ""
|
42
|
+
|
43
|
+
# Retrieve the text of the script from S3
|
44
|
+
text = TargetFile.body(scope, path)
|
45
|
+
|
46
|
+
# Execute the script directly without instrumentation because we are doing require/load
|
47
|
+
Object.class_eval(text, path, 1)
|
48
|
+
|
49
|
+
# Successful load/require returns true
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
32
53
|
# @param bucket [String] Name of the bucket to list
|
33
54
|
# @param prefix [String] Prefix to filter all files by
|
34
55
|
# @param start_time [Time|nil] Ruby time to find files after. nil means no start (first file on).
|
@@ -66,12 +87,24 @@ module OpenC3
|
|
66
87
|
filename = compress_file(filename)
|
67
88
|
bucket_key += '.gz'
|
68
89
|
end
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
90
|
+
|
91
|
+
retry_count = 0
|
92
|
+
begin
|
93
|
+
# We want to open this as a file and pass that to put_object to allow
|
94
|
+
# this to work with really large files. Otherwise the entire file has
|
95
|
+
# to be held in memory!
|
96
|
+
File.open(filename, 'rb') do |file|
|
97
|
+
client.put_object(bucket: ENV['OPENC3_LOGS_BUCKET'], key: bucket_key, body: file, metadata: metadata)
|
98
|
+
end
|
99
|
+
rescue => err
|
100
|
+
# Try to upload file three times
|
101
|
+
retry_count += 1
|
102
|
+
raise err if retry_count >= 3
|
103
|
+
Logger.warn("Error saving log file to bucket - retry #{retry_count}: #{filename}\n#{err.formatted}")
|
104
|
+
sleep(1)
|
105
|
+
retry
|
74
106
|
end
|
107
|
+
|
75
108
|
Logger.debug "wrote #{ENV['OPENC3_LOGS_BUCKET']}/#{bucket_key}"
|
76
109
|
ReducerModel.add_file(bucket_key) # Record the new file for data reduction
|
77
110
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: ascii-8bit
|
2
2
|
|
3
|
-
# Copyright
|
3
|
+
# Copyright 2023 OpenC3, Inc.
|
4
4
|
# All Rights Reserved.
|
5
5
|
#
|
6
6
|
# This program is free software; you can modify and/or redistribute it
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
#
|
16
|
-
# This file may also be used under the terms of a commercial license
|
16
|
+
# This file may also be used under the terms of a commercial license
|
17
17
|
# if purchased from OpenC3, Inc.
|
18
18
|
|
19
19
|
require 'openc3/utilities/bucket'
|
@@ -60,7 +60,7 @@ module OpenC3
|
|
60
60
|
|
61
61
|
if @otel_enabled
|
62
62
|
require 'redis'
|
63
|
-
require '
|
63
|
+
require 'faraday'
|
64
64
|
require 'openc3/utilities/bucket'
|
65
65
|
# Load the bucket client code so the instrumentation works later
|
66
66
|
Bucket.getClient()
|
@@ -86,7 +86,7 @@ module OpenC3
|
|
86
86
|
# To omit the attribute, set db_statement to :omit.
|
87
87
|
db_statement: :include,
|
88
88
|
}
|
89
|
-
c.use 'OpenTelemetry::Instrumentation::
|
89
|
+
c.use 'OpenTelemetry::Instrumentation::Faraday'
|
90
90
|
c.use 'OpenTelemetry::Instrumentation::AwsSdk'
|
91
91
|
# TODO: Add in additional cloud SDKs
|
92
92
|
end
|