Mini Shell
"""
Module for retrieving random information from Random.org
.. versionadded:: 2015.5.0
:configuration: This module can be used by either passing an api key and version
directly or by specifying both in a configuration profile in the salt
master/minion config.
For example:
.. code-block:: yaml
random_org:
api_key: 7be1402d-5719-5bd3-a306-3def9f135da5
api_version: 1
"""
import http.client
import logging
import urllib.request
import salt.utils.http
import salt.utils.json
log = logging.getLogger(__name__)
__virtualname__ = "random_org"
RANDOM_ORG_FUNCTIONS = {
"1": {
"getUsage": {"method": "getUsage"},
"generateIntegers": {"method": "generateIntegers"},
"generateStrings": {"method": "generateStrings"},
"generateUUIDs": {"method": "generateUUIDs"},
"generateDecimalFractions": {"method": "generateDecimalFractions"},
"generateGaussians": {"method": "generateGaussians"},
"generateBlobs": {"method": "generateBlobs"},
}
}
def __virtual__():
"""
Return virtual name of the module.
:return: The virtual name of the module.
"""
return __virtualname__
def _numeric(n):
"""
Tell whether an argument is numeric
"""
return isinstance(n, (int, float))
def _query(api_version=None, data=None):
"""
Slack object method function to construct and execute on the API URL.
:param api_key: The Random.org api key.
:param api_version: The version of Random.org api.
:param data: The data to be sent for POST method.
:return: The json response from the API call or False.
"""
if data is None:
data = {}
ret = {"res": True}
api_url = "https://api.random.org/"
base_url = urllib.parse.urljoin(api_url, "json-rpc/" + str(api_version) + "/invoke")
data = salt.utils.json.dumps(data)
result = salt.utils.http.query(
base_url,
method="POST",
params={},
data=data,
decode=True,
status=True,
header_dict={},
opts=__opts__,
)
if result.get("status", None) == http.client.OK:
_result = result["dict"]
if _result.get("result"):
return _result.get("result")
if _result.get("error"):
return _result.get("error")
return False
elif result.get("status", None) == http.client.NO_CONTENT:
return False
else:
ret["message"] = result.text if hasattr(result, "text") else ""
return ret
def getUsage(api_key=None, api_version=None):
"""
Show current usages statistics
:param api_key: The Random.org api key.
:param api_version: The Random.org api version.
:return: The current usage statistics.
CLI Example:
.. code-block:: bash
salt '*' random_org.getUsage
salt '*' random_org.getUsage api_key=peWcBiMOS9HrZG15peWcBiMOS9HrZG15 api_version=1
"""
ret = {"res": True}
if not api_key or not api_version:
try:
options = __salt__["config.option"]("random_org")
if not api_key:
api_key = options.get("api_key")
if not api_version:
api_version = options.get("api_version")
except (NameError, KeyError, AttributeError):
log.error("No Random.org api key found.")
ret["message"] = "No Random.org api key or api version found."
ret["res"] = False
return ret
if isinstance(api_version, int):
api_version = str(api_version)
_function = RANDOM_ORG_FUNCTIONS.get(api_version).get("getUsage").get("method")
data = {}
data["id"] = 1911220
data["jsonrpc"] = "2.0"
data["method"] = _function
data["params"] = {"apiKey": api_key}
result = _query(api_version=api_version, data=data)
if result:
ret["bitsLeft"] = result.get("bitsLeft")
ret["requestsLeft"] = result.get("requestsLeft")
ret["totalBits"] = result.get("totalBits")
ret["totalRequests"] = result.get("totalRequests")
else:
ret["res"] = False
ret["message"] = result["message"]
return ret
def generateIntegers(api_key=None, api_version=None, **kwargs):
"""
Generate random integers
:param api_key: The Random.org api key.
:param api_version: The Random.org api version.
:param number: The number of integers to generate
:param minimum: The lower boundary for the range from which the
random numbers will be picked. Must be within
the [-1e9,1e9] range.
:param maximum: The upper boundary for the range from which the
random numbers will be picked. Must be within
the [-1e9,1e9] range.
:param replacement: Specifies whether the random numbers should
be picked with replacement. The default (true)
will cause the numbers to be picked with replacement,
i.e., the resulting numbers may contain duplicate
values (like a series of dice rolls). If you want the
numbers picked to be unique (like raffle tickets drawn
from a container), set this value to false.
:param base: Specifies the base that will be used to display the numbers.
Values allowed are 2, 8, 10 and 16. This affects the JSON
types and formatting of the resulting data as discussed below.
:return: A list of integers.
CLI Example:
.. code-block:: bash
salt '*' random_org.generateIntegers number=5 minimum=1 maximum=6
salt '*' random_org.generateIntegers number=5 minimum=2 maximum=255 base=2
"""
ret = {"res": True}
if not api_key or not api_version:
try:
options = __salt__["config.option"]("random_org")
if not api_key:
api_key = options.get("api_key")
if not api_version:
api_version = options.get("api_version")
except (NameError, KeyError, AttributeError):
log.error("No Random.org api key found.")
ret["message"] = "No Random.org api key or api version found."
ret["res"] = False
return ret
for item in ["number", "minimum", "maximum"]:
if item not in kwargs:
ret["res"] = False
ret["message"] = f"Rquired argument, {item} is missing."
return ret
if not _numeric(kwargs["number"]) or not 1 <= kwargs["number"] <= 10000:
ret["res"] = False
ret["message"] = "Number of integers must be between 1 and 10000"
return ret
if (
not _numeric(kwargs["minimum"])
or not -1000000000 <= kwargs["minimum"] <= 1000000000
):
ret["res"] = False
ret["message"] = (
"Minimum argument must be between -1,000,000,000 and 1,000,000,000"
)
return ret
if (
not _numeric(kwargs["maximum"])
or not -1000000000 <= kwargs["maximum"] <= 1000000000
):
ret["res"] = False
ret["message"] = (
"Maximum argument must be between -1,000,000,000 and 1,000,000,000"
)
return ret
if "base" in kwargs:
base = kwargs["base"]
if base not in [2, 8, 10, 16]:
ret["res"] = False
ret["message"] = "Base must be either 2, 8, 10 or 16."
return ret
else:
base = 10
if "replacement" not in kwargs:
replacement = True
else:
replacement = kwargs["replacement"]
if isinstance(api_version, int):
api_version = str(api_version)
_function = (
RANDOM_ORG_FUNCTIONS.get(api_version).get("generateIntegers").get("method")
)
data = {}
data["id"] = 1911220
data["jsonrpc"] = "2.0"
data["method"] = _function
data["params"] = {
"apiKey": api_key,
"n": kwargs["number"],
"min": kwargs["minimum"],
"max": kwargs["maximum"],
"replacement": replacement,
"base": base,
}
result = _query(api_version=api_version, data=data)
log.debug("result %s", result)
if result:
if "random" in result:
random_data = result.get("random").get("data")
ret["data"] = random_data
else:
ret["res"] = False
ret["message"] = result["message"]
else:
ret["res"] = False
ret["message"] = result["message"]
return ret
def generateStrings(api_key=None, api_version=None, **kwargs):
"""
Generate random strings.
:param api_key: The Random.org api key.
:param api_version: The Random.org api version.
:param number: The number of strings to generate.
:param length: The length of each string. Must be
within the [1,20] range. All strings
will be of the same length
:param characters: A string that contains the set of
characters that are allowed to occur
in the random strings. The maximum number
of characters is 80.
:param replacement: Specifies whether the random strings should be picked
with replacement. The default (true) will cause the
strings to be picked with replacement, i.e., the
resulting list of strings may contain duplicates (like
a series of dice rolls). If you want the strings to be
unique (like raffle tickets drawn from a container), set
this value to false.
:return: A list of strings.
CLI Example:
.. code-block:: bash
salt '*' random_org.generateStrings number=5 length=8 characters='abcdefghijklmnopqrstuvwxyz'
salt '*' random_org.generateStrings number=10 length=16 characters'abcdefghijklmnopqrstuvwxyz'
"""
ret = {"res": True}
if not api_key or not api_version:
try:
options = __salt__["config.option"]("random_org")
if not api_key:
api_key = options.get("api_key")
if not api_version:
api_version = options.get("api_version")
except (NameError, KeyError, AttributeError):
log.error("No Random.org api key found.")
ret["message"] = "No Random.org api key or api version found."
ret["res"] = False
return ret
for item in ["number", "length", "characters"]:
if item not in kwargs:
ret["res"] = False
ret["message"] = f"Required argument, {item} is missing."
return ret
if not _numeric(kwargs["number"]) or not 1 <= kwargs["number"] <= 10000:
ret["res"] = False
ret["message"] = "Number of strings must be between 1 and 10000"
return ret
if not _numeric(kwargs["length"]) or not 1 <= kwargs["length"] <= 20:
ret["res"] = False
ret["message"] = "Length of strings must be between 1 and 20"
return ret
if len(kwargs["characters"]) >= 80:
ret["res"] = False
ret["message"] = "Length of characters must be less than 80."
return ret
if isinstance(api_version, int):
api_version = str(api_version)
if "replacement" not in kwargs:
replacement = True
else:
replacement = kwargs["replacement"]
_function = (
RANDOM_ORG_FUNCTIONS.get(api_version).get("generateStrings").get("method")
)
data = {}
data["id"] = 1911220
data["jsonrpc"] = "2.0"
data["method"] = _function
data["params"] = {
"apiKey": api_key,
"n": kwargs["number"],
"length": kwargs["length"],
"characters": kwargs["characters"],
"replacement": replacement,
}
result = _query(api_version=api_version, data=data)
if result:
if "random" in result:
random_data = result.get("random").get("data")
ret["data"] = random_data
else:
ret["res"] = False
ret["message"] = result["message"]
else:
ret["res"] = False
ret["message"] = result["message"]
return ret
def generateUUIDs(api_key=None, api_version=None, **kwargs):
"""
Generate a list of random UUIDs
:param api_key: The Random.org api key.
:param api_version: The Random.org api version.
:param number: How many random UUIDs you need.
Must be within the [1,1e3] range.
:return: A list of UUIDs
CLI Example:
.. code-block:: bash
salt '*' random_org.generateUUIDs number=5
"""
ret = {"res": True}
if not api_key or not api_version:
try:
options = __salt__["config.option"]("random_org")
if not api_key:
api_key = options.get("api_key")
if not api_version:
api_version = options.get("api_version")
except (NameError, KeyError, AttributeError):
log.error("No Random.org api key found.")
ret["message"] = "No Random.org api key or api version found."
ret["res"] = False
return ret
for item in ["number"]:
if item not in kwargs:
ret["res"] = False
ret["message"] = f"Required argument, {item} is missing."
return ret
if isinstance(api_version, int):
api_version = str(api_version)
if not _numeric(kwargs["number"]) or not 1 <= kwargs["number"] <= 1000:
ret["res"] = False
ret["message"] = "Number of UUIDs must be between 1 and 1000"
return ret
_function = RANDOM_ORG_FUNCTIONS.get(api_version).get("generateUUIDs").get("method")
data = {}
data["id"] = 1911220
data["jsonrpc"] = "2.0"
data["method"] = _function
data["params"] = {
"apiKey": api_key,
"n": kwargs["number"],
}
result = _query(api_version=api_version, data=data)
if result:
if "random" in result:
random_data = result.get("random").get("data")
ret["data"] = random_data
else:
ret["res"] = False
ret["message"] = result["message"]
else:
ret["res"] = False
ret["message"] = result["message"]
return ret
def generateDecimalFractions(api_key=None, api_version=None, **kwargs):
"""
Generates true random decimal fractions
:param api_key: The Random.org api key.
:param api_version: The Random.org api version.
:param number: How many random decimal fractions
you need. Must be within the [1,1e4] range.
:param decimalPlaces: The number of decimal places
to use. Must be within the [1,20] range.
:param replacement: Specifies whether the random numbers should
be picked with replacement. The default (true)
will cause the numbers to be picked with replacement,
i.e., the resulting numbers may contain duplicate
values (like a series of dice rolls). If you want the
numbers picked to be unique (like raffle tickets drawn
from a container), set this value to false.
:return: A list of decimal fraction
CLI Example:
.. code-block:: bash
salt '*' random_org.generateDecimalFractions number=10 decimalPlaces=4
salt '*' random_org.generateDecimalFractions number=10 decimalPlaces=4 replacement=True
"""
ret = {"res": True}
if not api_key or not api_version:
try:
options = __salt__["config.option"]("random_org")
if not api_key:
api_key = options.get("api_key")
if not api_version:
api_version = options.get("api_version")
except (NameError, KeyError, AttributeError):
log.error("No Random.org api key found.")
ret["message"] = "No Random.org api key or api version found."
ret["res"] = False
return ret
for item in ["number", "decimalPlaces"]:
if item not in kwargs:
ret["res"] = False
ret["message"] = f"Required argument, {item} is missing."
return ret
if not isinstance(kwargs["number"], int) or not 1 <= kwargs["number"] <= 10000:
ret["res"] = False
ret["message"] = "Number of decimal fractions must be between 1 and 10000"
return ret
if not _numeric(kwargs["decimalPlaces"]) or not 1 <= kwargs["decimalPlaces"] <= 20:
ret["res"] = False
ret["message"] = "Number of decimal places must be between 1 and 20"
return ret
if "replacement" not in kwargs:
replacement = True
else:
replacement = kwargs["replacement"]
if isinstance(api_version, int):
api_version = str(api_version)
_function = (
RANDOM_ORG_FUNCTIONS.get(api_version)
.get("generateDecimalFractions")
.get("method")
)
data = {}
data["id"] = 1911220
data["jsonrpc"] = "2.0"
data["method"] = _function
data["params"] = {
"apiKey": api_key,
"n": kwargs["number"],
"decimalPlaces": kwargs["decimalPlaces"],
"replacement": replacement,
}
result = _query(api_version=api_version, data=data)
if result:
if "random" in result:
random_data = result.get("random").get("data")
ret["data"] = random_data
else:
ret["res"] = False
ret["message"] = result["message"]
else:
ret["res"] = False
ret["message"] = result["message"]
return ret
def generateGaussians(api_key=None, api_version=None, **kwargs):
"""
This method generates true random numbers from a
Gaussian distribution (also known as a normal distribution).
:param api_key: The Random.org api key.
:param api_version: The Random.org api version.
:param number: How many random numbers you need.
Must be within the [1,1e4] range.
:param mean: The distribution's mean. Must be
within the [-1e6,1e6] range.
:param standardDeviation: The distribution's standard
deviation. Must be within
the [-1e6,1e6] range.
:param significantDigits: The number of significant digits
to use. Must be within the [2,20] range.
:return: The user list.
CLI Example:
.. code-block:: bash
salt '*' random_org.generateGaussians number=10 mean=0.0 standardDeviation=1.0 significantDigits=8
"""
ret = {"res": True}
if not api_key or not api_version:
try:
options = __salt__["config.option"]("random_org")
if not api_key:
api_key = options.get("api_key")
if not api_version:
api_version = options.get("api_version")
except (NameError, KeyError, AttributeError):
log.error("No Random.org api key found.")
ret["message"] = "No Random.org api key or api version found."
ret["res"] = False
return ret
for item in ["number", "mean", "standardDeviation", "significantDigits"]:
if item not in kwargs:
ret["res"] = False
ret["message"] = f"Required argument, {item} is missing."
return ret
if not _numeric(kwargs["number"]) or not 1 <= kwargs["number"] <= 10000:
ret["res"] = False
ret["message"] = "Number of decimal fractions must be between 1 and 10000"
return ret
if not _numeric(kwargs["mean"]) or not -1000000 <= kwargs["mean"] <= 1000000:
ret["res"] = False
ret["message"] = "The distribution's mean must be between -1000000 and 1000000"
return ret
if (
not _numeric(kwargs["standardDeviation"])
or not -1000000 <= kwargs["standardDeviation"] <= 1000000
):
ret["res"] = False
ret["message"] = (
"The distribution's standard deviation must be between -1000000 and 1000000"
)
return ret
if (
not _numeric(kwargs["significantDigits"])
or not 2 <= kwargs["significantDigits"] <= 20
):
ret["res"] = False
ret["message"] = "The number of significant digits must be between 2 and 20"
return ret
if isinstance(api_version, int):
api_version = str(api_version)
_function = (
RANDOM_ORG_FUNCTIONS.get(api_version).get("generateGaussians").get("method")
)
data = {}
data["id"] = 1911220
data["jsonrpc"] = "2.0"
data["method"] = _function
data["params"] = {
"apiKey": api_key,
"n": kwargs["number"],
"mean": kwargs["mean"],
"standardDeviation": kwargs["standardDeviation"],
"significantDigits": kwargs["significantDigits"],
}
result = _query(api_version=api_version, data=data)
if result:
if "random" in result:
random_data = result.get("random").get("data")
ret["data"] = random_data
else:
ret["res"] = False
ret["message"] = result["message"]
else:
ret["res"] = False
ret["message"] = result["message"]
return ret
def generateBlobs(api_key=None, api_version=None, **kwargs):
"""
List all Slack users.
:param api_key: The Random.org api key.
:param api_version: The Random.org api version.
:param format: Specifies the format in which the
blobs will be returned. Values
allowed are base64 and hex.
:return: The user list.
CLI Example:
.. code-block:: bash
salt '*' get_integers number=5 min=1 max=6
salt '*' get_integers number=5 min=1 max=6
"""
ret = {"res": True}
if not api_key or not api_version:
try:
options = __salt__["config.option"]("random_org")
if not api_key:
api_key = options.get("api_key")
if not api_version:
api_version = options.get("api_version")
except (NameError, KeyError, AttributeError):
log.error("No Random.org api key found.")
ret["message"] = "No Random.org api key or api version found."
ret["res"] = False
return ret
for item in ["number", "size"]:
if item not in kwargs:
ret["res"] = False
ret["message"] = f"Required argument, {item} is missing."
return ret
if not _numeric(kwargs["number"]) or not 1 <= kwargs["number"] <= 100:
ret["res"] = False
ret["message"] = "Number of blobs must be between 1 and 100"
return ret
# size should be between range and divisible by 8
if (
not _numeric(kwargs["size"])
or not 1 <= kwargs["size"] <= 1048576
or kwargs["size"] % 8 != 0
):
ret["res"] = False
ret["message"] = "Number of blobs must be between 1 and 100"
return ret
if "format" in kwargs:
_format = kwargs["format"]
if _format not in ["base64", "hex"]:
ret["res"] = False
ret["message"] = "Format must be either base64 or hex."
return ret
else:
_format = "base64"
if isinstance(api_version, int):
api_version = str(api_version)
_function = RANDOM_ORG_FUNCTIONS.get(api_version).get("generateBlobs").get("method")
data = {}
data["id"] = 1911220
data["jsonrpc"] = "2.0"
data["method"] = _function
data["params"] = {
"apiKey": api_key,
"n": kwargs["number"],
"size": kwargs["size"],
"format": _format,
}
result = _query(api_version=api_version, data=data)
if result:
if "random" in result:
random_data = result.get("random").get("data")
ret["data"] = random_data
else:
ret["res"] = False
ret["message"] = result["message"]
else:
ret["res"] = False
ret["message"] = result["message"]
return ret
Zerion Mini Shell 1.0