openc3 5.4.1 → 5.4.3.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,47 @@
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/utilities/store'
20
+
21
+ module OpenC3
22
+ class TraefikModel
23
+ def self.register_route(microservice_name:, port:, prefix:, priority: 20)
24
+ prefix = '/' + prefix unless prefix[0] == '/'
25
+ if ENV['KUBERNETES_SERVICE_HOST']
26
+ url = "http://#{microservice_name.gsub('__', '-')}:#{port}"
27
+ else
28
+ url = "http://openc3-operator:#{port}"
29
+ end
30
+ service_name = microservice_name
31
+ router_name = microservice_name
32
+ Store.set("traefik/http/services/#{service_name}/loadbalancer/servers/0/url", url)
33
+ Store.set("traefik/http/routers/#{router_name}/service", service_name)
34
+ Store.set("traefik/http/routers/#{router_name}/priority", priority)
35
+ Store.set("traefik/http/routers/#{router_name}/rule", "PathPrefix(`#{prefix}`)")
36
+ end
37
+
38
+ def self.unregister_route(microservice_name:)
39
+ service_name = microservice_name
40
+ router_name = microservice_name
41
+ Store.del("traefik/http/routers/#{router_name}/rule")
42
+ Store.del("traefik/http/routers/#{router_name}/priority")
43
+ Store.del("traefik/http/routers/#{router_name}/service")
44
+ Store.del("traefik/http/services/#{service_name}/loadbalancer/servers/0/url")
45
+ end
46
+ end
47
+ end
@@ -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/model'
@@ -92,11 +92,10 @@ module OpenC3
92
92
  if color.nil?
93
93
  color = '#%06x' % (rand * 0xffffff)
94
94
  end
95
- valid_color = color =~ /(#*)([0-9,a-f,A-f]{6})/
95
+ valid_color = color =~ /[0-9,a-f,A-F]{6}/
96
96
  if valid_color.nil?
97
97
  raise TriggerGroupInputError.new "invalid color must be in hex format. #FF0000"
98
98
  end
99
-
100
99
  unless color.start_with?('#')
101
100
  color = "##{color}"
102
101
  end
@@ -538,7 +538,7 @@ module OpenC3
538
538
  end
539
539
  end
540
540
 
541
- def _check_process_args(args, function_name, scope: $openc3_scope, token: $openc3_token)
541
+ def _check_process_args(args, method_name, scope: $openc3_scope, token: $openc3_token)
542
542
  case args.length
543
543
  when 1
544
544
  target_name, packet_name, item_name, comparison_to_eval = extract_fields_from_check_text(args[0])
@@ -549,7 +549,7 @@ module OpenC3
549
549
  comparison_to_eval = args[3]
550
550
  else
551
551
  # Invalid number of arguments
552
- raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{function_name}()"
552
+ raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{method_name}()"
553
553
  end
554
554
  return [target_name, packet_name, item_name, comparison_to_eval]
555
555
  end
@@ -679,17 +679,17 @@ module OpenC3
679
679
  # When testing an array with a tolerance, the expected value and tolerance
680
680
  # can both be supplied as either an array or a single value. If a single
681
681
  # value is passed in, that value will be used for all array elements.
682
- def array_tolerance_process_args(array_size, expected_value, tolerance, function_name, scope: $openc3_scope, token: $openc3_token)
682
+ def array_tolerance_process_args(array_size, expected_value, tolerance, method_name, scope: $openc3_scope, token: $openc3_token)
683
683
  if expected_value.is_a?(Array)
684
684
  if array_size != expected_value.size
685
- raise "ERROR: Invalid array size for expected_value passed to #{function_name}()"
685
+ raise "ERROR: Invalid array size for expected_value passed to #{method_name}()"
686
686
  end
687
687
  else
688
688
  expected_value = Array.new(array_size, expected_value)
689
689
  end
690
690
  if tolerance.is_a?(Array)
691
691
  if array_size != tolerance.size
692
- raise "ERROR: Invalid array size for tolerance passed to #{function_name}()"
692
+ raise "ERROR: Invalid array size for tolerance passed to #{method_name}()"
693
693
  end
694
694
  else
695
695
  tolerance = Array.new(array_size, tolerance)
@@ -65,7 +65,7 @@ module OpenC3
65
65
 
66
66
  endpoint = "/openc3-api/storage/upload/#{upload_path}"
67
67
  result = _get_presigned_request(endpoint, scope: scope)
68
- OpenC3::Logger.info "Writing #{upload_path} at #{result['url']}"
68
+ OpenC3::Logger.info "Writing #{upload_path}"
69
69
 
70
70
  # Try to put the file
71
71
  begin
@@ -104,11 +104,12 @@ module OpenC3
104
104
  if part == "targets_modified" and ENV['OPENC3_LOCAL_MODE']
105
105
  local_file = OpenC3::LocalMode.open_local_file(path, scope: scope)
106
106
  if local_file
107
+ OpenC3::Logger.info "Reading local #{scope}/#{path}"
107
108
  file = Tempfile.new('target', binmode: true)
108
109
  file.write(local_file.read)
109
110
  local_file.close
110
111
  file.rewind
111
- return file if local_file
112
+ return file
112
113
  end
113
114
  end
114
115
 
@@ -133,7 +134,7 @@ module OpenC3
133
134
 
134
135
  endpoint = "/openc3-api/storage/download/#{scope}/#{path}"
135
136
  result = _get_presigned_request(endpoint, scope: scope)
136
- OpenC3::Logger.info "Reading #{scope}/#{path} at #{result['url']}"
137
+ OpenC3::Logger.info "Reading #{scope}/#{path}"
137
138
 
138
139
  # Try to get the file
139
140
  uri = _get_uri(result['url'])
@@ -16,6 +16,8 @@
16
16
  # This file may also be used under the terms of a commercial license
17
17
  # if purchased from OpenC3, Inc.
18
18
 
19
+ require 'openc3/script/extract'
20
+
19
21
  module OpenC3
20
22
  module Script
21
23
  private
@@ -39,5 +41,40 @@ module OpenC3
39
41
  end
40
42
  return id, packets
41
43
  end
44
+
45
+ # inject_tlm, set_tlm, override_tlm, and normalize_tlm are implemented here simply to add a puts
46
+ # these methods modify the telemetry so the user should be notified in the Script Runner log messages
47
+
48
+ def inject_tlm(target_name, packet_name, item_hash = nil, type: :CONVERTED, scope: $openc3_scope, token: $openc3_token)
49
+ puts "inject_tlm(\"#{target_name}\", \"#{packet_name}\", #{item_hash}, type: #{type})"
50
+ $api_server.method_missing(:inject_tlm, target_name, packet_name, item_hash, type: type, scope: scope, token: token)
51
+ end
52
+
53
+ def set_tlm(*args, type: :ALL, scope: $openc3_scope, token: $openc3_token)
54
+ if args.length == 1
55
+ puts "set_tlm(\"#{args.join('')}\", type: #{type})"
56
+ else
57
+ puts "set_tlm(\"#{args.join('", "')}\", type: #{type})"
58
+ end
59
+ $api_server.method_missing(:set_tlm, *args, type: type, scope: scope, token: token)
60
+ end
61
+
62
+ def override_tlm(*args, type: :ALL, scope: $openc3_scope, token: $openc3_token)
63
+ if args.length == 1
64
+ puts "override_tlm(\"#{args.join('')}\", type: #{type})"
65
+ else
66
+ puts "override_tlm(\"#{args.join('", "')}\", type: #{type})"
67
+ end
68
+ $api_server.method_missing(:override_tlm, *args, type: type, scope: scope, token: token)
69
+ end
70
+
71
+ def normalize_tlm(*args, type: :ALL, scope: $openc3_scope, token: $openc3_token)
72
+ if args.length == 1
73
+ puts "normalize_tlm(\"#{args.join('')}\", type: #{type})"
74
+ else
75
+ puts "normalize_tlm(\"#{args.join('", "')}\", type: #{type})"
76
+ end
77
+ $api_server.method_missing(:normalize_tlm, *args, type: type, scope: scope, token: token)
78
+ end
42
79
  end
43
80
  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.1'
3
+ OPENC3_VERSION = '5.4.3-beta0'
4
4
  module OpenC3
5
5
  module Version
6
6
  MAJOR = '5'
7
7
  MINOR = '4'
8
- PATCH = '1'
9
- OTHER = ''
10
- BUILD = 'b347f2b134ad7f7ea4ae0f57c7b53c5acde4b648'
8
+ PATCH = '3'
9
+ OTHER = 'pre.beta0'
10
+ BUILD = '3eeed1efa129ce27f14bffc2b6bab4428a20c500'
11
11
  end
12
- VERSION = '5.4.1'
13
- GEM_VERSION = '5.4.1'
12
+ VERSION = '5.4.3-beta0'
13
+ GEM_VERSION = '5.4.3.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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openc3
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.4.1
4
+ version: 5.4.3.pre.beta0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Melton
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-02-03 00:00:00.000000000 Z
12
+ date: 2023-02-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -669,7 +669,6 @@ files:
669
669
  - data/config/_interfaces.yaml
670
670
  - data/config/_items.yaml
671
671
  - data/config/_params.yaml
672
- - data/config/cmd_tlm_server.yaml
673
672
  - data/config/command.yaml
674
673
  - data/config/command_modifiers.yaml
675
674
  - data/config/command_telemetry.yaml
@@ -872,6 +871,7 @@ files:
872
871
  - lib/openc3/models/timeline_model.rb
873
872
  - lib/openc3/models/tool_config_model.rb
874
873
  - lib/openc3/models/tool_model.rb
874
+ - lib/openc3/models/traefik_model.rb
875
875
  - lib/openc3/models/trigger_group_model.rb
876
876
  - lib/openc3/models/trigger_model.rb
877
877
  - lib/openc3/models/widget_model.rb
@@ -925,7 +925,6 @@ files:
925
925
  - lib/openc3/system/system_config.rb
926
926
  - lib/openc3/system/target.rb
927
927
  - lib/openc3/tools/cmd_tlm_server/api.rb
928
- - lib/openc3/tools/cmd_tlm_server/cmd_tlm_server_config.rb
929
928
  - lib/openc3/tools/cmd_tlm_server/interface_thread.rb
930
929
  - lib/openc3/tools/table_manager/table.rb
931
930
  - lib/openc3/tools/table_manager/table_config.rb
@@ -1012,9 +1011,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
1012
1011
  version: '2.7'
1013
1012
  required_rubygems_version: !ruby/object:Gem::Requirement
1014
1013
  requirements:
1015
- - - ">="
1014
+ - - ">"
1016
1015
  - !ruby/object:Gem::Version
1017
- version: '0'
1016
+ version: 1.3.1
1018
1017
  requirements: []
1019
1018
  rubygems_version: 3.3.14
1020
1019
  signing_key:
@@ -1,136 +0,0 @@
1
- ---
2
- TITLE:
3
- summary: Sets the Command and Telemetry Server window title
4
- parameters:
5
- - name: Text
6
- required: true
7
- description: Text to put in the title of the Command and Telemetry Server window
8
- values: .+
9
- PACKET_LOG_WRITER:
10
- summary: Declare a packet log writer
11
- description: Packet log writer is used to declare a packet log writer class and
12
- give it a name which can be referenced by an interface. This is required if you
13
- want interfaces to have their own dedicated log writers or want to combine
14
- various interfaces into a single log file. By default, OpenC3 logs all data
15
- on all interfaces into a single command log and a single telemetry log.
16
- This keyword can also be used if you want to declare a different log file class
17
- to create log files.
18
- warning: You should NOT override the default without consulting a OpenC3 expert
19
- as this may break the ability to successfully read and write log files.
20
- example: |
21
- PACKET_LOG_WRITER DEFAULT packet_log_writer.rb # Default
22
- # The default logger filename will be <DATE>_openc3tlm.bin and will create a new log every 1MB
23
- PACKET_LOG_WRITER DEFAULT packet_log_writer.rb openc3 true nil 1000000
24
- # Create a logger named OPENC3_LOG which creates a new log every 5 min (600s)
25
- PACKET_LOG_WRITER OPENC3_LOG packet_log_writer.rb openc3 true 600
26
- parameters:
27
- - name: Log Writer Name
28
- required: true
29
- description: The name of the log writer as reference by other cmd_tlm_server keywords.
30
- This name also appears in the Logging tab on the Command and Telemetry Server.
31
- values: .+
32
- - name: Filename
33
- required: true
34
- description: Ruby file to use when instantiating a new log writer
35
- values: '.+\.rb'
36
- - name: Parameters
37
- required: false
38
- description: Optional parameters to pass to the log writer class when instantiating it.
39
- AUTO_INTERFACE_TARGETS:
40
- summary: Automatically use each target's cmd_tlm_server.txt file to define the interface
41
- description: Look for a cmd_tlm_server.txt file at the top level
42
- of each target directory and use this file to configure the interface for that target.
43
- This is a good way of keeping the knowledge of how to interface to a target
44
- within that target. However, if you use substitute target names (by using DECLARE_TARGET)
45
- or use different IP addresses then this will not work and you'll have to use the
46
- INTERFACE_TARGET or INTERFACE keyword.
47
- INTERFACE_TARGET:
48
- summary: Load the specified target's cmd_tlm_server.txt configuration file
49
- example: |
50
- INTERFACE_TARGET OPENC3 # Look in the OPENC3 target directory for cmd_tlm_server.txt
51
- INTERFACE_TARGET OPENC3 config.txt # Look in the OPENC3 target directory for config.txt
52
- parameters:
53
- - name: Target Name
54
- required: true
55
- description: Name of the target
56
- values: .+
57
- - name: Configuration File
58
- required: false
59
- description: Configuration filename which contains the interface configuration.
60
- Defaults to 'cmd_tlm_server.txt'.
61
- values: .+
62
- INTERFACE:
63
- modifiers:
64
- <%= MetaConfigParser.load('interface_modifiers.yaml').to_meta_config_yaml(4) %>
65
- summary: Defines a connection to a physical target
66
- description: Interfaces are what OpenC3 uses to talk to a particular piece
67
- of hardware. Interfaces require a Ruby file which implements all the interface
68
- methods necessary to talk to the hardware. OpenC3 defines many built in interfaces
69
- or you can define your own as long as it implements the interface protocol.
70
- parameters:
71
- - name: Interface Name
72
- required: true
73
- description: Name of the interface. This name will appear in the
74
- Interfaces tab of the Server and is also referenced by other keywords.
75
- The OpenC3 convention is to name interfaces after their targets with
76
- '_INT' appended to the name, e.g. INST_INT for the INST target.
77
- values: \D\S*
78
- - name: Filename
79
- required: true
80
- description: Ruby file to use when instantiating the interface.
81
- values:
82
- <%= MetaConfigParser.load('_interfaces.yaml').to_meta_config_yaml(8) %>
83
- documentation: Additional parameters are required. Please see the [Interfaces](/docs/v5/interfaces)
84
- documentation for more details.
85
- ROUTER:
86
- modifiers:
87
- ROUTE:
88
- summary: Map an interface to a router
89
- description: Once an interface has been mapped to a router, all its received telemetry
90
- will be sent out through the router.
91
- parameters:
92
- - name: Interface
93
- required: true
94
- description: Name of the interface
95
- values: .+
96
- <%= MetaConfigParser.load('interface_modifiers.yaml').to_meta_config_yaml(4) %>
97
- summary: Create an interface which reverses cmd/tlm data
98
- description: Router creates an interface which receives command packets from
99
- their remote targets and send them out their interfaces. They receive telemetry
100
- packets from their interfaces and send them to their remote targets. This allows
101
- routers to be intermediaries between an external client and an actual device.
102
- parameters:
103
- - name: Name
104
- required: true
105
- description: Name of the router
106
- values: .+
107
- - name: Filename
108
- required: true
109
- description: Ruby file to use when instantiating the interface.
110
- values:
111
- <%= MetaConfigParser.load('_interfaces.yaml').to_meta_config_yaml(8) %>
112
- documentation: Additional parameters are required. Please see the [Interfaces](/docs/v5/interfaces)
113
- documentation for more details.
114
- COLLECT_METADATA:
115
- summary: Prompts the user for meta data when starting the Command and Telemetry Server
116
- BACKGROUND_TASK:
117
- modifiers:
118
- STOPPED:
119
- summary: Indicate the background task should not be automatically started
120
- summary: Create a background task in the Command and Telemetry Server
121
- description: The Server instantiates the class which must inherit from BackgroundTask
122
- and then calls the call() method which the class must implement. The call() method
123
- is only called once so if your background task is supposed to live on while the
124
- Server is running, you must implement your code in a loop with a sleep to not
125
- use all the CPU.
126
- example: BACKGROUND_TASK example_background_task.rb
127
- parameters:
128
- - name: Filename
129
- required: true
130
- description: Ruby file which contains the background task implementation.
131
- Must inherit from BackgroundTask and implement the call method.
132
- values: '.+\.rb'
133
- - name: Optional Arguments
134
- required: false
135
- description: Optional arguments to the background task constructor
136
- values: .+