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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba92696b60117db745207ad94efe543da2db11f25212f70269a6305cb8445295
4
- data.tar.gz: ac3d2cc21a962434b478f708644bb33b702858c770a4c93c0017529bcb5b7b05
3
+ metadata.gz: 859879129f5646a4e8fd10a916e1e88859a7b5ed178fe2983f42df4e7e8c1a52
4
+ data.tar.gz: 745a188c5e9277e0bb793207f383f85d6ec6d571d41d6115530f6f78bd671817
5
5
  SHA512:
6
- metadata.gz: cca2d57593526f75888406d0b7946f22ce53823d6e2a45e5204a0856948b6b752b9a7a9612f417d973a6a50c55bf46b16800f4e9295cbeb451d48600d1ae71d0
7
- data.tar.gz: 37cb6cf7247cc6956172641d95755145e409ef09ee35dc08d7bae7650e422961c7d17caf83ee7affb428da84057a94625c4484e5b11165bf50db7d692d72a0f2
6
+ metadata.gz: '0582ba269983955ae39c8d0c941666d2fcc65811416e3c1ae7026811fa00d9699ecffc09e195909f30cac3c8571f6b83889349fed9c96ec89c95091aff088a61'
7
+ data.tar.gz: a9c9c554d6595cd7718dc58b1e2e07e0ff9a440cd6545674b47250a3542164a41d27bad1bf237c8c121f170dd04380eeaa125769abc9423c0de2e610578f9799
data/Gemfile CHANGED
@@ -6,13 +6,8 @@ gem 'ruby-termios', '>= 0.9' if RbConfig::CONFIG['target_os'] !~ /mswin|mingw|cy
6
6
 
7
7
  gemspec :name => 'openc3'
8
8
 
9
- # unless ENV['JENKINS_HOME']
10
- # # Example of how to use a local branch (doesn't work on Jenkins)
11
- # # You also need to set "bundle config local.mock_redis <LOCAL PATH TO CHECKED OUT GEM>"
12
- # # For example: bundle config local.mock_redis C:/_Programs/oss/mock_redis
13
- # # Make sure the local copy is checked out to the specified branch
14
- # # Delete the config: bundle config --delete local.mock_redis
15
- # group :development do
16
- # gem 'mock_redis', github: 'jasonatball/mock_redis', branch: 'master'
17
- # end
18
- # end
9
+ # Include the rails gems for the convenience of custom microservice plugins
10
+ gem 'rails', '~> 7.0.0'
11
+ gem 'bootsnap', '>= 1.9.3', require: false
12
+ gem 'rack-cors', '~> 1.1'
13
+ gem 'tzinfo-data'
data/bin/openc3cli CHANGED
@@ -43,6 +43,8 @@ require 'redis'
43
43
  require 'erb'
44
44
  require 'pp'
45
45
  # require 'psych' # Psych code is commented out
46
+ require "irb"
47
+ require "irb/completion"
46
48
 
47
49
  $redis_url = "redis://#{ENV['OPENC3_REDIS_HOSTNAME']}:#{ENV['OPENC3_REDIS_PORT']}"
48
50
  # Initialize the connection to the bucket library
@@ -64,13 +66,14 @@ def print_usage
64
66
  puts "Usage:"
65
67
  puts " cli help # Displays this information"
66
68
  puts " cli rake # Runs rake in the local directory"
69
+ puts " cli irb # Runs irb in the local directory"
67
70
  puts " cli validate /PATH/FILENAME.gem SCOPE variables.txt # Validate a COSMOS plugin gem file"
68
71
  puts " cli load /PATH/FILENAME.gem SCOPE variables.txt # Loads a COSMOS plugin gem file"
69
72
  puts " cli generate plugin PLUGIN_NAME # Generate a COSMOS plugin"
70
73
  puts " #{MIGRATE_PARSER}"
71
74
  puts " cli bridge CONFIG_FILENAME # Run COSMOS host bridge"
72
75
  puts " cli bridgesetup CONFIG_FILENAME # Create a default config file"
73
- puts " cli geminstall GEMFILENAME SCOPE # Install loaded gem to /gems"
76
+ puts " cli geminstall GEMFILENAME SCOPE # Install loaded gem to /gems"
74
77
  puts " cli rubysloc # Counts Ruby SLOC recursively. Run with --help for more info."
75
78
  puts " cli xtce_converter # Convert to and from the XTCE format. Run with --help for more info."
76
79
  puts " cli cstol_converter # Converts CSTOL files (.prc) to COSMOS. Run with --help for more info."
@@ -526,6 +529,10 @@ if not ARGV[0].nil? # argument(s) given
526
529
  # Handle each task
527
530
  case ARGV[0].downcase
528
531
 
532
+ when 'irb'
533
+ ARGV.clear
534
+ IRB.start
535
+
529
536
  when 'rake'
530
537
  puts `rake #{ARGV[1..-1].join(' ')}`
531
538
 
@@ -27,7 +27,8 @@ tcpip_client_interface.rb:
27
27
  - name: Protocol Type
28
28
  required: true
29
29
  description: Protocol to apply on the interface data
30
- values:
30
+ # prettier-ignore
31
+ values:
31
32
  <%= MetaConfigParser.load('protocols.yaml').to_meta_config_yaml(8) %>
32
33
  tcpip_server_interface.rb:
33
34
  parameters:
@@ -52,7 +53,8 @@ tcpip_server_interface.rb:
52
53
  - name: Protocol Type
53
54
  required: true
54
55
  description: Protocol to apply on the interface data
55
- values:
56
+ # prettier-ignore
57
+ values:
56
58
  <%= MetaConfigParser.load('protocols.yaml').to_meta_config_yaml(8) %>
57
59
  udp_interface.rb:
58
60
  description: The UDP interface uses UDP packets to send and receive telemetry
@@ -142,73 +144,6 @@ serial_interface.rb:
142
144
  - name: Protocol Type
143
145
  required: true
144
146
  description: Protocol to apply on the interface data
145
- values:
147
+ # prettier-ignore
148
+ values:
146
149
  <%= MetaConfigParser.load('protocols.yaml').to_meta_config_yaml(8) %>
147
- cmd_tlm_server_interface.rb:
148
- description: Provides a connection to the OpenC3 Command and Telemetry Server.
149
- This allows scripts and other OpenC3 tools to send commands to the CmdTlmServer
150
- to enable and disable logging. It also allows scripts and other tools to
151
- receive a OpenC3 version information packet and a limits change packet which
152
- is sent when any telemetry items change limits states. The CmdTlmServer
153
- interface can be used by any OpenC3 configuration.
154
- linc_interface.rb:
155
- description: The LINC interface uses a single TCPIP socket to talk to a Ball
156
- Aerospace LINC Labview target.
157
- parameters:
158
- - name: Host
159
- required: true
160
- description: Machine name to connect to. Can be either a named
161
- machine (DNS entry) or IP address.
162
- values: .+
163
- - name: Port
164
- required: true
165
- description: Port to write commands to and read telemetry from
166
- values: \d{2,5}
167
- - name: Handshake Enabled
168
- required: false
169
- description: Enable command handshaking where commands block until the
170
- corresponding handshake message is received. Default is true.
171
- values: ["true", "false"]
172
- - name: Response Timeout
173
- required: false
174
- description: Number of seconds to wait for a handshaking response.
175
- Default is 5 seconds
176
- values: \d+
177
- - name: Read Timeout
178
- required: true
179
- description: Number of seconds to wait before aborting the read.
180
- Pass 'nil' to block on read. Default is nil.
181
- values: .+
182
- - name: Write Timeout
183
- required: true
184
- description: Number of seconds to wait before aborting the write.
185
- Pass 'nil' to block on write. Default is 5 seconds.
186
- values: .+
187
- - name: Length Bit Offset
188
- required: false
189
- description: The bit offset of the length field. Every packet using this
190
- interface must have the same structure such that the length field is the
191
- same size at the same location. Default is 0.
192
- values: \d+
193
- - name: Length Bit Size
194
- required: false
195
- description: The size in bits of the length field. Default is 16 bits.
196
- values: \d+
197
- - name: Length Value Offset
198
- required: false
199
- description: The offset to apply to the length field value. For example if
200
- the length field indicates packet length minus one, this value should be one.
201
- Default is 4.
202
- values: \d+
203
- - name: GUID Fieldname
204
- required: false
205
- description: Fieldname of the GUID field. Default is 'HDR_GUID'.
206
- values: .+
207
- - name: Length Endianness
208
- required: false
209
- description: The endianness of the length field. Default is BIG_ENDIAN.
210
- values: ["BIG_ENDIAN", "LITTLE_ENDIAN"]
211
- - name: Length Fieldname
212
- required: false
213
- description: Fieldname of the length field. Defaults is 'HDR_LENGTH'.
214
- values: .+
@@ -41,29 +41,6 @@ DISABLE_DISCONNECT:
41
41
  Use this keyword to prevent the user from disconnecting from the interface.
42
42
  This is typically used in a 'production' environment where you would not want
43
43
  the user to inadvertantly disconnect from a target.
44
- LOG:
45
- summary: Enable logging on the interface by the specified log writer
46
- description:
47
- LOG is only required if you want a log writer other than the default
48
- to log commands and telemetry on this interface
49
- warning: Choosing a custom log writer can prevent OpenC3 from reading back your log files
50
- parameters:
51
- - name: Name
52
- required: true
53
- description: Log writer name as defined by PACKET_LOG_WRITER
54
- values: \D\S*
55
- LOG_STORED:
56
- summary: Enable logging of stored telemetry on the interface by the specified log writer
57
- description:
58
- LOG_STORED allows you to specify a different log writer for stored telemetry
59
- (telemetry which has the 'stored' flag set in the packet). By default the stored telemetry
60
- is intermingled in the normal log file.
61
- warning: Choosing a custom log writer can prevent OpenC3 from reading back your log files
62
- parameters:
63
- - name: Name
64
- required: true
65
- description: Log writer name as defined by PACKET_LOG_WRITER
66
- values: \D\S*
67
44
  DONT_LOG:
68
45
  summary: Disable logging commands and telemetry on this interface
69
46
  LOG_RAW:
@@ -106,3 +106,11 @@ MICROSERVICE:
106
106
  required: true
107
107
  description: Environment variable name or file path to store secret
108
108
  values: .*
109
+ ROUTE_PREFIX:
110
+ summary: Prefix of route
111
+ description: Prefix of route to the microservice to expose externally with Traefik
112
+ parameters:
113
+ - name: Route Prefix
114
+ required: true
115
+ description: Route prefix. Must be unique across all scopes. Something like /myprefix
116
+ values: .*
@@ -156,6 +156,7 @@ TARGET:
156
156
  values: \d+
157
157
  TARGET_MICROSERVICE:
158
158
  summary: Breaks a target microservice out into its own process.
159
+ description:
159
160
  Can be used to give more resources to processing that is falling behind.
160
161
  If defined multiple times for the same type, will create multiple processes.
161
162
  Each process can be given specific packets to process with the PACKET keyword.
@@ -162,26 +162,6 @@ TITLE:
162
162
  required: true
163
163
  description: Text to display above the horizontal line
164
164
  values: .*
165
- # SPACER:
166
- # summary: Inserts a spacer into a layout. This can be used to
167
- # separate or align other widgets.
168
- # parameters:
169
- # - name: Width
170
- # required: true
171
- # description: The width of the spacer in pixels.
172
- # values: .*
173
- # - name: Height
174
- # required: true
175
- # description: The height of the spacer in pixels.
176
- # values: .*
177
- # - name: Horizontal Policy
178
- # required: false
179
- # description: The horizontal size policy of the spacer. Default is MINIMUM.
180
- # values: <%= %w(FIXED MINIMUM MAXIMUM PREFERRED EXPANDING MINIMUMEXPANDING IGNORED) %>
181
- # - name: Vertical Policy
182
- # required: false
183
- # description: The vertical size policy of the spacer. Default is MINIMUM.
184
- # values: <%= %w(FIXED MINIMUM MAXIMUM PREFERRED EXPANDING MINIMUMEXPANDING IGNORED) %>
185
165
  ARRAY:
186
166
  summary: Displays ARRAY data organized into rows and space separated
187
167
  parameters:
@@ -303,7 +283,8 @@ BLOCK:
303
283
  # values: .*
304
284
  FORMATVALUE:
305
285
  summary: Displays a box with a formatted value
306
- description: Data is formatted by the specified string rather than by a format string given in
286
+ description:
287
+ Data is formatted by the specified string rather than by a format string given in
307
288
  the telemetry definition files. The white portion of the box darkens to gray
308
289
  while the value remains stagnant, then brightens to white each time the value
309
290
  changes. Additionally the value is colored based on the items limits state
@@ -615,7 +596,8 @@ LABELVALUERANGEBAR:
615
596
  # values: .*
616
597
  LED:
617
598
  summary: Displays a LED which changes color based on telemetry values
618
- description: By default TRUE is green and FALSE is red and all other values are black.
599
+ description:
600
+ By default TRUE is green and FALSE is red and all other values are black.
619
601
  Additional values can be added by using the LED_COLOR setting. For example
620
602
  LED INST PARAMS VALUE3 RAW can be followed by SETTING LED_COLOR 0 GREEN,
621
603
  SETTING LED_COLOR 1 RED, and SETTING LED_COLOR ANY ORANGE.
@@ -1153,7 +1135,8 @@ TEXTBOX:
1153
1135
  # values: .*
1154
1136
  VALUE:
1155
1137
  summary: Displays a box with a telemetry item value
1156
- description: The white portion of the box darkens to gray while the value remains stagnant, then
1138
+ description:
1139
+ The white portion of the box darkens to gray while the value remains stagnant, then
1157
1140
  brightens to white each time the value changes. Additionally the value is
1158
1141
  colored based on the items limits state (Red for example if it is out of limits).
1159
1142
  parameters:
@@ -37,6 +37,7 @@ module OpenC3
37
37
  'set_tlm',
38
38
  'inject_tlm',
39
39
  'override_tlm',
40
+ 'get_overrides',
40
41
  'normalize_tlm',
41
42
  'get_tlm_buffer',
42
43
  'get_tlm_packet',
@@ -169,6 +170,12 @@ module OpenC3
169
170
  CvtModel.override(target_name, packet_name, item_name, value, type: type.intern, scope: scope)
170
171
  end
171
172
 
173
+ # Get the list of CVT overrides
174
+ def get_overrides(scope: $openc3_scope, token: $openc3_token)
175
+ authorize(permission: 'tlm', scope: scope, token: token)
176
+ CvtModel.overrides(scope: scope)
177
+ end
178
+
172
179
  # Normalize a telemetry item in a packet to its default behavior. Called
173
180
  # after override_tlm to restore standard processing.
174
181
  #
@@ -394,7 +401,7 @@ module OpenC3
394
401
  return nil
395
402
  end
396
403
 
397
- def tlm_process_args(args, function_name, scope: $openc3_scope, token: $openc3_token)
404
+ def tlm_process_args(args, method_name, scope: $openc3_scope, token: $openc3_token)
398
405
  case args.length
399
406
  when 1
400
407
  target_name, packet_name, item_name = extract_fields_from_tlm_text(args[0])
@@ -404,7 +411,7 @@ module OpenC3
404
411
  item_name = args[2]
405
412
  else
406
413
  # Invalid number of arguments
407
- raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{function_name}()"
414
+ raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{method_name}()"
408
415
  end
409
416
  if packet_name == 'LATEST'
410
417
  latest = -1
@@ -429,7 +436,7 @@ module OpenC3
429
436
  return [target_name, packet_name, item_name]
430
437
  end
431
438
 
432
- def set_tlm_process_args(args, function_name, scope: $openc3_scope, token: $openc3_token)
439
+ def set_tlm_process_args(args, method_name, scope: $openc3_scope, token: $openc3_token)
433
440
  case args.length
434
441
  when 1
435
442
  target_name, packet_name, item_name, value = extract_fields_from_set_tlm_text(args[0])
@@ -440,7 +447,7 @@ module OpenC3
440
447
  value = args[3]
441
448
  else
442
449
  # Invalid number of arguments
443
- raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{function_name}()"
450
+ raise "ERROR: Invalid number of arguments (#{args.length}) passed to #{method_name}()"
444
451
  end
445
452
  # Determine if this item exists, it will raise appropriate errors if not
446
453
  TargetModel.packet_item(target_name, packet_name, item_name, scope: scope)
@@ -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/packets/binary_accessor'
@@ -28,7 +28,7 @@ class String
28
28
  # The printable range of ASCII characters
29
29
  PRINTABLE_RANGE = 32..126
30
30
  # Regular expression to identify a character that is not in the printable range
31
- NON_PRINTABLE_REGEX = /[^\s -~]/
31
+ NON_PRINTABLE_REGEX = /[^\s!-~]/
32
32
  # Regular expression to identify a String as a floating point number
33
33
  FLOAT_CHECK_REGEX = /\A\s*[-+]?\d*\.\d+\s*\z/
34
34
  # Regular expression to identify a String as a floating point number in
@@ -56,11 +56,15 @@ end
56
56
 
57
57
  class String
58
58
  NON_ASCII_PRINTABLE = /[^\x21-\x7e\s]/
59
-
59
+ NON_UTF8_PRINTABLE = /[\x00-\x08\x0E-\x1F\x7F]/
60
60
  def as_json(options = nil)
61
61
  as_utf8 = self.dup.force_encoding('UTF-8')
62
62
  if as_utf8.valid_encoding?
63
- return as_utf8
63
+ if as_utf8 =~ NON_UTF8_PRINTABLE
64
+ return self.to_json_raw_object
65
+ else
66
+ return as_utf8
67
+ end
64
68
  else
65
69
  return self.to_json_raw_object
66
70
  end
@@ -362,14 +362,18 @@ module OpenC3
362
362
  @interface.tlm_target_names.each do |target_name|
363
363
  # Initialize the target's packet counters based on the Topic stream
364
364
  # Prevents packet count resetting to 0 when interface restarts
365
- System.telemetry.packets(target_name).each do |packet_name, packet|
366
- topic = "#{@scope}__TELEMETRY__{#{target_name}}__#{packet_name}"
367
- msg_id, msg_hash = Topic.get_newest_message(topic)
368
- if msg_id
369
- packet.received_count = msg_hash['received_count'].to_i
370
- else
371
- packet.received_count = 0
365
+ begin
366
+ System.telemetry.packets(target_name).each do |packet_name, packet|
367
+ topic = "#{@scope}__TELEMETRY__{#{target_name}}__#{packet_name}"
368
+ msg_id, msg_hash = Topic.get_newest_message(topic)
369
+ if msg_id
370
+ packet.received_count = msg_hash['received_count'].to_i
371
+ else
372
+ packet.received_count = 0
373
+ end
372
374
  end
375
+ rescue
376
+ # Handle targets without telemetry
373
377
  end
374
378
  end
375
379
  if @interface.connect_on_startup
@@ -649,15 +653,17 @@ module OpenC3
649
653
  # Need to make sure that @cancel_thread is set and the interface disconnected within
650
654
  # mutex to ensure that connect() is not called when we want to stop()
651
655
  @cancel_thread = true
652
- @handler_thread.stop
653
- @interface_thread_sleeper.cancel
654
- @interface.disconnect
655
- if @interface_or_router == 'INTERFACE'
656
- valid_interface = InterfaceStatusModel.get_model(name: @interface.name, scope: @scope)
657
- else
658
- valid_interface = RouterStatusModel.get_model(name: @interface.name, scope: @scope)
656
+ @handler_thread.stop if @handler_thread
657
+ @interface_thread_sleeper.cancel if @interface_thread_sleeper
658
+ if @interface
659
+ @interface.disconnect
660
+ if @interface_or_router == 'INTERFACE'
661
+ valid_interface = InterfaceStatusModel.get_model(name: @interface.name, scope: @scope)
662
+ else
663
+ valid_interface = RouterStatusModel.get_model(name: @interface.name, scope: @scope)
664
+ end
665
+ valid_interface.destroy if valid_interface
659
666
  end
660
- valid_interface.destroy if valid_interface
661
667
  end
662
668
  end
663
669
 
@@ -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/microservices/microservice'
@@ -31,6 +31,15 @@ module OpenC3
31
31
 
32
32
  def run
33
33
  Dir.chdir @work_dir
34
+ begin
35
+ if @config["cmd"][0] != 'ruby'
36
+ # Try to make sure the cmd is executable
37
+ FileUtils.chmod 0777, @config["cmd"][0]
38
+ end
39
+ rescue Exception
40
+ # Its ok if this fails
41
+ end
42
+
34
43
  # Fortify: Process Control
35
44
  # This is dangerous! However, plugins need to be able to run whatever they want.
36
45
  # Only admins can install plugins and they need to be vetted for content.
@@ -21,6 +21,7 @@
21
21
  # if purchased from OpenC3, Inc.
22
22
 
23
23
  require 'openc3/utilities/store'
24
+ require 'openc3/models/target_model'
24
25
 
25
26
  module OpenC3
26
27
  class CvtModel
@@ -41,22 +42,24 @@ module OpenC3
41
42
 
42
43
  # Set an item in the current value table
43
44
  def self.set_item(target_name, packet_name, item_name, value, type:, scope: $openc3_scope)
45
+ hash = JSON.parse(Store.hget("#{scope}__tlm__#{target_name}", packet_name), :allow_nan => true, :create_additions => true)
44
46
  case type
45
47
  when :WITH_UNITS
46
- field = "#{item_name}__U"
47
- value = value.to_s # WITH_UNITS should always be a string
48
+ hash["#{item_name}__U"] = value.to_s # WITH_UNITS should always be a string
48
49
  when :FORMATTED
49
- field = "#{item_name}__F"
50
- value = value.to_s # FORMATTED should always be a string
50
+ hash["#{item_name}__F"] = value.to_s # FORMATTED should always be a string
51
51
  when :CONVERTED
52
- field = "#{item_name}__C"
52
+ hash["#{item_name}__C"] = value
53
53
  when :RAW
54
- field = item_name
54
+ hash[item_name] = value
55
+ when :ALL
56
+ hash["#{item_name}__U"] = value.to_s # WITH_UNITS should always be a string
57
+ hash["#{item_name}__F"] = value.to_s # FORMATTED should always be a string
58
+ hash["#{item_name}__C"] = value
59
+ hash[item_name] = value
55
60
  else
56
61
  raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
57
62
  end
58
- hash = JSON.parse(Store.hget("#{scope}__tlm__#{target_name}", packet_name), :allow_nan => true, :create_additions => true)
59
- hash[field] = value
60
63
  Store.hset("#{scope}__tlm__#{target_name}", packet_name, JSON.generate(hash.as_json(:allow_nan => true)))
61
64
  end
62
65
 
@@ -144,6 +147,38 @@ module OpenC3
144
147
  results
145
148
  end
146
149
 
150
+ # Return all the overrides
151
+ def self.overrides(scope: $openc3_scope)
152
+ overrides = []
153
+ TargetModel.names(scope: scope).each do |target_name|
154
+ all = Store.hgetall("#{scope}__override__#{target_name}")
155
+ next if all.nil? or all.empty?
156
+ all.each do |packet_name, hash|
157
+ items = JSON.parse(hash, :allow_nan => true, :create_additions => true)
158
+ items.each do |key, value|
159
+ item = {}
160
+ item['target_name'] = target_name
161
+ item['packet_name'] = packet_name
162
+ item_name, value_type_key = key.split('__')
163
+ item['item_name'] = item_name
164
+ case value_type_key
165
+ when 'U'
166
+ item['value_type'] = 'WITH_UNITS'
167
+ when 'F'
168
+ item['value_type'] = 'FORMATTED'
169
+ when 'C'
170
+ item['value_type'] = 'CONVERTED'
171
+ else
172
+ item['value_type'] = 'RAW'
173
+ end
174
+ item['value'] = value
175
+ overrides << item
176
+ end
177
+ end
178
+ end
179
+ overrides
180
+ end
181
+
147
182
  # Override a current value table item such that it always returns the same value
148
183
  # for the given type
149
184
  def self.override(target_name, packet_name, item_name, value, type: :ALL, scope: $openc3_scope)
@@ -69,7 +69,7 @@ module OpenC3
69
69
  if @color.nil?
70
70
  @color = '#%06x' % (rand * 0xffffff)
71
71
  end
72
- unless @color =~ /(#*)([0-9,a-f,A-f]{6})/
72
+ unless @color =~ /(#*)([0-9,a-f,A-F]{6})/
73
73
  raise SortedInputError.new "invalid color, must be in hex format, e.g. #FF0000"
74
74
  end
75
75
  @color = "##{@color}" unless @color.start_with?('#')
@@ -23,6 +23,7 @@
23
23
  require 'openc3/top_level'
24
24
  require 'openc3/models/model'
25
25
  require 'openc3/models/metric_model'
26
+ require 'openc3/models/traefik_model'
26
27
  require 'openc3/utilities/bucket'
27
28
 
28
29
  module OpenC3
@@ -41,6 +42,7 @@ module OpenC3
41
42
  attr_accessor :ports
42
43
  attr_accessor :parent
43
44
  attr_accessor :secrets
45
+ attr_accessor :prefix
44
46
 
45
47
  # NOTE: The following three class methods are used by the ModelController
46
48
  # and are reimplemented to enable various Model class methods to work
@@ -99,6 +101,7 @@ module OpenC3
99
101
  plugin: nil,
100
102
  needs_dependencies: false,
101
103
  secrets: [],
104
+ prefix: nil,
102
105
  scope:
103
106
  )
104
107
  parts = name.split("__")
@@ -122,6 +125,7 @@ module OpenC3
122
125
  @container = container
123
126
  @needs_dependencies = needs_dependencies
124
127
  @secrets = secrets
128
+ @prefix = prefix
125
129
  @bucket = Bucket.getClient()
126
130
  end
127
131
 
@@ -141,7 +145,8 @@ module OpenC3
141
145
  'updated_at' => @updated_at,
142
146
  'plugin' => @plugin,
143
147
  'needs_dependencies' => @needs_dependencies,
144
- 'secrets' => @secrets.as_json(*a)
148
+ 'secrets' => @secrets.as_json(*a),
149
+ 'prefix' => @prefix
145
150
  }
146
151
  end
147
152
 
@@ -190,6 +195,9 @@ module OpenC3
190
195
  when 'SECRET'
191
196
  parser.verify_num_parameters(3, 3, "#{keyword} <Secret Type: ENV or FILE> <Secret Name> <Environment Variable Name or File Path>")
192
197
  @secrets << parameters.dup
198
+ when 'ROUTE_PREFIX'
199
+ parser.verify_num_parameters(1, 1, "#{keyword} <Route Prefix>")
200
+ @prefix = parameters[0]
193
201
  else
194
202
  raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Microservice: #{keyword} #{parameters.join(" ")}")
195
203
  end
@@ -214,9 +222,12 @@ module OpenC3
214
222
  end
215
223
  unless validate_only
216
224
  @bucket.put_object(bucket: ENV['OPENC3_CONFIG_BUCKET'], key: key, body: data)
217
- ConfigTopic.write({ kind: 'created', type: 'microservice', name: @name, plugin: @plugin }, scope: @scope)
218
225
  end
219
226
  end
227
+ unless validate_only
228
+ TraefikModel.register_route(microservice_name: @name, port: @ports[0][0], prefix: @prefix) if @ports[0] and ports[0][0] and @prefix
229
+ ConfigTopic.write({ kind: 'created', type: 'microservice', name: @name, plugin: @plugin }, scope: @scope)
230
+ end
220
231
  end
221
232
 
222
233
  def undeploy
@@ -224,6 +235,7 @@ module OpenC3
224
235
  @bucket.list_objects(bucket: ENV['OPENC3_CONFIG_BUCKET'], prefix: prefix).each do |object|
225
236
  @bucket.delete_object(bucket: ENV['OPENC3_CONFIG_BUCKET'], key: object.key)
226
237
  end
238
+ TraefikModel.unregister_route(microservice_name: @name, port: @ports[0][0], prefix: @prefix) if @ports[0] and ports[0][0] and @prefix
227
239
  ConfigTopic.write({ kind: 'deleted', type: 'microservice', name: @name, plugin: @plugin }, scope: @scope)
228
240
  rescue Exception => error
229
241
  Logger.error("Error undeploying microservice model #{@name} in scope #{@scope} due to #{error}")
@@ -63,20 +63,12 @@ module OpenC3
63
63
  # END NOTE
64
64
 
65
65
  # Loops over all items and returns objects that match a key value pair
66
- def self.filter(key, value, scope:, use_regex: false)
66
+ def self.filter(key, value, scope:, substr: false)
67
67
  filtered = {}
68
68
  results = all(scope: scope)
69
- regex = nil
70
- regex = Regexp.new(value) if use_regex
71
69
  results.each do |name, result|
72
- if regex
73
- if result[key] =~ regex
74
- filtered[name] = result
75
- end
76
- else
77
- if result[key] == value
78
- filtered[name] = result
79
- end
70
+ if result[key] == value || (substr && result[key].include?(value))
71
+ filtered[name] = result
80
72
  end
81
73
  end
82
74
  return filtered
@@ -78,7 +78,7 @@ module OpenC3
78
78
  if @color.nil?
79
79
  @color = '#%06x' % (rand * 0xffffff)
80
80
  end
81
- unless @color =~ /(#*)([0-9,a-f,A-f]{6})/
81
+ unless @color =~ /(#*)([0-9,a-f,A-F]{6})/
82
82
  raise SortedInputError.new "invalid color, must be in hex format, e.g. #FF0000"
83
83
  end
84
84
  @color = "##{@color}" unless @color.start_with?('#')
@@ -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'
@@ -91,11 +91,10 @@ module OpenC3
91
91
  if color.nil?
92
92
  color = '#%06x' % (rand * 0xffffff)
93
93
  end
94
- valid_color = color =~ /(#*)([0-9,a-f,A-f]{6})/
94
+ valid_color = color =~ /[0-9,a-f,A-F]{6}/
95
95
  if valid_color.nil?
96
96
  raise RuntimeError.new "invalid color but in hex format. #FF0000"
97
97
  end
98
-
99
98
  unless color.start_with?('#')
100
99
  color = "##{color}"
101
100
  end