openc3 5.6.0 → 5.7.0

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: 9de820bd93122cc0e11533c3d875e3d6babce9247128f9a63fe3ad6e75b6d196
4
- data.tar.gz: 293cf85c989666a805a3dec9125ba35692548c27910a09aff871f3c4c523fe7b
3
+ metadata.gz: 9233a93be94c8a50cf561413812f9ae718edb25838cefe5fedf6bcb6efdd5ade
4
+ data.tar.gz: 9a7a7e09b815c0f5c077c9987dadad5da1fcd986f7bf6c3db213b528ff2a293a
5
5
  SHA512:
6
- metadata.gz: 26a29caa9cd9a211959587b54c76c389dbb70390d573587972a52938c9a3c8ccfcbd702d52f942b37f89133bf76048018ef569a9dcd6ff1990b9030ba62d9208
7
- data.tar.gz: c8dce98075822016cfe3c10624b2e54f174d32b87fda748eb04d43031a89535538d8746f1da0945201f9a8b614499c961bcf3bc61fd03973999dfccae122ceb3
6
+ metadata.gz: 86bdc47e5dec0e3ca71de24ae2e4ce4e2fca4824696f214d37bacbbff1f914380e50e414ac270c6b52f64d965bf8eaa2ca22733993df261c42510480731b66ff
7
+ data.tar.gz: 8e813eb9fb74aae5da6ffd11e196e974be2e9ca9718e7a6ef08eedba8668078f3ea18bd9968f431ec7562de7772888f28e4e05e366f4226a808225571b447574
data/Gemfile CHANGED
@@ -11,3 +11,7 @@ gem 'rails', '~> 7.0.0'
11
11
  gem 'bootsnap', '>= 1.9.3', require: false
12
12
  gem 'rack-cors', '~> 1.1'
13
13
  gem 'tzinfo-data'
14
+ gem 'rspec-rails', '~> 6.0'
15
+ gem 'simplecov', '~> 0.20'
16
+ gem 'simplecov-cobertura', '~> 2.1'
17
+ gem 'mock_redis'
data/bin/openc3cli CHANGED
@@ -141,18 +141,21 @@ def migrate(args)
141
141
 
142
142
  # Overwrite plugin.txt with specified targets
143
143
  plugin = File.open('plugin.txt', 'w')
144
- plugin.puts "TARGET #{target_name}"
145
-
144
+ FileUtils.mkdir 'targets'
146
145
  args.each do |target|
147
146
  puts "Migrating target #{target}"
148
147
  FileUtils.cp_r "../config/targets/#{target}", 'targets'
149
- plugin.puts "TARGET #{target}"
148
+ plugin.puts "TARGET #{target} #{target}"
150
149
  end
151
150
  plugin.puts ""
152
151
 
153
- puts "Migrating /lib & /procedures to #{target_name}"
154
- FileUtils.cp_r '../lib', "targets/#{target_name}"
155
- FileUtils.cp_r '../procedures', "targets/#{target_name}"
152
+ files = Dir.glob('../lib/*')
153
+ files.concat(Dir.glob('../procedures/*'))
154
+ unless files.empty?
155
+ puts "Migrating /lib & /procedures to PROCEDURES target"
156
+ FileUtils.cp_r '../lib', "targets/PROCEDURES"
157
+ FileUtils.cp_r '../procedures', "targets/PROCEDURES"
158
+ end
156
159
 
157
160
  # Migrate cmd_tlm_server.txt info to plugin.txt
158
161
  Dir.glob('targets/**/cmd_tlm_server*.txt') do |file|
@@ -168,6 +171,36 @@ def migrate(args)
168
171
  end
169
172
  plugin.puts ''
170
173
  end
174
+
175
+ # Migrate target.txt
176
+ Dir.glob('targets/**/target.txt') do |filename|
177
+ file = File.read(filename)
178
+ file.gsub!('LOG_RAW', 'LOG_STREAM')
179
+ file.gsub!('AUTO_SCREEN_SUBSTITUTE', '')
180
+ File.write(filename, file)
181
+ end
182
+
183
+ # Migrate some of the screens api
184
+ Dir.glob('targets/**/screens/*') do |file|
185
+ screen = File.read(file)
186
+ screen.gsub!('cmd(', 'api.cmd(')
187
+ screen.gsub!('cmd_no_checks(', 'api.cmd_no_checks(')
188
+ screen.gsub!('cmd_no_range_check(', 'api.cmd_no_range_check(')
189
+ screen.gsub!('cmd_no_hazardous_check(', 'api.cmd_no_hazardous_check(')
190
+ screen.gsub!('get_named_widget(', 'screen.getNamedWidget(')
191
+ lines = screen.split("\n")
192
+ lines.map! do |line|
193
+ if line.include?('Qt.')
194
+ line = "# FIXME (no Qt): #{line.sub("<%", "< %").sub("%>", "% >")}"
195
+ elsif line.include?('Cosmos::')
196
+ line = "# FIXME (no Cosmos::): #{line.sub("<%", "< %").sub("%>", "% >")}"
197
+ else
198
+ line
199
+ end
200
+ end
201
+ File.write(file, lines.join("\n"))
202
+ end
203
+
171
204
  plugin.close
172
205
  puts "Plugin complete: #{File.expand_path('.')}" # Remember we're inside the plugin dir
173
206
  end
@@ -168,3 +168,74 @@ SECRET:
168
168
  example: |
169
169
  SECRET ENV USERNAME ENV_USERNAME USERNAME
170
170
  SECRET FILE KEY "/tmp/DATA/cert" KEY
171
+ ENV:
172
+ summary: Sets an environment variable in the microservice.
173
+ since: 5.7.0
174
+ parameters:
175
+ - name: Key
176
+ required: true
177
+ description: Environment variable name
178
+ values: .+
179
+ - name: Value
180
+ required: true
181
+ description: Environment variable value
182
+ values: .+
183
+ example: |
184
+ ENV COMPANY OpenC3
185
+ WORK_DIR:
186
+ summary: Set the working directory
187
+ description: Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in.
188
+ since: 5.7.0
189
+ parameters:
190
+ - name: Directory
191
+ required: true
192
+ description: Working directory to run the microservice CMD in. Can be a path relative to the microservice folder in the plugin, or an absolute path in the container the microservice runs in.
193
+ values: .+
194
+ example: |
195
+ WORK_DIR '/openc3/lib/openc3/microservices'
196
+ PORT:
197
+ summary: Open port for the microservice
198
+ description: Kubernetes needs a Service to be applied to open a port so this is required for Kubernetes support
199
+ since: 5.7.0
200
+ parameters:
201
+ - name: Number
202
+ required: true
203
+ description: Port number
204
+ values: \d+
205
+ - name: Protocol
206
+ required: false
207
+ description: Port protocol. Default is TCP.
208
+ values: .+
209
+ example: |
210
+ PORT 7272
211
+ CMD:
212
+ summary: Command line to execute to run the microservice.
213
+ description: Command line to execute to run the microservice.
214
+ since: 5.7.0
215
+ parameters:
216
+ - name: Args
217
+ required: true
218
+ description: One or more arguments to exec to run the microservice.
219
+ values: .+
220
+ example: |
221
+ CMD ruby interface_microservice.rb DEFAULT__INTERFACE__INT1
222
+ CONTAINER:
223
+ summary: Docker Container
224
+ description: Container to execute and run the microservice in. Only used in COSMOS Enterprise Edition.
225
+ since: 5.7.0
226
+ parameters:
227
+ - name: Args
228
+ required: false
229
+ description: Name of the container
230
+ values: .+
231
+ ROUTE_PREFIX:
232
+ summary: Prefix of route
233
+ description: Prefix of route to the microservice to expose externally with Traefik
234
+ since: 5.7.0
235
+ parameters:
236
+ - name: Route Prefix
237
+ required: true
238
+ description: Route prefix. Must be unique across all scopes. Something like /myprefix
239
+ values: .*
240
+ example: |
241
+ ROUTE_PREFIX /interface
@@ -288,3 +288,49 @@ TEMPLATE:
288
288
  or response timeouts. 'DISCONNECT' to disconnect after errors. The default
289
289
  is 'LOG' to log an error and continue.
290
290
  values: ["LOG", "DISCONNECT"]
291
+ SLIP:
292
+ description:
293
+ The SLIP Protocol implements RFC 1055. This is a terminated protocol which terminates
294
+ with a 0xC0 character, and escapes internally conflicting bytes.
295
+ parameters:
296
+ - name: Start Character
297
+ required: false
298
+ description:
299
+ Character to place at the beginning of a packet. Defaults to nil. Some variants of the
300
+ SLIP Protocol also place a 0xC0 byte at the beginning of packets.
301
+ values: \d+
302
+ - name: Read Strip Characters
303
+ required: false
304
+ description:
305
+ Whether or not to strip the start and end characters out of the packet when reading. Defaults
306
+ to true.
307
+ values: ["true", "false"]
308
+ - name: Read Enable Escaping
309
+ required: false
310
+ description: Whether or not to escape conflicting characters in the packet om reads. Defaults to true.
311
+ values: ["true", "false"]
312
+ - name: Write Enable Escaping
313
+ required: false
314
+ description: Whether or not to escape conflicting characters in the packet on writes. Defaults to true.
315
+ values: ["true", "false"]
316
+ - name: End Character
317
+ required: false
318
+ description: Character to end packets with. Defaults to 0xC0.
319
+ values: \d+
320
+ - name: Escape Character
321
+ required: false
322
+ description: Character that indicates an escape sequence. Defaults to 0xDB.
323
+ values: \d+
324
+ - name: Escaped End Character
325
+ required: false
326
+ description: Escaped version of the end character. Defaults to 0xDC.
327
+ values: \d+
328
+ - name: Escaped Escape Character
329
+ required: false
330
+ description: Escaped version of the escape character. Defaults to 0xDD.
331
+ values: \d+
332
+ COBS:
333
+ description:
334
+ The COBS Protocol implements the Consistent Overhead Byte Stuffing Protocol. This is a terminated protocol which terminates
335
+ with a 0x00 character, and escapes internal 0's using a unique algorithm that only adds one byte of overhead for every
336
+ 254 bytes.
@@ -492,6 +492,7 @@ module OpenC3
492
492
  end
493
493
  @protocol_info << [protocol_class, protocol_args, read_write]
494
494
  protocol.interface = self
495
+ return protocol
495
496
  end
496
497
 
497
498
  def interface_cmd(cmd_name, *cmd_args)
@@ -0,0 +1,120 @@
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/interfaces/protocols/terminated_protocol'
20
+ require 'openc3/config/config_parser'
21
+
22
+ # This file implements the COBS protocol as here:
23
+ # https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
24
+ # http://www.stuartcheshire.org/papers/COBSforToN.pdf
25
+
26
+ # COBS is a framing protocol and is therefore expected to be used for packet deliniation
27
+
28
+ module OpenC3
29
+
30
+ # Usage in plugin.txt:
31
+ #
32
+ # INTERFACE ...
33
+ # PROTOCOL READ_WRITE CobsProtocol
34
+
35
+ class CobsProtocol < TerminatedProtocol
36
+
37
+ # @param allow_empty_data [true/false/nil] See Protocol#initialize
38
+ def initialize(allow_empty_data = nil)
39
+
40
+ strip_read_termination = true
41
+ discard_leading_bytes = 0
42
+ sync_pattern = nil
43
+ fill_fields = false # Handled in write_data below
44
+
45
+ super(
46
+ "", # Write termination handled in write_data below
47
+ "00",
48
+ strip_read_termination,
49
+ discard_leading_bytes,
50
+ sync_pattern,
51
+ fill_fields,
52
+ allow_empty_data
53
+ )
54
+ end
55
+
56
+ def read_data(data)
57
+ data = super(data)
58
+ return data if data.length <= 0 or Symbol === data
59
+
60
+ result_data = ''
61
+ while data.length > 1
62
+ # Read the offset to the next zero byte
63
+ # Note: This may be off the end of the data. If so, the packet is over
64
+ zero_offset = data[0].unpack('C')[0]
65
+ if zero_offset == 0xFF # No zeros in this segment
66
+ result_data << data[1..254]
67
+ data = data[255..-1]
68
+ elsif zero_offset <= 1 # End of data or 1 zero
69
+ result_data << "\x00"
70
+ data = data[1..-1]
71
+ else # Mid range zero or end of packet
72
+ result_data << data[1..(zero_offset - 1)]
73
+ data = data[zero_offset..-1]
74
+ result_data << "\x00" if data.length >= 1
75
+ end
76
+ end
77
+
78
+ return result_data
79
+ end
80
+
81
+ def write_data(data)
82
+ # Intentionally not calling super()
83
+
84
+ need_insert = false
85
+ result_data = ''
86
+ while data.length > 0
87
+ index = data.index("\x00")
88
+ if (index and index > 253) or (index.nil? and data.length >= 254)
89
+ result_data << "\xFF"
90
+ result_data << data[0..253]
91
+ data = data[254..-1]
92
+ need_insert = false
93
+ else # index <= 254 or (index.nil? and data.length < 254)
94
+ if index
95
+ result_data << [index + 1].pack('C')
96
+ if index >= 1
97
+ result_data << data[0..(index - 1)]
98
+ end
99
+ data = data[(index + 1)..-1]
100
+ need_insert = true
101
+ else
102
+ result_data << [data.length + 1].pack('C')
103
+ result_data << data
104
+ data = ''
105
+ need_insert = false
106
+ end
107
+ end
108
+ end
109
+
110
+ # Handle a zero at the end of the packet
111
+ result_data << "\x01" if need_insert
112
+
113
+ # Terminate message with 0x00
114
+ result_data << "\x00"
115
+
116
+ return result_data
117
+ end
118
+ end
119
+
120
+ end
@@ -0,0 +1,150 @@
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/interfaces/protocols/terminated_protocol'
20
+ require 'openc3/config/config_parser'
21
+
22
+ # This file implements the SLIP protocol as documented in RFC 1055
23
+ # https://datatracker.ietf.org/doc/html/rfc1055
24
+
25
+ # SLIP is a framing protocol and is therefore expected to be used for packet deliniation
26
+
27
+ module OpenC3
28
+
29
+ # Usage in plugin.txt:
30
+ #
31
+ # INTERFACE ...
32
+ # PROTOCOL READ_WRITE SlipProtocol
33
+
34
+ class SlipProtocol < TerminatedProtocol
35
+
36
+ # Note: Characters are expected to be given as integers
37
+ # @param start_char [Integer/nil] Character to place at the start of frames (Defaults to nil)
38
+ # @param read_strip_characters [true/false] Strip off start_char and end_char from reads
39
+ # @param read_enable_escaping [true/false] Whether to enable or disable character escaping on reads
40
+ # @param write_enable_escaping [true/false] Whether to enable or disable character escaping on writes
41
+ # @param end_char [Integer] Character to place at the end of frames (Defaults to 0xC0)
42
+ # @param esc_char [Integer] Escape character (Defaults to 0xDB)
43
+ # @param esc_end_char [Integer] Character to Escape End character (Defaults to 0xDC)
44
+ # @param esc_esc_char [Integer] Character to Escape Escape character (Defaults to 0xDD)
45
+ # @param allow_empty_data [true/false/nil] See Protocol#initialize
46
+ def initialize(
47
+ start_char = nil,
48
+ read_strip_characters = true,
49
+ read_enable_escaping = true,
50
+ write_enable_escaping = true,
51
+ end_char = 0xC0,
52
+ esc_char = 0xDB,
53
+ esc_end_char = 0xDC,
54
+ esc_esc_char = 0xDD,
55
+ allow_empty_data = nil)
56
+
57
+ @start_char = ConfigParser.handle_nil(start_char)
58
+ @start_char = [Integer(end_char)].pack('C') if @start_char
59
+ @end_char = [Integer(end_char)].pack('C')
60
+ @esc_char = [Integer(esc_char)].pack('C')
61
+ @esc_end_char = [Integer(esc_end_char)].pack('C')
62
+ @esc_esc_char = [Integer(esc_esc_char)].pack('C')
63
+ @replace_end = @esc_char + @esc_end_char
64
+ @replace_esc = @esc_char + @esc_esc_char
65
+ @read_strip_characters = ConfigParser.handle_true_false(read_strip_characters)
66
+ raise "read_strip_characters must be true or false" if @read_strip_characters != true and @read_strip_characters != false
67
+ @read_enable_escaping = ConfigParser.handle_true_false(read_enable_escaping)
68
+ raise "read_enable_escaping must be true or false" if @read_enable_escaping != true and @read_enable_escaping != false
69
+ @write_enable_escaping = ConfigParser.handle_true_false(write_enable_escaping)
70
+ raise "write_enable_escaping must be true or false" if @write_enable_escaping != true and @write_enable_escaping != false
71
+
72
+ strip_read_termination = false
73
+ discard_leading_bytes = 0
74
+ if @start_char
75
+ sync_pattern = sprintf("%0X", Integer(start_char))
76
+ else
77
+ sync_pattern = nil
78
+ end
79
+ fill_fields = false # Handled in write_data below
80
+
81
+ super(
82
+ "", # Write termination handled in write_data below
83
+ sprintf("%0X", Integer(end_char)), # Expects Hex Character String
84
+ strip_read_termination,
85
+ discard_leading_bytes,
86
+ sync_pattern,
87
+ fill_fields,
88
+ allow_empty_data
89
+ )
90
+ end
91
+
92
+ def read_data(data)
93
+ data = super(data)
94
+ return data if data.length <= 0 or Symbol === data
95
+
96
+ if @read_strip_characters
97
+ if @start_char
98
+ data = data[1..-1]
99
+ end
100
+ data = data[0..-2]
101
+ end
102
+
103
+ if @read_enable_escaping
104
+ data = data.gsub(@replace_end, @end_char).gsub(@replace_esc, @esc_char)
105
+ end
106
+
107
+ return data
108
+ end
109
+
110
+ def write_data(data)
111
+ # Intentionally not calling super()
112
+
113
+ if @write_enable_escaping
114
+ data = data.gsub(@esc_char, @replace_esc).gsub(@end_char, @replace_end)
115
+ end
116
+
117
+ if @start_char
118
+ data = @start_char + data
119
+ end
120
+
121
+ data << @end_char
122
+
123
+ return data
124
+ end
125
+
126
+ def reduce_to_single_packet
127
+ return :STOP if @data.length <= 0
128
+ if @start_char
129
+ index = @data[1..-1].index(@read_termination_characters)
130
+ index = index + 1 if index
131
+ else
132
+ index = @data.index(@read_termination_characters)
133
+ end
134
+
135
+ # Reduce to packet data and setup current_data for next packet
136
+ if index
137
+ if index > 0
138
+ packet_data = @data[0..(index + @read_termination_characters.length - 1)]
139
+ else # @data begins with the termination characters
140
+ packet_data = @data[0..(@read_termination_characters.length - 1)]
141
+ end
142
+ @data.replace(@data[(index + @read_termination_characters.length)..-1])
143
+ return packet_data
144
+ else
145
+ return :STOP
146
+ end
147
+ end
148
+ end
149
+
150
+ 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/config/config_parser'
@@ -52,6 +52,7 @@ module OpenC3
52
52
  @write_termination_characters = write_termination_characters.hex_to_byte_string
53
53
  @read_termination_characters = read_termination_characters.hex_to_byte_string
54
54
  @strip_read_termination = ConfigParser.handle_true_false(strip_read_termination)
55
+ raise "strip_read_termination must be true or false" if @strip_read_termination != true and @strip_read_termination != false
55
56
 
56
57
  super(discard_leading_bytes, sync_pattern, fill_fields, allow_empty_data)
57
58
  end
@@ -65,7 +65,7 @@ module OpenC3
65
65
 
66
66
  def _request(*method_params, **kw_params)
67
67
  kw_params[:scope] = $openc3_scope unless kw_params[:scope]
68
- kw_params[:json] => true unless kw_params[:json]
68
+ kw_params[:json] = true unless kw_params[:json]
69
69
  @json_api.request(*method_params, **kw_params)
70
70
  end
71
71
  end
@@ -33,7 +33,6 @@ module OpenC3
33
33
  packet.write(name.to_s, value, type)
34
34
  end
35
35
  end
36
- topic = "#{@scope}__TELEMETRY__{#{target_name}}__#{packet_name}"
37
36
  packet.received_count += 1
38
37
  packet.received_time = Time.now.sys
39
38
  TelemetryTopic.write_packet(packet, scope: @scope)
@@ -2,10 +2,11 @@ require 'openc3/utilities/migration'
2
2
  require 'openc3/models/scope_model'
3
3
 
4
4
  module OpenC3
5
- class LogStream < Migration
5
+ class LogStuff < Migration
6
6
  def self.run
7
7
  ScopeModel.names.each do |scope|
8
8
  # Get all existing InterfaceModels and change json for log_raw to log_stream
9
+ # Also remove the log key
9
10
  interface_models = InterfaceModel.all(scope: scope)
10
11
  interface_models.each do |key, model_hash|
11
12
  if model_hash.has_key?('log_raw')
@@ -14,6 +15,9 @@ module OpenC3
14
15
  else
15
16
  model_hash['log_stream'] = nil
16
17
  end
18
+ if model_hash.has_key?('log')
19
+ model_hash.delete('log')
20
+ end
17
21
  model_hash.delete('log_raw')
18
22
  InterfaceModel.from_json(model_hash, scope: scope).update
19
23
  end
@@ -26,6 +30,9 @@ module OpenC3
26
30
  else
27
31
  model_hash['log_stream'] = nil
28
32
  end
33
+ if model_hash.has_key?('log')
34
+ model_hash.delete('log')
35
+ end
29
36
  model_hash.delete('log_raw')
30
37
  RouterModel.from_json(model_hash, scope: scope).update
31
38
  end
@@ -36,5 +43,5 @@ module OpenC3
36
43
  end
37
44
 
38
45
  unless ENV['OPENC3_NO_MIGRATE']
39
- OpenC3::LogStream.run
46
+ OpenC3::LogStuff.run
40
47
  end
@@ -44,6 +44,12 @@ module OpenC3
44
44
  attr_accessor :log_stream
45
45
  attr_accessor :needs_dependencies
46
46
  attr_accessor :secrets
47
+ attr_accessor :cmd
48
+ attr_accessor :container
49
+ attr_accessor :env
50
+ attr_accessor :work_dir
51
+ attr_accessor :ports
52
+ attr_accessor :prefix
47
53
 
48
54
  # NOTE: The following three class methods are used by the ModelController
49
55
  # and are reimplemented to enable various Model class methods to work
@@ -109,6 +115,12 @@ module OpenC3
109
115
  plugin: nil,
110
116
  needs_dependencies: false,
111
117
  secrets: [],
118
+ cmd: nil,
119
+ work_dir: '/openc3/lib/openc3/microservices',
120
+ ports: [],
121
+ env: {},
122
+ container: nil,
123
+ prefix: nil,
112
124
  scope:
113
125
  )
114
126
  if self.class._get_type == 'INTERFACE'
@@ -129,6 +141,17 @@ module OpenC3
129
141
  @protocols = protocols
130
142
  @log_stream = log_stream
131
143
  @needs_dependencies = needs_dependencies
144
+ @cmd = cmd
145
+ unless @cmd
146
+ type = self.class._get_type
147
+ microservice_name = "#{@scope}__#{type}__#{@name}"
148
+ @cmd = ["ruby", "#{type.downcase}_microservice.rb", microservice_name]
149
+ end
150
+ @work_dir = work_dir
151
+ @ports = ports
152
+ @env = env
153
+ @container = container
154
+ @prefix = prefix
132
155
  @secrets = secrets
133
156
  end
134
157
 
@@ -187,6 +210,12 @@ module OpenC3
187
210
  'plugin' => @plugin,
188
211
  'needs_dependencies' => @needs_dependencies,
189
212
  'secrets' => @secrets.as_json(*a),
213
+ 'cmd' => @cmd,
214
+ 'work_dir' => @work_dir,
215
+ 'ports' => @ports,
216
+ 'env' => @env,
217
+ 'container' => @container,
218
+ 'prefix' => @prefix,
190
219
  'updated_at' => @updated_at
191
220
  }
192
221
  end
@@ -266,6 +295,46 @@ module OpenC3
266
295
  @secrets[-1] << parameters[4]
267
296
  end
268
297
 
298
+ when 'ENV'
299
+ parser.verify_num_parameters(2, 2, "#{keyword} <Key> <Value>")
300
+ @env[parameters[0]] = parameters[1]
301
+
302
+ when 'PORT'
303
+ usage = "PORT <Number> <Protocol (Optional)"
304
+ parser.verify_num_parameters(1, 2, usage)
305
+ begin
306
+ @ports << [Integer(parameters[0])]
307
+ rescue # In case Integer fails
308
+ raise ConfigParser::Error.new(parser, "Port must be an integer: #{parameters[0]}", usage)
309
+ end
310
+ protocol = ConfigParser.handle_nil(parameters[1])
311
+ if protocol
312
+ # Per https://kubernetes.io/docs/concepts/services-networking/service/#protocol-support
313
+ if %w(TCP UDP SCTP).include?(protocol.upcase)
314
+ @ports[-1] << protocol.upcase
315
+ else
316
+ raise ConfigParser::Error.new(parser, "Unknown port protocol: #{parameters[1]}", usage)
317
+ end
318
+ else
319
+ @ports[-1] << 'TCP'
320
+ end
321
+
322
+ when 'WORK_DIR'
323
+ parser.verify_num_parameters(1, 1, "#{keyword} <Dir>")
324
+ @work_dir = parameters[0]
325
+
326
+ when 'CMD'
327
+ parser.verify_num_parameters(1, nil, "#{keyword} <Args>")
328
+ @cmd = parameters.dup
329
+
330
+ when 'CONTAINER'
331
+ parser.verify_num_parameters(1, 1, "#{keyword} <Container Image Name>")
332
+ @container = parameters[0]
333
+
334
+ when 'ROUTE_PREFIX'
335
+ parser.verify_num_parameters(1, 1, "#{keyword} <Route Prefix>")
336
+ @prefix = parameters[0]
337
+
269
338
  else
270
339
  raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Interface/Router: #{keyword} #{parameters.join(" ")}")
271
340
 
@@ -280,12 +349,16 @@ module OpenC3
280
349
  microservice_name = "#{@scope}__#{type}__#{@name}"
281
350
  microservice = MicroserviceModel.new(
282
351
  name: microservice_name,
283
- work_dir: '/openc3/lib/openc3/microservices',
284
- cmd: ["ruby", "#{type.downcase}_microservice.rb", microservice_name],
352
+ work_dir: @work_dir,
353
+ cmd: @cmd,
354
+ env: @env,
355
+ ports: @ports,
356
+ container: @container,
285
357
  target_names: @target_names,
286
358
  plugin: @plugin,
287
359
  needs_dependencies: @needs_dependencies,
288
360
  secrets: @secrets,
361
+ prefix: @prefix,
289
362
  scope: @scope
290
363
  )
291
364
  unless validate_only