From 490b1489f698dd7860804c77b13fe1b6a4bafee9 Mon Sep 17 00:00:00 2001 From: Nikita Beletskii <2nikita.b@gmail.com> Date: Tue, 6 Dec 2022 16:16:25 +0100 Subject: [PATCH 01/12] Remove support for Python 2, Python 3.6 and upgrade deps (#142) --- .github/workflows/main.yml | 11 +++-------- CHANGELOG.md | 4 ++++ mkdocs.yml | 2 ++ requirements-dev-py27.txt | 7 ------- requirements-dev.txt | 12 ++++++------ requirements.txt | 2 +- setup.py | 2 -- 7 files changed, 16 insertions(+), 24 deletions(-) delete mode 100644 requirements-dev-py27.txt diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 99f5e25..59d98e2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,13 +20,12 @@ jobs: env: NOMAD_IP: '127.0.0.1' NOMAD_PORT: '4646' - NOMAD_LATEST: '1.1.18' strategy: fail-fast: false matrix: - python-version: ['2.7', '3.7', '3.10'] - nomad-version: ['1.0.18', '1.1.18', '1.2.14', '1.3.7', '1.4.2'] + python-version: ['3.7', '3.11'] # the oldest and newest support versions + nomad-version: ['1.0.18', '1.1.18', '1.2.15', '1.3.8', '1.4.3'] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} @@ -57,11 +56,7 @@ jobs: run: | python -m pip install --upgrade pip if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - if [ $PYTHON_VERSION = "2.7" ]; then - pip install -r requirements-dev-py27.txt - else - pip install -r requirements-dev.txt - fi + pip install -r requirements-dev.txt - name: Before Tests shell: bash run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c89101..94d2a63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.0 (unreleased) +* Up `requests` lib version to 2.28.1 +* Drop Python 2 and Python 3.6 support + ## 1.5.0 * Add `namespace` agrument support for `get_allocations` and `get_deployments` endpoints (#133) * Add Python 3.10 support (#133) diff --git a/mkdocs.yml b/mkdocs.yml index 4119c91..7f7575b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -29,5 +29,7 @@ pages: - Namespace: 'api/namespace.md' - Namespaces: 'api/namespaces.md' - Sentinel: 'api/sentinel.md' + - Variable: 'api/variable.md' + - Variables: 'api/variables.md' - Validate: 'api/validate.md' - Contributing: 'CONTRIBUTING.md' diff --git a/requirements-dev-py27.txt b/requirements-dev-py27.txt deleted file mode 100644 index 21de22f..0000000 --- a/requirements-dev-py27.txt +++ /dev/null @@ -1,7 +0,0 @@ -coverage==5.2.1 -pytest==4.6.11 -pytest-cov==2.12.1 -mkdocs==1.0.4 -mock==1.2.0 -flaky==3.7.0 -responses==0.13.4 diff --git a/requirements-dev.txt b/requirements-dev.txt index eac8c93..6c4caad 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,7 @@ -coverage==5.2.1 -pytest==6.2.4 -pytest-cov==2.12.1 -mkdocs==1.2.3 -mock==1.2.0 +coverage==6.5.0 +pytest==7.2.0 +pytest-cov==4.0.0 +mkdocs==1.4.2 +mock==4.0.3 flaky==3.7.0 -responses==0.13.4 +responses==0.22.0 diff --git a/requirements.txt b/requirements.txt index a743bbe..d15ce5a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -requests==2.27.1 +requests==2.28.1 diff --git a/setup.py b/setup.py index 76f9e97..1d2e987 100644 --- a/setup.py +++ b/setup.py @@ -19,8 +19,6 @@ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', From 78452b63e19e9c292752386262534ed14a5c0e18 Mon Sep 17 00:00:00 2001 From: Nikita Beletskii <2nikita.b@gmail.com> Date: Thu, 22 Dec 2022 17:09:06 +0100 Subject: [PATCH 02/12] Add pylint (#143) * add pylint check to repo --- .github/workflows/lint.yml | 31 ++++++++++ .github/workflows/main.yml | 3 - .pylintrc | 6 ++ CHANGELOG.md | 5 +- CONTRIBUTING.md | 6 +- nomad/__init__.py | 105 +++++++++++++++++++++++++++++-- nomad/api/__init__.py | 3 +- nomad/api/acl.py | 36 +++++------ nomad/api/agent.py | 11 ++-- nomad/api/allocation.py | 19 +++--- nomad/api/allocations.py | 8 +-- nomad/api/base.py | 108 ++++++++++++++++++++------------ nomad/api/client.py | 119 ++++++++++++++++++----------------- nomad/api/deployment.py | 87 ++++++++++++++------------ nomad/api/deployments.py | 28 ++++----- nomad/api/evaluation.py | 34 +++++----- nomad/api/evaluations.py | 26 ++++---- nomad/api/event.py | 32 +++++----- nomad/api/exceptions.py | 7 ++- nomad/api/job.py | 124 ++++++++++++++++++------------------- nomad/api/jobs.py | 21 ++++--- nomad/api/metrics.py | 10 +-- nomad/api/namespace.py | 47 +++++++------- nomad/api/namespaces.py | 27 ++++---- nomad/api/node.py | 84 ++++++++++++------------- nomad/api/nodes.py | 34 +++++----- nomad/api/operator.py | 10 +-- nomad/api/regions.py | 28 ++++----- nomad/api/scaling.py | 21 ++++--- nomad/api/search.py | 16 ++--- nomad/api/sentinel.py | 28 +++++---- nomad/api/status.py | 34 +++++----- nomad/api/system.py | 10 +-- nomad/api/validate.py | 10 +-- nomad/api/variable.py | 16 ++--- nomad/api/variables.py | 22 +++---- requirements-dev.txt | 2 +- setup.py | 3 +- tests/test_acl.py | 8 +-- tests/test_job.py | 13 ++-- tests/test_sentinel.py | 8 +-- 41 files changed, 717 insertions(+), 533 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .pylintrc 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") From fb8afc229cdf51f8b94d576d2b10d5cf080c9ba9 Mon Sep 17 00:00:00 2001 From: KamilCuk Date: Mon, 16 Jan 2023 16:12:34 +0100 Subject: [PATCH 03/12] Add missing parameters, do not pass None (#144) * jobs: add additional parameters for job listing * allocations: add additional parameters to get_allocations * api/base: omit exception, check explicitly * api/base: cleanup parameters that are none * allocations,jobs: Add trailing underscore to filter not to conflict with builtin filter function Co-authored-by: Kamil Cukrowski --- nomad/api/allocations.py | 51 ++++++++++++++++++++++++++-------------- nomad/api/base.py | 7 ++++-- nomad/api/jobs.py | 47 ++++++++++++++++++++++-------------- 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/nomad/api/allocations.py b/nomad/api/allocations.py index a89e407..edd6229 100644 --- a/nomad/api/allocations.py +++ b/nomad/api/allocations.py @@ -1,4 +1,6 @@ """Nomad allocation: https://developer.hashicorp.com/nomad/api-docs/allocations""" +from typing import Optional + from nomad.api.base import Requester @@ -10,6 +12,7 @@ class Allocations(Requester): https://www.nomadproject.io/docs/http/allocs.html """ + ENDPOINT = "allocations" def __init__(self, **kwargs): @@ -32,22 +35,36 @@ def __iter__(self): response = self.get_allocations() return iter(response) - def get_allocations(self, prefix=None, namespace=None): - """ Lists all the allocations. - - https://www.nomadproject.io/docs/http/allocs.html - arguments: - - prefix :(str) optional, specifies a string to filter allocations on based on an prefix. - This is specified as a querystring parameter. - - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. - This is specified as a querystring parameter. - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException - """ - params = {"prefix": prefix} - if namespace: - params["namespace"] = namespace + def get_allocations( # pylint: disable=too-many-arguments + self, + prefix: Optional[str] = None, + filter_: Optional[str] = None, + namespace: Optional[str] = None, + resources: Optional[bool] = None, + task_states: Optional[bool] = None, + ): + """Lists all the allocations. + https://www.nomadproject.io/docs/http/allocs.html + arguments: + - prefix :(str) optional, specifies a string to filter allocations on based on an prefix. + This is specified as a querystring parameter. + - filter_ :(str) optional + Name has a trailing underscore not to conflict with builtin function. + - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. + This is specified as a querystring parameter. + - resources :(bool) optional + - task_states :(bool) optional + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException + """ + params = { + "prefix": prefix, + "filter": filter_, + "namespace": namespace, + "resources": resources, + "task_states": task_states, + } return self.request(method="get", params=params).json() diff --git a/nomad/api/base.py b/nomad/api/base.py index 3fd3975..22f6e3a 100644 --- a/nomad/api/base.py +++ b/nomad/api/base.py @@ -84,6 +84,9 @@ def _query_string_builder(self, endpoint, params=None): if not isinstance(params, dict): params = {} + # Remove parameters that are None + params = {key: val for key, val in params.items() if val is not None} + if ("namespace" not in params) and (self.namespace and self._required_namespace(endpoint)): query_string["namespace"] = self.namespace @@ -132,9 +135,9 @@ def _request( # pylint: disable=too-many-arguments, too-many-branches params = query_string if self.token: - try: + if headers is not None: headers["X-Nomad-Token"] = self.token - except TypeError: + else: headers = {"X-Nomad-Token": self.token} response = None diff --git a/nomad/api/jobs.py b/nomad/api/jobs.py index 98fa2b4..3d8793b 100644 --- a/nomad/api/jobs.py +++ b/nomad/api/jobs.py @@ -1,4 +1,5 @@ """Nomad job: https://developer.hashicorp.com/nomad/api-docs/jobs""" +from typing import Optional import nomad.api.exceptions from nomad.api.base import Requester @@ -62,24 +63,36 @@ def __iter__(self): jobs = self.get_jobs() return iter(jobs) - def get_jobs(self, prefix=None, namespace=None): - """ Lists all the jobs registered with Nomad. - - https://www.nomadproject.io/docs/http/jobs.html - arguments: - - prefix :(str) optional, specifies a string to filter jobs on based on an prefix. - This is specified as a querystring parameter. - - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. - This is specified as a querystring parameter. - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + def get_jobs( + self, + prefix: Optional[str] = None, + namespace: Optional[str] = None, + filter_: Optional[str] = None, + meta: Optional[bool] = None, + ): + """Lists all the jobs registered with Nomad. + + https://www.nomadproject.io/docs/http/jobs.html + arguments: + - prefix :(str) optional, specifies a string to filter jobs on based on an prefix. + This is specified as a querystring parameter. + - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. + This is specified as a querystring parameter. + - filter_ :(str) optional, specifies the expression used to filter the result. + Name has a trailing underscore not to conflict with builtin function. + - meta :(bool) optional, if set, jobs returned will include a meta field containing + key-value pairs provided in the job specification's meta block. + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ - params = {"prefix": prefix} - if namespace: - params["namespace"] = namespace - + params = { + "prefix": prefix, + "namespace": namespace, + "filter": filter_, + "meta": meta, + } return self.request(method="get", params=params).json() def register_job(self, job): From 94225917ef99d14a23f952f11b43edb2063cc520 Mon Sep 17 00:00:00 2001 From: Nikita Beletskii <2nikita.b@gmail.com> Date: Tue, 31 Jan 2023 12:24:32 +0100 Subject: [PATCH 04/12] Add code formatter and change _id to id_ (#146) * replace _id to id_ * add black to format files * change changelog * fix linter * add missing record to CHANGELOG.md --- .github/workflows/lint.yml | 3 +- CHANGELOG.md | 4 +- nomad/__init__.py | 87 ++++---- nomad/api/acl.py | 196 +++++++++--------- nomad/api/agent.py | 68 +++---- nomad/api/allocation.py | 32 +-- nomad/api/allocations.py | 26 +-- nomad/api/base.py | 6 +- nomad/api/client.py | 268 ++++++++++++------------- nomad/api/deployment.py | 210 ++++++++++---------- nomad/api/deployments.py | 24 +-- nomad/api/evaluation.py | 42 ++-- nomad/api/evaluations.py | 23 +-- nomad/api/event.py | 13 +- nomad/api/exceptions.py | 1 + nomad/api/job.py | 395 ++++++++++++++++++------------------- nomad/api/jobs.py | 54 ++--- nomad/api/metrics.py | 14 +- nomad/api/namespace.py | 82 ++++---- nomad/api/namespaces.py | 22 +-- nomad/api/node.py | 175 ++++++++-------- nomad/api/nodes.py | 22 +-- nomad/api/operator.py | 47 +++-- nomad/api/regions.py | 14 +- nomad/api/scaling.py | 32 +-- nomad/api/search.py | 79 ++++---- nomad/api/sentinel.py | 91 +++++---- nomad/api/status.py | 27 ++- nomad/api/system.py | 25 ++- nomad/api/validate.py | 16 +- nomad/api/variable.py | 42 ++-- nomad/api/variables.py | 13 +- requirements-lint.txt | 2 + tests/conftest.py | 6 +- tests/test_acl.py | 75 ++++--- tests/test_allocation.py | 24 ++- tests/test_allocations.py | 39 +++- tests/test_base.py | 70 ++++--- tests/test_client.py | 26 ++- tests/test_deployment.py | 69 +++++-- tests/test_deployments.py | 50 ++++- tests/test_evaluation.py | 3 +- tests/test_evaluations.py | 2 +- tests/test_event.py | 8 +- tests/test_job.py | 110 ++++++++--- tests/test_jobs.py | 72 +++++-- tests/test_metrics.py | 6 +- tests/test_namespace.py | 11 +- tests/test_namespaces.py | 57 ++---- tests/test_node.py | 12 +- tests/test_nodes.py | 2 +- tests/test_operator.py | 12 +- tests/test_regions.py | 2 +- tests/test_scaling.py | 2 + tests/test_search.py | 34 +++- tests/test_sentinel.py | 26 ++- tests/test_status.py | 11 +- tests/test_validate.py | 8 +- tests/test_variable.py | 80 ++++++-- tests/test_variables.py | 64 ++++-- 60 files changed, 1698 insertions(+), 1338 deletions(-) create mode 100644 requirements-lint.txt diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 218d60e..095b56c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,8 +24,9 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements.txt - pip install pylint==2.15.8 + pip install -r requirements-lint.txt - name: Lint shell: bash run: | pylint nomad/ + black --check -l 120 -t py311 nomad/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 4431209..831e35f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,11 @@ ## 2.0.0 (unreleased) ### BREAKING CHANGES * Drop Python 2 and Python 3.6 support -* Rename `id` arguments to `_id` across of code base +* Rename `id` arguments to `id_` across of code base +* Rename `type` arguments to `type_` across of code base ### Other changes * Up `requests` lib version to 2.28.1 +* Add migging parameters to allocations.get_allocations and jobs.get_jobs (#144). Thanks @Kamilcuk ## 1.5.0 * Add `namespace` agrument support for `get_allocations` and `get_deployments` endpoints (#133) diff --git a/nomad/__init__.py b/nomad/__init__.py index be2be26..0ad41b9 100644 --- a/nomad/__init__.py +++ b/nomad/__init__.py @@ -3,51 +3,54 @@ from nomad import api -class Nomad(): # pylint: disable=too-many-public-methods,too-many-instance-attributes + +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, - address=os.getenv('NOMAD_ADDR', None), - namespace=os.getenv('NOMAD_NAMESPACE', None), - token=os.getenv('NOMAD_TOKEN', None), - timeout=5, - region=os.getenv('NOMAD_REGION', None), - version='v1', - verify=False, - cert=(os.getenv('NOMAD_CLIENT_CERT', None), - os.getenv('NOMAD_CLIENT_KEY', None)), - session=None): - """ Nomad api client - - https://github.com/jrxFive/python-nomad/ - - optional arguments: - - host (defaults 127.0.0.1), string ip or name of the nomad api server/agent that will be used. - - port (defaults 4646), integer port that will be used to connect. - - secure (defaults False), define if the protocol is secured or not (https or http) - - version (defaults v1), vesion of the api of nomad. - - verify (defaults False), verify the certificate when tls/ssl is enabled - at nomad. - - cert (defaults empty), cert, or key and cert file to validate the certificate - configured at nomad. - - region (defaults None), version of the region to use. It will be used then - regions of the current agent of the connection. - - namespace (defaults to None), Specifies the enterpise namespace that will - be use to deploy or to ask info to nomad. - - token (defaults to None), Specifies to append ACL token to the headers to - make authentication on secured based nomad environemnts. - - session (defaults to None), allows for injecting a prepared requests.Session object that - all requests to Nomad should use. - returns: Nomad api client object - - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException - - nomad.api.exceptions.URLNotAuthorizedNomadException + + def __init__( # pylint: disable=too-many-arguments + self, + host="127.0.0.1", + secure=False, + port=4646, + address=os.getenv("NOMAD_ADDR", None), + namespace=os.getenv("NOMAD_NAMESPACE", None), + token=os.getenv("NOMAD_TOKEN", None), + timeout=5, + region=os.getenv("NOMAD_REGION", None), + version="v1", + verify=False, + cert=(os.getenv("NOMAD_CLIENT_CERT", None), os.getenv("NOMAD_CLIENT_KEY", None)), + session=None, + ): + """Nomad api client + + https://github.com/jrxFive/python-nomad/ + + optional arguments: + - host (defaults 127.0.0.1), string ip or name of the nomad api server/agent that will be used. + - port (defaults 4646), integer port that will be used to connect. + - secure (defaults False), define if the protocol is secured or not (https or http) + - version (defaults v1), vesion of the api of nomad. + - verify (defaults False), verify the certificate when tls/ssl is enabled + at nomad. + - cert (defaults empty), cert, or key and cert file to validate the certificate + configured at nomad. + - region (defaults None), version of the region to use. It will be used then + regions of the current agent of the connection. + - namespace (defaults to None), Specifies the enterpise namespace that will + be use to deploy or to ask info to nomad. + - token (defaults to None), Specifies to append ACL token to the headers to + make authentication on secured based nomad environemnts. + - session (defaults to None), allows for injecting a prepared requests.Session object that + all requests to Nomad should use. + returns: Nomad api client object + + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException + - nomad.api.exceptions.URLNotAuthorizedNomadException """ self.host = host self.secure = secure diff --git a/nomad/api/acl.py b/nomad/api/acl.py index 857c2dc..9b3b024 100644 --- a/nomad/api/acl.py +++ b/nomad/api/acl.py @@ -25,170 +25,170 @@ def __getattr__(self, item): raise AttributeError def generate_bootstrap(self): - """ Activate bootstrap token. + """Activate bootstrap token. - https://www.nomadproject.io/api/acl-tokens.html + https://www.nomadproject.io/api/acl-tokens.html - returns: dict + returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("bootstrap", method="post").json() def get_tokens(self): - """ Get a list of tokens. + """Get a list of tokens. - https://www.nomadproject.io/api/acl-tokens.html + https://www.nomadproject.io/api/acl-tokens.html - returns: list + returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("tokens", method="get").json() - def get_token(self, _id): - """ Retrieve specific token. + def get_token(self, id_): + """Retrieve specific token. - https://www.nomadproject.io/api/acl-tokens.html + https://www.nomadproject.io/api/acl-tokens.html - returns: dict + returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - 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. + """Retrieve self token used for auth. - https://www.nomadproject.io/api/acl-tokens.html + https://www.nomadproject.io/api/acl-tokens.html - returns: dict + returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("token", "self", method="get").json() def create_token(self, token): - """ Create token. + """Create token. - https://www.nomadproject.io/api/acl-tokens.html + https://www.nomadproject.io/api/acl-tokens.html - arguments: - token - returns: dict + arguments: + token + returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("token", json=token, method="post").json() - def delete_token(self, _id): - """ Delete specific token. + def delete_token(self, id_): + """Delete specific token. - https://www.nomadproject.io/api/acl-tokens.html + https://www.nomadproject.io/api/acl-tokens.html - returns: Boolean + returns: Boolean - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - 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): - """ Update token. + def update_token(self, id_, token): + """Update token. - https://www.nomadproject.io/api/acl-tokens.html + https://www.nomadproject.io/api/acl-tokens.html - arguments: - - AccdesorID - - token - returns: dict + arguments: + - AccdesorID + - token + returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - 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. + """Get a list of policies. - https://www.nomadproject.io/api/acl-policies.html + https://www.nomadproject.io/api/acl-policies.html - returns: list + returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("policies", method="get").json() - def create_policy(self, _id, policy): - """ Create policy. + def create_policy(self, id_, policy): + """Create policy. - https://www.nomadproject.io/api/acl-policies.html + https://www.nomadproject.io/api/acl-policies.html - arguments: - - policy - returns: request.Response + arguments: + - policy + returns: request.Response - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - 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): - """ Get a spacific. + def get_policy(self, id_): + """Get a spacific. - https://www.nomadproject.io/api/acl-policies.html + https://www.nomadproject.io/api/acl-policies.html - returns: dict + returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - 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): - """ Create policy. + def update_policy(self, id_, policy): + """Create policy. - https://www.nomadproject.io/api/acl-policies.html + https://www.nomadproject.io/api/acl-policies.html - arguments: - - name - - policy - returns: request.Response + arguments: + - name + - policy + returns: request.Response - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - 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): - """ Delete specific policy. + def delete_policy(self, id_): + """Delete specific policy. - https://www.nomadproject.io/api/acl-policies.html + https://www.nomadproject.io/api/acl-policies.html - arguments: - - id - returns: Boolean + arguments: + - id + returns: Boolean - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + 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/agent.py b/nomad/api/agent.py index 403d035..7ad412c 100644 --- a/nomad/api/agent.py +++ b/nomad/api/agent.py @@ -3,8 +3,8 @@ class Agent(Requester): - """The self endpoint is used to query the state of the target agent.""" + ENDPOINT = "agent" def __init__(self, **kwargs): @@ -21,64 +21,64 @@ def __getattr__(self, item): raise AttributeError(msg) def get_agent(self): - """ Query the state of the target agent. + """Query the state of the target agent. - https://www.nomadproject.io/docs/http/agent-self.html + https://www.nomadproject.io/docs/http/agent-self.html - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("self", method="get").json() def get_members(self): """Lists the known members of the gossip pool. - https://www.nomadproject.io/docs/http/agent-members.html + https://www.nomadproject.io/docs/http/agent-members.html - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("members", method="get").json() def get_servers(self): - """ Lists the known members of the gossip pool. + """Lists the known members of the gossip pool. - https://www.nomadproject.io/docs/http/agent-servers.html + https://www.nomadproject.io/docs/http/agent-servers.html - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("servers", method="get").json() def join_agent(self, addresses): """Initiate a join between the agent and target peers. - https://www.nomadproject.io/docs/http/agent-join.html + https://www.nomadproject.io/docs/http/agent-join.html - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"address": addresses} return self.request("join", params=params, method="post").json() def update_servers(self, addresses): """Updates the list of known servers to the provided list. - Replaces all previous server addresses with the new list. + Replaces all previous server addresses with the new list. - https://www.nomadproject.io/docs/http/agent-servers.html + https://www.nomadproject.io/docs/http/agent-servers.html - returns: 200 status code - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: 200 status code + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"address": addresses} return self.request("servers", params=params, method="post").status_code @@ -86,12 +86,12 @@ def update_servers(self, addresses): def force_leave(self, node): """Force a failed gossip member into the left state. - https://www.nomadproject.io/docs/http/agent-force-leave.html + https://www.nomadproject.io/docs/http/agent-force-leave.html - returns: 200 status code - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: 200 status code + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"node": node} return self.request("force-leave", params=params, method="post").status_code diff --git a/nomad/api/allocation.py b/nomad/api/allocation.py index c6ab949..6ca74a4 100644 --- a/nomad/api/allocation.py +++ b/nomad/api/allocation.py @@ -47,26 +47,26 @@ def __getitem__(self, item): except nomad.api.exceptions.URLNotFoundNomadException as exc: raise KeyError from exc - def get_allocation(self, _id): - """ Query a specific allocation. + def get_allocation(self, id_): + """Query a specific allocation. - https://www.nomadproject.io/docs/http/alloc.html + https://www.nomadproject.io/docs/http/alloc.html - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + 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 stop_allocation(self, _id): - """ Stop a specific allocation. + def stop_allocation(self, id_): + """Stop a specific allocation. - https://www.nomadproject.io/api-docs/allocations/#stop-allocation + https://www.nomadproject.io/api-docs/allocations/#stop-allocation - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: dict + raises: + - 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 edd6229..c776772 100644 --- a/nomad/api/allocations.py +++ b/nomad/api/allocations.py @@ -46,19 +46,19 @@ def get_allocations( # pylint: disable=too-many-arguments """Lists all the allocations. https://www.nomadproject.io/docs/http/allocs.html - arguments: - - prefix :(str) optional, specifies a string to filter allocations on based on an prefix. - This is specified as a querystring parameter. - - filter_ :(str) optional - Name has a trailing underscore not to conflict with builtin function. - - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. - This is specified as a querystring parameter. - - resources :(bool) optional - - task_states :(bool) optional - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - prefix :(str) optional, specifies a string to filter allocations on based on an prefix. + This is specified as a querystring parameter. + - filter_ :(str) optional + Name has a trailing underscore not to conflict with builtin function. + - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. + This is specified as a querystring parameter. + - resources :(bool) optional + - task_states :(bool) optional + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = { "prefix": prefix, diff --git a/nomad/api/base.py b/nomad/api/base.py index 22f6e3a..a4c7329 100644 --- a/nomad/api/base.py +++ b/nomad/api/base.py @@ -4,7 +4,7 @@ import nomad.api.exceptions -class Requester(): # pylint: disable=too-many-instance-attributes,too-few-public-methods +class Requester: # pylint: disable=too-many-instance-attributes,too-few-public-methods """ Base object for endpoints """ @@ -23,7 +23,7 @@ def __init__( # pylint: disable=too-many-arguments verify=False, cert=(), region=None, - session=None + session=None, ): self.uri = uri self.port = port @@ -114,7 +114,7 @@ def request(self, *args, **kwargs): return response - def _request( # pylint: disable=too-many-arguments, too-many-branches + def _request( # pylint: disable=too-many-arguments, too-many-branches self, method, endpoint, diff --git a/nomad/api/client.py b/nomad/api/client.py index 7b495fe..cefbd33 100644 --- a/nomad/api/client.py +++ b/nomad/api/client.py @@ -2,10 +2,13 @@ # 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(): + + +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) @@ -44,21 +47,21 @@ class ls(Requester): def __init__(self, **kwargs): super().__init__(**kwargs) - def list_files(self, _id=None, path="/"): - """ List files in an allocation directory. + def list_files(self, id_=None, path="/"): + """List files in an allocation directory. - https://www.nomadproject.io/docs/http/client-fs-ls.html + https://www.nomadproject.io/docs/http/client-fs-ls.html - arguments: - - _id - - path - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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() + if id_: + return self.request(id_, params={"path": path}, method="get").json() return self.request(params={"path": path}, method="get").json() @@ -79,21 +82,21 @@ class cat(Requester): def __init__(self, **kwargs): super().__init__(**kwargs) - def read_file(self, _id=None, path="/"): - """ Read contents of a file in an allocation directory. + 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 + https://www.nomadproject.io/docs/http/client-fs-cat.html - arguments: - - _id - - path - returns: (str) text - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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 + if id_: + return self.request(id_, params={"path": path}, method="get").text return self.request(params={"path": path}, method="get").text @@ -111,27 +114,23 @@ class read_at(Requester): def __init__(self, **kwargs): super().__init__(**kwargs) - def read_file_offset(self, _id, offset, limit, path="/"): - """ Read contents of a file in an allocation directory. + 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 + https://www.nomadproject.io/docs/http/client-fs-cat.html - arguments: - - _id: (str) allocation_id required - - offset: (int) required - - limit: (int) required - - path: (str) optional - returns: (str) text - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.BadRequestNomadException + arguments: + - id_: (str) allocation_id required + - offset: (int) required + - limit: (int) required + - path: (str) optional + returns: (str) text + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.BadRequestNomadException """ - params = { - "path": path, - "offset": offset, - "limit": limit - } - return self.request(_id, params=params, method="get").text + params = {"path": path, "offset": offset, "limit": limit} + return self.request(id_, params=params, method="get").text class stream_file(Requester): @@ -147,27 +146,23 @@ class stream_file(Requester): def __init__(self, **kwargs): super().__init__(**kwargs) - def stream(self, _id, offset, origin, path="/"): - """ This endpoint streams the contents of a file in an allocation directory. + 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 + https://www.nomadproject.io/api/client.html#stream-file - arguments: - - _id: (str) allocation_id required - - offset: (int) required - - origin: (str) either start|end - - path: (str) optional - returns: (str) text - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.BadRequestNomadException + arguments: + - id_: (str) allocation_id required + - offset: (int) required + - origin: (str) either start|end + - path: (str) optional + returns: (str) text + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.BadRequestNomadException """ - params = { - "path": path, - "offset": offset, - "origin": origin - } - return self.request(_id, params=params, method="get").text + params = {"path": path, "offset": offset, "origin": origin} + return self.request(id_, params=params, method="get").text class stream_logs(Requester): @@ -183,33 +178,26 @@ class stream_logs(Requester): def __init__(self, **kwargs): super().__init__(**kwargs) - 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 - - task: (str) name of the task inside the allocation to stream logs from - - _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" - - plain: (bool) Return just the plain text without framing. default False - returns: (str) text - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.BadRequestNomadException + 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 + - task: (str) name of the task inside the allocation to stream logs from + - 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" + - plain: (bool) Return just the plain text without framing. default False + returns: (str) text + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.BadRequestNomadException """ - params = { - "task": task, - "type": _type, - "follow": follow, - "offset": offset, - "origin": origin, - "plain": plain - } - return self.request(_id, params=params, method="get").text + params = {"task": task, "type": type_, "follow": follow, "offset": offset, "origin": origin, "plain": plain} + return self.request(id_, params=params, method="get").text class stat(Requester): @@ -226,27 +214,26 @@ class stat(Requester): def __init__(self, **kwargs): super().__init__(**kwargs) - def stat_file(self, _id=None, path="/"): - """ Stat a file in an allocation directory. + def stat_file(self, id_=None, path="/"): + """Stat a file in an allocation directory. - https://www.nomadproject.io/docs/http/client-fs-stat.html + https://www.nomadproject.io/docs/http/client-fs-stat.html - arguments: - - _id - - path - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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() + if id_: + return self.request(id_, params={"path": path}, method="get").json() return self.request(params={"path": path}, method="get").json() class stats(Requester): - """ The /stats endpoint queries the actual resources consumed on a node. The API endpoint is hosted by the Nomad client and requests have to @@ -261,21 +248,21 @@ def __init__(self, **kwargs): super().__init__(**kwargs) def read_stats(self, node_id=None): - """ Query the actual resources consumed on a node. + """ + Query the actual resources consumed on a node. - https://www.nomadproject.io/api/client.html#read-stats + https://www.nomadproject.io/api/client.html#read-stats - arguments: - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request(params={"node_id": node_id}, method="get").json() 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 @@ -290,30 +277,30 @@ class allocation(Requester): def __init__(self, **kwargs): super().__init__(**kwargs) - def read_allocation_stats(self, _id): - """ Query the actual resources consumed by an allocation. + def read_allocation_stats(self, id_): + """Query the actual resources consumed by an allocation. - https://www.nomadproject.io/api/client.html#read-allocation + https://www.nomadproject.io/api/client.html#read-allocation - arguments: - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + returns: dict + raises: + - 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): - """ Restart a specific allocation. + def restart_allocation(self, id_): + """Restart a specific allocation. - https://www.nomadproject.io/api-docs/allocations/#restart-allocation + https://www.nomadproject.io/api-docs/allocations/#restart-allocation - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: dict + raises: + - 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): @@ -329,22 +316,21 @@ class gc_allocation(Requester): def __init__(self, **kwargs): super().__init__(**kwargs) - def garbage_collect(self, _id): - """ This endpoint forces a garbage collection of a particular, stopped allocation on a node. + 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 + https://www.nomadproject.io/api/client.html#gc-allocation - arguments: - - _id: (str) full allocation_id - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ This endpoint forces a garbage collection of all stopped allocations on a node. @@ -357,13 +343,13 @@ def __init__(self, **kwargs): super().__init__(**kwargs) def garbage_collect(self, node_id=None): - """ This endpoint forces a garbage collection of all stopped allocations on a node. + """This endpoint forces a garbage collection of all stopped allocations on a node. - https://www.nomadproject.io/api/client.html#gc-all-allocation + https://www.nomadproject.io/api/client.html#gc-all-allocation - arguments: - - node_id: (str) full allocation_id - raises: - - nomad.api.exceptions.BaseNomadException + arguments: + - node_id: (str) full allocation_id + raises: + - nomad.api.exceptions.BaseNomadException """ self.request(params={"node_id": node_id}, method="get") diff --git a/nomad/api/deployment.py b/nomad/api/deployment.py index 90e27e2..2b2432c 100644 --- a/nomad/api/deployment.py +++ b/nomad/api/deployment.py @@ -11,6 +11,7 @@ class Deployment(Requester): https://www.nomadproject.io/docs/http/deployments.html """ + ENDPOINT = "deployment" def __init__(self, **kwargs): @@ -42,123 +43,120 @@ def __getitem__(self, item): except nomad.api.exceptions.URLNotFoundNomadException as exp: raise KeyError from exp - def get_deployment(self, _id): - """ This endpoint reads information about a specific deployment by ID. + def get_deployment(self, id_): + """This endpoint reads information about a specific deployment by ID. - https://www.nomadproject.io/docs/http/deployments.html + https://www.nomadproject.io/docs/http/deployments.html - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ This endpoint lists the allocations created or modified for the given deployment. + 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 + https://www.nomadproject.io/docs/http/deployments.html - arguments: - - _id - returns: list of dicts - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ 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. + 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 + https://www.nomadproject.io/docs/http/deployments.html - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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() - - 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 - - pause, Specifies whether to pause or resume the deployment. - 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() + + 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_ + - pause, Specifies whether to pause or resume the deployment. + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ - pause_json = {"Pause": pause, - "DeploymentID": _id} - return self.request("pause", _id, json=pause_json, method="post").json() - - 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. - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + pause_json = {"Pause": pause, "DeploymentID": id_} + return self.request("pause", id_, json=pause_json, method="post").json() + + 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. + 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() - - 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 - - groups, (list) Specifies a particular set of task groups that 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() + + 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_ + - 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() - - 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 - manually using this endpoint. Marking an allocation as healthy will allow the rolling upgrade to proceed. - Marking it as failed will cause the deployment to fail. - - https://www.nomadproject.io/docs/http/deployments.html - - arguments: - - _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 - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + promote_groups_json = {"Groups": groups, "DeploymentID": id_} + return self.request("promote", id_, json=promote_groups_json, method="post").json() + + 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 + manually using this endpoint. Marking an allocation as healthy will allow the rolling upgrade to proceed. + Marking it as failed will cause the deployment to fail. + + https://www.nomadproject.io/docs/http/deployments.html + + arguments: + - 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 + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ if healthy_allocations is None: healthy_allocations = [] @@ -166,7 +164,9 @@ def deployment_allocation_health(self, _id, healthy_allocations=None, unhealthy_ 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() + allocations = { + "HealthyAllocationIDs": healthy_allocations, + "UnHealthyAllocationIDs": unhealthy_allocations, + "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 a812d3a..91dd335 100644 --- a/nomad/api/deployments.py +++ b/nomad/api/deployments.py @@ -5,12 +5,12 @@ class Deployments(Requester): - """ The /deployment endpoints are used to query for and interact with deployments. https://www.nomadproject.io/docs/http/deployments.html """ + ENDPOINT = "deployments" def __init__(self, **kwargs): @@ -55,20 +55,20 @@ def __getitem__(self, item): raise KeyError from exc def get_deployments(self, prefix="", namespace=None): - """ This endpoint lists all deployments. + """This endpoint lists all deployments. - https://www.nomadproject.io/docs/http/deployments.html + https://www.nomadproject.io/docs/http/deployments.html - optional_arguments: - - prefix, (default "") Specifies a string to filter deployments on based on an index prefix. - This is specified as a querystring parameter. - - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. - This is specified as a querystring parameter. + optional_arguments: + - prefix, (default "") Specifies a string to filter deployments on based on an index prefix. + This is specified as a querystring parameter. + - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. + This is specified as a querystring parameter. - returns: list of dicts - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: list of dicts + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"prefix": prefix} if namespace: diff --git a/nomad/api/evaluation.py b/nomad/api/evaluation.py index a9ad84c..e7bbf9b 100644 --- a/nomad/api/evaluation.py +++ b/nomad/api/evaluation.py @@ -5,7 +5,6 @@ class Evaluation(Requester): - """ The evaluation endpoint is used to query a specific evaluations. By default, the agent's local region is used; another region can @@ -13,6 +12,7 @@ class Evaluation(Requester): https://www.nomadproject.io/docs/http/eval.html """ + ENDPOINT = "evaluation" def __init__(self, **kwargs): @@ -45,30 +45,30 @@ def __getitem__(self, item): except nomad.api.exceptions.URLNotFoundNomadException as exc: raise KeyError from exc - def get_evaluation(self, _id): - """ Query a specific evaluation. + def get_evaluation(self, id_): + """Query a specific evaluation. - https://www.nomadproject.io/docs/http/eval.html + https://www.nomadproject.io/docs/http/eval.html - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ Query the allocations created or modified by an evaluation. + def get_allocations(self, id_): + """Query the allocations created or modified by an evaluation. - https://www.nomadproject.io/docs/http/eval.html + https://www.nomadproject.io/docs/http/eval.html - arguments: - - _id - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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 8ec96e8..dae0f61 100644 --- a/nomad/api/evaluations.py +++ b/nomad/api/evaluations.py @@ -3,8 +3,8 @@ from nomad.api.base import Requester -class Evaluations(Requester): +class Evaluations(Requester): """ The evaluations endpoint is used to query the status of evaluations. By default, the agent's local region is used; another region can @@ -12,6 +12,7 @@ class Evaluations(Requester): https://www.nomadproject.io/docs/http/evals.html """ + ENDPOINT = "evaluations" def __init__(self, **kwargs): @@ -58,16 +59,16 @@ def __iter__(self): return iter(evaluations) def get_evaluations(self, prefix=None): - """ Lists all the evaluations. - - https://www.nomadproject.io/docs/http/evals.html - arguments: - - prefix :(str) optional, specifies a string to filter evaluations on based on an prefix. - This is specified as a querystring parameter. - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + """Lists all the evaluations. + + https://www.nomadproject.io/docs/http/evals.html + arguments: + - prefix :(str) optional, specifies a string to filter evaluations on based on an prefix. + This is specified as a querystring parameter. + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"prefix": prefix} return self.request(method="get", params=params).json() diff --git a/nomad/api/event.py b/nomad/api/event.py index ba001fc..cafadb2 100644 --- a/nomad/api/event.py +++ b/nomad/api/event.py @@ -7,10 +7,12 @@ from nomad.api.base import Requester -class Event(): + +class Event: """ Nomad Event """ + def __str__(self): return f"{self.__dict__}" @@ -23,6 +25,7 @@ def __getattr__(self, item): def __init__(self, **kwargs): self.stream = stream(**kwargs) + # backward compatibility class stream(Requester): # pylint: disable=invalid-name """ @@ -63,7 +66,9 @@ def _get_stream(self, method, params, timeout, event_queue, exit_event): # pyli except requests.exceptions.ConnectionError: continue - def get_stream(self, index=0, topic=None, namespace=None, event_queue=None, timeout=None): # pylint: disable=too-many-arguments + 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() @@ -120,8 +125,8 @@ def get_stream(self, index=0, topic=None, namespace=None, event_queue=None, time "params": params, "timeout": timeout, "event_queue": event_queue, - "exit_event": stream_exit_event - } + "exit_event": stream_exit_event, + }, ) return _stream, stream_exit_event, event_queue diff --git a/nomad/api/exceptions.py b/nomad/api/exceptions.py index 5f60205..578c16f 100644 --- a/nomad/api/exceptions.py +++ b/nomad/api/exceptions.py @@ -4,6 +4,7 @@ class BaseNomadException(Exception): """General Error occurred when interacting with nomad API""" + def __init__(self, nomad_resp): self.nomad_resp = nomad_resp diff --git a/nomad/api/job.py b/nomad/api/job.py index 6d0286b..03288db 100644 --- a/nomad/api/job.py +++ b/nomad/api/job.py @@ -5,13 +5,13 @@ class Job(Requester): - """ The job endpoint is used for CRUD on a single job. By default, the agent's local region is used. https://www.nomadproject.io/docs/http/job.html """ + ENDPOINT = "job" def __init__(self, **kwargs): @@ -46,257 +46,254 @@ def __getitem__(self, item): except nomad.api.exceptions.URLNotFoundNomadException as exc: raise KeyError from exc - def get_job(self, _id, namespace=None): - """ Query a single job for its specification and status. + def get_job(self, id_, namespace=None): + """Query a single job for its specification and status. - https://www.nomadproject.io/docs/http/job.html + https://www.nomadproject.io/docs/http/job.html - arguments: - - _id - - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. - This is specified as a querystring parameter. - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - id_ + - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. + This is specified as a querystring parameter. + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {} 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): - """ This endpoint reads information about all versions of a job. + def get_versions(self, id_): + """This endpoint reads information about all versions of a job. - https://www.nomadproject.io/docs/http/job.html + https://www.nomadproject.io/docs/http/job.html - arguments: - - id - returns: list of dicts - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - id + returns: list of dicts + raises: + - 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): - """ Query the allocations belonging to a single job. + def get_allocations(self, id_): + """Query the allocations belonging to a single job. - https://www.nomadproject.io/docs/http/job.html + https://www.nomadproject.io/docs/http/job.html - arguments: - - _id - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ Query the evaluations belonging to a single job. + def get_evaluations(self, id_): + """Query the evaluations belonging to a single job. - https://www.nomadproject.io/docs/http/job.html + https://www.nomadproject.io/docs/http/job.html - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ This endpoint lists a single job's deployments + def get_deployments(self, id_): + """This endpoint lists a single job's deployments - https://www.nomadproject.io/docs/http/job.html + https://www.nomadproject.io/docs/http/job.html - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ This endpoint returns a single job's most recent deployment. + def get_deployment(self, id_): + """This endpoint returns a single job's most recent deployment. - https://www.nomadproject.io/docs/http/job.html + https://www.nomadproject.io/docs/http/job.html - arguments: - - _id - returns: list of dicts - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ Query the summary of a job. + def get_summary(self, id_): + """Query the summary of a job. - https://www.nomadproject.io/docs/http/job.html + https://www.nomadproject.io/docs/http/job.html - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ Registers a new job or updates an existing job + def register_job(self, id_, job): + """Registers a new job or updates an existing job - https://www.nomadproject.io/docs/http/job.html + https://www.nomadproject.io/docs/http/job.html - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ Creates a new evaluation for the given job. - This can be used to force run the scheduling logic if necessary. + 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 + https://www.nomadproject.io/docs/http/job.html - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - id_ + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(_id, "evaluate", method="post").json() - - 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 - - job, dict - - diff, boolean - - policy_override, boolean - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + return self.request(id_, "evaluate", method="post").json() + + 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_ + - job, dict + - diff, boolean + - policy_override, boolean + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ json_dict = {} 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() - - 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 - run a periodic job. - - https://www.nomadproject.io/docs/http/job.html - - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + json_dict.setdefault("Diff", diff) + json_dict.setdefault("PolicyOverride", policy_override) + return self.request(id_, "plan", json=json_dict, method="post").json() + + 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 + run a periodic job. + + https://www.nomadproject.io/docs/http/job.html + + arguments: + - 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): - """ Dispatches a new instance of a parameterized job. + 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 + https://www.nomadproject.io/docs/http/job.html - arguments: - - _id - - payload - - meta - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - id_ + - payload + - meta + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ dispatch_json = {"Meta": meta, "Payload": payload} - return self.request(_id, "dispatch", json=dispatch_json, method="post").json() - - 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 - - version, Specifies the job version to revert to. - optional_arguments: - - enforce_prior_version, Optional value specifying the current job's version. - This is checked and acts as a check-and-set value before reverting to the - specified job. - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + return self.request(id_, "dispatch", json=dispatch_json, method="post").json() + + 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_ + - version, Specifies the job version to revert to. + optional_arguments: + - enforce_prior_version, Optional value specifying the current job's version. + This is checked and acts as a check-and-set value before reverting to the + specified job. + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ - revert_json = {"JobID": _id, - "JobVersion": version, - "EnforcePriorVersion": enforce_prior_version} - return self.request(_id, "revert", json=revert_json, method="post").json() - - def stable_job(self, _id, version, stable): - """ This endpoint sets the job's stability. - - https://www.nomadproject.io/docs/http/job.html - - arguments: - - _id - - version, Specifies the job version to revert to. - - stable, Specifies whether the job should be marked as stable or not. - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + revert_json = {"JobID": id_, "JobVersion": version, "EnforcePriorVersion": enforce_prior_version} + return self.request(id_, "revert", json=revert_json, method="post").json() + + def stable_job(self, id_, version, stable): + """This endpoint sets the job's stability. + + https://www.nomadproject.io/docs/http/job.html + + arguments: + - id_ + - version, Specifies the job version to revert to. + - stable, Specifies whether the job should be marked as stable or not. + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ - revert_json = {"JobID": _id, - "JobVersion": version, - "Stable": stable} - return self.request(_id, "stable", json=revert_json, method="post").json() - - 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 - - purge (bool), optionally specifies whether the job should be - stopped and purged immediately (`purge=True`) or deferred to the - Nomad garbage collector (`purge=False`). - - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException - - nomad.api.exceptions.InvalidParameters + revert_json = {"JobID": id_, "JobVersion": version, "Stable": stable} + return self.request(id_, "stable", json=revert_json, method="post").json() + + 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_ + - purge (bool), optionally specifies whether the job should be + stopped and purged immediately (`purge=True`) or deferred to the + Nomad garbage collector (`purge=False`). + + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException + - nomad.api.exceptions.InvalidParameters """ params = None if purge is not None: if not isinstance(purge, bool): - raise nomad.api.exceptions.InvalidParameters("purge is invalid " - f"(expected type {type(bool())} but got {type(purge)})") + raise nomad.api.exceptions.InvalidParameters( + "purge is invalid " 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 3d8793b..c57f31c 100644 --- a/nomad/api/jobs.py +++ b/nomad/api/jobs.py @@ -6,7 +6,6 @@ class Jobs(Requester): - """ The jobs endpoint is used to query the status of existing jobs in Nomad and to register new jobs. @@ -14,6 +13,7 @@ class Jobs(Requester): https://www.nomadproject.io/docs/http/jobs.html """ + ENDPOINT = "jobs" def __init__(self, **kwargs): @@ -73,19 +73,19 @@ def get_jobs( """Lists all the jobs registered with Nomad. https://www.nomadproject.io/docs/http/jobs.html - arguments: - - prefix :(str) optional, specifies a string to filter jobs on based on an prefix. - This is specified as a querystring parameter. - - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. - This is specified as a querystring parameter. - - filter_ :(str) optional, specifies the expression used to filter the result. - Name has a trailing underscore not to conflict with builtin function. - - meta :(bool) optional, if set, jobs returned will include a meta field containing - key-value pairs provided in the job specification's meta block. - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - prefix :(str) optional, specifies a string to filter jobs on based on an prefix. + This is specified as a querystring parameter. + - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. + This is specified as a querystring parameter. + - filter_ :(str) optional, specifies the expression used to filter the result. + Name has a trailing underscore not to conflict with builtin function. + - meta :(bool) optional, if set, jobs returned will include a meta field containing + key-value pairs provided in the job specification's meta block. + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = { "prefix": prefix, @@ -96,27 +96,27 @@ def get_jobs( return self.request(method="get", params=params).json() def register_job(self, job): - """ Register a job with Nomad. + """Register a job with Nomad. - https://www.nomadproject.io/docs/http/jobs.html + https://www.nomadproject.io/docs/http/jobs.html - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request(json=job, method="post").json() def parse(self, hcl, canonicalize=False): - """ Parse a HCL Job file. Returns a dict with the JSON formatted job. - This API endpoint is only supported from Nomad version 0.8.3. + """Parse a HCL Job file. Returns a dict with the JSON formatted job. + This API endpoint is only supported from Nomad version 0.8.3. - https://www.nomadproject.io/api/jobs.html#parse-job + https://www.nomadproject.io/api/jobs.html#parse-job - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request( "parse", json={"JobHCL": hcl, "Canonicalize": canonicalize}, method="post", allow_redirects=True diff --git a/nomad/api/metrics.py b/nomad/api/metrics.py index 2ecccf2..0575eff 100644 --- a/nomad/api/metrics.py +++ b/nomad/api/metrics.py @@ -3,7 +3,6 @@ class Metrics(Requester): - """ The /metrics endpoint returns metrics for the current Nomad process. @@ -13,6 +12,7 @@ class Metrics(Requester): https://www.nomadproject.io/docs/agent/telemetry.html """ + ENDPOINT = "metrics" def __init__(self, **kwargs): @@ -29,13 +29,13 @@ def __getattr__(self, item): raise AttributeError(msg) def get_metrics(self): - """ Get the metrics + """Get the metrics - https://www.nomadproject.io/api/metrics.html + https://www.nomadproject.io/api/metrics.html - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request(method="get").json() diff --git a/nomad/api/namespace.py b/nomad/api/namespace.py index 0860c73..d494449 100644 --- a/nomad/api/namespace.py +++ b/nomad/api/namespace.py @@ -5,13 +5,13 @@ class Namespace(Requester): - """ The job endpoint is used for CRUD on a single namespace. By default, the agent's local region is used. https://www.nomadproject.io/api/namespaces.html """ + ENDPOINT = "namespace" def __init__(self, **kwargs): @@ -49,60 +49,60 @@ def __getitem__(self, item): except nomad.api.exceptions.URLNotFoundNomadException as exc: raise KeyError from exc - def get_namespace(self, _id): - """ Query a single namespace. + def get_namespace(self, id_): + """Query a single namespace. - https://www.nomadproject.io/api/namespaces.html + https://www.nomadproject.io/api/namespaces.html - arguments: - - _id - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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 + """create namespace - https://www.nomadproject.io/api/namespaces.html + https://www.nomadproject.io/api/namespaces.html - arguments: - - id - - namespace (dict) - returns: requests.Response - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - id + - namespace (dict) + returns: requests.Response + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request(json=namespace, method="post") - def update_namespace(self, _id, namespace): - """ Update namespace + def update_namespace(self, id_, namespace): + """Update namespace - https://www.nomadproject.io/api/namespaces.html + https://www.nomadproject.io/api/namespaces.html - arguments: - - _id - - namespace (dict) - returns: requests.Response - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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): - """ delete namespace. + def delete_namespace(self, id_): + """delete namespace. - https://www.nomadproject.io/api/namespaces.html + https://www.nomadproject.io/api/namespaces.html - arguments: - - _id - returns: requests.Response - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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 3fb907f..a87108f 100644 --- a/nomad/api/namespaces.py +++ b/nomad/api/namespaces.py @@ -5,12 +5,12 @@ class Namespaces(Requester): - """ The namespaces from enterprise solution https://www.nomadproject.io/docs/enterprise/namespaces/index.html """ + ENDPOINT = "namespaces" def __init__(self, **kwargs): @@ -59,16 +59,16 @@ def __iter__(self): return iter(namespaces) def get_namespaces(self, prefix=None): - """ Lists all the namespaces registered with Nomad. - - https://www.nomadproject.io/docs/enterprise/namespaces/index.html - arguments: - - prefix :(str) optional, specifies a string to filter namespaces on based on an prefix. - This is specified as a querystring parameter. - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + """Lists all the namespaces registered with Nomad. + + https://www.nomadproject.io/docs/enterprise/namespaces/index.html + arguments: + - prefix :(str) optional, specifies a string to filter namespaces on based on an prefix. + This is specified as a querystring parameter. + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"prefix": prefix} return self.request(method="get", params=params).json() diff --git a/nomad/api/node.py b/nomad/api/node.py index 46688c2..48c3faf 100644 --- a/nomad/api/node.py +++ b/nomad/api/node.py @@ -5,13 +5,13 @@ class Node(Requester): - """ The node endpoint is used to query the a specific client node. By default, the agent's local region is used. https://www.nomadproject.io/docs/http/node.html """ + ENDPOINT = "node" def __init__(self, **kwargs): @@ -49,120 +49,109 @@ def __getitem__(self, item): except nomad.api.exceptions.URLNotFoundNomadException as exc: raise KeyError from exc - def get_node(self, _id): - """ Query the status of a client node registered with Nomad. + def get_node(self, id_): + """Query the status of a client node registered with Nomad. - https://www.nomadproject.io/docs/http/node.html + https://www.nomadproject.io/docs/http/node.html - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + 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): - """ Query the allocations belonging to a single node. + def get_allocations(self, id_): + """Query the allocations belonging to a single node. - https://www.nomadproject.io/docs/http/node.html + https://www.nomadproject.io/docs/http/node.html - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + 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 evaluate_node(self, _id): - """ Creates a new evaluation for the given node. - This can be used to force run the - scheduling logic if necessary. + def evaluate_node(self, id_): + """Creates a new evaluation for the given node. + This can be used to force run the + scheduling logic if necessary. - https://www.nomadproject.io/docs/http/node.html + https://www.nomadproject.io/docs/http/node.html - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(_id, "evaluate", method="post").json() - - 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. - - https://www.nomadproject.io/docs/http/node.html - - arguments: - - _id (str uuid): node id - - enable (bool): enable node drain or not to enable node drain - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + return self.request(id_, "evaluate", method="post").json() + + 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. + + https://www.nomadproject.io/docs/http/node.html + + arguments: + - id_ (str uuid): node id + - enable (bool): enable node drain or not to enable node drain + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - 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): - """ 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. + 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. - If an empty dictionary is given as drain_spec this will disable/toggle the drain. + If an empty dictionary is given as drain_spec this will disable/toggle the drain. - https://www.nomadproject.io/docs/http/node.html + https://www.nomadproject.io/docs/http/node.html - arguments: - - _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 - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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 + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ payload = {} if drain_spec and mark_eligible is not None: - payload = { - "NodeID": _id, - "DrainSpec": drain_spec, - "MarkEligible": mark_eligible - } + payload = {"NodeID": id_, "DrainSpec": drain_spec, "MarkEligible": mark_eligible} elif drain_spec and mark_eligible is None: - payload = { - "NodeID": _id, - "DrainSpec": drain_spec - } + payload = {"NodeID": id_, "DrainSpec": drain_spec} elif not drain_spec and mark_eligible is not None: - payload = { - "NodeID": _id, - "DrainSpec": None, - "MarkEligible": mark_eligible - } + payload = {"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): - """ Toggle the eligibility of the node. + def eligible_node(self, id_, eligible=None, ineligible=None): + """Toggle the eligibility of the node. - https://www.nomadproject.io/docs/http/node.html + https://www.nomadproject.io/docs/http/node.html - arguments: - - _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 - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - 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 + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ payload = {} @@ -172,24 +161,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): - """ This endpoint purges a node from the system. Nodes can still join the cluster if they are alive. + 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 5c4def0..4b02392 100644 --- a/nomad/api/nodes.py +++ b/nomad/api/nodes.py @@ -5,13 +5,13 @@ class Nodes(Requester): - """ The nodes endpoint is used to query the status of client nodes. By default, the agent's local region is used https://www.nomadproject.io/docs/http/nodes.html """ + ENDPOINT = "nodes" def __init__(self, **kwargs): @@ -62,16 +62,16 @@ def __iter__(self): return iter(nodes) def get_nodes(self, prefix=None): - """ Lists all the client nodes registered with Nomad. - - https://www.nomadproject.io/docs/http/nodes.html - arguments: - - prefix :(str) optional, specifies a string to filter nodes on based on an prefix. - This is specified as a querystring parameter. - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + """Lists all the client nodes registered with Nomad. + + https://www.nomadproject.io/docs/http/nodes.html + arguments: + - prefix :(str) optional, specifies a string to filter nodes on based on an prefix. + This is specified as a querystring parameter. + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"prefix": prefix} return self.request(method="get", params=params).json() diff --git a/nomad/api/operator.py b/nomad/api/operator.py index b301c18..8fa2146 100644 --- a/nomad/api/operator.py +++ b/nomad/api/operator.py @@ -3,7 +3,6 @@ class Operator(Requester): - """ The Operator endpoint provides cluster-level tools for Nomad operators, such as interacting with the Raft subsystem. @@ -27,37 +26,37 @@ def __getattr__(self, item): raise AttributeError(msg) def get_configuration(self, stale=False): - """ Query the status of a client node registered with Nomad. + """Query the status of a client node registered with Nomad. - https://www.nomadproject.io/docs/http/operator.html + https://www.nomadproject.io/docs/http/operator.html - returns: dict - optional arguments: - - stale, (defaults to False), Specifies if the cluster should respond without an active leader. - This is specified as a querystring parameter. - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: dict + optional arguments: + - stale, (defaults to False), Specifies if the cluster should respond without an active leader. + This is specified as a querystring parameter. + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"stale": stale} return self.request("raft", "configuration", params=params, method="get").json() def delete_peer(self, peer_address, stale=False): - """ Remove the Nomad server with given address from the Raft configuration. - The return code signifies success or failure. - - https://www.nomadproject.io/docs/http/operator.html - - arguments: - - peer_address, The address specifies the server to remove and is given as an IP:port - optional arguments: - - stale, (defaults to False), Specifies if the cluster should respond without an active leader. - This is specified as a querystring parameter. - returns: Boolean - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + """Remove the Nomad server with given address from the Raft configuration. + The return code signifies success or failure. + + https://www.nomadproject.io/docs/http/operator.html + + arguments: + - peer_address, The address specifies the server to remove and is given as an IP:port + optional arguments: + - stale, (defaults to False), Specifies if the cluster should respond without an active leader. + This is specified as a querystring parameter. + returns: Boolean + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"address": peer_address, "stale": stale} diff --git a/nomad/api/regions.py b/nomad/api/regions.py index 76b5038..bc89989 100644 --- a/nomad/api/regions.py +++ b/nomad/api/regions.py @@ -5,10 +5,10 @@ class Regions(Requester): - """ https://www.nomadproject.io/docs/http/regions.html """ + ENDPOINT = "regions" def __init__(self, **kwargs): @@ -55,13 +55,13 @@ def __iter__(self): return iter(regions) def get_regions(self): - """ Returns the known region names. + """Returns the known region names. - https://www.nomadproject.io/docs/http/regions.html + https://www.nomadproject.io/docs/http/regions.html - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request(method="get").json() diff --git a/nomad/api/scaling.py b/nomad/api/scaling.py index 850c76b..a05fa8a 100644 --- a/nomad/api/scaling.py +++ b/nomad/api/scaling.py @@ -10,6 +10,7 @@ class Scaling(Requester): https://developer.hashicorp.com/nomad/api-docs/scaling-policies """ + ENDPOINT = "scaling" def __init__(self, **kwargs): @@ -26,46 +27,47 @@ def __getattr__(self, item): raise AttributeError(msg) # we want to have common arguments name with Nomad API - def get_scaling_policies(self, job="", type=""): # pylint: disable=redefined-builtin + def get_scaling_policies(self, job="", type_=""): # pylint: disable=redefined-builtin """ This endpoint returns the scaling policies from all jobs. https://developer.hashicorp.com/nomad/api-docs/scaling-policies#list-scaling-policies arguments: - - job - - type + - job + - type_ returns: list of dicts raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ type_of_scaling_policies = [ "horizontal", "vertical_mem", "vertical_cpu", "", - ] # we have only horizontal in OSS + ] # we have only horizontal in OSS - if type not in type_of_scaling_policies: - raise nomad.api.exceptions.InvalidParameters("type is invalid " - f"(expected values are {type_of_scaling_policies} but got {type})") + if type_ not in type_of_scaling_policies: + raise nomad.api.exceptions.InvalidParameters( + "type is invalid " f"(expected values are {type_of_scaling_policies} but got {type_})" + ) - params = {"job": job, "type": 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 + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ - return self.request(f"policy/{_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 af8c3bf..e373ee8 100644 --- a/nomad/api/search.py +++ b/nomad/api/search.py @@ -13,6 +13,7 @@ class Search(Requester): https://developer.hashicorp.com/nomad/api-docs/search """ + ENDPOINT = "search" def __init__(self, **kwargs): @@ -29,57 +30,59 @@ def __getattr__(self, item): raise AttributeError(msg) def search(self, prefix, context): - """ The endpoint returns matches for a given prefix and context, where a context can be jobs, - allocations, evaluations, nodes, deployments, plugins, namespaces, or volumes. - - https://developer.hashicorp.com/nomad/api-docs/search - arguments: - - prefix:(str) required, specifies the identifier against which matches will be found. - For example, if the given prefix were "a", potential matches might be "abcd", or "aabb". - - context:(str) defines the scope in which a search for a prefix operates. - Contexts can be: "jobs", "evals", "allocs", "nodes", "deployment", "plugins", - "volumes" or "all", where "all" means every context will be searched. - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException - - nomad.api.exceptions.InvalidParameters + """The endpoint returns matches for a given prefix and context, where a context can be jobs, + allocations, evaluations, nodes, deployments, plugins, namespaces, or volumes. + + https://developer.hashicorp.com/nomad/api-docs/search + arguments: + - prefix:(str) required, specifies the identifier against which matches will be found. + For example, if the given prefix were "a", potential matches might be "abcd", or "aabb". + - context:(str) defines the scope in which a search for a prefix operates. + Contexts can be: "jobs", "evals", "allocs", "nodes", "deployment", "plugins", + "volumes" or "all", where "all" means every context will be searched. + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException + - nomad.api.exceptions.InvalidParameters """ accetaple_contexts = ("jobs", "evals", "allocs", "nodes", "deployment", "plugins", "volumes", "all") if context not in accetaple_contexts: - raise nomad.api.exceptions.InvalidParameters("context is invalid " - f"(expected values are {accetaple_contexts} but got {context})") + raise nomad.api.exceptions.InvalidParameters( + "context is invalid " 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, - fuzzy searching can be done across all contexts. - - https://developer.hashicorp.com/nomad/api-docs/search#fuzzy-searching - arguments: - - text:(str) required, specifies the identifier against which matches will be found. - For example, if the given text were "py", potential fuzzy matches might be "python", "spying", - or "happy". - - context:(str) defines the scope in which a search for a prefix operates. Contexts can be: - "jobs", "allocs", "nodes", "plugins", or "all", where "all" means every context will - be searched. - When "all" is selected, additional prefix matches will be included for the "deployments", - "evals", and "volumes" types. When searching in the "jobs" context, results that fuzzy match - "groups", "services", "tasks", "images", "commands", and "classes" are also included in the results. - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + """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, + fuzzy searching can be done across all contexts. + + https://developer.hashicorp.com/nomad/api-docs/search#fuzzy-searching + arguments: + - text:(str) required, specifies the identifier against which matches will be found. + For example, if the given text were "py", potential fuzzy matches might be "python", "spying", + or "happy". + - context:(str) defines the scope in which a search for a prefix operates. Contexts can be: + "jobs", "allocs", "nodes", "plugins", or "all", where "all" means every context will + be searched. + When "all" is selected, additional prefix matches will be included for the "deployments", + "evals", and "volumes" types. When searching in the "jobs" context, results that fuzzy match + "groups", "services", "tasks", "images", "commands", and "classes" are also included in the results. + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"Text": text, "Context": context} accetaple_contexts = ("jobs", "allocs", "nodes", "plugins", "all") if context not in accetaple_contexts: - raise nomad.api.exceptions.InvalidParameters("context is invalid " - f"(expected values are {accetaple_contexts} but got {context})") + raise nomad.api.exceptions.InvalidParameters( + "context is invalid " 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 ba0d49b..eaf7c20 100644 --- a/nomad/api/sentinel.py +++ b/nomad/api/sentinel.py @@ -3,7 +3,6 @@ class Sentinel(Requester): - """ The endpoint manage sentinel policies (Enterprise Only) @@ -26,73 +25,73 @@ def __getattr__(self, item): raise AttributeError(msg) def get_policies(self): - """ Get a list of policies. + """Get a list of policies. - https://www.nomadproject.io/api/sentinel-policies.html + https://www.nomadproject.io/api/sentinel-policies.html - returns: list + returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("policies", method="get").json() - def create_policy(self, _id, policy): - """ Create policy. + def create_policy(self, id_, policy): + """Create policy. - https://www.nomadproject.io/api/sentinel-policies.html + https://www.nomadproject.io/api/sentinel-policies.html - arguments: - - policy - returns: requests.Response + arguments: + - policy + returns: requests.Response - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - 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): - """ Get a spacific policy. + def get_policy(self, id_): + """Get a spacific policy. - https://www.nomadproject.io/api/sentinel-policies.html + https://www.nomadproject.io/api/sentinel-policies.html - returns: dict + returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - 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): - """ Create policy. + def update_policy(self, id_, policy): + """Create policy. - https://www.nomadproject.io/api/sentinel-policies.html + https://www.nomadproject.io/api/sentinel-policies.html - arguments: - - name - - policy - returns: requests.Response + arguments: + - name + - policy + returns: requests.Response - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + raises: + - 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): - """ Delete specific policy. + def delete_policy(self, id_): + """Delete specific policy. - https://www.nomadproject.io/api/sentinel-policies.html + https://www.nomadproject.io/api/sentinel-policies.html - arguments: - - _id - returns: Boolean + arguments: + - id_ + returns: Boolean - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + 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 3e33501..85d8a42 100644 --- a/nomad/api/status.py +++ b/nomad/api/status.py @@ -4,8 +4,7 @@ from nomad.api.base import Requester -class Status(): - +class Status: """ By default, the agent's local region is used @@ -48,14 +47,14 @@ def __len__(self): return len(leader) def get_leader(self): - """ Returns the address of the current leader in the region. + """Returns the address of the current leader in the region. - https://www.nomadproject.io/docs/http/status.html + https://www.nomadproject.io/docs/http/status.html - returns: string - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: string + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request(method="get").json() @@ -96,13 +95,13 @@ def __iter__(self): return iter(peers) def get_peers(self): - """ Returns the set of raft peers in the region. + """Returns the set of raft peers in the region. - https://www.nomadproject.io/docs/http/status.html + https://www.nomadproject.io/docs/http/status.html - returns: list - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: list + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request(method="get").json() diff --git a/nomad/api/system.py b/nomad/api/system.py index 8437821..4255ab4 100644 --- a/nomad/api/system.py +++ b/nomad/api/system.py @@ -3,7 +3,6 @@ class System(Requester): - """ The system endpoint is used to for system maintenance and should not be necessary for most users. @@ -28,25 +27,25 @@ def __getattr__(self, item): raise AttributeError(msg) def initiate_garbage_collection(self): - """ Initiate garbage collection of jobs, evals, allocations and nodes. + """Initiate garbage collection of jobs, evals, allocations and nodes. - https://www.nomadproject.io/docs/http/system.html + https://www.nomadproject.io/docs/http/system.html - returns: Boolean - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: Boolean + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("gc", method="put").ok def reconcile_summaries(self): - """ This endpoint reconciles the summaries of all registered jobs. + """This endpoint reconciles the summaries of all registered jobs. - https://www.nomadproject.io/docs/http/system.html + https://www.nomadproject.io/docs/http/system.html - returns: Boolean - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + returns: Boolean + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("reconcile", "summaries", method="put").ok diff --git a/nomad/api/validate.py b/nomad/api/validate.py index f0ba03a..ea17fda 100644 --- a/nomad/api/validate.py +++ b/nomad/api/validate.py @@ -28,17 +28,17 @@ def __getattr__(self, item): 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. + """This endpoint validates a Nomad job file. The local Nomad agent forwards the request to a server. In the event a server can't be reached the agent verifies the job file locally but skips validating driver configurations. - https://www.nomadproject.io/api/validate.html + https://www.nomadproject.io/api/validate.html - arguments: - - nomad_job_json, any valid nomad job IN dict FORMAT - returns: dict - raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + arguments: + - nomad_job_json, any valid nomad job IN dict FORMAT + returns: dict + raises: + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ return self.request("job", json=nomad_job_dict, method="post") diff --git a/nomad/api/variable.py b/nomad/api/variable.py index 2ff23a0..7df2446 100644 --- a/nomad/api/variable.py +++ b/nomad/api/variable.py @@ -5,7 +5,6 @@ class Variable(Requester): - """ The /var endpoints are used to read or create variables. https://developer.hashicorp.com/nomad/api-docs/variables @@ -45,11 +44,11 @@ def get_variable(self, var_path, namespace=None): https://developer.hashicorp.com/nomad/api-docs/variables#read-variable arguments: - - var_path :(str), path to variable + - var_path :(str), path to variable returns: dict raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {} if namespace: @@ -63,18 +62,18 @@ def create_variable(self, var_path, payload, namespace=None, cas=None): https://developer.hashicorp.com/nomad/api-docs/variables#create-variable arguments: - - var_path :(str), path to variable - - payload :(dict), variable object. Example: + - var_path :(str), path to variable + - payload :(dict), variable object. Example: https://developer.hashicorp.com/nomad/api-docs/variables#sample-payload - - 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 - current variables ModifyIndex. + - 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 + current variables ModifyIndex. returns: dict raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException - - nomad.api.exceptions.VariableConflict + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException + - nomad.api.exceptions.VariableConflict """ params = {} if cas is not None: @@ -84,23 +83,22 @@ def create_variable(self, var_path, payload, namespace=None, cas=None): return self.request(var_path, params=params, json=payload, method="put").json() - def delete_variable(self, var_path, namespace=None, cas=None): """ This endpoint reads a specific variable by path. This API returns the decrypted variable body. https://developer.hashicorp.com/nomad/api-docs/variables#delete-variable arguments: - - 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 - current variables ModifyIndex. + - 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 + current variables ModifyIndex. returns: dict raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException - - nomad.api.exceptions.VariableConflict + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException + - nomad.api.exceptions.VariableConflict """ params = {} if cas is not None: diff --git a/nomad/api/variables.py b/nomad/api/variables.py index c9d8928..d75f482 100644 --- a/nomad/api/variables.py +++ b/nomad/api/variables.py @@ -3,7 +3,6 @@ class Variables(Requester): - """ The /vars endpoints are used to query for and interact with variables. https://developer.hashicorp.com/nomad/api-docs/variables @@ -50,14 +49,14 @@ def get_variables(self, prefix="", namespace=None): https://developer.hashicorp.com/nomad/api-docs/variables optional_arguments: - - prefix, (default "") Specifies a string to filter variables on based on an index prefix. - This is specified as a query string parameter. - - namespace :(str) optional, Specifies the target namespace. - Specifying * will return all variables across all the authorized namespaces. + - prefix, (default "") Specifies a string to filter variables on based on an index prefix. + This is specified as a query string parameter. + - namespace :(str) optional, Specifies the target namespace. + Specifying * will return all variables across all the authorized namespaces. returns: list of dicts raises: - - nomad.api.exceptions.BaseNomadException - - nomad.api.exceptions.URLNotFoundNomadException + - nomad.api.exceptions.BaseNomadException + - nomad.api.exceptions.URLNotFoundNomadException """ params = {"prefix": prefix} if namespace: diff --git a/requirements-lint.txt b/requirements-lint.txt new file mode 100644 index 0000000..ad9fd7e --- /dev/null +++ b/requirements-lint.txt @@ -0,0 +1,2 @@ +pylint==2.15.10 +black==22.12.0 \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index a871f3b..8630b01 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,12 +2,16 @@ import pytest import tests.common as common + @pytest.fixture def nomad_setup(): n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN) return n + @pytest.fixture def nomad_setup_with_namespace(): - n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN, namespace=common.NOMAD_NAMESPACE) + n = nomad.Nomad( + host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN, namespace=common.NOMAD_NAMESPACE + ) return n diff --git a/tests/test_acl.py b/tests/test_acl.py index d7936fc..863959d 100644 --- a/tests/test_acl.py +++ b/tests/test_acl.py @@ -7,7 +7,10 @@ # integration tests requires nomad Vagrant VM or Binary running # IMPORTANT: without token activated -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported" +) @pytest.mark.run(order=0) def test_create_bootstrap(nomad_setup): bootstrap = nomad_setup.acl.generate_bootstrap() @@ -15,45 +18,59 @@ def test_create_bootstrap(nomad_setup): common.NOMAD_TOKEN = bootstrap["SecretID"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported" +) @pytest.mark.run(order=1) def test_list_tokens(nomad_setup): assert "Bootstrap Token" in nomad_setup.acl.get_tokens()[0]["Name"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported" +) @pytest.mark.run(order=2) def test_create_token(nomad_setup): - token_example='{"Name": "Readonly token","Type": "client","Policies": ["readonly"],"Global": false}' + token_example = '{"Name": "Readonly token","Type": "client","Policies": ["readonly"],"Global": false}' json_token = json.loads(token_example) created_token = nomad_setup.acl.create_token(json_token) assert "Readonly token" in created_token["Name"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported" +) @pytest.mark.run(order=3) def test_list_all_tokens(nomad_setup): tokens = nomad_setup.acl.get_tokens() assert isinstance(tokens, list) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported" +) @pytest.mark.run(order=4) def test_update_token(nomad_setup): - token_example='{"Name": "CreatedForUpdate","Type": "client","Policies": ["readonly"],"Global": false}' + token_example = '{"Name": "CreatedForUpdate","Type": "client","Policies": ["readonly"],"Global": false}' json_token = json.loads(token_example) created_token = nomad_setup.acl.create_token(json_token) - token_update ='{"AccessorID":"' + created_token["AccessorID"] + '","Name": "Updated" ,"Type": "client","Policies": ["readonly"]}' + 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"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported" +) @pytest.mark.run(order=5) def test_get_token(nomad_setup): - token_example='{"Name": "GetToken","Type": "client","Policies": ["readonly"],"Global": false}' + token_example = '{"Name": "GetToken","Type": "client","Policies": ["readonly"],"Global": false}' json_token = json.loads(token_example) created_token = nomad_setup.acl.create_token(json_token) @@ -61,10 +78,12 @@ def test_get_token(nomad_setup): assert "GetToken" in created_token["Name"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported" +) @pytest.mark.run(order=6) def test_delete_token(nomad_setup): - token_example='{"Name": "DeleteToken","Type": "client","Policies": ["readonly"],"Global": false}' + token_example = '{"Name": "DeleteToken","Type": "client","Policies": ["readonly"],"Global": false}' json_token = json.loads(token_example) created_token = nomad_setup.acl.create_token(json_token) assert "DeleteToken" in created_token["Name"] @@ -73,41 +92,53 @@ def test_delete_token(nomad_setup): assert False == any("DeleteToken" in x for x in nomad_setup.acl.get_tokens()) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@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_get_self_token(nomad_setup): current_token = nomad_setup.acl.get_self_token() assert nomad_setup.get_token() in current_token["SecretID"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@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_get_policies(nomad_setup): policies = nomad_setup.acl.get_policies() assert isinstance(policies, list) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@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_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()) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@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_get_policy(nomad_setup): policy = nomad_setup.acl.get_policy("my-policy") assert "This is a great policy" in policy["Description"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@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_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") +@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_allocation.py b/tests/test_allocation.py index 0d02137..1aca38c 100644 --- a/tests/test_allocation.py +++ b/tests/test_allocation.py @@ -20,7 +20,10 @@ def test_get_allocation(nomad_setup): assert isinstance(nomad_setup.allocation.get_allocation(id), dict) == True -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 9, 2), reason="Nomad alloc stop not supported") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 9, 2), + reason="Nomad alloc stop not supported", +) def test_stop_allocation(nomad_setup): id = nomad_setup.job.get_allocations("example")[0]["ID"] assert isinstance(nomad_setup.allocation.stop_allocation(id), dict) == True @@ -69,8 +72,21 @@ def test_dunder_getattr(nomad_setup): def test_get_allocation_with_namespace(nomad_setup_with_namespace): responses.add( responses.GET, - "http://{ip}:{port}/v1/allocation/a8198d79-cfdb-6593-a999-1e9adabcba2e?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE), + "http://{ip}:{port}/v1/allocation/a8198d79-cfdb-6593-a999-1e9adabcba2e?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE + ), status=200, - json={"ID": "a8198d79-cfdb-6593-a999-1e9adabcba2e","EvalID": "5456bd7a-9fc0-c0dd-6131-cbee77f57577","Namespace": common.NOMAD_NAMESPACE, "Name": "example.cache[0]","NodeID": "fb2170a8-257d-3c64-b14d-bc06cc94e34c","PreviousAllocation": "516d2753-0513-cfc7-57ac-2d6fac18b9dc","NextAllocation": "cd13d9b9-4f97-7184-c88b-7b451981616b"} + json={ + "ID": "a8198d79-cfdb-6593-a999-1e9adabcba2e", + "EvalID": "5456bd7a-9fc0-c0dd-6131-cbee77f57577", + "Namespace": common.NOMAD_NAMESPACE, + "Name": "example.cache[0]", + "NodeID": "fb2170a8-257d-3c64-b14d-bc06cc94e34c", + "PreviousAllocation": "516d2753-0513-cfc7-57ac-2d6fac18b9dc", + "NextAllocation": "cd13d9b9-4f97-7184-c88b-7b451981616b", + }, + ) + assert ( + common.NOMAD_NAMESPACE + in nomad_setup_with_namespace.allocation.get_allocation("a8198d79-cfdb-6593-a999-1e9adabcba2e")["Namespace"] ) - assert common.NOMAD_NAMESPACE in nomad_setup_with_namespace.allocation.get_allocation("a8198d79-cfdb-6593-a999-1e9adabcba2e")["Namespace"] diff --git a/tests/test_allocations.py b/tests/test_allocations.py index b35c445..b618786 100644 --- a/tests/test_allocations.py +++ b/tests/test_allocations.py @@ -38,7 +38,7 @@ def test_dunder_getattr(nomad_setup): def test_dunder_iter(nomad_setup): - assert hasattr(nomad_setup.allocations, '__iter__') + assert hasattr(nomad_setup.allocations, "__iter__") for j in nomad_setup.allocations: pass @@ -54,20 +54,47 @@ def test_dunder_len(nomad_setup): def test_get_allocations_with_namespace(nomad_setup_with_namespace): responses.add( responses.GET, - "http://{ip}:{port}/v1/allocations?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE), + "http://{ip}:{port}/v1/allocations?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE + ), status=200, - json=[{"ID": "a8198d79-cfdb-6593-a999-1e9adabcba2e","EvalID": "5456bd7a-9fc0-c0dd-6131-cbee77f57577","Namespace": common.NOMAD_NAMESPACE, "Name": "example.cache[0]","NodeID": "fb2170a8-257d-3c64-b14d-bc06cc94e34c","PreviousAllocation": "516d2753-0513-cfc7-57ac-2d6fac18b9dc","NextAllocation": "cd13d9b9-4f97-7184-c88b-7b451981616b"}] + json=[ + { + "ID": "a8198d79-cfdb-6593-a999-1e9adabcba2e", + "EvalID": "5456bd7a-9fc0-c0dd-6131-cbee77f57577", + "Namespace": common.NOMAD_NAMESPACE, + "Name": "example.cache[0]", + "NodeID": "fb2170a8-257d-3c64-b14d-bc06cc94e34c", + "PreviousAllocation": "516d2753-0513-cfc7-57ac-2d6fac18b9dc", + "NextAllocation": "cd13d9b9-4f97-7184-c88b-7b451981616b", + } + ], ) assert common.NOMAD_NAMESPACE in nomad_setup_with_namespace.allocations.get_allocations()[0]["Namespace"] + @responses.activate def test_get_allocations_with_namespace_override_namespace_declared_on_create(nomad_setup_with_namespace): override_namespace_name = "namespace=override-namespace" responses.add( responses.GET, - "http://{ip}:{port}/v1/allocations?prefix=a8198d79-cfdb-6593-a999-1e9adabcba2e&namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=override_namespace_name), + "http://{ip}:{port}/v1/allocations?prefix=a8198d79-cfdb-6593-a999-1e9adabcba2e&namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=override_namespace_name + ), status=200, - json=[{"ID": "a8198d79-cfdb-6593-a999-1e9adabcba2e","EvalID": "5456bd7a-9fc0-c0dd-6131-cbee77f57577","Namespace": override_namespace_name, "Name": "example.cache[0]","NodeID": "fb2170a8-257d-3c64-b14d-bc06cc94e34c","PreviousAllocation": "516d2753-0513-cfc7-57ac-2d6fac18b9dc","NextAllocation": "cd13d9b9-4f97-7184-c88b-7b451981616b"}] + json=[ + { + "ID": "a8198d79-cfdb-6593-a999-1e9adabcba2e", + "EvalID": "5456bd7a-9fc0-c0dd-6131-cbee77f57577", + "Namespace": override_namespace_name, + "Name": "example.cache[0]", + "NodeID": "fb2170a8-257d-3c64-b14d-bc06cc94e34c", + "PreviousAllocation": "516d2753-0513-cfc7-57ac-2d6fac18b9dc", + "NextAllocation": "cd13d9b9-4f97-7184-c88b-7b451981616b", + } + ], ) - nomad_setup_with_namespace.allocations.get_allocations("a8198d79-cfdb-6593-a999-1e9adabcba2e", namespace=override_namespace_name) \ No newline at end of file + nomad_setup_with_namespace.allocations.get_allocations( + "a8198d79-cfdb-6593-a999-1e9adabcba2e", namespace=override_namespace_name + ) diff --git a/tests/test_base.py b/tests/test_base.py index 08b5711..59b9be3 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -18,7 +18,14 @@ def test_base_region_qs(): def test_base_region_and_namespace_qs(): - n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN, region="random", namespace="test") + n = nomad.Nomad( + host=common.IP, + port=common.NOMAD_PORT, + verify=False, + token=common.NOMAD_TOKEN, + region="random", + namespace="test", + ) qs = n.jobs._query_string_builder("v1/jobs") assert "region" in qs @@ -29,7 +36,14 @@ def test_base_region_and_namespace_qs(): def test_base_region_and_namespace_qs_namespace_override(): - n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN, region="random", namespace="test") + n = nomad.Nomad( + host=common.IP, + port=common.NOMAD_PORT, + verify=False, + token=common.NOMAD_TOKEN, + region="random", + namespace="test", + ) qs = n.jobs._query_string_builder("v1/jobs", {"namespace": "new-namespace"}) assert "namespace" not in qs @@ -38,7 +52,14 @@ def test_base_region_and_namespace_qs_namespace_override(): def test_base_region_and_namespace_qs_region_override(): - n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN, region="random", namespace="test") + n = nomad.Nomad( + host=common.IP, + port=common.NOMAD_PORT, + verify=False, + token=common.NOMAD_TOKEN, + region="random", + namespace="test", + ) qs = n.jobs._query_string_builder("v1/jobs", {"region": "new-region"}) assert "region" not in qs @@ -47,7 +68,14 @@ def test_base_region_and_namespace_qs_region_override(): def test_base_region_and_namespace_qs_overrides_via_params(): - n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN, region="random", namespace="test") + n = nomad.Nomad( + host=common.IP, + port=common.NOMAD_PORT, + verify=False, + token=common.NOMAD_TOKEN, + region="random", + namespace="test", + ) qs = n.jobs._query_string_builder("v1/jobs", {"namespace": "new-namespace", "region": "new-region"}) assert qs == {} @@ -55,22 +83,19 @@ def test_base_region_and_namespace_qs_overrides_via_params(): # integration tests requires nomad Vagrant VM or Binary running def test_base_get_connection_error(): - n = nomad.Nomad( - host="162.16.10.102", port=common.NOMAD_PORT, timeout=0.001, verify=False) + n = nomad.Nomad(host="162.16.10.102", port=common.NOMAD_PORT, timeout=0.001, verify=False) with pytest.raises(nomad.api.exceptions.BaseNomadException): j = n.evaluations["nope"] def test_base_put_connection_error(): - n = nomad.Nomad( - host="162.16.10.102", port=common.NOMAD_PORT, timeout=0.001, verify=False) + n = nomad.Nomad(host="162.16.10.102", port=common.NOMAD_PORT, timeout=0.001, verify=False) with pytest.raises(nomad.api.exceptions.BaseNomadException): j = n.system.initiate_garbage_collection() def test_base_delete_connection_error(): - n = nomad.Nomad( - host="162.16.10.102", port=common.NOMAD_PORT, timeout=0.001, verify=False) + n = nomad.Nomad(host="162.16.10.102", port=common.NOMAD_PORT, timeout=0.001, verify=False) with pytest.raises(nomad.api.exceptions.BaseNomadException): j = n.job.deregister_job("example") @@ -80,12 +105,7 @@ def test_base_raise_exception_not_requests_response_object(mock_requests): mock_requests().delete.side_effect = [requests.RequestException()] with pytest.raises(nomad.api.exceptions.BaseNomadException) as excinfo: - n = nomad.Nomad( - host="162.16.10.102", - port=common.NOMAD_PORT, - timeout=0.001, - verify=False - ) + n = nomad.Nomad(host="162.16.10.102", port=common.NOMAD_PORT, timeout=0.001, verify=False) _ = n.job.deregister_job("example") @@ -109,23 +129,21 @@ def test_base_raise_exception_is_requests_response_object(nomad_setup): assert "raised with" in str(excinfo.value) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 0), reason="Nomad dispatch not supported") +@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_base_get_connnection_not_authorized(): - n = nomad.Nomad( - host=common.IP, port=common.NOMAD_PORT, token='aed2fc63-c155-40d5-b58a-18deed4b73e5', verify=False) + n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT, token="aed2fc63-c155-40d5-b58a-18deed4b73e5", verify=False) with pytest.raises(nomad.api.exceptions.URLNotAuthorizedNomadException): j = n.job.get_job("example") @responses.activate def test_base_use_address_instead_on_host_port(): - responses.add( - responses.GET, - 'https://nomad.service.consul:4646/v1/jobs', - status=200, - json=[] - ) + responses.add(responses.GET, "https://nomad.service.consul:4646/v1/jobs", status=200, json=[]) nomad_address = "https://nomad.service.consul:4646" - n = nomad.Nomad(address=nomad_address, host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN) + n = nomad.Nomad( + address=nomad_address, host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN + ) n.jobs.get_jobs() diff --git a/tests/test_client.py b/tests/test_client.py index 19c24a1..84bd076 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -26,41 +26,53 @@ def test_register_job(nomad_setup): max_iterations -= 1 -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 6), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 6), reason="Not supported in version" +) def test_ls_list_files(nomad_setup): a = nomad_setup.allocations.get_allocations()[0]["ID"] f = nomad_setup.client.ls.list_files(a) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 6), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 6), reason="Not supported in version" +) def test_stat_stat_file(nomad_setup): a = nomad_setup.allocations.get_allocations()[0]["ID"] f = nomad_setup.client.stat.stat_file(a) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 1), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 1), reason="Not supported in version" +) def test_streamfile_fail(nomad_setup): with pytest.raises(nomad.api.exceptions.BadRequestNomadException): a = nomad_setup.allocations.get_allocations()[0]["ID"] - _ = nomad_setup.client.stream_file.stream(a, 1, "start", "/redis/executor") #invalid file name + _ = nomad_setup.client.stream_file.stream(a, 1, "start", "/redis/executor") # invalid file name -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 6), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 6), reason="Not supported in version" +) def test_read_stats(nomad_setup): f = nomad_setup.client.stats.read_stats() -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 6), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 6), reason="Not supported in version" +) def test_read_allocation_stats(nomad_setup): a = nomad_setup.allocations.get_allocations()[0]["ID"] f = nomad_setup.client.allocation.read_allocation_stats(a) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 1), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 1), reason="Not supported in version" +) def test_gc_all_allocations(nomad_setup): node_id = nomad_setup.nodes.get_nodes()[0]["ID"] diff --git a/tests/test_deployment.py b/tests/test_deployment.py index d27bab8..8e0d1ca 100644 --- a/tests/test_deployment.py +++ b/tests/test_deployment.py @@ -16,14 +16,18 @@ def test_register_job(nomad_setup): # integration tests requires nomad Vagrant VM or Binary running -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_get_deployment(nomad_setup): deploymentID = nomad_setup.deployments.get_deployments()[0]["ID"] assert isinstance(nomad_setup.deployment.get_deployment(deploymentID), dict) assert deploymentID == nomad_setup.deployment.get_deployment(deploymentID)["ID"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_get_deployment_allocations(nomad_setup): deploymentID = nomad_setup.deployments.get_deployments()[0]["ID"] assert isinstance(nomad_setup.deployment.get_deployment_allocations(deploymentID), list) @@ -31,7 +35,9 @@ def test_get_deployment_allocations(nomad_setup): assert "example" == nomad_setup.deployment.get_deployment_allocations(deploymentID)[0]["JobID"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_fail_deployment(nomad_setup): deploymentID = nomad_setup.deployments.get_deployments()[0]["ID"] try: @@ -40,7 +46,9 @@ def test_fail_deployment(nomad_setup): assert err.nomad_resp.text == "can't fail terminal deployment" -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_pause_deployment(nomad_setup): deploymentID = nomad_setup.deployments.get_deployments()[0]["ID"] try: @@ -49,7 +57,9 @@ def test_pause_deployment(nomad_setup): assert err.nomad_resp.text == "can't resume terminal deployment" -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_promote_all_deployment(nomad_setup): deploymentID = nomad_setup.deployments.get_deployments()[0]["ID"] try: @@ -58,7 +68,9 @@ def test_promote_all_deployment(nomad_setup): assert err.nomad_resp.text == "can't promote terminal deployment" -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_promote_all_deployment(nomad_setup): deploymentID = nomad_setup.deployments.get_deployments()[0]["ID"] try: @@ -67,7 +79,9 @@ def test_promote_all_deployment(nomad_setup): assert err.nomad_resp.text == "can't promote terminal deployment" -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_deployment_allocation_health(nomad_setup): deploymentID = nomad_setup.deployments.get_deployments()[0]["ID"] allocationID = nomad_setup.deployment.get_deployment(deploymentID)["ID"] @@ -111,6 +125,7 @@ def test_dunder_getattr(nomad_setup): with pytest.raises(AttributeError): _ = nomad_setup.deployment.does_not_exist + @responses.activate # # fix No data when you are using namespaces #82 @@ -118,20 +133,48 @@ def test_dunder_getattr(nomad_setup): def test_get_deployment_with_namespace(nomad_setup_with_namespace): responses.add( responses.GET, - "http://{ip}:{port}/v1/deployment/a8198d79-cfdb-6593-a999-1e9adabcba2e?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE), + "http://{ip}:{port}/v1/deployment/a8198d79-cfdb-6593-a999-1e9adabcba2e?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE + ), status=200, - json={"ID": "70638f62-5c19-193e-30d6-f9d6e689ab8e","JobID": "example", "JobVersion": 1, "JobModifyIndex": 17, "JobSpecModifyIndex": 17, "JobCreateIndex": 7,"Namespace": common.NOMAD_NAMESPACE, "Name": "example.cache[0]"} + json={ + "ID": "70638f62-5c19-193e-30d6-f9d6e689ab8e", + "JobID": "example", + "JobVersion": 1, + "JobModifyIndex": 17, + "JobSpecModifyIndex": 17, + "JobCreateIndex": 7, + "Namespace": common.NOMAD_NAMESPACE, + "Name": "example.cache[0]", + }, + ) + assert ( + common.NOMAD_NAMESPACE + in nomad_setup_with_namespace.deployment.get_deployment("a8198d79-cfdb-6593-a999-1e9adabcba2e")["Namespace"] ) - assert common.NOMAD_NAMESPACE in nomad_setup_with_namespace.deployment.get_deployment("a8198d79-cfdb-6593-a999-1e9adabcba2e")["Namespace"] + @responses.activate def test_get_deployments_with_namespace_override_namespace_declared_on_create(nomad_setup_with_namespace): override_namespace_name = "override-namespace" responses.add( responses.GET, - "http://{ip}:{port}/v1/deployments?prefix=a8198d79-cfdb-6593-a999-1e9adabcba2e&namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=override_namespace_name), + "http://{ip}:{port}/v1/deployments?prefix=a8198d79-cfdb-6593-a999-1e9adabcba2e&namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=override_namespace_name + ), status=200, - json={"ID": "70638f62-5c19-193e-30d6-f9d6e689ab8e","JobID": "example", "JobVersion": 1, "JobModifyIndex": 17, "JobSpecModifyIndex": 17, "JobCreateIndex": 7,"Namespace": override_namespace_name, "Name": "example.cache[0]"} + json={ + "ID": "70638f62-5c19-193e-30d6-f9d6e689ab8e", + "JobID": "example", + "JobVersion": 1, + "JobModifyIndex": 17, + "JobSpecModifyIndex": 17, + "JobCreateIndex": 7, + "Namespace": override_namespace_name, + "Name": "example.cache[0]", + }, ) - nomad_setup_with_namespace.deployments.get_deployments("a8198d79-cfdb-6593-a999-1e9adabcba2e", namespace=override_namespace_name) \ No newline at end of file + nomad_setup_with_namespace.deployments.get_deployments( + "a8198d79-cfdb-6593-a999-1e9adabcba2e", namespace=override_namespace_name + ) diff --git a/tests/test_deployments.py b/tests/test_deployments.py index b361d71..258aedd 100644 --- a/tests/test_deployments.py +++ b/tests/test_deployments.py @@ -14,48 +14,64 @@ def test_register_job(nomad_setup): # integration tests requires nomad Vagrant VM or Binary running -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_get_evaluation(nomad_setup): assert "example" == nomad_setup.deployments.get_deployments()[0]["JobID"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_get_deployments_prefix(nomad_setup): deployments = nomad_setup.deployments.get_deployments() prefix = deployments[0]["ID"][:4] nomad_setup.deployments.get_deployments(prefix=prefix) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_dunder_getitem_exist(nomad_setup): jobID = nomad_setup.deployments.get_deployments()[0]["ID"] d = nomad_setup.deployment[jobID] assert isinstance(d, dict) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_dunder_getitem_not_exist(nomad_setup): with pytest.raises(KeyError): _ = nomad_setup.deployments["nope"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_dunder_contain_exists(nomad_setup): jobID = nomad_setup.deployments.get_deployments()[0]["ID"] assert jobID in nomad_setup.deployments -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_dunder_contain_not_exist(nomad_setup): assert "nope" not in nomad_setup.deployments -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_dunder_len(nomad_setup): assert len(nomad_setup.deployments) == 1 -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_dunder_iter(nomad_setup): for d in nomad_setup.deployments: pass @@ -74,6 +90,7 @@ def test_dunder_getattr(nomad_setup): with pytest.raises(AttributeError): _ = nomad_setup.deployments.does_not_exist + @responses.activate # # fix No data when you are using namespaces #82 @@ -81,8 +98,21 @@ def test_dunder_getattr(nomad_setup): def test_get_deployments_with_namespace(nomad_setup_with_namespace): responses.add( responses.GET, - "http://{ip}:{port}/v1/deployments?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE), + "http://{ip}:{port}/v1/deployments?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE + ), status=200, - json=[{"ID": "70638f62-5c19-193e-30d6-f9d6e689ab8e","JobID": "example", "JobVersion": 1, "JobModifyIndex": 17, "JobSpecModifyIndex": 17, "JobCreateIndex": 7,"Namespace": common.NOMAD_NAMESPACE, "Name": "example.cache[0]"}] + json=[ + { + "ID": "70638f62-5c19-193e-30d6-f9d6e689ab8e", + "JobID": "example", + "JobVersion": 1, + "JobModifyIndex": 17, + "JobSpecModifyIndex": 17, + "JobCreateIndex": 7, + "Namespace": common.NOMAD_NAMESPACE, + "Name": "example.cache[0]", + } + ], ) assert common.NOMAD_NAMESPACE in nomad_setup_with_namespace.deployments.get_deployments()[0]["Namespace"] diff --git a/tests/test_evaluation.py b/tests/test_evaluation.py index 8a80e43..ec16dac 100644 --- a/tests/test_evaluation.py +++ b/tests/test_evaluation.py @@ -14,8 +14,7 @@ def test_register_job(nomad_setup): # integration tests requires nomad Vagrant VM or Binary running def test_get_evaluation(nomad_setup): evalID = nomad_setup.job.get_allocations("example")[0]["EvalID"] - assert isinstance( - nomad_setup.evaluation.get_evaluation(evalID), dict) == True + assert isinstance(nomad_setup.evaluation.get_evaluation(evalID), dict) == True def test_get_allocations(nomad_setup): diff --git a/tests/test_evaluations.py b/tests/test_evaluations.py index 4ca4362..e3befa8 100644 --- a/tests/test_evaluations.py +++ b/tests/test_evaluations.py @@ -57,7 +57,7 @@ def test_dunder_getattr(nomad_setup): def test_dunder_iter(nomad_setup): - assert hasattr(nomad_setup.evaluations, '__iter__') + assert hasattr(nomad_setup.evaluations, "__iter__") for j in nomad_setup.evaluations: pass diff --git a/tests/test_event.py b/tests/test_event.py index 33a805f..3a2fd3b 100644 --- a/tests/test_event.py +++ b/tests/test_event.py @@ -39,6 +39,12 @@ def test_get_event_stream_with_customized_topic(nomad_setup): event = events.get(timeout=5) assert event assert "Index" in event - assert event["Events"][0]["Type"] in ("NodeRegistration", "NodeDeregistration", "NodeEligibility", "NodeDrain", "NodeEvent") + assert event["Events"][0]["Type"] in ( + "NodeRegistration", + "NodeDeregistration", + "NodeEligibility", + "NodeDrain", + "NodeEvent", + ) stream_exit.set() diff --git a/tests/test_job.py b/tests/test_job.py index 992f327..486a101 100644 --- a/tests/test_job.py +++ b/tests/test_job.py @@ -30,37 +30,73 @@ def test_get_job(nomad_setup): def test_get_jobs_with_namespace_override_no_namespace_declared_on_create_incorrect_declared_namespace(nomad_setup): responses.add( responses.GET, - "http://{ip}:{port}/v1/job/18a0f501-41d5-ae43-ff61-1d8ec3ec8314?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE), + "http://{ip}:{port}/v1/job/18a0f501-41d5-ae43-ff61-1d8ec3ec8314?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE + ), status=200, - json=[{"Region": "global","ID": "my-job", "ParentID": "", "Name": "my-job","Namespace": common.NOMAD_NAMESPACE, "Type": "batch", "Priority": 50}] + json=[ + { + "Region": "global", + "ID": "my-job", + "ParentID": "", + "Name": "my-job", + "Namespace": common.NOMAD_NAMESPACE, + "Type": "batch", + "Priority": 50, + } + ], ) 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 def test_get_jobs_with_namespace_override_no_namespace_declared_on_create(nomad_setup): responses.add( responses.GET, - "http://{ip}:{port}/v1/job/18a0f501-41d5-ae43-ff61-1d8ec3ec8314?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE), + "http://{ip}:{port}/v1/job/18a0f501-41d5-ae43-ff61-1d8ec3ec8314?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE + ), status=200, - json=[{"Region": "global","ID": "my-job", "ParentID": "", "Name": "my-job","Namespace": common.NOMAD_NAMESPACE, "Type": "batch", "Priority": 50}] + 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 def test_get_jobs_with_namespace_override_namespace_declared_on_create(nomad_setup_with_namespace): responses.add( responses.GET, - "http://{ip}:{port}/v1/job/18a0f501-41d5-ae43-ff61-1d8ec3ec8314?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace="override-namespace"), + "http://{ip}:{port}/v1/job/18a0f501-41d5-ae43-ff61-1d8ec3ec8314?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace="override-namespace" + ), status=200, - json=[{"Region": "global","ID": "my-job", "ParentID": "", "Name": "my-job","Namespace": common.NOMAD_NAMESPACE, "Type": "batch", "Priority": 50}] + 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): @@ -78,6 +114,7 @@ def test_get_evaluations(nomad_setup): def test_evaluate_job(nomad_setup): assert "EvalID" in nomad_setup.job.evaluate_job("example") + # def test_periodic_job(nomad_setup): # assert "EvalID" in nomad_setup.job.periodic_job("example") @@ -88,68 +125,93 @@ def test_delete_job(nomad_setup): @flaky(max_runs=5, min_passes=1) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 3), reason="Nomad dispatch not supported") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 3), reason="Nomad dispatch not supported" +) def test_dispatch_job(nomad_setup): with open("example_batch_parameterized.json") as fh: job = json.loads(fh.read()) nomad_setup.job.register_job("example-batch", job) try: nomad_setup.job.dispatch_job("example-batch", meta={"time": "500"}) - except (exceptions.URLNotFoundNomadException, - exceptions.BaseNomadException) as e: + except (exceptions.URLNotFoundNomadException, exceptions.BaseNomadException) as e: print(e.nomad_resp.text) raise e assert "example-batch" in nomad_setup.job -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 3), reason="Nomad dispatch not supported") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 3), reason="Nomad dispatch not supported" +) def test_summary_job(nomad_setup): j = nomad_setup.job["example"] assert "JobID" in nomad_setup.job.get_summary(j["ID"]) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 4, 0), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 4, 0), reason="Not supported in version" +) def test_plan_job(nomad_setup): with open("example.json") as fh: job = json.loads(fh.read()) - assert "Index" in nomad_setup.job.plan_job(nomad_setup.job["example"]["ID"],job) + assert "Index" in nomad_setup.job.plan_job(nomad_setup.job["example"]["ID"], job) + -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_versions_job(nomad_setup): assert "Versions" in nomad_setup.job.get_versions("example") -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_versions_job_missing(nomad_setup): with pytest.raises(nomad.api.exceptions.URLNotFoundNomadException): assert "Versions" in nomad_setup.job.get_versions("example1") -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_get_job_deployments(nomad_setup): assert "JobID" in nomad_setup.job.get_deployments("example")[0] assert isinstance(nomad_setup.job.get_deployments("example"), list) assert isinstance(nomad_setup.job.get_deployments("example")[0], dict) assert "example" == nomad_setup.job.get_deployments("example")[0]["JobID"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_get_job_deployment(nomad_setup): assert "JobID" in nomad_setup.job.get_deployment("example") assert isinstance(nomad_setup.job.get_deployment("example"), dict) 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") + +@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_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"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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") +@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): current_job_version = nomad_setup.job.get_deployment("example")["JobVersion"] nomad_setup.job.stable_job("example", current_job_version, True) @@ -187,9 +249,11 @@ def test_dunder_getattr(nomad_setup): with pytest.raises(AttributeError): d = nomad_setup.job.does_not_exist + def test_delete_job_with_invalid_purge_param_raises(nomad_setup): with pytest.raises(exceptions.InvalidParameters): - nomad_setup.job.deregister_job("example", purge='True') + nomad_setup.job.deregister_job("example", purge="True") + def test_delete_job_with_purge(nomad_setup): # Run this last since it will purge the job completely, resetting things like diff --git a/tests/test_jobs.py b/tests/test_jobs.py index 860bf58..05d5895 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -25,7 +25,9 @@ def test_get_jobs_prefix(nomad_setup): nomad_setup.jobs.get_jobs(prefix="ex") -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 3), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 3), reason="Not supported in version" +) def test_parse_job(nomad_setup): with open("example.nomad") as fh: hcl = fh.read() @@ -68,7 +70,7 @@ def test_dunder_getattr(nomad_setup): def test_dunder_iter(nomad_setup): - assert hasattr(nomad_setup.jobs, '__iter__') + assert hasattr(nomad_setup.jobs, "__iter__") for j in nomad_setup.jobs: pass @@ -82,9 +84,21 @@ def test_dunder_len(nomad_setup): def test_get_jobs_with_namespace(nomad_setup_with_namespace): responses.add( responses.GET, - "http://{ip}:{port}/v1/jobs?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE), + "http://{ip}:{port}/v1/jobs?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE + ), status=200, - json=[{"Region": "global","ID": "my-job", "ParentID": "", "Name": "my-job","Namespace": common.NOMAD_NAMESPACE, "Type": "batch", "Priority": 50}] + json=[ + { + "Region": "global", + "ID": "my-job", + "ParentID": "", + "Name": "my-job", + "Namespace": common.NOMAD_NAMESPACE, + "Type": "batch", + "Priority": 50, + } + ], ) assert common.NOMAD_NAMESPACE in nomad_setup_with_namespace.jobs.get_jobs()[0]["Namespace"] @@ -93,9 +107,21 @@ def test_get_jobs_with_namespace(nomad_setup_with_namespace): def test_get_jobs_with_namespace_override_no_namespace_declared_on_create_incorrect_declared_namespace(nomad_setup): responses.add( responses.GET, - "http://{ip}:{port}/v1/jobs?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE), + "http://{ip}:{port}/v1/jobs?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE + ), status=200, - json=[{"Region": "global","ID": "my-job", "ParentID": "", "Name": "my-job","Namespace": common.NOMAD_NAMESPACE, "Type": "batch", "Priority": 50}] + json=[ + { + "Region": "global", + "ID": "my-job", + "ParentID": "", + "Name": "my-job", + "Namespace": common.NOMAD_NAMESPACE, + "Type": "batch", + "Priority": 50, + } + ], ) with pytest.raises(BaseNomadException): @@ -106,9 +132,21 @@ def test_get_jobs_with_namespace_override_no_namespace_declared_on_create_incorr def test_get_jobs_with_namespace_override_no_namespace_declared_on_create(nomad_setup): responses.add( responses.GET, - "http://{ip}:{port}/v1/jobs?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE), + "http://{ip}:{port}/v1/jobs?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace=common.NOMAD_NAMESPACE + ), status=200, - json=[{"Region": "global","ID": "my-job", "ParentID": "", "Name": "my-job","Namespace": common.NOMAD_NAMESPACE, "Type": "batch", "Priority": 50}] + json=[ + { + "Region": "global", + "ID": "my-job", + "ParentID": "", + "Name": "my-job", + "Namespace": common.NOMAD_NAMESPACE, + "Type": "batch", + "Priority": 50, + } + ], ) nomad_setup.jobs.get_jobs(namespace=common.NOMAD_NAMESPACE) @@ -118,9 +156,21 @@ def test_get_jobs_with_namespace_override_no_namespace_declared_on_create(nomad_ def test_get_jobs_with_namespace_override_namespace_declared_on_create(nomad_setup_with_namespace): responses.add( responses.GET, - "http://{ip}:{port}/v1/jobs?namespace={namespace}".format(ip=common.IP, port=common.NOMAD_PORT, namespace="override-namespace"), + "http://{ip}:{port}/v1/jobs?namespace={namespace}".format( + ip=common.IP, port=common.NOMAD_PORT, namespace="override-namespace" + ), status=200, - json=[{"Region": "global","ID": "my-job", "ParentID": "", "Name": "my-job","Namespace": common.NOMAD_NAMESPACE, "Type": "batch", "Priority": 50}] + json=[ + { + "Region": "global", + "ID": "my-job", + "ParentID": "", + "Name": "my-job", + "Namespace": common.NOMAD_NAMESPACE, + "Type": "batch", + "Priority": 50, + } + ], ) - nomad_setup_with_namespace.jobs.get_jobs(namespace="override-namespace") \ No newline at end of file + nomad_setup_with_namespace.jobs.get_jobs(namespace="override-namespace") diff --git a/tests/test_metrics.py b/tests/test_metrics.py index 9d7bc00..618db14 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -3,7 +3,9 @@ # integration tests requires nomad Vagrant VM or Binary running -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 1), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 7, 1), reason="Not supported in version" +) def test_metrics(nomad_setup): nomad_setup.metrics.get_metrics() @@ -19,4 +21,4 @@ def test_dunder_repr(nomad_setup): def test_dunder_getattr(nomad_setup): with pytest.raises(AttributeError): - d = nomad_setup.metrics.does_not_exist \ No newline at end of file + d = nomad_setup.metrics.does_not_exist diff --git a/tests/test_namespace.py b/tests/test_namespace.py index 57077bf..53a3924 100644 --- a/tests/test_namespace.py +++ b/tests/test_namespace.py @@ -9,9 +9,7 @@ def test_create_namespace(nomad_setup): responses.add( - responses.POST, - "http://{ip}:{port}/v1/namespace".format(ip=common.IP, port=common.NOMAD_PORT), - status=200 + responses.POST, "http://{ip}:{port}/v1/namespace".format(ip=common.IP, port=common.NOMAD_PORT), status=200 ) namespace_api = '{"Name":"api","Description":"api server namespace"}' @@ -23,9 +21,7 @@ def test_create_namespace(nomad_setup): def test_update_namespace(nomad_setup): responses.add( - responses.POST, - "http://{ip}:{port}/v1/namespace/api".format(ip=common.IP, port=common.NOMAD_PORT), - status=200 + responses.POST, "http://{ip}:{port}/v1/namespace/api".format(ip=common.IP, port=common.NOMAD_PORT), status=200 ) namespace_api = '{"Name":"api","Description":"updated namespace"}' @@ -40,7 +36,7 @@ def test_get_namespace(nomad_setup): responses.GET, "http://{ip}:{port}/v1/namespace/api".format(ip=common.IP, port=common.NOMAD_PORT), status=200, - json={"Name": "api", "Description": "api server namespace"} + json={"Name": "api", "Description": "api server namespace"}, ) assert "api" in nomad_setup.namespace.get_namespace("api")["Name"] @@ -57,7 +53,6 @@ def test_delete_namespace(nomad_setup): nomad_setup.namespace.delete_namespace("api") - ######### ENTERPRISE TEST ########### # def test_apply_namespace(nomad_setup): # namespace_api='{"Name":"api","Description":"api server namespace"}' diff --git a/tests/test_namespaces.py b/tests/test_namespaces.py index 393baa8..46e51f2 100644 --- a/tests/test_namespaces.py +++ b/tests/test_namespaces.py @@ -12,19 +12,9 @@ def test_get_namespaces(nomad_setup): "http://{ip}:{port}/v1/namespaces".format(ip=common.IP, port=common.NOMAD_PORT), status=200, json=[ - { - "CreateIndex": 31, - "Description": "Production API Servers", - "ModifyIndex": 31, - "Name": "api-prod" - }, - { - "CreateIndex": 5, - "Description": "Default shared namespace", - "ModifyIndex": 5, - "Name": "default" - } - ] + {"CreateIndex": 31, "Description": "Production API Servers", "ModifyIndex": 31, "Name": "api-prod"}, + {"CreateIndex": 5, "Description": "Default shared namespace", "ModifyIndex": 5, "Name": "default"}, + ], ) assert isinstance(nomad_setup.namespaces.get_namespaces(), list) == True @@ -37,13 +27,8 @@ def test_get_namespaces_prefix(nomad_setup): "http://{ip}:{port}/v1/namespaces?prefix=api-".format(ip=common.IP, port=common.NOMAD_PORT), status=200, json=[ - { - "CreateIndex": 31, - "Description": "Production API Servers", - "ModifyIndex": 31, - "Name": "api-prod" - }, - ] + {"CreateIndex": 31, "Description": "Production API Servers", "ModifyIndex": 31, "Name": "api-prod"}, + ], ) assert isinstance(nomad_setup.namespaces.get_namespaces(prefix="api-"), list) == True @@ -56,19 +41,9 @@ def test_namespaces_iter(nomad_setup): "http://{ip}:{port}/v1/namespaces".format(ip=common.IP, port=common.NOMAD_PORT), status=200, json=[ - { - "CreateIndex": 31, - "Description": "Production API Servers", - "ModifyIndex": 31, - "Name": "api-prod" - }, - { - "CreateIndex": 5, - "Description": "Default shared namespace", - "ModifyIndex": 5, - "Name": "default" - } - ] + {"CreateIndex": 31, "Description": "Production API Servers", "ModifyIndex": 31, "Name": "api-prod"}, + {"CreateIndex": 5, "Description": "Default shared namespace", "ModifyIndex": 5, "Name": "default"}, + ], ) assert "api-prod" in nomad_setup.namespaces @@ -81,19 +56,9 @@ def test_namespaces_len(nomad_setup): "http://{ip}:{port}/v1/namespaces".format(ip=common.IP, port=common.NOMAD_PORT), status=200, json=[ - { - "CreateIndex": 31, - "Description": "Production API Servers", - "ModifyIndex": 31, - "Name": "api-prod" - }, - { - "CreateIndex": 5, - "Description": "Default shared namespace", - "ModifyIndex": 5, - "Name": "default" - } - ] + {"CreateIndex": 31, "Description": "Production API Servers", "ModifyIndex": 31, "Name": "api-prod"}, + {"CreateIndex": 5, "Description": "Default shared namespace", "ModifyIndex": 5, "Name": "default"}, + ], ) assert 2 == len(nomad_setup.namespaces) diff --git a/tests/test_node.py b/tests/test_node.py index d63274b..055b1f5 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -23,7 +23,9 @@ def test_evaluate_node(nomad_setup): assert "EvalIDs" in nomad_setup.node.evaluate_node(nodeID) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) > (1, 1, 0), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) > (1, 1, 0), reason="Not supported in version" +) def test_drain_node(nomad_setup): nodeID = nomad_setup.nodes["pynomad1"]["ID"] assert "EvalIDs" in nomad_setup.node.drain_node(nodeID) @@ -33,7 +35,9 @@ def test_drain_node(nomad_setup): assert nomad_setup.node[nodeID]["Drain"] is False -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 1), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 1), reason="Not supported in version" +) def test_drain_node_with_spec(nomad_setup): nodeID = nomad_setup.nodes["pynomad1"]["ID"] assert "EvalIDs" in nomad_setup.node.drain_node_with_spec(nodeID, drain_spec={"Duration": "-100000000"}) @@ -42,7 +46,9 @@ def test_drain_node_with_spec(nomad_setup): assert nomad_setup.node[nodeID]["Drain"] is False -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 1), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 8, 1), reason="Not supported in version" +) def test_eligible_node(nomad_setup): nodeID = nomad_setup.nodes["pynomad1"]["ID"] diff --git a/tests/test_nodes.py b/tests/test_nodes.py index f708682..0214902 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -46,7 +46,7 @@ def test_dunder_getattr(nomad_setup): def test_dunder_iter(nomad_setup): - assert hasattr(nomad_setup.nodes, '__iter__') + assert hasattr(nomad_setup.nodes, "__iter__") for j in nomad_setup.nodes: pass diff --git a/tests/test_operator.py b/tests/test_operator.py index 85747e4..85d94f3 100644 --- a/tests/test_operator.py +++ b/tests/test_operator.py @@ -4,17 +4,23 @@ # integration tests requires nomad Vagrant VM or Binary running -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 5), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 5), reason="Not supported in version" +) def test_get_configuration_default(nomad_setup): assert isinstance(nomad_setup.operator.get_configuration(), dict) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 5), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 5), reason="Not supported in version" +) def test_get_configuration_stale(nomad_setup): assert isinstance(nomad_setup.operator.get_configuration(stale=True), dict) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 5), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 5, 5), reason="Not supported in version" +) def test_delete_peer(nomad_setup): with pytest.raises(exceptions.BaseNomadException): nomad_setup.operator.delete_peer("192.168.33.10:4646") diff --git a/tests/test_regions.py b/tests/test_regions.py index 4a16139..5654419 100644 --- a/tests/test_regions.py +++ b/tests/test_regions.py @@ -44,7 +44,7 @@ def test_dunder_getattr(nomad_setup): def test_dunder_iter(nomad_setup): - assert hasattr(nomad_setup.regions, '__iter__') + assert hasattr(nomad_setup.regions, "__iter__") for j in nomad_setup.regions: pass diff --git a/tests/test_scaling.py b/tests/test_scaling.py index 686ad3b..ffc3ff2 100644 --- a/tests/test_scaling.py +++ b/tests/test_scaling.py @@ -2,10 +2,12 @@ from nomad.api import exceptions + def test_scaling_list(nomad_setup): result = nomad_setup.scaling.get_scaling_policies() assert not result + def test_scaling_policy_not_exist(nomad_setup): with pytest.raises(exceptions.URLNotFoundNomadException): nomad_setup.scaling.get_scaling_policy("example") diff --git a/tests/test_search.py b/tests/test_search.py index 6b291ae..04812b3 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -3,32 +3,50 @@ from nomad.api import exceptions -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version" +) def test_search(nomad_setup): result = nomad_setup.search.search("example", "jobs") assert "example" in result["Matches"]["jobs"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version" +) def test_search_incorrect_context(nomad_setup): # job context doesn't exist with pytest.raises(exceptions.InvalidParameters): nomad_setup.search.search("example", "job") -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version" +) def test_search_fuzzy(nomad_setup): result = nomad_setup.search.fuzzy_search("example", "jobs") - assert any(r['ID'] == 'example' for r in result["Matches"]["jobs"]) + assert any(r["ID"] == "example" for r in result["Matches"]["jobs"]) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version" +) def test_search_fuzzy_incorrect_context(nomad_setup): # job context doesn't exist with pytest.raises(exceptions.InvalidParameters): nomad_setup.search.fuzzy_search("example", "job") -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version" +) def test_search_str(nomad_setup): assert isinstance(str(nomad_setup.search), str) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 1, 0), reason="Not supported in version" +) def test_search_repr(nomad_setup): - assert isinstance(repr(nomad_setup.search), str) \ No newline at end of file + assert isinstance(repr(nomad_setup.search), str) diff --git a/tests/test_sentinel.py b/tests/test_sentinel.py index 5d26057..99de2fb 100644 --- a/tests/test_sentinel.py +++ b/tests/test_sentinel.py @@ -19,9 +19,9 @@ def test_list_policies(nomad_setup): "EnforcementLevel": "advisory", "Hash": "CIs8aNX5OfFvo4D7ihWcQSexEJpHp+Za+dHSncVx5+8=", "CreateIndex": 8, - "ModifyIndex": 8 + "ModifyIndex": 8, } - ] + ], ) policies = nomad_setup.sentinel.get_policies() @@ -35,26 +35,22 @@ def test_create_policy(nomad_setup): responses.add( responses.POST, "http://{ip}:{port}/v1/sentinel/policy/my-policy".format(ip=common.IP, port=common.NOMAD_PORT), - status=200 + status=200, ) 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 def test_update_policy(nomad_setup): - responses.add( - responses.POST, - f"http://{common.IP}:{common.NOMAD_PORT}/v1/sentinel/policy/my-policy", - status=200 - ) + responses.add(responses.POST, 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 @@ -71,8 +67,8 @@ def test_get_policy(nomad_setup): "Policy": "main = rule { true }\n", "Hash": "CIs8aNX5OfFvo4D7ihWcQSexEJpHp+Za+dHSncVx5+8=", "CreateIndex": 8, - "ModifyIndex": 8 - } + "ModifyIndex": 8, + }, ) policy = nomad_setup.sentinel.get_policy("foo") @@ -93,8 +89,8 @@ def test_delete_policy(nomad_setup): "Policy": "main = rule { true }\n", "Hash": "CIs8aNX5OfFvo4D7ihWcQSexEJpHp+Za+dHSncVx5+8=", "CreateIndex": 8, - "ModifyIndex": 8 - } + "ModifyIndex": 8, + }, ) - nomad_setup.sentinel.delete_policy(_id="my-policy") + nomad_setup.sentinel.delete_policy(id_="my-policy") diff --git a/tests/test_status.py b/tests/test_status.py index f29494b..dde1a39 100644 --- a/tests/test_status.py +++ b/tests/test_status.py @@ -8,8 +8,7 @@ def test_get_leader(nomad_setup): if int(sys.version[0]) == 3: assert isinstance(nomad_setup.status.leader.get_leader(), str) == True else: - assert isinstance( - nomad_setup.status.leader.get_leader(), unicode) == True + assert isinstance(nomad_setup.status.leader.get_leader(), unicode) == True def test_get_peers(nomad_setup): @@ -35,8 +34,7 @@ def test_peers_dunder_contain_exists(nomad_setup): def test_peers_dunder_contain_not_exist(nomad_setup): - assert "{IP}:4647".format( - IP="172.16.10.100") not in nomad_setup.status.peers + assert "{IP}:4647".format(IP="172.16.10.100") not in nomad_setup.status.peers def test_leader_dunder_contain_exists(nomad_setup): @@ -44,8 +42,7 @@ def test_leader_dunder_contain_exists(nomad_setup): def test_leader_dunder_contain_not_exist(nomad_setup): - assert "{IP}:4647".format( - IP="172.16.10.100") not in nomad_setup.status.leader + assert "{IP}:4647".format(IP="172.16.10.100") not in nomad_setup.status.leader def test_dunder_str(nomad_setup): @@ -67,7 +64,7 @@ def test_dunder_getattr(nomad_setup): def test_peers_dunder_iter(nomad_setup): - assert hasattr(nomad_setup.status.peers, '__iter__') + assert hasattr(nomad_setup.status.peers, "__iter__") for p in nomad_setup.status.peers: pass diff --git a/tests/test_validate.py b/tests/test_validate.py index 1efde82..9888369 100644 --- a/tests/test_validate.py +++ b/tests/test_validate.py @@ -5,14 +5,18 @@ # integration tests requires nomad Vagrant VM or Binary running -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_validate_job(nomad_setup): with open("example.json") as job: nomad_setup.validate.validate_job(json.loads(job.read())) # integration tests requires nomad Vagrant VM or Binary running -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (0, 6, 0), reason="Not supported in 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_invalid_job(nomad_setup): with pytest.raises(nomad.api.exceptions.BadRequestNomadException): nomad_setup.validate.validate_job({}) diff --git a/tests/test_variable.py b/tests/test_variable.py index 66ff38a..a1d1056 100644 --- a/tests/test_variable.py +++ b/tests/test_variable.py @@ -1,10 +1,13 @@ import pytest import os + # Nomad doesn't have any variables by default from nomad.api import exceptions -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_create_variable(nomad_setup): payload = { "Items": {"user": "test", "password": "test123"}, @@ -12,7 +15,10 @@ def test_create_variable(nomad_setup): nomad_setup.variable.create_variable("example/first", payload) assert "example/first" in nomad_setup.variables -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_create_variable_in_namespace(nomad_setup): payload = { "Items": {"user": "test2", "password": "321tset"}, @@ -20,7 +26,10 @@ def test_create_variable_in_namespace(nomad_setup): nomad_setup.variable.create_variable("example/second", payload, namespace="default") assert "example/second" in nomad_setup.variables -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_create_variable_with_cas(nomad_setup): payload = { "Items": {"user": "test3", "password": "321tset123"}, @@ -28,67 +37,106 @@ def test_create_variable_with_cas(nomad_setup): nomad_setup.variable.create_variable("example/third", payload, cas=0) assert "example/third" in nomad_setup.variables -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_get_variable_and_check_value(nomad_setup): var = nomad_setup.variable.get_variable("example/first") assert var["Items"]["user"] == "test" -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_get_variable_in_namespace(nomad_setup): var = nomad_setup.variable.get_variable("example/first", namespace="default") assert var["Items"]["user"] == "test" -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_get_no_exist_variable(nomad_setup): with pytest.raises(KeyError): assert nomad_setup.variable["no_exist"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variable_getitem_exist(nomad_setup): var = nomad_setup.variable["example/first"] assert isinstance(var, dict) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variable_str(nomad_setup): assert isinstance(str(nomad_setup.variable), str) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variable_repr(nomad_setup): assert isinstance(repr(nomad_setup.variable), str) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variable_getattr(nomad_setup): with pytest.raises(AttributeError): nomad_setup.variable.does_not_exist -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variable_exist(nomad_setup): assert "example/second" in nomad_setup.variable -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variable_no_exist(nomad_setup): assert "no_exist" not in nomad_setup.variable -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variable_getitem_not_exist(nomad_setup): with pytest.raises(KeyError): nomad_setup.variable["no_exists"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_delete_variable(nomad_setup): assert 3 == len(nomad_setup.variables.get_variables()) nomad_setup.variable.delete_variable("example/third") assert "example/third" not in nomad_setup.variables assert 2 == len(nomad_setup.variables.get_variables()) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_delete_variable_in_namespace(nomad_setup): assert 2 == len(nomad_setup.variables.get_variables()) nomad_setup.variable.delete_variable("example/second", namespace="default") assert "example/third" not in nomad_setup.variables assert 1 == len(nomad_setup.variables.get_variables()) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_delete_variable_with_cas(nomad_setup): variable_path = "variable_with_cas" payload = { diff --git a/tests/test_variables.py b/tests/test_variables.py index cf096e2..c39d31b 100644 --- a/tests/test_variables.py +++ b/tests/test_variables.py @@ -1,55 +1,91 @@ import pytest import os -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_get_variables(nomad_setup): assert 1 == len(nomad_setup.variables.get_variables()) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_get_variables_with_prefix(nomad_setup): assert 1 == len(nomad_setup.variables.get_variables("example/first")) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_get_variables_with_prefix_no_exist(nomad_setup): assert 0 == len(nomad_setup.variables.get_variables("no_exist_var")) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_get_variables_from_namespace(nomad_setup): assert 1 == len(nomad_setup.variables.get_variables(namespace="default")) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_iter_variables(nomad_setup): - assert hasattr(nomad_setup.variables, '__iter__') + assert hasattr(nomad_setup.variables, "__iter__") for _ in nomad_setup.variables: pass -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variables_str(nomad_setup): assert isinstance(str(nomad_setup.variables), str) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variables_repr(nomad_setup): assert isinstance(repr(nomad_setup.variables), str) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variables_not_exist(nomad_setup): assert "no_exist" not in nomad_setup.variables -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variables_exist(nomad_setup): assert "example/first" in nomad_setup.variables -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variables_getitem_exist(nomad_setup): var = nomad_setup.variables["example/first"] assert isinstance(var, dict) -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variables_getitem_not_exist(nomad_setup): with pytest.raises(KeyError): nomad_setup.variables["no_exists"] -@pytest.mark.skipif(tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version") + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 4, 0), reason="Not supported in version" +) def test_variables_getattr(nomad_setup): with pytest.raises(AttributeError): - nomad_setup.variables.does_not_exist \ No newline at end of file + nomad_setup.variables.does_not_exist From 975b9027b97630920ee8a838838dd63b13775774 Mon Sep 17 00:00:00 2001 From: El Nerdo <10955996+elnerd@users.noreply.github.com> Date: Wed, 22 Feb 2023 18:48:05 +0100 Subject: [PATCH 05/12] Fixed ${NOMAD_META_TIME -> ${NOMAD_META_TIME} (#147) Corrected small typo in example --- docs/api/job.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/job.md b/docs/api/job.md index 9e7d39d..4008d4d 100644 --- a/docs/api/job.md +++ b/docs/api/job.md @@ -287,7 +287,7 @@ parametrize_job = { "Name": "example-task", "Driver": "docker", "Config": { - "args": ["${NOMAD_META_TIME"], + "args": ["${NOMAD_META_TIME}"], "command": "sleep", "image": "scratch", "logging": [], From d65f5daaa75154ef4d4cbd2498aa5e5a5b4a87c1 Mon Sep 17 00:00:00 2001 From: Alex K Date: Mon, 27 Mar 2023 09:57:36 -0400 Subject: [PATCH 06/12] chore(docs): update link to the docs (#148) Co-authored-by: Alex Konyukov --- docs/api/acl.md | 24 ++++++++++++------------ docs/api/agent.md | 14 +++++++------- docs/api/allocation.md | 2 +- docs/api/allocations.md | 2 +- docs/api/client.md | 2 +- docs/api/deployment.md | 12 ++++++------ docs/api/deployments.md | 2 +- docs/api/evaluation.md | 4 ++-- docs/api/evaluations.md | 2 +- docs/api/job.md | 30 +++++++++++++++--------------- docs/api/jobs.md | 6 +++--- docs/api/metrics.md | 2 +- docs/api/namespace.md | 8 ++++---- docs/api/namespaces.md | 2 +- docs/api/node.md | 14 +++++++------- docs/api/nodes.md | 2 +- docs/api/regions.md | 2 +- docs/api/sentinel.md | 10 +++++----- docs/api/status.md | 4 ++-- docs/api/system.md | 4 ++-- docs/api/validate.md | 2 +- 21 files changed, 75 insertions(+), 75 deletions(-) diff --git a/docs/api/acl.md b/docs/api/acl.md index 34ec265..90fe636 100644 --- a/docs/api/acl.md +++ b/docs/api/acl.md @@ -8,7 +8,7 @@ Nomad must be running with ACL mode enabled. This endpoint is used to bootstrap the ACL system and provide the initial management token. This request is always forwarded to the authoritative region. It can only be invoked once until a bootstrap reset is performed. -https://www.nomadproject.io/api/acl-tokens.html#bootstrap-token +https://developer.hashicorp.com/nomad/api-docs/acl/tokens#bootstrap-token Example: @@ -48,7 +48,7 @@ print (my_nomad.get_token()) This endpoint lists all ACL tokens. This lists the local tokens and the global tokens which have been replicated to the region, and may lag behind the authoritative region. -https://www.nomadproject.io/api/acl-tokens.html#list-tokens +https://developer.hashicorp.com/nomad/api-docs/acl/tokens#list-tokens Exmaple: @@ -68,7 +68,7 @@ for token in tokens: This endpoint creates an ACL Token. If the token is a global token, the request is forwarded to the authoritative region. -https://www.nomadproject.io/api/acl-tokens.html#create-token +https://developer.hashicorp.com/nomad/api-docs/acl/tokens#create-token Exmample: @@ -91,7 +91,7 @@ created_token = my_nomad.acl.create_token(new_token) This endpoint updates an existing ACL Token. If the token is a global token, the request is forwarded to the authoritative region. Note that a token cannot be switched from global to local or vice versa. -https://www.nomadproject.io/api/acl-tokens.html#update-token +https://developer.hashicorp.com/nomad/api-docs/acl/tokens#update-token Example: @@ -115,7 +115,7 @@ updated_token = my_nomad.acl.update_token('377ba749-8b0e-c7fd-c0c0-9da5bb943088' This endpoint reads an ACL token with the given accessor. If the token is a global token which has been replicated to the region it may lag behind the authoritative region. -https://www.nomadproject.io/api/acl-tokens.html#read-token +https://developer.hashicorp.com/nomad/api-docs/acl/tokens#read-token Exmaple: @@ -131,7 +131,7 @@ token = my_nomad.acl.get_token("377ba749-8b0e-c7fd-c0c0-9da5bb943088") This endpoint reads the ACL token given by the passed SecretID. If the token is a global token which has been replicated to the region it may lag behind the authoritative region. -https://www.nomadproject.io/api/acl-tokens.html#read-self-token +https://developer.hashicorp.com/nomad/api-docs/acl/tokens#read-self-token Exmaple: @@ -147,7 +147,7 @@ self_token = my_nomad.acl.get_self_token() This endpoint deletes the ACL token by accessor. This request is forwarded to the authoritative region for global tokens. -https://www.nomadproject.io/api/acl-tokens.html#delete-token +https://developer.hashicorp.com/nomad/api-docs/acl/tokens#delete-token Example: @@ -164,13 +164,13 @@ my_nomad.acl.delete_token("377ba749-8b0e-c7fd-c0c0-9da5bb943088") Manage acl Policies -https://www.nomadproject.io/api/acl-policies.html +https://developer.hashicorp.com/nomad/api-docs/acl-policies.html ### List policies This endpoint lists all ACL policies. This lists the policies that have been replicated to the region, and may lag behind the authoritative region. -https://www.nomadproject.io/api/acl-policies.html#list-policies +https://developer.hashicorp.com/nomad/api-docs/acl-policies#list-policies Example: @@ -186,7 +186,7 @@ policies = my_nomad.acl.get_policies() This endpoint creates an ACL Policy. This request is always forwarded to the authoritative region. -https://www.nomadproject.io/api/acl-policies.html#create-or-update-policy +https://developer.hashicorp.com/nomad/api-docs/acl-policies#create-or-update-policy Example: ``` @@ -207,7 +207,7 @@ my_nomad.acl.create_policy("my-policy", policy) This endpoint update an ACL Policy. This request is always forwarded to the authoritative region. -https://www.nomadproject.io/api/acl-policies.html#create-or-update-policy +https://developer.hashicorp.com/nomad/api-docs/acl-policies#create-or-update-policy Example: @@ -229,7 +229,7 @@ my_nomad.acl.update_policy("my-policy", policy) This endpoint reads an ACL policy with the given name. This queries the policy that have been replicated to the region, and may lag behind the authoritative region. -https://www.nomadproject.io/api/acl-policies.html#read-policy +https://developer.hashicorp.com/nomad/api-docs/acl-policies#read-policy Example: diff --git a/docs/api/agent.md b/docs/api/agent.md index 32da2d2..81f623f 100644 --- a/docs/api/agent.md +++ b/docs/api/agent.md @@ -4,7 +4,7 @@ This endpoint queries the agent for the known peers in the gossip pool. This endpoint is only applicable to servers. Due to the nature of gossip, this is eventually consistent. -https://www.nomadproject.io/api/agent.html#list-members +https://developer.hashicorp.com/nomad/api-docs/agent#list-members Example: @@ -23,7 +23,7 @@ for member in members["Members"]: This endpoint lists the known server nodes. The servers endpoint is used to query an agent in client mode for its list of known servers. Client nodes register themselves with these server addresses so that they may dequeue work. The servers endpoint can be used to keep this configuration up to date if there are changes in the cluster -https://www.nomadproject.io/api/agent.html#list-servers +https://developer.hashicorp.com/nomad/api-docs/agent#list-servers Example: @@ -42,7 +42,7 @@ for server in servers: This endpoint queries the state of the target agent (self). -https://www.nomadproject.io/api/agent.html#query-self +https://developer.hashicorp.com/nomad/api-docs/agent#query-self Example: @@ -60,7 +60,7 @@ print (agent) This endpoint updates the list of known servers to the provided list. This replaces all previous server addresses with the new list. -https://www.nomadproject.io/api/agent.html#update-servers +https://developer.hashicorp.com/nomad/api-docs/agent#update-servers Example: @@ -76,7 +76,7 @@ r = my_nomad.agent.update_servers(['192.168.33.11', '10.1.10.200:4829']) This endpoint introduces a new member to the gossip pool. This endpoint is only eligible for servers. -https://www.nomadproject.io/api/agent.html#join-agent +https://developer.hashicorp.com/nomad/api-docs/agent#join-agent Example: @@ -92,7 +92,7 @@ r = my_nomad.agent.join_agent("server02") This endpoint forces a member of the gossip pool from the "failed" state to the "left" state. This allows the consensus protocol to remove the peer and stop attempting replication. This is only applicable for servers. -https://www.nomadproject.io/api/agent.html#force-leave-agent +https://developer.hashicorp.com/nomad/api-docs/agent#force-leave-agent Exmaple: @@ -110,7 +110,7 @@ This endpoint returns whether or not the agent is healthy. When using Consul it When the agent is unhealthy 500 will be returned along with JSON response containing an error message. -https://www.nomadproject.io/api/agent.html#health +https://developer.hashicorp.com/nomad/api-docs/agent#health Example: diff --git a/docs/api/allocation.md b/docs/api/allocation.md index 2c331d2..02efd9d 100644 --- a/docs/api/allocation.md +++ b/docs/api/allocation.md @@ -4,7 +4,7 @@ This endpoint reads information about a specific allocation. -https://www.nomadproject.io/api/allocations.html#read-allocation +https://developer.hashicorp.com/nomad/api-docs/allocations#read-allocation ``` import nomad diff --git a/docs/api/allocations.md b/docs/api/allocations.md index 8c7ef2f..4f525af 100644 --- a/docs/api/allocations.md +++ b/docs/api/allocations.md @@ -4,7 +4,7 @@ This endpoint lists all allocations. -https://www.nomadproject.io/api/allocations.html#list-allocations +https://developer.hashicorp.com/nomad/api-docs/allocations#list-allocations Example: diff --git a/docs/api/client.md b/docs/api/client.md index da9ca15..bd7746f 100644 --- a/docs/api/client.md +++ b/docs/api/client.md @@ -4,7 +4,7 @@ This endpoint queries the actual resources consumed on a node. 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-stats +https://developer.hashicorp.com/nomad/api-docs/client#read-stats Example: diff --git a/docs/api/deployment.md b/docs/api/deployment.md index 9445cd8..919bbcd 100644 --- a/docs/api/deployment.md +++ b/docs/api/deployment.md @@ -6,7 +6,7 @@ The deployment endpoints are used to query for and interact with deployments. This endpoint reads information about a specific deployment by ID. -https://www.nomadproject.io/api/deployments.html#read-deployment +https://developer.hashicorp.com/nomad/api-docs/deployments#read-deployment Example: @@ -25,7 +25,7 @@ print (deployment) This endpoint lists the allocations created or modified for the given deployment. -https://www.nomadproject.io/api/deployments.html#list-allocations-for-deployment +https://developer.hashicorp.com/nomad/api-docs/deployments#list-allocations-for-deployment Example: @@ -44,7 +44,7 @@ for allocation in allocations: 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. This endpoint only triggers a rollback if the most recent stable version of the job has a different specification than the job being reverted. -https://www.nomadproject.io/api/deployments.html#fail-deployment +https://developer.hashicorp.com/nomad/api-docs/deployments#fail-deployment example: @@ -69,7 +69,7 @@ fail_deployment = my_nomad.deployment.fail_deployment('a8061a1c-d4c9-2a7d-a4b2-9 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/api/deployments.html#pause-deployment +https://developer.hashicorp.com/nomad/api-docs/deployments#pause-deployment example: @@ -103,7 +103,7 @@ pause = my_nomad.deployment.pause_deployment("52c47d49-eefa-540f-f0f1-d25ba298c8 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/api/deployments.html#promote-deployment +https://developer.hashicorp.com/nomad/api-docs/deployments#promote-deployment #### Promote All @@ -138,7 +138,7 @@ promote = my_nomad.deployment.promote_deployment_groups("52c47d49-eefa-540f-f0f1 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 manually using this endpoint. Marking an allocation as healthy will allow the rolling upgrade to proceed. Marking it as failed will cause the deployment to fail. This endpoint only triggers a rollback if the most recent stable version of the job has a different specification than the job being reverted. -https://www.nomadproject.io/api/deployments.html#set-allocation-health-in-deployment +https://developer.hashicorp.com/nomad/api-docs/deployments#set-allocation-health-in-deployment example: diff --git a/docs/api/deployments.md b/docs/api/deployments.md index ab5bdcf..4cc0a03 100644 --- a/docs/api/deployments.md +++ b/docs/api/deployments.md @@ -6,7 +6,7 @@ The deployment endpoints are used to query for and interact with deployments. This endpoint lists all deployments. -https://www.nomadproject.io/api/deployments.html#list-deployments +https://developer.hashicorp.com/nomad/api-docs/deployments#list-deployments Example: diff --git a/docs/api/evaluation.md b/docs/api/evaluation.md index e035a83..561dc98 100644 --- a/docs/api/evaluation.md +++ b/docs/api/evaluation.md @@ -4,7 +4,7 @@ This endpoint reads information about a specific evaluation by ID. -https://www.nomadproject.io/api/evaluations.html#read-evaluation +https://developer.hashicorp.com/nomad/api-docs/evaluations#read-evaluation Example: @@ -22,7 +22,7 @@ print (evaluation) This endpoint lists the allocations created or modified for the given evaluation. -https://www.nomadproject.io/api/evaluations.html#list-allocations-for-evaluation +https://developer.hashicorp.com/nomad/api-docs/evaluations#list-allocations-for-evaluation Example: diff --git a/docs/api/evaluations.md b/docs/api/evaluations.md index f0745cd..fcf48b3 100644 --- a/docs/api/evaluations.md +++ b/docs/api/evaluations.md @@ -4,7 +4,7 @@ This endpoint lists all evaluations. -https://www.nomadproject.io/api/evaluations.html#list-evaluations +https://developer.hashicorp.com/nomad/api-docs/evaluations#list-evaluations Example: diff --git a/docs/api/job.md b/docs/api/job.md index 4008d4d..af6f77f 100644 --- a/docs/api/job.md +++ b/docs/api/job.md @@ -4,7 +4,7 @@ This endpoint creates (aka "registers") a new job in the system. -https://www.nomadproject.io/api/jobs.html#create-job +https://developer.hashicorp.com/nomad/api-docs/jobs#create-job Example: @@ -109,7 +109,7 @@ response = my_nomad.job.register_job("example", job) This endpoint reads information about a single job for its specification and status. -https://www.nomadproject.io/api/jobs.html#read-job +https://developer.hashicorp.com/nomad/api-docs/jobs#read-job Example: @@ -126,7 +126,7 @@ job = my_nomad.job.get_job("example") This endpoint reads information about all versions of a job. -https://www.nomadproject.io/api/jobs.html#list-job-versions +https://developer.hashicorp.com/nomad/api-docs/jobs#list-job-versions Example: @@ -145,7 +145,7 @@ for version in versions["Versions"]: This endpoint reads information about a single job's allocations. -https://www.nomadproject.io/api/jobs.html#list-job-allocations +https://developer.hashicorp.com/nomad/api-docs/jobs#list-job-allocations Example: @@ -164,7 +164,7 @@ for allocation in allocations: This endpoint reads information about a single job's evaluations -https://www.nomadproject.io/api/jobs.html#list-job-evaluations +https://developer.hashicorp.com/nomad/api-docs/jobs#list-job-evaluations Example: @@ -184,7 +184,7 @@ for evaluation in evaluations: This endpoint lists a single job's deployments -https://www.nomadproject.io/api/jobs.html#list-job-deployments +https://developer.hashicorp.com/nomad/api-docs/jobs#list-job-deployments Example: @@ -204,7 +204,7 @@ for deployment in deployments: This endpoint returns a single job's most recent deployment. -https://www.nomadproject.io/api/jobs.html#read-job-39-s-most-recent-deployment +https://developer.hashicorp.com/nomad/api-docs/jobs#read-job-39-s-most-recent-deployment Example: @@ -221,7 +221,7 @@ deployment = my_nomad.job.get_deployment("example") This endpoint reads summary information about a job. -https://www.nomadproject.io/api/jobs.html#read-job-summary +https://developer.hashicorp.com/nomad/api-docs/jobs#read-job-summary Example: @@ -238,7 +238,7 @@ summary = my_nomad.job.get_summary("example") This endpoint registers a new job or updates an existing job. -https://www.nomadproject.io/api/jobs.html#update-existing-job +https://developer.hashicorp.com/nomad/api-docs/jobs#update-existing-job Example: @@ -249,7 +249,7 @@ See create new job This endpoint dispatches a new instance of a parameterized job. -https://www.nomadproject.io/api/jobs.html#dispatch-job +https://developer.hashicorp.com/nomad/api-docs/jobs#dispatch-job Example: @@ -340,7 +340,7 @@ my_nomad.job.dispatch_job("example-batch", meta={"time": "500"}) This endpoint reverts the job to an older version. -https://www.nomadproject.io/api/jobs.html#revert-to-older-job-version +https://developer.hashicorp.com/nomad/api-docs/jobs#revert-to-older-job-version Example: @@ -361,7 +361,7 @@ my_nomad.job.revert_job("example", prior_job_version, current_job_version) This endpoint sets the job's stability. -https://www.nomadproject.io/api/jobs.html#set-job-stability +https://developer.hashicorp.com/nomad/api-docs/jobs#set-job-stability Example: @@ -380,7 +380,7 @@ my_nomad.job.stable_job("example", current_job_version, True) This endpoint creates a new evaluation for the given job. This can be used to force run the scheduling logic if necessary. -https://www.nomadproject.io/api/jobs.html#create-job-evaluation +https://developer.hashicorp.com/nomad/api-docs/jobs#create-job-evaluation Example: @@ -396,7 +396,7 @@ my_nomad.job.evaluate_job("example") This endpoint invokes a dry-run of the scheduler for the job. -https://www.nomadproject.io/api/jobs.html#create-job-plan +https://developer.hashicorp.com/nomad/api-docs/jobs#create-job-plan Example: @@ -500,7 +500,7 @@ plan = my_nomad.job.plan_job("example", job) This endpoint deregisters a job, and stops all allocations part of it. -https://www.nomadproject.io/api/jobs.html#stop-a-job +https://developer.hashicorp.com/nomad/api-docs/jobs#stop-a-job Example of deferred removal of job (performed by Nomad garbage collector): diff --git a/docs/api/jobs.md b/docs/api/jobs.md index 08fb1f6..c1a94a5 100644 --- a/docs/api/jobs.md +++ b/docs/api/jobs.md @@ -4,7 +4,7 @@ This endpoint lists all known jobs in the system registered with Nomad. -https://www.nomadproject.io/api/jobs.html#list-jobs +https://developer.hashicorp.com/nomad/api-docs/jobs#list-jobs Example: @@ -23,7 +23,7 @@ for job in jobs: This endpoint creates (aka "registers") a new job in the system. -https://www.nomadproject.io/api/jobs.html#create-job +https://developer.hashicorp.com/nomad/api-docs/jobs#create-job Example: @@ -129,7 +129,7 @@ To convert to python dict and verify for correctness a hcl/nomad file. The examp `nomad job init` and it will assume this file is in the current working directory. In practice this file should already be read and used as the parameter hcl. -https://www.nomadproject.io/api/jobs.html#parse-job +https://developer.hashicorp.com/nomad/api-docs/jobs#parse-job ```python diff --git a/docs/api/metrics.md b/docs/api/metrics.md index f797525..5c5fe0c 100644 --- a/docs/api/metrics.md +++ b/docs/api/metrics.md @@ -2,7 +2,7 @@ ### Get node metrics -https://www.nomadproject.io/api/metrics.html +https://developer.hashicorp.com/nomad/api-docs/metrics.html Example: diff --git a/docs/api/namespace.md b/docs/api/namespace.md index c4d8a42..52d126c 100644 --- a/docs/api/namespace.md +++ b/docs/api/namespace.md @@ -8,7 +8,7 @@ You must have nomad **ENTERPRISE Edition** Create new namespace -https://www.nomadproject.io/api/namespaces.html#create-or-update-namespace +https://developer.hashicorp.com/nomad/api-docs/namespaces#create-or-update-namespace Exmample: @@ -52,7 +52,7 @@ print (my_nomad.get_namespace()) This endpoint reads information about a specific namespace. -https://www.nomadproject.io/api/namespaces.html#read-namespace +https://developer.hashicorp.com/nomad/api-docs/namespaces#read-namespace Exmample: @@ -69,7 +69,7 @@ namespace = my_nomad.namespace.get_namespace("api-prod") Update existing namespace -https://www.nomadproject.io/api/namespaces.html#create-or-update-namespace +https://developer.hashicorp.com/nomad/api-docs/namespaces#create-or-update-namespace Example: @@ -89,7 +89,7 @@ my_nomad.namespace.create_namespace("api-prod", namespace) Delete namespace -https://www.nomadproject.io/api/namespaces.html#create-or-update-namespace +https://developer.hashicorp.com/nomad/api-docs/namespaces#create-or-update-namespace Exmaple: diff --git a/docs/api/namespaces.md b/docs/api/namespaces.md index bb2595b..359ced3 100644 --- a/docs/api/namespaces.md +++ b/docs/api/namespaces.md @@ -8,7 +8,7 @@ You must have nomad **ENTERPRISE Edition** This endpoint lists all namespaces. -https://www.nomadproject.io/api/namespaces.html#list-namespaces +https://developer.hashicorp.com/nomad/api-docs/namespaces#list-namespaces Exmaple: diff --git a/docs/api/node.md b/docs/api/node.md index 9accd9d..f89ef69 100644 --- a/docs/api/node.md +++ b/docs/api/node.md @@ -4,7 +4,7 @@ This endpoint queries the status of a client node. -https://www.nomadproject.io/api/nodes.html#read-node +https://developer.hashicorp.com/nomad/api-docs/nodes#read-node Example: @@ -20,7 +20,7 @@ node = my_nomad.node.get_node('ed1bbae7-c38a-df2d-1de7-50dbc753fc98') This endpoint lists all of the allocations for the given node. This can be used to determine what allocations have been scheduled on the node, their current status, and the values of dynamically assigned resources, like ports. -https://www.nomadproject.io/api/nodes.html#list-node-allocations +https://developer.hashicorp.com/nomad/api-docs/nodes#list-node-allocations Example: @@ -40,7 +40,7 @@ for allocation in allocations: This endpoint creates a new evaluation for the given node. This can be used to force a run of the scheduling logic. -https://www.nomadproject.io/api/nodes.html#create-node-evaluation +https://developer.hashicorp.com/nomad/api-docs/nodes#create-node-evaluation Example: @@ -56,7 +56,7 @@ my_nomad.node.evaluate_node('ed1bbae7-c38a-df2d-1de7-50dbc753fc98') 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. -https://www.nomadproject.io/api/nodes.html#drain-node +https://developer.hashicorp.com/nomad/api-docs/nodes#drain-node Example: @@ -76,7 +76,7 @@ my_nomad.node.drain_node('ed1bbae7-c38a-df2d-1de7-50dbc753fc98', enable=False) 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. -https://www.nomadproject.io/api/nodes.html#drain-node +https://developer.hashicorp.com/nomad/api-docs/nodes#drain-node Example: @@ -102,7 +102,7 @@ my_nomad.node.drain_node_with_spec('ed1bbae7-c38a-df2d-1de7-50dbc753fc98', drain This endpoint toggles the eligibility of the node. When a node's "SchedulingEligibility" is ineligible the scheduler will not consider it for new placements. -https://www.nomadproject.io/api/nodes.html#toggle-node-eligibility +https://developer.hashicorp.com/nomad/api-docs/nodes#toggle-node-eligibility Example: @@ -122,7 +122,7 @@ my_nomad.node.eligible_node('ed1bbae7-c38a-df2d-1de7-50dbc753fc98', eligible=Tru This endpoint purges a node from the system. Nodes can still join the cluster if they are alive. -https://www.nomadproject.io/api/nodes.html#purge-node +https://developer.hashicorp.com/nomad/api-docs/nodes#purge-node Example: diff --git a/docs/api/nodes.md b/docs/api/nodes.md index 03cbc78..825957e 100644 --- a/docs/api/nodes.md +++ b/docs/api/nodes.md @@ -4,7 +4,7 @@ This endpoint lists all nodes registered with Nomad. -https://www.nomadproject.io/api/nodes.html#list-nodes +https://developer.hashicorp.com/nomad/api-docs/nodes#list-nodes Example: diff --git a/docs/api/regions.md b/docs/api/regions.md index 54b7754..f68c230 100644 --- a/docs/api/regions.md +++ b/docs/api/regions.md @@ -2,7 +2,7 @@ ### List regions -https://www.nomadproject.io/api/regions.html#list-regions +https://developer.hashicorp.com/nomad/api-docs/regions#list-regions Example: diff --git a/docs/api/sentinel.md b/docs/api/sentinel.md index 2693c28..1fe7148 100644 --- a/docs/api/sentinel.md +++ b/docs/api/sentinel.md @@ -8,7 +8,7 @@ You must have nomad **ENTERPRISE Edition** Get all policies -https://www.nomadproject.io/api/sentinel-policies.html#list-policies +https://developer.hashicorp.com/nomad/api-docs/sentinel-policies#list-policies Example: @@ -24,7 +24,7 @@ policies = my_nomad.sentinel.get_policies() Create a policy -https://www.nomadproject.io/api/sentinel-policies.html#create-or-update-policy +https://developer.hashicorp.com/nomad/api-docs/sentinel-policies#create-or-update-policy Example: ``` @@ -47,7 +47,7 @@ my_nomad.sentinel.create_policy("my-policy", policy) Update specific policy -https://www.nomadproject.io/api/sentinel-policies.html#create-or-update-policy +https://developer.hashicorp.com/nomad/api-docs/sentinel-policies#create-or-update-policy Example: @@ -71,7 +71,7 @@ my_nomad.sentinel.update_policy("my-policy", policy) Get specific policy -https://www.nomadproject.io/api/sentinel-policies.html#read-policy +https://developer.hashicorp.com/nomad/api-docs/sentinel-policies#read-policy Example: @@ -87,7 +87,7 @@ policy = my_nomad.sentinel.get_policy("my-policy") Delete specific policy -https://www.nomadproject.io/api/sentinel-policies.html#delete-policy +https://developer.hashicorp.com/nomad/api-docs/sentinel-policies#delete-policy Example: diff --git a/docs/api/status.md b/docs/api/status.md index ed5cc97..6e30d5d 100644 --- a/docs/api/status.md +++ b/docs/api/status.md @@ -4,7 +4,7 @@ This endpoint returns the address of the current leader in the region. -https://www.nomadproject.io/api/status.html#read-leader +https://developer.hashicorp.com/nomad/api-docs/status#read-leader Example: @@ -20,7 +20,7 @@ leader = my_nomad.status.leader.get_leader() This endpoint returns the set of raft peers in the region. -https://www.nomadproject.io/api/status.html#list-peers +https://developer.hashicorp.com/nomad/api-docs/status#list-peers Example: diff --git a/docs/api/system.md b/docs/api/system.md index ead5bc0..f836fe6 100644 --- a/docs/api/system.md +++ b/docs/api/system.md @@ -4,7 +4,7 @@ This endpoint initializes a garbage collection of jobs, evaluations, allocations, and nodes. This is an asynchronous operation. -https://www.nomadproject.io/api/system.html#force-gc +https://developer.hashicorp.com/nomad/api-docs/system#force-gc Example: @@ -20,7 +20,7 @@ my_nomad.system.initiate_garbage_collection() This endpoint reconciles the summaries of all registered jobs. -https://www.nomadproject.io/api/system.html#reconcile-summaries +https://developer.hashicorp.com/nomad/api-docs/system#reconcile-summaries Example: diff --git a/docs/api/validate.md b/docs/api/validate.md index 8b84022..ce05d91 100644 --- a/docs/api/validate.md +++ b/docs/api/validate.md @@ -4,7 +4,7 @@ This endpoint validates a Nomad job file. The local Nomad agent forwards the request to a server. In the event a server can't be reached the agent verifies the job file locally but skips validating driver configurations. -https://www.nomadproject.io/api/validate.html#validate-job +https://developer.hashicorp.com/nomad/api-docs/validate#validate-job Example: From ef6bc84c6ea633911f3a58797e8f017eba65859b Mon Sep 17 00:00:00 2001 From: Nikita Beletskii <2nikita.b@gmail.com> Date: Wed, 12 Apr 2023 13:19:49 +0200 Subject: [PATCH 07/12] add option for custom user agent (#150) * add option for custom user agent * add tests --- CHANGELOG.md | 2 +- nomad/__init__.py | 37 ++++++++++++++++++++++--------------- nomad/api/base.py | 29 ++++++++++++++++++----------- tests/test_base.py | 14 ++++++++++++++ 4 files changed, 55 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 831e35f..71144a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ ### Other changes * Up `requests` lib version to 2.28.1 * Add migging parameters to allocations.get_allocations and jobs.get_jobs (#144). Thanks @Kamilcuk - +* Add option for custom user agent ## 1.5.0 * Add `namespace` agrument support for `get_allocations` and `get_deployments` endpoints (#133) * Add Python 3.10 support (#133) diff --git a/nomad/__init__.py b/nomad/__init__.py index 0ad41b9..fdb4f16 100644 --- a/nomad/__init__.py +++ b/nomad/__init__.py @@ -1,5 +1,8 @@ """Nomad Python library""" import os +from typing import Optional + +import requests from nomad import api @@ -11,18 +14,19 @@ class Nomad: # pylint: disable=too-many-public-methods,too-many-instance-attrib def __init__( # pylint: disable=too-many-arguments self, - host="127.0.0.1", - secure=False, - port=4646, - address=os.getenv("NOMAD_ADDR", None), - namespace=os.getenv("NOMAD_NAMESPACE", None), - token=os.getenv("NOMAD_TOKEN", None), - timeout=5, - region=os.getenv("NOMAD_REGION", None), - version="v1", - verify=False, - cert=(os.getenv("NOMAD_CLIENT_CERT", None), os.getenv("NOMAD_CLIENT_KEY", None)), - session=None, + host: str = "127.0.0.1", + secure: bool = False, + port: int = 4646, + address: Optional[str] = os.getenv("NOMAD_ADDR", None), + user_agent: Optional[str] = None, + namespace: Optional[str] = os.getenv("NOMAD_NAMESPACE", None), + token: Optional[str] = os.getenv("NOMAD_TOKEN", None), + timeout: int = 5, + region: Optional[str] = os.getenv("NOMAD_REGION", None), + version: str = "v1", + verify: bool = False, + cert: tuple = (os.getenv("NOMAD_CLIENT_CERT", None), os.getenv("NOMAD_CLIENT_KEY", None)), + session: requests.Session = None, ): """Nomad api client @@ -31,18 +35,19 @@ def __init__( # pylint: disable=too-many-arguments optional arguments: - host (defaults 127.0.0.1), string ip or name of the nomad api server/agent that will be used. - port (defaults 4646), integer port that will be used to connect. + - user_agent (defaults None), custom user agent for requests to Nomad. - secure (defaults False), define if the protocol is secured or not (https or http) - - version (defaults v1), vesion of the api of nomad. + - version (defaults v1), version of the api of nomad. - verify (defaults False), verify the certificate when tls/ssl is enabled at nomad. - cert (defaults empty), cert, or key and cert file to validate the certificate configured at nomad. - region (defaults None), version of the region to use. It will be used then regions of the current agent of the connection. - - namespace (defaults to None), Specifies the enterpise namespace that will + - namespace (defaults to None), Specifies the enterprise namespace that will be use to deploy or to ask info to nomad. - token (defaults to None), Specifies to append ACL token to the headers to - make authentication on secured based nomad environemnts. + make authentication on secured based nomad environments. - session (defaults to None), allows for injecting a prepared requests.Session object that all requests to Nomad should use. returns: Nomad api client object @@ -56,6 +61,7 @@ def __init__( # pylint: disable=too-many-arguments self.secure = secure self.port = port self.address = address + self.user_agent = user_agent self.region = region self.timeout = timeout self.version = version @@ -69,6 +75,7 @@ def __init__( # pylint: disable=too-many-arguments "address": self.address, "uri": self.get_uri(), "port": self.port, + "user_agent": self.user_agent, "namespace": self.__namespace, "token": self.token, "timeout": self.timeout, diff --git a/nomad/api/base.py b/nomad/api/base.py index a4c7329..87f3714 100644 --- a/nomad/api/base.py +++ b/nomad/api/base.py @@ -1,4 +1,6 @@ """Requester""" +from typing import Optional + import requests import nomad.api.exceptions @@ -13,20 +15,22 @@ class Requester: # pylint: disable=too-many-instance-attributes,too-few-public- 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, + address: Optional[str] = None, + uri: Optional[str] = "http://127.0.0.1", + port: int = 4646, + user_agent: Optional[str] = None, + namespace: Optional[str] = None, + token: Optional[str] = None, + timeout: int = 5, + version: str = "v1", + verify: bool = False, + cert: tuple = (), + region: Optional[str] = None, + session: requests.Session = None, ): self.uri = uri self.port = port + self.user_agent = user_agent self.namespace = namespace self.token = token self.timeout = timeout @@ -140,6 +144,9 @@ def _request( # pylint: disable=too-many-arguments, too-many-branches else: headers = {"X-Nomad-Token": self.token} + if self.user_agent: + headers["User-Agent"] = self.user_agent + response = None try: diff --git a/tests/test_base.py b/tests/test_base.py index 59b9be3..d1501a0 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -147,3 +147,17 @@ def test_base_use_address_instead_on_host_port(): address=nomad_address, host=common.IP, port=common.NOMAD_PORT, verify=False, token=common.NOMAD_TOKEN ) n.jobs.get_jobs() + +@responses.activate +def test_use_custom_user_agent(): + custom_agent_name = "custom_agent" + responses.add(responses.GET, "https://nomad.service.consul:4646/v1/jobs", status=200, json=[]) + + nomad_address = "https://nomad.service.consul:4646" + n = nomad.Nomad( + address=nomad_address, host=common.IP, port=common.NOMAD_PORT, verify=False, + token=common.NOMAD_TOKEN, user_agent=custom_agent_name + ) + n.jobs.get_jobs() + + assert responses.calls[0].request.headers["User-Agent"] == custom_agent_name From 364f063a061d95a4ae4500580930bb0bb42ba134 Mon Sep 17 00:00:00 2001 From: Nikita Beletskii <2nikita.b@gmail.com> Date: Mon, 17 Apr 2023 20:02:32 +0200 Subject: [PATCH 08/12] Add missing arguments to get_allocations() (#149) * replace _id to id_ * add black to format files * change changelog * fix linter * add missing record to CHANGELOG.md * add parameters to allocations endpoint --- CHANGELOG.md | 5 +++-- nomad/api/allocations.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71144a2..6b6cc6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,12 @@ * Rename `id` arguments to `id_` across of code base * Rename `type` arguments to `type_` across of code base ### Other changes +* Add more missing parameters to allocations.get_allocations() * Up `requests` lib version to 2.28.1 -* Add migging parameters to allocations.get_allocations and jobs.get_jobs (#144). Thanks @Kamilcuk +* Add missing parameters to allocations.get_allocations and jobs.get_jobs (#144). Thanks @Kamilcuk * Add option for custom user agent ## 1.5.0 -* Add `namespace` agrument support for `get_allocations` and `get_deployments` endpoints (#133) +* Add `namespace` argument support for `get_allocations` and `get_deployments` endpoints (#133) * Add Python 3.10 support (#133) * Add support for pre-populated Sessions (#132) * Add scaling policy endpoint (#136) diff --git a/nomad/api/allocations.py b/nomad/api/allocations.py index c776772..128b072 100644 --- a/nomad/api/allocations.py +++ b/nomad/api/allocations.py @@ -38,10 +38,13 @@ def __iter__(self): def get_allocations( # pylint: disable=too-many-arguments self, prefix: Optional[str] = None, + next_token: Optional[str] = None, + per_page: Optional[int] = None, filter_: Optional[str] = None, namespace: Optional[str] = None, resources: Optional[bool] = None, task_states: Optional[bool] = None, + reverse: Optional[bool] = None, ): """Lists all the allocations. @@ -49,12 +52,18 @@ def get_allocations( # pylint: disable=too-many-arguments arguments: - prefix :(str) optional, specifies a string to filter allocations on based on an prefix. This is specified as a querystring parameter. + - next_token :(str) optional. + This endpoint supports paging. The next_token parameter accepts a string which identifies the next + expected allocation. This value can be obtained from the X-Nomad-NextToken header from the previous + response. + - per_page :(int) optional - filter_ :(str) optional Name has a trailing underscore not to conflict with builtin function. - namespace :(str) optional, specifies the target namespace. Specifying * would return all jobs. This is specified as a querystring parameter. - resources :(bool) optional - task_states :(bool) optional + - reverse :(bool) optional returns: list raises: - nomad.api.exceptions.BaseNomadException @@ -62,9 +71,12 @@ def get_allocations( # pylint: disable=too-many-arguments """ params = { "prefix": prefix, + "next_token": next_token, + "per_page": per_page, "filter": filter_, "namespace": namespace, "resources": resources, "task_states": task_states, + "reverse": reverse, } return self.request(method="get", params=params).json() From f5dcfd119fb63df3d27098dfeaca641861e87184 Mon Sep 17 00:00:00 2001 From: Nikita Beletskii <2nikita.b@gmail.com> Date: Tue, 23 May 2023 18:42:37 +0200 Subject: [PATCH 09/12] add missing arguments to node endpoints (#152) * add missing arguments to node endpoints * add tests * fix * add more tests * add CHANGELOG --- CHANGELOG.md | 3 ++- nomad/api/allocation.py | 4 ++-- nomad/api/evaluation.py | 1 - nomad/api/namespace.py | 2 -- nomad/api/node.py | 17 ++++++++--------- nomad/api/nodes.py | 21 +++++++++++++++++++-- tests/test_allocations.py | 3 +++ tests/test_nodes.py | 18 ++++++++++++++++-- 8 files changed, 50 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b6cc6a..1ac2a9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ * Add more missing parameters to allocations.get_allocations() * Up `requests` lib version to 2.28.1 * Add missing parameters to allocations.get_allocations and jobs.get_jobs (#144). Thanks @Kamilcuk -* Add option for custom user agent +* Add option for custom user agent (#150) +* Add missing parameters to nodes.get_nodes (#152). ## 1.5.0 * Add `namespace` argument support for `get_allocations` and `get_deployments` endpoints (#133) * Add Python 3.10 support (#133) diff --git a/nomad/api/allocation.py b/nomad/api/allocation.py index 6ca74a4..87d64d9 100644 --- a/nomad/api/allocation.py +++ b/nomad/api/allocation.py @@ -47,7 +47,7 @@ def __getitem__(self, item): except nomad.api.exceptions.URLNotFoundNomadException as exc: raise KeyError from exc - def get_allocation(self, id_): + def get_allocation(self, id_: str): """Query a specific allocation. https://www.nomadproject.io/docs/http/alloc.html @@ -59,7 +59,7 @@ def get_allocation(self, id_): """ return self.request(id_, method="get").json() - def stop_allocation(self, id_): + def stop_allocation(self, id_: str): """Stop a specific allocation. https://www.nomadproject.io/api-docs/allocations/#stop-allocation diff --git a/nomad/api/evaluation.py b/nomad/api/evaluation.py index e7bbf9b..2f1546a 100644 --- a/nomad/api/evaluation.py +++ b/nomad/api/evaluation.py @@ -36,7 +36,6 @@ def __contains__(self, item): return False def __getitem__(self, item): - try: evaluation = self.get_evaluation(item) if evaluation["ID"] == item: diff --git a/nomad/api/namespace.py b/nomad/api/namespace.py index d494449..4044e5b 100644 --- a/nomad/api/namespace.py +++ b/nomad/api/namespace.py @@ -28,7 +28,6 @@ def __getattr__(self, item): raise AttributeError(msg) def __contains__(self, item): - try: self.get_namespace(item) return True @@ -36,7 +35,6 @@ def __contains__(self, item): return False def __getitem__(self, item): - try: job = self.get_namespace(item) diff --git a/nomad/api/node.py b/nomad/api/node.py index 48c3faf..86a7462 100644 --- a/nomad/api/node.py +++ b/nomad/api/node.py @@ -1,4 +1,5 @@ """Nomad Node: https://developer.hashicorp.com/nomad/api-docs/nodes""" +from typing import Optional import nomad.api.exceptions from nomad.api.base import Requester @@ -28,7 +29,6 @@ def __getattr__(self, item): raise AttributeError(msg) def __contains__(self, item): - try: self.get_node(item) return True @@ -36,7 +36,6 @@ def __contains__(self, item): return False def __getitem__(self, item): - try: node = self.get_node(item) @@ -49,7 +48,7 @@ def __getitem__(self, item): except nomad.api.exceptions.URLNotFoundNomadException as exc: raise KeyError from exc - def get_node(self, id_): + def get_node(self, id_: str): """Query the status of a client node registered with Nomad. https://www.nomadproject.io/docs/http/node.html @@ -61,7 +60,7 @@ def get_node(self, id_): """ return self.request(id_, method="get").json() - def get_allocations(self, id_): + def get_allocations(self, id_: str): """Query the allocations belonging to a single node. https://www.nomadproject.io/docs/http/node.html @@ -73,7 +72,7 @@ def get_allocations(self, id_): """ return self.request(id_, "allocations", method="get").json() - def evaluate_node(self, id_): + def evaluate_node(self, id_: str): """Creates a new evaluation for the given node. This can be used to force run the scheduling logic if necessary. @@ -87,7 +86,7 @@ def evaluate_node(self, id_): """ return self.request(id_, "evaluate", method="post").json() - def drain_node(self, id_, enable=False): + def drain_node(self, id_, enable: bool = False): """Toggle the drain mode of the node. When enabled, no further allocations will be assigned and existing allocations will be migrated. @@ -105,7 +104,7 @@ def drain_node(self, id_, enable=False): 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: Optional[dict], mark_eligible: Optional[bool] = 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. @@ -139,7 +138,7 @@ def drain_node_with_spec(self, id_, drain_spec, mark_eligible=None): return self.request(id_, "drain", json=payload, method="post").json() - def eligible_node(self, id_, eligible=None, ineligible=None): + def eligible_node(self, id_: str, eligible: Optional[bool] = None, ineligible: Optional[bool] = None): """Toggle the eligibility of the node. https://www.nomadproject.io/docs/http/node.html @@ -171,7 +170,7 @@ def eligible_node(self, id_, eligible=None, ineligible=None): return self.request(id_, "eligibility", json=payload, method="post").json() - def purge_node(self, id_): + def purge_node(self, id_: str): """This endpoint purges a node from the system. Nodes can still join the cluster if they are alive. arguments: - id_ (str uuid): node id diff --git a/nomad/api/nodes.py b/nomad/api/nodes.py index 4b02392..28949e4 100644 --- a/nomad/api/nodes.py +++ b/nomad/api/nodes.py @@ -1,4 +1,6 @@ """Nomad Node: https://developer.hashicorp.com/nomad/api-docs/nodes""" +from typing import Optional + import nomad.api.exceptions from nomad.api.base import Requester @@ -61,7 +63,15 @@ def __iter__(self): nodes = self.get_nodes() return iter(nodes) - def get_nodes(self, prefix=None): + def get_nodes( # pylint: disable=too-many-arguments + self, + prefix: Optional[str] = None, + next_token: Optional[str] = None, + per_page: Optional[str] = None, + filter_: Optional[str] = None, + resources: Optional[bool] = None, + os: Optional[bool] = None, # pylint: disable=invalid-name + ): """Lists all the client nodes registered with Nomad. https://www.nomadproject.io/docs/http/nodes.html @@ -73,5 +83,12 @@ def get_nodes(self, prefix=None): - nomad.api.exceptions.BaseNomadException - nomad.api.exceptions.URLNotFoundNomadException """ - params = {"prefix": prefix} + params = { + "prefix": prefix, + "next_token": next_token, + "per_page": per_page, + "filter_": filter_, + "resources": resources, + "os": os, + } return self.request(method="get", params=params).json() diff --git a/tests/test_allocations.py b/tests/test_allocations.py index b618786..186a41d 100644 --- a/tests/test_allocations.py +++ b/tests/test_allocations.py @@ -22,6 +22,9 @@ def test_get_allocations_prefix(nomad_setup): prefix = allocations[0]["ID"][:4] nomad_setup.allocations.get_allocations(prefix=prefix) +def test_get_allocations_resouces(nomad_setup): + allocations = nomad_setup.allocations.get_allocations(resources=True) + assert "AllocatedResources" in allocations[0] def test_dunder_str(nomad_setup): assert isinstance(str(nomad_setup.allocations), str) diff --git a/tests/test_nodes.py b/tests/test_nodes.py index 0214902..96087e4 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -1,16 +1,30 @@ import pytest +import os # integration tests requires nomad Vagrant VM or Binary running def test_get_nodes(nomad_setup): assert isinstance(nomad_setup.nodes.get_nodes(), list) == True - +def test_get_node(nomad_setup): + node = nomad_setup.nodes.get_nodes()[0] + print(node) + assert node["ID"] in nomad_setup.nodes def test_get_nodes_prefix(nomad_setup): nodes = nomad_setup.nodes.get_nodes() prefix = nodes[0]["ID"][:4] nomad_setup.nodes.get_nodes(prefix=prefix) - +def test_get_nodes_resouces(nomad_setup): + nodes = nomad_setup.nodes.get_nodes(resources=True) + print(nodes) + assert "NodeResources" in nodes[0] + +@pytest.mark.skipif( + tuple(int(i) for i in os.environ.get("NOMAD_VERSION").split(".")) < (1, 3, 0), reason="Not supported in version" +) +def test_get_nodes_os(nomad_setup): + nodes = nomad_setup.nodes.get_nodes(os=True) + assert "os.name" in nodes[0]["Attributes"] def test_dunder_getitem_exist(nomad_setup): n = nomad_setup.nodes["pynomad1"] From 5cc2beb64241408b23839f4b24a02af6d440af40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 May 2023 18:43:27 +0200 Subject: [PATCH 10/12] Bump requests from 2.28.1 to 2.31.0 (#154) Bumps [requests](https://github.com/psf/requests) from 2.28.1 to 2.31.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.28.1...v2.31.0) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d15ce5a..2c24336 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -requests==2.28.1 +requests==2.31.0 From 6b9ebd61d720c84bab74d4decb7999342e36a7e3 Mon Sep 17 00:00:00 2001 From: Nikita Beletskii <2nikita.b@gmail.com> Date: Tue, 23 May 2023 18:43:53 +0200 Subject: [PATCH 11/12] add nomad 1.5.x to tests (#151) * add nomad 1.5.x to tests * fix nomad file path * modern versions * fix * fix * fix * fix * fix * fix * fxi --- .github/workflows/main.yml | 14 +++++--------- run_tests.sh | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9a33440..c1de942 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,7 +25,7 @@ jobs: fail-fast: false matrix: python-version: ['3.7', '3.11'] # the oldest and newest support versions - nomad-version: ['1.0.18', '1.1.18', '1.2.15', '1.3.8', '1.4.3'] + nomad-version: ['1.0.18', '1.1.18', '1.2.15', '1.3.14', '1.4.9', '1.5.5'] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} @@ -43,11 +43,7 @@ jobs: curl -L -o /tmp/nomad_${NOMAD_VERSION}_linux_amd64.zip https://releases.hashicorp.com/nomad/${NOMAD_VERSION}/nomad_${NOMAD_VERSION}_linux_amd64.zip echo "unzip nomad" - unzip -d /tmp /tmp/nomad_${NOMAD_VERSION}_linux_amd64.zip - - echo "starting nomad server" - /tmp/nomad agent -dev -bind ${NOMAD_IP} -node pynomad1 --acl-enabled > /dev/null 2>&1 & - sleep 30 + unzip -d /usr/local/bin/ /tmp/nomad_${NOMAD_VERSION}_linux_amd64.zip - name: Install Dependencies shell: bash run: | @@ -57,14 +53,14 @@ jobs: - name: Before Tests shell: bash run: | - /tmp/nomad init - /tmp/nomad run -output example.nomad > example.json + nomad init example.nomad + nomad run -output example.nomad > example.json - name: Unit and Integration Tests env: NOMAD_VERSION: ${{ matrix.nomad-version }} shell: bash run: | - py.test --cov=nomad --cov-report=term-missing --runxfail tests/ + ./run_tests.sh - name: Upload coverage to Codecov uses: codecov/codecov-action@v2 - name: Create Package diff --git a/run_tests.sh b/run_tests.sh index 61c8cfa..0318587 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -6,9 +6,9 @@ set -ueo pipefail if [ "${1-}" == "init" ]; then virtualenv .venv pip install -r requirements-dev.txt + source .venv/bin/activate fi -source .venv/bin/activate NOMAD_VERSION=`nomad --version | awk '{print $2}' | cut -c2-` echo "Run Nomad in dev mode" From 2b02b70d63d97c16933adea58ee14796095be241 Mon Sep 17 00:00:00 2001 From: Nikita Beletskii <2nikita.b@gmail.com> Date: Fri, 26 May 2023 17:06:42 +0200 Subject: [PATCH 12/12] 2.0.0 release (#155) --- CHANGELOG.md | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ac2a9d..5c452ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.0.0 (unreleased) +## 2.0.0 ### BREAKING CHANGES * Drop Python 2 and Python 3.6 support * Rename `id` arguments to `id_` across of code base diff --git a/setup.py b/setup.py index 5fddd91..88d6a72 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setuptools.setup( name='python-nomad', - version='1.5.0', + version='2.0.0', install_requires=['requests'], packages=['nomad', 'nomad.api'], url='http://github.com/jrxfive/python-nomad',