openc3 5.0.7 → 5.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19c4ca95f60633de6f38b56a72891bda7cdcdf0b902a16d52f6527966c213bab
4
- data.tar.gz: 7ed07cc0014bd9ca27c57ff307cc879e385617339a6cb9b6c1fa891ab971a018
3
+ metadata.gz: 3a1e753382bf9c7d98b63dad72fed1aa08e3a234ce140327d0bbf07ed2a913dd
4
+ data.tar.gz: 4b61da453f0fc1c75b7ec5df06516970b1a0d3325425e15f550322a505e90883
5
5
  SHA512:
6
- metadata.gz: bc5c9ff0457266a17d4bef4f89c40fc99b851d4fe87d1d40783db3bdd84bf2581244e0055bfd6c5db706a60f35f4073d3eb0f9c0659a88a736bdc185051535bc
7
- data.tar.gz: fdc7c1552371c0555f0d67e30d8f31b9e966986224ecec2ab0c5705e60f8f2d4708782fb26776d359514c696ea6632f380526f7ba7a6dc34d382d32eab3f536b
6
+ metadata.gz: 3cfaad4b9103a68a6608d48513f1e1161df68325bfb0684d9dac6aebcc47af0e4c2a3225692dff08b7d28aa96ce33a3b7812928e0191620bffb08686fbe511d6
7
+ data.tar.gz: a385b3d5ac4524c8919adf9cc1050793c1ce5e30fb62c679a711b79f7523d3908301de23cfd97d426ec0c58ce1815d16047807802afb8530cbb1faf91392a444
data/bin/openc3cli CHANGED
@@ -530,6 +530,9 @@ if not ARGV[0].nil? # argument(s) given
530
530
  if plugin["name"] =~ /tool-base/ and plugin["name"] !~ /enterprise/
531
531
  unload_plugin(plugin_name, scope: scope_name)
532
532
  end
533
+ if plugin["name"] =~ /tool-admin/ and plugin["name"] !~ /enterprise/
534
+ unload_plugin(plugin_name, scope: scope_name)
535
+ end
533
536
  end
534
537
  end
535
538
 
@@ -545,6 +548,10 @@ if not ARGV[0].nil? # argument(s) given
545
548
  end
546
549
  end
547
550
 
551
+ when 'destroyscope'
552
+ scope = OpenC3::ScopeModel.get_model(name: ARGV[1])
553
+ scope.destroy
554
+
548
555
  else # Unknown task
549
556
  print_usage()
550
557
  abort("Unknown task: #{ARGV[0]}")
@@ -78,7 +78,7 @@ ARRAY_PARAMETER:
78
78
  - name: Name
79
79
  required: true
80
80
  description: Name of the parameter. Must be unique within the command.
81
- values: \'
81
+ values: .*
82
82
  - name: Bit Offset
83
83
  required: true
84
84
  description: Bit offset into the command packet of the Most Significant Bit of this parameter.
@@ -95,7 +95,7 @@ APPEND_ARRAY_PARAMETER:
95
95
  - name: Name
96
96
  required: true
97
97
  description: Name of the parameter. Must be unique within the command.
98
- values: '\D\S*'
98
+ values: .*
99
99
  <%= MetaConfigParser.load('_array_params.yaml').to_meta_config_yaml(4) %>
100
100
  SELECT_PARAMETER:
101
101
  modifiers:
@@ -61,3 +61,11 @@ TOOL:
61
61
  required: true
62
62
  description: Whether or not the tool is shown. TRUE or FALSE
63
63
  values: ["true", "false"]
64
+ POSITION:
65
+ summary: Position of the tool in the nav bar
66
+ description: Position of the tool as an integer starting at 1. Tools without a position are appended to the end as they are installed.
67
+ parameters:
68
+ - name: Position
69
+ required: true
70
+ description: Numerical position
71
+ values: \d+
@@ -909,6 +909,37 @@ LINEGRAPH:
909
909
  # required: false
910
910
  # description: The type of the value to display. Default is CONVERTED.
911
911
  # values: <%= %w(RAW CONVERTED FORMATTED WITH_UNITS) %>
912
+ SPARKLINE:
913
+ summary: Displays a sparkline graph (no cursor, scale or legend) of a telemetry item
914
+ parameters:
915
+ - name: Target name
916
+ required: true
917
+ description: The target name
918
+ values: .+
919
+ - name: Packet name
920
+ required: true
921
+ description: The packet name
922
+ values: .+
923
+ - name: Item name
924
+ required: true
925
+ description: The item name
926
+ values: .+
927
+ LABELSPARKLINE:
928
+ summary: Displays a LABEL widget to show the telemetry
929
+ item name followed by a SPARKLINE widget to graph the item
930
+ parameters:
931
+ - name: Target name
932
+ required: true
933
+ description: The target name
934
+ values: .+
935
+ - name: Packet name
936
+ required: true
937
+ description: The packet name
938
+ values: .+
939
+ - name: Item name
940
+ required: true
941
+ description: The item name
942
+ values: .+
912
943
  PROGRESSBAR:
913
944
  summary: Displays a progress bar that is useful for displaying percentages
914
945
  parmeters:
@@ -40,12 +40,12 @@ module OpenC3
40
40
 
41
41
  # Delete the current value table for a target
42
42
  def self.del(target_name:, packet_name:, scope:)
43
- EphemeralStore.hdel("#{scope}__tlm__#{target_name}", packet_name)
43
+ Store.hdel("#{scope}__tlm__#{target_name}", packet_name)
44
44
  end
45
45
 
46
46
  # Set the current value table for a target, packet
47
47
  def self.set(hash, target_name:, packet_name:, scope:)
48
- EphemeralStore.hset("#{scope}__tlm__#{target_name}", packet_name, JSON.generate(hash.as_json(:allow_nan => true)))
48
+ Store.hset("#{scope}__tlm__#{target_name}", packet_name, JSON.generate(hash.as_json(:allow_nan => true)))
49
49
  end
50
50
 
51
51
  # Set an item in the current value table
@@ -62,9 +62,9 @@ module OpenC3
62
62
  else
63
63
  raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
64
64
  end
65
- hash = JSON.parse(EphemeralStore.hget("#{scope}__tlm__#{target_name}", packet_name), :allow_nan => true, :create_additions => true)
65
+ hash = JSON.parse(Store.hget("#{scope}__tlm__#{target_name}", packet_name), :allow_nan => true, :create_additions => true)
66
66
  hash[field] = value
67
- EphemeralStore.hset("#{scope}__tlm__#{target_name}", packet_name, JSON.generate(hash.as_json(:allow_nan => true)))
67
+ Store.hset("#{scope}__tlm__#{target_name}", packet_name, JSON.generate(hash.as_json(:allow_nan => true)))
68
68
  end
69
69
 
70
70
  # Get an item from the current value table
@@ -86,7 +86,7 @@ module OpenC3
86
86
  else
87
87
  raise "Unknown type '#{type}' for #{target_name} #{packet_name} #{item_name}"
88
88
  end
89
- hash = JSON.parse(EphemeralStore.hget("#{scope}__tlm__#{target_name}", packet_name), :allow_nan => true, :create_additions => true)
89
+ hash = JSON.parse(Store.hget("#{scope}__tlm__#{target_name}", packet_name), :allow_nan => true, :create_additions => true)
90
90
  hash.values_at(*types).each do |result|
91
91
  return result if result
92
92
  end
@@ -106,7 +106,7 @@ module OpenC3
106
106
 
107
107
  lookups.each do |target_packet_key, target_name, packet_name, packet_values|
108
108
  unless packet_lookup[target_packet_key]
109
- packet = EphemeralStore.hget("#{scope}__tlm__#{target_name}", packet_name)
109
+ packet = Store.hget("#{scope}__tlm__#{target_name}", packet_name)
110
110
  raise "Packet '#{target_name} #{packet_name}' does not exist" unless packet
111
111
  packet_lookup[target_packet_key] = JSON.parse(packet, :allow_nan => true, :create_additions => true)
112
112
  end
@@ -267,11 +267,13 @@ module OpenC3
267
267
 
268
268
  # Undeploy all models associated with this plugin
269
269
  def undeploy
270
+ microservice_count = 0
270
271
  MicroserviceModel.find_all_by_plugin(plugin: @name, scope: @scope).each do |name, model_instance|
271
272
  model_instance.destroy
273
+ microservice_count += 1
272
274
  end
273
275
  # Wait for the operator to wake up and remove the microservice processes
274
- sleep 12 # Cycle time 5s times 2 plus 2s wait for soft stop and then hard stop
276
+ sleep 12 if microservice_count > 0 # Cycle time 5s times 2 plus 2s wait for soft stop and then hard stop
275
277
  # Remove all the other models now that the processes have stopped
276
278
  # Save TargetModel for last as it has the most to cleanup
277
279
  [InterfaceModel, RouterModel, ToolModel, WidgetModel, TargetModel].each do |model|
@@ -40,10 +40,47 @@ module OpenC3
40
40
  super(PRIMARY_KEY)
41
41
  end
42
42
 
43
+ def self.from_json(json, scope: nil)
44
+ json = JSON.parse(json, :allow_nan => true, :create_additions => true) if String === json
45
+ raise "json data is nil" if json.nil?
46
+
47
+ json.transform_keys!(&:to_sym)
48
+ self.new(**json, scope: scope)
49
+ end
50
+
51
+ def self.get_model(name:, scope: nil)
52
+ json = get(name: name)
53
+ if json
54
+ return from_json(json)
55
+ else
56
+ return nil
57
+ end
58
+ end
59
+
43
60
  def initialize(name:, updated_at: nil, scope: nil)
44
61
  super(PRIMARY_KEY, name: name, scope: name, updated_at: updated_at)
45
62
  end
46
63
 
64
+ def create(update: false, force: false)
65
+ # Ensure there are no "." in the scope name - prevents gems accidently becoming scope names
66
+ raise "Invalid scope name: #{@name}" if @name !~ /^[a-zA-Z0-9_-]+$/
67
+ @name = @name.upcase
68
+ super(update: update, force: force)
69
+ end
70
+
71
+ def destroy
72
+ if @name != 'DEFAULT'
73
+ # Remove all the plugins for this scope
74
+ plugins = PluginModel.get_all_models(scope: @name)
75
+ plugins.each do |plugin_name, plugin|
76
+ plugin.destroy
77
+ end
78
+ super()
79
+ else
80
+ raise "DEFAULT scope cannot be destroyed"
81
+ end
82
+ end
83
+
47
84
  def as_json(*a)
48
85
  { 'name' => @name,
49
86
  'updated_at' => @updated_at }
@@ -51,9 +88,12 @@ module OpenC3
51
88
 
52
89
  def deploy(gem_path, variables)
53
90
  seed_database()
54
-
55
91
  ConfigTopic.initialize_stream(@scope)
56
92
 
93
+ # Create UNKNOWN target for display of unknown data
94
+ model = TargetModel.new(name: "UNKNOWN", scope: @scope)
95
+ model.create
96
+
57
97
  # OpenC3 Log Microservice
58
98
  microservice_name = "#{@scope}__OPENC3__LOG"
59
99
  microservice = MicroserviceModel.new(
@@ -203,6 +203,9 @@ module OpenC3
203
203
  when 'SHOWN'
204
204
  parser.verify_num_parameters(1, 1, "SHOWN <true/false>")
205
205
  @shown = ConfigParser.handle_true_false(parameters[0])
206
+ when 'POSITION'
207
+ parser.verify_num_parameters(1, 1, "POSITION <value>")
208
+ @position = parameters[0].to_i
206
209
  else
207
210
  raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Tool: #{keyword} #{parameters.join(" ")}")
208
211
  end
@@ -90,7 +90,7 @@ module OpenC3
90
90
  @new_microservices.each do |microservice_name, microservice_config|
91
91
  cmd_array, work_dir, env, scope, container = convert_microservice_to_process_definition(microservice_name, microservice_config)
92
92
  if cmd_array
93
- process = OperatorProcess.new(cmd_array, work_dir: work_dir, env: env, scope: scope, container: container)
93
+ process = OperatorProcess.new(cmd_array, work_dir: work_dir, env: env, scope: scope, container: container, config: microservice_config)
94
94
  @new_processes[microservice_name] = process
95
95
  @processes[microservice_name] = process
96
96
  end
@@ -108,7 +108,7 @@ module OpenC3
108
108
  @changed_processes[microservice_name] = process
109
109
  else # TODO: How is this even possible?
110
110
  Logger.error("Changed microservice #{microservice_name} does not exist. Creating new...", scope: scope)
111
- process = OperatorProcess.new(cmd_array, work_dir: work_dir, env: env, scope: scope, container: container)
111
+ process = OperatorProcess.new(cmd_array, work_dir: work_dir, env: env, scope: scope, container: container, config: microservice_config)
112
112
  @new_processes[microservice_name] = process
113
113
  @processes[microservice_name] = process
114
114
  end
@@ -35,7 +35,8 @@ module OpenC3
35
35
  # Perform any setup steps necessary
36
36
  end
37
37
 
38
- def initialize(process_definition, work_dir: '/openc3/lib/openc3/microservices', temp_dir: nil, env: {}, scope:, container: nil) # container is not used, it's just here for Enterprise
38
+ # container is not used, it's just here for Enterprise
39
+ def initialize(process_definition, work_dir: '/openc3/lib/openc3/microservices', temp_dir: nil, env: {}, scope:, container: nil, config: nil)
39
40
  @process = nil
40
41
  @process_definition = process_definition
41
42
  @work_dir = work_dir
@@ -43,12 +44,26 @@ module OpenC3
43
44
  @new_temp_dir = temp_dir
44
45
  @env = env
45
46
  @scope = scope
47
+ # @config only used in start to help print a better Logger message
48
+ @config = config
46
49
  end
47
50
 
48
51
  def start
49
52
  @temp_dir = @new_temp_dir
50
53
  @new_temp_dir = nil
51
- Logger.info("Starting: #{@process_definition.join(' ')}", scope: @scope)
54
+
55
+ # In ProcessManager processes, the process_definition is the actual thing run
56
+ # e.g. OpenC3::ProcessManager.instance.spawn(["ruby", "/openc3/bin/openc3cli", "load", ...])
57
+ # However, if the MicroserviceOperator is spawning the proceses it sets
58
+ # process_definition = ["ruby", "plugin_microservice.rb"]
59
+ # which then calls exec(*@config["cmd"]) to actually run
60
+ # So check if the @config['cmd'] is defined to give the user more info in the log
61
+ cmd = @process_definition.join(' ')
62
+ if @config && @config['cmd']
63
+ cmd = @config['cmd'].join(' ')
64
+ end
65
+ Logger.info("Starting: #{cmd}", scope: @scope)
66
+
52
67
  @process = ChildProcess.build(*@process_definition)
53
68
  # This lets the ChildProcess use the parent IO ... but it breaks unit tests
54
69
  # @process.io.inherit!
@@ -22,6 +22,22 @@ require 'openc3/models/reducer_model'
22
22
 
23
23
  module OpenC3
24
24
  class S3Utilities
25
+ def self.put_object_and_check(params = {})
26
+ rubys3_client = Aws::S3::Client.new
27
+ rubys3_client.put_object(params)
28
+ # polls in a loop, sleeping between attempts
29
+ rubys3_client.wait_until(:object_exists,
30
+ {
31
+ bucket: params[:bucket],
32
+ key: params[:key]
33
+ },
34
+ {
35
+ max_attempts: 30,
36
+ delay: 0.1, # seconds
37
+ }
38
+ )
39
+ end
40
+
25
41
  def self.list_files_before_time(bucket, prefix, time)
26
42
  rubys3_client = Aws::S3::Client.new
27
43
  oldest_list = []
@@ -1,14 +1,14 @@
1
1
  # encoding: ascii-8bit
2
2
 
3
- OPENC3_VERSION = '5.0.7'
3
+ OPENC3_VERSION = '5.0.8'
4
4
  module OpenC3
5
5
  module Version
6
6
  MAJOR = '5'
7
7
  MINOR = '0'
8
- PATCH = '7'
8
+ PATCH = '8'
9
9
  OTHER = ''
10
- BUILD = 'be957bd6e3c30c2e535b9ee8dfbeffe75c720874'
10
+ BUILD = '8dc96d0ce9d272e063d9d806f848803b7d5c61ed'
11
11
  end
12
- VERSION = '5.0.7'
13
- GEM_VERSION = '5.0.7'
12
+ VERSION = '5.0.8'
13
+ GEM_VERSION = '5.0.8'
14
14
  end
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.0.7
4
+ version: 5.0.8
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: 2022-08-05 00:00:00.000000000 Z
12
+ date: 2022-08-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '6.3'
34
+ version: '6.4'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '6.3'
41
+ version: '6.4'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rake
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -185,14 +185,14 @@ dependencies:
185
185
  requirements:
186
186
  - - "~>"
187
187
  - !ruby/object:Gem::Version
188
- version: '3.0'
188
+ version: '4.0'
189
189
  type: :runtime
190
190
  prerelease: false
191
191
  version_requirements: !ruby/object:Gem::Requirement
192
192
  requirements:
193
193
  - - "~>"
194
194
  - !ruby/object:Gem::Version
195
- version: '3.0'
195
+ version: '4.0'
196
196
  - !ruby/object:Gem::Dependency
197
197
  name: matrix
198
198
  requirement: !ruby/object:Gem::Requirement
@@ -311,14 +311,14 @@ dependencies:
311
311
  requirements:
312
312
  - - "~>"
313
313
  - !ruby/object:Gem::Version
314
- version: '3.1'
314
+ version: '4.0'
315
315
  type: :development
316
316
  prerelease: false
317
317
  version_requirements: !ruby/object:Gem::Requirement
318
318
  requirements:
319
319
  - - "~>"
320
320
  - !ruby/object:Gem::Version
321
- version: '3.1'
321
+ version: '4.0'
322
322
  - !ruby/object:Gem::Dependency
323
323
  name: diff-lcs
324
324
  requirement: !ruby/object:Gem::Requirement