Skip to content

Commit

Permalink
Merge pull request #28 from jrxFive/add_operator_endpoint
Browse files Browse the repository at this point in the history
add operator endpoint and job/summary and job/plan for #27
  • Loading branch information
jrxFive authored Apr 7, 2017
2 parents 40b4184 + 08212d2 commit bc57162
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# vi: set ft=ruby :

IP = "192.168.33.10"
NOMAD_VERSION = "0.5.0"
NOMAD_VERSION = "0.5.5"
NOMAD_PORT_GUEST = 4646
NOMAD_PORT_HOST = 4646

Expand Down
5 changes: 5 additions & 0 deletions nomad/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def __init__(self, host='127.0.0.1', port=4646, timeout=5, region=None, version=
self._regions = api.Regions(self.requester)
self._status = api.Status(self.requester)
self._system = api.System(self.requester)
self._operator = api.Operator(self.requester)

@property
def jobs(self):
Expand Down Expand Up @@ -77,3 +78,7 @@ def status(self):
@property
def system(self):
return self._system

@property
def operator(self):
return self._operator
1 change: 1 addition & 0 deletions nomad/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
from nomad.api.regions import Regions
from nomad.api.status import Status
from nomad.api.system import System
from nomad.api.operator import Operator
4 changes: 2 additions & 2 deletions nomad/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ def put(self, endpoint, params=None, data=None, headers=None):
except requests.RequestException:
raise nomad.api.exceptions.BaseNomadException(response)

def delete(self, endpoint, headers=None):
def delete(self, endpoint, params=None, headers=None):
url = self._urlBuilder(endpoint)
response = None

try:
response = self.session.delete(
url, headers=headers, timeout=self.timeout)
url, params=params, headers=headers, timeout=self.timeout)

if response.ok:
return response
Expand Down
32 changes: 31 additions & 1 deletion nomad/api/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,26 @@ def get_evaluations(self, id):
"""
return self._get(id, "evaluations")

def get_summary(self, id):
""" Query the summary of a job.
https://www.nomadproject.io/docs/http/job.html
arguments:
- id
returns: dict
raises:
- nomad.api.exceptions.BaseNomadException
- nomad.api.exceptions.URLNotFoundNomadException
"""
return self._get(id, "summary")

def _post(self, *args, **kwargs):
try:
url = self._requester._endpointBuilder(Job.ENDPOINT, *args)

if kwargs:
response = self._requester.post(url, json=kwargs["json_dict"])
response = self._requester.post(url, json=kwargs["json_dict"], params=kwargs.get("params", None))
else:
response = self._requester.post(url)

Expand Down Expand Up @@ -140,6 +154,22 @@ def evaluate_job(self, id):
"""
return self._post(id, "evaluate")

def plan_job(self, id, job, diff=False):
""" Invoke a dry-run of the scheduler for the job.
https://www.nomadproject.io/docs/http/job.html
arguments:
- id
- job, dict
- diff, optional boolean
returns: dict
raises:
- nomad.api.exceptions.BaseNomadException
- nomad.api.exceptions.URLNotFoundNomadException
"""
return self._post(id, "plan", json_dict=job, params={"diff": diff})

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.
Expand Down
74 changes: 74 additions & 0 deletions nomad/api/operator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@

class Operator(object):

"""
The Operator endpoint provides cluster-level tools for
Nomad operators, such as interacting with the Raft subsystem.
https://www.nomadproject.io/docs/http/operator.html
"""

ENDPOINT = "operator"

def __init__(self, requester):
self._requester = requester

def __str__(self):
return "{0}".format(self.__dict__)

def __repr__(self):
return "{0}".format(self.__dict__)

def __getattr__(self, item):
raise AttributeError

def _get(self, *args, **kwargs):
try:
url = self._requester._endpointBuilder(Operator.ENDPOINT, *args)
response = self._requester.get(url,
params=kwargs.get("params",None))

return response.json()
except:
raise

def _delete(self, *args, **kwargs):
try:
url = self._requester._endpointBuilder(Operator.ENDPOINT, *args)
response = self._requester.delete(url,
params=kwargs.get("params", None))

return response.ok
except:
raise

def get_configuration(self, stale=False):
""" Query the status of a client node registered with Nomad.
https://www.nomadproject.io/docs/http/operator.html
returns: dict
raises:
- nomad.api.exceptions.BaseNomadException
- nomad.api.exceptions.URLNotFoundNomadException
"""

params = {"stale": stale}
return self._get("raft", "configuration", params=params)

def delete_peer(self, peer_address):
""" 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
returns: Ok status
raises:
- nomad.api.exceptions.BaseNomadException
- nomad.api.exceptions.URLNotFoundNomadException
"""

params = {"address": peer_address}
return self._delete("raft", "peer", params=params)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='python-nomad',
version='0.0.2',
version='0.1.0',
install_requires=['requests'],
packages=['nomad', 'nomad.api'],
url='http://github.com/jrxfive/python-nomad',
Expand Down
17 changes: 14 additions & 3 deletions tests/test_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ def test_delete_job(nomad_setup):
test_register_job(nomad_setup)


@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())
Expand All @@ -67,6 +65,19 @@ def test_dispatch_job(nomad_setup):
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")
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")
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)


def test_dunder_getitem_exist(nomad_setup):
j = nomad_setup.job["example"]
assert isinstance(j, dict)
Expand Down
37 changes: 37 additions & 0 deletions tests/test_operator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pytest
import tests.common as common
import nomad
import json
import os
import mock
from nomad.api import exceptions


@pytest.fixture
def nomad_setup():
n = nomad.Nomad(host=common.IP, port=common.NOMAD_PORT)
return n

# 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")
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")
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")
def test_delete_peer(nomad_setup):
with pytest.raises(exceptions.URLNotFoundNomadException):
nomad_setup.operator.delete_peer("192.168.10.133:4646")

def test_dunder_str(nomad_setup):
assert isinstance(str(nomad_setup.operator), str)

def test_dunder_repr(nomad_setup):
assert isinstance(repr(nomad_setup.operator), str)

def test_dunder_getattr(nomad_setup):
with pytest.raises(AttributeError):
d = nomad_setup.operator.does_not_exist

0 comments on commit bc57162

Please sign in to comment.