openc3 5.4.2 → 5.5.0.pre.beta0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openc3 might be problematic. Click here for more details.

@@ -0,0 +1,423 @@
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/streams/web_socket_client_stream'
20
+ require 'openc3/utilities/authentication'
21
+ require 'openc3/io/json_rpc'
22
+
23
+ module OpenC3
24
+ # Base class - Do not use directly
25
+ class WebSocketApi
26
+ USER_AGENT = 'OpenC3 / v5 (ruby/openc3/lib/io/web_socket_api)'.freeze
27
+
28
+ # Create the WebsocketApi object. If a block is given will automatically connect/disconnect
29
+ def initialize(url:, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope, &block)
30
+ @scope = scope
31
+ @authentication = authentication.nil? ? generate_auth() : authentication
32
+ @url = url
33
+ @write_timeout = write_timeout
34
+ @read_timeout = read_timeout
35
+ @connect_timeout = connect_timeout
36
+ @subscribed = false
37
+ if block_given?
38
+ begin
39
+ connect()
40
+ yield self
41
+ ensure
42
+ disconnect()
43
+ end
44
+ end
45
+ end
46
+
47
+ # Read the next message without filtering / parsing
48
+ def read_message
49
+ subscribe()
50
+ return @stream.read
51
+ end
52
+
53
+ # Read the next message with json parsing, filtering, and timeout support
54
+ def read(ignore_protocol_messages: true, timeout: nil)
55
+ start_time = Time.now
56
+ while true
57
+ message = read_message()
58
+ if message
59
+ json_hash = JSON.parse(message, allow_nan: true, create_additions: true)
60
+ if ignore_protocol_messages
61
+ type = json_hash['type']
62
+ if type # ping, welcome, confirm_subscription, reject_subscription, disconnect
63
+ if type == 'disconnect'
64
+ if json_hash['reason'] == 'unauthorized'
65
+ raise "Unauthorized"
66
+ end
67
+ end
68
+ if type == 'reject_subscription'
69
+ raise "Subscription Rejected"
70
+ end
71
+ if timeout
72
+ end_time = Time.now
73
+ if (start_time - end_time) > timeout
74
+ raise Timeout::Error, "No Data Timeout"
75
+ end
76
+ end
77
+ if defined? RunningScript and RunningScript.instance
78
+ raise StopScript if RunningScript.instance.stop?
79
+ end
80
+ next
81
+ end
82
+ end
83
+ return json_hash['message']
84
+ end
85
+ return message
86
+ end
87
+ end
88
+
89
+ # Will subscribe to the channel based on @identifier
90
+ def subscribe
91
+ unless @subscribed
92
+ json_hash = {}
93
+ json_hash['command'] = 'subscribe'
94
+ json_hash['identifier'] = JSON.generate(@identifier)
95
+ @stream.write(JSON.generate(json_hash))
96
+ @subscribed = true
97
+ end
98
+ end
99
+
100
+ # Will unsubscribe to the channel based on @identifier
101
+ def unsubscribe
102
+ if @subscribed
103
+ json_hash = {}
104
+ json_hash['command'] = 'unsubscribe'
105
+ json_hash['identifier'] = JSON.generate(@identifier)
106
+ @stream.write(JSON.generate(json_hash))
107
+ @subscribed = false
108
+ end
109
+ end
110
+
111
+ # Send an ActionCable command
112
+ def write_action(data_hash)
113
+ json_hash = {}
114
+ json_hash['command'] = 'message'
115
+ json_hash['identifier'] = JSON.generate(@identifier)
116
+ json_hash['data'] = JSON.generate(data_hash)
117
+ write(JSON.generate(json_hash))
118
+ end
119
+
120
+ # General write to the websocket
121
+ def write(data)
122
+ subscribe()
123
+ @stream.write(data)
124
+ end
125
+
126
+ # Connect to the websocket with authorization in query params
127
+ def connect
128
+ disconnect()
129
+ final_url = @url + "?scope=#{@scope}&authorization=#{@authentication.token}"
130
+ @stream = WebSocketClientStream.new(final_url, @write_timeout, @read_timeout, @connect_timeout)
131
+ @stream.headers = {
132
+ 'Sec-WebSocket-Protocol' => 'actioncable-v1-json, actioncable-unsupported',
133
+ 'User-Agent' => USER_AGENT
134
+ }
135
+ @stream.connect
136
+ end
137
+
138
+ # Are we connected?
139
+ def connected?
140
+ if @stream
141
+ @stream.connected?
142
+ else
143
+ false
144
+ end
145
+ end
146
+
147
+ # Disconnect from the websocket and attempt to send unsubscribe message
148
+ def disconnect
149
+ if connected?()
150
+ begin
151
+ unsubscribe()
152
+ rescue
153
+ # Oh well, we tried
154
+ end
155
+ @stream.disconnect
156
+ end
157
+ end
158
+
159
+ # private
160
+
161
+ # Generate the appropriate token for OpenC3
162
+ def generate_auth
163
+ if ENV['OPENC3_API_TOKEN'].nil? and ENV['OPENC3_API_USER'].nil?
164
+ if ENV['OPENC3_API_PASSWORD'] || ENV['OPENC3_SERVICE_PASSWORD']
165
+ return OpenC3Authentication.new()
166
+ else
167
+ raise "Environment Variables Not Set for Authentication"
168
+ end
169
+ else
170
+ return OpenC3KeycloakAuthentication.new(ENV['OPENC3_KEYCLOAK_URL'])
171
+ end
172
+ end
173
+ end
174
+
175
+ # Base class for cmd-tlm-api websockets - Do not use directly
176
+ class CmdTlmWebSocketApi < WebSocketApi
177
+ def initialize(url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
178
+ url = generate_url() unless url
179
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
180
+ end
181
+
182
+ def generate_url
183
+ schema = ENV['OPENC3_API_SCHEMA'] || 'http'
184
+ hostname = ENV['OPENC3_API_HOSTNAME'] || (ENV['OPENC3_DEVEL'] ? '127.0.0.1' : 'openc3-cosmos-cmd-tlm-api')
185
+ port = ENV['OPENC3_API_PORT'] || '2901'
186
+ port = port.to_i
187
+ return "#{schema}://#{hostname}:#{port}/openc3-api/cable"
188
+ end
189
+ end
190
+
191
+ # Base class for script-runner-api websockets - Do not use directly
192
+ class ScriptWebSocketApi < WebSocketApi
193
+ def initialize(url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_token)
194
+ url = generate_url() unless url
195
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
196
+ end
197
+
198
+ def generate_url
199
+ schema = ENV['OPENC3_SCRIPT_API_SCHEMA'] || 'http'
200
+ hostname = ENV['OPENC3_SCRIPT_API_HOSTNAME'] || (ENV['OPENC3_DEVEL'] ? '127.0.0.1' : 'openc3-cosmos-script-runner-api')
201
+ port = ENV['OPENC3_SCRIPT_API_PORT'] || '2902'
202
+ port = port.to_i
203
+ return "#{schema}://#{hostname}:#{port}/script-api/cable"
204
+ end
205
+ end
206
+
207
+ # Running Script WebSocket
208
+ class RunningScriptWebSocketApi < ScriptWebSocketApi
209
+ def initialize(id:, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
210
+ @identifier = {
211
+ channel: "RunningScriptChannel",
212
+ id: id
213
+ }
214
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
215
+ end
216
+ end
217
+
218
+ # Log Messages WebSocket
219
+ class MessagesWebSocketApi < CmdTlmWebSocketApi
220
+ def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
221
+ @identifier = {
222
+ channel: "MessagesChannel",
223
+ history_count: history_count
224
+ }
225
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
226
+ end
227
+ end
228
+
229
+ # Notifications WebSocket
230
+ class NotificationsWebSocketApi < CmdTlmWebSocketApi
231
+ def initialize(history_count: 0, start_offset: nil, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
232
+ @identifier = {
233
+ channel: "NotificationsChannel",
234
+ history_count: history_count,
235
+ start_offset: start_offset
236
+ }
237
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
238
+ end
239
+ end
240
+
241
+ # Autonomic Events WebSocket
242
+ class AutonomicEventsWebSocketApi < CmdTlmWebSocketApi
243
+ def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
244
+ @identifier = {
245
+ channel: "AutonomicEventsChannel",
246
+ history_count: history_count
247
+ }
248
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
249
+ end
250
+ end
251
+
252
+ # Calendar Events WebSocket
253
+ class CalendarEventsWebSocketApi < CmdTlmWebSocketApi
254
+ def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
255
+ @identifier = {
256
+ channel: "CalendarEventsChannel",
257
+ history_count: history_count
258
+ }
259
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
260
+ end
261
+ end
262
+
263
+ # Config Events WebSocket
264
+ class ConfigEventsWebSocketApi < CmdTlmWebSocketApi
265
+ def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
266
+ @identifier = {
267
+ channel: "ConfigEventsChannel",
268
+ history_count: history_count
269
+ }
270
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
271
+ end
272
+ end
273
+
274
+ # Limits Events WebSocket
275
+ class LimitsEventsWebSocketApi < CmdTlmWebSocketApi
276
+ def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
277
+ @identifier = {
278
+ channel: "LimitsEventsChannel",
279
+ history_count: history_count
280
+ }
281
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
282
+ end
283
+ end
284
+
285
+ # Timeline WebSocket
286
+ class TimelineEventsWebSocketApi < CmdTlmWebSocketApi
287
+ def initialize(history_count: 0, url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
288
+ @identifier = {
289
+ channel: "TimelineEventsChannel",
290
+ history_count: history_count
291
+ }
292
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
293
+ end
294
+ end
295
+
296
+ # Streaming API WebSocket
297
+ class StreamingWebSocketApi < CmdTlmWebSocketApi
298
+ def initialize(url: nil, write_timeout: 10.0, read_timeout: 10.0, connect_timeout: 5.0, authentication: nil, scope: $openc3_scope)
299
+ @identifier = {
300
+ channel: "StreamingChannel"
301
+ }
302
+ super(url: url, write_timeout: write_timeout, read_timeout: read_timeout, connect_timeout: connect_timeout, authentication: authentication, scope: scope)
303
+ end
304
+
305
+ # Request to add data to the stream
306
+ #
307
+ # arguments:
308
+ # scope: scope name
309
+ # start_time: 64-bit nanoseconds from unix epoch - If not present then realtime
310
+ # end_time: 64-bit nanoseconds from unix epoch - If not present stream forever
311
+ # items: [ [ MODE__CMDORTLM__TARGET__PACKET__ITEM__VALUETYPE__REDUCEDTYPE, item_key] ]
312
+ # MODE - RAW, DECOM, REDUCED_MINUTE, REDUCED_HOUR, or REDUCED_DAY
313
+ # CMDORTLM - CMD or TLM
314
+ # TARGET - Target name
315
+ # PACKET - Packet name
316
+ # ITEM - Item Name
317
+ # VALUETYPE - RAW, CONVERTED, FORMATTED, or WITH_UNITS
318
+ # REDUCEDTYPE - MIN, MAX, AVG, STDDEV (only for reduced modes)
319
+ # item_key is an optional shortened name to return the data as
320
+ # packets: [ MODE__CMDORTLM__TARGET__PACKET__VALUETYPE ]
321
+ # MODE - RAW, DECOM, REDUCED_MINUTE, REDUCED_HOUR, or REDUCED_DAY
322
+ # CMDORTLM - CMD or TLM
323
+ # TARGET - Target name
324
+ # PACKET - Packet name
325
+ # VALUETYPE - RAW, CONVERTED, FORMATTED, WITH_UNITS, or PURE (pure means all types as stored in log)
326
+ #
327
+ def add(items: nil, packets: nil, start_time: nil, end_time: nil, scope: $openc3_scope)
328
+ data_hash = {}
329
+ data_hash['action'] = 'add'
330
+ if start_time
331
+ if Time === start_time
332
+ start_time = start_time.to_nsec_from_epoch
333
+ end
334
+ data_hash['start_time'] = start_time
335
+ end
336
+ if end_time
337
+ if Time === end_time
338
+ end_time = end_time.to_nsec_from_epoch
339
+ end
340
+ data_hash['end_time'] = end_time
341
+ end
342
+ data_hash['items'] = items if items
343
+ data_hash['packets'] = packets if packets
344
+ data_hash['scope'] = scope
345
+ data_hash['token'] = @authentication.token
346
+ write_action(data_hash)
347
+ end
348
+
349
+ # Request to remove data from the stream
350
+ #
351
+ # arguments:
352
+ # scope: scope name
353
+ # items: [ [ MODE__CMDORTLM__TARGET__PACKET__ITEM__VALUETYPE__REDUCEDTYPE] ]
354
+ # MODE - RAW, DECOM, REDUCED_MINUTE, REDUCED_HOUR, or REDUCED_DAY
355
+ # CMDORTLM - CMD or TLM
356
+ # TARGET - Target name
357
+ # PACKET - Packet name
358
+ # ITEM - Item Name
359
+ # VALUETYPE - RAW, CONVERTED, FORMATTED, or WITH_UNITS
360
+ # REDUCEDTYPE - MIN, MAX, AVG, STDDEV (only for reduced modes)
361
+ # packets: [ MODE__CMDORTLM__TARGET__PACKET__VALUETYPE ]
362
+ # MODE - RAW, DECOM, REDUCED_MINUTE, REDUCED_HOUR, or REDUCED_DAY
363
+ # CMDORTLM - CMD or TLM
364
+ # TARGET - Target name
365
+ # PACKET - Packet name
366
+ # VALUETYPE - RAW, CONVERTED, FORMATTED, WITH_UNITS, or PURE (pure means all types as stored in log)
367
+ #
368
+ def remove(items: nil, packets: nil, scope: $openc3_scope)
369
+ data_hash = {}
370
+ data_hash['action'] = 'remove'
371
+ data_hash['items'] = items if items
372
+ data_hash['packets'] = packets if packets
373
+ data_hash['scope'] = scope
374
+ data_hash['token'] = @authentication.token
375
+ write_action(data_hash)
376
+ end
377
+
378
+ # Convenience method to read all data until end marker is received.
379
+ # Warning: DATA IS STORED IN RAM. Do not use this with large queries
380
+ def self.read_all(items: nil, packets: nil, start_time: nil, end_time:, scope: $openc3_scope, timeout: nil)
381
+ read_all_start_time = Time.now
382
+ data = []
383
+ self.new do |api|
384
+ api.add(items: items, packets: packets, start_time: start_time, end_time: end_time, scope: scope)
385
+ while true
386
+ batch = api.read
387
+ if batch.length == 0
388
+ return data
389
+ else
390
+ data.concat(batch)
391
+ end
392
+ if timeout
393
+ if (Time.now - read_all_start_time) > timeout
394
+ return data
395
+ end
396
+ end
397
+ end
398
+ end
399
+ end
400
+ end
401
+ end
402
+
403
+ # # Example Use
404
+ # $openc3_scope = 'DEFAULT'
405
+ # ENV['OPENC3_API_HOSTNAME'] = 'localhost'
406
+ # ENV['OPENC3_API_PORT'] = '2900'
407
+ # ENV['OPENC3_SCRIPT_API_HOSTNAME'] = 'localhost'
408
+ # ENV['OPENC3_SCRIPT_API_PORT'] = '2900'
409
+ # ENV['OPENC3_API_PASSWORD'] = 'password'
410
+ #
411
+ # OpenC3::StreamingWebSocketApi.new do |api|
412
+ # api.add(items: ['DECOM__TLM__INST__HEALTH_STATUS__TEMP1__CONVERTED', 'DECOM__TLM__INST__HEALTH_STATUS__TEMP2__CONVERTED'])
413
+ # 5.times do
414
+ # puts api.read
415
+ # end
416
+ # api.remove(items: ['DECOM__TLM__INST__HEALTH_STATUS__TEMP1__CONVERTED'])
417
+ # 5.times do
418
+ # puts api.read
419
+ # end
420
+ # end
421
+ #
422
+ # # Warning this saves all data to RAM. Do not use for large queries
423
+ # data = OpenC3::StreamingWebSocketApi.read_all(items: ['DECOM__TLM__INST__HEALTH_STATUS__TEMP1__CONVERTED', 'DECOM__TLM__INST__HEALTH_STATUS__TEMP2__CONVERTED'], end_time: Time.now + 30)
@@ -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 'socket'
@@ -0,0 +1,99 @@
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 'openssl'
20
+ require 'openc3/streams/tcpip_client_stream'
21
+ require 'websocket'
22
+ require 'uri'
23
+
24
+ module OpenC3
25
+ class WebSocketClientStream < TcpipClientStream
26
+ attr_accessor :headers
27
+
28
+ # @param url [String] The host to connect to
29
+ # @param write_timeout (see TcpipSocketStream#initialize)
30
+ # @param read_timeout (see TcpipSocketStream#initialize)
31
+ # @param connect_timeout (see TcpipClientStream#initialize)
32
+ def initialize(url, write_timeout, read_timeout, connect_timeout = 5.0)
33
+ @url = url
34
+ @uri = URI.parse @url
35
+ port = ((@uri.scheme == 'wss' or @uri.scheme == 'https') ? 443 : 80)
36
+ port = @uri.port if @uri.port
37
+ super(@uri.host, port, port, write_timeout, read_timeout, connect_timeout)
38
+ if ['https', 'wss'].include? @uri.scheme
39
+ socket = ::OpenSSL::SSL::SSLSocket.new(@write_socket)
40
+ socket.sync_close = true
41
+ socket.hostname = @uri.host
42
+ @write_socket = socket
43
+ @read_socket = socket
44
+ end
45
+ @headers = {}
46
+ end
47
+
48
+ def connect
49
+ super()
50
+ @handshake = ::WebSocket::Handshake::Client.new(:url => @url, :headers => @headers)
51
+ @frame = ::WebSocket::Frame::Incoming::Client.new
52
+ @handshaked = false
53
+ @write_socket.write(@handshake.to_s)
54
+ start_time = Time.now
55
+ read() # This should wait for the handshake
56
+ return true
57
+ end
58
+
59
+ def read
60
+ while true
61
+ if @handshaked
62
+ msg = @frame.next
63
+ return msg.data if msg
64
+ end
65
+
66
+ data = super()
67
+ return data if data.length <= 0
68
+
69
+ if @handshaked
70
+ @frame << data
71
+ msg = @frame.next
72
+ return msg.data if msg
73
+ else
74
+ index = 0
75
+ chars = ""
76
+ data.each_char do |char|
77
+ @handshake << char
78
+ chars << char
79
+ index += 1
80
+ if @handshake.finished?
81
+ @handshaked = true
82
+ break
83
+ end
84
+ end
85
+ if @handshaked
86
+ data = data[index..-1]
87
+ @frame << data
88
+ return
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ def write(data, type: :text)
95
+ frame = ::WebSocket::Frame::Outgoing::Client.new(:data => data, :type => type, :version => @handshake.version)
96
+ super(frame.to_s)
97
+ end
98
+ end
99
+ end
@@ -461,22 +461,7 @@ module OpenC3
461
461
 
462
462
  # @param filename [String] Name of the file to open in the web browser
463
463
  def self.open_in_web_browser(filename)
464
- if filename
465
- if Kernel.is_windows?
466
- self.run_process("cmd /c \"start \"\" \"#{filename.gsub('/', '\\')}\"\"")
467
- elsif Kernel.is_mac?
468
- self.run_process("open -a Safari \"#{filename}\"")
469
- else
470
- which_firefox = `which firefox`.chomp
471
- if which_firefox =~ /Command not found/i or which_firefox =~ /no .* in/i
472
- raise "Firefox not found"
473
- else
474
- system_call = "#{which_firefox} \"#{filename}\""
475
- end
476
-
477
- self.run_process(system_call)
478
- end
479
- end
464
+ puts "open_in_web_browser is DEPRECATED"
480
465
  end
481
466
 
482
467
  # Temporarily set the working directory during a block
@@ -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/models/auth_model'
@@ -42,7 +42,9 @@ rescue LoadError
42
42
 
43
43
  if $openc3_authorize
44
44
  raise AuthError.new("Token is required") unless token
45
- raise AuthError.new("Token is invalid for '#{permission}' permission") unless OpenC3::AuthModel.verify(token, permission: permission)
45
+ unless OpenC3::AuthModel.verify(token, permission: permission)
46
+ raise AuthError.new("Current role is invalid for '#{permission}' permission")
47
+ end
46
48
  end
47
49
  end
48
50
 
@@ -119,6 +119,8 @@ module OpenC3
119
119
  end
120
120
  # Array of objects with key and size methods
121
121
  result
122
+ rescue Aws::S3::Errors::NoSuchBucket => error
123
+ raise NotFound, "Bucket '#{bucket}' does not exist."
122
124
  end
123
125
 
124
126
  # Lists the files under a specified path
@@ -164,6 +166,8 @@ module OpenC3
164
166
  token = resp.next_continuation_token
165
167
  end
166
168
  result
169
+ rescue Aws::S3::Errors::NoSuchBucket => error
170
+ raise NotFound, "Bucket '#{bucket}' does not exist."
167
171
  end
168
172
 
169
173
  # put_object fires off the request to store but does not confirm
@@ -21,6 +21,10 @@ ENV['OPENC3_CLOUD'] ||= 'local'
21
21
  # Interface class implemented by each cloud provider: AWS, GCS, Azure
22
22
  module OpenC3
23
23
  class Bucket
24
+ # Raised when the underlying bucket does not exist
25
+ class NotFound < RuntimeError
26
+ end
27
+
24
28
  def self.getClient
25
29
  raise 'OPENC3_CLOUD environment variable is required' unless ENV['OPENC3_CLOUD']
26
30
  # Base is AwsBucket which works with MINIO, Enterprise implements additional
@@ -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/operators/operator'
@@ -52,7 +52,7 @@ module OpenC3
52
52
 
53
53
  # Spawns short lived processes and ensures they complete
54
54
  class ProcessManager
55
- MONITOR_CYCLE_SECONDS = 10
55
+ MONITOR_CYCLE_SECONDS = 5
56
56
  CLEANUP_CYCLE_SECONDS = 600
57
57
 
58
58
  @@instance = nil
@@ -68,6 +68,7 @@ module OpenC3
68
68
  begin
69
69
  monitor()
70
70
  rescue => err
71
+ Logger.error("ProcessManager unexpectedly died\n#{err.formatted}", scope: 'DEFAULT')
71
72
  raise "ProcessManager unexpectedly died\n#{err.formatted}"
72
73
  end
73
74
  end
@@ -111,10 +112,10 @@ module OpenC3
111
112
  end
112
113
  processes_to_delete.each do |process|
113
114
  if process.status.state == "Complete"
114
- Logger.info "Process #{process.status.name}:#{process.process_type}:#{process.detail} completed with state #{process.status.state}"
115
+ Logger.info("Process #{process.status.name}:#{process.process_type}:#{process.detail} completed with state #{process.status.state}", scope: process.scope)
115
116
  else
116
- Logger.error "Process #{process.status.name}:#{process.process_type}:#{process.detail} completed with state #{process.status.state}"
117
- Logger.error "Process Output:\n#{process.status.output}"
117
+ Logger.error("Process #{process.status.name}:#{process.process_type}:#{process.detail} completed with state #{process.status.state}", scope: process.scope)
118
+ Logger.error("Process Output:\n#{process.status.output}", scope: process.scope)
118
119
  end
119
120
 
120
121
  @processes.delete(process)
@@ -1,14 +1,14 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- OPENC3_VERSION = '5.4.2'
3
+ OPENC3_VERSION = '5.5.0-beta0'
4
4
  module OpenC3
5
5
  module Version
6
6
  MAJOR = '5'
7
- MINOR = '4'
8
- PATCH = '2'
9
- OTHER = ''
10
- BUILD = '6a7f2b4ff8e1255aa4d9768b539211b175cb9ec7'
7
+ MINOR = '5'
8
+ PATCH = '0'
9
+ OTHER = 'pre.beta0'
10
+ BUILD = 'abab088dbe97761fca351752b3396f1c05dd852b'
11
11
  end
12
- VERSION = '5.4.2'
13
- GEM_VERSION = '5.4.2'
12
+ VERSION = '5.5.0-beta0'
13
+ GEM_VERSION = '5.5.0.pre.beta0'
14
14
  end
data/lib/openc3.rb CHANGED
@@ -22,6 +22,9 @@
22
22
 
23
23
  # This file sets up using the OpenC3 framework
24
24
 
25
+ # Improve DNS (especially on Alpine)
26
+ require 'resolv-replace'
27
+
25
28
  # Set default encodings
26
29
  saved_verbose = $VERBOSE; $VERBOSE = nil
27
30
  Encoding.default_external = Encoding::ASCII_8BIT