Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add client for SystemLink jobs API #85

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c2278f1
feat: add systems client code for get jobs API.
ganesh-nithin Nov 27, 2024
cbba5c7
feat: add systems client code for create job API.
ganesh-nithin Nov 27, 2024
258f373
feat: add systems client code for get jobs summary API.
ganesh-nithin Nov 27, 2024
4e22c28
feat: add systems client code for query jobs API.
ganesh-nithin Nov 27, 2024
6070c71
feat: add systems client code for cancel jobs API.
ganesh-nithin Nov 27, 2024
55684d8
refactor: modify docs strings for systems client.
ganesh-nithin Nov 27, 2024
412c8ef
feat: add unit tests for jobs in systems client/
ganesh-nithin Nov 29, 2024
2f91a6c
refactor: change name systems into system.
ganesh-nithin Nov 29, 2024
63083f5
feat: add example documentation for system client.
ganesh-nithin Nov 29, 2024
5a4f0ae
feat: add api references for system client API.
ganesh-nithin Nov 29, 2024
1e17b89
refactor: format code using black & flake8.
ganesh-nithin Dec 1, 2024
13accda
refactor: address system client PR comments.
ganesh-nithin Dec 3, 2024
5dd2381
refactor: modify system client tests.
ganesh-nithin Dec 3, 2024
4a4b977
refactor: fix lint issues in CI.
ganesh-nithin Dec 3, 2024
814f1fb
refactor: modify model names.
ganesh-nithin Dec 4, 2024
85cc103
refactor: modify test cases for system client.
ganesh-nithin Dec 4, 2024
3ef21ec
refactor: modify field names to be pythonic.
ganesh-nithin Dec 6, 2024
6167da2
refactor: modify tests.
ganesh-nithin Dec 9, 2024
0e33a87
refactor: add wrapping for job client.
ganesh-nithin Dec 10, 2024
5575f20
refactor: modify clients & tests.
ganesh-nithin Dec 11, 2024
ee1d908
refactor: format system client code.
ganesh-nithin Dec 11, 2024
3e727c8
refactor: modify union operator.
ganesh-nithin Dec 11, 2024
6ebb8f1
refactor: format system client code.
ganesh-nithin Dec 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ API Reference
api_reference/dataframe
api_reference/spec
api_reference/file
api_reference/system

Indices and tables
------------------
Expand Down
18 changes: 18 additions & 0 deletions docs/api_reference/system.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.. _api_tag_page:

nisystemlink.clients.system
======================

.. autoclass:: nisystemlink.clients.system.SystemClient
:exclude-members: __init__

.. automethod:: __init__
.. automethod:: list_jobs
.. automethod:: create_job
.. automethod:: get_job_summary
.. automethod:: query_jobs
.. automethod:: cancel_jobs

.. automodule:: nisystemlink.clients.system.models
:members:
:imported-members:
28 changes: 28 additions & 0 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -210,5 +210,33 @@ Examples
Get the metadata of a File using its Id and download it.

.. literalinclude:: ../examples/file/download_file.py
:language: python
:linenos:


System API
-------

Overview
~~~~~~~~

The :class:`.SystemClient` class is the primary entry point of the System API.

When constructing a :class:`.SystemClient`, you can pass an
:class:`.HttpConfiguration` (like one retrieved from the
:class:`.HttpConfigurationManager`), or let :class:`.SystemClient` use the
default connection. The default connection depends on your environment.

With a :class:`.SystemClient` object, you can:

* Create, get, query, and cancel jobs
* Get the summary of a jobs

Examples
~~~~~~~~

Create, get, query, and cancel jobs

.. literalinclude:: ../examples/system/system.py
:language: python
:linenos:
57 changes: 57 additions & 0 deletions examples/system/system.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from nisystemlink.clients.core import HttpConfiguration
from nisystemlink.clients.system import SystemClient
from nisystemlink.clients.system.models import (
CancelJobRequest,
CreateJobRequest,
JobState,
QueryJobsRequest,
)

# Setup the server configuration to point to your instance of SystemLink Enterprise
server_configuration = HttpConfiguration(
server_uri="https://yourserver.yourcompany.com",
api_key="YourAPIKeyGeneratedFromSystemLink",
)
client = SystemClient(configuration=server_configuration)

# Get all jobs that have succeeded
jobs = client.list_jobs(
system_id="system_id",
jid="jid",
state=JobState.SUCCEEDED,
function="function",
skip=0,
take=10,
)

# Create a job
arg = [["A description"]]
tgt = ["HVM_domU--SN-ec200972-eeca-062e-5bf5-017a25451b39--MAC-0A-E1-20-D6-96-2B"]
fun = ["system.set_computer_desc"]
metadata = {"queued": True, "refresh_minion_cache": {"grains": True}}
job = CreateJobRequest(
arg=arg,
tgt=tgt,
fun=fun,
metadata=metadata,
)

create_job_response = client.create_job(job)

# Get job summary
job_summary = client.get_job_summary()

# Query jobs
query_job = QueryJobsRequest(
skip=0,
take=1000,
filter="result.success.Contains(false)",
projection="new(id,jid,state,lastUpdatedTimestamp,metadata.queued as queued)",
orderBy="createdTimestamp descending",
)
query_jobs_response = client.query_jobs(query_job)


# Cancel a job
cancel_job_request = CancelJobRequest(jid=create_job_response.jid, tgt=tgt[0])
cancel_job_response = client.cancel_jobs([cancel_job_request])
3 changes: 3 additions & 0 deletions nisystemlink/clients/system/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from ._system_client import SystemClient

# flake8: noqa
132 changes: 132 additions & 0 deletions nisystemlink/clients/system/_system_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
from typing import List, Optional

from nisystemlink.clients import core
from nisystemlink.clients.core._uplink._base_client import BaseClient
from nisystemlink.clients.core._uplink._methods import (
get,
post,
)
from uplink import Query

from . import models


class SystemClient(BaseClient):
def __init__(self, configuration: Optional[core.HttpConfiguration] = None):
"""Initialize an instance.

Args:
configuration: Defines the web server to connect to and information about
how to connect. If not provided, the
:class:`HttpConfigurationManager <nisystemlink.clients.core.HttpConfigurationManager>`
is used to obtain the configuration.

Raises:
ApiException: if unable to communicate with the ``/nisysmgmt`` Service.
"""
if configuration is None:
configuration = core.HttpConfigurationManager.get_configuration()

super().__init__(configuration, "/nisysmgmt/v1/")

@get(
"jobs",
args=[
Query("systemId"),
Query("jid"),
Query("state"),
Query("function"),
Query("skip"),
Query("take"),
],
)
def list_jobs(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def list_jobs(
def list_jobs_paged(

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipping the suggestion as list jobs are not paged as it don't have continuation token property.

self,
system_id: Optional[str] = None,
jid: Optional[str] = None,
state: Optional[models.JobState] = None,
function: Optional[str] = None,
skip: Optional[int] = None,
take: Optional[int] = None,
) -> List[models.Job]:
"""List the jobs that matched the criteria.

Args:
system_id: The ID of the system to that the jobs belong.
jid: The ID of the job.
state: The state of the jobs.
function: The salt function to run on the client.
skip: The number of jobs to skip.
take: The number of jobs to return.

Returns:
The list of jobs that matched the criteria.

Raises:
ApiException: if unable to communicate with the ``/nisysmgmt`` Service
or provided an invalid argument.
"""
...

@post("jobs")
def create_job(self, job: models.CreateJobRequest) -> models.CreateJobResponse:
"""Create a job.

Args:
job: The request to create the job.

Returns:
The job that was created.

Raises:
ApiException: if unable to communicate with the ``/nisysmgmt`` Service
or provided an invalid argument.
"""
...

@get("get-jobs-summary")
def get_job_summary(self) -> models.JobSummaryResponse:
"""Get a summary of the jobs.

Returns:
An instance of a JobsSummaryResponse.

Raises:
ApiException: if unable to communicate with the ``/nisysmgmt`` Service
or provided an invalid argument.
"""
...

@post("query-jobs")
def query_jobs(self, query: models.QueryJobsRequest) -> models.QueryJobsResponse:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def query_jobs(self, query: models.QueryJobsRequest) -> models.QueryJobsResponse:
def query_jobs_paged(self, query: models.QueryJobsRequest) -> models.QueryJobsResponse:

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipping the suggestion as query jobs are not paged as it don't have continuation token property.

"""Query the jobs.

Args:
query: The request to query the jobs.

Returns:
An instance of QueryJobsRequest.

Raises:
ApiException: if unable to communicate with the ``/nisysmgmt`` Service
or provided an invalid argument.
"""
...

@post("cancel-jobs")
def cancel_jobs(
self, job_ids: List[models.CancelJobRequest]
) -> models.CancelJobResponse:
"""Cancel the jobs.

Args:
job_ids: List of CancelJobRequest.

Returns:
The errors that appear while attempting the operation.

Raises:
ApiException: if unable to communicate with the ``/nisysmgmt`` Service
or provided an invalid argument.
"""
...
10 changes: 10 additions & 0 deletions nisystemlink/clients/system/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from ._job import Job, JobState
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from ._job import Job, JobState
from ._job import Job, JobState, JobConfig, JobResult

from ._create_job_request import CreateJobRequest
from ._create_job_response import CreateJobResponse
from ._job_summary_response import JobSummaryResponse
from ._query_jobs_request import QueryJobsRequest
from ._query_jobs_response import QueryJobsResponse
from ._cancel_job_request import CancelJobRequest
from ._cancel_job_response import CancelJobResponse

# flake8: noqa
13 changes: 13 additions & 0 deletions nisystemlink/clients/system/models/_cancel_job_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from typing import Optional

from nisystemlink.clients.core._uplink._json_model import JsonModel


class CancelJobRequest(JsonModel):
"""Model for cancel job request."""

jid: Optional[str] = None
"""The ID of the job to cancel."""

system_id: Optional[str] = None
"""The system ID that the job to cancel targets."""
11 changes: 11 additions & 0 deletions nisystemlink/clients/system/models/_cancel_job_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from typing import Optional

from nisystemlink.clients.core import ApiError
from nisystemlink.clients.core._uplink._json_model import JsonModel


class CancelJobResponse(JsonModel):
"""Model for response of a cancel job request."""

error: Optional[ApiError] = None
"""Represents the standard error structure."""
19 changes: 19 additions & 0 deletions nisystemlink/clients/system/models/_create_job_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from typing import Any, Dict, List, Optional

from nisystemlink.clients.core._uplink._json_model import JsonModel


class CreateJobRequest(JsonModel):
"""Model for create job request."""

arg: Optional[List[List[str]]] = None
"""Arguments of the salt functions."""

tgt: Optional[List[str]] = None
"""The target systems for the job."""

fun: Optional[List[str]] = None
"""Salt functions related to the job."""

metadata: Optional[Dict[str, Any]] = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update it with actual properties..

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated it. As CreateJobResponse is extended from CreateJobRequest, properties will be updated in it.

"""The metadata associated with the job."""
15 changes: 15 additions & 0 deletions nisystemlink/clients/system/models/_create_job_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from typing import Optional

from nisystemlink.clients.core import ApiError

from ._create_job_request import CreateJobRequest


class CreateJobResponse(CreateJobRequest):
"""Model for response of create job request."""

error: Optional[ApiError] = None
"""Represents the standard error structure."""

jid: Optional[str] = None
"""The job ID."""
Loading
Loading