diff --git a/.gencode_hash.txt b/.gencode_hash.txt index 1a25f426d..67bc8015c 100644 --- a/.gencode_hash.txt +++ b/.gencode_hash.txt @@ -1,27 +1,27 @@ b35646a2f3d7c30fd34e3ea6ab6a1070b39c469fd1de49cab1093ff32faaf06d gencode/docs/command_discovery.html 3e292717e9b220403c250eebcfb4132becb6f59546f0bd3c3ec3042c31986d48 gencode/docs/command_mapping.html -ca860612da2fddd2747d5a1f765efe9205be37b0ad4b327052320f915eb17948 gencode/docs/config.html +64bafb080b454189b7b64a95e049c3427fd1cca70cf0809a31150610f40e9525 gencode/docs/config.html 73b3beb740f5bc3ff26d173c356b2d3bf3b9892be83a704d3eeee7c9ff030230 gencode/docs/config_mapping.html b12d1fd583bc750b99aa343beea680d08fdc0110c6da8684cee24800c8cfaea0 gencode/docs/configuration_endpoint.html b7ca70e3176f997f254c32bd8d53dff1462ac8a71c0e166aaa85193d67bff60b gencode/docs/configuration_execution.html 4ac5b147d64b5a10408649dec791ac3b4d55a4c45f3f63489e1a980dbb1c4293 gencode/docs/configuration_pubber.html 0f0355e343cb8197dfbae1481c0eca3a0566d73181bc968e33fd469a1c94d1e6 gencode/docs/envelope.html -490e684c7710138b6c9fd41b131acf6638df64d715e35c799bd95a06756b7d87 gencode/docs/event.html +92da453dec3e27493216f8c3672b6203be9eb9b3086741c22fda9432c22504b7 gencode/docs/event.html e81e06349dd9d88a57d7f6119da1fee2832b07fe8190b6df139e26777e7e76bc gencode/docs/event_discovery.html 9497b83603d537e11e264ee2d8056b298f5a5178e2c6aa435a6c9c0a051414b4 gencode/docs/event_mapping.html 71fe25d3b17d1dc87b52c049a3235c20527f73e12ffa53fa4800a15e53f73732 gencode/docs/event_pointset.html -3851c5c20c1938a14e21d7a4e329377b4582b7f88f1b18c0e9b34656e316e35e gencode/docs/event_system.html +c601733d04b0d389d7800a801b0862da41567d1f1fa63d9529a462b8269f0462 gencode/docs/event_system.html 301d174a945f82816c9640450e072c55abdcb37383b76428e6d37dfbc6aa9dfe gencode/docs/event_validation.html 9ae793a641f2e053c5af734bf813cd2637a675330acb8d9e903ef03b4286e007 gencode/docs/metadata.html f01a413b528783682ecbc3b846d677490aa1e0a0cf15867e2305cee60a1f4a8e gencode/docs/persistent_device.html 5d039d607af9ec75ee552dfe36b16c702687ea16f5663f41fc49b4533b86e00d gencode/docs/properties.html 392f272c1c8cd047eb6906f2f11ffacc7083c32f639da2437d6a9ca861062ecc gencode/docs/readme.md -690d56e96c4e180e49e0abcba358ab1842ea06dd3f693918852a9de370c994d5 gencode/docs/reflect_config.html +f46367beaab5886ef87ce70b542611134c3565daa53e367de4f49dab51214f12 gencode/docs/reflect_config.html 9332e44c87dae9261b079424e748d5ee1df08a3c6b39987d254ebf78274e2f34 gencode/docs/reflect_state.html 741b880216be3743f6747800a042f2dbd89f3b0344c6b0a965f4bc010f03a930 gencode/docs/schema_doc.css 878ea88206c974f40643c3cc430875f9c4e8c5e3fd6bcd6358bd3eb6d48699a9 gencode/docs/schema_doc.min.js 7ed934930aee763e0beebc349725ba3909115e8d346bb762f28bcbe745bb163a gencode/docs/schema_extras.js -a63c6d5ab8e3fd869d584578b5a850a86e43247f860d2830a4565da83f25b3e1 gencode/docs/state.html +63cd94346f634ca2945982c147546cb1103fcfea4c42eac04b065ca838f5217f gencode/docs/state.html f10172c9b4cd350cae1f673077b07b1362168599b966a78d4ec4ef19b7bbf441 gencode/docs/state_mapping.html 552f85739f547960d2c1b96c99152ff831a036ce4d19908a5361b35a2d5f2132 gencode/docs/state_validation.html d39d7fe37a41c74a40080af7b0a429d201ab1fdff7444428c4b98eb7b38c332b gencode/java/udmi/schema/Asset.java @@ -71,7 +71,8 @@ b815ba1f198fd32b11fbedf71e5fa820bba08713dc5c95603c700dfa21ec5904 gencode/java/u 052b6b7f9ca8173901d9d2fae314f5858e034f20efa5d184780b800bd870cb2b gencode/java/udmi/schema/MappingEventEntity.java d2bf4eea0ca3df47b9ffe31481a52170e2d2bc3a0e7f2eab582e93cc20ccc886 gencode/java/udmi/schema/MappingState.java 304164da05dc722b6e94cfa68659f0120e2425c94bfb5f5a4c6d796fe13da885 gencode/java/udmi/schema/Metadata.java -bce55f08bba033c8dd05f63a91d99f86d2039f833130a1188eec8c774a115b50 gencode/java/udmi/schema/Metrics.java +df64e4ddbf543ac70e7c2af9d3fbc20ffe3dff68c6718aa9ceadab7f64d3d171 gencode/java/udmi/schema/Metrics.java +e49db649d7080e0b54cd7dc556bf58ff6afd1688c9394fdeeb5103b64ab91730 gencode/java/udmi/schema/Operation.java 5e1c5411fae4d7c47391ceb5d19ae864fcd484df75ac6b6db39fd2d12647dec8 gencode/java/udmi/schema/Physical_tag.java d808259db6bbcd26ecf438844ce286d15d4750906be24588d97acfbe8a4ae315 gencode/java/udmi/schema/PointEnumerationEvent.java eb478a6ebd66b150da8d6dc8fdf05a10d09d6d0ea1df8a0578728703718c5551 gencode/java/udmi/schema/PointPointsetConfig.java @@ -89,15 +90,17 @@ ca2e7566106818ca7e5190c8041eb86f0c9b3251b0bda8c3ea7ce11a0c891a0a gencode/java/u 997acde04cef70d3f6d009a21f3ce4f3d06e6c3093736c03fdc82d78ffea1aa8 gencode/java/udmi/schema/PubberOptions.java 7bc53cb9a61df8f804a75aa4860403d19281f7c665cbddd5364a2aa746a1f651 gencode/java/udmi/schema/ReflectorConfig.java abe99dd74122c186403baa6982300a9d5968f8bbb7a67b1689104111b98f32fb gencode/java/udmi/schema/ReflectorState.java -5a44075bc03f2b9b2cc090f007fd1692832871f0981dcb02579d8dda96a96206 gencode/java/udmi/schema/SetupReflectorConfig.java +362499688dd17f0596e5d6f064db0fe3bb3f3a25bdf01319624ba423de779220 gencode/java/udmi/schema/SetupReflectorConfig.java 649c0291ad81421fc51da0c2f7da3286628127157a5a6eef77610e8c37c14941 gencode/java/udmi/schema/SetupReflectorState.java 580df660dad1b97399002271716d597f72aa1a6110a49de9e162104c231752f4 gencode/java/udmi/schema/State.java -b2274107ce0e4e663b2a35e2ca284e492ec683bd687f6b8d8b014d5f8be67233 gencode/java/udmi/schema/SystemConfig.java -7de481ba531ea915a57cb6c5b23278db4fac6588354683cf63613b20c522af24 gencode/java/udmi/schema/SystemDiscoveryEvent.java +47ad54328160a1aabce719a3263d4bfea903e8e8255e04a54ace86eb095b0f0c gencode/java/udmi/schema/StateSystemHardware.java +c9b920d355e5f6350fa6eb978afbfe55dd1438df171d2ea215845d5ac0b3e7e9 gencode/java/udmi/schema/StateSystemOperation.java +d771dcb6bd06620e4e21419420d252b1f4aa0c55d0be315d6310299cebff56d6 gencode/java/udmi/schema/SystemConfig.java +6f7b213970bfe2b1ac3056b83da8c8f5b4c50eac221dc1d6c6887e193e8bf40c gencode/java/udmi/schema/SystemDiscoveryEvent.java 21ca023d5a9006b1e041fcf644d572270b5743fcd2d2f221364a3046f0c5609c gencode/java/udmi/schema/SystemEvent.java 2cf23174ef4e2876511fb471d3f9fcb5cefe2fde324db844c2d0d505fd2c8844 gencode/java/udmi/schema/SystemHardware.java ceacfb4a1d0a4b4f4110b0e0717e57f2bbfd80ef18599d24fab19ddf497f399e gencode/java/udmi/schema/SystemModel.java -64e5b9a2c5699a3ca3b13dc6cb0243ff5b4c90908a14e3f11c5298ae89c8b261 gencode/java/udmi/schema/SystemState.java +7d8d9f058878d3228a2042b8ffe6a5d897548c32b218307004101699aa17c2b3 gencode/java/udmi/schema/SystemState.java 7d6dd13e368e7f073738fee69c15e18652a9b7d7ac63bde0a200f747e3aa1b1d gencode/java/udmi/schema/TargetTestingModel.java d3968b92497e83a63f18cc0e74484a9807f1bb92db0c92d556ec2caaa143d645 gencode/java/udmi/schema/TestingModel.java 7793d6d76a430dc7acf668d92d2df5f8e0625d6228207731f96e220f3b90e659 gencode/java/udmi/schema/TestingSystemConfig.java @@ -105,7 +108,7 @@ ac6f8fd87c8986cce01e872460c15ff6fe71e3816f9bde610acfe25f7d38c8d4 gencode/java/u f7d117dc8b9764acf0c95a13a2bfdfbdf31d1a8ec83a707448aa4d7391ef07e2 gencode/java/udmi/schema/ValidationState.java e007ddd1ceeae3603c85110c33e1bb4a418ff9c7a791ca0df25b7ea3caeafd36 gencode/java/udmi/schema/ValidationSummary.java b77d953fd22e655c0f10ae32deeaa222769d971f8c38b3379eba45720fb910cc gencode/java/udmi/schema/VirtualEquipmentLinks.java -bef6dcfef0ed87cc87178b82c0ed702969c69d827aac6e69d45ff76518605e12 gencode/python/udmi/schema/__init__.py +67553fdfe44896f487a7d4cf8161537e2595d48a96f8e44a1f9bac4a6d71591a gencode/python/udmi/schema/__init__.py 4b25dd95f863059b761269f93adcae7049507924a1c6e74d6856849203c179db gencode/python/udmi/schema/ancillary_properties.py dab4f5fca272ec48c2881bca2b6bc43786ada47fa1f6dd935c35f7ce0eb6b0f6 gencode/python/udmi/schema/building_translation.py 470b688984b89b25fcdfa8e08bd95b0c5d8c551d53a6ab5512503ee39419e6fa gencode/python/udmi/schema/category.py @@ -123,7 +126,7 @@ ac3facbd96f7cb2f7e387e7497d6a36af379a2687329571f250c5670f9933244 gencode/python 1867ee8f1f4552ff121b7a2a62815817b2c9939a8817f1e093fbd688b8faa1a4 gencode/python/udmi/schema/config_mapping_device.py 9eab64849e04b25203d5da47856c3f8dda2b96903e4dc43ab932ee35014700bd gencode/python/udmi/schema/config_pointset.py 33ce7ee99051d56dd3c4d69edf92583d0bb7fd751417948b71292ac2285d3c19 gencode/python/udmi/schema/config_pointset_point.py -ba37d2d54df565aba42ef055a0ec961175d180c2e8092a914e62029bc5388857 gencode/python/udmi/schema/config_system.py +7da3bdb37f338260d5f3829fa5fcbb9bbf9f146b514a68319c314a96c6b8ac12 gencode/python/udmi/schema/config_system.py cce623b34fd694880039a1c080214c33e00acaef5bc72276cf11a3bb2de40000 gencode/python/udmi/schema/config_system_testing.py cda883348ee365c981355c0bab1eea1745768a7dd03197ba1370813d95aca225 gencode/python/udmi/schema/configuration_endpoint.py e8a1574074554b6144b178d2adedc76a1c7be5ae911b253deff4460d8d82c6ee gencode/python/udmi/schema/configuration_execution.py @@ -131,7 +134,7 @@ e8a1574074554b6144b178d2adedc76a1c7be5ae911b253deff4460d8d82c6ee gencode/python 998ce105f88686f27b85f3630a396ed04b106f830c133a684ea5c505ca95b1c3 gencode/python/udmi/schema/envelope.py ed8ace0196c5e99d20778cb4210aa88cfe44a5e4539af98a1e194b9a71fa538e gencode/python/udmi/schema/equipment_translation.py 1eb9019b9d0b4ff7de2df8beb625a4f89292d636ece0c02f160495c537bd6c2c gencode/python/udmi/schema/event.py -aae3399ce27d070b553d6d1da8001ad65f61a8c1705bf2827e35b858ee637dae gencode/python/udmi/schema/event_discovery.py +bdc5ee3e4779f2dc28bafa57461aeea69bf02877d289848b669c55fa8aa570ec gencode/python/udmi/schema/event_discovery.py ad33b91a7fabb4eed7e49c30a983a2106c96330facbe0f376f94d06e2263d6d0 gencode/python/udmi/schema/event_discovery_family.py 42e6fb6edda2b6aeae5e5b48ae66f87a5daf336bca1e746b1157e8f1ce31d5d5 gencode/python/udmi/schema/event_discovery_point.py 50bdecfa353d86d04a1ad0ebac5b3625f8fd4ee8a1e2f8e51b29055a37d9685c gencode/python/udmi/schema/event_mapping.py @@ -139,7 +142,7 @@ ad33b91a7fabb4eed7e49c30a983a2106c96330facbe0f376f94d06e2263d6d0 gencode/python 3652a73a7df2d9df18a45b72d948c38a84a61e008d7543d006dad1832640c54f gencode/python/udmi/schema/event_mapping_entity.py ddf849bfeb2b87d071cefd5e6feacabc57375a7fff6d72b6d42ffb89f33c859b gencode/python/udmi/schema/event_pointset.py 44aff1bc930dbdbadd51ac3fe0e7d9c83ad84a6a9f9d1c809b3fce66cbcd5e00 gencode/python/udmi/schema/event_pointset_point.py -72b8c0c02951e5bbd37ad6fb8b8a035a45ed6ef1da642a664d517e86bb15d5a8 gencode/python/udmi/schema/event_system.py +d89500d1e1c88ac754ddc5abd13135dd140d40c60568ca9294f6fe384b0b12ef gencode/python/udmi/schema/event_system.py fb8a8a0e09eca4bb061c6cb2ff91b8eee77203e6ea353d3356e411692e1e4f2a gencode/python/udmi/schema/event_validation.py 2bb36986f805c2127f0c300de07bce07897c0c6d8f504bddec6e201d0f0ab1bf gencode/python/udmi/schema/event_validation_device.py 42f3429edf4a187be6ebfe9760f5e14821a25afa8f7c65b69e0e34fb29a7932e gencode/python/udmi/schema/metadata.py @@ -158,7 +161,7 @@ aafe6e70c281152db958adf77a024e3e9fab8293927106297c5ec48c11f54e27 gencode/python e8e694e260bb70998d228e14516b2fedb7e9d82e68f5586a7e78d0573bd2de8b gencode/python/udmi/schema/options_pubber.py 6c5f3dd1c5ca9d821e3c48298af118fc7eafd97af9265dfd34b2ed8642efca77 gencode/python/udmi/schema/persistent_device.py a58f8c98e837a5b56126ca0f410e02f1e9cfcd80a8cb429e0ef522defab1f690 gencode/python/udmi/schema/properties.py -1f521678016ad267ad1c817896c7900ba30a85fc694669577b71148193db32c1 gencode/python/udmi/schema/reflect_config.py +5dad0f2ee3e94ec32d11d1de3bfde35d087d3561ee18c0a9eeb0722d17d0f58a gencode/python/udmi/schema/reflect_config.py 1a4eef286957d77418777eb7f4cd1ee13aa24c2d916ec71a7ff4e56de76e303e gencode/python/udmi/schema/reflect_state.py 32bc70a30e37e89cfae14b44add18d546a6f9e00a3ec3519ede9c7486114d39c gencode/python/udmi/schema/state.py 4a908cee3fb8afb559bcbfa594e57dbc515a35e4468e02600751b2fcce05a238 gencode/python/udmi/schema/state_blobset.py @@ -170,7 +173,8 @@ cb6a5558fe87dea5bce9e1cc6b22984a7d8c379babc4941c50df13edad36579a gencode/python f2a76b32a5568d87a8c9ca8b32dc8a129bc7386f9522c5399d32db433be4cb70 gencode/python/udmi/schema/state_mapping_device.py 3520ad936af70b414d9e7f90e606a011768bc4ee3bf1248714acc517ee9b393d gencode/python/udmi/schema/state_pointset.py 837ecc89c477abe3a1faf837733ca05475774891b55353d84ca231d90a1fbf31 gencode/python/udmi/schema/state_pointset_point.py -8184e783f3e2da5a6d3fb7e7fac105aaeb28106a7c146e82b610049554abf184 gencode/python/udmi/schema/state_system.py -791006619518fd7b38adb532879bcacd6f3f8795026cd75e10d3434a177757ac gencode/python/udmi/schema/state_system_hardware.py +8a601de0130081eec02724fd554749b7bd96d02874b0a3557d461cced41bd09b gencode/python/udmi/schema/state_system.py +8a0bf4294fb70533a056322a6bfc6f13a963381d2100d1468d8b6de757cd72e9 gencode/python/udmi/schema/state_system_hardware.py +37c55dce0e38dddad3cebb3d40270128a4dbb7b586657d1746bb96dac90e2ac1 gencode/python/udmi/schema/state_system_operation.py 231479e4dd7d961d59149580aba6a99cd466cea553400f338e9da2bf3ffbe78c gencode/python/udmi/schema/state_validation.py 83a57db63df10d43b1789c3f115a515c23bb7bc7a8cc8c2accdc17d0cbac89fe gencode/python/udmi/schema/virtual_links.py diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 6ce14d665..ec5fef66d 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -24,17 +24,17 @@ jobs: python-version: '3.10' - name: Checkout source uses: actions/checkout@v2.3.4 - - name: Install dependencies + - name: bin/run_tests install_dependencies run: bin/run_tests install_dependencies - - name: code checks + - name: bin/run_tests code_checks if: ${{ always() }} run: bin/run_tests code_checks - - name: Schema conformance tests + - name: bin/run_tests schema_tests if: ${{ always() }} - run: bin/run_tests schema_conformance_tests - - name: simple trace test - run: bin/run_tests simple_trace_test - - name: Registrar tests + run: bin/run_tests schema_tests + - name: bin/run_tests trace_tests + run: bin/run_tests trace_tests + - name: bin/run_tests registrar_tests if: ${{ always() }} run: bin/run_tests registrar_tests @@ -92,7 +92,7 @@ jobs: udmi: name: Integration Tests runs-on: ubuntu-latest - timeout-minutes: 40 + timeout-minutes: 30 steps: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 @@ -107,8 +107,6 @@ jobs: run: | bin/test_validator $GCP_TARGET_PROJECT more /tmp/validator.out - echo Comparing test run results with golden file: - diff -u /tmp/validator.out etc/validator.out - name: sequence tests env: GCP_TARGET_PROJECT: ${{ secrets.GCP_TARGET_PROJECT }} diff --git a/bin/check_version b/bin/check_version index f574ceecf..86dd03a1f 100755 --- a/bin/check_version +++ b/bin/check_version @@ -15,7 +15,7 @@ if [[ -z $origin ]]; then origin=faucetsdn fi -git fetch $origin --tags 2>/dev/null +git fetch $origin --tags 2>/dev/null || true upstream_ver=`git describe $origin/$branch --abbrev=0 || echo unknown` current_ver=`git describe HEAD --abbrev=0 || echo unknown` diff --git a/bin/clone_model b/bin/clone_model index 9bea6b5e9..0629cce55 100755 --- a/bin/clone_model +++ b/bin/clone_model @@ -5,7 +5,7 @@ mkdir -p $ROOT_DIR/sites cd $ROOT_DIR/sites MODEL_DIR=udmi_site_model -MODEL_VER=1.8 +MODEL_VER=1.9 TEST_SITE_GIT=https://github.com/faucetsdn/$MODEL_DIR.git MODEL_REPO=origin diff --git a/bin/run_tests b/bin/run_tests index 432986278..37e494b0d 100755 --- a/bin/run_tests +++ b/bin/run_tests @@ -5,13 +5,13 @@ function usage() { $0 [step] -step is one of: - +where [step] is one of: install_dependencies code_checks - schema_conformance_tests - simple_trace_test + schema_tests + trace_tests registrar_tests + all_tests EOF false } @@ -27,16 +27,22 @@ case "$1" in validator/bin/build check bin/test_pylint ;; - schema_conformance_tests) - bin/test_schema -p + schema_tests) + bin/test_schema ;; - simple_trace_test) + trace_tests) bin/test_trace simple ;; registrar_tests) bin/test_registrar bin/test_sites - ;; + ;; + all_tests) + bin/run_tests code_checks + bin/run_tests schema_tests + bin/run_tests trace_tests + bin/run_tests registrar_tests + ;; *) usage ;; diff --git a/bin/test_redirect b/bin/test_redirect index 8b73c79c9..5bd1f79e7 100755 --- a/bin/test_redirect +++ b/bin/test_redirect @@ -70,7 +70,9 @@ sha256=$(openssl sha256 < out/endpoint.json | awk '{print $2}') cat < out/blobs.json { "system": { - "mode": "active" + "operation": { + "mode": "active" + } }, "blobset": { "blobs": { @@ -86,7 +88,7 @@ EOF # Merge JSON files together into new redirect config jq -s '.[0] * .[1]' $out_base/generated_config.json out/blobs.json > $out_base/redirect_config.json -jq '.system.mode = "restart"' $out_base/redirect_config.json > $out_base/restart_config.json +jq '.system.operation.mode = "restart"' $out_base/redirect_config.json > $out_base/restart_config.json echo New redirection config: cat /tmp/${device_id}_config.json @@ -107,7 +109,7 @@ sleep 20 # Now test that pubber responds to an later last_start config (to trigger automatic shutdown) now_date=$(python3 -c 'import datetime; print(datetime.datetime.utcnow().isoformat() + "Z")') echo Setting last_start time to $now_date for pubber shutdown... -jq ".system.last_start = \"$now_date\"" $out_base/redirect_config.json > $out_base/shutdown_config.json +jq ".system.operation.last_start = \"$now_date\"" $out_base/redirect_config.json > $out_base/shutdown_config.json echo bin/reset_config $site_path $project_id $device_id shutdown_config.json bin/reset_config $site_path $project_id $device_id shutdown_config.json diff --git a/bin/test_schema b/bin/test_schema index bdc5f6352..498db7d0d 100755 --- a/bin/test_schema +++ b/bin/test_schema @@ -10,12 +10,12 @@ rm -f $errorfile build=y force=n -parallel= +upgrade= schemadir=schema testdir=tests -while getopts "d:s:fnp" opt; do +while getopts "d:s:fnu" opt; do case $opt in f) force=y @@ -23,17 +23,17 @@ while getopts "d:s:fnp" opt; do n) build=n ;; + u) + upgrade=-u + ;; s) subsets=${OPTARG} ;; d) testdir=${OPTARG} ;; - p) - parallel=y - ;; \?) - echo "Usage: $0 [-p] [-f] [-n] [-d TEST_DATA_DIR] [-s TEST_SUBSET]" + echo "Usage: $0 [-f] [-n] [-u] [-d TEST_DATA_DIR] [-s TEST_SUBSET]" exit -1 ;; esac @@ -48,10 +48,6 @@ fi jarfile=$(realpath validator/build/libs/validator-1.0-SNAPSHOT-all.jar) -if [[ -n $parallel ]]; then - echo ========================= Running validation tests in parallel... -fi - if [[ -z $subsets ]]; then subsets=$(cd $testdir; ls -d *.tests) fi @@ -63,6 +59,18 @@ echo Testing against $subsets for subset in $subsets; do schemaname=${subset%.tests}.json testfiles=$(cd $testdir/$subset; ls *.json || true) + testbase=$testdir/$subset + + echo ================================== $subset + + if [[ "$testbase" == "$schemadir" ]]; then + reltest=$subset + else + reldir=$(realpath --relative-to $schemadir $testdir) + reltest=$reldir:$subset + fi + (cd $schemadir; java -jar -Dnashorn.args=--no-deprecation-warning $jarfile -a $schemaname $upgrade -f $reltest) || true + for testfile in $testfiles; do outfile=${testfile%.json}.out testbase=$testdir/$subset @@ -88,27 +96,21 @@ for subset in $subsets; do reldir=$(realpath --relative-to $schemadir $testdir) reltest=$reldir:$(realpath --relative-to $testdir $testpath) fi - ( - (cd $schemadir; java -jar -Dnashorn.args=--no-deprecation-warning $jarfile -a $schemaname -f $reltest) || true - if [ $force == y ]; then - diff $output $expected || echo Updating $expected && cp $output $expected - else - diff -b $output $expected || (echo ' ' diff $output $expected | tee -a $errorfile) - fi - ) & - if [[ -z $parallel ]]; then - wait + if [ $force == y ]; then + diff $output $expected || echo Updating $expected && cp $output $expected + else + diff -b $output $expected || (echo ' ' diff $output $expected | tee -a $errorfile) + fi + + if [[ -n $upgrade ]]; then + upgrade_new=${output%.out}.json + diff $upgrade_new $testpath || (echo cp $upgrade_new $testpath | tee -a $errorfile) fi done done -if [[ -n $parallel ]]; then - sleep 5 - echo ========================= Waiting for validation results... - wait -fi - +echo ================================== echo if [ -f $errorfile ]; then diff --git a/bin/test_validator b/bin/test_validator index 308f95a2c..f6d115075 100755 --- a/bin/test_validator +++ b/bin/test_validator @@ -118,3 +118,5 @@ more /dev/null $outfiles | sed -E >> $TMP_VALIDATOR \ -e "s/[0-9-]{10}T[0-9:]{8}Z/1999-10-20T01:02:03Z/" \ -e "s/Validator.java:[0-9]+/redacted/" \ -e 's/\\t[a-zA-Z .()$0-9]+\.java:[0-9]+\)\\n/\\tredacted\\n/g' \ + +diff -u $TMP_VALIDATOR etc/validator.out && echo No mismatch from golden file. diff --git a/bin/upversion b/bin/upgrade_version similarity index 99% rename from bin/upversion rename to bin/upgrade_version index 539bfacd5..41aff6626 100755 --- a/bin/upversion +++ b/bin/upgrade_version @@ -1,7 +1,7 @@ #!/bin/bash -e # # Usage: -# bin/upversion NEW_VERSION +# bin/upgrade_version NEW_VERSION # # Changes the version where it is hardcoded in UDMI files, performing checks # that the new version is available, and that the files can be safely updated. diff --git a/common/src/main/java/com/google/udmi/util/GeneralUtils.java b/common/src/main/java/com/google/udmi/util/GeneralUtils.java index e85db5bf1..e7f9dc1d1 100644 --- a/common/src/main/java/com/google/udmi/util/GeneralUtils.java +++ b/common/src/main/java/com/google/udmi/util/GeneralUtils.java @@ -5,7 +5,10 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.util.ISO8601DateFormat; import com.google.common.hash.Hashing; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.OutputStream; +import java.io.PrintStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Base64; @@ -133,4 +136,18 @@ public static String encodeBase64(String payload) { public static String encodeBase64(byte[] payload) { return Base64.getEncoder().encodeToString(payload); } + + /** + * Get a string of the java stack trace. + * + * @param e stack to trace + * @return stack trace string + */ + public static String stackTraceString(Throwable e) { + OutputStream outputStream = new ByteArrayOutputStream(); + try (PrintStream ps = new PrintStream(outputStream)) { + e.printStackTrace(ps); + } + return outputStream.toString(); + } } diff --git a/common/src/main/java/com/google/udmi/util/JsonUtil.java b/common/src/main/java/com/google/udmi/util/JsonUtil.java index 0547e3ace..ef7d10899 100644 --- a/common/src/main/java/com/google/udmi/util/JsonUtil.java +++ b/common/src/main/java/com/google/udmi/util/JsonUtil.java @@ -102,7 +102,7 @@ public static T convertTo(Class targetClass, Object message) { } /** - * Convert the pojo to a mapped representaiton. + * Convert the pojo to a mapped representation. * * @param message input object to convert * @return object-as-map @@ -113,6 +113,18 @@ public static Map toMap(Object message) { return map; } + /** + * Convert the given input file to a mapped representation. + * + * @param inputFile input file to convert to a map + * @return object-as-map + */ + public static Map toMap(File inputFile) { + @SuppressWarnings("unchecked") + Map map = convertTo(TreeMap.class, loadFile(TreeMap.class, inputFile)); + return map; + } + /** * Convert an object to a json string. * diff --git a/docs/guides/development.md b/docs/guides/development.md index e629974ba..f3122d5a2 100644 --- a/docs/guides/development.md +++ b/docs/guides/development.md @@ -28,19 +28,19 @@ section ## Releases -The `bin/upversion` tool updates : +The `bin/upgrade_version` tool updates : * the `$udmi_version` field in schema files, * the version in `version` of of manually curated payloads in `tests/*.tests` * documentation inline message examples. * the `UDMI_VERSION` constant in specific JAVA files. File in the `tests` directory must be listed in `etc/upversion.txt`. Only files -which are preceded by a `y` in `upversion_yay.txt` will have their version upgraded. Comments are supported after the file path, e.g. +which are preceded by a `y` in `upversion.txt` will have their version upgraded. Comments are supported after the file path, e.g. `y tests/state.tests/makemodel_upgrade.json tests message upgrade from v1` -`bin/upversions` carries out several checks on files which must be cleared before an update. +`bin/upgrade_version` carries out several checks on files which must be cleared before an update. -`bin/upversion` does not update any generated files (e.g. for CI testing). +`bin/upgrade_version` does not update any generated files (e.g. for CI testing). The following files need to be update: * After `bin/test_trace simple`, contents of `sites/udmi_site_model/sites/out/devices` diff --git a/docs/specs/sequences/endpoint_reconfiguration.md b/docs/specs/sequences/endpoint_reconfiguration.md index 5a581e433..0c30169cc 100644 --- a/docs/specs/sequences/endpoint_reconfiguration.md +++ b/docs/specs/sequences/endpoint_reconfiguration.md @@ -108,7 +108,7 @@ a successful reconfiguration ```json { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2022-07-13T12:00:10.000Z", "system": { "hardware": { @@ -120,7 +120,9 @@ a successful reconfiguration }, "serial_no": "000000", "last_config": "2022-07-13T12:00:00.000Z", - "operational": true + "operation": { + "operational": true + } }, "blobset": { "blobs": { @@ -136,7 +138,7 @@ This is an example of the state message sent to the original endpoint after a fa ```json { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2022-07-13T12:00:11.000Z", "system": { "hardware": { @@ -148,7 +150,9 @@ This is an example of the state message sent to the original endpoint after a fa }, "serial_no": "000000", "last_config": "2022-07-13T12:00:00.000Z", - "operational": true + "operation": { + "operational": true + } }, "blobset": { "blobs": { diff --git a/docs/specs/sequences/generated.md b/docs/specs/sequences/generated.md index b9cfe7996..d0e4cd47c 100644 --- a/docs/specs/sequences/generated.md +++ b/docs/specs/sequences/generated.md @@ -66,7 +66,6 @@ Check that the device correctly handles a broken (non-json) config message. 1. Force reset config 1. Check that no interesting system status 1. Update config before last_config updated: - * Add `system.last_start` = `device reported` * Set `system.min_loglevel` = `100` 1. Wait for last_config updated 1. Wait for log category `system.config.apply` level `NOTICE` was logged @@ -140,8 +139,6 @@ Check connection to an alternate project. * Add `blobset` = { "blobs": { "_iot_endpoint_config": { "phase": `final`, "generation": `blob generation`, "sha256": `blob data hash`, "url": `endpoint url` } } } 1. Wait for blobset phase is apply and stateStatus is null 1. Check that no interesting system status -1. Update config before blobset phase is final and stateStatus is null: - * Add `system.testing.endpoint_type` = `alternate` 1. Wait for blobset phase is final and stateStatus is null 1. Check that no interesting system status 1. Wait for alternate last_config matches config timestamp @@ -152,8 +149,6 @@ Check connection to an alternate project. * Add `blobset.blobs._iot_endpoint_config` = { "phase": `final`, "generation": `blob generation`, "sha256": `blob data hash`, "url": `endpoint url` } 1. Wait for blobset phase is apply and stateStatus is null 1. Check that no interesting system status -1. Update config before blobset phase is final and stateStatus is null: - * Remove `system.testing.endpoint_type` 1. Wait for blobset phase is final and stateStatus is null 1. Check that no interesting system status 1. Wait for restored last_config matches config timestamp @@ -300,21 +295,23 @@ Check that the min log-level config is honored by the device. Restart and connect to same endpoint and expect it returns. 1. Wait for last_start is not zero -1. Update config before deviceState.system.mode == ACTIVE: - * Add `system.mode` = `active` -1. Wait for deviceState.system.mode == ACTIVE -1. Update config before deviceState.system.mode == INITIAL: - * Set `system.mode` = `restart` -1. Wait for deviceState.system.mode == INITIAL -1. Update config before deviceState.system.mode == ACTIVE: - * Set `system.mode` = `active` -1. Wait for deviceState.system.mode == ACTIVE +1. Check that initial count is greater than 0 +1. Update config before system mode is ACTIVE: + * Add `system.operation.mode` = `active` +1. Wait for system mode is ACTIVE +1. Update config before system mode is INITIAL: + * Set `system.operation.mode` = `restart` +1. Wait for system mode is INITIAL +1. Check that restart count increased by one +1. Update config before system mode is ACTIVE: + * Set `system.operation.mode` = `active` +1. Wait for system mode is ACTIVE 1. Wait for last_config is newer than previous last_config after abort 1. Wait for last_start is newer than previous last_start ## valid_serial_no -1. Wait for received serial no matches +1. Wait for received serial number matches ## writeback_failure diff --git a/gencode/docs/config.html b/gencode/docs/config.html index 283417026..ae13a1925 100644 --- a/gencode/docs/config.html +++ b/gencode/docs/config.html @@ -215,18 +215,18 @@

-
+
-
+

- +

-
+
Type: enum (of string)
+ operation
Type: object
+ No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ + Type: enum (of string)

Operating mode for the device. Default is 'active'.

-
+

Must be one of:

  • "initial"
  • "active"
  • "restart"
  • "shutdown"
@@ -261,18 +304,18 @@

Must be one of:

-
+
-
+

- +

-
+
Type: string
+ operation + + + + last_start
Type: string

Last time a device with this id said it restarted: being later than status-supplied last_start indicates resource conflict.

@@ -298,6 +348,10 @@

+

+
+
+
diff --git a/gencode/docs/event.html b/gencode/docs/event.html index aa7689649..db687aa53 100644 --- a/gencode/docs/event.html +++ b/gencode/docs/event.html @@ -2348,53 +2348,6 @@

-
-
-
-

- -

-
- -
-
- - Type: integer
- - - - - - - -
-
-
-
diff --git a/gencode/docs/event_system.html b/gencode/docs/event_system.html index 2d92f00ae..f4169aac4 100644 --- a/gencode/docs/event_system.html +++ b/gencode/docs/event_system.html @@ -2029,46 +2029,6 @@

-
-
-
-

- -

-
- -
-
- - Type: integer
- - - - - - - -
-
-
-
diff --git a/gencode/docs/reflect_config.html b/gencode/docs/reflect_config.html index 02ce54df4..5db1eac0e 100644 --- a/gencode/docs/reflect_config.html +++ b/gencode/docs/reflect_config.html @@ -130,6 +130,46 @@

+
+
+
+

+ +

+
+ +
+
+ + Type: integer
+ + + + + + + +
+
+
+
diff --git a/gencode/docs/state.html b/gencode/docs/state.html index 83b840ed2..e1cf0b3ce 100644 --- a/gencode/docs/state.html +++ b/gencode/docs/state.html @@ -264,18 +264,18 @@

-
+
-
+

- +

-
+
Type: boolean
+ operation
Type: object
+

A collection of state fields that describes the system operation

+
+ + No Additional Properties + + + + + + +
+
+
+

+ +

+
+ +
+
+ + Type: boolean

Operational status of the device.

@@ -305,18 +351,18 @@

-
+
-
+

- +

-
+
Type: enum (of string)
-

Operating mode for the device. Default is 'active'.

+ operation + + + + last_start
Type: string
+

Last time the system started up.

+ -
-

Must be one of:

-
  • "initial"
  • "active"
  • "restart"
  • "shutdown"
-
+ + + + +
+
+
+
+
+
+
+

+ +

+
+ +
+
+ + Type: integer
+

Number of system restarts

+
@@ -351,18 +447,18 @@

Must be one of:

-
+
-
+

- +

-
+
Type: string
-

Last time the system started up.

+ operation + + + + mode
Type: enum (of string)
+

Operating mode for the device. Default is 'active'.

+ +
+

Must be one of:

+
  • "initial"
  • "active"
  • "restart"
  • "shutdown"
+
+
+
+
+
diff --git a/gencode/java/udmi/schema/Metrics.java b/gencode/java/udmi/schema/Metrics.java index 2d2a8c6af..eb47aac89 100644 --- a/gencode/java/udmi/schema/Metrics.java +++ b/gencode/java/udmi/schema/Metrics.java @@ -8,7 +8,6 @@ @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ - "restart_count", "mem_total_mb", "mem_free_mb", "store_total_mb", @@ -18,8 +17,6 @@ @Generated("jsonschema2pojo") public class Metrics { - @JsonProperty("restart_count") - public Integer restart_count; @JsonProperty("mem_total_mb") public Double mem_total_mb; @JsonProperty("mem_free_mb") @@ -36,10 +33,9 @@ public int hashCode() { int result = 1; result = ((result* 31)+((this.store_free_mb == null)? 0 :this.store_free_mb.hashCode())); result = ((result* 31)+((this.mem_free_mb == null)? 0 :this.mem_free_mb.hashCode())); - result = ((result* 31)+((this.restart_count == null)? 0 :this.restart_count.hashCode())); - result = ((result* 31)+((this.mem_total_mb == null)? 0 :this.mem_total_mb.hashCode())); result = ((result* 31)+((this.system_load == null)? 0 :this.system_load.hashCode())); result = ((result* 31)+((this.store_total_mb == null)? 0 :this.store_total_mb.hashCode())); + result = ((result* 31)+((this.mem_total_mb == null)? 0 :this.mem_total_mb.hashCode())); return result; } @@ -52,7 +48,7 @@ public boolean equals(Object other) { return false; } Metrics rhs = ((Metrics) other); - return (((((((this.store_free_mb == rhs.store_free_mb)||((this.store_free_mb!= null)&&this.store_free_mb.equals(rhs.store_free_mb)))&&((this.mem_free_mb == rhs.mem_free_mb)||((this.mem_free_mb!= null)&&this.mem_free_mb.equals(rhs.mem_free_mb))))&&((this.restart_count == rhs.restart_count)||((this.restart_count!= null)&&this.restart_count.equals(rhs.restart_count))))&&((this.mem_total_mb == rhs.mem_total_mb)||((this.mem_total_mb!= null)&&this.mem_total_mb.equals(rhs.mem_total_mb))))&&((this.system_load == rhs.system_load)||((this.system_load!= null)&&this.system_load.equals(rhs.system_load))))&&((this.store_total_mb == rhs.store_total_mb)||((this.store_total_mb!= null)&&this.store_total_mb.equals(rhs.store_total_mb)))); + return ((((((this.store_free_mb == rhs.store_free_mb)||((this.store_free_mb!= null)&&this.store_free_mb.equals(rhs.store_free_mb)))&&((this.mem_free_mb == rhs.mem_free_mb)||((this.mem_free_mb!= null)&&this.mem_free_mb.equals(rhs.mem_free_mb))))&&((this.system_load == rhs.system_load)||((this.system_load!= null)&&this.system_load.equals(rhs.system_load))))&&((this.store_total_mb == rhs.store_total_mb)||((this.store_total_mb!= null)&&this.store_total_mb.equals(rhs.store_total_mb))))&&((this.mem_total_mb == rhs.mem_total_mb)||((this.mem_total_mb!= null)&&this.mem_total_mb.equals(rhs.mem_total_mb)))); } } diff --git a/gencode/java/udmi/schema/Operation.java b/gencode/java/udmi/schema/Operation.java new file mode 100644 index 000000000..90c264598 --- /dev/null +++ b/gencode/java/udmi/schema/Operation.java @@ -0,0 +1,109 @@ + +package udmi.schema; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.processing.Generated; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonValue; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "mode", + "last_start" +}) +@Generated("jsonschema2pojo") +public class Operation { + + /** + * System Mode + *

+ * Operating mode for the device. Default is 'active'. + * + */ + @JsonProperty("mode") + @JsonPropertyDescription("Operating mode for the device. Default is 'active'.") + public Operation.SystemMode mode; + /** + * Last time a device with this id said it restarted: being later than status-supplied last_start indicates resource conflict. + * + */ + @JsonProperty("last_start") + @JsonPropertyDescription("Last time a device with this id said it restarted: being later than status-supplied last_start indicates resource conflict.") + public Date last_start; + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.mode == null)? 0 :this.mode.hashCode())); + result = ((result* 31)+((this.last_start == null)? 0 :this.last_start.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof Operation) == false) { + return false; + } + Operation rhs = ((Operation) other); + return (((this.mode == rhs.mode)||((this.mode!= null)&&this.mode.equals(rhs.mode)))&&((this.last_start == rhs.last_start)||((this.last_start!= null)&&this.last_start.equals(rhs.last_start)))); + } + + + /** + * System Mode + *

+ * Operating mode for the device. Default is 'active'. + * + */ + @Generated("jsonschema2pojo") + public enum SystemMode { + + INITIAL("initial"), + ACTIVE("active"), + RESTART("restart"), + SHUTDOWN("shutdown"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Operation.SystemMode c: values()) { + CONSTANTS.put(c.value, c); + } + } + + SystemMode(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Operation.SystemMode fromValue(String value) { + Operation.SystemMode constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/gencode/java/udmi/schema/SetupReflectorConfig.java b/gencode/java/udmi/schema/SetupReflectorConfig.java index d7aaebb4b..f9c6b12df 100644 --- a/gencode/java/udmi/schema/SetupReflectorConfig.java +++ b/gencode/java/udmi/schema/SetupReflectorConfig.java @@ -16,12 +16,15 @@ */ @JsonInclude(JsonInclude.Include.NON_NULL) @JsonPropertyOrder({ + "functions", "last_state", "deployed_at" }) @Generated("jsonschema2pojo") public class SetupReflectorConfig { + @JsonProperty("functions") + public Integer functions; @JsonProperty("last_state") public Date last_state; @JsonProperty("deployed_at") @@ -31,6 +34,7 @@ public class SetupReflectorConfig { public int hashCode() { int result = 1; result = ((result* 31)+((this.last_state == null)? 0 :this.last_state.hashCode())); + result = ((result* 31)+((this.functions == null)? 0 :this.functions.hashCode())); result = ((result* 31)+((this.deployed_at == null)? 0 :this.deployed_at.hashCode())); return result; } @@ -44,7 +48,7 @@ public boolean equals(Object other) { return false; } SetupReflectorConfig rhs = ((SetupReflectorConfig) other); - return (((this.last_state == rhs.last_state)||((this.last_state!= null)&&this.last_state.equals(rhs.last_state)))&&((this.deployed_at == rhs.deployed_at)||((this.deployed_at!= null)&&this.deployed_at.equals(rhs.deployed_at)))); + return ((((this.last_state == rhs.last_state)||((this.last_state!= null)&&this.last_state.equals(rhs.last_state)))&&((this.functions == rhs.functions)||((this.functions!= null)&&this.functions.equals(rhs.functions))))&&((this.deployed_at == rhs.deployed_at)||((this.deployed_at!= null)&&this.deployed_at.equals(rhs.deployed_at)))); } } diff --git a/gencode/java/udmi/schema/StateSystemHardware.java b/gencode/java/udmi/schema/StateSystemHardware.java new file mode 100644 index 000000000..c748dd6f3 --- /dev/null +++ b/gencode/java/udmi/schema/StateSystemHardware.java @@ -0,0 +1,80 @@ + +package udmi.schema; + +import javax.annotation.processing.Generated; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * State System Hardware + *

+ * A collection of fields which describe the physical hardware of the device. + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "make", + "model", + "sku", + "rev" +}) +@Generated("jsonschema2pojo") +public class StateSystemHardware { + + /** + * The manufacturer of the device + * (Required) + * + */ + @JsonProperty("make") + @JsonPropertyDescription("The manufacturer of the device") + public String make; + /** + * The model of the device + * (Required) + * + */ + @JsonProperty("model") + @JsonPropertyDescription("The model of the device") + public String model; + /** + * A stock keeping unit which identifies the unique composition of a device, for example those with different hardware configurations + * + */ + @JsonProperty("sku") + @JsonPropertyDescription("A stock keeping unit which identifies the unique composition of a device, for example those with different hardware configurations") + public String sku; + /** + * Hardware revision of the device + * + */ + @JsonProperty("rev") + @JsonPropertyDescription("Hardware revision of the device") + public String rev; + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.model == null)? 0 :this.model.hashCode())); + result = ((result* 31)+((this.rev == null)? 0 :this.rev.hashCode())); + result = ((result* 31)+((this.sku == null)? 0 :this.sku.hashCode())); + result = ((result* 31)+((this.make == null)? 0 :this.make.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof StateSystemHardware) == false) { + return false; + } + StateSystemHardware rhs = ((StateSystemHardware) other); + return (((((this.model == rhs.model)||((this.model!= null)&&this.model.equals(rhs.model)))&&((this.rev == rhs.rev)||((this.rev!= null)&&this.rev.equals(rhs.rev))))&&((this.sku == rhs.sku)||((this.sku!= null)&&this.sku.equals(rhs.sku))))&&((this.make == rhs.make)||((this.make!= null)&&this.make.equals(rhs.make)))); + } + +} diff --git a/gencode/java/udmi/schema/StateSystemOperation.java b/gencode/java/udmi/schema/StateSystemOperation.java new file mode 100644 index 000000000..ed2db3cfa --- /dev/null +++ b/gencode/java/udmi/schema/StateSystemOperation.java @@ -0,0 +1,82 @@ + +package udmi.schema; + +import java.util.Date; +import javax.annotation.processing.Generated; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * StateSystemOperation + *

+ * A collection of state fields that describes the system operation + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "operational", + "last_start", + "restart_count", + "mode" +}) +@Generated("jsonschema2pojo") +public class StateSystemOperation { + + /** + * Operational status of the device. + * (Required) + * + */ + @JsonProperty("operational") + @JsonPropertyDescription("Operational status of the device.") + public Boolean operational; + /** + * Last time the system started up. + * + */ + @JsonProperty("last_start") + @JsonPropertyDescription("Last time the system started up.") + public Date last_start; + /** + * Number of system restarts + * + */ + @JsonProperty("restart_count") + @JsonPropertyDescription("Number of system restarts") + public Integer restart_count; + /** + * System Mode + *

+ * Operating mode for the device. Default is 'active'. + * + */ + @JsonProperty("mode") + @JsonPropertyDescription("Operating mode for the device. Default is 'active'.") + public udmi.schema.Operation.SystemMode mode; + + @Override + public int hashCode() { + int result = 1; + result = ((result* 31)+((this.mode == null)? 0 :this.mode.hashCode())); + result = ((result* 31)+((this.operational == null)? 0 :this.operational.hashCode())); + result = ((result* 31)+((this.restart_count == null)? 0 :this.restart_count.hashCode())); + result = ((result* 31)+((this.last_start == null)? 0 :this.last_start.hashCode())); + return result; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if ((other instanceof StateSystemOperation) == false) { + return false; + } + StateSystemOperation rhs = ((StateSystemOperation) other); + return (((((this.mode == rhs.mode)||((this.mode!= null)&&this.mode.equals(rhs.mode)))&&((this.operational == rhs.operational)||((this.operational!= null)&&this.operational.equals(rhs.operational))))&&((this.restart_count == rhs.restart_count)||((this.restart_count!= null)&&this.restart_count.equals(rhs.restart_count))))&&((this.last_start == rhs.last_start)||((this.last_start!= null)&&this.last_start.equals(rhs.last_start)))); + } + +} diff --git a/gencode/java/udmi/schema/SystemConfig.java b/gencode/java/udmi/schema/SystemConfig.java index f80b48d1b..5592c71a7 100644 --- a/gencode/java/udmi/schema/SystemConfig.java +++ b/gencode/java/udmi/schema/SystemConfig.java @@ -1,16 +1,11 @@ package udmi.schema; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; import javax.annotation.processing.Generated; -import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import com.fasterxml.jackson.annotation.JsonValue; /** @@ -23,8 +18,7 @@ @JsonPropertyOrder({ "min_loglevel", "metrics_rate_sec", - "mode", - "last_start", + "operation", "testing" }) @Generated("jsonschema2pojo") @@ -44,22 +38,8 @@ public class SystemConfig { @JsonProperty("metrics_rate_sec") @JsonPropertyDescription("The rate at which the system should send system event metric updates. 0 indicates no updates.") public Integer metrics_rate_sec = 600; - /** - * System Mode - *

- * Operating mode for the device. Default is 'active'. - * - */ - @JsonProperty("mode") - @JsonPropertyDescription("Operating mode for the device. Default is 'active'.") - public SystemConfig.SystemMode mode; - /** - * Last time a device with this id said it restarted: being later than status-supplied last_start indicates resource conflict. - * - */ - @JsonProperty("last_start") - @JsonPropertyDescription("Last time a device with this id said it restarted: being later than status-supplied last_start indicates resource conflict.") - public Date last_start; + @JsonProperty("operation") + public Operation operation; /** * Testing System Config *

@@ -74,8 +54,7 @@ public class SystemConfig { public int hashCode() { int result = 1; result = ((result* 31)+((this.metrics_rate_sec == null)? 0 :this.metrics_rate_sec.hashCode())); - result = ((result* 31)+((this.mode == null)? 0 :this.mode.hashCode())); - result = ((result* 31)+((this.last_start == null)? 0 :this.last_start.hashCode())); + result = ((result* 31)+((this.operation == null)? 0 :this.operation.hashCode())); result = ((result* 31)+((this.min_loglevel == null)? 0 :this.min_loglevel.hashCode())); result = ((result* 31)+((this.testing == null)? 0 :this.testing.hashCode())); return result; @@ -90,56 +69,7 @@ public boolean equals(Object other) { return false; } SystemConfig rhs = ((SystemConfig) other); - return ((((((this.metrics_rate_sec == rhs.metrics_rate_sec)||((this.metrics_rate_sec!= null)&&this.metrics_rate_sec.equals(rhs.metrics_rate_sec)))&&((this.mode == rhs.mode)||((this.mode!= null)&&this.mode.equals(rhs.mode))))&&((this.last_start == rhs.last_start)||((this.last_start!= null)&&this.last_start.equals(rhs.last_start))))&&((this.min_loglevel == rhs.min_loglevel)||((this.min_loglevel!= null)&&this.min_loglevel.equals(rhs.min_loglevel))))&&((this.testing == rhs.testing)||((this.testing!= null)&&this.testing.equals(rhs.testing)))); - } - - - /** - * System Mode - *

- * Operating mode for the device. Default is 'active'. - * - */ - @Generated("jsonschema2pojo") - public enum SystemMode { - - INITIAL("initial"), - ACTIVE("active"), - RESTART("restart"), - SHUTDOWN("shutdown"); - private final String value; - private final static Map CONSTANTS = new HashMap(); - - static { - for (SystemConfig.SystemMode c: values()) { - CONSTANTS.put(c.value, c); - } - } - - SystemMode(String value) { - this.value = value; - } - - @Override - public String toString() { - return this.value; - } - - @JsonValue - public String value() { - return this.value; - } - - @JsonCreator - public static SystemConfig.SystemMode fromValue(String value) { - SystemConfig.SystemMode constant = CONSTANTS.get(value); - if (constant == null) { - throw new IllegalArgumentException(value); - } else { - return constant; - } - } - + return (((((this.metrics_rate_sec == rhs.metrics_rate_sec)||((this.metrics_rate_sec!= null)&&this.metrics_rate_sec.equals(rhs.metrics_rate_sec)))&&((this.operation == rhs.operation)||((this.operation!= null)&&this.operation.equals(rhs.operation))))&&((this.min_loglevel == rhs.min_loglevel)||((this.min_loglevel!= null)&&this.min_loglevel.equals(rhs.min_loglevel))))&&((this.testing == rhs.testing)||((this.testing!= null)&&this.testing.equals(rhs.testing)))); } } diff --git a/gencode/java/udmi/schema/SystemDiscoveryEvent.java b/gencode/java/udmi/schema/SystemDiscoveryEvent.java index e988f4197..9c4dfa0b6 100644 --- a/gencode/java/udmi/schema/SystemDiscoveryEvent.java +++ b/gencode/java/udmi/schema/SystemDiscoveryEvent.java @@ -41,14 +41,14 @@ public class SystemDiscoveryEvent { @JsonPropertyDescription("Arbitrary blob of json associated with this point") public HashMap ancillary; /** - * SystemHardware + * State System Hardware *

* A collection of fields which describe the physical hardware of the device. * */ @JsonProperty("hardware") @JsonPropertyDescription("A collection of fields which describe the physical hardware of the device.") - public SystemHardware hardware; + public StateSystemHardware hardware; @Override public int hashCode() { diff --git a/gencode/java/udmi/schema/SystemState.java b/gencode/java/udmi/schema/SystemState.java index 411f76dc0..db87e5464 100644 --- a/gencode/java/udmi/schema/SystemState.java +++ b/gencode/java/udmi/schema/SystemState.java @@ -21,9 +21,7 @@ "timestamp", "version", "last_config", - "operational", - "mode", - "last_start", + "operation", "serial_no", "hardware", "software", @@ -56,29 +54,15 @@ public class SystemState { @JsonPropertyDescription("Time from the `timestamp` field of the last successfully parsed `config` message (not the timestamp the message was received/processed). Part of the [config state sequence](../docs/specs/sequences/config.md)") public Date last_config; /** - * Operational status of the device. - * (Required) - * - */ - @JsonProperty("operational") - @JsonPropertyDescription("Operational status of the device.") - public Boolean operational; - /** - * System Mode + * StateSystemOperation *

- * Operating mode for the device. Default is 'active'. - * - */ - @JsonProperty("mode") - @JsonPropertyDescription("Operating mode for the device. Default is 'active'.") - public udmi.schema.SystemConfig.SystemMode mode; - /** - * Last time the system started up. + * A collection of state fields that describes the system operation + * (Required) * */ - @JsonProperty("last_start") - @JsonPropertyDescription("Last time the system started up.") - public Date last_start; + @JsonProperty("operation") + @JsonPropertyDescription("A collection of state fields that describes the system operation") + public StateSystemOperation operation; /** * The serial number of the physical device * (Required) @@ -88,7 +72,7 @@ public class SystemState { @JsonPropertyDescription("The serial number of the physical device") public java.lang.String serial_no; /** - * SystemHardware + * State System Hardware *

* A collection of fields which describe the physical hardware of the device. * (Required) @@ -96,7 +80,7 @@ public class SystemState { */ @JsonProperty("hardware") @JsonPropertyDescription("A collection of fields which describe the physical hardware of the device.") - public SystemHardware hardware; + public StateSystemHardware hardware; /** * A collection of items which can be used to describe version of software running on a device * (Required) @@ -119,12 +103,10 @@ public class SystemState { @Override public int hashCode() { int result = 1; - result = ((result* 31)+((this.mode == null)? 0 :this.mode.hashCode())); - result = ((result* 31)+((this.last_start == null)? 0 :this.last_start.hashCode())); result = ((result* 31)+((this.software == null)? 0 :this.software.hashCode())); - result = ((result* 31)+((this.operational == null)? 0 :this.operational.hashCode())); result = ((result* 31)+((this.params == null)? 0 :this.params.hashCode())); result = ((result* 31)+((this.version == null)? 0 :this.version.hashCode())); + result = ((result* 31)+((this.operation == null)? 0 :this.operation.hashCode())); result = ((result* 31)+((this.serial_no == null)? 0 :this.serial_no.hashCode())); result = ((result* 31)+((this.timestamp == null)? 0 :this.timestamp.hashCode())); result = ((result* 31)+((this.last_config == null)? 0 :this.last_config.hashCode())); @@ -142,7 +124,7 @@ public boolean equals(Object other) { return false; } SystemState rhs = ((SystemState) other); - return ((((((((((((this.mode == rhs.mode)||((this.mode!= null)&&this.mode.equals(rhs.mode)))&&((this.last_start == rhs.last_start)||((this.last_start!= null)&&this.last_start.equals(rhs.last_start))))&&((this.software == rhs.software)||((this.software!= null)&&this.software.equals(rhs.software))))&&((this.operational == rhs.operational)||((this.operational!= null)&&this.operational.equals(rhs.operational))))&&((this.params == rhs.params)||((this.params!= null)&&this.params.equals(rhs.params))))&&((this.version == rhs.version)||((this.version!= null)&&this.version.equals(rhs.version))))&&((this.serial_no == rhs.serial_no)||((this.serial_no!= null)&&this.serial_no.equals(rhs.serial_no))))&&((this.timestamp == rhs.timestamp)||((this.timestamp!= null)&&this.timestamp.equals(rhs.timestamp))))&&((this.last_config == rhs.last_config)||((this.last_config!= null)&&this.last_config.equals(rhs.last_config))))&&((this.hardware == rhs.hardware)||((this.hardware!= null)&&this.hardware.equals(rhs.hardware))))&&((this.status == rhs.status)||((this.status!= null)&&this.status.equals(rhs.status)))); + return ((((((((((this.software == rhs.software)||((this.software!= null)&&this.software.equals(rhs.software)))&&((this.params == rhs.params)||((this.params!= null)&&this.params.equals(rhs.params))))&&((this.version == rhs.version)||((this.version!= null)&&this.version.equals(rhs.version))))&&((this.operation == rhs.operation)||((this.operation!= null)&&this.operation.equals(rhs.operation))))&&((this.serial_no == rhs.serial_no)||((this.serial_no!= null)&&this.serial_no.equals(rhs.serial_no))))&&((this.timestamp == rhs.timestamp)||((this.timestamp!= null)&&this.timestamp.equals(rhs.timestamp))))&&((this.last_config == rhs.last_config)||((this.last_config!= null)&&this.last_config.equals(rhs.last_config))))&&((this.hardware == rhs.hardware)||((this.hardware!= null)&&this.hardware.equals(rhs.hardware))))&&((this.status == rhs.status)||((this.status!= null)&&this.status.equals(rhs.status)))); } } diff --git a/gencode/python/udmi/schema/__init__.py b/gencode/python/udmi/schema/__init__.py index b15b03924..1cbc9167e 100644 --- a/gencode/python/udmi/schema/__init__.py +++ b/gencode/python/udmi/schema/__init__.py @@ -63,6 +63,7 @@ from .state_pointset import PointsetState from .state_pointset_point import PointPointsetState from .state_system import SystemState -from .state_system_hardware import SystemHardware +from .state_system_hardware import StateSystemHardware +from .state_system_operation import StateSystemOperation from .state_validation import ValidationState from .virtual_links import VirtualEquipmentLinks diff --git a/gencode/python/udmi/schema/config_system.py b/gencode/python/udmi/schema/config_system.py index 4b87c9a81..b10a90957 100644 --- a/gencode/python/udmi/schema/config_system.py +++ b/gencode/python/udmi/schema/config_system.py @@ -8,8 +8,7 @@ class SystemConfig: def __init__(self): self.min_loglevel = None self.metrics_rate_sec = None - self.mode = None - self.last_start = None + self.operation = None self.testing = None @staticmethod @@ -19,8 +18,7 @@ def from_dict(source): result = SystemConfig() result.min_loglevel = source.get('min_loglevel') result.metrics_rate_sec = source.get('metrics_rate_sec') - result.mode = source.get('mode') - result.last_start = source.get('last_start') + result.operation = source.get('operation') result.testing = TestingSystemConfig.from_dict(source.get('testing')) return result @@ -46,10 +44,8 @@ def to_dict(self): result['min_loglevel'] = self.min_loglevel # 5 if self.metrics_rate_sec: result['metrics_rate_sec'] = self.metrics_rate_sec # 5 - if self.mode: - result['mode'] = self.mode # 5 - if self.last_start: - result['last_start'] = self.last_start # 5 + if self.operation: + result['operation'] = self.operation # 5 if self.testing: result['testing'] = self.testing.to_dict() # 4 return result diff --git a/gencode/python/udmi/schema/event_discovery.py b/gencode/python/udmi/schema/event_discovery.py index e9747c05c..9e45c98dd 100644 --- a/gencode/python/udmi/schema/event_discovery.py +++ b/gencode/python/udmi/schema/event_discovery.py @@ -37,7 +37,7 @@ def to_dict(self): result = {} return result from .ancillary_properties import AncillaryProperties -from .state_system_hardware import SystemHardware +from .state_system_hardware import StateSystemHardware class SystemDiscoveryEvent: @@ -55,7 +55,7 @@ def from_dict(source): result = SystemDiscoveryEvent() result.serial_no = source.get('serial_no') result.ancillary = AncillaryProperties.from_dict(source.get('ancillary')) - result.hardware = SystemHardware.from_dict(source.get('hardware')) + result.hardware = StateSystemHardware.from_dict(source.get('hardware')) return result @staticmethod diff --git a/gencode/python/udmi/schema/event_system.py b/gencode/python/udmi/schema/event_system.py index d8e1ec259..1de8b98f8 100644 --- a/gencode/python/udmi/schema/event_system.py +++ b/gencode/python/udmi/schema/event_system.py @@ -1,11 +1,10 @@ """Generated class for event_system.json""" -class Object706FB19B: +class Object214BCB0C: """Generated schema class""" def __init__(self): - self.restart_count = None self.mem_total_mb = None self.mem_free_mb = None self.store_total_mb = None @@ -16,8 +15,7 @@ def __init__(self): def from_dict(source): if not source: return None - result = Object706FB19B() - result.restart_count = source.get('restart_count') + result = Object214BCB0C() result.mem_total_mb = source.get('mem_total_mb') result.mem_free_mb = source.get('mem_free_mb') result.store_total_mb = source.get('store_total_mb') @@ -31,7 +29,7 @@ def map_from(source): return None result = {} for key in source: - result[key] = Object706FB19B.from_dict(source[key]) + result[key] = Object214BCB0C.from_dict(source[key]) return result @staticmethod @@ -43,8 +41,6 @@ def expand_dict(input): def to_dict(self): result = {} - if self.restart_count: - result['restart_count'] = self.restart_count # 5 if self.mem_total_mb: result['mem_total_mb'] = self.mem_total_mb # 5 if self.mem_free_mb: @@ -79,7 +75,7 @@ def from_dict(source): result.last_config = source.get('last_config') result.logentries = Entry.array_from(source.get('logentries')) result.event_count = source.get('event_count') - result.metrics = Object706FB19B.from_dict(source.get('metrics')) + result.metrics = Object214BCB0C.from_dict(source.get('metrics')) return result @staticmethod diff --git a/gencode/python/udmi/schema/reflect_config.py b/gencode/python/udmi/schema/reflect_config.py index 3c3ee0b4c..8dfce33a6 100644 --- a/gencode/python/udmi/schema/reflect_config.py +++ b/gencode/python/udmi/schema/reflect_config.py @@ -5,6 +5,7 @@ class SetupReflectorConfig: """Generated schema class""" def __init__(self): + self.functions = None self.last_state = None self.deployed_at = None @@ -13,6 +14,7 @@ def from_dict(source): if not source: return None result = SetupReflectorConfig() + result.functions = source.get('functions') result.last_state = source.get('last_state') result.deployed_at = source.get('deployed_at') return result @@ -35,6 +37,8 @@ def expand_dict(input): def to_dict(self): result = {} + if self.functions: + result['functions'] = self.functions # 5 if self.last_state: result['last_state'] = self.last_state # 5 if self.deployed_at: diff --git a/gencode/python/udmi/schema/state_system.py b/gencode/python/udmi/schema/state_system.py index a56f5ebc6..2aa5528b9 100644 --- a/gencode/python/udmi/schema/state_system.py +++ b/gencode/python/udmi/schema/state_system.py @@ -1,5 +1,6 @@ """Generated class for state_system.json""" -from .state_system_hardware import SystemHardware +from .state_system_operation import StateSystemOperation +from .state_system_hardware import StateSystemHardware from .common import Entry @@ -10,9 +11,7 @@ def __init__(self): self.timestamp = None self.version = None self.last_config = None - self.operational = None - self.mode = None - self.last_start = None + self.operation = None self.serial_no = None self.hardware = None self.software = None @@ -27,11 +26,9 @@ def from_dict(source): result.timestamp = source.get('timestamp') result.version = source.get('version') result.last_config = source.get('last_config') - result.operational = source.get('operational') - result.mode = source.get('mode') - result.last_start = source.get('last_start') + result.operation = StateSystemOperation.from_dict(source.get('operation')) result.serial_no = source.get('serial_no') - result.hardware = SystemHardware.from_dict(source.get('hardware')) + result.hardware = StateSystemHardware.from_dict(source.get('hardware')) result.software = source.get('software') result.params = source.get('params') result.status = Entry.from_dict(source.get('status')) @@ -61,12 +58,8 @@ def to_dict(self): result['version'] = self.version # 5 if self.last_config: result['last_config'] = self.last_config # 5 - if self.operational: - result['operational'] = self.operational # 5 - if self.mode: - result['mode'] = self.mode # 5 - if self.last_start: - result['last_start'] = self.last_start # 5 + if self.operation: + result['operation'] = self.operation.to_dict() # 4 if self.serial_no: result['serial_no'] = self.serial_no # 5 if self.hardware: diff --git a/gencode/python/udmi/schema/state_system_hardware.py b/gencode/python/udmi/schema/state_system_hardware.py index 55a0aa7a5..cb5e70ad4 100644 --- a/gencode/python/udmi/schema/state_system_hardware.py +++ b/gencode/python/udmi/schema/state_system_hardware.py @@ -1,7 +1,7 @@ """Generated class for state_system_hardware.json""" -class SystemHardware: +class StateSystemHardware: """Generated schema class""" def __init__(self): @@ -14,7 +14,7 @@ def __init__(self): def from_dict(source): if not source: return None - result = SystemHardware() + result = StateSystemHardware() result.make = source.get('make') result.model = source.get('model') result.sku = source.get('sku') @@ -27,7 +27,7 @@ def map_from(source): return None result = {} for key in source: - result[key] = SystemHardware.from_dict(source[key]) + result[key] = StateSystemHardware.from_dict(source[key]) return result @staticmethod diff --git a/gencode/python/udmi/schema/state_system_operation.py b/gencode/python/udmi/schema/state_system_operation.py new file mode 100644 index 000000000..cb78cd56b --- /dev/null +++ b/gencode/python/udmi/schema/state_system_operation.py @@ -0,0 +1,50 @@ +"""Generated class for state_system_operation.json""" + + +class StateSystemOperation: + """Generated schema class""" + + def __init__(self): + self.operational = None + self.last_start = None + self.restart_count = None + self.mode = None + + @staticmethod + def from_dict(source): + if not source: + return None + result = StateSystemOperation() + result.operational = source.get('operational') + result.last_start = source.get('last_start') + result.restart_count = source.get('restart_count') + result.mode = source.get('mode') + return result + + @staticmethod + def map_from(source): + if not source: + return None + result = {} + for key in source: + result[key] = StateSystemOperation.from_dict(source[key]) + return result + + @staticmethod + def expand_dict(input): + result = {} + for property in input: + result[property] = input[property].to_dict() if input[property] else {} + return result + + def to_dict(self): + result = {} + if self.operational: + result['operational'] = self.operational # 5 + if self.last_start: + result['last_start'] = self.last_start # 5 + if self.restart_count: + result['restart_count'] = self.restart_count # 5 + if self.mode: + result['mode'] = self.mode # 5 + return result diff --git a/pubber/src/main/java/daq/pubber/Pubber.java b/pubber/src/main/java/daq/pubber/Pubber.java index 8776b9530..200dfde75 100644 --- a/pubber/src/main/java/daq/pubber/Pubber.java +++ b/pubber/src/main/java/daq/pubber/Pubber.java @@ -43,6 +43,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledExecutorService; @@ -83,6 +84,8 @@ import udmi.schema.LocalnetModel; import udmi.schema.Metadata; import udmi.schema.Metrics; +import udmi.schema.Operation; +import udmi.schema.Operation.SystemMode; import udmi.schema.PointEnumerationEvent; import udmi.schema.PointPointsetConfig; import udmi.schema.PointPointsetModel; @@ -93,10 +96,10 @@ import udmi.schema.PubberConfiguration; import udmi.schema.PubberOptions; import udmi.schema.State; +import udmi.schema.StateSystemHardware; +import udmi.schema.StateSystemOperation; import udmi.schema.SystemConfig; -import udmi.schema.SystemConfig.SystemMode; import udmi.schema.SystemEvent; -import udmi.schema.SystemHardware; import udmi.schema.SystemState; /** @@ -110,7 +113,7 @@ public class Pubber { public static final String PERSISTENT_TMP_FORMAT = "/tmp/pubber_%s_" + PERSISTENT_STORE_FILE; public static final String PUBBER_LOG_CATEGORY = "device.log"; public static final String DATA_URL_JSON_BASE64 = "data:application/json;base64,"; - static final String UDMI_VERSION = "1.4.0"; + static final String UDMI_VERSION = "1.4.1"; private static final Logger LOG = LoggerFactory.getLogger(Pubber.class); private static final String HOSTNAME = System.getenv("HOSTNAME"); private static final int MIN_REPORT_MS = 200; @@ -384,8 +387,9 @@ private double convertValue(Object baselineValue, double defaultBaselineValue) { private void initializeDevice() { deviceState.system = new SystemState(); - deviceState.system.hardware = new SystemHardware(); - deviceState.system.last_start = DEVICE_START_TIME; + deviceState.system.operation = new StateSystemOperation(); + deviceState.system.operation.last_start = DEVICE_START_TIME; + deviceState.system.hardware = new StateSystemHardware(); deviceState.pointset = new PointsetState(); deviceState.pointset.points = new HashMap<>(); devicePoints.points = new HashMap<>(); @@ -411,8 +415,8 @@ private void initializeDevice() { configuration.deviceId, configuration.serialNo, configuration.macAddr, configuration.gatewayId, optionsString(configuration.options))); - deviceState.system.operational = true; - deviceState.system.mode = SystemMode.INITIAL; + deviceState.system.operation.operational = true; + deviceState.system.operation.mode = SystemMode.INITIAL; deviceState.system.serial_no = configuration.serialNo; deviceState.system.hardware.make = "BOS"; deviceState.system.hardware.model = "pubber"; @@ -445,6 +449,7 @@ private void initializePersistentStore() { persistentStore.exists() ? fromJsonFile(persistentStore, DevicePersistent.class) : new DevicePersistent(); persistentData.restart_count = Objects.requireNonNullElse(persistentData.restart_count, 0) + 1; + deviceState.system.operation.restart_count = persistentData.restart_count; writePersistentStore(); } @@ -595,7 +600,6 @@ private void periodicUpdate() { private void sendSystemEvent() { SystemEvent systemEvent = getSystemEvent(); systemEvent.metrics = new Metrics(); - systemEvent.metrics.restart_count = persistentData.restart_count; Runtime runtime = Runtime.getRuntime(); systemEvent.metrics.mem_free_mb = (double) runtime.freeMemory() / BYTES_PER_MEGABYTE; systemEvent.metrics.mem_total_mb = (double) runtime.totalMemory() / BYTES_PER_MEGABYTE; @@ -617,27 +621,25 @@ private void deferredConfigActions() { } private void maybeRestartSystem() { - SystemConfig systemConfig = deviceConfig.system; - if (systemConfig == null) { - return; - } - if (SystemMode.ACTIVE.equals(deviceState.system.mode) - && SystemMode.RESTART.equals(systemConfig.mode)) { + SystemConfig system = Optional.ofNullable(deviceConfig.system).orElseGet(SystemConfig::new); + Operation operation = Optional.ofNullable(system.operation).orElseGet(Operation::new); + if (SystemMode.ACTIVE.equals(deviceState.system.operation.mode) + && SystemMode.RESTART.equals(operation.mode)) { restartSystem(true); } - if (SystemMode.ACTIVE.equals(systemConfig.mode)) { - deviceState.system.mode = SystemMode.ACTIVE; + if (SystemMode.ACTIVE.equals(operation.mode)) { + deviceState.system.operation.mode = SystemMode.ACTIVE; markStateDirty(); } - if (systemConfig.last_start != null && DEVICE_START_TIME.before(systemConfig.last_start)) { + if (operation.last_start != null && DEVICE_START_TIME.before(operation.last_start)) { System.err.printf("Device start time %s before last config start %s, terminating.", - isoConvert(DEVICE_START_TIME), isoConvert(systemConfig.last_start)); + isoConvert(DEVICE_START_TIME), isoConvert(operation.last_start)); restartSystem(false); } } private void restartSystem(boolean restart) { - deviceState.system.mode = restart ? SystemMode.RESTART : SystemMode.SHUTDOWN; + deviceState.system.operation.mode = restart ? SystemMode.RESTART : SystemMode.SHUTDOWN; try { publishSynchronousState(); } catch (Exception e) { @@ -683,7 +685,7 @@ private void captureExceptions(String action, Runnable runnable) { void terminate() { warn("Terminating"); - deviceState.system.mode = SystemMode.SHUTDOWN; + deviceState.system.operation.mode = SystemMode.SHUTDOWN; captureExceptions("publishing shutdown state", this::publishSynchronousState); stop(); captureExceptions("executor flush", this::stopExecutor); diff --git a/pubber/src/test/java/daq/pubber/PubberTest.java b/pubber/src/test/java/daq/pubber/PubberTest.java index b1da0e3aa..a5f2edc80 100644 --- a/pubber/src/test/java/daq/pubber/PubberTest.java +++ b/pubber/src/test/java/daq/pubber/PubberTest.java @@ -81,6 +81,7 @@ public void missingDevice() { try { makeTestPubber(BAD_DEVICE); } catch (Throwable e) { + e.printStackTrace(); while (e != null) { String message = e.getMessage(); if (message.contains(BAD_DEVICE)) { diff --git a/schema/config_system.json b/schema/config_system.json index 45b987cf7..b295e8b17 100644 --- a/schema/config_system.json +++ b/schema/config_system.json @@ -1,5 +1,5 @@ { - "$udmi_version": "1.4.0", + "$udmi_version": "1.4.1", "title": "System Config", "description": "[System Config Documentation](../docs/messages/system.md#config)", "type": "object", @@ -20,13 +20,18 @@ "maximum": 86400, "default": 600 }, - "mode": { - "$ref": "file:common.json#/definitions/mode" - }, - "last_start": { - "description": "Last time a device with this id said it restarted: being later than status-supplied last_start indicates resource conflict.", - "type": "string", - "format": "date-time" + "operation": { + "additionalProperties": false, + "properties": { + "mode": { + "$ref": "file:common.json#/definitions/mode" + }, + "last_start": { + "description": "Last time a device with this id said it restarted: being later than status-supplied last_start indicates resource conflict.", + "type": "string", + "format": "date-time" + } + } }, "testing": { "$ref": "file:config_system_testing.json#" diff --git a/schema/event_system.json b/schema/event_system.json index 37dd24288..eb79d086f 100644 --- a/schema/event_system.json +++ b/schema/event_system.json @@ -37,9 +37,6 @@ "type": "object", "additionalProperties": false, "properties": { - "restart_count": { - "type": "integer" - }, "mem_total_mb": { "type": "number" }, diff --git a/schema/reflect_config.json b/schema/reflect_config.json index a5e7cafeb..c5d7a6f69 100644 --- a/schema/reflect_config.json +++ b/schema/reflect_config.json @@ -20,6 +20,9 @@ "title": "Setup Reflector Config", "type": "object", "properties": { + "functions": { + "type": "integer" + }, "last_state": { "type": "string", "format": "date-time" diff --git a/schema/state_discovery_family.json b/schema/state_discovery_family.json index e88f3d4e4..314ebc195 100644 --- a/schema/state_discovery_family.json +++ b/schema/state_discovery_family.json @@ -1,5 +1,5 @@ { - "$udmi_version": "1.4.0", + "$udmi_version": "1.4.1", "title": "Family Discovery State", "description": "State for [discovery](../docs/specs/discovery.md)", "type": "object", diff --git a/schema/state_system.json b/schema/state_system.json index 2c6d2ed23..302138ced 100644 --- a/schema/state_system.json +++ b/schema/state_system.json @@ -1,5 +1,5 @@ { - "$udmi_version": "1.4.0", + "$udmi_version": "1.4.1", "title": "System State", "description": "[System State Documentation](../docs/messages/system.md#state)", "type": "object", @@ -22,17 +22,8 @@ "format": "date-time", "examples": ["2019-01-17T14:02:29.364Z"] }, - "operational": { - "description": "Operational status of the device.", - "type": "boolean" - }, - "mode": { - "$ref": "file:common.json#/definitions/mode" - }, - "last_start": { - "description": "Last time the system started up.", - "type": "string", - "format": "date-time" + "operation": { + "$ref": "file:state_system_operation.json" }, "serial_no": { "description": "The serial number of the physical device", @@ -73,6 +64,6 @@ "last_config", "hardware", "software", - "operational" + "operation" ] } diff --git a/schema/state_system_hardware.json b/schema/state_system_hardware.json index fca1decb9..5d608bf75 100644 --- a/schema/state_system_hardware.json +++ b/schema/state_system_hardware.json @@ -1,6 +1,6 @@ { "$udmi_version": "1.4.0", - "title": "SystemHardware", + "title": "State System Hardware", "description": "A collection of fields which describe the physical hardware of the device.", "type": "object", "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/schema/state_system_operation.json b/schema/state_system_operation.json new file mode 100644 index 000000000..cde7e9fd7 --- /dev/null +++ b/schema/state_system_operation.json @@ -0,0 +1,29 @@ +{ + "$udmi_version": "1.4.1", + "title": "StateSystemOperation", + "description": "A collection of state fields that describes the system operation", + "type": "object", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "operational": { + "description": "Operational status of the device.", + "type": "boolean" + }, + "last_start": { + "description": "Last time the system started up.", + "type": "string", + "format": "date-time" + }, + "restart_count": { + "description": "Number of system restarts", + "type": "integer" + }, + "mode": { + "$ref": "file:common.json#/definitions/mode" + } + }, + "required": [ + "operational" + ] +} diff --git a/tests/config.tests/blobset_final_incomplete_payload.out b/tests/config.tests/blobset_final_incomplete_payload.out new file mode 100644 index 000000000..4ec871c6e --- /dev/null +++ b/tests/config.tests/blobset_final_incomplete_payload.out @@ -0,0 +1,2 @@ +1 schema violations found + /blobset/blobs/arbitrary_manufacturer_id: instance failed to match exactly one schema (matched 0 out of 2) diff --git a/tests/config.tests/blobset_final_incomplete_url.out b/tests/config.tests/blobset_final_incomplete_url.out index 5e41bd854..b97f30ec9 100644 --- a/tests/config.tests/blobset_final_incomplete_url.out +++ b/tests/config.tests/blobset_final_incomplete_url.out @@ -1,2 +1,2 @@ 1 schema violations found - object has missing required properties (["generation","sha256"]) + /blobset/blobs/_firmware_update: object has missing required properties (["generation","sha256"]) diff --git a/tests/config.tests/delta_x1_gateway.out b/tests/config.tests/delta_x1_gateway.out index 566079e3a..19c1e95dd 100644 --- a/tests/config.tests/delta_x1_gateway.out +++ b/tests/config.tests/delta_x1_gateway.out @@ -1,5 +1,5 @@ 4 schema violations found - ECMA 262 regex "^[A-Z]{3}-[1-9][0-9]{0,2}$" does not match input string "TRHC-26" - object has missing required properties (["families"]) + /gateway/proxy_ids/0: ECMA 262 regex "^[A-Z]{3}-[1-9][0-9]{0,2}$" does not match input string "TRHC-26" + /localnet: object has missing required properties (["families"]) + /localnet: object instance has properties which are not allowed by the schema: ["subsystem"] object has missing required properties (["version"]) - object instance has properties which are not allowed by the schema: ["subsystem"] diff --git a/tests/config.tests/delta_x1_target.out b/tests/config.tests/delta_x1_target.out index b0a72ba64..0696c059a 100644 --- a/tests/config.tests/delta_x1_target.out +++ b/tests/config.tests/delta_x1_target.out @@ -1,4 +1,4 @@ 3 schema violations found - object has missing required properties (["families"]) + /localnet: object has missing required properties (["families"]) + /localnet: object instance has properties which are not allowed by the schema: ["subsystem"] object has missing required properties (["version"]) - object instance has properties which are not allowed by the schema: ["subsystem"] diff --git a/tests/config.tests/errors.out b/tests/config.tests/errors.out index ffb056e08..65c21435a 100644 --- a/tests/config.tests/errors.out +++ b/tests/config.tests/errors.out @@ -1,7 +1,7 @@ 6 schema violations found - instance type (integer) does not match any allowed primitive type (allowed: ["string"]) - instance type (string) does not match any allowed primitive type (allowed: ["integer"]) - object instance has properties which are not allowed by the schema: ["config_etag","id","properties"] - object instance has properties which are not allowed by the schema: ["object_type"] + /pointset/points/return_air_temperature_sensor: object instance has properties which are not allowed by the schema: ["object_type"] + /pointset/sample_rate_sec: instance type (string) does not match any allowed primitive type (allowed: ["integer"]) + /pointset/state_etag: string "2a8b71dwqhdhdddddddddddddddddddddddddddddddddddddddddd8" is too long (length: 55, maximum allowed: 32) + /pointset/version: instance type (integer) does not match any allowed primitive type (allowed: ["string"]) + /pointset: object instance has properties which are not allowed by the schema: ["config_etag","id","properties"] object instance has properties which are not allowed by the schema: ["points","properties","type"] - string "2a8b71dwqhdhdddddddddddddddddddddddddddddddddddddddddd8" is too long (length: 55, maximum allowed: 32) diff --git a/tests/config.tests/fcu.out b/tests/config.tests/fcu.out index d50fae07e..cedf4f958 100644 --- a/tests/config.tests/fcu.out +++ b/tests/config.tests/fcu.out @@ -1,3 +1,3 @@ 2 schema violations found - object instance has properties which are not allowed by the schema: ["max_update_ms"] - object instance has properties which are not allowed by the schema: ["min_update_ms"] + /pointset/points/chilled_water_valve_percentage_command: object instance has properties which are not allowed by the schema: ["min_update_ms"] + /system: object instance has properties which are not allowed by the schema: ["max_update_ms"] diff --git a/tests/config.tests/gateway.out b/tests/config.tests/gateway.out index 7f3c915b1..31077431c 100644 --- a/tests/config.tests/gateway.out +++ b/tests/config.tests/gateway.out @@ -1,2 +1,2 @@ 1 schema violations found - ECMA 262 regex "^[A-Z]{3}-[1-9][0-9]{0,2}$" does not match input string "991" + /gateway/proxy_ids/2: ECMA 262 regex "^[A-Z]{3}-[1-9][0-9]{0,2}$" does not match input string "991" diff --git a/tests/config.tests/restart.json b/tests/config.tests/restart.json index ae11ef6ba..a02e8b4c5 100644 --- a/tests/config.tests/restart.json +++ b/tests/config.tests/restart.json @@ -1,10 +1,12 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "metrics_rate_sec": 10, "min_loglevel": 400, - "mode": "restart" + "operation": { + "mode": "restart" + } }, "pointset": { "sample_limit_sec": 2, diff --git a/tests/config.tests/smartprimus.out b/tests/config.tests/smartprimus.out index de3853d00..c06af5362 100644 --- a/tests/config.tests/smartprimus.out +++ b/tests/config.tests/smartprimus.out @@ -1,2 +1,3 @@ 2 schema violations found - object instance has properties which are not allowed by the schema: ["fix_value"] + /pointset/points/fan_run_enable: object instance has properties which are not allowed by the schema: ["fix_value"] + /pointset/points/fan_run_status: object instance has properties which are not allowed by the schema: ["fix_value"] diff --git a/tests/configuration_endpoint.tests/multiple.out b/tests/configuration_endpoint.tests/multiple.out index efdc9e303..7b0b39a45 100644 --- a/tests/configuration_endpoint.tests/multiple.out +++ b/tests/configuration_endpoint.tests/multiple.out @@ -1,2 +1,2 @@ 1 schema violations found - ECMA 262 regex "^[-_/a-zA-Z0-9]+$" does not match input string "/devices/#" + /topic_prefix: ECMA 262 regex "^[-_/a-zA-Z0-9]+$" does not match input string "/devices/#" diff --git a/tests/downgrade.site/devices/DWN-1/expected/metadata_norm.json b/tests/downgrade.site/devices/DWN-1/expected/metadata_norm.json index 3a8d6c903..9eff3c97e 100644 --- a/tests/downgrade.site/devices/DWN-1/expected/metadata_norm.json +++ b/tests/downgrade.site/devices/DWN-1/expected/metadata_norm.json @@ -1,7 +1,7 @@ { "timestamp": "2020-05-01T13:39:07Z", - "version": "1.3.14", - "hash": "c62d55be", + "version": "1.4.0", + "hash": "ac33820a", "cloud": { "auth_type": "RS256" }, diff --git a/tests/downgrade.site/devices/DWN-2/expected/generated_config.json b/tests/downgrade.site/devices/DWN-2/expected/generated_config.json index 686a4ef39..3034aba0a 100644 --- a/tests/downgrade.site/devices/DWN-2/expected/generated_config.json +++ b/tests/downgrade.site/devices/DWN-2/expected/generated_config.json @@ -1,9 +1,10 @@ { "timestamp" : "2020-05-01T13:39:07Z", - "version" : "1.4.0", + "version" : "1.4.1", "system" : { "min_loglevel" : 300, - "metrics_rate_sec" : 600 + "metrics_rate_sec" : 600, + "operation" : { } }, "localnet" : { "families" : { diff --git a/tests/downgrade.site/devices/DWN-2/out/generated_config.json b/tests/downgrade.site/devices/DWN-2/out/generated_config.json index 686a4ef39..3034aba0a 100644 --- a/tests/downgrade.site/devices/DWN-2/out/generated_config.json +++ b/tests/downgrade.site/devices/DWN-2/out/generated_config.json @@ -1,9 +1,10 @@ { "timestamp" : "2020-05-01T13:39:07Z", - "version" : "1.4.0", + "version" : "1.4.1", "system" : { "min_loglevel" : 300, - "metrics_rate_sec" : 600 + "metrics_rate_sec" : 600, + "operation" : { } }, "localnet" : { "families" : { diff --git a/tests/downgrade.site/registration_summary.json b/tests/downgrade.site/registration_summary.json index c79181fb5..d436976a5 100644 --- a/tests/downgrade.site/registration_summary.json +++ b/tests/downgrade.site/registration_summary.json @@ -8,6 +8,6 @@ "DWN-2" : "devices/DWN-2" }, "Version" : { - "main" : "1.3.14-104-gbc8bee55" + "main" : "1.4.0-195-gdfe40886" } -} +} \ No newline at end of file diff --git a/tests/envelope.tests/errors1.out b/tests/envelope.tests/errors1.out index b8300d55f..4d5cca29e 100644 --- a/tests/envelope.tests/errors1.out +++ b/tests/envelope.tests/errors1.out @@ -1,6 +1,6 @@ 5 schema violations found - ECMA 262 regex "^[0-9]+$" does not match input string "921302198324X" - ECMA 262 regex "^[A-Z]{2,6}-[0-9]{1,6}$" does not match input string "fcu-1" - ECMA 262 regex "^[a-zA-Z][-a-zA-Z0-9._+~%]*[a-zA-Z0-9]$" does not match input string "test/registry" - instance value (5) not found in enum (possible values: ["event","command","state","config","model"]) + /deviceId: ECMA 262 regex "^[A-Z]{2,6}-[0-9]{1,6}$" does not match input string "fcu-1" + /deviceNumId: ECMA 262 regex "^[0-9]+$" does not match input string "921302198324X" + /deviceRegistryId: ECMA 262 regex "^[a-zA-Z][-a-zA-Z0-9._+~%]*[a-zA-Z0-9]$" does not match input string "test/registry" + /subType: instance value (5) not found in enum (possible values: ["event","command","state","config","model"]) object has missing required properties (["projectId","subFolder"]) diff --git a/tests/envelope.tests/errors2.out b/tests/envelope.tests/errors2.out index 1aa5b319b..a98393916 100644 --- a/tests/envelope.tests/errors2.out +++ b/tests/envelope.tests/errors2.out @@ -1,4 +1,4 @@ 3 schema violations found - ECMA 262 regex "^[0-9]+$" does not match input string "-9213923812" - ECMA 262 regex "^[A-Z]{2,6}-[0-9]{1,6}$" does not match input string "FCUs_02_NW_12" + /deviceId: ECMA 262 regex "^[A-Z]{2,6}-[0-9]{1,6}$" does not match input string "FCUs_02_NW_12" + /deviceNumId: ECMA 262 regex "^[0-9]+$" does not match input string "-9213923812" object has missing required properties (["projectId","subFolder"]) diff --git a/tests/event_discovery.tests/errors.out b/tests/event_discovery.tests/errors.out index 870d0b902..f194c454e 100644 --- a/tests/event_discovery.tests/errors.out +++ b/tests/event_discovery.tests/errors.out @@ -1,6 +1,6 @@ 5 schema violations found - ECMA 262 regex "^[-_.:0-9A-Z]+$" does not match input string "92E*A09" + /families/bacnet/id: ECMA 262 regex "^[-_.:0-9A-Z]+$" does not match input string "92E*A09" + /families: object instance has properties which are not allowed by the schema: ["ip_v4","mac"] + /uniqs/bad_entity_name_: object instance has properties which are not allowed by the schema: ["present_value"] object has missing required properties (["generation"]) object instance has properties which are not allowed by the schema: ["id","points"] - object instance has properties which are not allowed by the schema: ["ip_v4","mac"] - object instance has properties which are not allowed by the schema: ["present_value"] diff --git a/tests/event_pointset.tests/errors.out b/tests/event_pointset.tests/errors.out index 367cb144d..1e6047f3d 100644 --- a/tests/event_pointset.tests/errors.out +++ b/tests/event_pointset.tests/errors.out @@ -1,7 +1,9 @@ 8 schema violations found - instance type (string) does not match any allowed primitive type (allowed: ["object"]) - object has missing required properties (["present_value"]) - object instance has properties which are not allowed by the schema: ["analogValue_1","bad_____sensor","bad_entity_name_","comment$string"] - object instance has properties which are not allowed by the schema: ["bad_property_name"] + /points/guid: instance type (string) does not match any allowed primitive type (allowed: ["object"]) + /points/missing_present_value: object has missing required properties (["present_value"]) + /points/old_properties: object has missing required properties (["present_value"]) + /points/old_properties: object instance has properties which are not allowed by the schema: ["properties"] + /points/yoyo_motion_sensor: object has missing required properties (["present_value"]) + /points/yoyo_motion_sensor: object instance has properties which are not allowed by the schema: ["bad_property_name"] + /points: object instance has properties which are not allowed by the schema: ["analogValue_1","bad_____sensor","bad_entity_name_","comment$string"] object instance has properties which are not allowed by the schema: ["comment$string","id","properties","state_etag"] - object instance has properties which are not allowed by the schema: ["properties"] diff --git a/tests/event_system.tests/categories.out b/tests/event_system.tests/categories.out index c9f7e86f2..e6f91f325 100644 --- a/tests/event_system.tests/categories.out +++ b/tests/event_system.tests/categories.out @@ -1,2 +1,5 @@ 4 schema violations found - instance failed to match exactly one schema (matched 0 out of 29) + /logentries/3/category: instance failed to match exactly one schema (matched 0 out of 29) + /logentries/4/category: instance failed to match exactly one schema (matched 0 out of 29) + /logentries/5/category: instance failed to match exactly one schema (matched 0 out of 29) + /logentries/6/category: instance failed to match exactly one schema (matched 0 out of 29) diff --git a/tests/event_system.tests/errors.out b/tests/event_system.tests/errors.out index e0d4cdc7b..e79654ebe 100644 --- a/tests/event_system.tests/errors.out +++ b/tests/event_system.tests/errors.out @@ -1,5 +1,5 @@ 4 schema violations found - instance failed to match exactly one schema (matched 0 out of 29) - instance type (string) does not match any allowed primitive type (allowed: ["object"]) - numeric instance is lower than the required minimum (minimum: 100, found: 60) - object has missing required properties (["message","timestamp"]) + /logentries/0/category: instance failed to match exactly one schema (matched 0 out of 29) + /logentries/0/level: numeric instance is lower than the required minimum (minimum: 100, found: 60) + /logentries/0: object has missing required properties (["message","timestamp"]) + /logentries/1: instance type (string) does not match any allowed primitive type (allowed: ["object"]) diff --git a/tests/event_system.tests/metrics.json b/tests/event_system.tests/metrics.json index 506032a35..a1c59e3d1 100644 --- a/tests/event_system.tests/metrics.json +++ b/tests/event_system.tests/metrics.json @@ -2,7 +2,6 @@ "version": "1.4.0", "timestamp": "2018-08-26T21:39:29.364Z", "metrics": { // Fixed keys, all scalar values (for graphing). - "restart_count": 10, "mem_total_mb": 25164.88, "mem_free_mb": 16104.33, "store_total_mb": 250164.88, diff --git a/tests/metadata.tests/errors.out b/tests/metadata.tests/errors.out index 2fb783540..81a238bd7 100644 --- a/tests/metadata.tests/errors.out +++ b/tests/metadata.tests/errors.out @@ -1,8 +1,8 @@ 7 schema violations found - ECMA 262 regex "^[A-Z]{2,6}-[0-9]{1,6}$" does not match input string "AHU-A01_extension11-option" - ECMA 262 regex "^[A-Z]{2}-[A-Z]{3}-[A-Z0-9]{2,9}$" does not match input string "New Zealand" - ECMA 262 regex "^[A-Z]{2}-[A-Z]{3}-[A-Z0-9]{2,9}$" does not match input string "US-SFO-XYY_Noope!" - object has missing required properties (["guid"]) - object instance has properties which are not allowed by the schema: ["guid"] - object instance has properties which are not allowed by the schema: ["monkeys"] - object instance has properties which are not allowed by the schema: ["rabbits"] + /pointset/points/return_air_temperature_sensor: object instance has properties which are not allowed by the schema: ["monkeys"] + /pointset: object instance has properties which are not allowed by the schema: ["rabbits"] + /system/location/site: ECMA 262 regex "^[A-Z]{2}-[A-Z]{3}-[A-Z0-9]{2,9}$" does not match input string "New Zealand" + /system/physical_tag/asset/name: ECMA 262 regex "^[A-Z]{2,6}-[0-9]{1,6}$" does not match input string "AHU-A01_extension11-option" + /system/physical_tag/asset/site: ECMA 262 regex "^[A-Z]{2}-[A-Z]{3}-[A-Z0-9]{2,9}$" does not match input string "US-SFO-XYY_Noope!" + /system/physical_tag/asset: object has missing required properties (["guid"]) + /system: object instance has properties which are not allowed by the schema: ["guid"] diff --git a/tests/metadata.tests/toomany.out b/tests/metadata.tests/toomany.out index 7f60ca7e5..fc51f6c66 100644 --- a/tests/metadata.tests/toomany.out +++ b/tests/metadata.tests/toomany.out @@ -1,3 +1,3 @@ 2 schema violations found - ECMA 262 regex "^[A-Z]{2,6}-[0-9]{1,6}$" does not match input string "UK-LON-S2_LTGW-3" - object has too many properties (found 672 but schema requires at most 150) + /pointset/points: object has too many properties (found 672 but schema requires at most 150) + /system/physical_tag/asset/name: ECMA 262 regex "^[A-Z]{2,6}-[0-9]{1,6}$" does not match input string "UK-LON-S2_LTGW-3" diff --git a/tests/state.tests/blobset_received.json b/tests/state.tests/blobset_received.json index 40cf691d7..9b5dc0dd8 100644 --- a/tests/state.tests/blobset_received.json +++ b/tests/state.tests/blobset_received.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2022-07-13T12:00:10.000Z", "system": { "hardware": { @@ -11,7 +11,9 @@ }, "serial_no": "000000", "last_config": "2022-07-11T00:00:10.000Z", - "operational": true + "operation": { + "operational": true + } }, "blobset": { "blobs": { diff --git a/tests/state.tests/blobset_updating.json b/tests/state.tests/blobset_updating.json index 72e1161e3..e626ff8ad 100644 --- a/tests/state.tests/blobset_updating.json +++ b/tests/state.tests/blobset_updating.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2022-07-13T12:00:10.000Z", "system": { "hardware": { @@ -11,7 +11,9 @@ }, "serial_no": "000000", "last_config": "2022-07-11T00:00:10.000Z", - "operational": true + "operation": { + "operational": true + } }, "blobset" : { "blobs" : { diff --git a/tests/state.tests/continuous.json b/tests/state.tests/continuous.json index 7c8831b4e..c985ec3e0 100644 --- a/tests/state.tests/continuous.json +++ b/tests/state.tests/continuous.json @@ -3,7 +3,7 @@ // where {device_id} is that of the discovery node. // { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { @@ -15,7 +15,9 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": true + "operation": { + "operational": true + } }, "discovery": { "families": { diff --git a/tests/state.tests/delta_x1_gateway.out b/tests/state.tests/delta_x1_gateway.out index 37b277309..3f6e25a6f 100644 --- a/tests/state.tests/delta_x1_gateway.out +++ b/tests/state.tests/delta_x1_gateway.out @@ -1 +1,5 @@ -Node already has hardware field +4 schema violations found + /gateway: object instance has properties which are not allowed by the schema: ["error_ids"] + /system/hardware: object has missing required properties (["make","model"]) + /system/hardware: object instance has properties which are not allowed by the schema: ["cpu_usage","free_dynamic_memory","last_reset_timestamp","last_restart_reason","reset_count","revision","total_dynamic_memory"] + object instance has properties which are not allowed by the schema: ["last_config"] diff --git a/tests/state.tests/delta_x1_target.out b/tests/state.tests/delta_x1_target.out index 3e10428e2..859981bfa 100644 --- a/tests/state.tests/delta_x1_target.out +++ b/tests/state.tests/delta_x1_target.out @@ -1,3 +1,3 @@ 2 schema violations found - object has missing required properties (["serial_no"]) - object instance has properties which are not allowed by the schema: ["vendor_name"] + /system: object has missing required properties (["serial_no"]) + /system: object instance has properties which are not allowed by the schema: ["vendor_name"] diff --git a/tests/state.tests/discovery.json b/tests/state.tests/discovery.json index 21356ca02..ba17241c7 100644 --- a/tests/state.tests/discovery.json +++ b/tests/state.tests/discovery.json @@ -3,7 +3,7 @@ // where {device_id} is that of the discovery node. // { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { @@ -15,7 +15,9 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": true + "operation": { + "operational": true + } }, "discovery": { "families": { diff --git a/tests/state.tests/endpoint_reconfiguration.json b/tests/state.tests/endpoint_reconfiguration.json index 543869cd9..a9d269131 100644 --- a/tests/state.tests/endpoint_reconfiguration.json +++ b/tests/state.tests/endpoint_reconfiguration.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2022-07-13T12:00:10.000Z", "system": { "hardware": { @@ -11,7 +11,9 @@ }, "serial_no": "000000", "last_config": "2022-07-13T12:00:00.000Z", - "operational": true + "operation": { + "operational": true + } }, "blobset": { "blobs": { diff --git a/tests/state.tests/endpoint_reconfiguration_failed.json b/tests/state.tests/endpoint_reconfiguration_failed.json index 8e6244133..1387955cc 100644 --- a/tests/state.tests/endpoint_reconfiguration_failed.json +++ b/tests/state.tests/endpoint_reconfiguration_failed.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2022-07-13T12:00:11.000Z", "system": { "hardware": { @@ -11,7 +11,9 @@ }, "serial_no": "000000", "last_config": "2022-07-13T12:00:00.000Z", - "operational": true + "operation": { + "operational": true + } }, "blobset": { "blobs": { diff --git a/tests/state.tests/enumeration.json b/tests/state.tests/enumeration.json index 6b5512acd..fe3e1e483 100644 --- a/tests/state.tests/enumeration.json +++ b/tests/state.tests/enumeration.json @@ -3,7 +3,7 @@ // where {device_id} is that of the enumerated node. // { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { @@ -15,7 +15,9 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": true + "operation": { + "operational": true + } }, "discovery": { "generation": "2018-08-26T21:37:12Z" diff --git a/tests/state.tests/errors.out b/tests/state.tests/errors.out index 4a694b508..28692d934 100644 --- a/tests/state.tests/errors.out +++ b/tests/state.tests/errors.out @@ -1,6 +1,7 @@ 6 schema violations found - instance type (string) does not match any allowed primitive type (allowed: ["object"]) - object has missing required properties (["hardware","last_config","operational","serial_no","software"]) - object instance has properties which are not allowed by the schema: ["cov_increment","deadband","high_limit","instance_number","low_limit","object_type","rapt","resolution"] - object instance has properties which are not allowed by the schema: ["device_id","device_status","fling","object_name","system_status"] + /pointset/points/return_air_temperature_sensor/status: instance type (string) does not match any allowed primitive type (allowed: ["object"]) + /pointset/points/return_air_temperature_sensor: object instance has properties which are not allowed by the schema: ["cov_increment","deadband","high_limit","instance_number","low_limit","object_type","rapt","resolution"] + /system/status: instance type (string) does not match any allowed primitive type (allowed: ["object"]) + /system: object has missing required properties (["hardware","last_config","operation","serial_no","software"]) + /system: object instance has properties which are not allowed by the schema: ["device_id","device_status","fling","object_name","system_status"] object instance has properties which are not allowed by the schema: ["id","status"] diff --git a/tests/state.tests/example.json b/tests/state.tests/example.json index ee7d78c5a..1a648e802 100644 --- a/tests/state.tests/example.json +++ b/tests/state.tests/example.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { @@ -11,7 +11,12 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": true, + "operation": { + "operational": true, + "last_start": "2018-08-25T21:49:29.364Z", + "mode": "active", + "restart_count": 121 + }, "status": { "message": "Tickity Boo", "category": "system.config.apply", diff --git a/tests/state.tests/fcu.json b/tests/state.tests/fcu.json index 03172c8e9..f2afed938 100644 --- a/tests/state.tests/fcu.json +++ b/tests/state.tests/fcu.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2019-01-17T14:02:29.364Z", "system": { "hardware": { @@ -11,7 +11,9 @@ }, "serial_no": "182732142", "last_config": "2019-01-14T21:49:29.364Z", - "operational": true, + "operation": { + "operational": true + }, "status": { "message": "Time on the device is not synchronized", "category": "system.config.apply", diff --git a/tests/state.tests/gateway.json b/tests/state.tests/gateway.json index 3465794ec..24d62ee0c 100644 --- a/tests/state.tests/gateway.json +++ b/tests/state.tests/gateway.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { // Fixed set of keys with arbitrary values indicating hardware items. @@ -22,7 +22,9 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": true, + "operation": { + "operational": true + }, "status": { "message": "Tickity Boo", "category": "system.config.apply", diff --git a/tests/state.tests/gateway_test.json b/tests/state.tests/gateway_test.json index eae7cca94..ff7686585 100644 --- a/tests/state.tests/gateway_test.json +++ b/tests/state.tests/gateway_test.json @@ -1,10 +1,12 @@ { "system": { - "last_start": "2022-11-09T15:14:29.181Z", + "operation": { + "operational": true, + "last_start": "2022-11-09T15:14:29.181Z" + }, "software": { "firmware": "4.12.0.156" }, - "operational": true, "serial_no": "3637357", "last_config": "2022-11-06T21:30:39.000Z", "hardware": { @@ -23,7 +25,7 @@ } } }, - "version": "1.4.0", + "version": "1.4.1", "gateway": { "devices": { "AHU-18003": {}, diff --git a/tests/state.tests/makemodel_error.json b/tests/state.tests/makemodel_error.json index 8b803a3e9..7898b5c30 100644 --- a/tests/state.tests/makemodel_error.json +++ b/tests/state.tests/makemodel_error.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "make_model": "ACME Bird Trap", @@ -8,7 +8,9 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": true, + "operation": { + "operational": true + }, "status": { "message": "Tickity Boo", "category": "system.config.apply", diff --git a/tests/state.tests/makemodel_error.out b/tests/state.tests/makemodel_error.out index 9a14ae074..779dc6ded 100644 --- a/tests/state.tests/makemodel_error.out +++ b/tests/state.tests/makemodel_error.out @@ -1,3 +1,3 @@ 2 schema violations found - object has missing required properties (["hardware","software"]) - object instance has properties which are not allowed by the schema: ["firmware","make_model"] \ No newline at end of file + /system: object has missing required properties (["hardware","software"]) + /system: object instance has properties which are not allowed by the schema: ["firmware","make_model"] diff --git a/tests/state.tests/restart.json b/tests/state.tests/restart.json index 73d1c57f7..63f252e0c 100644 --- a/tests/state.tests/restart.json +++ b/tests/state.tests/restart.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { @@ -11,8 +11,12 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": false, - "mode": "restart", + "operation": { + "operational": true, + "last_start": "2018-08-25T21:49:29.364Z", + "mode": "restart", + "restart_count": 10 + }, "status": { "message": "System rebooting due to config trigger", "category": "system.config.apply", diff --git a/tests/state.tests/scan_bad.json b/tests/state.tests/scan_bad.json index ffc46499e..98ba4cd1f 100644 --- a/tests/state.tests/scan_bad.json +++ b/tests/state.tests/scan_bad.json @@ -3,7 +3,7 @@ // where {device_id} is that of the discovery node. // { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { @@ -15,7 +15,9 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": true + "operation": { + "operational": true + } }, "discovery": { "families": { diff --git a/tests/state.tests/scan_bad.out b/tests/state.tests/scan_bad.out index 6b0fb8af7..4e3842bea 100644 --- a/tests/state.tests/scan_bad.out +++ b/tests/state.tests/scan_bad.out @@ -1,2 +1,2 @@ 1 schema violations found - object instance has properties which are not allowed by the schema: ["BACnet"] + /discovery/families: object instance has properties which are not allowed by the schema: ["BACnet"] diff --git a/tests/state.tests/scan_error.json b/tests/state.tests/scan_error.json index 10e4ee2fe..4f7ab6f12 100644 --- a/tests/state.tests/scan_error.json +++ b/tests/state.tests/scan_error.json @@ -3,7 +3,7 @@ // where {device_id} is that of the discovery node. // { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { @@ -15,7 +15,9 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": true + "operation": { + "operational": true + } }, "discovery": { "families": { diff --git a/tests/state.tests/scan_stop.json b/tests/state.tests/scan_stop.json index 956b165a6..b5e97c433 100644 --- a/tests/state.tests/scan_stop.json +++ b/tests/state.tests/scan_stop.json @@ -3,7 +3,7 @@ // where {device_id} is that of the discovery node. // { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { @@ -15,7 +15,9 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:49:29.364Z", - "operational": true + "operation": { + "operational": true + } }, "discovery": { "families": { diff --git a/tests/state.tests/writeback.json b/tests/state.tests/writeback.json index a1e2f0482..9810c7c32 100644 --- a/tests/state.tests/writeback.json +++ b/tests/state.tests/writeback.json @@ -1,5 +1,5 @@ { - "version": "1.4.0", + "version": "1.4.1", "timestamp": "2018-08-26T21:39:29.364Z", "system": { "hardware": { @@ -11,7 +11,9 @@ }, "serial_no": "182732142", "last_config": "2018-08-26T21:38:29.364Z", - "operational": true + "operation": { + "operational": true + } }, "pointset": { "state_etag": "2a8b718", diff --git a/udmis/deploy_udmis_gcloud b/udmis/deploy_udmis_gcloud index 9146cf029..0005be069 100755 --- a/udmis/deploy_udmis_gcloud +++ b/udmis/deploy_udmis_gcloud @@ -1,5 +1,9 @@ #!/bin/bash -e +# This version is used to automatically check that the deployed cloud functions are suitable for any bit +# of client code. Clients (e.g. sqeuencer) can query this value and check that it's within range. +FUNCTIONS_VERSION=1 + if (( $# < 1 )); then echo Usage: $0 PROJECT_ID [options] false @@ -11,7 +15,7 @@ cd $ROOT/udmis PROJECT=$1 shift -RUNTIME=nodejs12 +RUNTIME=nodejs16 SOURCE=functions/ version=`git describe --dirty` @@ -19,7 +23,8 @@ echo Deploying version $version to $PROJECT cat < functions/version.js module.exports = { - udmis: '$version' + udmis: '$version', + functions: $FUNCTIONS_VERSION } EOF diff --git a/udmis/functions/index.js b/udmis/functions/index.js index 1fdd900d1..3282cc020 100644 --- a/udmis/functions/index.js +++ b/udmis/functions/index.js @@ -19,6 +19,7 @@ const iot = require('@google-cloud/iot'); const REFLECT_REGISTRY = 'UDMS-REFLECT'; const UDMI_VERSION = version.udmis; +const UDMI_FUNCTIONS = version.functions; const EVENT_TYPE = 'event'; const CONFIG_TYPE = 'config'; const STATE_TYPE = 'state'; @@ -30,6 +31,7 @@ const ALL_REGIONS = ['us-central1', 'europe-west1', 'asia-east1']; let registry_regions = null; console.log('Using UDMI version ' + UDMI_VERSION); +console.log('Using functions ver ' + UDMI_FUNCTIONS); if (useFirestore) { admin.initializeApp(functions.config().firebase); @@ -60,8 +62,8 @@ function recordMessage(attributes, message) { message.timestamp = timestamp; message.version = message.version || UDMI_VERSION; } - - console.log('Message record', registryId, deviceId, subType, subFolder, message.event_count); + const event_count = message && message.event_count; + console.log('Message record', registryId, deviceId, subType, subFolder, event_count); if (useFirestore) { const reg_doc = firestore.collection('registries').doc(registryId); @@ -87,8 +89,8 @@ function recordMessage(attributes, message) { } function sendCommand(registryId, deviceId, subFolder, message) { - return sendCommandStr(registryId, deviceId, subFolder, JSON.stringify(message), - message.debug_config_nonce); + const nonce = message && message.debug_config_nonce; + return sendCommandStr(registryId, deviceId, subFolder, JSON.stringify(message), nonce); } function sendCommandStr(registryId, deviceId, subFolder, messageStr, nonce) { @@ -169,13 +171,14 @@ exports.udmi_reflect = functions.pubsub.topic('udmi_reflect').onPublish((event) return udmi_reflector_state(attributes, msgObject); } + const nonce = msgObject && msgObject.debug_config_nonce; const parts = attributes.subFolder.split('/'); attributes.deviceRegistryId = attributes.deviceId; attributes.deviceId = parts[1]; attributes.subFolder = parts[2]; attributes.subType = parts[3]; console.log('Reflect', attributes.deviceRegistryId, attributes.deviceId, attributes.subType, - attributes.subFolder, msgObject.debug_config_nonce); + attributes.subFolder, nonce); return registry_promise.then(() => { attributes.cloudRegion = registry_regions[attributes.deviceRegistryId]; @@ -197,6 +200,7 @@ function udmi_reflector_state(attributes, msgObject) { const registryId = attributes.deviceRegistryId; const deviceId = attributes.deviceId; const subContents = { + 'functions': UDMI_FUNCTIONS, 'last_state': msgObject.timestamp }; const startTime = currentTimestamp(); @@ -273,7 +277,9 @@ function process_state_update(attributes, msgObject) { attributes.subType = STATE_TYPE; promises.push(publishPubsubMessage('udmi_target', attributes, msgObject)); - const stateStart = msgObject.system && msgObject.system.last_start; + // Check both potential locations for last_start, can be cleaned-up post release. + const stateStart = msgObject.system && + (msgObject.system.last_start || msgObject.system.operation.last_start); stateStart && promises.push(modify_device_config(registryId, deviceId, 'last_start', stateStart, currentTimestamp())); @@ -309,8 +315,8 @@ exports.udmi_config = functions.pubsub.topic('udmi_config').onPublish((event) => const msgString = Buffer.from(base64, 'base64').toString(); const msgObject = JSON.parse(msgString); - console.log('Config message', registryId, deviceId, subFolder, msgObject.debug_config_nonce, - msgString); + const nonce = msgObject && msgObject.debug_config_nonce; + console.log('Config message', registryId, deviceId, subFolder, nonce, msgString); if (!msgString) { console.warn('Config abort', registryId, deviceId, subFolder, msgString); return null; @@ -343,11 +349,25 @@ function parse_old_config(configStr, resetConfig) { } if (resetConfig) { - const configLastStart = config.system && config.system.last_start; + const configLastStart = config.system && + (config.system.last_start || + (config.system.operation && config.system.operation.last_start)); console.warn('Resetting config bock', configLastStart); - config = { - system: { - last_start: configLastStart + + // Preserve the original structure of the config message for backwards compatibility. + if (config.system && config.system.operation) { + config = { + system: { + "operation": { + last_start: configLastStart + } + } + } + } else { + config = { + system: { + last_start: configLastStart + } } } } @@ -355,11 +375,18 @@ function parse_old_config(configStr, resetConfig) { } function update_last_start(config, stateStart) { - const configStart = config.system && config.system.last_start; + const configLastStart = config.system && + (config.system.last_start || + (config.system.operation && config.system.operation.last_start)); const stateNonce = Date.now(); - const shouldUpdate = stateStart && (!configStart || (stateStart > configStart)); - console.log('State update last state/config', stateStart, configStart, shouldUpdate, stateNonce); - config.system.last_start = stateStart; + const shouldUpdate = stateStart && (!configLastStart || (stateStart > configLastStart)); + console.log('State update last state/config', stateStart, configLastStart, shouldUpdate, stateNonce); + // Preserve the existing structure of the config message to maintain backwards compatability. + if (config.system && config.system.operation) { + config.system.operation.last_start = stateStart; + } else { + config.system.last_start = stateStart; + } if (config.debug_config_nonce) { config.debug_config_nonce = stateNonce; config.system.debug_config_nonce = stateNonce; @@ -370,6 +397,7 @@ function update_last_start(config, stateStart) { async function modify_device_config(registryId, deviceId, subFolder, subContents, startTime) { const [oldConfig, version] = await get_device_config(registryId, deviceId); var newConfig; + const nonce = subContents && subContents.debug_config_nonce; if (subFolder == 'last_start') { newConfig = parse_old_config(oldConfig, false); @@ -377,7 +405,7 @@ async function modify_device_config(registryId, deviceId, subFolder, subContents return; } } else if (subFolder == 'update') { - console.log('Config replace version', version, startTime, subContents.debug_config_nonce); + console.log('Config replace version', version, startTime, nonce); newConfig = subContents; } else { const resetConfig = subFolder == 'system' && subContents && subContents.extra_field == 'reset_config'; @@ -389,12 +417,12 @@ async function modify_device_config(registryId, deviceId, subFolder, subContents newConfig.version = UDMI_VERSION; newConfig.timestamp = currentTimestamp(); - console.log('Config modify', subFolder, version, startTime, subContents.debug_config_nonce); + console.log('Config modify', subFolder, version, startTime, nonce); if (subContents) { delete subContents.version; delete subContents.timestamp; newConfig[subFolder] = subContents; - newConfig.debug_config_nonce = subContents.debug_config_nonce; + newConfig.debug_config_nonce = nonce; } else { if (!newConfig[subFolder]) { console.log('Config target already null', subFolder, version, startTime); @@ -412,11 +440,9 @@ async function modify_device_config(registryId, deviceId, subFolder, subContents }; return update_device_config(newConfig, attributes, version) .then(() => { - console.log('Config accepted', subFolder, version, startTime, - subContents.debug_config_nonce); + console.log('Config accepted', subFolder, version, startTime, nonce); }).catch(e => { - console.log('Config rejected', subFolder, version, startTime, - subContents.debug_config_nonce); + console.log('Config rejected', subFolder, version, startTime, nonce); return modify_device_config(registryId, deviceId, subFolder, subContents, startTime); }) } @@ -457,7 +483,7 @@ function update_device_config(message, attributes, preVersion) { const normalJson = extraField !== 'break_json'; console.log('Config extra field is ' + extraField + ' ' + normalJson); - const nonce = message.debug_config_nonce; + const nonce = message && message.debug_config_nonce; const msgString = normalJson ? JSON.stringify(message) : '{ broken because extra_field == ' + message.system.extra_field; const binaryData = Buffer.from(msgString); diff --git a/udmis/functions/package-lock.json b/udmis/functions/package-lock.json index a243f497a..02d4754d4 100644 --- a/udmis/functions/package-lock.json +++ b/udmis/functions/package-lock.json @@ -14,7 +14,7 @@ "node-forge": "1.3.0" }, "engines": { - "node": "12" + "node": "16" } }, "node_modules/@babel/parser": { diff --git a/udmis/functions/package.json b/udmis/functions/package.json index 141a334fa..3a81d3b45 100644 --- a/udmis/functions/package.json +++ b/udmis/functions/package.json @@ -9,7 +9,7 @@ "logs": "firebase functions:log" }, "engines": { - "node": "12" + "node": "16" }, "dependencies": { "@google-cloud/iot": "2.3.4", diff --git a/udmis/package-lock.json b/udmis/package-lock.json index 4d56041e1..ee1fff7b3 100644 --- a/udmis/package-lock.json +++ b/udmis/package-lock.json @@ -1,6 +1,3025 @@ { - "name": "dashboard", + "name": "udmis", "lockfileVersion": 2, "requires": true, - "packages": {} + "packages": { + "": { + "dependencies": { + "firebase-admin": "10.3" + } + }, + "node_modules/@fastify/busboy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.1.0.tgz", + "integrity": "sha512-Fv854f94v0CzIDllbY3i/0NJPNBRNLDawf3BTYVGCe9VrIIs3Wi7AFx24F9NzCxdf0wyx/x0Q9kEVnvDOPnlxA==", + "dependencies": { + "text-decoding": "^1.0.0" + }, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", + "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==", + "peer": true + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.7.tgz", + "integrity": "sha512-yA/dTveGGPcc85JP8ZE/KZqfGQyQTBCV10THdI8HTlP1GDvNrhr//J5jAt58MlsCOaO3XmC4DqScPBbtIsR/EA==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.21.tgz", + "integrity": "sha512-12MMQ/ulfygKpEJpseYMR0HunJdlsLrwx2XcEs40M18jocy2+spyzHHEwegN3x/2/BLFBjR5247Etmz0G97Qpg==", + "dependencies": { + "@firebase/util": "1.7.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "0.13.10", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.13.10.tgz", + "integrity": "sha512-KRucuzZ7ZHQsRdGEmhxId5jyM2yKsjsQWF9yv0dIhlxYg0D8rCVDZc/waoPKA5oV3/SEIoptF8F7R1Vfe7BCQA==", + "dependencies": { + "@firebase/auth-interop-types": "0.1.7", + "@firebase/component": "0.5.21", + "@firebase/logger": "0.3.4", + "@firebase/util": "1.7.3", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.2.10.tgz", + "integrity": "sha512-fK+IgUUqVKcWK/gltzDU+B1xauCOfY6vulO8lxoNTkcCGlSxuTtwsdqjGkFmgFRMYjXFWWJ6iFcJ/vXahzwCtA==", + "dependencies": { + "@firebase/component": "0.5.21", + "@firebase/database": "0.13.10", + "@firebase/database-types": "0.9.17", + "@firebase/logger": "0.3.4", + "@firebase/util": "1.7.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "0.9.17", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.17.tgz", + "integrity": "sha512-YQm2tCZyxNtEnlS5qo5gd2PAYgKCy69tUKwioGhApCFThW+mIgZs7IeYeJo2M51i4LCixYUl+CvnOyAnb/c3XA==", + "dependencies": { + "@firebase/app-types": "0.8.1", + "@firebase/util": "1.7.3" + } + }, + "node_modules/@firebase/database-types/node_modules/@firebase/app-types": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.8.1.tgz", + "integrity": "sha512-p75Ow3QhB82kpMzmOntv866wH9eZ3b4+QbUY+8/DA5Zzdf1c8Nsk8B7kbFpzJt4wwHMdy5LTF5YUnoTc1JiWkw==" + }, + "node_modules/@firebase/logger": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.4.tgz", + "integrity": "sha512-hlFglGRgZEwoyClZcGLx/Wd+zoLfGmbDkFx56mQt/jJ0XMbfPqwId1kiPl0zgdWZX+D8iH+gT6GuLPFsJWgiGw==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/util": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.7.3.tgz", + "integrity": "sha512-wxNqWbqokF551WrJ9BIFouU/V5SL1oYCGx1oudcirdhadnQRFH5v1sjgGL7cUV/UsekSycygphdrF2lxBxOYKg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@google-cloud/firestore": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.15.1.tgz", + "integrity": "sha512-2PWsCkEF1W02QbghSeRsNdYKN1qavrHBP3m72gPDMHQSYrGULOaTi7fSJquQmAtc4iPVB2/x6h80rdLHTATQtA==", + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^2.24.1", + "protobufjs": "^6.8.6" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@google-cloud/paginator": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz", + "integrity": "sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/projectify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.1.1.tgz", + "integrity": "sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ==", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz", + "integrity": "sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/storage": { + "version": "5.20.5", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.20.5.tgz", + "integrity": "sha512-lOs/dCyveVF8TkVFnFSF7IGd0CJrTm91qiK6JLu+Z8qiT+7Ag0RyVhxZIWkhiACqwABo7kSHDm8FdH8p2wxSSw==", + "optional": true, + "dependencies": { + "@google-cloud/paginator": "^3.0.7", + "@google-cloud/projectify": "^2.0.0", + "@google-cloud/promisify": "^2.0.0", + "abort-controller": "^3.0.0", + "arrify": "^2.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "configstore": "^5.0.0", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "gaxios": "^4.0.0", + "google-auth-library": "^7.14.1", + "hash-stream-validation": "^0.2.2", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "pumpify": "^2.0.0", + "retry-request": "^4.2.2", + "stream-events": "^1.0.4", + "teeny-request": "^7.1.3", + "uuid": "^8.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.12.tgz", + "integrity": "sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw==", + "optional": true, + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/grpc-js/node_modules/@grpc/proto-loader": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.4.tgz", + "integrity": "sha512-MnWjkGwqQ3W8fx94/c1CwqLsNmHHv2t0CFn+9++6+cDphC1lolpg9M2OU0iebIjK//pBNX9e94ho+gjx6vz39w==", + "optional": true, + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^7.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/grpc-js/node_modules/protobufjs": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.1.2.tgz", + "integrity": "sha512-4ZPTPkXCdel3+L81yw3dG6+Kq3umdWKh7Dc7GW/CpNk4SX3hK58iPCWeCyhVTDrbkNeKrYNZ7EojM5WDaEWTLQ==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@grpc/grpc-js/node_modules/protobufjs/node_modules/long": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", + "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==", + "optional": true + }, + "node_modules/@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "optional": true, + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.11.3", + "yargs": "^16.2.0" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "optional": true + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "optional": true + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "optional": true + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "optional": true + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "optional": true + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "optional": true + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "optional": true + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "optional": true + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "optional": true + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "optional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.15.tgz", + "integrity": "sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.31", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/jsonwebtoken": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz", + "integrity": "sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "optional": true + }, + "node_modules/@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "node_modules/@types/node": { + "version": "18.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz", + "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "dependencies": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "optional": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "optional": true, + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, + "node_modules/bignumber.js": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "optional": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "optional": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "optional": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "optional": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "optional": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "optional": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "optional": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true + }, + "node_modules/fast-text-encoding": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", + "optional": true + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/firebase-admin": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.3.0.tgz", + "integrity": "sha512-A0wgMLEjyVyUE+heyMJYqHRkPVjpebhOYsa47RHdrTM4ltApcx8Tn86sUmjqxlfh09gNnILAm7a8q5+FmgBYpg==", + "dependencies": { + "@fastify/busboy": "^1.1.0", + "@firebase/database-compat": "^0.2.0", + "@firebase/database-types": "^0.9.7", + "@types/node": ">=12.12.47", + "jsonwebtoken": "^8.5.1", + "jwks-rsa": "^2.0.2", + "node-forge": "^1.3.1", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^4.15.1", + "@google-cloud/storage": "^5.18.3" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "optional": true + }, + "node_modules/gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "optional": true, + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "optional": true, + "dependencies": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "optional": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/google-gax": { + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", + "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "~1.6.0", + "@grpc/proto-loader": "^0.6.12", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^7.14.0", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^0.1.8", + "protobufjs": "6.11.3", + "retry-request": "^4.0.0" + }, + "bin": { + "compileProtos": "build/tools/compileProtos.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "optional": true, + "dependencies": { + "node-forge": "^1.3.1" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "optional": true + }, + "node_modules/gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "optional": true, + "dependencies": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hash-stream-validation": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz", + "integrity": "sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==", + "optional": true + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "optional": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", + "optional": true + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "optional": true + }, + "node_modules/jose": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.6.tgz", + "integrity": "sha512-FVoPY7SflDodE4lknJmbAHSUjLCzE2H1F6MS0RYKMQ8SR+lNccpMf8R4eqkNYyyUjR5qZReOzZo5C5YiHOCjjg==", + "dependencies": { + "@panva/asn1.js": "^1.0.0" + }, + "engines": { + "node": ">=10.13.0 < 13 || >=13.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "optional": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwks-rsa": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.5.tgz", + "integrity": "sha512-IODtn1SwEm7n6GQZnQLY0oxKDrMh7n/jRH1MzE8mlxWMrh2NnMyOsXTebu8vJ1qCpmuTJcL4DdiE0E4h8jnwsA==", + "dependencies": { + "@types/express": "^4.17.14", + "@types/jsonwebtoken": "^8.5.9", + "debug": "^4.3.4", + "jose": "^2.0.6", + "limiter": "^1.1.5", + "lru-memoizer": "^2.1.4" + }, + "engines": { + "node": ">=10 < 13 || >=14" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "optional": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "optional": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru-memoizer": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz", + "integrity": "sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==", + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "~4.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/lru-cache": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", + "dependencies": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + } + }, + "node_modules/lru-memoizer/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "optional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "optional": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "optional": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/proto3-json-serializer": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", + "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "optional": true, + "dependencies": { + "protobufjs": "^6.11.2" + } + }, + "node_modules/protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "optional": true, + "dependencies": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-request": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz", + "integrity": "sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==", + "optional": true, + "dependencies": { + "debug": "^4.1.1", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true + }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "optional": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "optional": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "optional": true + }, + "node_modules/teeny-request": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.2.0.tgz", + "integrity": "sha512-SyY0pek1zWsi0LRVAALem+avzMLc33MKW/JLLakdP4s9+D7+jHcy5x6P+h94g2QNZsAqQNfX5lsbd3WSeJXrrw==", + "optional": true, + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, + "node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "optional": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "optional": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "optional": true + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "optional": true + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "optional": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@fastify/busboy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.1.0.tgz", + "integrity": "sha512-Fv854f94v0CzIDllbY3i/0NJPNBRNLDawf3BTYVGCe9VrIIs3Wi7AFx24F9NzCxdf0wyx/x0Q9kEVnvDOPnlxA==", + "requires": { + "text-decoding": "^1.0.0" + } + }, + "@firebase/app-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.0.tgz", + "integrity": "sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==", + "peer": true + }, + "@firebase/auth-interop-types": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.7.tgz", + "integrity": "sha512-yA/dTveGGPcc85JP8ZE/KZqfGQyQTBCV10THdI8HTlP1GDvNrhr//J5jAt58MlsCOaO3XmC4DqScPBbtIsR/EA==", + "requires": {} + }, + "@firebase/component": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.21.tgz", + "integrity": "sha512-12MMQ/ulfygKpEJpseYMR0HunJdlsLrwx2XcEs40M18jocy2+spyzHHEwegN3x/2/BLFBjR5247Etmz0G97Qpg==", + "requires": { + "@firebase/util": "1.7.3", + "tslib": "^2.1.0" + } + }, + "@firebase/database": { + "version": "0.13.10", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.13.10.tgz", + "integrity": "sha512-KRucuzZ7ZHQsRdGEmhxId5jyM2yKsjsQWF9yv0dIhlxYg0D8rCVDZc/waoPKA5oV3/SEIoptF8F7R1Vfe7BCQA==", + "requires": { + "@firebase/auth-interop-types": "0.1.7", + "@firebase/component": "0.5.21", + "@firebase/logger": "0.3.4", + "@firebase/util": "1.7.3", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + } + }, + "@firebase/database-compat": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-0.2.10.tgz", + "integrity": "sha512-fK+IgUUqVKcWK/gltzDU+B1xauCOfY6vulO8lxoNTkcCGlSxuTtwsdqjGkFmgFRMYjXFWWJ6iFcJ/vXahzwCtA==", + "requires": { + "@firebase/component": "0.5.21", + "@firebase/database": "0.13.10", + "@firebase/database-types": "0.9.17", + "@firebase/logger": "0.3.4", + "@firebase/util": "1.7.3", + "tslib": "^2.1.0" + } + }, + "@firebase/database-types": { + "version": "0.9.17", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.9.17.tgz", + "integrity": "sha512-YQm2tCZyxNtEnlS5qo5gd2PAYgKCy69tUKwioGhApCFThW+mIgZs7IeYeJo2M51i4LCixYUl+CvnOyAnb/c3XA==", + "requires": { + "@firebase/app-types": "0.8.1", + "@firebase/util": "1.7.3" + }, + "dependencies": { + "@firebase/app-types": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.8.1.tgz", + "integrity": "sha512-p75Ow3QhB82kpMzmOntv866wH9eZ3b4+QbUY+8/DA5Zzdf1c8Nsk8B7kbFpzJt4wwHMdy5LTF5YUnoTc1JiWkw==" + } + } + }, + "@firebase/logger": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.3.4.tgz", + "integrity": "sha512-hlFglGRgZEwoyClZcGLx/Wd+zoLfGmbDkFx56mQt/jJ0XMbfPqwId1kiPl0zgdWZX+D8iH+gT6GuLPFsJWgiGw==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@firebase/util": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.7.3.tgz", + "integrity": "sha512-wxNqWbqokF551WrJ9BIFouU/V5SL1oYCGx1oudcirdhadnQRFH5v1sjgGL7cUV/UsekSycygphdrF2lxBxOYKg==", + "requires": { + "tslib": "^2.1.0" + } + }, + "@google-cloud/firestore": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.15.1.tgz", + "integrity": "sha512-2PWsCkEF1W02QbghSeRsNdYKN1qavrHBP3m72gPDMHQSYrGULOaTi7fSJquQmAtc4iPVB2/x6h80rdLHTATQtA==", + "optional": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^2.24.1", + "protobufjs": "^6.8.6" + } + }, + "@google-cloud/paginator": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz", + "integrity": "sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + } + }, + "@google-cloud/projectify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.1.1.tgz", + "integrity": "sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ==", + "optional": true + }, + "@google-cloud/promisify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz", + "integrity": "sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==", + "optional": true + }, + "@google-cloud/storage": { + "version": "5.20.5", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.20.5.tgz", + "integrity": "sha512-lOs/dCyveVF8TkVFnFSF7IGd0CJrTm91qiK6JLu+Z8qiT+7Ag0RyVhxZIWkhiACqwABo7kSHDm8FdH8p2wxSSw==", + "optional": true, + "requires": { + "@google-cloud/paginator": "^3.0.7", + "@google-cloud/projectify": "^2.0.0", + "@google-cloud/promisify": "^2.0.0", + "abort-controller": "^3.0.0", + "arrify": "^2.0.0", + "async-retry": "^1.3.3", + "compressible": "^2.0.12", + "configstore": "^5.0.0", + "duplexify": "^4.0.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "gaxios": "^4.0.0", + "google-auth-library": "^7.14.1", + "hash-stream-validation": "^0.2.2", + "mime": "^3.0.0", + "mime-types": "^2.0.8", + "p-limit": "^3.0.1", + "pumpify": "^2.0.0", + "retry-request": "^4.2.2", + "stream-events": "^1.0.4", + "teeny-request": "^7.1.3", + "uuid": "^8.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "@grpc/grpc-js": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.6.12.tgz", + "integrity": "sha512-JmvQ03OTSpVd9JTlj/K3IWHSz4Gk/JMLUTtW7Zb0KvO1LcOYGATh5cNuRYzCAeDR3O8wq+q8FZe97eO9MBrkUw==", + "optional": true, + "requires": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "dependencies": { + "@grpc/proto-loader": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.4.tgz", + "integrity": "sha512-MnWjkGwqQ3W8fx94/c1CwqLsNmHHv2t0CFn+9++6+cDphC1lolpg9M2OU0iebIjK//pBNX9e94ho+gjx6vz39w==", + "optional": true, + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^7.0.0", + "yargs": "^16.2.0" + } + }, + "protobufjs": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.1.2.tgz", + "integrity": "sha512-4ZPTPkXCdel3+L81yw3dG6+Kq3umdWKh7Dc7GW/CpNk4SX3hK58iPCWeCyhVTDrbkNeKrYNZ7EojM5WDaEWTLQ==", + "optional": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "dependencies": { + "long": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", + "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==", + "optional": true + } + } + } + } + }, + "@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "optional": true, + "requires": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.11.3", + "yargs": "^16.2.0" + } + }, + "@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "optional": true + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "optional": true + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "optional": true + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "optional": true + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "optional": true, + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "optional": true + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "optional": true + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "optional": true + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "optional": true + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "optional": true + }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "optional": true + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.15.tgz", + "integrity": "sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.31", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/jsonwebtoken": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz", + "integrity": "sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==", + "requires": { + "@types/node": "*" + } + }, + "@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "optional": true + }, + "@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "@types/node": { + "version": "18.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz", + "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==" + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "requires": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "optional": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "requires": { + "debug": "4" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "optional": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "optional": true + }, + "async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "optional": true, + "requires": { + "retry": "0.13.1" + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "optional": true + }, + "bignumber.js": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "optional": true + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "optional": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "optional": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "optional": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "optional": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "optional": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "optional": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "optional": true, + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "optional": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "optional": true, + "requires": { + "once": "^1.4.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "optional": true + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "optional": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true + }, + "fast-text-encoding": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", + "optional": true + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "firebase-admin": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-10.3.0.tgz", + "integrity": "sha512-A0wgMLEjyVyUE+heyMJYqHRkPVjpebhOYsa47RHdrTM4ltApcx8Tn86sUmjqxlfh09gNnILAm7a8q5+FmgBYpg==", + "requires": { + "@fastify/busboy": "^1.1.0", + "@firebase/database-compat": "^0.2.0", + "@firebase/database-types": "^0.9.7", + "@google-cloud/firestore": "^4.15.1", + "@google-cloud/storage": "^5.18.3", + "@types/node": ">=12.12.47", + "jsonwebtoken": "^8.5.1", + "jwks-rsa": "^2.0.2", + "node-forge": "^1.3.1", + "uuid": "^8.3.2" + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "optional": true + }, + "gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "optional": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + } + }, + "gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "optional": true, + "requires": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "optional": true + }, + "google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-gax": { + "version": "2.30.5", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.30.5.tgz", + "integrity": "sha512-Jey13YrAN2hfpozHzbtrwEfEHdStJh1GwaQ2+Akh1k0Tv/EuNVSuBtHZoKSBm5wBMvNsxTsEIZ/152NrYyZgxQ==", + "optional": true, + "requires": { + "@grpc/grpc-js": "~1.6.0", + "@grpc/proto-loader": "^0.6.12", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^4.0.0", + "fast-text-encoding": "^1.0.3", + "google-auth-library": "^7.14.0", + "is-stream-ended": "^0.1.4", + "node-fetch": "^2.6.1", + "object-hash": "^3.0.0", + "proto3-json-serializer": "^0.1.8", + "protobufjs": "6.11.3", + "retry-request": "^4.0.0" + } + }, + "google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "optional": true, + "requires": { + "node-forge": "^1.3.1" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "optional": true + }, + "gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "optional": true, + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + } + }, + "hash-stream-validation": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz", + "integrity": "sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==", + "optional": true + }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "optional": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "optional": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "optional": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "optional": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "optional": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "optional": true + }, + "is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", + "optional": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "optional": true + }, + "jose": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.6.tgz", + "integrity": "sha512-FVoPY7SflDodE4lknJmbAHSUjLCzE2H1F6MS0RYKMQ8SR+lNccpMf8R4eqkNYyyUjR5qZReOzZo5C5YiHOCjjg==", + "requires": { + "@panva/asn1.js": "^1.0.0" + } + }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "optional": true, + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + } + } + }, + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jwks-rsa": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.5.tgz", + "integrity": "sha512-IODtn1SwEm7n6GQZnQLY0oxKDrMh7n/jRH1MzE8mlxWMrh2NnMyOsXTebu8vJ1qCpmuTJcL4DdiE0E4h8jnwsA==", + "requires": { + "@types/express": "^4.17.14", + "@types/jsonwebtoken": "^8.5.9", + "debug": "^4.3.4", + "jose": "^2.0.6", + "limiter": "^1.1.5", + "lru-memoizer": "^2.1.4" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "limiter": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "optional": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "optional": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "lru-memoizer": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz", + "integrity": "sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==", + "requires": { + "lodash.clonedeep": "^4.5.0", + "lru-cache": "~4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", + "requires": { + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + } + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "optional": true + } + } + }, + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "optional": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "optional": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "optional": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "optional": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "optional": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "proto3-json-serializer": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz", + "integrity": "sha512-A60IisqvnuI45qNRygJjrnNjX2TMdQGMY+57tR3nul3ZgO2zXkR9OGR8AXxJhkqx84g0FTnrfi3D5fWMSdANdQ==", + "optional": true, + "requires": { + "protobufjs": "^6.11.2" + } + }, + "protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "optional": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "optional": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "optional": true, + "requires": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "optional": true + }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "optional": true + }, + "retry-request": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz", + "integrity": "sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==", + "optional": true, + "requires": { + "debug": "^4.1.1", + "extend": "^3.0.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true + }, + "stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "optional": true, + "requires": { + "stubs": "^3.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "optional": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "optional": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "optional": true + }, + "teeny-request": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.2.0.tgz", + "integrity": "sha512-SyY0pek1zWsi0LRVAALem+avzMLc33MKW/JLLakdP4s9+D7+jHcy5x6P+h94g2QNZsAqQNfX5lsbd3WSeJXrrw==", + "optional": true, + "requires": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^8.0.0" + } + }, + "text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, + "tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "optional": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "optional": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "optional": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "optional": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "optional": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "optional": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "optional": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "optional": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "optional": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "optional": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "optional": true + } + } } diff --git a/validator/sequences/broken_config/sequence.md b/validator/sequences/broken_config/sequence.md index fb77eed22..9b82b2cdc 100644 --- a/validator/sequences/broken_config/sequence.md +++ b/validator/sequences/broken_config/sequence.md @@ -15,7 +15,6 @@ Check that the device correctly handles a broken (non-json) config message. 1. Force reset config 1. Check that no interesting system status 1. Update config before last_config updated: - * Add `system.last_start` = `device reported` * Set `system.min_loglevel` = `100` 1. Wait for last_config updated 1. Wait for log category `system.config.apply` level `NOTICE` was logged diff --git a/validator/sequences/empty_enumeration/sequence.md b/validator/sequences/empty_enumeration/sequence.md index 342117497..12653f15d 100644 --- a/validator/sequences/empty_enumeration/sequence.md +++ b/validator/sequences/empty_enumeration/sequence.md @@ -11,5 +11,5 @@ * Remove `discovery.generation` 1. Wait for cleared enumeration generation 1. Check that no family enumeration -1. Check that no point enumeration 1. Check that no feature enumeration +1. Check that no point enumeration diff --git a/validator/sequences/endpoint_connection_success_alternate/sequence.md b/validator/sequences/endpoint_connection_success_alternate/sequence.md index b780a9f33..f3144733f 100644 --- a/validator/sequences/endpoint_connection_success_alternate/sequence.md +++ b/validator/sequences/endpoint_connection_success_alternate/sequence.md @@ -8,8 +8,6 @@ Check connection to an alternate project. * Add `blobset` = { "blobs": { "_iot_endpoint_config": { "phase": `final`, "generation": `blob generation`, "sha256": `blob data hash`, "url": `endpoint url` } } } 1. Wait for blobset phase is apply and stateStatus is null 1. Check that no interesting system status -1. Update config before blobset phase is final and stateStatus is null: - * Add `system.testing.endpoint_type` = `alternate` 1. Wait for blobset phase is final and stateStatus is null 1. Check that no interesting system status 1. Wait for alternate last_config matches config timestamp @@ -20,8 +18,6 @@ Check connection to an alternate project. * Add `blobset.blobs._iot_endpoint_config` = { "phase": `final`, "generation": `blob generation`, "sha256": `blob data hash`, "url": `endpoint url` } 1. Wait for blobset phase is apply and stateStatus is null 1. Check that no interesting system status -1. Update config before blobset phase is final and stateStatus is null: - * Remove `system.testing.endpoint_type` 1. Wait for blobset phase is final and stateStatus is null 1. Check that no interesting system status 1. Wait for restored last_config matches config timestamp diff --git a/validator/sequences/system_mode_restart/sequence.md b/validator/sequences/system_mode_restart/sequence.md index 0c78bed83..93056b7a3 100644 --- a/validator/sequences/system_mode_restart/sequence.md +++ b/validator/sequences/system_mode_restart/sequence.md @@ -4,14 +4,16 @@ Restart and connect to same endpoint and expect it returns. 1. Wait for last_start is not zero -1. Update config before deviceState.system.mode == ACTIVE: - * Add `system.mode` = `active` -1. Wait for deviceState.system.mode == ACTIVE -1. Update config before deviceState.system.mode == INITIAL: - * Set `system.mode` = `restart` -1. Wait for deviceState.system.mode == INITIAL -1. Update config before deviceState.system.mode == ACTIVE: - * Set `system.mode` = `active` -1. Wait for deviceState.system.mode == ACTIVE +1. Check that initial count is greater than 0 +1. Update config before system mode is ACTIVE: + * Add `system.operation.mode` = `active` +1. Wait for system mode is ACTIVE +1. Update config before system mode is INITIAL: + * Set `system.operation.mode` = `restart` +1. Wait for system mode is INITIAL +1. Check that restart count increased by one +1. Update config before system mode is ACTIVE: + * Set `system.operation.mode` = `active` +1. Wait for system mode is ACTIVE 1. Wait for last_config is newer than previous last_config after abort 1. Wait for last_start is newer than previous last_start diff --git a/validator/sequences/valid_serial_no/sequence.md b/validator/sequences/valid_serial_no/sequence.md index e9f160f79..7e94d8e4e 100644 --- a/validator/sequences/valid_serial_no/sequence.md +++ b/validator/sequences/valid_serial_no/sequence.md @@ -1,4 +1,4 @@ ## valid_serial_no -1. Wait for received serial no matches +1. Wait for received serial number matches diff --git a/validator/src/main/java/com/google/daq/mqtt/registrar/LocalDevice.java b/validator/src/main/java/com/google/daq/mqtt/registrar/LocalDevice.java index 10b6d6892..91319fb54 100644 --- a/validator/src/main/java/com/google/daq/mqtt/registrar/LocalDevice.java +++ b/validator/src/main/java/com/google/daq/mqtt/registrar/LocalDevice.java @@ -72,6 +72,7 @@ import udmi.schema.GatewayConfig; import udmi.schema.LocalnetConfig; import udmi.schema.Metadata; +import udmi.schema.Operation; import udmi.schema.PointPointsetConfig; import udmi.schema.PointPointsetModel; import udmi.schema.PointsetConfig; @@ -185,7 +186,7 @@ class LocalDevice { ES_CERT_TYPE, ES_CERT_FILE); private static final String ERROR_FORMAT_INDENT = " "; private static final int MAX_METADATA_LENGTH = 32767; - private static final String UDMI_VERSION = "1.4.0"; + private static final String UDMI_VERSION = "1.4.1"; private final String deviceId; private final Map schemas; private final File siteDir; @@ -295,7 +296,7 @@ private Metadata readMetadataWithValidation(boolean validate) { try (InputStream targetStream = new FileInputStream(metadataFile)) { instance = OBJECT_MAPPER.readTree(targetStream); baseVersion = instance.get(VERSION_PROPERTY_KEY); - new MessageUpgrader(METADATA_SCHEMA, instance).upgrade(); + new MessageUpgrader(METADATA_SCHEMA, instance).upgrade(false); } catch (IOException ioException) { exceptionMap.put(EXCEPTION_LOADING, ioException); return null; @@ -560,6 +561,8 @@ public Config deviceConfigObject() { Config config = new Config(); config.timestamp = metadata.timestamp; config.version = UDMI_VERSION; + config.system = new SystemConfig(); + config.system.operation = new Operation(); if (isGateway()) { config.gateway = new GatewayConfig(); config.gateway.proxy_ids = getProxyDevicesList(); @@ -572,9 +575,6 @@ public Config deviceConfigObject() { } // Copy selected MetadataSystem properties into device config. if (metadata.system.min_loglevel != null) { - if (config.system == null) { - config.system = new SystemConfig(); - } config.system.min_loglevel = metadata.system.min_loglevel; } return config; diff --git a/validator/src/main/java/com/google/daq/mqtt/registrar/MessageDowngrader.java b/validator/src/main/java/com/google/daq/mqtt/registrar/MessageDowngrader.java index 2c4937a44..5a0182391 100644 --- a/validator/src/main/java/com/google/daq/mqtt/registrar/MessageDowngrader.java +++ b/validator/src/main/java/com/google/daq/mqtt/registrar/MessageDowngrader.java @@ -51,6 +51,13 @@ public void downgrade(JsonNode versionNode) { downgradeLocalnet(); + if (major == 1 && (minor < 4 || (minor == 4 && patch < 1))) { + ObjectNode system = (ObjectNode) message.get("system"); + if (system != null) { + system.remove("operation"); + } + } + message.set(VERSION_PROPERTY_KEY, versionNode); } diff --git a/validator/src/main/java/com/google/daq/mqtt/sequencer/SequenceBase.java b/validator/src/main/java/com/google/daq/mqtt/sequencer/SequenceBase.java index 16c64c9e6..c79acb193 100644 --- a/validator/src/main/java/com/google/daq/mqtt/sequencer/SequenceBase.java +++ b/validator/src/main/java/com/google/daq/mqtt/sequencer/SequenceBase.java @@ -74,6 +74,7 @@ import udmi.schema.ExecutionConfiguration; import udmi.schema.Level; import udmi.schema.Metadata; +import udmi.schema.Operation; import udmi.schema.PointsetEvent; import udmi.schema.ReflectorConfig; import udmi.schema.ReflectorState; @@ -101,7 +102,6 @@ public class SequenceBase { public static final int NORM_TIMEOUT_MS = 180 * 1000; public static final String CONFIG_NONCE_KEY = "debug_config_nonce"; private static final String EMPTY_MESSAGE = "{}"; - private static final String CLOUD_IOT_CONFIG_FILE = "cloud_iot_config.json"; private static final String RESULT_LOG_FILE = "RESULT.log"; private static final String DEVICE_METADATA_FORMAT = "%s/devices/%s/metadata.json"; private static final String DEVICE_CONFIG_FORMAT = "%s/devices/%s/out/generated_config.json"; @@ -128,11 +128,18 @@ public class SequenceBase { private static final String SEQUENCE_MD = "sequence.md"; private static final int LOG_TIMEOUT_SEC = 10; private static final long ONE_SECOND_MS = 1000; + private static final int MIN_CLOUD_FUNC_VER = 1; + private static final int MAX_CLOUD_FUNC_VER = 1; + private static final Date REFLECTOR_STATE_TIMESTAMP = new Date(); + private static final int EXIT_CODE_PRESERVE = -9; + private static final String SYSTEM_TESTING_MARKER = " `system.testing"; + private static final Map sentConfig = new HashMap<>(); protected static Metadata deviceMetadata; protected static String projectId; protected static String cloudRegion; protected static String registryId; protected static String altRegistry; + protected static Config deviceConfig; static ExecutionConfiguration validatorConfig; private static String udmiVersion; private static String siteModel; @@ -144,9 +151,7 @@ public class SequenceBase { private static MessagePublisher altClient; private static SequenceBase activeInstance; private static MessageBundle stashedBundle; - private static Date stateTimestamp; - - private final Map sentConfig = new HashMap<>(); + private static boolean resetRequired = true; private final Map receivedState = new HashMap<>(); private final Map>> receivedEvents = new HashMap<>(); private final Map receivedUpdates = new HashMap<>(); @@ -157,7 +162,6 @@ public class SequenceBase { public Timeout globalTimeout = new Timeout(NORM_TIMEOUT_MS, TimeUnit.MILLISECONDS); @Rule public SequenceTestWatcher testWatcher = new SequenceTestWatcher(); - protected Config deviceConfig; protected State deviceState; protected boolean configAcked; private String extraField; @@ -275,14 +279,13 @@ private static MessagePublisher getReflectorClient() { private static void initializeReflectorState(IotReflectorClient client) { ReflectorState reflectorState = new ReflectorState(); - stateTimestamp = new Date(); - reflectorState.timestamp = stateTimestamp; + reflectorState.timestamp = REFLECTOR_STATE_TIMESTAMP; reflectorState.version = udmiVersion; reflectorState.setup = new SetupReflectorState(); reflectorState.setup.user = System.getenv("USER"); try { System.err.printf("Setting state version %s timestamp %s%n", - udmiVersion, getTimestamp(stateTimestamp)); + udmiVersion, getTimestamp(REFLECTOR_STATE_TIMESTAMP)); client.setReflectorState(stringify(reflectorState)); } catch (Exception e) { throw new RuntimeException("Could not set reflector state", e); @@ -353,29 +356,39 @@ private void resetDeviceConfig() { private void resetDeviceConfig(boolean clean) { deviceConfig = clean ? new Config() : readGeneratedConfig(); - sentConfig.clear(); + setExtraField(null); sanitizeConfig(deviceConfig); deviceConfig.system = ofNullable(deviceConfig.system).orElse(new SystemConfig()); deviceConfig.system.min_loglevel = Level.INFO.value(); - deviceConfig.system.testing = new TestingSystemConfig(); - deviceConfig.system.testing.sequence_name = testName; } - private Config sanitizeConfig(Config deviceConfig) { - if (!(deviceConfig.timestamp instanceof SemanticDate)) { - deviceConfig.timestamp = SemanticDate.describe("generated timestamp", deviceConfig.timestamp); + private Config sanitizeConfig(Config config) { + if (!(config.timestamp instanceof SemanticDate)) { + config.timestamp = SemanticDate.describe("generated timestamp", config.timestamp); + } + if (!SemanticValue.isSemanticString(config.version)) { + config.version = SemanticValue.describe("cloud udmi version", config.version); + } + if (config.system == null) { + config.system = new SystemConfig(); + } + + if (config.system.operation == null) { + config.system.operation = new Operation(); } - if (!SemanticValue.isSemanticString(deviceConfig.version)) { - deviceConfig.version = SemanticValue.describe("cloud udmi version", deviceConfig.version); + if (config.system.operation.last_start == null) { + config.system.operation.last_start = catchToNull( + () -> deviceState.system.operation.last_start); } - if (deviceConfig.system == null) { - deviceConfig.system = new SystemConfig(); + if (!(config.system.operation.last_start instanceof SemanticDate)) { + config.system.operation.last_start = SemanticDate.describe("device reported", + config.system.operation.last_start); } - if (!(deviceConfig.system.last_start instanceof SemanticDate)) { - deviceConfig.system.last_start = SemanticDate.describe("device reported", - deviceConfig.system.last_start); + if (config.system.testing == null) { + deviceConfig.system.testing = new TestingSystemConfig(); } - return deviceConfig; + deviceConfig.system.testing.sequence_name = testName; + return config; } private Config readGeneratedConfig() { @@ -402,7 +415,6 @@ public void setUp() { // TODO: Minimize time, or better yet find deterministic way to flush messages. safeSleep(CONFIG_UPDATE_DELAY_MS); - deviceState = new State(); configAcked = false; receivedState.clear(); receivedEvents.clear(); @@ -410,10 +422,10 @@ public void setUp() { recordMessages = true; recordSequence = false; - resetConfig(); - queryState(); + resetConfig(resetRequired); + updateConfig(); untilTrue("device state update", () -> deviceState != null); @@ -423,17 +435,24 @@ public void setUp() { } protected void resetConfig() { + resetConfig(true); + } + + protected void resetConfig(boolean fullReset) { recordSequence("Force reset config"); withRecordSequence(false, () -> { - debug("Starting reset_config"); - resetDeviceConfig(true); - setExtraField("reset_config"); - deviceConfig.system.testing.sequence_name = extraField; - updateConfig(); - setExtraField(null); + debug("Starting reset_config full reset " + fullReset); + if (fullReset) { + resetDeviceConfig(true); + sentConfig.clear(); + setExtraField("reset_config"); + deviceConfig.system.testing.sequence_name = extraField; + updateConfig(); + } resetDeviceConfig(); updateConfig(); debug("Done with reset_config"); + resetRequired = false; }); } @@ -443,7 +462,7 @@ private void waitForConfigSync(Instant configUpdateStart) { debug("lastConfigUpdate is " + lastConfigUpdate); withRecordSequence(false, () -> untilTrue("device config sync", this::configReady)); } finally { - configReady(true); + debug("wait for config sync result " + configReady(true)); } } @@ -453,7 +472,7 @@ public void valid_serial_no() { if (serialNo == null) { throw new SkipTest("No test serial number provided"); } - untilTrue("received serial no matches", () -> serialNo.equals(lastSerialNo)); + untilTrue("received serial number matches", () -> serialNo.equals(lastSerialNo)); } private void recordResult(String result, org.junit.runner.Description description, @@ -512,7 +531,7 @@ private void recordRawMessage(Map message, String messageBase) { String prefix = messageBase.startsWith(LOCAL_PREFIX) ? "local " : "received "; File messageFile = new File(testDir, messageBase + ".json"); - Object savedException = message.get(EXCEPTION_KEY); + Object savedException = message == null ? null : message.get(EXCEPTION_KEY); try { // An actual exception here will cause the JSON seralizer to barf, so temporarily sanitize. if (savedException instanceof Exception) { @@ -608,13 +627,6 @@ public void tearDown() { debug(String.format("stage done %s at %s", waitingCondition.peek(), timeSinceStart())); recordMessages = false; recordSequence = false; - if (debugLogLevel()) { - warning("Not resetting config to enable post-execution debugging"); - } else { - whileDoing("tear down", this::resetConfig); - } - deviceConfig = null; - deviceState = null; configAcked = false; } @@ -639,9 +651,9 @@ protected void updateConfig(String reason) { if (computedConfigChange != updated) { notice("cachedMessageData " + cachedMessageData); notice("cachedSentBlock " + cachedSentBlock); - throw new AbortMessageLoop("Unexpected config change!"); + throw new AbortMessageLoop("Unexpected config change! updated=" + updated); } - if (computedConfigChange) { + if (updated) { safeSleep(ONE_SECOND_MS); waitForConfigSync(configStart); } @@ -662,6 +674,8 @@ private boolean updateConfig(SubFolder subBlock, Object data) { debug(String.format("update %s_%s", CONFIG_SUBTYPE, subBlock)); recordRawMessage(tracedObject, LOCAL_PREFIX + subBlock.value()); sentConfig.put(subBlock, messageData); + } else { + trace("unchanged config_" + subBlock + ": " + messageData); } return updated; } catch (Exception e) { @@ -689,20 +703,19 @@ private boolean localConfigChange(String reason) { String header = String.format("Update config%s:", suffix); debug(header + " " + getTimestamp(deviceConfig.timestamp)); recordRawMessage(deviceConfig, LOCAL_CONFIG_UPDATE); - List configUpdates = configDiffEngine.computeChanges(deviceConfig); - if (configUpdates.isEmpty() && !extraFieldChanged) { - return false; - } - if (!configUpdates.isEmpty()) { + List allDiffs = configDiffEngine.computeChanges(deviceConfig); + List filteredDiffs = filterTesting(allDiffs); + if (!filteredDiffs.isEmpty()) { recordSequence(header); - configUpdates.forEach(this::recordBullet); + filteredDiffs.forEach(this::recordBullet); sequenceMd.flush(); } + boolean somethingChanged = extraFieldChanged || !allDiffs.isEmpty(); if (extraFieldChanged) { debug("Device config extra_field changed: " + extraField); extraFieldChanged = false; } - return true; + return somethingChanged; } catch (Exception e) { throw new RuntimeException("While recording device config", e); } @@ -725,12 +738,12 @@ protected boolean validSerialNo() { String deviceSerial = deviceState == null ? null : deviceState.system == null ? null : deviceState.system.serial_no; if (!Objects.equals(deviceSerial, lastSerialNo)) { - notice(String.format("Received serial no %s", deviceSerial)); + notice(String.format("Received serial number %s", deviceSerial)); lastSerialNo = deviceSerial; } boolean serialValid = deviceSerial != null && Objects.equals(serialNo, deviceSerial); if (!serialValid && enforceSerial && Objects.equals(serialNo, deviceSerial)) { - throw new IllegalStateException("Serial no mismatch " + serialNo + " != " + deviceSerial); + throw new IllegalStateException("Serial number mismatch " + serialNo + " != " + deviceSerial); } enforceSerial = serialValid; return serialValid; @@ -932,13 +945,22 @@ MessageBundle nextMessageBundle() { private void processConfig(Map message, Map attributes) { ReflectorConfig reflectorConfig = JsonUtil.convertTo(ReflectorConfig.class, message); Date lastState = reflectorConfig.setup.last_state; - if (CleanDateFormat.dateEquals(lastState, stateTimestamp)) { + if (CleanDateFormat.dateEquals(lastState, REFLECTOR_STATE_TIMESTAMP)) { + info("Received matching state/config timestamp " + getTimestamp(lastState)); + info("Cloud UDMI version " + reflectorConfig.version); if (!udmiVersion.equals(reflectorConfig.version)) { warning("Local/cloud UDMI version mismatch!"); } + + int funcVer = Optional.ofNullable(reflectorConfig.setup.functions).orElse(0); + info("Cloud functions version " + funcVer); + if (funcVer < MIN_CLOUD_FUNC_VER || funcVer > MAX_CLOUD_FUNC_VER) { + throw new RuntimeException("Unsupported cloud function version, please redeploy"); + } } else { info("Ignoring mismatch state/config timestamp " + getTimestamp(lastState)); + debug("Received reflectorConfig: " + stringify(reflectorConfig)); } } @@ -948,7 +970,8 @@ private void processCommand(Map message, Map att String subTypeRaw = attributes.get("subType"); if (CONFIG_SUBTYPE.equals(subTypeRaw)) { String attributeMark = String.format("%s/%s/%s", deviceId, subTypeRaw, subFolderRaw); - trace("received command " + attributeMark + " nonce " + message.get(CONFIG_NONCE_KEY)); + Object debugConfigNonce = message == null ? null : message.get(CONFIG_NONCE_KEY); + trace("received command " + attributeMark + " nonce " + debugConfigNonce); } if (!SequenceBase.getDeviceId().equals(deviceId)) { return; @@ -1027,8 +1050,8 @@ private void updateDeviceConfig(Config config) { // These parameters are set by the cloud functions, so explicitly set to maintain parity. deviceConfig.timestamp = config.timestamp; deviceConfig.version = config.version; - if (config.system != null) { - deviceConfig.system.last_start = config.system.last_start; + if (config.system != null && config.system.operation != null) { + deviceConfig.system.operation.last_start = config.system.operation.last_start; } sanitizeConfig(deviceConfig); } @@ -1066,30 +1089,45 @@ private boolean configReady() { } private boolean configReady(boolean debugOut) { - Object receivedConfig = receivedUpdates.get(CONFIG_SUBTYPE); - if (!(receivedConfig instanceof Config)) { - trace("no valid received config"); - return false; - } - if (configExceptionTimestamp != null) { - debug("Received config exception at " + configExceptionTimestamp); - return true; - } - // Config isn't properly sync'd until this is filled in, else there are startup race-conditions. - if (deviceConfig.system.last_start == null) { - return false; - } - List differences = configDiffEngine.diff( - sanitizeConfig((Config) receivedConfig), deviceConfig); - boolean configReady = differences.isEmpty(); - Consumer output = debugOut ? this::debug : this::trace; - output.accept("testing valid received config " + configReady); - if (!configReady) { - output.accept("\n+- " + Joiner.on("\n+- ").join(differences)); - trace("final deviceConfig: " + JsonUtil.stringify(deviceConfig)); - trace("final receivedConfig: " + JsonUtil.stringify(receivedUpdates.get(CONFIG_SUBTYPE))); + try { + Consumer output = debugOut ? this::debug : this::trace; + Object receivedConfig = receivedUpdates.get(CONFIG_SUBTYPE); + if (!(receivedConfig instanceof Config)) { + output.accept("no valid received config"); + return false; + } + if (configExceptionTimestamp != null) { + output.accept("Received config exception at " + configExceptionTimestamp); + return true; + } + // Config isn't properly sync'd until this is filled in, else there are race-conditions. + if (deviceConfig.system.operation.last_start == null) { + output.accept("Missing config ready last_start field"); + return false; + } + List differences = filterTesting( + configDiffEngine.diff(sanitizeConfig((Config) receivedConfig), deviceConfig)); + boolean configReady = differences.isEmpty(); + output.accept("testing valid received config " + configReady); + if (!configReady) { + output.accept("\n+- " + Joiner.on("\n+- ").join(differences)); + output.accept("final deviceConfig: " + JsonUtil.stringify(deviceConfig)); + output.accept( + "final receivedConfig: " + JsonUtil.stringify(receivedUpdates.get(CONFIG_SUBTYPE))); + } + return configReady; + } catch (Exception e) { + error("While processing waitForConfigSync: " + e.getMessage()); + throw e; } - return configReady; + } + + /** + * Filter out any testing-oriented messages, since they should not impact behavior. + */ + private List filterTesting(List allDiffs) { + return allDiffs.stream() + .filter(message -> !message.contains(SYSTEM_TESTING_MARKER)).collect(Collectors.toList()); } protected void trace(String message) { @@ -1166,7 +1204,7 @@ protected void withAlternateClient(Runnable evaluator) { whileDoing("using alternate client", evaluator); } finally { useAlternateClient = false; - deviceConfig.system.testing.endpoint_type = null; + catchToNull(() -> deviceConfig.system.testing.endpoint_type = null); } } @@ -1242,9 +1280,6 @@ protected void starting(org.junit.runner.Description description) { testName = description.getMethodName(); testDescription = getTestDescription(description); - if (deviceConfig != null) { - deviceConfig.system.testing.sequence_name = testName; - } testStartTimeMs = System.currentTimeMillis(); @@ -1309,9 +1344,15 @@ protected void failed(Throwable e, org.junit.runner.Description description) { type = RESULT_FAIL; level = Level.ERROR; } + debug("ending stack trace: " + GeneralUtils.stackTraceString(e)); recordCompletion(type, level, description, message); String actioned = type.equals(RESULT_SKIP) ? "skipped" : "failed"; withRecordSequence(true, () -> recordSequence("Test " + actioned + ": " + message)); + resetRequired = true; + if (debugLogLevel()) { + error("Reset required during debug, forcing exit to preserve failing config/state"); + System.exit(EXIT_CODE_PRESERVE); + } } private void recordCompletion(String result, Level level, diff --git a/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/BlobsetSequences.java b/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/BlobsetSequences.java index 9bacc5749..fd715b782 100644 --- a/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/BlobsetSequences.java +++ b/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/BlobsetSequences.java @@ -24,7 +24,7 @@ import udmi.schema.EndpointConfiguration.Protocol; import udmi.schema.Entry; import udmi.schema.Level; -import udmi.schema.SystemConfig.SystemMode; +import udmi.schema.Operation.SystemMode; /** @@ -202,27 +202,34 @@ public void endpoint_connection_success_alternate() { public void system_mode_restart() { // Prepare for the restart. final Date dateZero = new Date(0); - untilTrue("last_start is not zero", () -> deviceState.system.last_start.after(dateZero)); + untilTrue("last_start is not zero", + () -> deviceState.system.operation.last_start.after(dateZero)); - deviceConfig.system.mode = SystemMode.ACTIVE; + final Integer initialCount = deviceState.system.operation.restart_count; + checkThat("initial count is greater than 0", () -> initialCount > 0); - untilTrue("deviceState.system.mode == ACTIVE", - () -> deviceState.system.mode.equals(SystemMode.ACTIVE)); + deviceConfig.system.operation.mode = SystemMode.ACTIVE; + + untilTrue("system mode is ACTIVE", + () -> deviceState.system.operation.mode.equals(SystemMode.ACTIVE)); final Date last_config = deviceState.system.last_config; - final Date last_start = deviceConfig.system.last_start; + final Date last_start = deviceConfig.system.operation.last_start; // Send the restart mode. - deviceConfig.system.mode = SystemMode.RESTART; + deviceConfig.system.operation.mode = SystemMode.RESTART; // Wait for the device to go through the correct states as it restarts. - untilTrue("deviceState.system.mode == INITIAL", - () -> deviceState.system.mode.equals(SystemMode.INITIAL)); + untilTrue("system mode is INITIAL", + () -> deviceState.system.operation.mode.equals(SystemMode.INITIAL)); + + checkThat("restart count increased by one", + () -> deviceState.system.operation.restart_count == initialCount + 1); - deviceConfig.system.mode = SystemMode.ACTIVE; + deviceConfig.system.operation.mode = SystemMode.ACTIVE; - untilTrue("deviceState.system.mode == ACTIVE", - () -> deviceState.system.mode.equals(SystemMode.ACTIVE)); + untilTrue("system mode is ACTIVE", + () -> deviceState.system.operation.mode.equals(SystemMode.ACTIVE)); // Capture error from last_start unexpectedly changing due to restart condition. try { @@ -236,7 +243,7 @@ public void system_mode_restart() { () -> deviceState.system.last_config.after(last_config)); untilTrue("last_start is newer than previous last_start", - () -> deviceConfig.system.last_start.after(last_start)); + () -> deviceConfig.system.operation.last_start.after(last_start)); } } diff --git a/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/ConfigSequences.java b/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/ConfigSequences.java index c922f39bf..5db65bbb1 100644 --- a/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/ConfigSequences.java +++ b/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/ConfigSequences.java @@ -97,7 +97,7 @@ public void broken_config() { // The last_config should not be updated to not reflect the broken config. assertTrue("following stable_config matches last_config", dateEquals(stableConfig, deviceState.system.last_config)); - assertTrue("system operational", deviceState.system.operational); + assertTrue("system operational", deviceState.system.operation.operational); untilLogged(SYSTEM_CONFIG_PARSE, Level.ERROR); checkNotLogged(SYSTEM_CONFIG_APPLY, SYSTEM_CONFIG_APPLY_LEVEL); @@ -107,7 +107,7 @@ public void broken_config() { untilTrue("last_config updated", () -> !dateEquals(stableConfig, deviceState.system.last_config) ); - assertTrue("system operational", deviceState.system.operational); + assertTrue("system operational", deviceState.system.operation.operational); untilLogged(SYSTEM_CONFIG_APPLY, SYSTEM_CONFIG_APPLY_LEVEL); checkNotLogged(SYSTEM_CONFIG_RECEIVE, SYSTEM_CONFIG_RECEIVE_LEVEL); checkNotLogged(SYSTEM_CONFIG_PARSE, SYSTEM_CONFIG_PARSE_LEVEL); @@ -118,13 +118,13 @@ public void broken_config() { public void extra_config() { deviceConfig.system.min_loglevel = Level.DEBUG.value(); untilTrue("last_config not null", () -> deviceState.system.last_config != null); - untilTrue("system operational", () -> deviceState.system.operational); + untilTrue("system operational", () -> deviceState.system.operation.operational); checkThatHasInterestingSystemStatus(false); final Date prevConfig = deviceState.system.last_config; setExtraField("Flabberguilstadt"); untilLogged(SYSTEM_CONFIG_RECEIVE, SYSTEM_CONFIG_RECEIVE_LEVEL); untilTrue("last_config updated", () -> !deviceState.system.last_config.equals(prevConfig)); - untilTrue("system operational", () -> deviceState.system.operational); + untilTrue("system operational", () -> deviceState.system.operation.operational); checkThatHasInterestingSystemStatus(false); untilLogged(SYSTEM_CONFIG_PARSE, SYSTEM_CONFIG_PARSE_LEVEL); untilLogged(SYSTEM_CONFIG_APPLY, SYSTEM_CONFIG_APPLY_LEVEL); @@ -134,7 +134,7 @@ public void extra_config() { untilTrue("last_config updated again", () -> !deviceState.system.last_config.equals(updatedConfig) ); - untilTrue("system operational", () -> deviceState.system.operational); + untilTrue("system operational", () -> deviceState.system.operation.operational); checkThatHasInterestingSystemStatus(false); untilLogged(SYSTEM_CONFIG_PARSE, SYSTEM_CONFIG_PARSE_LEVEL); untilLogged(SYSTEM_CONFIG_APPLY, SYSTEM_CONFIG_APPLY_LEVEL); diff --git a/validator/src/main/java/com/google/daq/mqtt/util/Common.java b/validator/src/main/java/com/google/daq/mqtt/util/Common.java index 525ff6352..d6e91dfcd 100644 --- a/validator/src/main/java/com/google/daq/mqtt/util/Common.java +++ b/validator/src/main/java/com/google/daq/mqtt/util/Common.java @@ -1,11 +1,10 @@ package com.google.daq.mqtt.util; +import static com.google.udmi.util.GeneralUtils.stackTraceString; + import com.google.common.reflect.ClassPath; import com.google.common.reflect.ClassPath.ClassInfo; import com.google.daq.mqtt.sequencer.sequences.ConfigSequences; -import java.io.ByteArrayOutputStream; -import java.io.OutputStream; -import java.io.PrintStream; import java.util.List; import java.util.MissingFormatArgumentException; import java.util.Optional; @@ -63,21 +62,6 @@ public static String getExceptionLine(Throwable e, Class container) { return null; } - /** - * Get a string of the java strack trace. - * - * @param e stack to trace - * @return stack trace string - */ - public static String stackTraceString(Throwable e) { - OutputStream outputStream = new ByteArrayOutputStream(); - try (PrintStream ps = new PrintStream(outputStream)) { - e.printStackTrace(ps); - } - return outputStream.toString(); - } - - public static String getExceptionMessage(Throwable exception) { String message = exception.getMessage(); return message != null ? message : exception.toString(); diff --git a/validator/src/main/java/com/google/daq/mqtt/util/MessageUpgrader.java b/validator/src/main/java/com/google/daq/mqtt/util/MessageUpgrader.java index 36531d2cd..2f5119309 100644 --- a/validator/src/main/java/com/google/daq/mqtt/util/MessageUpgrader.java +++ b/validator/src/main/java/com/google/daq/mqtt/util/MessageUpgrader.java @@ -38,8 +38,8 @@ public MessageUpgrader(String schemaName, JsonNode message) { String[] components = verStr.split("-", 2); String[] parts = components[0].split("\\.", 4); major = Integer.parseInt(parts[0]); - minor = parts.length >= 2 ? Integer.parseInt(parts[1]) : 0; - patch = parts.length >= 3 ? Integer.parseInt(parts[2]) : 0; + minor = parts.length >= 2 ? Integer.parseInt(parts[1]) : -1; + patch = parts.length >= 3 ? Integer.parseInt(parts[2]) : -1; if (parts.length >= 4) { throw new IllegalArgumentException("Unexpected version " + verStr); @@ -48,30 +48,57 @@ public MessageUpgrader(String schemaName, JsonNode message) { /** * Update message to the latest standard. + * + * @param forceUpgrade true to force a complete upgrade pass irrespective of original version + * @return true if the message has been altered */ - public void upgrade() { + public boolean upgrade(boolean forceUpgrade) { if (major != 1) { throw new IllegalArgumentException("Starting major version " + major); } + + final JsonNode original = message.deepCopy(); + boolean upgraded = false; + + if (forceUpgrade || minor < 0) { + minor = 0; + patch = 0; + upgraded = true; + } + if (minor < 3) { - upgrade_1_3(); + minor = 3; + patch = 0; } + if (minor == 3 && patch < 14) { + JsonNode before = message.deepCopy(); upgrade_1_3_14(); + upgraded |= !before.equals(message); + patch = 14; + } + + if (minor < 4) { + minor = 4; + patch = 0; } - if (message.has(VERSION_PROPERTY_KEY)) { + + if (minor == 4 && patch < 1) { + JsonNode before = message.deepCopy(); + upgrade_1_4_1(); + upgraded |= !before.equals(message); + patch = 0; + } + + if (upgraded && message.has(VERSION_PROPERTY_KEY)) { ((ObjectNode) message).put(VERSION_PROPERTY_KEY, String.format(TARGET_FORMAT, major, minor, patch)); } - } - private void upgrade_1_3() { - minor = 3; - patch = 0; + return !original.equals(message); } private void upgrade_1_3_14() { - patch = 14; if (STATE_SCHEMA.equals(schemaName)) { upgrade_1_3_14_state(); } @@ -100,18 +127,34 @@ private void upgrade_1_3_14_metadata() { } } + private void upgrade_1_4_1() { + if (STATE_SCHEMA.equals(schemaName)) { + upgrade_1_4_1_state(); + } + } + + private void upgrade_1_4_1_state() { + ObjectNode system = (ObjectNode) message.get("system"); + if (system != null) { + assertFalse("operation key in older version", system.has("operation")); + JsonNode operational = system.remove("operational"); + if (operational != null) { + ObjectNode operation = new ObjectNode(NODE_FACTORY); + system.set("operation", operation); + operation.set("operational", operational); + } + } + } + + private void assertFalse(String message, boolean value) { + if (value) { + throw new RuntimeException(message); + } + } + private void upgradeStatuses(ObjectNode system) { JsonNode statuses = system.remove("statuses"); - if (statuses != null) { - if (system.has("status")) { - throw new IllegalStateException("Node already has status field"); - } - if (statuses.size() == 0) { - return; - } - if (statuses.size() > 1) { - throw new IllegalStateException("More than one statuses to upgrade"); - } + if (statuses != null && !system.has("status") && statuses.size() != 0) { system.set("status", statuses.get(0)); } } @@ -119,11 +162,8 @@ private void upgradeStatuses(ObjectNode system) { private void upgradeFirmware(ObjectNode system) { JsonNode firmware = system.remove("firmware"); if (firmware != null) { - if (system.has("software")) { - throw new IllegalStateException("Node already has software field"); - } JsonNode version = ((ObjectNode) firmware).remove(VERSION_PROPERTY_KEY); - if (version != null) { + if (version != null && !system.has("software")) { ObjectNode softwareNode = new ObjectNode(NODE_FACTORY); softwareNode.put("firmware", version.asText()); system.set("software", softwareNode); @@ -133,10 +173,7 @@ private void upgradeFirmware(ObjectNode system) { private void upgradeMakeModel(ObjectNode system) { JsonNode makeModel = system.remove("make_model"); - if (makeModel != null) { - if (system.has("hardware")) { - throw new IllegalStateException("Node already has hardware field"); - } + if (makeModel != null && !system.has("hardware")) { ObjectNode hardwareNode = new ObjectNode(NODE_FACTORY); hardwareNode.put("model", makeModel.asText()); hardwareNode.put("make", "unknown"); diff --git a/validator/src/main/java/com/google/daq/mqtt/util/SimpleWebServer.java b/validator/src/main/java/com/google/daq/mqtt/util/SimpleWebServer.java index ceb0642a0..eb3bb3f7b 100644 --- a/validator/src/main/java/com/google/daq/mqtt/util/SimpleWebServer.java +++ b/validator/src/main/java/com/google/daq/mqtt/util/SimpleWebServer.java @@ -1,11 +1,8 @@ package com.google.daq.mqtt.util; -import com.google.api.client.util.ArrayMap; import com.google.common.base.Joiner; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; +import com.google.udmi.util.GeneralUtils; import com.sun.net.httpserver.HttpServer; -import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.InetSocketAddress; @@ -77,7 +74,7 @@ private String tryAction(Consumer> handler, Map processingMessage.getLogLevel().compareTo(LogLevel.ERROR) >= 0) - .map(processingMessage -> new ValidationException(processingMessage.getMessage())) - .collect(toImmutableList()); + .map(ValidationException::convertMessage).collect(toImmutableList()); return new ValidationException( String.format("%d schema violations found", causingExceptions.size()), causingExceptions); } + private static ValidationException convertMessage(ProcessingMessage processingMessage) { + String pointer = processingMessage.asJson().get("instance").get("pointer").asText(); + String prefix = Strings.isNullOrEmpty(pointer) ? "" : (pointer + ": "); + return new ValidationException(prefix + processingMessage.getMessage()); + } + /** * Get the exception that started it all. * diff --git a/validator/src/main/java/com/google/daq/mqtt/validator/ReportingDevice.java b/validator/src/main/java/com/google/daq/mqtt/validator/ReportingDevice.java index e4a4e0cc9..45d5e4dc9 100644 --- a/validator/src/main/java/com/google/daq/mqtt/validator/ReportingDevice.java +++ b/validator/src/main/java/com/google/daq/mqtt/validator/ReportingDevice.java @@ -108,7 +108,8 @@ private static String validationMessage(ValidationException exception) { } private static String replaceCategoryMissing(String message) { - return message.startsWith(CATEGORY_MISSING_MESSAGE) ? CATEGORY_MISSING_REPLACEMENT : message; + int index = message.indexOf(CATEGORY_MISSING_MESSAGE); + return index < 0 ? message : message.substring(0, index) + CATEGORY_MISSING_REPLACEMENT; } /** diff --git a/validator/src/main/java/com/google/daq/mqtt/validator/Validator.java b/validator/src/main/java/com/google/daq/mqtt/validator/Validator.java index 598e2a5b2..33ed82f25 100644 --- a/validator/src/main/java/com/google/daq/mqtt/validator/Validator.java +++ b/validator/src/main/java/com/google/daq/mqtt/validator/Validator.java @@ -13,6 +13,7 @@ import static com.google.daq.mqtt.util.ConfigUtil.readExecutionConfiguration; import static com.google.udmi.util.JsonUtil.JSON_SUFFIX; import static com.google.udmi.util.JsonUtil.OBJECT_MAPPER; +import static com.google.udmi.util.JsonUtil.stringify; import static java.util.Objects.requireNonNull; import com.fasterxml.jackson.core.type.TypeReference; @@ -62,6 +63,7 @@ import java.util.Map; import java.util.MissingFormatArgumentException; import java.util.Optional; +import java.util.Scanner; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; @@ -71,6 +73,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import org.apache.commons.io.FileUtils; import udmi.schema.Category; import udmi.schema.DeviceValidationEvent; import udmi.schema.Envelope.SubFolder; @@ -145,6 +148,7 @@ public class Validator { private File traceDir; private boolean simulatedMessages; private Instant mockNow = null; + private boolean forceUpgrade; /** * Create validator with the given args. @@ -209,6 +213,9 @@ private List parseArgs(List argList) { case "-f": validateFilesOutput(removeNextArg(argList)); break; + case "-u": + forceUpgrade = true; + break; case "-r": validateMessageTrace(removeNextArg(argList)); break; @@ -765,7 +772,7 @@ private void validateFiles(String schemaSpec, String prefix, String targetSpec) System.out.println( "Validating " + targetFile.getName() + " against " + schemaFile.getName()); String schemaName = fileName.substring(0, fileName.length() - JSON_SUFFIX.length()); - validateFile(prefix, targetSpec, schemaName, schema); + validateFile(prefix, targetFile.getPath(), schemaName, schema); } catch (Exception e) { validateExceptions.put(targetFile.getName(), e); } @@ -833,13 +840,20 @@ private List makeFileList(String prefix, File partialTarget) { private void validateFile( String prefix, String targetFile, String schemaName, JsonSchema schema) { final File targetOut = getTargetPath(prefix, targetFile.replace(".json", ".out")); - try { - File fullPath = getFullPath(prefix, new File(targetFile)); - Map message = OBJECT_MAPPER.readValue(fullPath, Map.class); + File outputFile = getTargetPath(prefix, targetFile); + try (OutputStream outputStream = new FileOutputStream(outputFile)) { + File inputFile = getFullPath(prefix, new File(targetFile)); + copyFileHeader(inputFile, outputStream); + Map message = JsonUtil.toMap(inputFile); sanitizeMessage(schemaName, message); JsonNode jsonNode = OBJECT_MAPPER.valueToTree(message); - upgradeMessage(schemaName, jsonNode); - OBJECT_MAPPER.writeValue(getTargetPath(prefix, targetFile), jsonNode); + if (upgradeMessage(schemaName, jsonNode)) { + OBJECT_MAPPER.writeValue(outputStream, jsonNode); + } else { + // If the message was not upgraded, then copy over unmolested to preserve formatting. + outputStream.close(); + FileUtils.copyFile(inputFile, outputFile); + } validateJsonNode(schema, jsonNode); writeExceptionOutput(targetOut, null); } catch (Exception e) { @@ -848,6 +862,20 @@ private void validateFile( } } + private void copyFileHeader(File inputFile, OutputStream outputFile) { + try (Scanner scanner = new Scanner(inputFile)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (!line.trim().startsWith("//")) { + break; + } + outputFile.write((line + "\n").getBytes()); + } + } catch (Exception e) { + throw new RuntimeException("While copying header from " + inputFile.getAbsolutePath(), e); + } + } + private void writeExceptionOutput(File targetOut, Exception e) { try (OutputStream outputStream = new FileOutputStream(targetOut)) { if (e != null) { @@ -876,8 +904,8 @@ private void upgradeMessage(String schemaName, Map message) { message.putAll(objectMap); } - private void upgradeMessage(String schemaName, JsonNode jsonNode) { - new MessageUpgrader(schemaName, jsonNode).upgrade(); + private boolean upgradeMessage(String schemaName, JsonNode jsonNode) { + return new MessageUpgrader(schemaName, jsonNode).upgrade(forceUpgrade); } private void validateJsonNode(JsonSchema schema, JsonNode jsonNode) throws ProcessingException { diff --git a/validator/traces/simple.in/GAT-123/001_state_update.json b/validator/traces/simple.in/GAT-123/001_state_update.json index 8ac170f9e..caf2a741f 100644 --- a/validator/traces/simple.in/GAT-123/001_state_update.json +++ b/validator/traces/simple.in/GAT-123/001_state_update.json @@ -1,10 +1,12 @@ { "system": { - "last_start": "2022-11-09T15:14:29.181Z", "software": { "firmware": "4.12.0.156" }, - "operational": true, + "operation": { + "last_start": "2022-11-09T15:14:29.181Z", + "operational": true + }, "serial_no": "3637357", "last_config": "2022-11-06T21:30:39.000Z", "hardware": { @@ -23,7 +25,7 @@ } } }, - "version": "1.4.0", + "version": "1.4.1", "gateway": { "devices": { "AHU-18003": {}, diff --git a/validator/traces/simple.out/devices/GAT-123/state.json b/validator/traces/simple.out/devices/GAT-123/state.json index 1e7d1b5ad..4db9428e8 100644 --- a/validator/traces/simple.out/devices/GAT-123/state.json +++ b/validator/traces/simple.out/devices/GAT-123/state.json @@ -21,11 +21,13 @@ } }, "system" : { - "last_start" : "2022-11-09T15:14:29.181Z", "software" : { "firmware" : "4.12.0.156" }, - "operational" : true, + "operation" : { + "last_start" : "2022-11-09T15:14:29.181Z", + "operational" : true + }, "serial_no" : "3637357", "last_config" : "2022-11-06T21:30:39.000Z", "hardware" : { @@ -34,5 +36,5 @@ } }, "timestamp" : "1999-10-20T01:02:03Z", - "version" : "1.4.0" + "version" : "1.4.1" } \ No newline at end of file diff --git a/validator/traces/simple.out/devices/SNS-4/event_system.out b/validator/traces/simple.out/devices/SNS-4/event_system.out index f529a6a0b..2ccca46d2 100644 --- a/validator/traces/simple.out/devices/SNS-4/event_system.out +++ b/validator/traces/simple.out/devices/SNS-4/event_system.out @@ -5,7 +5,7 @@ "sub_type" : "event", "status" : { "message" : "While converting to json node: 1 schema violations found", - "detail" : "event_system: While converting to json node: 1 schema violations found @Validator.validateMessage(redacted); 1 schema violations found; instance entry category not recognized", + "detail" : "event_system: While converting to json node: 1 schema violations found @Validator.validateMessage(redacted); 1 schema violations found; /logentries/0/category: instance entry category not recognized", "category" : "validation.device.schema", "timestamp" : "1999-10-20T01:02:03Z", "level" : 500 @@ -30,7 +30,7 @@ "level" : 500 }, { "message" : "While converting to json node: 1 schema violations found", - "detail" : "event_system: While converting to json node: 1 schema violations found @Validator.validateMessage(redacted); 1 schema violations found; instance entry category not recognized", + "detail" : "event_system: While converting to json node: 1 schema violations found @Validator.validateMessage(redacted); 1 schema violations found; /logentries/0/category: instance entry category not recognized", "category" : "validation.device.schema", "timestamp" : "1999-10-20T01:02:03Z", "level" : 500