8000 feat: added clients for systems management service create virtual system, remove systems and query system API by ammarhusain-EMR · Pull Request #138 · ni/nisystemlink-clients-python · GitHub
[go: up one dir, main page]

Skip to content

feat: added clients for systems management service create virtual system, remove systems and query system API #138

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

Merged
merged 17 commits into from
May 26, 2025
Merged
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
16 changes: 16 additions & 0 deletions docs/api_reference/systems.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.. _api_tag_page:

nisystemlink.clients.systems
======================

.. autoclass:: nisystemlink.clients.spec.SystemsClient
:exclude-members: __init__

.. automethod:: __init__
.. automethod:: create_virtual_system
.. automethod:: remove_systems
.. automethod:: query_systems

.. automodule:: nisystemlink.clients.systems.models
:members:
:imported-members:
29 changes: 27 additions & 2 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,6 @@ Create, query, retry, and cancel notebook executions.
:language: python
:linenos:


Asset Management API
-------

Expand All @@ -346,4 +345,30 @@ create, delete and query asset

.. literalinclude:: ../examples/assetmanagement/assets.py
:language: python
:linenos:
:linenos:

Systems API
-------

Overview
~~~~~~~~

The :class:`.SystemsClient` class is the primary entry point of the Systems API.

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

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

* Create, query, and remove systems.

Examples
~~~~~~~~

Create, query, and remove some systems.

.. literalinclude:: ../examples/systems/systems.py
:language: python
:linenos:
44 changes: 44 additions & 0 deletions examples/systems/systems.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from nisystemlink.clients.core._http_configuration import HttpConfiguration
from nisystemlink.clients.systems._systems_client import SystemsClient
from nisystemlink.clients.systems.models._create_virtual_systems_request import (
CreateVirtualSystemRequest,
)
from nisystemlink.clients.systems.models._query_systems_request import (
QuerySystemsRequest,
)

# 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 = SystemsClient(configuration=server_configuration)

# Systems request metadata.
create_virtual_system_request: CreateVirtualSystemRequest = CreateVirtualSystemRequest(
alias="Python integration virtual system",
workspace="33eba2fe-fe42-48a1-a47f-a6669479a8aa",
)

# Create a virtual system.
create_virtual_system_response = client.create_virtual_system(
create_virtual_system_request=create_virtual_system_request
)

minion_id = None

if create_virtual_system_response and create_virtual_system_response.minionId:
minion_id = create_virtual_system_response.minionId

# Query systems using id.
query_systems_request = QuerySystemsRequest(
filter=f'id="{minion_id}"', projection="new(id, alias)"
)

client.query_systems(query=query_systems_request)

# Delete the created systems.
if minion_id is not None:
remove_systems = [minion_id]
client.remove_systems(tgt=remove_systems)
3 changes: 3 additions & 0 deletions nisystemlink/clients/systems/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from nisystemlink.clients.systems._systems_client import SystemsClient

# flake8: noqa
87 changes: 87 additions & 0 deletions nisystemlink/clients/s 8000 ystems/_systems_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""Implementation of SystemsClient"""

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 post
from uplink import Field, retry

from . import models


@retry(
when=retry.when.status(408, 429, 502, 503, 504),
stop=retry.stop.after_attempt(5),
on_exception=retry.CONNECTION_ERROR,
)
class SystemsClient(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 Systems Service.
"""
if configuration is None:
configuration = core.HttpConfigurationManager.get_configuration()

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

@post("virtual")
def create_virtual_system(
self, create_virtual_system_request: models.CreateVirtualSystemRequest
) -> models.CreateVirtualSystemResponse:
"""Creates a virtual system.

Args:
alias: The alias of the virtual system.
workspace: The workspace to create the virtual system in.

Raises:
ApiException: if unable to communicate with the `/nisysmgmt` service or provided invalid
arguments.
"""
...

@post("query-systems")
def query_systems(
self, query: models.QuerySystemsRequest
) -> models.QuerySystemsResponse:
"""Queries for systems that match the filter.

Args:
query : The query contains a DynamicLINQ query string in addition to other details
about how to filter and return the list of systems.

Returns:
Response containing the list of systems that match the filter.

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

@post("remove-systems", args=[Field("tgt")])
def remove_systems(self, tgt: List[str]) -> models.RemoveSystemsResponse:
"""Removes multiple systems.

Args:
virtual_system_to_remove : List of unique IDs of systems.

Returns:
A partial success if any systems failed to remove, or None if all
systems were removed successfully.

Raises:
ApiException: if unable to communicate with the `/nisysmgmt` Service
or provided an invalid argument.
"""
...
17 changes: 17 additions & 0 deletions nisys 9E19 temlink/clients/systems/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from nisystemlink.clients.systems.models._create_virtual_systems_request import (
CreateVirtualSystemRequest,
)
from nisystemlink.clients.systems.models._create_virtual_systems_response import (
CreateVirtualSystemResponse,
)
from nisystemlink.clients.systems.models._query_systems_request import (
QuerySystemsRequest,
)
from nisystemlink.clients.systems.models._query_systems_response import (
QuerySystemsResponse,
)
from nisystemlink.clients.systems.models._remove_systems_response import (
RemoveSystemsResponse,
)

# flake8: noqa
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from nisystemlink.clients.core._uplink._json_model import JsonModel


class CreateVirtualSystemRequest(JsonModel):
"""Model for create virtual system response containing the minion ID of the system which is created."""

alias: str
"""Alias of the virtual system."""

workspace: str
"""Workspace to create the virtual system in."""
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import Optional

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


class CreateVirtualSystemResponse(JsonModel):
"""Model for create virtual system response containing the minion ID of the system which is created."""

minionId: Optional[str] = None
"""The minion ID of the created virtual system."""
68 changes: 68 additions & 0 deletions nisystemlink/clients/systems/models/_query_systems_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from typing import Optional

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


class QuerySystemsRequest(JsonModel):
"""Model for query systems request."""

skip: Optional[int] = None
"""Gets or sets the number of systems to skip."""

take: Optional[int] = None
"""Gets or sets number of systems to return maximum value is 1000."""

filter: Optional[str] = None
"""The systems query filter is dynamic LINQ format.

`id` : String representing the ID of the system.
`createdTimestamp`: ISO-8601 formatted timestamp string specifying the
date when the system was registered.
`lastUpdatedTimestamp`: ISO-8601 formatted timestamp string
specifying the last date the system was updated.
`alias`: String representing the alias of the system.
`activation.lastUpdatedTimestamp`: ISO-8601 formatted timestamp string
specifying the last date the system activation was updated.
`activation.data.activated`: Boolean representing whether the system is
activated or not.
`activation.data.licenseName`: String representing the name of the license.
`activation.data.licenseVersion`: String representing the license version.
`connected.lastUpdatedTimestamp`: ISO-8601 formatted timestamp string
specifying the last date the system connection was updated.
`connected.data.state`: String representing the state of the system.
`grains.lastUpdatedTimestamp`: ISO-8601 formatted timestamp string
specifying the last date the system grains were updated.
`grains.data`: Dictionary of string to object representing general
information about the system. Example: grains.data.os == "Windows"
`packages.lastUpdatedTimestamp`: ISO-8601 formatted timestamp string
specifying the last date the system installed packages were updated.
`packages.data`: Dictionary representing software packages installed on the
system.
Example: packages.data.ni-package-manager-upgrader.version: String
representing the installed version of ni-package-manager-upgrader package.
`feeds.lastUpdatedTimestamp`: ISO-8601 formatted timestamp string
specifying the last date the system configured feeds were updated.
`feeds.data`: Dictionary representing the feeds configured on the system.
`keywords.lastUpdatedTimestamp`: ISO-8601 formatted timestamp string
specifying the last date the system keywords were updated.
`keywords.data`: Array of strings representing the keywords of the system.
Example: keywords.data.Contains("test")
`properties.lastUpdatedTimestamp`: ISO-8601 formatted timestamp string
specifying the last date the system properties were updated.
`properties.data`: Dictionary of string to string representing metadata
information about a system. Example: properties.data.owner == "admin"
`status.data.http_connected`: Boolean representing the status of the http
connection to the master.

See [Dynamic Linq](https://github.com/ni/systemlink-OpenAPI-documents/wiki/Dynamic-Linq-Query-Language)
documentation for more details.

`"@0"`, `"@1"` etc. can be used in conjunction with the `substitutions` parameter to keep this
query string more simple and reusable."""

projection: Optional[str] = None
"""Gets or sets specifies the projection for resources.
Use this field to receive specific properties of the model."""

order_by: Optional[str] = None
"""Gets or sets the order in which data returns."""
13 changes: 13 additions & 0 deletions nisystemlink/clients/systems/models/_query_systems_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from typing import Any, Dict, List, Optional

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


class QuerySystemsResponse(JsonModel):
"""Model for query systems request."""

count: Optional[int] = None
"""Number of systems match the query."""

data: Optional[List[Dict[str, Any]]] = None
"""Contains info of the queried systems."""
16 changes: 16 additions & 0 deletions nisystemlink/clients/systems/models/_remove_systems_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import List, Optional

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


class RemoveSystemsResponse(JsonModel):
"""Model for remove systems response containing the IDs of the systems which were deleted."""

jid: Optional[str] = None
"""The job ID of the remove systems operation."""

removed_ids: Optional[List[str]] = None
"""The IDs of the systems that were successfully removed."""

failed_ids: Optional[List[str]] = None
"""The IDs of the systems that could not be removed."""
1 change: 1 addition & 0 deletions tests/integration/systems/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# flake8: noqa
Loading
0