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 Systems State Service APIs #89

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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/systemsstate

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

nisystemlink.clients.systemsstate
======================

.. autoclass:: nisystemlink.clients.systemsstate.SystemsStateClient
:exclude-members: __init__

.. automethod:: __init__
.. automethod:: get_states
.. automethod:: create_state
.. automethod:: export_state
.. automethod:: export_state_from_system
.. automethod:: get_state
.. automethod:: update_state
.. automethod:: delete_state
.. automethod:: replace_state_content
.. automethod:: import_state
.. automethod:: delete_states

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

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


SystemsStateService API
-------

Overview
~~~~~~~~

The :class:`.SystemsStateClient` class is the primary entry point of the Product API.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
The :class:`.SystemsStateClient` class is the primary entry point of the Product API.
The :class:`.SystemsStateClient` class is the primary entry point of the Systems State API.


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

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

* Create, update, query, and delete states

Examples
~~~~~~~~

Create, query, update, and delete states

.. literalinclude:: ../examples/systemsstate/systemsstate.py
:language: python
:linenos:
3 changes: 3 additions & 0 deletions nisystemlink/clients/systemsstate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from ._systems_state_client import SystemsStateClient

# flake8: noqa
256 changes: 256 additions & 0 deletions nisystemlink/clients/systemsstate/_systems_state_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
"""Implementation of SystemsStateService Client"""

from typing import Dict, List, Optional

from nisystemlink.clients import core
from nisystemlink.clients.core._uplink._base_client import BaseClient
from nisystemlink.clients.core._uplink._methods import delete, get, patch, post
from uplink import Body, Part, Path, Query

from . import models


class SystemsStateClient(BaseClient):
# prevent pytest from thinking this is a test class
__test__ = False
Comment on lines +14 to +15
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# prevent pytest from thinking this is a test class
__test__ = False

Not relevant as the class name does not start with Test


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 Spec Service.
"""
if configuration is None:
configuration = core.HttpConfigurationManager.get_configuration()

super().__init__(configuration, base_path="/nisystemsstate/v1/")

@get(
"states",
args=[
Query("Skip"),
Query("Take"),
Query("Workspace"),
Query("Architecture"),
Query("Distribution"),
],
)
def get_states(
self,
skip: Optional[int] = None,
take: Optional[int] = None,
workspace: Optional[str] = None,
architecture: Optional[models.Architecture] = None,
distribution: Optional[models.Distribution] = None,
Comment on lines +49 to +50
Copy link
Member

Choose a reason for hiding this comment

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

Enum is not supported by Uplink and hence create a wrapper method to take care of Enum to str conversion.

Reference -

order_by_str = order_by.value if order_by is not None else None

) -> models.StateDescriptionListResponse:
"""Get the list of states

Args:
`skip`: Number of files to skip in the result when paging
`take`: Number of files to return in the result
`workspace`: The workspace id of the states
`architecture`: The states that are compatible with the requested architecture
`distribution`: The states that are compatible with the requested distribution

Returns:
The list of states for the given query parameters

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

@post("states", args=[Body])
def create_state(self, new_state: models.StateRequest) -> models.StateResponse:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def create_state(self, new_state: models.StateRequest) -> models.StateResponse:
def create_state(self, state: models.StateRequest) -> models.StateResponse:

"""Create state

Args:
`state`: Information about the state to be created.

Returns:
The state created

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

@post("export-state", args=[Body])
def export_state(self, export_state_request: models.ExportStateRequest) -> str:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def export_state(self, export_state_request: models.ExportStateRequest) -> str:
def export_state(self, query: models.ExportStateRequest) -> str:

"""Generate state export

Args:
`export_state_request`: Contains identifying information on the state to export.

Returns:
The exported state as a file.

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

@post("export-state-from-system", args=[Body])
def export_state_from_system(
self, export_state_from_system_request: models.ExportStateFromSystemRequest
) -> str:
Comment on lines +101 to +105
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
@post("export-state-from-system", args=[Body])
def export_state_from_system(
self, export_state_from_system_request: models.ExportStateFromSystemRequest
) -> str:
@params({"inline": True}) # type: ignore
@post("export-state-from-system", args=[Field("systemID")])
def export_state_from_system(self, system_id: str) -> str:

Eliminate the need for a request object by inlining parameters,
References for the recommendation,

@params({"inline": True}) # type: ignore

@post("products", args=[Field("products")])

"""Generate state export of a system

Args:
`export_state_from_system_request`: Contains the system id from which to export the state.

Returns:
The exported state of the system as a file.

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

@get("states/{stateId}", args=[Path("stateId")])
def get_state(self, state_id: str) -> models.StateResponse:
Copy link
Member

Choose a reason for hiding this comment

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

The method name and arg id together implies state_id

Suggested change
def get_state(self, state_id: str) -> models.StateResponse:
def get_state(self, id: str) -> models.StateResponse:

"""Get state based on the give stateId parameter

Args:
`state_id`: The respective id of the state

Returns:
The state of the given id

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

@patch("states/{stateId}", args=[Path("stateId"), Body])
def update_state(
self, state_id: str, patch_updates: Dict[str, str]
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
self, state_id: str, patch_updates: Dict[str, str]
self, id: str, patch_updates: Dict[str, str]

) -> models.StateResponse:
"""Update an existing state

Args:
`state_id`: The respective id of the state to be updated
`patch_updates`: A dictionary containing the properties to update, where
keys are property names (strings) and values are the updated values.

Returns:
The updated state

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

@delete("states/{stateId}", args=[Path("stateId")])
def delete_state(self, state_id: str) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def delete_state(self, state_id: str) -> None:
def delete_state(self, id: str) -> None:

"""Deleting an existing state

Args:
`state_id`: The respective id of the state to be deleted

Returns:
None

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

@post(
"replace-state-content",
args=[
Part(name="Id", type=str),
Part(name="ChangeDescription", type=str),
Part(name="File", type=str),
],
)
def replace_state_content(
Copy link
Member

Choose a reason for hiding this comment

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

By file, do you mean the str content of the file? in the description it states as .sls file, then, should the file be a path?

self, id: str, change_description: str, file: str
) -> models.StateResponse:
"""Replace state content

Args:
`id`: The id of the state that is to have its content replaced.
`change_description`: The description for this change.
`file`: The state file (.sls) to get replaced with the existing one.

Returns:
The replaced state.

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

@post(
"import-state",
args=[
Part(name="Name", type=str),
Part(name="Description", type=str),
Part(name="Distribution", type=str),
Part(name="Architecture", type=str),
Part(name="Properties", type=str),
Part(name="Workspace", type=str),
Part(name="File", type=str),
],
)
def import_state(
Copy link
Member

Choose a reason for hiding this comment

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

Since there are models.Architecture and models.Distribution, use the same as inputs for this method as well, do handle the enum to str conversion using the wrapper function

self,
name: str,
description: str,
distribution: str,
architecture: str,
properties: str,
workspace: str,
file: str,
) -> models.StateResponse:
"""Import state

Args:
`name`: The name of the state to be imported. Required.
`description`: A description of the state.
`distribution`: The distribution supported by the state. Required.
`architecture`: The architecture supported by the state. Required.
`properties`: Custom properties for the state, serialized as a JSON string.
`workspace`: The ID of the workspace. Available starting with version 3 of
the createOrUpdateStates operation.
`file`: The state file (.sls) to be imported.

Returns:
The imported state.

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

@post("delete-states", args=[Body])
def delete_states(self, states_id_list: List[str]) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def delete_states(self, states_id_list: List[str]) -> None:
def delete_states(self, ids: List[str]) -> None:

"""Delete multiple states

Args:
`states_id_list`: A list of state ids for the states that are to be deleted.

Returns:
None.

Raises:
ApiException : if unable to communicate with the ``/nisystemsstate`` Service
or provided an invalid argument.
"""
...
10 changes: 10 additions & 0 deletions nisystemlink/clients/systemsstate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from ._state_response import StateDescriptionListResponse, StateResponse
from ._state_request import (
StateRequest,
ExportStateRequest,
ExportStateFromSystemRequest,
)
from ._architecture_enum import Architecture
from ._distribution_enum import Distribution

# flake8: noqa
13 changes: 13 additions & 0 deletions nisystemlink/clients/systemsstate/models/_architecture_enum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from enum import Enum


class Architecture(Enum):
"""Supported architecture by a state"""

ARM = "ARM"

X64 = "X64"

X86 = "X86"

ANY = "ANY"
13 changes: 13 additions & 0 deletions nisystemlink/clients/systemsstate/models/_distribution_enum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from enum import Enum


class Distribution(Enum):
"""Supported distribution by a state"""

NI_LINUXRT = "NI_LINUXRT"

NI_LINUXRT_NXG = "NI_LINUXRT_NXG"

WINDOWS = "WINDOWS"

ANY = "ANY"
21 changes: 21 additions & 0 deletions nisystemlink/clients/systemsstate/models/_feed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from typing import Optional

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


class Feed(JsonModel):
"""Model for object defining a feed, which contains the name, url, and Booleans
for whether the feed is enabled and compressed
"""

name: Optional[str] = None
"""Gets or sets name of the feed."""

url: Optional[str] = None
"""Gets or sets the url for the repository."""

enabled: bool
"""Gets or sets whether the feed is enabled or not."""

compressed: bool
"""Gets or sets whether the feed is compressed or not."""
Loading
Loading