Skip to content

Commit

Permalink
#337 - Added API endpoints for Job import/export (#353)
Browse files Browse the repository at this point in the history
* #337 - Added API endpoints for Job import/export
  • Loading branch information
jlrpnbbngtn authored Sep 17, 2021
1 parent 134c46a commit 0e98ace
Show file tree
Hide file tree
Showing 14 changed files with 371 additions and 43 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,7 @@ target/

# IDE
.idea/

# Jupyter
.ipydb_checkpoints/
*.ipynb
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ clean: clean-build clean-docs clean-python clean-test ## remove everything but s

# Formatting
format: ## Run black formatter in-line
black -t py27 $(MODULE_NAME) $(TEST_DIR)
black --target-version py27 $(MODULE_NAME) $(TEST_DIR)


# Linting
lint: ## check style with flake8
flake8 $(MODULE_NAME) $(TEST_DIR)
black --check $(MODULE_NAME) $(TEST_DIR)
black --target-version py27 --check $(MODULE_NAME) $(TEST_DIR)


# Testing / Coverage
Expand Down
68 changes: 49 additions & 19 deletions brewtils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from enum import Enum

import pytz
import six
import pytz # noqa # not in requirements file
import six # noqa # not in requirements file
from brewtils.errors import ModelError, _deprecate

__all__ = [
Expand Down Expand Up @@ -210,7 +210,7 @@ def __init__(
self,
name=None,
description=None,
id=None,
id=None, # noqa # shadows built-in
status=None,
status_info=None,
queue_type=None,
Expand Down Expand Up @@ -241,7 +241,10 @@ class Choices(BaseModel):
TYPES = ("static", "url", "command")
DISPLAYS = ("select", "typeahead")

def __init__(self, type=None, display=None, value=None, strict=None, details=None):
def __init__(
self, type=None, display=None, value=None, strict=None, details=None # noqa
):
# parameter 'type' shadows built-in
self.type = type
self.strict = strict
self.value = value
Expand Down Expand Up @@ -279,7 +282,7 @@ class Parameter(BaseModel):
def __init__(
self,
key=None,
type=None,
type=None, # noqa # shadows built-in
multi=None,
display_name=None,
optional=None,
Expand Down Expand Up @@ -399,10 +402,12 @@ def is_different(self, other):
class RequestFile(BaseModel):
schema = "RequestFileSchema"

def __init__(self, storage_type=None, filename=None, id=None):
def __init__(
self, storage_type=None, filename=None, id=None # noqa # shadows built-in
):
self.storage_type = storage_type
self.filename = filename
self.id = id
self.id = id # noqa # shadows built-in

def __str__(self):
return self.filename
Expand All @@ -419,7 +424,7 @@ class File(BaseModel):

def __init__(
self,
id=None,
id=None, # noqa # shadows built-in
owner_id=None,
owner_type=None,
updated_at=None,
Expand Down Expand Up @@ -457,7 +462,14 @@ def __repr__(self):
class FileChunk(BaseModel):
schema = "FileChunkSchema"

def __init__(self, id=None, file_id=None, offset=None, data=None, owner=None):
def __init__(
self,
id=None, # noqa # shadows built-in
file_id=None,
offset=None,
data=None,
owner=None,
):
self.id = id
self.file_id = file_id
self.offset = offset
Expand Down Expand Up @@ -608,7 +620,7 @@ def __init__(
instance_name=None,
namespace=None,
command=None,
id=None,
id=None, # noqa # shadows built-in
parent=None,
children=None,
parameters=None,
Expand Down Expand Up @@ -705,7 +717,7 @@ def __init__(
name=None,
description=None,
version=None,
id=None,
id=None, # noqa # shadows built-in
max_instances=None,
instances=None,
commands=None,
Expand Down Expand Up @@ -778,7 +790,7 @@ def get_instance_by_name(self, name, raise_missing=False):

return None

def get_instance_by_id(self, id, raise_missing=False):
def get_instance_by_id(self, id, raise_missing=False): # noqa # shadows built-in
"""Get an instance that currently exists in the system
Args:
Expand Down Expand Up @@ -1053,7 +1065,7 @@ class Principal(BaseModel):

def __init__(
self,
id=None,
id=None, # noqa # shadows built-in
username=None,
roles=None,
permissions=None,
Expand Down Expand Up @@ -1081,7 +1093,13 @@ def __repr__(self):
class LegacyRole(BaseModel):
schema = "LegacyRoleSchema"

def __init__(self, id=None, name=None, description=None, permissions=None):
def __init__(
self,
id=None, # noqa # shadows built-in
name=None,
description=None,
permissions=None,
):
self.id = id
self.name = name
self.description = description
Expand All @@ -1097,7 +1115,13 @@ def __repr__(self):
class RefreshToken(BaseModel):
schema = "RefreshTokenSchema"

def __init__(self, id=None, issued=None, expires=None, payload=None):
def __init__(
self,
id=None, # noqa # shadows built-in
issued=None,
expires=None,
payload=None,
):
self.id = id
self.issued = issued
self.expires = expires
Expand All @@ -1121,7 +1145,7 @@ class Job(BaseModel):

def __init__(
self,
id=None,
id=None, # noqa # shadows built-in
name=None,
trigger_type=None,
trigger=None,
Expand Down Expand Up @@ -1379,7 +1403,7 @@ class Garden(BaseModel):

def __init__(
self,
id=None,
id=None, # noqa # shadows built-in
name=None,
status=None,
status_info=None,
Expand Down Expand Up @@ -1450,7 +1474,7 @@ class Runner(BaseModel):

def __init__(
self,
id=None,
id=None, # noqa # shadows built-in
name=None,
path=None,
instance_id=None,
Expand Down Expand Up @@ -1491,7 +1515,13 @@ class Resolvable(BaseModel):
# Resolvable parameter types
TYPES = ("Base64", "Bytes")

def __init__(self, id=None, type=None, storage=None, details=None):
def __init__(
self,
id=None, # noqa # shadows built-in
type=None, # noqa # shadows built-in
storage=None,
details=None,
):
self.id = id
self.type = type
self.storage = storage
Expand Down
6 changes: 3 additions & 3 deletions brewtils/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,9 @@ def client(self, new_client):

# Several _system properties can come from the client, so update if needed
if not self._system.name:
self._system.name = getattr(new_client, "_bg_name")
self._system.name = getattr(new_client, "_bg_name") # noqa
if not self._system.version:
self._system.version = getattr(new_client, "_bg_version")
self._system.version = getattr(new_client, "_bg_version") # noqa
if not self._system.description and new_client.__doc__:
self._system.description = new_client.__doc__.split("\n")[0]

Expand Down Expand Up @@ -635,7 +635,7 @@ def _read_log(self, **kwargs):

def _correct_system(self, request):
"""Validate that a request is intended for this Plugin"""
request_system = getattr(request, "system") or ""
request_system = getattr(request, "system") or "" # noqa
if request_system.upper() != self._system.name.upper():
raise DiscardMessageException(
"Received message for system {0}".format(request.system)
Expand Down
32 changes: 32 additions & 0 deletions brewtils/rest/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ def __init__(self, *args, **kwargs):
self.queue_url = self.base_url + "api/v1/queues/"
self.logging_url = self.base_url + "api/v1/logging/"
self.job_url = self.base_url + "api/v1/jobs/"
self.job_export_url = self.base_url + "api/v1/export/jobs/"
self.job_import_url = self.base_url + "api/v1/import/jobs/"
self.token_url = self.base_url + "api/v1/tokens/"
self.user_url = self.base_url + "api/v1/users/"
self.admin_url = self.base_url + "api/v1/admin/"
Expand Down Expand Up @@ -641,6 +643,36 @@ def post_jobs(self, payload):
"""
return self.session.post(self.job_url, data=payload, headers=self.JSON_HEADERS)

@enable_auth
def post_export_jobs(self, payload):
# type: (str) -> Response
"""Perform a POST on the Job export URL.
Args:
payload: Serialized list of Jobs
Returns:
Requests Response object
"""
return self.session.post(
self.job_export_url, data=payload, headers=self.JSON_HEADERS
)

@enable_auth
def post_import_jobs(self, payload):
# type: (str) -> Response
"""Perform a POST on the Job import URL.
Args:
payload: Serialized list of job definitions
Returns:
Requests Response object
"""
return self.session.post(
self.job_import_url, data=payload, headers=self.JSON_HEADERS
)

@enable_auth
def patch_job(self, job_id, payload):
# type: (str, str) -> Response
Expand Down
47 changes: 45 additions & 2 deletions brewtils/rest/easy_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
WaitExceededError,
_deprecate,
)
from brewtils.models import BaseModel, Event, PatchOperation
from brewtils.models import BaseModel, Event, Job, PatchOperation
from brewtils.rest.client import RestClient
from brewtils.schema_parser import SchemaParser
from requests import Response
from requests import Response # noqa # not in requirements file


def get_easy_client(**kwargs):
Expand Down Expand Up @@ -749,6 +749,49 @@ def find_jobs(self, **kwargs):
"""
return self.client.get_jobs(**kwargs)

@wrap_response(parse_method="parse_job", parse_many=True, default_exc=FetchError)
def export_jobs(self, job_id_list=None):
# type: (Optional[List[str]]) -> List[Job]
"""Export jobs from an optional job ID list.
If `job_id_list` is None or empty, definitions for all jobs are returned.
Args:
job_id_list: A list of job IDS, optional
Returns:
A list of job definitions
"""
# we should check that the argument is a list (if it's not None) because the
# call to `len` will otherwise produce an unhelpful error message
if job_id_list is not None and not isinstance(job_id_list, list):
raise TypeError("Argument must be a list of job IDs, an empty list or None")

payload = (
SchemaParser.serialize_job_ids(job_id_list, many=True)
if job_id_list is not None and len(job_id_list) > 0
else "{}"
)

return self.client.post_export_jobs(payload) # noqa # wrapper changes type

@wrap_response(
parse_method="parse_job_ids", parse_many=True, default_exc=FetchError
)
def import_jobs(self, job_list):
# type: (List[Job]) -> List[str]
"""Import job definitions from a list of Jobs.
Args:
job_list: A list of jobs to import
Returns:
A list of the job IDs created
"""
return self.client.post_import_jobs( # noqa # wrapper changes type
SchemaParser.serialize_job_for_import(job_list, many=True)
)

@wrap_response(parse_method="parse_job", parse_many=False, default_exc=SaveError)
def create_job(self, job):
"""Create a new Job
Expand Down
Loading

0 comments on commit 0e98ace

Please sign in to comment.