diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..218d60e --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,31 @@ +name: Lint + +on: + push: + branches: + - master + pull_request: + workflow_dispatch: + + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Python 3 + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install Dependencies + shell: bash + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install pylint==2.15.8 + - name: Lint + shell: bash + run: | + pylint nomad/ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 59d98e2..9a33440 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,7 +37,6 @@ jobs: NOMAD_VERSION: ${{ matrix.nomad-version }} shell: bash run: | - echo $NOMAD_VERSION echo ${NOMAD_VERSION} echo "downloading nomad" @@ -50,8 +49,6 @@ jobs: /tmp/nomad agent -dev -bind ${NOMAD_IP} -node pynomad1 --acl-enabled > /dev/null 2>&1 & sleep 30 - name: Install Dependencies - env: - PYTHON_VERSION: ${{ matrix.python-version }} shell: bash run: | python -m pip install --upgrade pip diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..279e122 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,6 @@ +[FORMAT] +# Maximum number of characters on a single line. +max-line-length=120 + +[MESSAGES CONTROL] +disable=duplicate-code \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 94d2a63..4431209 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## 2.0.0 (unreleased) -* Up `requests` lib version to 2.28.1 +### BREAKING CHANGES * Drop Python 2 and Python 3.6 support +* Rename `id` arguments to `_id` across of code base +### Other changes +* Up `requests` lib version to 2.28.1 ## 1.5.0 * Add `namespace` agrument support for `get_allocations` and `get_deployments` endpoints (#133) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fb4e933..f888149 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -180,7 +180,7 @@ class (Requester): ENDPOINT = "" def __init__(self, **kwargs): - super(, self).__init__(**kwargs) + super().__init__(**kwargs) ``` ##### Entity @@ -249,7 +249,7 @@ class cat(Requester): ENDPOINT = "client/fs/cat" def __init__(self, **kwargs): - super(cat, self).__init__(**kwargs) + super().__init__(**kwargs) def read_file(self, id=None, path="/"): """ Read contents of a file in an allocation directory. @@ -382,7 +382,7 @@ class (Requester): ENDPOINT = "" def __init__(self, **kwargs): - super(, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): return "{0}".format(self.__dict__) diff --git a/nomad/__init__.py b/nomad/__init__.py index ca5d767..be2be26 100644 --- a/nomad/__init__.py +++ b/nomad/__init__.py @@ -1,10 +1,13 @@ -import nomad.api as api +"""Nomad Python library""" import os +from nomad import api -class Nomad(object): - - def __init__(self, +class Nomad(): # pylint: disable=too-many-public-methods,too-many-instance-attributes + """ + Nomad API + """ + def __init__(self, # pylint: disable=too-many-arguments host='127.0.0.1', secure=False, port=4646, @@ -102,122 +105,212 @@ def __init__(self, self._variables = api.Variables(**self.requester_settings) def get_uri(self): + """ + Get Nomad host + """ if self.secure: protocol = "https" else: protocol = "http" - return "{protocol}://{host}".format(protocol=protocol, host=self.host) + return f"{protocol}://{self.host}" def get_namespace(self): + """ + Get Nomad namaspace + """ return self.__namespace def get_token(self): + """ + Get Nomad token + """ return self.token @property def jobs(self): + """ + Jobs API + """ return self._jobs @property def job(self): + """ + Job API + """ return self._job @property def nodes(self): + """ + Nodes API + """ return self._nodes @property def node(self): + """ + Node API + """ return self._node @property def allocations(self): + """ + Allocations API + """ return self._allocations @property def allocation(self): + """ + Allocation API + """ return self._allocation @property def evaluations(self): + """ + Evaluations API + """ return self._evaluations @property def evaluation(self): + """ + Evaluation API + """ return self._evaluation @property def event(self): + """ + Event API + """ return self._event @property def agent(self): + """ + Agent API + """ return self._agent @property def client(self): + """ + Client API + """ return self._client @property def deployments(self): + """ + Deployments API + """ return self._deployments @property def deployment(self): + """ + Deployment API + """ return self._deployment @property def regions(self): + """ + Regions API + """ return self._regions @property def scaling(self): + """ + Scaling API + """ return self._scaling @property def status(self): + """ + Status API + """ return self._status @property def system(self): + """ + System API + """ return self._system @property def operator(self): + """ + Operator API + """ return self._operator @property def validate(self): + """ + Validate API + """ return self._validate @property def namespaces(self): + """ + Namespaces API + """ return self._namespaces @property def namespace(self): + """ + Namespace API + """ return self._namespace @property def acl(self): + """ + ACL API + """ return self._acl @property def sentinel(self): + """ + Sentinel API + """ return self._sentinel @property def search(self): + """ + Search API + """ return self._search @property def metrics(self): + """ + Metrics API + """ return self._metrics @property def variable(self): + """ + Variable API + """ return self._variable @property def variables(self): - return self._variables \ No newline at end of file + """ + Variables API + """ + return self._variables diff --git a/nomad/api/__init__.py b/nomad/api/__init__.py index f326865..3886570 100644 --- a/nomad/api/__init__.py +++ b/nomad/api/__init__.py @@ -1,3 +1,4 @@ +"""Nomad Python library""" import nomad.api.exceptions from nomad.api.acl import Acl from nomad.api.agent import Agent @@ -26,4 +27,4 @@ from nomad.api.system import System from nomad.api.validate import Validate from nomad.api.variable import Variable -from nomad.api.variables import Variables \ No newline at end of file +from nomad.api.variables import Variables diff --git a/nomad/api/acl.py b/nomad/api/acl.py index af23e80..857c2dc 100644 --- a/nomad/api/acl.py +++ b/nomad/api/acl.py @@ -1,4 +1,4 @@ -import nomad.api.exceptions +"""Nomad ACL: https://developer.hashicorp.com/nomad/api-docs/acl""" from nomad.api.base import Requester @@ -13,13 +13,13 @@ class Acl(Requester): ENDPOINT = "acl" def __init__(self, **kwargs): - super(Acl, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): raise AttributeError @@ -51,7 +51,7 @@ def get_tokens(self): return self.request("tokens", method="get").json() - def get_token(self, id): + def get_token(self, _id): """ Retrieve specific token. https://www.nomadproject.io/api/acl-tokens.html @@ -62,7 +62,7 @@ def get_token(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("token", id, method="get").json() + return self.request("token", _id, method="get").json() def get_self_token(self): """ Retrieve self token used for auth. @@ -92,7 +92,7 @@ def create_token(self, token): """ return self.request("token", json=token, method="post").json() - def delete_token(self, id): + def delete_token(self, _id): """ Delete specific token. https://www.nomadproject.io/api/acl-tokens.html @@ -103,9 +103,9 @@ def delete_token(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("token", id, method="delete").ok + return self.request("token", _id, method="delete").ok - def update_token(self, id, token): + def update_token(self, _id, token): """ Update token. https://www.nomadproject.io/api/acl-tokens.html @@ -119,7 +119,7 @@ def update_token(self, id, token): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("token", id, json=token, method="post").json() + return self.request("token", _id, json=token, method="post").json() def get_policies(self): """ Get a list of policies. @@ -134,7 +134,7 @@ def get_policies(self): """ return self.request("policies", method="get").json() - def create_policy(self, id, policy): + def create_policy(self, _id, policy): """ Create policy. https://www.nomadproject.io/api/acl-policies.html @@ -147,9 +147,9 @@ def create_policy(self, id, policy): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("policy", id, json=policy, method="post") + return self.request("policy", _id, json=policy, method="post") - def get_policy(self, id): + def get_policy(self, _id): """ Get a spacific. https://www.nomadproject.io/api/acl-policies.html @@ -160,9 +160,9 @@ def get_policy(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("policy", id, method="get").json() + return self.request("policy", _id, method="get").json() - def update_policy(self, id, policy): + def update_policy(self, _id, policy): """ Create policy. https://www.nomadproject.io/api/acl-policies.html @@ -176,9 +176,9 @@ def update_policy(self, id, policy): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("policy", id, json=policy, method="post") + return self.request("policy", _id, json=policy, method="post") - def delete_policy(self, id): + def delete_policy(self, _id): """ Delete specific policy. https://www.nomadproject.io/api/acl-policies.html @@ -191,4 +191,4 @@ def delete_policy(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("policy", id, method="delete").ok + return self.request("policy", _id, method="delete").ok diff --git a/nomad/api/agent.py b/nomad/api/agent.py index c954c29..403d035 100644 --- a/nomad/api/agent.py +++ b/nomad/api/agent.py @@ -1,5 +1,4 @@ -import nomad.api.exceptions - +"""Nomad Agent: https://developer.hashicorp.com/nomad/api-docs/agent""" from nomad.api.base import Requester @@ -9,16 +8,16 @@ class Agent(Requester): ENDPOINT = "agent" def __init__(self, **kwargs): - super(Agent, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - msg = "{0} does not exist".format(item) + msg = f"{item} does not exist" raise AttributeError(msg) def get_agent(self): diff --git a/nomad/api/allocation.py b/nomad/api/allocation.py index 2967d30..c6ab949 100644 --- a/nomad/api/allocation.py +++ b/nomad/api/allocation.py @@ -1,3 +1,4 @@ +"""Nomad allocation: https://developer.hashicorp.com/nomad/api-docs/allocations""" import nomad.api.exceptions from nomad.api.base import Requester @@ -15,13 +16,13 @@ class Allocation(Requester): ENDPOINT = "allocation" def __init__(self, **kwargs): - super(Allocation, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): raise AttributeError @@ -32,6 +33,7 @@ def __contains__(self, item): if response["ID"] == item: return True + return False except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -41,10 +43,11 @@ def __getitem__(self, item): if response["ID"] == item: return response - except nomad.api.exceptions.URLNotFoundNomadException: raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc - def get_allocation(self, id): + def get_allocation(self, _id): """ Query a specific allocation. https://www.nomadproject.io/docs/http/alloc.html @@ -54,9 +57,9 @@ def get_allocation(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, method="get").json() + return self.request(_id, method="get").json() - def stop_allocation(self, id): + def stop_allocation(self, _id): """ Stop a specific allocation. https://www.nomadproject.io/api-docs/allocations/#stop-allocation @@ -66,4 +69,4 @@ def stop_allocation(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "stop", method="post").json() + return self.request(_id, "stop", method="post").json() diff --git a/nomad/api/allocations.py b/nomad/api/allocations.py index e532f0e..a89e407 100644 --- a/nomad/api/allocations.py +++ b/nomad/api/allocations.py @@ -1,8 +1,8 @@ +"""Nomad allocation: https://developer.hashicorp.com/nomad/api-docs/allocations""" from nomad.api.base import Requester class Allocations(Requester): - """ The allocations endpoint is used to query the status of allocations. By default, the agent's local region is used; another region can be @@ -13,13 +13,13 @@ class Allocations(Requester): ENDPOINT = "allocations" def __init__(self, **kwargs): - super(Allocations, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): raise AttributeError diff --git a/nomad/api/base.py b/nomad/api/base.py index e0fae4d..3fd3975 100644 --- a/nomad/api/base.py +++ b/nomad/api/base.py @@ -1,15 +1,30 @@ +"""Requester""" import requests -import nomad.api.exceptions -from requests.packages.urllib3.exceptions import InsecureRequestWarning -requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +import nomad.api.exceptions -class Requester(object): +class Requester(): # pylint: disable=too-many-instance-attributes,too-few-public-methods + """ + Base object for endpoints + """ ENDPOINT = "" - def __init__(self, address=None, uri='http://127.0.0.1', port=4646, namespace=None, token=None, timeout=5, version='v1', verify=False, cert=(), region=None, session=None, **kwargs): + def __init__( # pylint: disable=too-many-arguments + self, + address=None, + uri="http://127.0.0.1", + port=4646, + namespace=None, + token=None, + timeout=5, + version="v1", + verify=False, + cert=(), + region=None, + session=None + ): self.uri = uri self.port = port self.namespace = namespace @@ -24,28 +39,32 @@ def __init__(self, address=None, uri='http://127.0.0.1', port=4646, namespace=No def _endpoint_builder(self, *args): if args: - u = "/".join(args) - return "{v}/".format(v=self.version) + u + args_str = "/".join(args) + return f"{self.version}/" + args_str + + return "/" def _required_namespace(self, endpoint): required_namespace = [ - "job", - "jobs", - "allocation", - "allocations", - "deployment", - "deployments", - "acl", - "client", - "node" - ] + "job", + "jobs", + "allocation", + "allocations", + "deployment", + "deployments", + "acl", + "client", + "node", + "variable", + "variables", + ] # split 0 -> Api Version # split 1 -> Working Endpoint - ENDPOINT_NAME = 1 endpoint_split = endpoint.split("/") try: - required = endpoint_split[ENDPOINT_NAME] in required_namespace - except: + endpoint_name = 1 + required = endpoint_split[endpoint_name] in required_namespace + except IndexError: required = False return required @@ -54,27 +73,29 @@ def _url_builder(self, endpoint): url = self.address if self.address is None: - url = "{uri}:{port}".format(uri=self.uri, port=self.port) - - url = "{url}/{endpoint}".format(url=url, endpoint=endpoint) + url = f"{self.uri}:{self.port}" + url = f"{url}/{endpoint}" return url def _query_string_builder(self, endpoint, params=None): - qs = {} + query_string = {} if not isinstance(params, dict): params = {} if ("namespace" not in params) and (self.namespace and self._required_namespace(endpoint)): - qs["namespace"] = self.namespace + query_string["namespace"] = self.namespace if "region" not in params and self.region: - qs["region"] = self.region + query_string["region"] = self.region - return qs + return query_string def request(self, *args, **kwargs): + """ + Send HTTP Request (wrapper around requests) + """ endpoint = self._endpoint_builder(self.ENDPOINT, *args) response = self._request( endpoint=endpoint, @@ -85,19 +106,30 @@ def request(self, *args, **kwargs): headers=kwargs.get("headers", None), allow_redirects=kwargs.get("allow_redirects", False), timeout=kwargs.get("timeout", self.timeout), - stream=kwargs.get("stream", False) + stream=kwargs.get("stream", False), ) return response - def _request(self, method, endpoint, params=None, data=None, json=None, headers=None, allow_redirects=None, timeout=None, stream=False): + def _request( # pylint: disable=too-many-arguments, too-many-branches + self, + method, + endpoint, + params=None, + data=None, + json=None, + headers=None, + allow_redirects=None, + timeout=None, + stream=False, + ): url = self._url_builder(endpoint) - qs = self._query_string_builder(endpoint=endpoint, params=params) + query_string = self._query_string_builder(endpoint=endpoint, params=params) if params: - params.update(qs) + params.update(query_string) else: - params = qs + params = query_string if self.token: try: @@ -156,16 +188,16 @@ def _request(self, method, endpoint, params=None, data=None, json=None, headers= if response.ok: return response - elif response.status_code == 400: + if response.status_code == 400: raise nomad.api.exceptions.BadRequestNomadException(response) - elif response.status_code == 403: + if response.status_code == 403: raise nomad.api.exceptions.URLNotAuthorizedNomadException(response) - elif response.status_code == 404: + if response.status_code == 404: raise nomad.api.exceptions.URLNotFoundNomadException(response) - elif response.status_code == 409: + if response.status_code == 409: raise nomad.api.exceptions.VariableConflict(response) - else: - raise nomad.api.exceptions.BaseNomadException(response) + + raise nomad.api.exceptions.BaseNomadException(response) except requests.exceptions.ConnectionError as error: if all([stream, timeout]): diff --git a/nomad/api/client.py b/nomad/api/client.py index 4178f57..7b495fe 100644 --- a/nomad/api/client.py +++ b/nomad/api/client.py @@ -1,8 +1,11 @@ +# we want to have backward compatibility here +# pylint: disable=invalid-name,too-many-instance-attributes,too-many-arguments +"""Nomad Client: https://developer.hashicorp.com/nomad/api-docs/client""" from nomad.api.base import Requester - - -class Client(object): - +class Client(): + """ + The /client endpoints are used to interact with the Nomad clients. + """ def __init__(self, **kwargs): self.ls = ls(**kwargs) self.cat = cat(**kwargs) @@ -16,13 +19,14 @@ def __init__(self, **kwargs): self.gc_all_allocations = gc_all_allocations(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) class ls(Requester): @@ -38,25 +42,25 @@ class ls(Requester): ENDPOINT = "client/fs/ls" def __init__(self, **kwargs): - super(ls, self).__init__(**kwargs) + super().__init__(**kwargs) - def list_files(self, id=None, path="/"): + def list_files(self, _id=None, path="/"): """ List files in an allocation directory. https://www.nomadproject.io/docs/http/client-fs-ls.html arguments: - - id - - path + - _id + - path returns: list raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - if id: - return self.request(id, params={"path": path}, method="get").json() - else: - return self.request(params={"path": path}, method="get").json() + if _id: + return self.request(_id, params={"path": path}, method="get").json() + + return self.request(params={"path": path}, method="get").json() class cat(Requester): @@ -73,25 +77,25 @@ class cat(Requester): ENDPOINT = "client/fs/cat" def __init__(self, **kwargs): - super(cat, self).__init__(**kwargs) + super().__init__(**kwargs) - def read_file(self, id=None, path="/"): + def read_file(self, _id=None, path="/"): """ Read contents of a file in an allocation directory. https://www.nomadproject.io/docs/http/client-fs-cat.html arguments: - - id + - _id - path returns: (str) text raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - if id: - return self.request(id, params={"path": path}, method="get").text - else: - return self.request(params={"path": path}, method="get").text + if _id: + return self.request(_id, params={"path": path}, method="get").text + + return self.request(params={"path": path}, method="get").text class read_at(Requester): @@ -105,15 +109,15 @@ class read_at(Requester): ENDPOINT = "client/fs/readat" def __init__(self, **kwargs): - super(read_at, self).__init__(**kwargs) + super().__init__(**kwargs) - def read_file_offset(self, id, offset, limit, path="/"): + def read_file_offset(self, _id, offset, limit, path="/"): """ Read contents of a file in an allocation directory. https://www.nomadproject.io/docs/http/client-fs-cat.html arguments: - - id: (str) allocation_id required + - _id: (str) allocation_id required - offset: (int) required - limit: (int) required - path: (str) optional @@ -127,7 +131,7 @@ def read_file_offset(self, id, offset, limit, path="/"): "offset": offset, "limit": limit } - return self.request(id, params=params, method="get").text + return self.request(_id, params=params, method="get").text class stream_file(Requester): @@ -141,15 +145,15 @@ class stream_file(Requester): ENDPOINT = "client/fs/stream" def __init__(self, **kwargs): - super(stream_file, self).__init__(**kwargs) + super().__init__(**kwargs) - def stream(self, id, offset, origin, path="/"): + def stream(self, _id, offset, origin, path="/"): """ This endpoint streams the contents of a file in an allocation directory. https://www.nomadproject.io/api/client.html#stream-file arguments: - - id: (str) allocation_id required + - _id: (str) allocation_id required - offset: (int) required - origin: (str) either start|end - path: (str) optional @@ -163,7 +167,7 @@ def stream(self, id, offset, origin, path="/"): "offset": offset, "origin": origin } - return self.request(id, params=params, method="get").text + return self.request(_id, params=params, method="get").text class stream_logs(Requester): @@ -177,17 +181,17 @@ class stream_logs(Requester): ENDPOINT = "client/fs/logs" def __init__(self, **kwargs): - super(stream_logs, self).__init__(**kwargs) + super().__init__(**kwargs) - def stream(self, id, task, type, follow=False, offset=0, origin="start", plain=False): + def stream(self, _id, task, _type, follow=False, offset=0, origin="start", plain=False): """ This endpoint streams a task's stderr/stdout logs. https://www.nomadproject.io/api/client.html#stream-logs arguments: - - id: (str) allocation_id required + - _id: (str) allocation_id required - task: (str) name of the task inside the allocation to stream logs from - - type: (str) Specifies the stream to stream. Either "stderr|stdout" + - _type: (str) Specifies the stream to stream. Either "stderr|stdout" - follow: (bool) default false - offset: (int) default 0 - origin: (str) either start|end, default "start" @@ -199,19 +203,18 @@ def stream(self, id, task, type, follow=False, offset=0, origin="start", plain=F """ params = { "task": task, - "type": type, + "type": _type, "follow": follow, "offset": offset, "origin": origin, "plain": plain } - return self.request(id, params=params, method="get").text + return self.request(_id, params=params, method="get").text class stat(Requester): - """ - The /fs/stat endpoint is used to show stat information + The /fs/stat endpoint is used to show stat information This API endpoint is hosted by the Nomad client and requests have to be made to the Nomad client where the particular allocation was placed. @@ -221,25 +224,25 @@ class stat(Requester): ENDPOINT = "client/fs/stat" def __init__(self, **kwargs): - super(stat, self).__init__(**kwargs) + super().__init__(**kwargs) - def stat_file(self, id=None, path="/"): + def stat_file(self, _id=None, path="/"): """ Stat a file in an allocation directory. https://www.nomadproject.io/docs/http/client-fs-stat.html arguments: - - id + - _id - path returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - if id: - return self.request(id, params={"path": path}, method="get").json() - else: - return self.request(params={"path": path}, method="get").json() + if _id: + return self.request(_id, params={"path": path}, method="get").json() + + return self.request(params={"path": path}, method="get").json() class stats(Requester): @@ -255,7 +258,7 @@ class stats(Requester): ENDPOINT = "client/stats" def __init__(self, **kwargs): - super(stats, self).__init__(**kwargs) + super().__init__(**kwargs) def read_stats(self, node_id=None): """ Query the actual resources consumed on a node. @@ -275,8 +278,8 @@ class allocation(Requester): """ The allocation/:alloc_id/stats endpoint is used to query the actual - resources consumed by an allocation. The API endpoint is hosted by the - Nomad client and requests have to be made to the nomad client whose + resources consumed by an allocation. The API endpoint is hosted by the + Nomad client and requests have to be made to the nomad client whose resource usage metrics are of interest. https://www.nomadproject.io/api/client.html#read-allocation @@ -285,9 +288,9 @@ class allocation(Requester): ENDPOINT = "client/allocation" def __init__(self, **kwargs): - super(allocation, self).__init__(**kwargs) + super().__init__(**kwargs) - def read_allocation_stats(self, id): + def read_allocation_stats(self, _id): """ Query the actual resources consumed by an allocation. https://www.nomadproject.io/api/client.html#read-allocation @@ -298,9 +301,9 @@ def read_allocation_stats(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "stats", method="get").json() + return self.request(_id, "stats", method="get").json() - def restart_allocation(self, id): + def restart_allocation(self, _id): """ Restart a specific allocation. https://www.nomadproject.io/api-docs/allocations/#restart-allocation @@ -310,7 +313,7 @@ def restart_allocation(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "restart", method="post").json() + return self.request(_id, "restart", method="post").json() class gc_allocation(Requester): @@ -324,20 +327,20 @@ class gc_allocation(Requester): ENDPOINT = "client/allocation" def __init__(self, **kwargs): - super(gc_allocation, self).__init__(**kwargs) + super().__init__(**kwargs) - def garbage_collect(self, id): + def garbage_collect(self, _id): """ This endpoint forces a garbage collection of a particular, stopped allocation on a node. https://www.nomadproject.io/api/client.html#gc-allocation arguments: - - id: (str) full allocation_id + - _id: (str) full allocation_id raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - self.request(id, "gc", method="get") + self.request(_id, "gc", method="get") class gc_all_allocations(Requester): @@ -351,7 +354,7 @@ class gc_all_allocations(Requester): ENDPOINT = "client/gc" def __init__(self, **kwargs): - super(gc_all_allocations, self).__init__(**kwargs) + super().__init__(**kwargs) def garbage_collect(self, node_id=None): """ This endpoint forces a garbage collection of all stopped allocations on a node. diff --git a/nomad/api/deployment.py b/nomad/api/deployment.py index 238bf2f..90e27e2 100644 --- a/nomad/api/deployment.py +++ b/nomad/api/deployment.py @@ -1,3 +1,4 @@ +"""Nomad Deployment: https://developer.hashicorp.com/nomad/api-docs/deployments""" import nomad.api.exceptions from nomad.api.base import Requester @@ -13,88 +14,86 @@ class Deployment(Requester): ENDPOINT = "deployment" def __init__(self, **kwargs): - super(Deployment, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - msg = "{0} does not exist".format(item) + msg = f"{item} does not exist" raise AttributeError(msg) def __contains__(self, item): - try: - d = self.get_deployment(item) + self.get_deployment(item) return True except nomad.api.exceptions.URLNotFoundNomadException: return False def __getitem__(self, item): - try: - d = self.get_deployment(item) - - if d["ID"] == item: - return d - except nomad.api.exceptions.URLNotFoundNomadException: + deployment = self.get_deployment(item) + if deployment["ID"] == item: + return deployment raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exp: + raise KeyError from exp - def get_deployment(self, id): + def get_deployment(self, _id): """ This endpoint reads information about a specific deployment by ID. https://www.nomadproject.io/docs/http/deployments.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, method="get").json() + return self.request(_id, method="get").json() - def get_deployment_allocations(self, id): + def get_deployment_allocations(self, _id): """ This endpoint lists the allocations created or modified for the given deployment. https://www.nomadproject.io/docs/http/deployments.html arguments: - - id + - _id returns: list of dicts raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("allocations", id, method="get").json() + return self.request("allocations", _id, method="get").json() - def fail_deployment(self, id): + def fail_deployment(self, _id): """ This endpoint is used to mark a deployment as failed. This should be done to force the scheduler to stop creating allocations as part of the deployment or to cause a rollback to a previous job version. https://www.nomadproject.io/docs/http/deployments.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - fail_json = {"DeploymentID": id} - return self.request("fail", id, json=fail_json, method="post").json() + fail_json = {"DeploymentID": _id} + return self.request("fail", _id, json=fail_json, method="post").json() - def pause_deployment(self, id, pause): + def pause_deployment(self, _id, pause): """ This endpoint is used to pause or unpause a deployment. This is done to pause a rolling upgrade or resume it. https://www.nomadproject.io/docs/http/deployments.html arguments: - - id + - _id - pause, Specifies whether to pause or resume the deployment. returns: dict raises: @@ -102,46 +101,48 @@ def pause_deployment(self, id, pause): - nomad.api.exceptions.URLNotFoundNomadException """ pause_json = {"Pause": pause, - "DeploymentID": id} - return self.request("pause", id, json=pause_json, method="post").json() + "DeploymentID": _id} + return self.request("pause", _id, json=pause_json, method="post").json() - def promote_deployment_all(self, id, all=True): + def promote_deployment_all(self, _id, _all=True): """ This endpoint is used to promote task groups that have canaries for a deployment. This should be done when the placed canaries are healthy and the rolling upgrade of the remaining allocations should begin. https://www.nomadproject.io/docs/http/deployments.html arguments: - - id - - all, Specifies whether all task groups should be promoted. + - _id + - _all, Specifies whether all task groups should be promoted. returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - promote_all_json = {"All": all, - "DeploymentID": id} - return self.request("promote", id, json=promote_all_json, method="post").json() + promote_all_json = {"All": _all, + "DeploymentID": _id} + return self.request("promote", _id, json=promote_all_json, method="post").json() - def promote_deployment_groups(self, id, groups=list()): + def promote_deployment_groups(self, _id, groups=None): """ This endpoint is used to promote task groups that have canaries for a deployment. This should be done when the placed canaries are healthy and the rolling upgrade of the remaining allocations should begin. https://www.nomadproject.io/docs/http/deployments.html arguments: - - id + - _id - groups, (list) Specifies a particular set of task groups that should be promoted returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ + if groups is None: + groups = [] promote_groups_json = {"Groups": groups, - "DeploymentID": id} - return self.request("promote", id, json=promote_groups_json, method="post").json() + "DeploymentID": _id} + return self.request("promote", _id, json=promote_groups_json, method="post").json() - def deployment_allocation_health(self, id, healthy_allocations=list(), unhealthy_allocations=list()): + def deployment_allocation_health(self, _id, healthy_allocations=None, unhealthy_allocations=None): """ This endpoint is used to set the health of an allocation that is in the deployment manually. In some use cases, automatic detection of allocation health may not be desired. As such those task groups can be marked with an upgrade policy that uses health_check = "manual". Those allocations must have their health marked @@ -151,7 +152,7 @@ def deployment_allocation_health(self, id, healthy_allocations=list(), unhealthy https://www.nomadproject.io/docs/http/deployments.html arguments: - - id + - _id - healthy_allocations, Specifies the set of allocation that should be marked as healthy. - unhealthy_allocations, Specifies the set of allocation that should be marked as unhealthy. returns: dict @@ -159,7 +160,13 @@ def deployment_allocation_health(self, id, healthy_allocations=list(), unhealthy - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ + if healthy_allocations is None: + healthy_allocations = [] + + if unhealthy_allocations is None: + unhealthy_allocations = [] + allocations = {"HealthyAllocationIDs": healthy_allocations, "UnHealthyAllocationIDs": unhealthy_allocations, - "DeploymentID": id} - return self.request("allocation-health", id, json=allocations, method="post").json() + "DeploymentID": _id} + return self.request("allocation-health", _id, json=allocations, method="post").json() diff --git a/nomad/api/deployments.py b/nomad/api/deployments.py index 92b7145..a812d3a 100644 --- a/nomad/api/deployments.py +++ b/nomad/api/deployments.py @@ -1,3 +1,4 @@ +"""Nomad Deployment: https://developer.hashicorp.com/nomad/api-docs/deployments""" import nomad.api.exceptions from nomad.api.base import Requester @@ -13,13 +14,13 @@ class Deployments(Requester): ENDPOINT = "deployments" def __init__(self, **kwargs): - super(Deployments, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): raise AttributeError @@ -35,26 +36,23 @@ def __iter__(self): def __contains__(self, item): try: deployments = self.get_deployments() - - for d in deployments: - if d["ID"] == item: + for deployment in deployments: + if deployment["ID"] == item: return True - else: - return False + + return False except nomad.api.exceptions.URLNotFoundNomadException: return False def __getitem__(self, item): try: deployments = self.get_deployments() - - for d in deployments: - if d["ID"] == item: - return d - else: - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: + for deployment in deployments: + if deployment["ID"] == item: + return deployment raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc def get_deployments(self, prefix="", namespace=None): """ This endpoint lists all deployments. diff --git a/nomad/api/evaluation.py b/nomad/api/evaluation.py index 2aa6bb2..a9ad84c 100644 --- a/nomad/api/evaluation.py +++ b/nomad/api/evaluation.py @@ -1,3 +1,4 @@ +"""Nomad Evaluation: https://developer.hashicorp.com/nomad/api-docs/evaluations""" import nomad.api.exceptions from nomad.api.base import Requester @@ -15,22 +16,21 @@ class Evaluation(Requester): ENDPOINT = "evaluation" def __init__(self, **kwargs): - super(Evaluation, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - msg = "{0} does not exist".format(item) + msg = f"{item} does not exist" raise AttributeError(msg) def __contains__(self, item): - try: - e = self.get_evaluation(item) + self.get_evaluation(item) return True except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -38,37 +38,37 @@ def __contains__(self, item): def __getitem__(self, item): try: - e = self.get_evaluation(item) - - if e["ID"] == item: - return e - except nomad.api.exceptions.URLNotFoundNomadException: + evaluation = self.get_evaluation(item) + if evaluation["ID"] == item: + return evaluation raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc - def get_evaluation(self, id): + def get_evaluation(self, _id): """ Query a specific evaluation. https://www.nomadproject.io/docs/http/eval.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, method="get").json() + return self.request(_id, method="get").json() - def get_allocations(self, id): + def get_allocations(self, _id): """ Query the allocations created or modified by an evaluation. https://www.nomadproject.io/docs/http/eval.html arguments: - - id + - _id returns: list raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "allocations", method="get").json() + return self.request(_id, "allocations", method="get").json() diff --git a/nomad/api/evaluations.py b/nomad/api/evaluations.py index 8e581bc..8ec96e8 100644 --- a/nomad/api/evaluations.py +++ b/nomad/api/evaluations.py @@ -1,3 +1,4 @@ +"""Nomad Evaluations: https://developer.hashicorp.com/nomad/api-docs/evaluations""" import nomad.api.exceptions from nomad.api.base import Requester @@ -14,13 +15,13 @@ class Evaluations(Requester): ENDPOINT = "evaluations" def __init__(self, **kwargs): - super(Evaluations, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): raise AttributeError @@ -29,11 +30,11 @@ def __contains__(self, item): try: evaluations = self.get_evaluations() - for e in evaluations: - if e["ID"] == item: + for evaluation in evaluations: + if evaluation["ID"] == item: return True - else: - return False + + return False except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -45,13 +46,12 @@ def __getitem__(self, item): try: evaluations = self.get_evaluations() - for e in evaluations: - if e["ID"] == item: - return e - else: - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: + for evaluation in evaluations: + if evaluation["ID"] == item: + return evaluation raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc def __iter__(self): evaluations = self.get_evaluations() diff --git a/nomad/api/event.py b/nomad/api/event.py index 658c1ca..ba001fc 100644 --- a/nomad/api/event.py +++ b/nomad/api/event.py @@ -1,24 +1,21 @@ +"""Nomad Events: https://developer.hashicorp.com/nomad/api-docs/events""" import json import threading +import queue import requests from nomad.api.base import Requester -from nomad.api.exceptions import TimeoutNomadException - -try: - import queue -except ImportError: - import Queue as queue - - -class Event(object): +class Event(): + """ + Nomad Event + """ def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): raise AttributeError @@ -26,8 +23,8 @@ def __getattr__(self, item): def __init__(self, **kwargs): self.stream = stream(**kwargs) - -class stream(Requester): +# backward compatibility +class stream(Requester): # pylint: disable=invalid-name """ The /event/stream endpoint is used to stream events generated by Nomad. @@ -37,9 +34,9 @@ class stream(Requester): ENDPOINT = "event/stream" def __init__(self, **kwargs): - super(stream, self).__init__(**kwargs) + super().__init__(**kwargs) - def _get_stream(self, method, params, timeout, event_queue, exit_event): + def _get_stream(self, method, params, timeout, event_queue, exit_event): # pylint: disable=too-many-arguments """ Used as threading target, to obtain json() value Args: @@ -66,7 +63,7 @@ def _get_stream(self, method, params, timeout, event_queue, exit_event): except requests.exceptions.ConnectionError: continue - def get_stream(self, index=0, topic=None, namespace=None, event_queue=None, timeout=None): + def get_stream(self, index=0, topic=None, namespace=None, event_queue=None, timeout=None): # pylint: disable=too-many-arguments """ Usage: stream, stream_exit_event, events = n.event.stream.get_stream() @@ -81,7 +78,8 @@ def get_stream(self, index=0, topic=None, namespace=None, event_queue=None, time index: (int), Specifies the index to start streaming events from. If the requested index is no longer in the buffer the stream will start at the next available index. - topic: (None or dict), Specifies a topic to subscribe to and filter on. The default is to subscribe to all topics. + topic: (None or dict), Specifies a topic to subscribe to and filter on. + The default is to subscribe to all topics. Multiple topics may be specified by passing multiple topic parameters. A valid topic parameter includes a topic type and an optional filter_key separated by a colon :. As an example ?topic=Deployment:redis would subscribe to all Deployment events for a job redis. diff --git a/nomad/api/exceptions.py b/nomad/api/exceptions.py index ca5e343..5f60205 100644 --- a/nomad/api/exceptions.py +++ b/nomad/api/exceptions.py @@ -1,3 +1,4 @@ +"""Internal library exceptions""" import requests @@ -8,9 +9,9 @@ def __init__(self, nomad_resp): def __str__(self): if isinstance(self.nomad_resp, requests.Response) and hasattr(self.nomad_resp, "text"): - return 'The {0} was raised with following response: {1}.'.format(self.__class__.__name__, self.nomad_resp.text) - else: - return 'The {0} was raised due to the following error: {1}'.format(self.__class__.__name__, str(self.nomad_resp)) + return f"The {self.__class__.__name__} was raised with following response: {self.nomad_resp.text}." + + return f"The {self.__class__.__name__} was raised due to the following error: {self.nomad_resp}" class URLNotFoundNomadException(BaseNomadException): diff --git a/nomad/api/job.py b/nomad/api/job.py index b1c0a3a..6d0286b 100644 --- a/nomad/api/job.py +++ b/nomad/api/job.py @@ -1,3 +1,4 @@ +"""Nomad job: https://developer.hashicorp.com/nomad/api-docs/jobs""" import nomad.api.exceptions from nomad.api.base import Requester @@ -14,47 +15,44 @@ class Job(Requester): ENDPOINT = "job" def __init__(self, **kwargs): - super(Job, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - msg = "{0} does not exist".format(item) + msg = f"{item} does not exist" raise AttributeError(msg) def __contains__(self, item): - try: - j = self.get_job(item) + self.get_job(item) return True except nomad.api.exceptions.URLNotFoundNomadException: return False def __getitem__(self, item): - try: - j = self.get_job(item) - - if j["ID"] == item: - return j - if j["Name"] == item: - return j - else: - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: + job = self.get_job(item) + if job["ID"] == item: + return job + if job["Name"] == item: + return job + raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc - def get_job(self, id, namespace=None): + def get_job(self, _id, namespace=None): """ Query a single job for its specification and status. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. This is specified as a querystring parameter. returns: dict @@ -67,9 +65,9 @@ def get_job(self, id, namespace=None): if namespace: params["namespace"] = namespace - return self.request(id, method="get", params=params).json() + return self.request(_id, method="get", params=params).json() - def get_versions(self, id): + def get_versions(self, _id): """ This endpoint reads information about all versions of a job. https://www.nomadproject.io/docs/http/job.html @@ -81,114 +79,114 @@ def get_versions(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "versions", method="get").json() + return self.request(_id, "versions", method="get").json() - def get_allocations(self, id): + def get_allocations(self, _id): """ Query the allocations belonging to a single job. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id returns: list raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "allocations", method="get").json() + return self.request(_id, "allocations", method="get").json() - def get_evaluations(self, id): + def get_evaluations(self, _id): """ Query the evaluations belonging to a single job. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "evaluations", method="get").json() + return self.request(_id, "evaluations", method="get").json() - def get_deployments(self, id): + def get_deployments(self, _id): """ This endpoint lists a single job's deployments https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "deployments", method="get").json() + return self.request(_id, "deployments", method="get").json() - def get_deployment(self, id): + def get_deployment(self, _id): """ This endpoint returns a single job's most recent deployment. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id returns: list of dicts raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "deployment", method="get").json() + return self.request(_id, "deployment", method="get").json() - def get_summary(self, id): + def get_summary(self, _id): """ Query the summary of a job. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "summary", method="get").json() + return self.request(_id, "summary", method="get").json() - def register_job(self, id, job): + def register_job(self, _id, job): """ Registers a new job or updates an existing job https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, json=job, method="post").json() + return self.request(_id, json=job, method="post").json() - def evaluate_job(self, id): + def evaluate_job(self, _id): """ Creates a new evaluation for the given job. This can be used to force run the scheduling logic if necessary. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "evaluate", method="post").json() + return self.request(_id, "evaluate", method="post").json() - def plan_job(self, id, job, diff=False, policy_override=False): + def plan_job(self, _id, job, diff=False, policy_override=False): """ Invoke a dry-run of the scheduler for the job. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id - job, dict - diff, boolean - policy_override, boolean @@ -201,9 +199,9 @@ def plan_job(self, id, job, diff=False, policy_override=False): json_dict.update(job) json_dict.setdefault('Diff', diff) json_dict.setdefault('PolicyOverride', policy_override) - return self.request(id, "plan", json=json_dict, method="post").json() + return self.request(_id, "plan", json=json_dict, method="post").json() - def periodic_job(self, id): + def periodic_job(self, _id): """ Forces a new instance of the periodic job. A new instance will be created even if it violates the job's prohibit_overlap settings. As such, this should be only used to immediately @@ -212,21 +210,21 @@ def periodic_job(self, id): https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "periodic", "force", method="post").json() + return self.request(_id, "periodic", "force", method="post").json() - def dispatch_job(self, id, payload=None, meta=None): + def dispatch_job(self, _id, payload=None, meta=None): """ Dispatches a new instance of a parameterized job. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id - payload - meta returns: dict @@ -235,15 +233,15 @@ def dispatch_job(self, id, payload=None, meta=None): - nomad.api.exceptions.URLNotFoundNomadException """ dispatch_json = {"Meta": meta, "Payload": payload} - return self.request(id, "dispatch", json=dispatch_json, method="post").json() + return self.request(_id, "dispatch", json=dispatch_json, method="post").json() - def revert_job(self, id, version, enforce_prior_version=None): + def revert_job(self, _id, version, enforce_prior_version=None): """ This endpoint reverts the job to an older version. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id - version, Specifies the job version to revert to. optional_arguments: - enforce_prior_version, Optional value specifying the current job's version. @@ -254,18 +252,18 @@ def revert_job(self, id, version, enforce_prior_version=None): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - revert_json = {"JobID": id, + revert_json = {"JobID": _id, "JobVersion": version, "EnforcePriorVersion": enforce_prior_version} - return self.request(id, "revert", json=revert_json, method="post").json() + return self.request(_id, "revert", json=revert_json, method="post").json() - def stable_job(self, id, version, stable): + def stable_job(self, _id, version, stable): """ This endpoint sets the job's stability. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id - version, Specifies the job version to revert to. - stable, Specifies whether the job should be marked as stable or not. returns: dict @@ -273,18 +271,18 @@ def stable_job(self, id, version, stable): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - revert_json = {"JobID": id, + revert_json = {"JobID": _id, "JobVersion": version, "Stable": stable} - return self.request(id, "stable", json=revert_json, method="post").json() + return self.request(_id, "stable", json=revert_json, method="post").json() - def deregister_job(self, id, purge=None): + def deregister_job(self, _id, purge=None): """ Deregisters a job, and stops all allocations part of it. https://www.nomadproject.io/docs/http/job.html arguments: - - id + - _id - purge (bool), optionally specifies whether the job should be stopped and purged immediately (`purge=True`) or deferred to the Nomad garbage collector (`purge=False`). @@ -299,6 +297,6 @@ def deregister_job(self, id, purge=None): if purge is not None: if not isinstance(purge, bool): raise nomad.api.exceptions.InvalidParameters("purge is invalid " - "(expected type %s but got %s)"%(type(bool()), type(purge))) + f"(expected type {type(bool())} but got {type(purge)})") params = {"purge": purge} - return self.request(id, params=params, method="delete").json() + return self.request(_id, params=params, method="delete").json() diff --git a/nomad/api/jobs.py b/nomad/api/jobs.py index 09e6f3a..98fa2b4 100644 --- a/nomad/api/jobs.py +++ b/nomad/api/jobs.py @@ -1,3 +1,4 @@ +"""Nomad job: https://developer.hashicorp.com/nomad/api-docs/jobs""" import nomad.api.exceptions from nomad.api.base import Requester @@ -15,16 +16,16 @@ class Jobs(Requester): ENDPOINT = "jobs" def __init__(self, **kwargs): - super(Jobs, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return "{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return "{self.__dict__}" def __getattr__(self, item): - msg = "{0} does not exist".format(item) + msg = f"{item} does not exist" raise AttributeError(msg) def __contains__(self, item): @@ -36,8 +37,7 @@ def __contains__(self, item): return True if j["Name"] == item: return True - else: - return False + return False except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -54,10 +54,9 @@ def __getitem__(self, item): return j if j["Name"] == item: return j - else: - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc def __iter__(self): jobs = self.get_jobs() @@ -106,4 +105,6 @@ def parse(self, hcl, canonicalize=False): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("parse", json={"JobHCL": hcl, "Canonicalize": canonicalize}, method="post", allow_redirects=True).json() + return self.request( + "parse", json={"JobHCL": hcl, "Canonicalize": canonicalize}, method="post", allow_redirects=True + ).json() diff --git a/nomad/api/metrics.py b/nomad/api/metrics.py index beef3c3..2ecccf2 100644 --- a/nomad/api/metrics.py +++ b/nomad/api/metrics.py @@ -1,3 +1,4 @@ +"""Nomad Metrics: https://developer.hashicorp.com/nomad/api-docs/metrics""" from nomad.api.base import Requester @@ -15,16 +16,17 @@ class Metrics(Requester): ENDPOINT = "metrics" def __init__(self, **kwargs): - super(Metrics, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def get_metrics(self): """ Get the metrics diff --git a/nomad/api/namespace.py b/nomad/api/namespace.py index 0f51b01..0860c73 100644 --- a/nomad/api/namespace.py +++ b/nomad/api/namespace.py @@ -1,3 +1,4 @@ +"""Nomad namespace: https://developer.hashicorp.com/nomad/api-docs/namespaces""" import nomad.api.exceptions from nomad.api.base import Requester @@ -14,22 +15,22 @@ class Namespace(Requester): ENDPOINT = "namespace" def __init__(self, **kwargs): - super(Namespace, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - msg = "{0} does not exist".format(item) + msg = f"{item} does not exist" raise AttributeError(msg) def __contains__(self, item): try: - j = self.get_namespace(item) + self.get_namespace(item) return True except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -37,30 +38,30 @@ def __contains__(self, item): def __getitem__(self, item): try: - j = self.get_namespace(item) - - if j["ID"] == item: - return j - if j["Name"] == item: - return j - else: - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: + job = self.get_namespace(item) + + if job["ID"] == item: + return job + if job["Name"] == item: + return job + raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc - def get_namespace(self, id): + def get_namespace(self, _id): """ Query a single namespace. https://www.nomadproject.io/api/namespaces.html arguments: - - id + - _id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, method="get").json() + return self.request(_id, method="get").json() def create_namespace(self, namespace): """ create namespace @@ -77,31 +78,31 @@ def create_namespace(self, namespace): """ return self.request(json=namespace, method="post") - def update_namespace(self, id, namespace): + def update_namespace(self, _id, namespace): """ Update namespace https://www.nomadproject.io/api/namespaces.html arguments: - - id + - _id - namespace (dict) returns: requests.Response raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, json=namespace, method="post") + return self.request(_id, json=namespace, method="post") - def delete_namespace(self, id): + def delete_namespace(self, _id): """ delete namespace. https://www.nomadproject.io/api/namespaces.html arguments: - - id + - _id returns: requests.Response raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, method="delete") + return self.request(_id, method="delete") diff --git a/nomad/api/namespaces.py b/nomad/api/namespaces.py index 12b39a1..3fb907f 100644 --- a/nomad/api/namespaces.py +++ b/nomad/api/namespaces.py @@ -1,3 +1,4 @@ +"""Nomad namespace: https://developer.hashicorp.com/nomad/api-docs/namespaces""" import nomad.api.exceptions from nomad.api.base import Requester @@ -13,26 +14,26 @@ class Namespaces(Requester): ENDPOINT = "namespaces" def __init__(self, **kwargs): - super(Namespaces, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - msg = "{0} does not exist".format(item) + msg = f"{item} does not exist" raise AttributeError(msg) def __contains__(self, item): try: namespaces = self.get_namespaces() - for n in namespaces: - if n["Name"] == item: + for namespace in namespaces: + if namespace["Name"] == item: return True - + return False except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -45,13 +46,13 @@ def __getitem__(self, item): try: namespaces = self.get_namespaces() - for n in namespaces: - if n["Name"] == item: - return n - - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: + for namespace in namespaces: + if namespace["Name"] == item: + return namespace + raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc def __iter__(self): namespaces = self.get_namespaces() diff --git a/nomad/api/node.py b/nomad/api/node.py index bdff1a7..46688c2 100644 --- a/nomad/api/node.py +++ b/nomad/api/node.py @@ -1,3 +1,4 @@ +"""Nomad Node: https://developer.hashicorp.com/nomad/api-docs/nodes""" import nomad.api.exceptions from nomad.api.base import Requester @@ -14,22 +15,22 @@ class Node(Requester): ENDPOINT = "node" def __init__(self, **kwargs): - super(Node, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - msg = "{0} does not exist".format(item) + msg = f"{item} does not exist" raise AttributeError(msg) def __contains__(self, item): try: - n = self.get_node(item) + self.get_node(item) return True except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -37,18 +38,18 @@ def __contains__(self, item): def __getitem__(self, item): try: - n = self.get_node(item) - - if n["ID"] == item: - return n - if n["Name"] == item: - return n - else: - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: + node = self.get_node(item) + + if node["ID"] == item: + return node + if node["Name"] == item: + return node + raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc - def get_node(self, id): + def get_node(self, _id): """ Query the status of a client node registered with Nomad. https://www.nomadproject.io/docs/http/node.html @@ -58,9 +59,9 @@ def get_node(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, method="get").json() + return self.request(_id, method="get").json() - def get_allocations(self, id): + def get_allocations(self, _id): """ Query the allocations belonging to a single node. https://www.nomadproject.io/docs/http/node.html @@ -70,11 +71,11 @@ def get_allocations(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "allocations", method="get").json() + return self.request(_id, "allocations", method="get").json() - def evaluate_node(self, id): + def evaluate_node(self, _id): """ Creates a new evaluation for the given node. - This can be used to force run the + This can be used to force run the scheduling logic if necessary. https://www.nomadproject.io/docs/http/node.html @@ -84,9 +85,9 @@ def evaluate_node(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "evaluate", method="post").json() + return self.request(_id, "evaluate", method="post").json() - def drain_node(self, id, enable=False): + def drain_node(self, _id, enable=False): """ Toggle the drain mode of the node. When enabled, no further allocations will be assigned and existing allocations will be migrated. @@ -94,7 +95,7 @@ def drain_node(self, id, enable=False): https://www.nomadproject.io/docs/http/node.html arguments: - - id (str uuid): node id + - _id (str uuid): node id - enable (bool): enable node drain or not to enable node drain returns: dict raises: @@ -102,9 +103,9 @@ def drain_node(self, id, enable=False): - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "drain", params={"enable": enable}, method="post").json() + return self.request(_id, "drain", params={"enable": enable}, method="post").json() - def drain_node_with_spec(self, id, drain_spec, mark_eligible=None): + def drain_node_with_spec(self, _id, drain_spec, mark_eligible=None): """ This endpoint toggles the drain mode of the node. When draining is enabled, no further allocations will be assigned to this node, and existing allocations will be migrated to new nodes. @@ -114,7 +115,7 @@ def drain_node_with_spec(self, id, drain_spec, mark_eligible=None): https://www.nomadproject.io/docs/http/node.html arguments: - - id (str uuid): node id + - _id (str uuid): node id - drain_spec (dict): https://www.nomadproject.io/api/nodes.html#drainspec - mark_eligible (bool): https://www.nomadproject.io/api/nodes.html#markeligible returns: dict @@ -126,36 +127,36 @@ def drain_node_with_spec(self, id, drain_spec, mark_eligible=None): if drain_spec and mark_eligible is not None: payload = { - "NodeID": id, + "NodeID": _id, "DrainSpec": drain_spec, "MarkEligible": mark_eligible } elif drain_spec and mark_eligible is None: payload = { - "NodeID": id, + "NodeID": _id, "DrainSpec": drain_spec } elif not drain_spec and mark_eligible is not None: payload = { - "NodeID": id, + "NodeID": _id, "DrainSpec": None, "MarkEligible": mark_eligible } elif not drain_spec and mark_eligible is None: payload = { - "NodeID": id, + "NodeID": _id, "DrainSpec": None, } - return self.request(id, "drain", json=payload, method="post").json() + return self.request(_id, "drain", json=payload, method="post").json() - def eligible_node(self, id, eligible=None, ineligible=None): + def eligible_node(self, _id, eligible=None, ineligible=None): """ Toggle the eligibility of the node. https://www.nomadproject.io/docs/http/node.html arguments: - - id (str uuid): node id + - _id (str uuid): node id - eligible (bool): Set to True to mark node eligible - ineligible (bool): Set to True to mark node ineligible returns: dict @@ -171,25 +172,24 @@ def eligible_node(self, id, eligible=None, ineligible=None): raise nomad.api.exceptions.InvalidParameters if eligible is not None and eligible: - payload = {"Eligibility": "eligible", "NodeID": id} + payload = {"Eligibility": "eligible", "NodeID": _id} elif eligible is not None and not eligible: - payload = {"Eligibility": "ineligible", "NodeID": id} + payload = {"Eligibility": "ineligible", "NodeID": _id} elif ineligible is not None: - payload = {"Eligibility": "ineligible", "NodeID": id} + payload = {"Eligibility": "ineligible", "NodeID": _id} elif ineligible is not None and not ineligible: - payload = {"Eligibility": "eligible", "NodeID": id} + payload = {"Eligibility": "eligible", "NodeID": _id} - return self.request(id, "eligibility", json=payload, method="post").json() + return self.request(_id, "eligibility", json=payload, method="post").json() - def purge_node(self, id): + def purge_node(self, _id): """ This endpoint purges a node from the system. Nodes can still join the cluster if they are alive. arguments: - - id (str uuid): node id + - _id (str uuid): node id returns: dict raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(id, "purge", method="post").json() - + return self.request(_id, "purge", method="post").json() diff --git a/nomad/api/nodes.py b/nomad/api/nodes.py index 30dd1b0..5c4def0 100644 --- a/nomad/api/nodes.py +++ b/nomad/api/nodes.py @@ -1,3 +1,4 @@ +"""Nomad Node: https://developer.hashicorp.com/nomad/api-docs/nodes""" import nomad.api.exceptions from nomad.api.base import Requester @@ -14,28 +15,28 @@ class Nodes(Requester): ENDPOINT = "nodes" def __init__(self, **kwargs): - super(Nodes, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def __contains__(self, item): try: nodes = self.get_nodes() - for n in nodes: - if n["ID"] == item: + for node in nodes: + if node["ID"] == item: return True - if n["Name"] == item: + if node["Name"] == item: return True - else: - return False + return False except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -47,15 +48,14 @@ def __getitem__(self, item): try: nodes = self.get_nodes() - for n in nodes: - if n["ID"] == item: - return n - if n["Name"] == item: - return n - else: - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: + for node in nodes: + if node["ID"] == item: + return node + if node["Name"] == item: + return node raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc def __iter__(self): nodes = self.get_nodes() diff --git a/nomad/api/operator.py b/nomad/api/operator.py index 52cef1f..b301c18 100644 --- a/nomad/api/operator.py +++ b/nomad/api/operator.py @@ -1,3 +1,4 @@ +"""Nomad Operator: https://developer.hashicorp.com/nomad/api-docs/operator""" from nomad.api.base import Requester @@ -13,16 +14,17 @@ class Operator(Requester): ENDPOINT = "operator" def __init__(self, **kwargs): - super(Operator, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def get_configuration(self, stale=False): """ Query the status of a client node registered with Nomad. diff --git a/nomad/api/regions.py b/nomad/api/regions.py index 49bc765..76b5038 100644 --- a/nomad/api/regions.py +++ b/nomad/api/regions.py @@ -1,3 +1,4 @@ +"""Nomad region: https://developer.hashicorp.com/nomad/api-docs/regions""" import nomad.api.exceptions from nomad.api.base import Requester @@ -11,26 +12,26 @@ class Regions(Requester): ENDPOINT = "regions" def __init__(self, **kwargs): - super(Regions, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def __contains__(self, item): try: regions = self.get_regions() - for r in regions: - if r == item: + for region in regions: + if region == item: return True - else: - return False + return False except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -42,13 +43,12 @@ def __getitem__(self, item): try: regions = self.get_regions() - for r in regions: - if r == item: - return r - else: - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: + for region in regions: + if region == item: + return region raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc def __iter__(self): regions = self.get_regions() diff --git a/nomad/api/scaling.py b/nomad/api/scaling.py index 56776a2..850c76b 100644 --- a/nomad/api/scaling.py +++ b/nomad/api/scaling.py @@ -1,3 +1,4 @@ +"""Nomad Scalling API: https://developer.hashicorp.com/nomad/api-docs/scaling-policies""" import nomad.api.exceptions from nomad.api.base import Requester @@ -12,18 +13,20 @@ class Scaling(Requester): ENDPOINT = "scaling" def __init__(self, **kwargs): - super(Scaling, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) - def get_scaling_policies(self, job="", type=""): + # we want to have common arguments name with Nomad API + def get_scaling_policies(self, job="", type=""): # pylint: disable=redefined-builtin """ This endpoint returns the scaling policies from all jobs. @@ -46,23 +49,23 @@ def get_scaling_policies(self, job="", type=""): if type not in type_of_scaling_policies: raise nomad.api.exceptions.InvalidParameters("type is invalid " - "(expected values are {} but got {})".format(type_of_scaling_policies, type)) + f"(expected values are {type_of_scaling_policies} but got {type})") params = {"job": job, "type": type} return self.request("policies", method="get", params=params).json() - def get_scaling_policy(self, id): + def get_scaling_policy(self, _id): """ This endpoint reads a specific scaling policy. https://developer.hashicorp.com/nomad/api-docs/scaling-policies#read-scaling-policy arguments: - - id + - _id returns: list of dicts raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("policy/{}".format(id), method="get").json() + return self.request(f"policy/{_id}", method="get").json() diff --git a/nomad/api/search.py b/nomad/api/search.py index 66e4dc9..af8c3bf 100644 --- a/nomad/api/search.py +++ b/nomad/api/search.py @@ -1,3 +1,4 @@ +"""Nomad Search API: https://developer.hashicorp.com/nomad/api-docs/search""" import nomad.api.exceptions from nomad.api.base import Requester @@ -15,16 +16,17 @@ class Search(Requester): ENDPOINT = "search" def __init__(self, **kwargs): - super(Search, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def search(self, prefix, context): """ The endpoint returns matches for a given prefix and context, where a context can be jobs, @@ -46,14 +48,14 @@ def search(self, prefix, context): accetaple_contexts = ("jobs", "evals", "allocs", "nodes", "deployment", "plugins", "volumes", "all") if context not in accetaple_contexts: raise nomad.api.exceptions.InvalidParameters("context is invalid " - "(expected values are {} but got {})".format(accetaple_contexts, context)) + f"(expected values are {accetaple_contexts} but got {context})") params = {"Prefix": prefix, "Context": context} return self.request(json=params, method="post").json() def fuzzy_search(self, text, context): """ The /search/fuzzy endpoint returns partial substring matches for a given search term and context, - where a context can be jobs, allocations, nodes, plugins, or namespaces. Additionally, + where a context can be jobs, allocations, nodes, plugins, or namespaces. Additionally, fuzzy searching can be done across all contexts. https://developer.hashicorp.com/nomad/api-docs/search#fuzzy-searching @@ -78,6 +80,6 @@ def fuzzy_search(self, text, context): accetaple_contexts = ("jobs", "allocs", "nodes", "plugins", "all") if context not in accetaple_contexts: raise nomad.api.exceptions.InvalidParameters("context is invalid " - "(expected values are {} but got {})".format(accetaple_contexts,context)) + f"(expected values are {accetaple_contexts} but got {context})") return self.request("fuzzy", json=params, method="post").json() diff --git a/nomad/api/sentinel.py b/nomad/api/sentinel.py index 29d91a4..ba0d49b 100644 --- a/nomad/api/sentinel.py +++ b/nomad/api/sentinel.py @@ -1,3 +1,4 @@ +"""Nomad Sentinel API: https://developer.hashicorp.com/nomad/api-docs/sentinel-policies""" from nomad.api.base import Requester @@ -12,16 +13,17 @@ class Sentinel(Requester): ENDPOINT = "sentinel" def __init__(self, **kwargs): - super(Sentinel, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def get_policies(self): """ Get a list of policies. @@ -36,7 +38,7 @@ def get_policies(self): """ return self.request("policies", method="get").json() - def create_policy(self, id, policy): + def create_policy(self, _id, policy): """ Create policy. https://www.nomadproject.io/api/sentinel-policies.html @@ -49,9 +51,9 @@ def create_policy(self, id, policy): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("policy", id, json=policy, method="post") + return self.request("policy", _id, json=policy, method="post") - def get_policy(self, id): + def get_policy(self, _id): """ Get a spacific policy. https://www.nomadproject.io/api/sentinel-policies.html @@ -62,9 +64,9 @@ def get_policy(self, id): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("policy", id, method="get").json() + return self.request("policy", _id, method="get").json() - def update_policy(self, id, policy): + def update_policy(self, _id, policy): """ Create policy. https://www.nomadproject.io/api/sentinel-policies.html @@ -78,19 +80,19 @@ def update_policy(self, id, policy): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("policy", id, json=policy, method="post") + return self.request("policy", _id, json=policy, method="post") - def delete_policy(self, id): + def delete_policy(self, _id): """ Delete specific policy. https://www.nomadproject.io/api/sentinel-policies.html arguments: - - id + - _id returns: Boolean raises: - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request("policy", id, method="delete").ok + return self.request("policy", _id, method="delete").ok diff --git a/nomad/api/status.py b/nomad/api/status.py index ba598e0..3e33501 100644 --- a/nomad/api/status.py +++ b/nomad/api/status.py @@ -1,9 +1,10 @@ +"""Nomad Status API: https://developer.hashicorp.com/nomad/api-docs/status""" import nomad.api.exceptions from nomad.api.base import Requester -class Status(object): +class Status(): """ By default, the agent's local region is used @@ -16,16 +17,18 @@ def __init__(self, **kwargs): self.peers = Peers(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) class Leader(Requester): + """This endpoint returns the address of the current leader in the region.""" ENDPOINT = "status/leader" @@ -35,8 +38,8 @@ def __contains__(self, item): if leader == item: return True - else: - return False + + return False except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -58,6 +61,7 @@ def get_leader(self): class Peers(Requester): + """This endpoint returns the set of raft peers in the region.""" ENDPOINT = "status/peers" @@ -65,11 +69,10 @@ def __contains__(self, item): try: peers = self.get_peers() - for p in peers: - if p == item: + for peer in peers: + if peer == item: return True - else: - return False + return False except nomad.api.exceptions.URLNotFoundNomadException: return False @@ -81,13 +84,12 @@ def __getitem__(self, item): try: peers = self.get_peers() - for p in peers: - if p == item: - return p - else: - raise KeyError - except nomad.api.exceptions.URLNotFoundNomadException: + for peer in peers: + if peer == item: + return peer raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc def __iter__(self): peers = self.get_peers() diff --git a/nomad/api/system.py b/nomad/api/system.py index 923d587..8437821 100644 --- a/nomad/api/system.py +++ b/nomad/api/system.py @@ -1,3 +1,4 @@ +"""Nomad System API: https://developer.hashicorp.com/nomad/api-docs/system""" from nomad.api.base import Requester @@ -14,16 +15,17 @@ class System(Requester): ENDPOINT = "system" def __init__(self, **kwargs): - super(System, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def initiate_garbage_collection(self): """ Initiate garbage collection of jobs, evals, allocations and nodes. diff --git a/nomad/api/validate.py b/nomad/api/validate.py index a0c3d7d..f0ba03a 100644 --- a/nomad/api/validate.py +++ b/nomad/api/validate.py @@ -1,3 +1,4 @@ +"""Nomad Validate API: https://developer.hashicorp.com/nomad/api-docs/validate""" from nomad.api.base import Requester @@ -14,16 +15,17 @@ class Validate(Requester): ENDPOINT = "validate" def __init__(self, **kwargs): - super(Validate, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def validate_job(self, nomad_job_dict): """ This endpoint validates a Nomad job file. The local Nomad agent forwards the request to a server. diff --git a/nomad/api/variable.py b/nomad/api/variable.py index 434d543..2ff23a0 100644 --- a/nomad/api/variable.py +++ b/nomad/api/variable.py @@ -1,3 +1,4 @@ +"""Nomad Valiables API: https://developer.hashicorp.com/nomad/api-docs/variables""" import nomad.api.exceptions from nomad.api.base import Requester @@ -13,16 +14,17 @@ class Variable(Requester): ENDPOINT = "var" def __init__(self, **kwargs): - super(Variable, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def __contains__(self, item): try: @@ -34,8 +36,8 @@ def __contains__(self, item): def __getitem__(self, item): try: return self.get_variable(item) - except nomad.api.exceptions.URLNotFoundNomadException: - raise KeyError + except nomad.api.exceptions.URLNotFoundNomadException as exc: + raise KeyError from exc def get_variable(self, var_path, namespace=None): """ @@ -92,7 +94,7 @@ def delete_variable(self, var_path, namespace=None, cas=None): - var_path :(str), path to variable - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. This is specified as a querystring parameter. - - cas :(int) optional, If set, the variable will only be deleted if the cas value matches the + - cas :(int) optional, If set, the variable will only be deleted if the cas value matches the current variables ModifyIndex. returns: dict raises: diff --git a/nomad/api/variables.py b/nomad/api/variables.py index 75338ec..c9d8928 100644 --- a/nomad/api/variables.py +++ b/nomad/api/variables.py @@ -1,5 +1,4 @@ -import nomad.api.exceptions - +"""Nomad Valiables API: https://developer.hashicorp.com/nomad/api-docs/variables""" from nomad.api.base import Requester @@ -13,16 +12,17 @@ class Variables(Requester): ENDPOINT = "vars" def __init__(self, **kwargs): - super(Variables, self).__init__(**kwargs) + super().__init__(**kwargs) def __str__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __repr__(self): - return "{0}".format(self.__dict__) + return f"{self.__dict__}" def __getattr__(self, item): - raise AttributeError + msg = f"{item} does not exist" + raise AttributeError(msg) def __contains__(self, item): variables = self.get_variables() @@ -30,8 +30,7 @@ def __contains__(self, item): for var in variables: if var["Path"] == item: return True - else: - return False + return False def __getitem__(self, item): variables = self.get_variables() @@ -39,15 +38,14 @@ def __getitem__(self, item): for var in variables: if var["Path"] == item: return var - else: - raise KeyError + raise KeyError def __iter__(self): variables = self.get_variables() return iter(variables) def get_variables(self, prefix="", namespace=None): - """ + """ This endpoint lists variables. https://developer.hashicorp.com/nomad/api-docs/variables @@ -66,5 +64,3 @@ def get_variables(self, prefix="", namespace=None): params["namespace"] = namespace return self.request(params=params, method="get").json() - - diff --git a/requirements-dev.txt b/requirements-dev.txt index 6c4caad..6e3596d 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,4 +4,4 @@ pytest-cov==4.0.0 mkdocs==1.4.2 mock==4.0.3 flaky==3.7.0 -responses==0.22.0 +responses==0.22.0 \ No newline at end of file diff --git a/setup.py b/setup.py index 1d2e987..5fddd91 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ +"""Nomad Python Library""" import setuptools -with open("README.md", "r") as fh: +with open("README.md", "r", encoding='utf-8') as fh: long_description = fh.read() setuptools.setup( diff --git a/tests/test_acl.py b/tests/test_acl.py index ec7c151..d7936fc 100644 --- a/tests/test_acl.py +++ b/tests/test_acl.py @@ -46,7 +46,7 @@ def test_update_token(nomad_setup): token_update ='{"AccessorID":"' + created_token["AccessorID"] + '","Name": "Updated" ,"Type": "client","Policies": ["readonly"]}' json_token_update = json.loads(token_update) - update_token = nomad_setup.acl.update_token(id=created_token["AccessorID"],token=json_token_update) + update_token = nomad_setup.acl.update_token(_id=created_token["AccessorID"],token=json_token_update) assert "Updated" in update_token["Name"] @@ -89,7 +89,7 @@ def test_get_policies(nomad_setup): def test_create_policy(nomad_setup): policy_example = '{ "Name": "my-policy", "Description": "This is a great policy", "Rules": "" }' json_policy = json.loads(policy_example) - nomad_setup.acl.create_policy(id="my-policy", policy=json_policy) + nomad_setup.acl.create_policy(_id="my-policy", policy=json_policy) assert False == any("my-policy" in x for x in nomad_setup.acl.get_policies()) @@ -103,11 +103,11 @@ def test_get_policy(nomad_setup): def test_update_policy(nomad_setup): policy_update = '{"Name": "my-policy","Description": "Updated","Rules": ""}' json_policy_update = json.loads(policy_update) - nomad_setup.acl.update_policy(id="my-policy", policy=json_policy_update) + nomad_setup.acl.update_policy(_id="my-policy", policy=json_policy_update) assert False == any("Updated" in x for x in nomad_setup.acl.get_policies()) @pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") def test_delete_policy(nomad_setup): - nomad_setup.acl.delete_policy(id="my-policy") + nomad_setup.acl.delete_policy(_id="my-policy") assert False == any("my-policy" in x for x in nomad_setup.acl.get_policies()) diff --git a/tests/test_job.py b/tests/test_job.py index a5019e1..992f327 100644 --- a/tests/test_job.py +++ b/tests/test_job.py @@ -36,7 +36,7 @@ def test_get_jobs_with_namespace_override_no_namespace_declared_on_create_incorr ) with pytest.raises(exceptions.BaseNomadException): - nomad_setup.job.get_job(id=str(uuid.uuid4())) + nomad_setup.job.get_job(_id=str(uuid.uuid4())) @responses.activate @@ -48,7 +48,7 @@ def test_get_jobs_with_namespace_override_no_namespace_declared_on_create(nomad_ json=[{"Region": "global","ID": "my-job", "ParentID": "", "Name": "my-job","Namespace": common.NOMAD_NAMESPACE, "Type": "batch", "Priority": 50}] ) - nomad_setup.job.get_job(id="18a0f501-41d5-ae43-ff61-1d8ec3ec8314", namespace=common.NOMAD_NAMESPACE) + nomad_setup.job.get_job(_id="18a0f501-41d5-ae43-ff61-1d8ec3ec8314", namespace=common.NOMAD_NAMESPACE) @responses.activate @@ -60,7 +60,7 @@ def test_get_jobs_with_namespace_override_namespace_declared_on_create(nomad_set json=[{"Region": "global","ID": "my-job", "ParentID": "", "Name": "my-job","Namespace": common.NOMAD_NAMESPACE, "Type": "batch", "Priority": 50}] ) - nomad_setup_with_namespace.job.get_job(id="18a0f501-41d5-ae43-ff61-1d8ec3ec8314", namespace="override-namespace") + nomad_setup_with_namespace.job.get_job(_id="18a0f501-41d5-ae43-ff61-1d8ec3ec8314", namespace="override-namespace") def test_get_allocations(nomad_setup): @@ -137,7 +137,7 @@ def test_get_job_deployment(nomad_setup): assert "example" == nomad_setup.job.get_deployment("example")["JobID"] @pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in version") -def test_get_job_deployment(nomad_setup): +def test_get_summary(nomad_setup): assert "JobID" in nomad_setup.job.get_summary("example") assert isinstance(nomad_setup.job.get_summary("example"), dict) assert "example" == nomad_setup.job.get_summary("example")["JobID"] @@ -148,11 +148,6 @@ def test_revert_job(nomad_setup): prior_job_version = current_job_version - 1 nomad_setup.job.revert_job("example", prior_job_version, current_job_version) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in version") -def test_revert_job(nomad_setup): - current_job_version = nomad_setup.job.get_deployment("example")["JobVersion"] - prior_job_version = current_job_version - 1 - nomad_setup.job.revert_job("example", prior_job_version, current_job_version) @pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in version") def test_stable_job(nomad_setup): diff --git a/tests/test_sentinel.py b/tests/test_sentinel.py index 46dc07a..5d26057 100644 --- a/tests/test_sentinel.py +++ b/tests/test_sentinel.py @@ -40,7 +40,7 @@ def test_create_policy(nomad_setup): policy_example = '{"Name": "my-policy", "Description": "This is a great policy", "Scope": "submit-job", "EnforcementLevel": "advisory", "Policy": "main = rule { true }"}' json_policy = json.loads(policy_example) - nomad_setup.sentinel.create_policy(id="my-policy", policy=json_policy) + nomad_setup.sentinel.create_policy(_id="my-policy", policy=json_policy) @responses.activate @@ -48,13 +48,13 @@ def test_update_policy(nomad_setup): responses.add( responses.POST, - "http://{ip}:{port}/v1/sentinel/policy/my-policy".format(ip=common.IP, port=common.NOMAD_PORT), + f"http://{common.IP}:{common.NOMAD_PORT}/v1/sentinel/policy/my-policy", status=200 ) policy_example = '{"Name": "my-policy", "Description": "Update", "Scope": "submit-job", "EnforcementLevel": "advisory", "Policy": "main = rule { true }"}' json_policy = json.loads(policy_example) - nomad_setup.sentinel.update_policy(id="my-policy", policy=json_policy) + nomad_setup.sentinel.update_policy(_id="my-policy", policy=json_policy) @responses.activate @@ -97,4 +97,4 @@ def test_delete_policy(nomad_setup): } ) - nomad_setup.sentinel.delete_policy(id="my-policy") + nomad_setup.sentinel.delete_policy(_id="my-policy")