openc3 5.7.0 → 5.8.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.
Potentially problematic release.
This version of openc3 might be problematic. Click here for more details.
- 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 +5 -5
- 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
|