diff --git a/Pipfile b/Pipfile index 41be9840..6f88ee09 100644 --- a/Pipfile +++ b/Pipfile @@ -16,7 +16,8 @@ yappi = "==0.98" pyOpenSSL = "==18.0.0" setuptools = "*" aiohttp = "==3.8.1" -python-dateutil = "*" +python-dateutil = "2.8.2" +msgpack = "1.0.4" [dev-packages] pyinstaller = "==4.10" diff --git a/Pipfile.lock b/Pipfile.lock index ae982696..09b4492b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "bcb03a4ea7bba1f1137eb04a75daf94aec94f5b908fdfed2a23e4cdb08eff6b1" + "sha256": "ce93766c10d647151780f011d6a131ac8eecf6d0185c4b346e05436f4816b8a4" }, "pipfile-spec": 6, "requires": { @@ -215,11 +215,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", - "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df" + "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", + "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" ], - "markers": "python_version >= '3.5'", - "version": "==2.0.12" + "markers": "python_version >= '3.6'", + "version": "==2.1.0" }, "cryptography": { "hashes": [ @@ -331,6 +331,64 @@ "index": "pypi", "version": "==2.5.1" }, + "msgpack": { + "hashes": [ + "sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467", + "sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae", + "sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92", + "sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef", + "sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624", + "sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227", + "sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88", + "sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9", + "sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8", + "sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd", + "sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6", + "sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55", + "sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e", + "sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2", + "sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44", + "sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6", + "sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9", + "sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab", + "sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae", + "sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa", + "sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9", + "sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e", + "sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250", + "sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce", + "sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075", + "sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236", + "sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae", + "sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e", + "sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f", + "sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08", + "sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6", + "sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d", + "sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43", + "sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1", + "sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6", + "sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0", + "sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c", + "sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff", + "sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db", + "sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243", + "sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661", + "sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba", + "sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e", + "sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb", + "sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52", + "sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6", + "sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1", + "sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f", + "sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da", + "sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f", + "sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c", + "sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8" + ], + "index": "pypi", + "version": "==1.0.4" + }, "multidict": { "hashes": [ "sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60", @@ -463,11 +521,11 @@ }, "setuptools": { "hashes": [ - "sha256:d1746e7fd520e83bbe210d02fff1aa1a425ad671c7a9da7d246ec2401a087198", - "sha256:e7d11f3db616cda0751372244c2ba798e8e56a28e096ec4529010b803485f3fe" + "sha256:990a4f7861b31532871ab72331e755b5f14efbe52d336ea7f6118144dd478741", + "sha256:c1848f654aea2e3526d17fc3ce6aeaa5e7e24e66e645b5be2171f3f6b4e5a178" ], "index": "pypi", - "version": "==62.3.3" + "version": "==62.6.0" }, "six": { "hashes": [ @@ -603,32 +661,32 @@ }, "black": { "hashes": [ - "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b", - "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176", - "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09", - "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a", - "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015", - "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79", - "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb", - "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20", - "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464", - "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968", - "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82", - "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21", - "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0", - "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265", - "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b", - "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a", - "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72", - "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce", - "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0", - "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a", - "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163", - "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad", - "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d" + "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90", + "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c", + "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78", + "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4", + "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee", + "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e", + "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e", + "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6", + "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9", + "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c", + "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256", + "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f", + "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2", + "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c", + "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b", + "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807", + "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf", + "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def", + "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad", + "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d", + "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849", + "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69", + "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666" ], "index": "pypi", - "version": "==22.3.0" + "version": "==22.6.0" }, "click": { "hashes": [ @@ -835,11 +893,11 @@ }, "setuptools": { "hashes": [ - "sha256:d1746e7fd520e83bbe210d02fff1aa1a425ad671c7a9da7d246ec2401a087198", - "sha256:e7d11f3db616cda0751372244c2ba798e8e56a28e096ec4529010b803485f3fe" + "sha256:990a4f7861b31532871ab72331e755b5f14efbe52d336ea7f6118144dd478741", + "sha256:c1848f654aea2e3526d17fc3ce6aeaa5e7e24e66e645b5be2171f3f6b4e5a178" ], "index": "pypi", - "version": "==62.3.3" + "version": "==62.6.0" }, "six": { "hashes": [ @@ -854,7 +912,7 @@ "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version < '3.11.0a7'", "version": "==2.0.1" }, "traceback2": { diff --git a/asadm.py b/asadm.py index a628af58..4f95c0bb 100755 --- a/asadm.py +++ b/asadm.py @@ -14,6 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from lib.utils.logger import logger # THIS MUST BE THE FIRST IMPORT +from lib.base_controller import ShellException import inspect import cmd import getpass @@ -25,6 +27,7 @@ import sys import asyncio import readline + from lib.utils.async_object import AsyncObject @@ -36,7 +39,6 @@ # Setup logger before anything -from lib.utils.logger import logger from lib.collectinfo_analyzer.collectinfo_root_controller import ( CollectinfoRootController, ) @@ -58,7 +60,7 @@ # codec is registered well before it is used in getaddrinfo. # see https://bugs.python.org/issue29288, https://github.com/aws/aws-cli/blob/1.16.277/awscli/clidriver.py#L55, # and https://github.com/pyinstaller/pyinstaller/issues/1113 for more info :) -u"".encode("idna") +"".encode("idna") # Do not remove this line. It mitigates a race condition that occurs when using # pyinstaller and socket.getaddrinfo. For some reason the idna codec is not registered @@ -263,31 +265,43 @@ def set_privaliged_prompt(self): def clean_line(self, line): # get rid of extra whitespace - lexer = shlex.shlex(line) + lexer = shlex.shlex(line, posix=True) # TODO: shlex is not working with 'with' ip addresses. Need to write a # new parser or correct shlex behavior. commands = [] command = [] build_token = "" - lexer.wordchars += ".*-:/_{}@" - for token in lexer: - build_token += token - if token == "-": - continue - if token == ";": - if command: + # Maybe someday we should not allow most of the characters below without + # quotes surrounding them. These characters below define what can be in + # an unquotes string. + lexer.wordchars += r"`~!@#$;%^&*()_-+={}[]|:<>,./\?" + lexer.escapedquotes += "'" + + try: + for token in lexer: + build_token += token + + if token == ";": + if command: + commands.append(command) + command = [] + elif token.endswith(";"): + command.append(build_token[:-1]) commands.append(command) command = [] + else: + command.append(build_token) + build_token = "" else: - command.append(build_token) - build_token = "" - else: - if build_token: - command.append(build_token) - if command: - commands.append(command) + if build_token: + command.append(build_token) + if command: + commands.append(command) + + except ValueError as e: + raise ShellException(e) return commands diff --git a/lib/base_controller.py b/lib/base_controller.py index f88d4d27..5b0cf7e3 100644 --- a/lib/base_controller.py +++ b/lib/base_controller.py @@ -317,7 +317,7 @@ def _run_results(self, results): rv.append(result) return rv - async def execute(self, line) -> Union[None, str, list[None]]: + async def execute(self, line: list[str]) -> Union[None, str, list[None]]: # Init all command controller objects self._init() diff --git a/lib/live_cluster/client/__init__.py b/lib/live_cluster/client/__init__.py index 37595fd9..1e8b2cc3 100644 --- a/lib/live_cluster/client/__init__.py +++ b/lib/live_cluster/client/__init__.py @@ -31,6 +31,8 @@ from .cluster import Cluster +from .ctx import CTXItem, CTXItems, CDTContext, ASValue, ASValues + __all__ = ( Cluster, ASInfoError, @@ -44,4 +46,9 @@ EnumConfigType, StringConfigType, IntConfigType, + CTXItem, + CTXItems, + CDTContext, + ASValue, + ASValues, ) diff --git a/lib/live_cluster/client/config-schemas/6_1_0.json b/lib/live_cluster/client/config-schemas/6_1_0.json new file mode 100644 index 00000000..6bc0dd1a --- /dev/null +++ b/lib/live_cluster/client/config-schemas/6_1_0.json @@ -0,0 +1,3527 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema", + "additionalProperties": false, + "type": "object", + "required": [ + "network", + "namespaces" + ], + "properties": { + "service": { + "type": "object", + "additionalProperties": false, + "oneOf": [ + { + "required": [ + "feature-key-file" + ] + }, + { + "required": [ + "feature-key-files" + ] + } + ], + "properties": { + "query-buf-size": { + "type": "integer", + "default": 2, + "minimum": 0, + "maximum": 2147483647, + "description": "", + "dynamic": true + }, + "user": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "group": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "paxos-single-replica-limit": { + "type": "integer", + "default": 1, + "minimum": 0, + "maximum": 256, + "description": "", + "dynamic": false + }, + "pidfile": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "proto-fd-max": { + "type": "integer", + "default": 15000, + "minimum": 0, + "maximum": 2147483647, + "description": "", + "dynamic": true + }, + "advertise-ipv6": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "auto-pin": { + "type": "string", + "description": "", + "dynamic": false, + "default": "none", + "enum": [ + "none", + "cpu", + "numa", + "adq" + ] + }, + "batch-index-threads": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 256, + "description": "", + "dynamic": true + }, + "batch-max-buffers-per-queue": { + "type": "integer", + "default": 255, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "batch-max-requests": { + "type": "integer", + "default": 5000, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "batch-max-unused-buffers": { + "type": "integer", + "default": 256, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "batch-without-digests": { + "type": "boolean", + "default": true, + "description": "", + "dynamic": true + }, + "cluster-name": { + "type": "string", + "default": "", + "description": "", + "dynamic": true + }, + "disable-udf-execution": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "enable-benchmarks-fabric": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-health-check": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-hist-info": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "feature-key-file": { + "type": "string", + "default": "/opt/aerospike/data/features.conf", + "description": "", + "dynamic": false + }, + "feature-key-files": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [ + "/opt/aerospike/data/features.conf" + ] + }, + "info-threads": { + "type": "integer", + "default": 16, + "minimum": 0, + "maximum": 2147483647, + "description": "", + "dynamic": true + }, + "keep-caps-ssd-health": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "log-local-time": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "log-millis": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "microsecond-histograms": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "migrate-fill-delay": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "migrate-max-num-incoming": { + "type": "integer", + "default": 4, + "minimum": 0, + "maximum": 256, + "description": "", + "dynamic": true + }, + "migrate-threads": { + "type": "integer", + "default": 1, + "minimum": 0, + "maximum": 100, + "description": "", + "dynamic": true + }, + "min-cluster-size": { + "type": "integer", + "default": 1, + "minimum": 0, + "maximum": 256, + "description": "", + "dynamic": true + }, + "node-id": { + "type": "string", + "default": "BB9138953270008", + "description": "", + "dynamic": false + }, + "node-id-interface": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "os-group-perms": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "proto-fd-idle-ms": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 2147483647, + "description": "", + "dynamic": true + }, + "run-as-daemon": { + "type": "boolean", + "default": true, + "description": "", + "dynamic": false + }, + "service-threads": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 4096, + "description": "", + "dynamic": true + }, + "sindex-builder-threads": { + "type": "integer", + "default": 4, + "minimum": 1, + "maximum": 32, + "description": "", + "dynamic": true + }, + "sindex-gc-period": { + "type": "integer", + "default": 10, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "stay-quiesced": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "ticker-interval": { + "type": "integer", + "default": 10, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "transaction-max-ms": { + "type": "integer", + "default": 1000, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "transaction-retry-ms": { + "type": "integer", + "default": 1002, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "vault-ca": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "vault-path": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "vault-token-file": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "vault-url": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "work-directory": { + "type": "string", + "default": "/opt/aerospike", + "description": "", + "dynamic": false + }, + "debug-allocations": { + "type": "string", + "description": "", + "dynamic": false, + "default": "none", + "enum": [ + "none", + "transient", + "persistent", + "all" + ] + }, + "indent-allocations": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + } + } + }, + "logging": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "default": " ", + "description": "", + "dynamic": false + }, + "misc": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "alloc": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "arenax": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "hardware": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "msg": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "rbuffer": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "socket": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "tls": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "vault": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "vmapx": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "xmem": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "aggr": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "appeal": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "as": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "batch": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "bin": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "config": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "clustering": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "drv_pmem": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "drv_ssd": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "exchange": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "exp": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "fabric": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "flat": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "geo": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "hb": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "health": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "hlc": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "index": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "info": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "info-port": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "job": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "migrate": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "mon": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "namespace": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "nsup": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "particle": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "partition": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "paxos": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "proto": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "proxy": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "proxy-divert": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "query": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "record": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "roster": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "rw": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "rw-client": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "scan": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "security": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "service": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "service-list": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "sindex": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "skew": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "smd": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "storage": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "truncate": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "tsvc": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "udf": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "xdr": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "xdr-client": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + }, + "any": { + "enum": [ + "CRITICAL", + "critical", + "WARNING", + "warning", + "INFO", + "info", + "DEBUG", + "debug", + "DETAIL", + "detail" + ], + "description": "", + "dynamic": true, + "default": "INFO" + } + } + } + }, + "network": { + "type": "object", + "additionalProperties": false, + "required": [ + "service", + "heartbeat", + "fabric" + ], + "properties": { + "service": { + "type": "object", + "additionalProperties": false, + "required": [ + "port" + ], + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + }, + "access-addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "access-port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + }, + "alternate-access-addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "alternate-access-port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + }, + "disable-localhost": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "tls-access-addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "tls-access-port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + }, + "tls-addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "tls-alternate-access-addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "tls-alternate-access-port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + }, + "tls-authenticate-client": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "tls-name": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "tls-port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + } + } + }, + "heartbeat": { + "type": "object", + "additionalProperties": false, + "required": [ + "mode", + "port" + ], + "properties": { + "mode": { + "type": "string", + "description": "", + "dynamic": false, + "default": "", + "enum": [ + "mesh", + "multicast" + ] + }, + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "multicast-groups": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + }, + "mesh-seed-address-ports": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "interval": { + "type": "integer", + "default": 150, + "minimum": 50, + "maximum": 600000, + "description": "", + "dynamic": true + }, + "timeout": { + "type": "integer", + "default": 10, + "minimum": 3, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "connect-timeout-ms": { + "type": "integer", + "default": 500, + "minimum": 50, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "mtu": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "multicast-ttl": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255, + "description": "", + "dynamic": false + }, + "protocol": { + "type": "string", + "description": "", + "dynamic": true, + "default": "v3", + "enum": [ + "none", + "v3" + ] + }, + "tls-addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "tls-mesh-seed-address-ports": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "tls-name": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "tls-port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + } + } + }, + "fabric": { + "type": "object", + "additionalProperties": false, + "required": [ + "port" + ], + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + }, + "channel-bulk-fds": { + "type": "integer", + "default": 2, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": false + }, + "channel-bulk-recv-threads": { + "type": "integer", + "default": 4, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": true + }, + "channel-ctrl-fds": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": false + }, + "channel-ctrl-recv-threads": { + "type": "integer", + "default": 4, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": true + }, + "channel-meta-fds": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": false + }, + "channel-meta-recv-threads": { + "type": "integer", + "default": 4, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": true + }, + "channel-rw-fds": { + "type": "integer", + "default": 8, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": false + }, + "channel-rw-recv-pools": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 16, + "description": "", + "dynamic": false + }, + "channel-rw-recv-threads": { + "type": "integer", + "default": 16, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": true + }, + "keepalive-enabled": { + "type": "boolean", + "default": true, + "description": "", + "dynamic": false + }, + "keepalive-intvl": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 2147483647, + "description": "", + "dynamic": false + }, + "keepalive-probes": { + "type": "integer", + "default": 10, + "minimum": 1, + "maximum": 2147483647, + "description": "", + "dynamic": false + }, + "keepalive-time": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 2147483647, + "description": "", + "dynamic": false + }, + "latency-max-ms": { + "type": "integer", + "default": 5, + "minimum": 0, + "maximum": 1000, + "description": "", + "dynamic": false + }, + "recv-rearm-threshold": { + "type": "integer", + "default": 1024, + "minimum": 0, + "maximum": 1048576, + "description": "", + "dynamic": true + }, + "send-threads": { + "type": "integer", + "default": 8, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": false + }, + "tls-addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "tls-name": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "tls-port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + } + } + }, + "info": { + "type": "object", + "additionalProperties": false, + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "port": { + "type": "integer", + "default": 0, + "minimum": 1024, + "maximum": 65535, + "description": "", + "dynamic": false + } + } + }, + "tls": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "default": " ", + "description": "", + "dynamic": false + }, + "ca-file": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "ca-path": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "cert-blacklist": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "cert-file": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "cipher-suite": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "key-file": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "key-file-password": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "protocols": { + "type": "string", + "default": "TLSv1.2", + "description": "", + "dynamic": false + } + } + } + } + } + }, + "namespaces": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "memory-size" + ], + "properties": { + "name": { + "type": "string", + "default": " ", + "description": "", + "dynamic": false + }, + "replication-factor": { + "type": "integer", + "default": 2, + "minimum": 1, + "maximum": 256, + "description": "", + "dynamic": false + }, + "memory-size": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 18446744073709551615, + "description": "", + "dynamic": true + }, + "default-ttl": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 315360000, + "description": "", + "dynamic": true + }, + "storage-engine": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "", + "dynamic": false, + "default": "memory", + "enum": [ + "memory" + ] + } + } + }, + { + "type": "object", + "additionalProperties": false, + "oneOf": [ + { + "required": [ + "type", + "devices" + ] + }, + { + "required": [ + "type", + "files" + ] + } + ], + "properties": { + "type": { + "type": "string", + "description": "", + "dynamic": false, + "default": "device", + "enum": [ + "device" + ] + }, + "devices": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "files": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "filesize": { + "type": "integer", + "default": 0, + "minimum": 1048576, + "maximum": 2199023255552, + "description": "", + "dynamic": false + }, + "scheduler-mode": { + "type": "string", + "default": "", + "enum": [ + "anticipatory", + "cfq", + "deadline", + "noop", + "null" + ], + "description": "", + "dynamic": false + }, + "write-block-size": { + "type": "integer", + "default": 1048576, + "minimum": 1024, + "maximum": 8388608, + "description": "", + "dynamic": false + }, + "data-in-memory": { + "type": "boolean", + "default": true, + "description": "", + "dynamic": false + }, + "cache-replica-writes": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "cold-start-empty": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "commit-to-device": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "commit-min-size": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 8388608, + "description": "", + "dynamic": false + }, + "compression": { + "type": "string", + "description": "", + "dynamic": true, + "default": "none", + "enum": [ + "none", + "lz4", + "snappy", + "zstd" + ] + }, + "compression-level": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 9, + "description": "", + "dynamic": true + }, + "defrag-lwm-pct": { + "type": "integer", + "default": 50, + "minimum": 1, + "maximum": 99, + "description": "", + "dynamic": true + }, + "defrag-queue-min": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "defrag-sleep": { + "type": "integer", + "default": 1000, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "defrag-startup-minimum": { + "type": "integer", + "default": 6, + "minimum": 0, + "maximum": 99, + "description": "", + "dynamic": false + }, + "direct-files": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "disable-odsync": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "enable-benchmarks-storage": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "encryption": { + "type": "string", + "description": "", + "dynamic": false, + "default": "aes-128", + "enum": [ + "aes-128", + "aes-256" + ] + }, + "encryption-key-file": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "flush-max-ms": { + "type": "integer", + "default": 1000, + "minimum": 0, + "maximum": 1000, + "description": "", + "dynamic": true + }, + "max-write-cache": { + "type": "integer", + "default": 67108864, + "minimum": 0, + "maximum": 18446744073709551615, + "description": "", + "dynamic": true + }, + "min-avail-pct": { + "type": "integer", + "default": 5, + "minimum": 0, + "maximum": 100, + "description": "", + "dynamic": true + }, + "post-write-queue": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 4096, + "description": "", + "dynamic": true + }, + "read-page-cache": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "serialize-tomb-raider": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "sindex-startup-device-scan": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "tomb-raider-sleep": { + "type": "integer", + "default": 1000, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "files" + ], + "properties": { + "type": { + "type": "string", + "description": "", + "dynamic": false, + "default": "pmem", + "enum": [ + "pmem" + ] + }, + "files": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "filesize": { + "type": "integer", + "default": 0, + "minimum": 1048576, + "maximum": 2199023255552, + "description": "", + "dynamic": false + }, + "commit-to-device": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "compression": { + "type": "string", + "description": "", + "dynamic": true, + "default": "none", + "enum": [ + "none", + "lz4", + "snappy", + "zstd" + ] + }, + "compression-level": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 9, + "description": "", + "dynamic": true + }, + "defrag-lwm-pct": { + "type": "integer", + "default": 50, + "minimum": 1, + "maximum": 99, + "description": "", + "dynamic": true + }, + "defrag-queue-min": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "defrag-sleep": { + "type": "integer", + "default": 1000, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "defrag-startup-minimum": { + "type": "integer", + "default": 10, + "minimum": 1, + "maximum": 99, + "description": "", + "dynamic": false + }, + "direct-files": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "disable-odsync": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "enable-benchmarks-storage": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "encryption": { + "type": "string", + "description": "", + "dynamic": false, + "default": "aes-128", + "enum": [ + "aes-128", + "aes-256" + ] + }, + "encryption-key-file": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "flush-max-ms": { + "type": "integer", + "default": 1000, + "minimum": 0, + "maximum": 1000, + "description": "", + "dynamic": true + }, + "max-write-cache": { + "type": "integer", + "default": 67108864, + "minimum": 0, + "maximum": 18446744073709551615, + "description": "", + "dynamic": true + }, + "min-avail-pct": { + "type": "integer", + "default": 5, + "minimum": 0, + "maximum": 100, + "description": "", + "dynamic": true + }, + "serialize-tomb-raider": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "tomb-raider-sleep": { + "type": "integer", + "default": 1000, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + } + } + } + ] + }, + "allow-ttl-without-nsup": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "conflict-resolution-policy": { + "type": "string", + "description": "", + "dynamic": true, + "default": "generation", + "enum": [ + "generation", + "last-update-time" + ] + }, + "conflict-resolve-writes": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "data-in-index": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "disable-cold-start-eviction": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "disable-write-dup-res": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "disallow-null-setname": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-benchmarks-batch-sub": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-benchmarks-ops-sub": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-benchmarks-read": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-benchmarks-udf": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-benchmarks-udf-sub": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-benchmarks-write": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-hist-proxy": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "evict-hist-buckets": { + "type": "integer", + "default": 10000, + "minimum": 100, + "maximum": 10000000, + "description": "", + "dynamic": true + }, + "evict-tenths-pct": { + "type": "integer", + "default": 5, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "high-water-disk-pct": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 100, + "description": "", + "dynamic": true + }, + "high-water-memory-pct": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 100, + "description": "", + "dynamic": true + }, + "ignore-migrate-fill-delay": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "index-stage-size": { + "type": "integer", + "default": 1073741824, + "minimum": 134217728, + "maximum": 17179869184, + "description": "", + "dynamic": false + }, + "index-type": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "description": "", + "dynamic": false, + "default": "shmem", + "enum": [ + "shmem" + ] + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "mounts", + "mounts-size-limit" + ], + "properties": { + "type": { + "type": "string", + "description": "", + "dynamic": false, + "default": "pmem", + "enum": [ + "pmem" + ] + }, + "mounts": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "mounts-high-water-pct": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 100, + "description": "", + "dynamic": true + }, + "mounts-size-limit": { + "type": "integer", + "default": 0, + "minimum": 1073741824, + "maximum": 18446744073709551615, + "description": "", + "dynamic": true + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "mounts", + "mounts-size-limit" + ], + "properties": { + "type": { + "type": "string", + "description": "", + "dynamic": false, + "default": "flash", + "enum": [ + "flash" + ] + }, + "mounts": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "mounts-high-water-pct": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 100, + "description": "", + "dynamic": true + }, + "mounts-size-limit": { + "type": "integer", + "default": 0, + "minimum": 4294967296, + "maximum": 18446744073709551615, + "description": "", + "dynamic": true + } + } + } + ] + }, + "max-record-size": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "migrate-order": { + "type": "integer", + "default": 5, + "minimum": 1, + "maximum": 10, + "description": "", + "dynamic": true + }, + "migrate-retransmit-ms": { + "type": "integer", + "default": 5000, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "migrate-sleep": { + "type": "integer", + "default": 1, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "nsup-hist-period": { + "type": "integer", + "default": 3600, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "nsup-period": { + "type": "integer", + "default": 120, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "nsup-threads": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": true + }, + "partition-tree-sprigs": { + "type": "integer", + "default": 256, + "minimum": 16, + "maximum": 4096, + "description": "", + "dynamic": false + }, + "prefer-uniform-balance": { + "type": "boolean", + "default": true, + "description": "", + "dynamic": true + }, + "rack-id": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 1000000, + "description": "", + "dynamic": true + }, + "read-consistency-level-override": { + "type": "string", + "description": "", + "dynamic": true, + "default": "off", + "enum": [ + "all", + "off", + "one" + ] + }, + "reject-non-xdr-writes": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "reject-xdr-writes": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "sets": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "default": " ", + "description": "", + "dynamic": false + }, + "disable-eviction": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "enable-index": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "stop-writes-count": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 18446744073709551615, + "description": "", + "dynamic": true + } + } + } + }, + "sindex": { + "type": "object", + "additionalProperties": false, + "properties": { + "index-stage-size": { + "type": "integer", + "default": 1073741824, + "minimum": 134217728, + "maximum": 4294967296, + "description": "", + "dynamic": false + } + } + }, + "geo2dsphere-within": { + "type": "object", + "additionalProperties": false, + "properties": { + "strict": { + "type": "boolean", + "default": true, + "description": "", + "dynamic": false + }, + "min-level": { + "type": "integer", + "default": 1, + "minimum": 0, + "maximum": 30, + "description": "", + "dynamic": true + }, + "max-level": { + "type": "integer", + "default": 20, + "minimum": 0, + "maximum": 30, + "description": "", + "dynamic": true + }, + "max-cells": { + "type": "integer", + "default": 12, + "minimum": 1, + "maximum": 256, + "description": "", + "dynamic": true + }, + "level-mod": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 3, + "description": "", + "dynamic": false + }, + "earth-radius-meters": { + "type": "integer", + "default": 6371000, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": false + } + } + }, + "single-bin": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "stop-writes-pct": { + "type": "integer", + "default": 90, + "minimum": 0, + "maximum": 100, + "description": "", + "dynamic": true + }, + "strong-consistency": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "strong-consistency-allow-expunge": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "tomb-raider-eligible-age": { + "type": "integer", + "default": 86400, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "tomb-raider-period": { + "type": "integer", + "default": 86400, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "transaction-pending-limit": { + "type": "integer", + "default": 20, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "truncate-threads": { + "type": "integer", + "default": 4, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": true + }, + "write-commit-level-override": { + "type": "string", + "description": "", + "dynamic": true, + "default": "off", + "enum": [ + "all", + "master", + "off" + ] + }, + "xdr-bin-tombstone-ttl": { + "type": "integer", + "default": 86400, + "minimum": 0, + "maximum": 315360000, + "description": "", + "dynamic": true + }, + "xdr-tomb-raider-period": { + "type": "integer", + "default": 120, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "xdr-tomb-raider-threads": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 128, + "description": "", + "dynamic": true + } + } + } + }, + "mod-lua": { + "type": "object", + "additionalProperties": false, + "properties": { + "cache-enabled": { + "type": "boolean", + "default": true, + "description": "", + "dynamic": false + }, + "user-path": { + "type": "string", + "default": "/opt/aerospike/usr/udf/lua", + "description": "", + "dynamic": false + } + } + }, + "security": { + "type": "object", + "additionalProperties": false, + "properties": { + "enable-quotas": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "session-ttl": { + "type": "integer", + "default": 86400, + "minimum": 120, + "maximum": 864000, + "description": "", + "dynamic": true + }, + "privilege-refresh-period": { + "type": "integer", + "default": 300, + "minimum": 10, + "maximum": 86400, + "description": "", + "dynamic": true + }, + "tps-weight": { + "type": "integer", + "default": 2, + "minimum": 2, + "maximum": 20, + "description": "", + "dynamic": true + }, + "ldap": { + "type": "object", + "additionalProperties": false, + "properties": { + "disable-tls": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "login-threads": { + "type": "integer", + "default": 8, + "minimum": 1, + "maximum": 64, + "description": "", + "dynamic": false + }, + "polling-period": { + "type": "integer", + "default": 300, + "minimum": 0, + "maximum": 86400, + "description": "", + "dynamic": true + }, + "query-base-dn": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "query-user-dn": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "query-user-password-file": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "role-query-base-dn": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "role-query-patterns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "role-query-search-ou": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": false + }, + "server": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "tls-ca-file": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "token-hash-method": { + "type": "string", + "default": "sha-256", + "description": "", + "dynamic": false + }, + "user-dn-pattern": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + }, + "user-query-pattern": { + "type": "string", + "default": "", + "description": "", + "dynamic": false + } + } + }, + "log": { + "type": "object", + "additionalProperties": false, + "properties": { + "report-authentication": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "report-data-op": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "report-data-op-role": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "report-data-op-user": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "report-sys-admin": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "report-user-admin": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "report-violation": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + } + } + }, + "syslog": { + "type": "object", + "additionalProperties": false, + "properties": { + "local": { + "type": "integer", + "default": -1, + "minimum": 0, + "maximum": 7, + "description": "", + "dynamic": false + }, + "report-authentication": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "report-data-op": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "report-data-op-role": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "report-data-op-user": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "report-sys-admin": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "report-user-admin": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "report-violation": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + } + } + } + } + }, + "xdr": { + "type": "object", + "additionalProperties": false, + "properties": { + "dcs": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "default": " ", + "description": "", + "dynamic": false + }, + "node-address-ports": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": false, + "default": [] + }, + "namespaces": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "default": " ", + "description": "", + "dynamic": false + }, + "bin-policy": { + "type": "string", + "description": "", + "dynamic": true, + "default": "all", + "enum": [ + "all", + "only-changed", + "changed-and-specified", + "changed-or-specified" + ] + }, + "compression-level": { + "type": "integer", + "default": 1, + "minimum": 1, + "maximum": 9, + "description": "", + "dynamic": true + }, + "delay-ms": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 5000, + "description": "", + "dynamic": true + }, + "enable-compression": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "forward": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "hot-key-ms": { + "type": "integer", + "default": 100, + "minimum": 0, + "maximum": 5000, + "description": "", + "dynamic": true + }, + "ignore-bins": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "ignore-expunges": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "ignore-sets": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "max-throughput": { + "type": "integer", + "default": 100000, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "remote-namespace": { + "type": "string", + "default": "", + "description": "", + "dynamic": true + }, + "sc-replication-wait-ms": { + "type": "integer", + "default": 100, + "minimum": 5, + "maximum": 1000, + "description": "", + "dynamic": true + }, + "ship-bins": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "ship-bin-luts": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "ship-nsup-deletes": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "ship-only-specified-sets": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "ship-sets": { + "type": "array", + "items": { + "type": "string" + }, + "description": "", + "dynamic": true, + "default": [] + }, + "transaction-queue-limit": { + "type": "integer", + "default": 16384, + "minimum": 1024, + "maximum": 1048576, + "description": "", + "dynamic": true + }, + "write-policy": { + "type": "string", + "description": "", + "dynamic": true, + "default": "auto", + "enum": [ + "auto", + "update", + "replace" + ] + } + } + } + }, + "auth-mode": { + "type": "string", + "description": "", + "dynamic": true, + "default": "internal", + "enum": [ + "internal", + "external", + "external-insecure" + ] + }, + "auth-password-file": { + "type": "string", + "default": "", + "description": "", + "dynamic": true + }, + "auth-user": { + "type": "string", + "default": "", + "description": "", + "dynamic": true + }, + "connector": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + }, + "max-recoveries-interleaved": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 4294967295, + "description": "", + "dynamic": true + }, + "max-used-service-threads": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 4096, + "description": "", + "dynamic": true + }, + "period-ms": { + "type": "integer", + "default": 100, + "minimum": 5, + "maximum": 1000, + "description": "", + "dynamic": true + }, + "tls-name": { + "type": "string", + "default": "", + "description": "", + "dynamic": true + }, + "use-alternate-access-address": { + "type": "boolean", + "default": false, + "description": "", + "dynamic": true + } + } + } + }, + "src-id": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255, + "description": "", + "dynamic": true + } + } + } + } +} \ No newline at end of file diff --git a/lib/live_cluster/client/ctx.py b/lib/live_cluster/client/ctx.py new file mode 100644 index 00000000..52212037 --- /dev/null +++ b/lib/live_cluster/client/ctx.py @@ -0,0 +1,122 @@ +from typing import Any, Generic, TypeVar + +T = TypeVar("T") + + +class ASValue(Generic[T]): + def __init__(self, value: T): + self.value = value + + def __eq__(self, __o: object) -> bool: + return type(self) is type(__o) and self.__dict__ == __o.__dict__ + + def __str__(self) -> str: + return "{}({})".format(type(self), self.value) + + +class ASValues: + class ASBool(ASValue[bool]): + def __init__(self, value: bool): + super().__init__(value) + + class ASInt(ASValue[int]): + def __init__(self, value: int): + super().__init__(value) + + class ASString(ASValue[str]): + def __init__(self, value: str): + super().__init__(value) + + class ASBytes(ASValue[bytes]): + def __init__(self, value: bytes): + super().__init__(value) + + class ASDouble(ASValue[float]): + def __init__(self, value: float): + super().__init__(value) + + """ + Not used. Here for reference in case they become needed. + """ + + # class ASList(ASValue[list[ASValue]]): + # def __init__(self, value: list[ASValue]): + # super().__init__(value) + + # class ASMap(ASValue[dict[ASValue, ASValue]]): + # def __init__(self, value: dict[ASValue, ASValue]): + # super().__init__(value) + + # class ASGeoJson(ASValue[str]): + # def __init__(self, value: str): + # super().__init__(value) + + # class ASWildCard(ASValue[None]): + # def __init__(self): # maybe could be dict? + # super().__init__(None) + + # class ASUndef(ASValue): + # def __init__(self): + # super().__init__(None) + + # class ASNil(ASValue): + # def __init__(self): + # super().__init__(None) + + # class ASRec(ASValue): + # def __init__(self, value): + # super().__init__(value) + + +class CTXItem(Generic[T]): + def __init__(self, val: T): + self.value = val + + def __eq__(self, __o: object) -> bool: + return type(__o) is type(self) and __o.__dict__ == self.__dict__ + + def __str__(self): + return "{}({})".format(type(self), self.value) + + +class CTXIntItem(CTXItem[int]): + def __init__(self, val: int): + if not isinstance(val, int): + raise TypeError("CTX value must of type int") + + super().__init__(val) + + +class CTXParticleItem(CTXItem[ASValue]): + def __init__(self, val: ASValue): + if not isinstance(val, ASValue): + raise TypeError("CTX value must of type ASValue") + + super().__init__(val) + + +class CTXItems: + class ListIndex(CTXIntItem): + pass + + class ListRank(CTXIntItem): + pass + + class ListValue(CTXParticleItem): + pass + + class MapIndex(CTXIntItem): + pass + + class MapRank(CTXIntItem): + pass + + class MapKey(CTXParticleItem): + pass + + class MapValue(CTXParticleItem): + pass + + +class CDTContext(list[CTXItem]): + pass diff --git a/lib/live_cluster/client/info.py b/lib/live_cluster/client/info.py index dd8ba1ff..1be49224 100644 --- a/lib/live_cluster/client/info.py +++ b/lib/live_cluster/client/info.py @@ -64,7 +64,10 @@ _STRUCT_PROTOCOL_HEADER = struct.Struct("! B B 3H") _STRUCT_UINT8 = struct.Struct("! B") +_STRUCT_UINT16 = struct.Struct("! H") _STRUCT_UINT32 = struct.Struct("! I") +_STRUCT_UINT64 = struct.Struct("! Q") +_STRUCT_INT64 = struct.Struct("! q") _STRUCT_FIELD_HEADER = struct.Struct("! I B") _STRUCT_ADMIN_HEADER = struct.Struct("! B B B B 12x") diff --git a/lib/live_cluster/client/msgpack.py b/lib/live_cluster/client/msgpack.py new file mode 100644 index 00000000..98664c58 --- /dev/null +++ b/lib/live_cluster/client/msgpack.py @@ -0,0 +1,107 @@ +import struct +from typing import Union +from msgpack.fallback import Packer +from msgpack import ExtType + +from lib.live_cluster.client.ctx import ASValue, ASValues, CDTContext, CTXItem, CTXItems + +AS_BYTES_STRING = 3 +AS_BYTES_BLOB = 4 +AS_BYTES_GEOJSON = 23 +ASVAL_CMP_EXT_TYPE = 0xFF +ASVAL_CMP_WILDCARD = 0x00 + + +class CTXItemWireType: + AS_CDT_CTX_LIST_INDEX = 0x10 + AS_CDT_CTX_LIST_RANK = 0x11 + AS_CDT_CTX_LIST_VALUE = 0x13 + AS_CDT_CTX_MAP_INDEX = 0x20 + AS_CDT_CTX_MAP_RANK = 0x21 + AS_CDT_CTX_MAP_KEY = 0x22 + AS_CDT_CTX_MAP_VALUE = 0x23 + + +class ASPacker(Packer): + def __init__(self, autoreset=False): + super().__init__(autoreset=autoreset) + + def pack(self, obj): + if isinstance(obj, ASValue): + self._pack_as_value(obj) + return + elif isinstance(obj, CDTContext): + self._pack_as_cdt_ctx(obj) + return + + super().pack(obj) + + def _pack_as_cdt_ctx(self, obj: CDTContext): + """ + For packing an ctx in order to create a secondary index. The protocol + for packing a CDT with a CTX has a slightly different format. + """ + n = len(obj) * 2 + self.pack_array_header(n) + + for item in obj: + self._pack_as_cdt_item(item) + + return + + def _pack_as_cdt_item(self, obj: CTXItem): + if isinstance(obj, CTXItems.ListIndex): + self.pack(CTXItemWireType.AS_CDT_CTX_LIST_INDEX) + elif isinstance(obj, CTXItems.ListRank): + self.pack(CTXItemWireType.AS_CDT_CTX_LIST_RANK) + elif isinstance(obj, CTXItems.ListValue): + self.pack(CTXItemWireType.AS_CDT_CTX_LIST_VALUE) + elif isinstance(obj, CTXItems.MapIndex): + self.pack(CTXItemWireType.AS_CDT_CTX_MAP_INDEX) + elif isinstance(obj, CTXItems.MapRank): + self.pack(CTXItemWireType.AS_CDT_CTX_MAP_RANK) + elif isinstance(obj, CTXItems.MapKey): + self.pack(CTXItemWireType.AS_CDT_CTX_MAP_KEY) + elif isinstance(obj, CTXItems.MapValue): + self.pack(CTXItemWireType.AS_CDT_CTX_MAP_VALUE) + self.pack(obj.value) + return + + def _pack_as_value(self, obj: ASValue): + if isinstance(obj, ASValues.ASString): + val = obj.value + val = chr(AS_BYTES_STRING) + val + self.pack(val) + return + + if isinstance(obj, ASValues.ASBytes): + val = obj.value + val = chr(AS_BYTES_BLOB) + val.decode("utf-8") + self.pack(val) + return + + """ + Not used. Here for reference in case one day they are. + """ + + # if isinstance(obj, ASValues.ASGeoJson): + # val = obj.value + # val = chr(AS_BYTES_GEOJSON) + val + # self.pack(val) + # return + + # if isinstance(obj, ASValues.ASList): + # val = obj.value + # n = len(val) + # self._pack_array_header(n) + # for i in range(n): + # self._pack_as_value(val[i]) + # return + + # if isinstance(obj, ASValues.ASWildCard): + # wildCardExt = ExtType(ASVAL_CMP_EXT_TYPE, ASVAL_CMP_WILDCARD) + # super().pack(wildCardExt) + # return + + self.pack(obj.value) + return diff --git a/lib/live_cluster/client/node.py b/lib/live_cluster/client/node.py index 51effec7..61dc042a 100644 --- a/lib/live_cluster/client/node.py +++ b/lib/live_cluster/client/node.py @@ -20,6 +20,9 @@ import threading import time import base64 +from typing import Optional +from lib.live_cluster.client.ctx import CDTContext +from lib.live_cluster.client.msgpack import ASPacker from lib.utils import common, constants, util, version, conf_parser from lib.utils import common, constants, util, version, logger_debug, conf_parser @@ -2217,7 +2220,14 @@ async def info_sindex_statistics(self, namespace, indexname): @async_return_exceptions async def info_sindex_create( - self, index_name, namespace, bin_name, bin_type, index_type=None, set_=None + self, + index_name: str, + namespace: str, + bin_name: str, + bin_type: str, + index_type: Optional[str] = None, + set_: Optional[str] = None, + ctx: Optional[CDTContext] = None, ): """ Create a new secondary index. index_type and set are optional. @@ -2234,7 +2244,17 @@ async def info_sindex_create( if set_: command += "set={};".format(set_) + if ctx: + packer = ASPacker() + packer.pack(ctx) + ctx_bytes: bytes = packer.bytes() + ctx_b64 = base64.b64encode(ctx_bytes) + ctx_b64 = util.bytes_to_str(ctx_b64) + + command += "context={};".format(ctx_b64) + command += "indexdata={},{}".format(bin_name, bin_type) + resp = await self.info(command) if resp.lower() != ASINFO_RESPONSE_OK: diff --git a/lib/live_cluster/client/types.py b/lib/live_cluster/client/types.py index 21f2794e..ba376812 100644 --- a/lib/live_cluster/client/types.py +++ b/lib/live_cluster/client/types.py @@ -1,5 +1,6 @@ from enum import IntEnum, unique import logging +from typing import Literal, Union Addr_Port_TLSName = tuple[str, int, str] @@ -157,26 +158,26 @@ def __eq__(self, o: object) -> bool: class ASInfoError(Exception): generic_error = "Unknown error occurred" - def __init__(self, message, response): + def __init__(self, message: str, server_resp: str): self.message = message - self.raw_response = response + self.raw_response = server_resp # Success can either be "ok", "OK", or "" :( - if response.lower() in {ASINFO_RESPONSE_OK, ""}: + if server_resp.lower() in {ASINFO_RESPONSE_OK, ""}: raise ValueError('info() returned value "ok" which is not an error.') try: # sometimes there is a message with 'error' and sometimes not. i.e. set-config, udf-put - if response.startswith("error") or response.startswith("ERROR"): + if server_resp.startswith("error") or server_resp.startswith("ERROR"): try: - response = response.split("=")[1] + server_resp = server_resp.split("=")[1] except IndexError: - response = response.split(":")[2] + server_resp = server_resp.split(":")[2] - elif response.startswith("fail") or response.startswith("FAIL"): - response = response.split(":")[2] + elif server_resp.startswith("fail") or server_resp.startswith("FAIL"): + server_resp = server_resp.split(":")[2] - self.response = response.strip(" .") + self.response = server_resp.strip(" .") except IndexError: self.response = self.generic_error diff --git a/lib/live_cluster/live_cluster_command_controller.py b/lib/live_cluster/live_cluster_command_controller.py index eef4ecda..32366d93 100644 --- a/lib/live_cluster/live_cluster_command_controller.py +++ b/lib/live_cluster/live_cluster_command_controller.py @@ -3,7 +3,7 @@ class LiveClusterCommandController(CommandController): - cluster = None + cluster: Cluster = None def __init__(self, cluster: Cluster): LiveClusterCommandController.cluster = cluster diff --git a/lib/live_cluster/manage_controller.py b/lib/live_cluster/manage_controller.py index 8057e336..ac7e0bef 100644 --- a/lib/live_cluster/manage_controller.py +++ b/lib/live_cluster/manage_controller.py @@ -1,11 +1,15 @@ import asyncio +import base64 +import binascii import os import logging from datetime import datetime +import re from dateutil import parser as date_parser from typing import Optional from getpass import getpass from functools import reduce +from lib.live_cluster.client.ctx import ASValues, CTXItem, CTXItems from lib.view import terminal from lib.utils import constants, util, version @@ -19,6 +23,7 @@ EnumConfigType, StringConfigType, IntConfigType, + CDTContext, ) from .live_cluster_command_controller import LiveClusterCommandController from lib.get_controller import GetJobsController @@ -920,8 +925,8 @@ def _do_default(self, line): @CommandHelp( - "Usage: create ns [set ] bin [in ]", - " bin-type - The bin type of the provided . Should be one of the following values:", + "Usage: create ns [set ] bin [in ] [ctx [. . .]]", + " bin-type - The bin type of the provided . Should be one of the following values:", " numeric, string, or geo2dsphere", " index-name - Name of the secondary index to be created. Should be 20 characters", ' or less and not contain ":" or ";".', @@ -933,16 +938,171 @@ def _do_default(self, line): " mapkeys: Specifies to use the keys of a map as keys.", " mapvalues: Specifies to use the values of a map as keys.", " [default: Specifies to use the contents of a bin as keys.]", + " ctx - A list of context items describing how to index into a CDT.", + " Possible values include: list_index() list_rank(),", + " list_value(), map_index(), map_rank(),", + " map_key(), and map_value(). Where is", + " , int(), bool(), or bytes() a base64", + " encoded byte array (no quotes).", ) class ManageSIndexCreateController(ManageLeafCommandController): def __init__(self): + self.required_modifiers = set(["line", "ns", "bin"]) - self.modifiers = set(["set", "in"]) + self.modifiers = set(["set", "in", "ctx"]) def _do_default(self, line): self.execute_help(line) - async def _do_create(self, line, bin_type): + @staticmethod + def _split_ctx_list(ctx_str: str) -> list[str]: + ctx_str = ctx_str.strip() + split_pattern = r"\)(\s*)(?:list|map)" + ctx_list = [] + start = 0 + + for m in re.finditer(split_pattern, ctx_str): + end = m.start(1) + ctx_list.append(ctx_str[start:end]) + start = m.end(1) + + ctx_list.append(ctx_str[start : len(ctx_str)]) + + return ctx_list + + @staticmethod + def _list_to_cdt_ctx(ctx_list: list[str]) -> CDTContext: + cdt_ctx: CDTContext = CDTContext() + int_pattern = r"-?\d+" + str_pattern = r".*" + particle_pattern_with_names = ( + r"(?:" + + r"(?:float\(" + + r"(?P" + + str_pattern + + r")" + + r"\)" + + r")" + + r"|" + + r"(?:int\(" + + r"(?P" + + str_pattern + + r")" + + r"\)" + + r")" + + r"|" + + r"(?:bool\(" + + r"(?P" + + str_pattern + + r")" + + r"\)" + + r")" + + r"|" + + r"(?:bytes\(" + + r"(?P" + + str_pattern + + r")" + + r"\)" + + r")" + + r")" + ) + particle_pattern = re.compile(particle_pattern_with_names) + + # ctx_list = ManageSIndexCreateController._split_ctx_list(ctx_str) + + str_to_ctx = { + re.compile(r"^list_index\((" + int_pattern + r")\)"): CTXItems.ListIndex, + re.compile(r"^list_rank\((" + int_pattern + r")\)"): CTXItems.ListRank, + re.compile(r"^list_value\((" + str_pattern + r")\)"): CTXItems.ListValue, + re.compile(r"^map_index\((" + int_pattern + r")\)"): CTXItems.MapIndex, + re.compile(r"^map_rank\((" + int_pattern + r")\)"): CTXItems.MapRank, + re.compile(r"^map_key\((" + str_pattern + r")\)"): CTXItems.MapKey, + re.compile(r"^map_value\((" + str_pattern + r")\)"): CTXItems.MapValue, + } + + for ctx_item_str in ctx_list: + ctx_item_str = ctx_item_str.strip() + found = False + + for regex_key, ctx_cls in str_to_ctx.items(): + ctx_match = regex_key.search(ctx_item_str) + + if ctx_match is not None: + + if ( + ctx_cls == CTXItems.ListValue + or ctx_cls == CTXItems.MapKey + or ctx_cls == CTXItems.MapValue + ): + groups = ctx_match.groups() + + if len(groups) != 1: + raise ShellException( + "Malformed value: {}".format(ctx_item_str) + ) + + str_val = groups[0] + val_match = particle_pattern.search(str_val) + + if val_match is not None: + groups = val_match.groupdict() + double_, int_, bool_, base_64 = ( + groups["double"], + groups["int"], + # groups["str"], + groups["bool"], + groups["bytes_base64"], + ) + + if double_ is not None: + double_ = float(double_) + as_val = ASValues.ASDouble(double_) + elif int_ is not None: + int_ = int(int_) + as_val = ASValues.ASInt(int_) + elif bool_ is not None: + if bool_.lower() == "true": + bool_ = True + elif bool_.lower() == "false": + bool_ = False + else: + raise ShellException( + "Unable to parse bool {}".format(bool_) + ) + as_val = ASValues.ASBool(bool_) + elif base_64 is not None: + try: + base_64 = binascii.a2b_base64( + bytes(base_64, "utf-8") + ) + as_val = ASValues.ASBytes(base_64) + except ValueError as e: + raise ShellException( + "Unable to decode base64 encoded bytes : {}".format( + e + ) + ) + else: + raise Exception( + "Not able to decode to type other than string?" + ) + else: + as_val = ASValues.ASString(str_val) + else: + groups = ctx_match.groups() + as_val = int(groups[0]) + + found = True + cdt_ctx.append(ctx_cls(as_val)) + + break + + if not found: + raise ShellException("Unable to parse ctx item {}".format(ctx_item_str)) + + return cdt_ctx + + async def _do_create(self, line, bin_type: str): index_name = line.pop(0) namespace = util.get_arg_and_delete_from_mods( line=line, @@ -977,6 +1137,25 @@ async def _do_create(self, line, bin_type): mods=self.mods, ) + ctx_list = self.mods["ctx"] + cdt_ctx = None + + if ctx_list: + builds = await self.cluster.info_build(nodes=self.nodes) + + if not all( + [ + version.LooseVersion(build) + >= version.LooseVersion( + constants.SERVER_SINDEX_ON_CDT_FIRST_VERSION + ) + for build in builds.values() + ] + ): + raise ShellException("One or more servers does not support 'ctx'.") + + cdt_ctx = self._list_to_cdt_ctx(ctx_list) + index_type = index_type.lower() if index_type else None bin_type = bin_type.lower() @@ -992,17 +1171,19 @@ async def _do_create(self, line, bin_type): bin_type, index_type, set_, + cdt_ctx, nodes="principal", ) resp = list(resp.values())[0] - if isinstance(resp, ASInfoError): - self.logger.error(resp) - return - elif isinstance(resp, Exception): + if isinstance(resp, Exception): raise resp - self.view.print_result("Successfully created sindex {}.".format(index_name)) + self.view.print_result( + "Use 'show sindex' to confirm {} was created successfully.".format( + index_name + ) + ) # Hack for auto-complete async def do_numeric(self, line): @@ -1084,10 +1265,7 @@ async def _do_default(self, line): ) resp = list(resp.values())[0] - if isinstance(resp, ASInfoError): - self.logger.error(resp) - return - elif isinstance(resp, Exception): + if isinstance(resp, Exception): raise resp self.view.print_result("Successfully deleted sindex {}.".format(index_name)) diff --git a/lib/utils/constants.py b/lib/utils/constants.py index 4f7f6379..78ff16d8 100644 --- a/lib/utils/constants.py +++ b/lib/utils/constants.py @@ -119,6 +119,8 @@ class JobType: # server versions with critical changes +# TODO: Change to functions on the node +SERVER_SINDEX_ON_CDT_FIRST_VERSION = "6.1" SERVER_QUERIES_ABORT_ALL_FIRST_VERSION = "6.0" SERVER_39_BYTE_OVERHEAD_FIRST_VERSION = "6.0" SERVER_SINDEX_BUILDER_REMOVED_VERSION = "5.7" diff --git a/lib/utils/util.py b/lib/utils/util.py index 48980986..550dfde1 100644 --- a/lib/utils/util.py +++ b/lib/utils/util.py @@ -369,7 +369,7 @@ def get_value_from_dict( Returns value of first matching key from keys which is available in d else returns default_value """ - if not isinstance(keys, tuple): + if not isinstance(keys, tuple) and not isinstance(keys, list): keys = (keys,) for key in keys: @@ -530,7 +530,10 @@ def restructure_sys_data(content, cmd): def get_value_from_second_level_of_dict( - data, keys, default_value: DefaultType = None, return_type: Type[ReturnType] = str + data: dict[Any, str], + keys: list[str], + default_value: DefaultType = None, + return_type: Type[ReturnType] = str, ) -> dict[str, Union[ReturnType, DefaultType]]: """ Function takes dictionary and subkeys to find values inside all keys of dictionary. diff --git a/lib/view/sheet/decleration.py b/lib/view/sheet/decleration.py index 4f1b8b2b..66b153a6 100644 --- a/lib/view/sheet/decleration.py +++ b/lib/view/sheet/decleration.py @@ -587,12 +587,14 @@ def __init__(self, numerator_projector, denominator_projector): """ self.numerator_projector = numerator_projector self.denominator_projector = denominator_projector - self.sources = set( - ( - field_fn.source - for field_fn in [numerator_projector, denominator_projector] - ) - ) + self.sources = set([]) + + for field_fn in [numerator_projector, denominator_projector]: + if field_fn.source is None: + source = field_fn.sources + else: + source = set([field_fn.source]) + self.sources = self.sources.union(source) def do_project(self, sheet, sources): """ @@ -630,7 +632,7 @@ def do_project(self, sheet, sources): return result if not self.invert else 100 - result class Any(BaseProjector): - def __init__(self, field_type, *field_projectors): + def __init__(self, field_type: str, *field_projectors: BaseProjector): """ Arguments: field_type -- The 'FieldType' for this field. @@ -640,12 +642,10 @@ def __init__(self, field_type, *field_projectors): self.field_type = field_type self.sources = set() for field_fn in field_projectors: - if field_fn.source is None: source = field_fn.sources else: source = set([field_fn.source]) - self.sources = self.sources.union(source) self.field_projectors = field_projectors diff --git a/lib/view/templates.py b/lib/view/templates.py index 01190f74..ac6fa02f 100644 --- a/lib/view/templates.py +++ b/lib/view/templates.py @@ -15,9 +15,6 @@ from datetime import datetime import itertools from typing import Iterable, Union -from unicodedata import numeric -from lib.utils import file_size -from lib.utils.common import SummaryStorageUsageDict from lib.view.sheet.decleration import ComplexAggregator, EntryData from lib.live_cluster.client.node import ASINFO_RESPONSE_OK, ASInfoError from lib.view.sheet import ( @@ -740,6 +737,20 @@ def sindex_state_converter(edata): return state +def _ignore_zero(num: int): + if num == 0: + return None + + return num + + +def _ignore_null(s: str): + if s == "null": + return None + + return s + + info_sindex_sheet = Sheet( ( Field("Index Name", Projectors.String("sindex_stats", "indexname")), @@ -747,7 +758,7 @@ def sindex_state_converter(edata): Field("Set", Projectors.String("sindex_stats", "set")), node_field, hidden_node_id_field, - Field("Bins", Projectors.String("sindex_stats", "bins", "bin")), + Field("Bin", Projectors.String("sindex_stats", "bins", "bin")), Field("Num Bins", Projectors.Number("sindex_stats", "num_bins")), Field("Bin Type", Projectors.String("sindex_stats", "type")), Field( @@ -757,12 +768,44 @@ def sindex_state_converter(edata): ), # new Field("Sync State", Projectors.String("sindex_stats", "sync_state")), # old # removed 6.0 - Field("Keys", Projectors.Number("sindex_stats", "keys")), Field( - "Entries", - Projectors.Number("sindex_stats", "entries", "objects"), + "Keys", + Projectors.Any( + FieldType.number, + Projectors.Div( + Projectors.Number("sindex_stats", "entries", "objects"), + Projectors.Func( + FieldType.number, + _ignore_zero, + Projectors.Number("sindex_stats", "keys", "entries_per_bval"), + ), + ), + Projectors.Number("sindex_stats", "keys"), + ), converter=Converters.scientific_units, - aggregator=Aggregators.sum(), + ), + # added 6.1 + Subgroup( + "Entries", + ( + Field( + "Total", + Projectors.Number("sindex_stats", "entries", "objects"), + converter=Converters.scientific_units, + aggregator=Aggregators.sum(), + ), + Field( + "Avg Per Rec", + Projectors.Number("sindex_stats", "keys", "entries_per_rec"), + converter=Converters.scientific_units, + ), + Field( + "Avg Per Bin Val", + Projectors.Number("sindex_stats", "keys", "entries_per_bval"), + converter=Converters.scientific_units, + aggregator=Aggregators.sum(), + ), + ), ), Field( "Memory Used", @@ -778,6 +821,14 @@ def sindex_state_converter(edata): converter=Converters.byte, aggregator=Aggregators.sum(), ), + Field( + "Context", + Projectors.Func( + FieldType.string, + _ignore_null, + Projectors.String("sindex_stats", "context"), + ), + ), Subgroup( "Queries", ( @@ -1581,6 +1632,12 @@ def turn_empty_to_none(ls): Field("Bin Type", Projectors.String("data", "type")), Field("Index Type", Projectors.String("data", "indextype")), Field("State", Projectors.String("data", "state")), + Field( + "Context", + Projectors.Func( + "string", _ignore_null, Projectors.String("data", "context") + ), + ), ), from_source=("data"), group_by=("Namespace", "Set"), diff --git a/test/unit/live_cluster/client/test_msgpack.py b/test/unit/live_cluster/client/test_msgpack.py new file mode 100644 index 00000000..8d7bd661 --- /dev/null +++ b/test/unit/live_cluster/client/test_msgpack.py @@ -0,0 +1,85 @@ +import unittest +from lib.live_cluster.client.ctx import ASValues, CDTContext, CTXItems + +from lib.live_cluster.client.msgpack import ( + AS_BYTES_BLOB, + AS_BYTES_STRING, + ASPacker, + CTXItemWireType, +) + + +class MsgPackTest(unittest.TestCase): + def setUp(self): + self.packer = ASPacker() + + def pack(self, val) -> bytes: + self.packer.pack(val) + return self.packer.bytes() + + def test_pack_as_string_fixstr(self): + string = "abcd" + as_string = ASValues.ASString(string) + expected = bytes([0xA5, AS_BYTES_STRING]) + bytes(string, encoding="utf-8") + + actual = self.pack(as_string) + + self.assertEqual(expected, actual) + + def test_pack_as_string_8(self): + string = "abcdefghijklmnopqrstuvwxyz123456" + as_string = ASValues.ASString(string) + expected = bytearray([0xD9, 33, AS_BYTES_STRING]) + expected.extend(bytearray(string, encoding="ascii")) + + actual = self.pack(as_string) + + self.assertEqual(expected, actual) + + def test_pack_as_bytes_fixstr(self): + string = b"abcd" + as_string = ASValues.ASBytes(string) + expected = bytearray([0xA5, AS_BYTES_BLOB]) + expected.extend(bytearray(string)) + + actual = self.pack(as_string) + + self.assertEqual(expected, actual) + + def test_pack_as_bool_false(self): + actual = self.pack(ASValues.ASBool(False)) + self.assertEqual(bytes([0xC2]), actual) + + def test_pack_as_bool_true(self): + actual = self.pack(ASValues.ASBool(True)) + self.assertEqual(bytes([0xC3]), actual) + + def test_pack_cdt_ctx(self): + ctx = CDTContext( + [ + CTXItems.ListIndex(1), + CTXItems.ListRank(2), + CTXItems.MapIndex(3), + CTXItems.MapRank(4), + CTXItems.MapKey(ASValues.ASString("abcd")), + CTXItems.ListValue(ASValues.ASBool(True)), + CTXItems.MapValue(ASValues.ASInt(5)), + ] + ) + + expected = ( + bytes([0x9E]) + + bytes([CTXItemWireType.AS_CDT_CTX_LIST_INDEX, 1]) + + bytes([CTXItemWireType.AS_CDT_CTX_LIST_RANK, 2]) + + bytes([CTXItemWireType.AS_CDT_CTX_MAP_INDEX, 3]) + + bytes([CTXItemWireType.AS_CDT_CTX_MAP_RANK, 4]) + + bytes([CTXItemWireType.AS_CDT_CTX_MAP_KEY]) + + bytes([0xA5, AS_BYTES_STRING]) + + bytes("abcd", encoding="utf-8") + + bytes([CTXItemWireType.AS_CDT_CTX_LIST_VALUE, 0xC3]) + + bytes([CTXItemWireType.AS_CDT_CTX_MAP_VALUE, 5]) + ) + + actual = self.pack(ctx) + + self.assertEqual(expected, actual) diff --git a/test/unit/live_cluster/client/test_node.py b/test/unit/live_cluster/client/test_node.py index 66379af7..4b602b98 100644 --- a/test/unit/live_cluster/client/test_node.py +++ b/test/unit/live_cluster/client/test_node.py @@ -24,6 +24,7 @@ from mock.mock import AsyncMock, Mock import lib +from lib.live_cluster.client.ctx import CDTContext, CTXItem, CTXItems from lib.live_cluster.client.types import ASProtocolError, ASResponse from test.unit import util from lib.utils import constants @@ -3195,8 +3196,8 @@ async def test_info_sindex_statistics(self): async def test_info_sindex_create_success(self): self.info_mock.return_value = "OK" - expected_call = "sindex-create:indexname={};ns={};indexdata={},{}".format( - "iname", "ns", "data1", "data2" + expected_call = ( + "sindex-create:indexname=iname;ns=ns;indexdata=data1,data2".format() ) actual = await self.node.info_sindex_create("iname", "ns", "data1", "data2") @@ -3205,12 +3206,16 @@ async def test_info_sindex_create_success(self): self.assertEqual(actual, ASINFO_RESPONSE_OK) self.info_mock.return_value = "OK" - expected_call = "sindex-create:indexname={};indextype={};ns={};set={};indexdata={},{}".format( - "iname", "itype", "ns", "set", "data1", "data2" - ) + expected_call = "sindex-create:indexname=iname;indextype=itype;ns=ns;set=set;context=khAB;indexdata=data1,data2" actual = await self.node.info_sindex_create( - "iname", "ns", "data1", "data2", index_type="itype", set_="set" + "iname", + "ns", + "data1", + "data2", + index_type="itype", + set_="set", + ctx=CDTContext([CTXItems.ListIndex(1)]), ) self.info_mock.assert_called_with(expected_call, self.ip) diff --git a/test/unit/live_cluster/test_manage_controller.py b/test/unit/live_cluster/test_manage_controller.py index 920abd7c..e874389e 100644 --- a/test/unit/live_cluster/test_manage_controller.py +++ b/test/unit/live_cluster/test_manage_controller.py @@ -1,3 +1,4 @@ +import unittest from pytest import PytestUnraisableExceptionWarning from lib.base_controller import ShellException from mock import MagicMock, patch @@ -12,6 +13,7 @@ Cluster, ) from lib.live_cluster.client.config_handler import JsonDynamicConfigHandler +from lib.live_cluster.client.ctx import ASValues, CDTContext, CTXItems from lib.live_cluster.client.node import Node from lib.live_cluster.live_cluster_command_controller import ( LiveClusterCommandController, @@ -33,6 +35,9 @@ ManageRosterRemoveController, ManageRosterStageNodesController, ManageRosterStageObservedController, + ManageSIndexController, + ManageSIndexCreateController, + ManageSIndexDeleteController, ManageTruncateController, ) from lib.utils import constants @@ -1276,6 +1281,333 @@ def run_test(tc: TestCase): run_test(tc) +class ManageSIndexCreateStrToCTXTest(unittest.TestCase): + def test_str_to_cdt_ctx_with_list_index(self): + line = "list_index(3)" + expected = CDTContext([CTXItems.ListIndex(3)]) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_list_rank(self): + line = "list_rank(2)" + expected = CDTContext([CTXItems.ListRank(2)]) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_list_str_value(self): + line = "list_value(str)" + expected = CDTContext([CTXItems.ListValue(ASValues.ASString("str"))]) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_map_index(self): + line = "map_index(3)" + expected = CDTContext([CTXItems.MapIndex(3)]) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_map_rank(self): + line = "map_rank(2)" + expected = CDTContext([CTXItems.MapRank(2)]) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_map_str_key(self): + line = "map_key(str)" + expected = CDTContext([CTXItems.MapKey(ASValues.ASString("str"))]) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_map_str_value(self): + line = "map_value(str)" + expected = CDTContext([CTXItems.MapValue(ASValues.ASString("str"))]) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_multiple_items(self): + line = "list_index(3) list_rank(2) list_value(str) map_index(3) map_rank(2) map_key(str) map_value('str')" + expected = CDTContext( + [ + CTXItems.ListIndex(3), + CTXItems.ListRank(2), + CTXItems.ListValue(ASValues.ASString("str")), + CTXItems.MapIndex(3), + CTXItems.MapRank(2), + CTXItems.MapKey(ASValues.ASString("str")), + CTXItems.MapValue(ASValues.ASString("'str'")), + ] + ) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_double(self): + line = "map_key(float(3.14159)) map_key(float(0.0)) map_key(float(-3.14159))" + expected = CDTContext( + [ + CTXItems.MapKey(ASValues.ASDouble(3.14159)), + CTXItems.MapKey(ASValues.ASDouble(0.0)), + CTXItems.MapKey(ASValues.ASDouble(-3.14159)), + ] + ) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_int(self): + line = "map_key(int(3)) map_key(int(0)) map_key(int(-3))" + expected = CDTContext( + [ + CTXItems.MapKey(ASValues.ASInt(3)), + CTXItems.MapKey(ASValues.ASInt(0)), + CTXItems.MapKey(ASValues.ASInt(-3)), + ] + ) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertEqual(expected, actual) + + def test_str_to_cdt_ctx_with_str(self): + line = [ + 'map_key(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP QRSTUVWXYZ1234567890"-=!@#$%^&*()_+[]\\,.;/`~)' + ] + expected = CDTContext( + [ + CTXItems.MapKey( + ASValues.ASString( + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP QRSTUVWXYZ1234567890"-=!@#$%^&*()_+[]\\,.;/`~' + ) + ), + ] + ) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line) + + self.assertListEqual(expected, actual) + + def test_str_to_cdt_ctx_with_bool(self): + line = "map_key(bool(FaLsE)) map_key(bool(TRUE))" + expected = CDTContext( + [ + CTXItems.MapKey(ASValues.ASBool(False)), + CTXItems.MapKey(ASValues.ASBool(True)), + ] + ) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + + self.assertListEqual(expected, actual) + + def test_str_to_cdt_ctx_with_bytes(self): + line = "map_key(bytes(YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwLT1gIUAjJV4mKigpXytbXXt9Oyc6IltdOiwu)) map_key(bytes(YmxhaA==))" + expected = CDTContext( + [ + CTXItems.MapKey( + ASValues.ASBytes( + bytes( + "abcdefghijklmnopqrstuvwxyz1234567890-=`!@#%^&*()_+[]{};':\"[]:,.", + encoding="utf-8", + ) + ) + ), + CTXItems.MapKey(ASValues.ASBytes(bytes("blah", encoding="utf-8"))), + ] + ) + + actual = ManageSIndexCreateController._list_to_cdt_ctx(line.split()) + self.assertListEqual(expected, actual) + + def test_str_to_cdt_ctx_with_bool_fails(self): + line = "map_key(bool(FaLs))" + + self.assertRaisesRegex( + ShellException, + r"Unable to parse bool FaLs", + ManageSIndexCreateController._list_to_cdt_ctx, + line.split(), + ) + + def test_str_to_cdt_ctx_with_bytes_fails(self): + line = "map_key(bytes(abc))" + + self.assertRaisesRegex( + ShellException, + r"Unable to decode base64 encoded bytes : Incorrect padding", + ManageSIndexCreateController._list_to_cdt_ctx, + line.split(), + ) + + def test_incorrect_item_sytax_raises_shell_exception(self): + line = "map_index(1.'5)" + + self.assertRaisesRegex( + ShellException, + r"Unable to parse ctx item map_index\(1.'5\)", + ManageSIndexCreateController._list_to_cdt_ctx, + line.split(), + ) + + +class ManageSIndexCreateControllerTest(asynctest.TestCase): + def setUp(self) -> None: + self.cluster_mock = patch( + "lib.live_cluster.manage_controller.ManageLeafCommandController.cluster", + AsyncMock(), + ).start() + self.controller = ManageSIndexCreateController() + self.logger_mock = patch("lib.base_controller.BaseController.logger").start() + self.view_mock = patch("lib.base_controller.BaseController.view").start() + self.prompt_mock = patch( + "lib.live_cluster.manage_controller.ManageSIndexCreateController.prompt_challenge" + ).start() + + self.cluster_mock.info_build.return_value = {"principal": "6.1.0.0"} + + self.addCleanup(patch.stopall) + + async def test_prompt_challenge_fails(self): + line = "numeric a-index ns test bin a ctx list_value(1)".split() + self.controller.warn = True + self.prompt_mock.return_value = False + + await self.controller.execute(line) + + self.prompt_mock.assert_called_once_with( + "Adding a secondary index will cause longer restart times." + ) + + async def test_create_successful(self): + line = "numeric a-index ns test set testset bin a in mapkeys ctx list_value(int(1))".split() + self.cluster_mock.info_sindex_create.return_value = { + "1.1.1.1": ASINFO_RESPONSE_OK + } + + await self.controller.execute(line) + + self.cluster_mock.info_sindex_create.assert_called_once_with( + "a-index", + "test", + "a", + "numeric", + "mapkeys", + "testset", + CDTContext([CTXItems.ListValue(ASValues.ASInt(1))]), + nodes="principal", + ) + self.view_mock.print_result.assert_called_once_with( + "Use 'show sindex' to confirm a-index was created successfully." + ) + + async def test_create_fails_with_asinfo_error(self): + line = "numeric a-index ns test bin a ctx list_value(1)".split() + self.cluster_mock.info_sindex_create.return_value = { + "1.1.1.1": ASInfoError("foo", "ERROR::bar") + } + + await self.assertAsyncRaisesRegex( + ASInfoError, "bar", self.controller.execute(line) + ) + + async def test_ctx_invalid_format(self): + line = "numeric a-index ns test bin a ctx foo".split() + self.cluster_mock.info_build.return_value = {"principal": "6.1.0.0"} + + await self.assertAsyncRaisesRegex( + ShellException, + "Unable to parse ctx item foo", + self.controller.execute(line), + ) + + async def test_ctx_not_supported(self): + line = "numeric a-index ns test bin a ctx [foo]".split() + self.cluster_mock.info_build.return_value = {"principal": "6.0.0.0"} + + await self.assertAsyncRaisesRegex( + ShellException, + "One or more servers does not support 'ctx'.", + self.controller.execute(line), + ) + + +class ManageSIndexDeleteControllerTest(asynctest.TestCase): + def setUp(self) -> None: + self.cluster_mock = patch( + "lib.live_cluster.manage_controller.ManageLeafCommandController.cluster", + AsyncMock(), + ).start() + self.controller = ManageSIndexDeleteController() + self.logger_mock = patch("lib.base_controller.BaseController.logger").start() + self.view_mock = patch("lib.base_controller.BaseController.view").start() + self.prompt_mock = patch( + "lib.live_cluster.manage_controller.ManageSIndexDeleteController.prompt_challenge" + ).start() + + self.cluster_mock.info_build.return_value = {"principal": "6.1.0.0"} + + self.addCleanup(patch.stopall) + + async def test_prompt_challenge_fails(self): + line = "a-index ns test set testset".split() + self.controller.warn = True + self.prompt_mock.return_value = False + self.cluster_mock.info_sindex_statistics.return_value = { + "1.1.1.1": {"keys": 1111}, + "2.2.2.2": {"keys": 2222}, + } + + await self.controller.execute(line) + + self.prompt_mock.assert_called_once_with( + "The secondary index a-index has 3333 keys indexed." + ) + self.cluster_mock.info_sindex_delete.assert_not_called() + + async def test_delete_successful(self): + line = "a-index ns test set testset".split() + self.cluster_mock.info_sindex_delete.return_value = { + "1.1.1.1": ASINFO_RESPONSE_OK + } + + await self.controller.execute(line) + + self.cluster_mock.info_sindex_delete.assert_called_once_with( + "a-index", + "test", + "testset", + nodes="principal", + ) + self.view_mock.print_result.assert_called_once_with( + "Successfully deleted sindex a-index." + ) + + async def test_create_fails_with_asinfo_error(self): + line = "a-index ns test set testset".split() + self.cluster_mock.info_sindex_delete.return_value = { + "1.1.1.1": ASInfoError("foo", "ERROR::bar") + } + + await self.assertAsyncRaisesRegex( + ASInfoError, "bar", self.controller.execute(line) + ) + + @asynctest.fail_on(active_handles=True) class ManageTruncateControllerTest(asynctest.TestCase): def setUp(self) -> None: