openc3 6.9.1 → 6.9.2
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.
- checksums.yaml +4 -4
- data/bin/openc3cli +289 -0
- data/lib/openc3/interfaces.rb +6 -4
- data/lib/openc3/microservices/interface_microservice.rb +9 -5
- data/lib/openc3/microservices/queue_microservice.rb +14 -6
- data/lib/openc3/models/plugin_model.rb +63 -6
- data/lib/openc3/models/reaction_model.rb +1 -1
- data/lib/openc3/models/target_model.rb +7 -3
- data/lib/openc3/models/trigger_model.rb +1 -1
- data/lib/openc3/script/script.rb +1 -1
- data/lib/openc3/system/system.rb +3 -3
- data/lib/openc3/utilities/authentication.rb +25 -6
- data/lib/openc3/utilities/cli_generator.rb +347 -3
- data/lib/openc3/version.rb +5 -5
- data/templates/command_validator/command_validator.py +49 -0
- data/templates/command_validator/command_validator.rb +54 -0
- data/templates/tool_angular/package.json +48 -2
- data/templates/tool_react/package.json +51 -1
- data/templates/tool_svelte/package.json +48 -1
- data/templates/tool_vue/package.json +36 -3
- data/templates/widget/package.json +28 -2
- metadata +5 -5
- data/templates/tool_vue/.browserslistrc +0 -16
- data/templates/widget/.browserslistrc +0 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4d4fd7006c78d3a21531579d68d42bc5cba596c92091e8cd7895c4b42ecff569
|
|
4
|
+
data.tar.gz: 85fdaa738dafbfafcc16fb463abb5d86517f9f1edefb4bbef9a5e7171738211c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 419ddee4f6203f3500c9d3eb45347824dfa57a074527086fd8bfdaee16c4dc10ec07b3b78122e1a753a064913bbb1193f29344e260ba7a04b029cdb11682a9e7
|
|
7
|
+
data.tar.gz: 961d67c9c972a2cdf60c31c9279b69a7e1fc315e62813935eb66fefbbd853cf931c633c36aa6b9606cb1eedfd66ef8ba2db07b34f24acf99967aa6983755deb3
|
data/bin/openc3cli
CHANGED
|
@@ -875,6 +875,22 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
875
875
|
case ARGV[0].downcase
|
|
876
876
|
|
|
877
877
|
when 'irb'
|
|
878
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
879
|
+
puts "Usage: cli irb"
|
|
880
|
+
puts ""
|
|
881
|
+
puts "Start an interactive Ruby (IRB) session with COSMOS libraries loaded"
|
|
882
|
+
puts ""
|
|
883
|
+
puts "This provides access to all COSMOS classes and methods for interactive"
|
|
884
|
+
puts "debugging and exploration. Use 'exit' or Ctrl-D to quit the IRB session."
|
|
885
|
+
puts ""
|
|
886
|
+
puts "Example:"
|
|
887
|
+
puts " cli irb"
|
|
888
|
+
puts " > require 'openc3'"
|
|
889
|
+
puts " > OpenC3::System.targets"
|
|
890
|
+
puts ""
|
|
891
|
+
puts "Note: For IRB-specific options, start IRB first then type 'help'"
|
|
892
|
+
exit 0
|
|
893
|
+
end
|
|
878
894
|
ARGV.clear
|
|
879
895
|
IRB.start
|
|
880
896
|
|
|
@@ -882,6 +898,29 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
882
898
|
cli_script(ARGV[1..-1])
|
|
883
899
|
|
|
884
900
|
when 'rake'
|
|
901
|
+
# Check for --help first, before checking for Rakefile
|
|
902
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
903
|
+
puts "Usage: cli rake [RAKE_OPTIONS] [TASKS...]"
|
|
904
|
+
puts ""
|
|
905
|
+
puts "Run rake tasks in the current directory"
|
|
906
|
+
puts ""
|
|
907
|
+
puts "This runs the standard Ruby rake tool with all COSMOS libraries available."
|
|
908
|
+
puts "A Rakefile must exist in the current directory."
|
|
909
|
+
puts ""
|
|
910
|
+
puts "Common rake options:"
|
|
911
|
+
puts " -T, --tasks List all available rake tasks with descriptions"
|
|
912
|
+
puts " -D, --describe PATTERN Describe tasks matching PATTERN"
|
|
913
|
+
puts " -h, --help Show rake's full help message"
|
|
914
|
+
puts ""
|
|
915
|
+
puts "Examples:"
|
|
916
|
+
puts " cli rake -T # List all available tasks"
|
|
917
|
+
puts " cli rake build # Run the 'build' task"
|
|
918
|
+
puts " cli rake test # Run tests"
|
|
919
|
+
puts ""
|
|
920
|
+
puts "Note: Must be run in a directory containing a Rakefile"
|
|
921
|
+
exit 0
|
|
922
|
+
end
|
|
923
|
+
# Now check for Rakefile existence
|
|
885
924
|
if File.exist?('Rakefile')
|
|
886
925
|
puts `rake #{ARGV[1..-1].join(' ')}`
|
|
887
926
|
else
|
|
@@ -889,9 +928,70 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
889
928
|
end
|
|
890
929
|
|
|
891
930
|
when 'validate'
|
|
931
|
+
if ARGV[1].nil? || ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
932
|
+
puts "Usage: cli validate PLUGIN.gem [SCOPE] [VARIABLES.json]"
|
|
933
|
+
puts ""
|
|
934
|
+
puts "Validate a COSMOS plugin gem file"
|
|
935
|
+
puts ""
|
|
936
|
+
puts "Arguments:"
|
|
937
|
+
puts " PLUGIN.gem Plugin gem file to validate (required)"
|
|
938
|
+
puts " SCOPE Scope for validation (optional, default: DEFAULT)"
|
|
939
|
+
puts " VARIABLES.json Variables JSON file (optional)"
|
|
940
|
+
puts ""
|
|
941
|
+
puts "Options:"
|
|
942
|
+
puts " -h, --help Show this help message"
|
|
943
|
+
exit(ARGV[1].nil? ? 1 : 0)
|
|
944
|
+
end
|
|
892
945
|
validate_plugin(ARGV[1], scope: ARGV[2], variables_file: ARGV[3])
|
|
893
946
|
|
|
894
947
|
when 'load'
|
|
948
|
+
# Check for help flag or missing arguments
|
|
949
|
+
if ARGV[1].nil? || ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
950
|
+
puts "Usage:"
|
|
951
|
+
puts " cli load PLUGIN.gem"
|
|
952
|
+
puts " cli load PLUGIN.gem --variables VARIABLES.json"
|
|
953
|
+
puts " cli load PLUGIN.gem SCOPE PLUGIN_HASH.json [force]"
|
|
954
|
+
puts " cli load PLUGIN.gem --variables VARIABLES.json SCOPE PLUGIN_HASH.json [force]"
|
|
955
|
+
puts ""
|
|
956
|
+
puts "Load a COSMOS plugin gem file"
|
|
957
|
+
puts ""
|
|
958
|
+
puts "Common Usage (Auto-detect):"
|
|
959
|
+
puts " cli load PLUGIN.gem"
|
|
960
|
+
puts " - Installs new plugin in DEFAULT scope"
|
|
961
|
+
puts " - Automatically detects and upgrades if plugin already exists"
|
|
962
|
+
puts " - Skips installation if same version already installed"
|
|
963
|
+
puts ""
|
|
964
|
+
puts " cli load PLUGIN.gem --variables VARIABLES.json"
|
|
965
|
+
puts " - Same as above, but provides variables for plugin configuration"
|
|
966
|
+
puts ""
|
|
967
|
+
puts "Advanced Usage (Manual Control):"
|
|
968
|
+
puts " cli load PLUGIN.gem SCOPE PLUGIN_HASH.json [force]"
|
|
969
|
+
puts " - Used by Admin UI for plugin create/edit/upgrade operations"
|
|
970
|
+
puts " - Requires PLUGIN_HASH.json (output from install_phase1)"
|
|
971
|
+
puts " - 'force' argument forces reinstall even if version unchanged"
|
|
972
|
+
puts ""
|
|
973
|
+
puts "Arguments:"
|
|
974
|
+
puts " PLUGIN.gem Plugin gem file to load (required)"
|
|
975
|
+
puts " SCOPE Scope to install plugin in (default: DEFAULT)"
|
|
976
|
+
puts " PLUGIN_HASH.json Plugin hash JSON file from install_phase1 (optional)"
|
|
977
|
+
puts " force Force plugin installation even if no changes (optional)"
|
|
978
|
+
puts ""
|
|
979
|
+
puts "Options:"
|
|
980
|
+
puts " --variables FILE Variables JSON file for plugin installation"
|
|
981
|
+
puts " -h, --help Show this help message"
|
|
982
|
+
puts ""
|
|
983
|
+
puts "IMPORTANT LIMITATION:"
|
|
984
|
+
puts " To specify SCOPE without PLUGIN_HASH.json, you must use the --variables"
|
|
985
|
+
puts " option (even with an empty JSON file) to prevent argument misinterpretation."
|
|
986
|
+
puts ""
|
|
987
|
+
puts "Examples:"
|
|
988
|
+
puts " cli load my-plugin-1.0.0.gem"
|
|
989
|
+
puts " cli load my-plugin-1.0.0.gem --variables vars.json"
|
|
990
|
+
puts " cli load my-plugin-1.0.0.gem DEFAULT plugin_hash.json"
|
|
991
|
+
puts " cli load my-plugin-1.0.0.gem DEFAULT plugin_hash.json force"
|
|
992
|
+
exit(ARGV[1].nil? ? 1 : 0)
|
|
993
|
+
end
|
|
994
|
+
|
|
895
995
|
# force is a boolean so if they pass 'force' it is true
|
|
896
996
|
# See plugins_controller.rb install for usage
|
|
897
997
|
variables_option = ARGV.find_index('--variables')
|
|
@@ -908,15 +1008,68 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
908
1008
|
load_plugin(ARGV[1], scope: scope, plugin_hash_file: plugin_hash_file, force: force, variables_file: variables_file)
|
|
909
1009
|
|
|
910
1010
|
when 'list'
|
|
1011
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1012
|
+
puts "Usage: cli list [SCOPE]"
|
|
1013
|
+
puts ""
|
|
1014
|
+
puts "List all installed plugins in the specified scope"
|
|
1015
|
+
puts ""
|
|
1016
|
+
puts "Arguments:"
|
|
1017
|
+
puts " SCOPE Scope to list plugins from (optional, default: DEFAULT)"
|
|
1018
|
+
puts ""
|
|
1019
|
+
puts "Options:"
|
|
1020
|
+
puts " -h, --help Show this help message"
|
|
1021
|
+
exit 0
|
|
1022
|
+
end
|
|
911
1023
|
list_plugins(scope: ARGV[1])
|
|
912
1024
|
|
|
913
1025
|
when 'unload'
|
|
1026
|
+
if ARGV[1].nil? || ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1027
|
+
puts "Usage: cli unload PLUGIN_NAME [SCOPE]"
|
|
1028
|
+
puts ""
|
|
1029
|
+
puts "Unload a COSMOS plugin"
|
|
1030
|
+
puts ""
|
|
1031
|
+
puts "Arguments:"
|
|
1032
|
+
puts " PLUGIN_NAME Name of the plugin to unload (required)"
|
|
1033
|
+
puts " SCOPE Scope to unload from (optional, default: DEFAULT)"
|
|
1034
|
+
puts ""
|
|
1035
|
+
puts "Options:"
|
|
1036
|
+
puts " -h, --help Show this help message"
|
|
1037
|
+
exit(ARGV[1].nil? ? 1 : 0)
|
|
1038
|
+
end
|
|
914
1039
|
unload_plugin(ARGV[1], scope: ARGV[2])
|
|
915
1040
|
|
|
916
1041
|
when 'pkginstall', 'geminstall'
|
|
1042
|
+
if ARGV[1].nil? || ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1043
|
+
puts "Usage: cli pkginstall PACKAGE_NAME [SCOPE]"
|
|
1044
|
+
puts " cli geminstall GEM_NAME [SCOPE]"
|
|
1045
|
+
puts ""
|
|
1046
|
+
puts "Install a package/gem into a loaded plugin"
|
|
1047
|
+
puts ""
|
|
1048
|
+
puts "Arguments:"
|
|
1049
|
+
puts " PACKAGE_NAME Name of the package to install (required)"
|
|
1050
|
+
puts " SCOPE Scope for installation (optional, default: DEFAULT)"
|
|
1051
|
+
puts ""
|
|
1052
|
+
puts "Options:"
|
|
1053
|
+
puts " -h, --help Show this help message"
|
|
1054
|
+
exit(ARGV[1].nil? ? 1 : 0)
|
|
1055
|
+
end
|
|
917
1056
|
cli_pkg_install(ARGV[1], scope: ARGV[2])
|
|
918
1057
|
|
|
919
1058
|
when 'pkguninstall', 'gemuninstall'
|
|
1059
|
+
if ARGV[1].nil? || ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1060
|
+
puts "Usage: cli pkguninstall PACKAGE_NAME [SCOPE]"
|
|
1061
|
+
puts " cli gemuninstall GEM_NAME [SCOPE]"
|
|
1062
|
+
puts ""
|
|
1063
|
+
puts "Uninstall a package/gem from a loaded plugin"
|
|
1064
|
+
puts ""
|
|
1065
|
+
puts "Arguments:"
|
|
1066
|
+
puts " PACKAGE_NAME Name of the package to uninstall (required)"
|
|
1067
|
+
puts " SCOPE Scope for uninstallation (optional, default: DEFAULT)"
|
|
1068
|
+
puts ""
|
|
1069
|
+
puts "Options:"
|
|
1070
|
+
puts " -h, --help Show this help message"
|
|
1071
|
+
exit(ARGV[1].nil? ? 1 : 0)
|
|
1072
|
+
end
|
|
920
1073
|
cli_pkg_uninstall(ARGV[1], scope: ARGV[2])
|
|
921
1074
|
|
|
922
1075
|
when 'generate'
|
|
@@ -934,6 +1087,19 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
934
1087
|
xtce_converter(ARGV[1..-1])
|
|
935
1088
|
|
|
936
1089
|
when 'bridge'
|
|
1090
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1091
|
+
puts "Usage: cli bridge [FILENAME] [PARAMS...]"
|
|
1092
|
+
puts ""
|
|
1093
|
+
puts "Run a COSMOS bridge from a bridge configuration file"
|
|
1094
|
+
puts ""
|
|
1095
|
+
puts "Arguments:"
|
|
1096
|
+
puts " FILENAME Bridge config file (optional, default: bridge.txt)"
|
|
1097
|
+
puts " PARAMS Additional parameters to pass to bridge"
|
|
1098
|
+
puts ""
|
|
1099
|
+
puts "Options:"
|
|
1100
|
+
puts " -h, --help Show this help message"
|
|
1101
|
+
exit 0
|
|
1102
|
+
end
|
|
937
1103
|
ENV['OPENC3_NO_STORE'] = '1'
|
|
938
1104
|
filename = ARGV[1]
|
|
939
1105
|
filename = 'bridge.txt' unless filename
|
|
@@ -942,6 +1108,19 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
942
1108
|
run_bridge(filename, params)
|
|
943
1109
|
|
|
944
1110
|
when 'bridgegem'
|
|
1111
|
+
if ARGV[1].nil? || ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1112
|
+
puts "Usage: cli bridgegem GEM_NAME [PARAMS...]"
|
|
1113
|
+
puts ""
|
|
1114
|
+
puts "Run a COSMOS bridge from a gem's bridge.txt file"
|
|
1115
|
+
puts ""
|
|
1116
|
+
puts "Arguments:"
|
|
1117
|
+
puts " GEM_NAME Name of the gem containing bridge.txt (required)"
|
|
1118
|
+
puts " PARAMS Additional parameters to pass to bridge"
|
|
1119
|
+
puts ""
|
|
1120
|
+
puts "Options:"
|
|
1121
|
+
puts " -h, --help Show this help message"
|
|
1122
|
+
exit(ARGV[1].nil? ? 1 : 0)
|
|
1123
|
+
end
|
|
945
1124
|
ENV['OPENC3_NO_STORE'] = '1'
|
|
946
1125
|
filename = nil
|
|
947
1126
|
gem_name = ARGV[1]
|
|
@@ -967,6 +1146,18 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
967
1146
|
run_bridge(filename, params)
|
|
968
1147
|
|
|
969
1148
|
when 'bridgesetup'
|
|
1149
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1150
|
+
puts "Usage: cli bridgesetup [FILENAME]"
|
|
1151
|
+
puts ""
|
|
1152
|
+
puts "Generate a default bridge configuration file"
|
|
1153
|
+
puts ""
|
|
1154
|
+
puts "Arguments:"
|
|
1155
|
+
puts " FILENAME Output filename (optional, default: bridge.txt)"
|
|
1156
|
+
puts ""
|
|
1157
|
+
puts "Options:"
|
|
1158
|
+
puts " -h, --help Show this help message"
|
|
1159
|
+
exit 0
|
|
1160
|
+
end
|
|
970
1161
|
ENV['OPENC3_NO_STORE'] = '1'
|
|
971
1162
|
filename = ARGV[1]
|
|
972
1163
|
filename = 'bridge.txt' unless filename
|
|
@@ -978,10 +1169,36 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
978
1169
|
print_usage()
|
|
979
1170
|
|
|
980
1171
|
when 'redis'
|
|
1172
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1173
|
+
puts "Usage: cli redis COMMAND [ARGS...]"
|
|
1174
|
+
puts ""
|
|
1175
|
+
puts "Interact with the Redis database"
|
|
1176
|
+
puts ""
|
|
1177
|
+
puts "Commands:"
|
|
1178
|
+
puts " keys Get all Redis keys"
|
|
1179
|
+
puts " hget HASH KEY Get a value from a Redis hash"
|
|
1180
|
+
puts ""
|
|
1181
|
+
puts "Options:"
|
|
1182
|
+
puts " -h, --help Show this help message"
|
|
1183
|
+
exit 0
|
|
1184
|
+
end
|
|
981
1185
|
case (ARGV[1])
|
|
982
1186
|
when 'keys'
|
|
983
1187
|
get_redis_keys()
|
|
984
1188
|
when 'hget'
|
|
1189
|
+
if ARGV[2].nil? || ARGV[3].nil? || ARGV[2] == '--help' || ARGV[2] == '-h'
|
|
1190
|
+
puts "Usage: cli redis hget HASH KEY"
|
|
1191
|
+
puts ""
|
|
1192
|
+
puts "Get a value from a Redis hash"
|
|
1193
|
+
puts ""
|
|
1194
|
+
puts "Arguments:"
|
|
1195
|
+
puts " HASH Redis hash name (required)"
|
|
1196
|
+
puts " KEY Key within the hash (required)"
|
|
1197
|
+
puts ""
|
|
1198
|
+
puts "Options:"
|
|
1199
|
+
puts " -h, --help Show this help message"
|
|
1200
|
+
exit(ARGV[2].nil? || ARGV[3].nil? ? 1 : 0)
|
|
1201
|
+
end
|
|
985
1202
|
redis = Redis.new(url: $redis_url, username: ENV['OPENC3_REDIS_USERNAME'], password: ENV['OPENC3_REDIS_PASSWORD'])
|
|
986
1203
|
puts JSON.parse(redis.hget(ARGV[2], ARGV[3]), allow_nan: true, create_additions: true)
|
|
987
1204
|
else
|
|
@@ -990,6 +1207,16 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
990
1207
|
end
|
|
991
1208
|
|
|
992
1209
|
when 'removebase'
|
|
1210
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1211
|
+
puts "Usage: cli removebase"
|
|
1212
|
+
puts ""
|
|
1213
|
+
puts "Remove non-enterprise tool base and admin plugins from all scopes"
|
|
1214
|
+
puts "This is typically used to support enterprise upgrades"
|
|
1215
|
+
puts ""
|
|
1216
|
+
puts "Options:"
|
|
1217
|
+
puts " -h, --help Show this help message"
|
|
1218
|
+
exit 0
|
|
1219
|
+
end
|
|
993
1220
|
# Used to remove tool base to better support enterprise upgrade
|
|
994
1221
|
scopes = OpenC3::ScopeModel.all
|
|
995
1222
|
scopes.each do |scope_name, _scope|
|
|
@@ -1005,6 +1232,16 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
1005
1232
|
end
|
|
1006
1233
|
|
|
1007
1234
|
when 'removeenterprise'
|
|
1235
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1236
|
+
puts "Usage: cli removeenterprise"
|
|
1237
|
+
puts ""
|
|
1238
|
+
puts "Remove all enterprise plugins from all scopes"
|
|
1239
|
+
puts "This is typically used to support downgrades"
|
|
1240
|
+
puts ""
|
|
1241
|
+
puts "Options:"
|
|
1242
|
+
puts " -h, --help Show this help message"
|
|
1243
|
+
exit 0
|
|
1244
|
+
end
|
|
1008
1245
|
# Used to remove enterprise plugins to better support downgrade
|
|
1009
1246
|
scopes = OpenC3::ScopeModel.all
|
|
1010
1247
|
scopes.each do |scope_name, _scope|
|
|
@@ -1017,6 +1254,19 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
1017
1254
|
end
|
|
1018
1255
|
|
|
1019
1256
|
when 'createqueue'
|
|
1257
|
+
if ARGV[1].nil? || ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1258
|
+
puts "Usage: cli createqueue QUEUE_NAME [SCOPE]"
|
|
1259
|
+
puts ""
|
|
1260
|
+
puts "Create a new queue in the specified scope"
|
|
1261
|
+
puts ""
|
|
1262
|
+
puts "Arguments:"
|
|
1263
|
+
puts " QUEUE_NAME Name of the queue to create (required)"
|
|
1264
|
+
puts " SCOPE Scope for the queue (optional, default: DEFAULT)"
|
|
1265
|
+
puts ""
|
|
1266
|
+
puts "Options:"
|
|
1267
|
+
puts " -h, --help Show this help message"
|
|
1268
|
+
exit(ARGV[1].nil? ? 1 : 0)
|
|
1269
|
+
end
|
|
1020
1270
|
queue = OpenC3::QueueModel.get(name: ARGV[1], scope: ARGV[2])
|
|
1021
1271
|
unless queue
|
|
1022
1272
|
queue = OpenC3::QueueModel.new(name: ARGV[1], state: 'RELEASE', scope: ARGV[2])
|
|
@@ -1024,13 +1274,43 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
1024
1274
|
end
|
|
1025
1275
|
|
|
1026
1276
|
when 'destroyscope'
|
|
1277
|
+
if ARGV[1].nil? || ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1278
|
+
puts "Usage: cli destroyscope SCOPE_NAME"
|
|
1279
|
+
puts ""
|
|
1280
|
+
puts "Destroy a scope and all its associated data"
|
|
1281
|
+
puts ""
|
|
1282
|
+
puts "Arguments:"
|
|
1283
|
+
puts " SCOPE_NAME Name of the scope to destroy (required)"
|
|
1284
|
+
puts ""
|
|
1285
|
+
puts "Options:"
|
|
1286
|
+
puts " -h, --help Show this help message"
|
|
1287
|
+
exit(ARGV[1].nil? ? 1 : 0)
|
|
1288
|
+
end
|
|
1027
1289
|
scope = OpenC3::ScopeModel.get_model(name: ARGV[1])
|
|
1028
1290
|
scope.destroy
|
|
1029
1291
|
|
|
1030
1292
|
when 'localinit'
|
|
1293
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1294
|
+
puts "Usage: cli localinit"
|
|
1295
|
+
puts ""
|
|
1296
|
+
puts "Initialize local mode configuration"
|
|
1297
|
+
puts ""
|
|
1298
|
+
puts "Options:"
|
|
1299
|
+
puts " -h, --help Show this help message"
|
|
1300
|
+
exit 0
|
|
1301
|
+
end
|
|
1031
1302
|
OpenC3::LocalMode.local_init()
|
|
1032
1303
|
|
|
1033
1304
|
when 'initbuckets'
|
|
1305
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1306
|
+
puts "Usage: cli initbuckets"
|
|
1307
|
+
puts ""
|
|
1308
|
+
puts "Initialize all configured COSMOS buckets"
|
|
1309
|
+
puts ""
|
|
1310
|
+
puts "Options:"
|
|
1311
|
+
puts " -h, --help Show this help message"
|
|
1312
|
+
exit 0
|
|
1313
|
+
end
|
|
1034
1314
|
client = OpenC3::Bucket.getClient()
|
|
1035
1315
|
ENV.map do |key, value|
|
|
1036
1316
|
if key.match(/^OPENC3_(.+)_BUCKET$/) && !value.empty?
|
|
@@ -1040,6 +1320,15 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
1040
1320
|
client.ensure_public(ENV['OPENC3_TOOLS_BUCKET'])
|
|
1041
1321
|
|
|
1042
1322
|
when 'runmigrations'
|
|
1323
|
+
if ARGV[1] == '--help' || ARGV[1] == '-h'
|
|
1324
|
+
puts "Usage: cli runmigrations"
|
|
1325
|
+
puts ""
|
|
1326
|
+
puts "Run database migrations"
|
|
1327
|
+
puts ""
|
|
1328
|
+
puts "Options:"
|
|
1329
|
+
puts " -h, --help Show this help message"
|
|
1330
|
+
exit 0
|
|
1331
|
+
end
|
|
1043
1332
|
run_migrations(ARGV[1])
|
|
1044
1333
|
|
|
1045
1334
|
else # Unknown task
|
data/lib/openc3/interfaces.rb
CHANGED
|
@@ -34,14 +34,16 @@ module OpenC3
|
|
|
34
34
|
autoload(:TcpipServerInterface, 'openc3/interfaces/tcpip_server_interface.rb')
|
|
35
35
|
autoload(:UdpInterface, 'openc3/interfaces/udp_interface.rb')
|
|
36
36
|
|
|
37
|
-
autoload(:Protocol, 'openc3/interfaces/protocols/protocol.rb')
|
|
38
37
|
autoload(:BurstProtocol, 'openc3/interfaces/protocols/burst_protocol.rb')
|
|
38
|
+
autoload(:CmdResponseProtocol, 'openc3/interfaces/protocols/cmd_response_protocol.rb')
|
|
39
|
+
autoload(:CobsProtocol, 'openc3/interfaces/protocols/cobs_protocol.rb')
|
|
40
|
+
autoload(:CrcProtocol, 'openc3/interfaces/protocols/crc_protocol.rb')
|
|
39
41
|
autoload(:FixedProtocol, 'openc3/interfaces/protocols/fixed_protocol.rb')
|
|
42
|
+
autoload(:IgnorePacketProtocol, 'openc3/interfaces/protocols/ignore_packet_protocol.rb')
|
|
40
43
|
autoload(:LengthProtocol, 'openc3/interfaces/protocols/length_protocol.rb')
|
|
41
44
|
autoload(:PreidentifiedProtocol, 'openc3/interfaces/protocols/preidentified_protocol.rb')
|
|
45
|
+
autoload(:Protocol, 'openc3/interfaces/protocols/protocol.rb')
|
|
46
|
+
autoload(:SlipProtocol, 'openc3/interfaces/protocols/slip_protocol.rb')
|
|
42
47
|
autoload(:TemplateProtocol, 'openc3/interfaces/protocols/template_protocol.rb')
|
|
43
48
|
autoload(:TerminatedProtocol, 'openc3/interfaces/protocols/terminated_protocol.rb')
|
|
44
|
-
autoload(:CmdResponseProtocol, 'openc3/interfaces/protocols/cmd_response_protocol.rb')
|
|
45
|
-
autoload(:CrcProtocol, 'openc3/interfaces/protocols/crc_protocol.rb')
|
|
46
|
-
autoload(:IgnorePacketProtocol, 'openc3/interfaces/protocols/ignore_packet_protocol.rb')
|
|
47
49
|
end
|
|
@@ -231,6 +231,8 @@ module OpenC3
|
|
|
231
231
|
cmd_name = msg_hash['cmd_name']
|
|
232
232
|
manual = ConfigParser.handle_true_false(msg_hash['manual'])
|
|
233
233
|
cmd_params = nil
|
|
234
|
+
range_check = true
|
|
235
|
+
raw = false
|
|
234
236
|
cmd_buffer = nil
|
|
235
237
|
hazardous_check = nil
|
|
236
238
|
if msg_hash['cmd_params']
|
|
@@ -288,14 +290,13 @@ module OpenC3
|
|
|
288
290
|
if @critical_commanding and @critical_commanding != 'OFF' and not release_critical
|
|
289
291
|
restricted = command.restricted
|
|
290
292
|
if hazardous or restricted or (@critical_commanding == 'ALL' and manual)
|
|
293
|
+
cmd_type = 'NORMAL'
|
|
291
294
|
if hazardous
|
|
292
|
-
|
|
295
|
+
cmd_type = 'HAZARDOUS'
|
|
293
296
|
elsif restricted
|
|
294
|
-
|
|
295
|
-
else
|
|
296
|
-
type = 'NORMAL'
|
|
297
|
+
cmd_type = 'RESTRICTED'
|
|
297
298
|
end
|
|
298
|
-
model = CriticalCmdModel.new(name: SecureRandom.uuid, type:
|
|
299
|
+
model = CriticalCmdModel.new(name: SecureRandom.uuid, type: cmd_type, interface_name: @interface.name, username: msg_hash['username'], cmd_hash: msg_hash, scope: @scope)
|
|
299
300
|
model.create
|
|
300
301
|
@logger.info("Critical Cmd Pending: #{msg_hash['cmd_string']}", user: msg_hash['username'], scope: @scope)
|
|
301
302
|
next "CriticalCmdError\n#{model.name}"
|
|
@@ -428,10 +429,12 @@ module OpenC3
|
|
|
428
429
|
params = JSON.parse(msg_hash['params'], allow_nan: true, create_additions: true)
|
|
429
430
|
end
|
|
430
431
|
@router = @tlm.attempting(*params)
|
|
432
|
+
next 'SUCCESS'
|
|
431
433
|
end
|
|
432
434
|
if msg_hash['disconnect']
|
|
433
435
|
@logger.info "#{@router.name}: Disconnect requested"
|
|
434
436
|
@tlm.disconnect(false)
|
|
437
|
+
next 'SUCCESS'
|
|
435
438
|
end
|
|
436
439
|
if msg_hash.key?('log_stream')
|
|
437
440
|
if msg_hash['log_stream'] == 'true'
|
|
@@ -441,6 +444,7 @@ module OpenC3
|
|
|
441
444
|
@logger.info "#{@router.name}: Disable stream logging"
|
|
442
445
|
@router.stop_raw_logging
|
|
443
446
|
end
|
|
447
|
+
next 'SUCCESS'
|
|
444
448
|
end
|
|
445
449
|
if msg_hash.key?('router_cmd')
|
|
446
450
|
params = JSON.parse(msg_hash['router_cmd'], allow_nan: true, create_additions: true)
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
require 'openc3/microservices/microservice'
|
|
20
20
|
require 'openc3/topics/queue_topic'
|
|
21
|
+
require 'openc3/models/queue_model'
|
|
21
22
|
require 'openc3/utilities/authentication'
|
|
22
23
|
require 'openc3/api/api'
|
|
23
24
|
|
|
@@ -90,15 +91,22 @@ module OpenC3
|
|
|
90
91
|
@queue_name = @name.split('__')[2]
|
|
91
92
|
|
|
92
93
|
initial_state = 'HOLD'
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
# See if the queue already exists to get its state
|
|
95
|
+
queue = OpenC3::QueueModel.get(name: @queue_name, scope: @scope)
|
|
96
|
+
if queue
|
|
97
|
+
initial_state = queue['state']
|
|
98
|
+
else
|
|
99
|
+
(@config['options'] || []).each do |option|
|
|
100
|
+
case option[0].upcase
|
|
101
|
+
when 'QUEUE_STATE'
|
|
102
|
+
initial_state = option[1]
|
|
103
|
+
else
|
|
104
|
+
@logger.error("Unknown option passed to microservice #{@name}: #{option}")
|
|
105
|
+
end
|
|
99
106
|
end
|
|
100
107
|
end
|
|
101
108
|
|
|
109
|
+
@logger.info "Creating QueueMicroservice in scope #{@scope} for queue #{@queue_name} with initial state #{initial_state}"
|
|
102
110
|
@processor = QueueProcessor.new(name: @queue_name, state: initial_state, logger: @logger, scope: @scope)
|
|
103
111
|
@processor_thread = nil
|
|
104
112
|
@read_topic = true
|
|
@@ -56,6 +56,13 @@ module OpenC3
|
|
|
56
56
|
attr_accessor :plugin_txt_lines
|
|
57
57
|
attr_accessor :needs_dependencies
|
|
58
58
|
attr_accessor :store_id
|
|
59
|
+
attr_accessor :title
|
|
60
|
+
attr_accessor :description
|
|
61
|
+
attr_accessor :licenses
|
|
62
|
+
attr_accessor :homepage
|
|
63
|
+
attr_accessor :repository
|
|
64
|
+
attr_accessor :keywords
|
|
65
|
+
attr_accessor :img_path
|
|
59
66
|
|
|
60
67
|
# NOTE: The following three class methods are used by the ModelController
|
|
61
68
|
# and are reimplemented to enable various Model class methods to work
|
|
@@ -179,11 +186,31 @@ module OpenC3
|
|
|
179
186
|
raise "Invalid screen filename: #{filename}. Screen filenames must be lowercase."
|
|
180
187
|
end
|
|
181
188
|
end
|
|
189
|
+
|
|
190
|
+
# Process app store metadata
|
|
191
|
+
plugin_model.title = pkg.spec.metadata['openc3_store_title'] || pkg.spec.summary.strip
|
|
192
|
+
plugin_model.description = pkg.spec.metadata['openc3_store_description'] || pkg.spec.description.strip
|
|
193
|
+
plugin_model.licenses = pkg.spec.licenses
|
|
194
|
+
plugin_model.homepage = pkg.spec.homepage
|
|
195
|
+
plugin_model.repository = pkg.spec.metadata['source_code_uri'] # this key because it's in the official gemspec examples
|
|
196
|
+
plugin_model.keywords = pkg.spec.metadata['openc3_store_keywords']&.split(/, ?/)
|
|
197
|
+
img_path = pkg.spec.metadata['openc3_store_image']
|
|
198
|
+
unless img_path
|
|
199
|
+
default_img_path = 'public/store_img.png'
|
|
200
|
+
full_default_path = File.join(gem_path, default_img_path)
|
|
201
|
+
img_path = default_img_path if File.exist? full_default_path
|
|
202
|
+
end
|
|
203
|
+
plugin_model.img_path = File.join('gems', gem_name.split(".gem")[0], img_path) if img_path # convert this filesystem path to volumes mount path
|
|
204
|
+
plugin_model.update() unless validate_only
|
|
205
|
+
|
|
182
206
|
needs_dependencies = pkg.spec.runtime_dependencies.length > 0
|
|
183
207
|
needs_dependencies = true if Dir.exist?(File.join(gem_path, 'lib'))
|
|
184
208
|
|
|
185
|
-
# Handle python requirements.txt
|
|
186
|
-
|
|
209
|
+
# Handle python dependencies (pyproject.toml or requirements.txt)
|
|
210
|
+
pyproject_path = File.join(gem_path, 'pyproject.toml')
|
|
211
|
+
requirements_path = File.join(gem_path, 'requirements.txt')
|
|
212
|
+
|
|
213
|
+
if File.exist?(pyproject_path) || File.exist?(requirements_path)
|
|
187
214
|
begin
|
|
188
215
|
pypi_url = get_setting('pypi_url', scope: scope)
|
|
189
216
|
if pypi_url
|
|
@@ -202,11 +229,20 @@ module OpenC3
|
|
|
202
229
|
end
|
|
203
230
|
end
|
|
204
231
|
unless validate_only
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
232
|
+
if File.exist?(pyproject_path)
|
|
233
|
+
Logger.info "Installing python packages from pyproject.toml with pypi_url=#{pypi_url}"
|
|
234
|
+
if ENV['PIP_ENABLE_TRUSTED_HOST'].nil?
|
|
235
|
+
pip_args = "--no-warn-script-location -i #{pypi_url} #{gem_path}"
|
|
236
|
+
else
|
|
237
|
+
pip_args = "--no-warn-script-location -i #{pypi_url} --trusted-host #{URI.parse(pypi_url).host} #{gem_path}"
|
|
238
|
+
end
|
|
208
239
|
else
|
|
209
|
-
|
|
240
|
+
Logger.info "Installing python packages from requirements.txt with pypi_url=#{pypi_url}"
|
|
241
|
+
if ENV['PIP_ENABLE_TRUSTED_HOST'].nil?
|
|
242
|
+
pip_args = "--no-warn-script-location -i #{pypi_url} -r #{requirements_path}"
|
|
243
|
+
else
|
|
244
|
+
pip_args = "--no-warn-script-location -i #{pypi_url} --trusted-host #{URI.parse(pypi_url).host} -r #{requirements_path}"
|
|
245
|
+
end
|
|
210
246
|
end
|
|
211
247
|
puts `/openc3/bin/pipinstall #{pip_args}`
|
|
212
248
|
end
|
|
@@ -302,6 +338,13 @@ module OpenC3
|
|
|
302
338
|
plugin_txt_lines: [],
|
|
303
339
|
needs_dependencies: false,
|
|
304
340
|
store_id: nil,
|
|
341
|
+
title: nil,
|
|
342
|
+
description: nil,
|
|
343
|
+
keywords: nil,
|
|
344
|
+
licenses: nil,
|
|
345
|
+
homepage: nil,
|
|
346
|
+
repository: nil,
|
|
347
|
+
img_path: nil,
|
|
305
348
|
updated_at: nil,
|
|
306
349
|
scope:
|
|
307
350
|
)
|
|
@@ -310,6 +353,13 @@ module OpenC3
|
|
|
310
353
|
@plugin_txt_lines = plugin_txt_lines
|
|
311
354
|
@needs_dependencies = ConfigParser.handle_true_false(needs_dependencies)
|
|
312
355
|
@store_id = store_id
|
|
356
|
+
@title = title
|
|
357
|
+
@description = description
|
|
358
|
+
@keywords = keywords
|
|
359
|
+
@licenses = licenses
|
|
360
|
+
@homepage = homepage
|
|
361
|
+
@repository = repository
|
|
362
|
+
@img_path = img_path
|
|
313
363
|
end
|
|
314
364
|
|
|
315
365
|
def create(update: false, force: false, queued: false)
|
|
@@ -329,6 +379,13 @@ module OpenC3
|
|
|
329
379
|
'plugin_txt_lines' => @plugin_txt_lines,
|
|
330
380
|
'needs_dependencies' => @needs_dependencies,
|
|
331
381
|
'store_id' => @store_id,
|
|
382
|
+
'title' => @title,
|
|
383
|
+
'description' => @description,
|
|
384
|
+
'keywords' => @keywords,
|
|
385
|
+
'licenses' => @licenses,
|
|
386
|
+
'homepage' => @homepage,
|
|
387
|
+
'repository' => @repository,
|
|
388
|
+
'img_path' => @img_path,
|
|
332
389
|
'updated_at' => @updated_at
|
|
333
390
|
}
|
|
334
391
|
end
|
|
@@ -143,7 +143,7 @@ module OpenC3
|
|
|
143
143
|
unless triggers.is_a?(Array)
|
|
144
144
|
raise ReactionInputError.new "invalid triggers, must be array of hashes: #{triggers}"
|
|
145
145
|
end
|
|
146
|
-
trigger_hash =
|
|
146
|
+
trigger_hash = {}
|
|
147
147
|
triggers.each do | trigger |
|
|
148
148
|
unless trigger.is_a?(Hash)
|
|
149
149
|
raise ReactionInputError.new "invalid trigger, must be hash: #{trigger}"
|
|
@@ -166,10 +166,14 @@ module OpenC3
|
|
|
166
166
|
end
|
|
167
167
|
|
|
168
168
|
def self.download(target_name, scope:)
|
|
169
|
+
# Validate target_name to not allow directory traversal
|
|
170
|
+
if target_name.include?('..') || target_name.include?('/') || target_name.include?('\\')
|
|
171
|
+
raise ArgumentError, "Invalid target_name: #{target_name.inspect}"
|
|
172
|
+
end
|
|
169
173
|
tmp_dir = Dir.mktmpdir
|
|
170
174
|
zip_filename = File.join(tmp_dir, "#{target_name}.zip")
|
|
171
175
|
Zip.continue_on_exists_proc = true
|
|
172
|
-
zip = Zip::File.open(zip_filename,
|
|
176
|
+
zip = Zip::File.open(zip_filename, create: true)
|
|
173
177
|
|
|
174
178
|
if ENV['OPENC3_LOCAL_MODE']
|
|
175
179
|
OpenC3::LocalMode.zip_target(target_name, zip, scope: scope)
|
|
@@ -756,7 +760,7 @@ module OpenC3
|
|
|
756
760
|
prefix = File.dirname(target_folder) + '/'
|
|
757
761
|
output_file = File.join(temp_dir, @name + '_' + @id + '.zip')
|
|
758
762
|
Zip.continue_on_exists_proc = true
|
|
759
|
-
Zip::File.open(output_file,
|
|
763
|
+
Zip::File.open(output_file, create: true) do |zipfile|
|
|
760
764
|
target_files.each do |target_file|
|
|
761
765
|
zip_file_path = target_file.delete_prefix(prefix)
|
|
762
766
|
if File.directory?(target_file)
|
|
@@ -807,7 +811,7 @@ module OpenC3
|
|
|
807
811
|
Logger.error("Invalid text present in #{target_name} #{packet_name} tlm packet")
|
|
808
812
|
raise e
|
|
809
813
|
end
|
|
810
|
-
json_hash =
|
|
814
|
+
json_hash = {}
|
|
811
815
|
packet.sorted_items.each do |item|
|
|
812
816
|
json_hash[item.name] = nil
|
|
813
817
|
TargetModel.add_to_target_allitems_list(target_name, item.name, scope: @scope)
|