Metadata-Version: 2.4
Name: maat_client
Version: 0.1.1
Summary: Python library for communicating with the Maat API (Management of Assets and Services)
Author: PCSS Maat Client Contributors, Tomasz Szewczyk, Marcin Adamski
License-Expression: MIT
Project-URL: Repository, https://gitlab.pcss.pl/public-projects/maat_client
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.25.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: black>=22.0; extra == "dev"
Requires-Dist: flake8>=5.0; extra == "dev"
Requires-Dist: isort>=5.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Dynamic: license-file

[![Latest Release](https://gitlab.pcss.pl/public-projects/maat_client/-/badges/release.svg)](https://gitlab.pcss.pl/public-projects/maat_client/-/releases)


# maat_client

Python library for communicating with the Maat API (Management of Assets and Services) for managing physical resources, services, and their characteristics.

## Installation

```bash
pip install maat_client
```

Or install from source:

```bash
pip install .
```

For development:

```bash
pip install -e ".[dev]"
```

## Requirements

- Python >= 3.8
- requests

## Quick Start

### Initializing client with basic authentication

```python
from maat_client import MaatClient

client = MaatClient(
    host="https://maat.example.com",
    resource_path="/resourceInventoryManagement/v4.0.0/resource",
    username="user",
    password="password"
)
```

### Initializing client with Keycloak

```python
from maat_client import MaatClient

client = MaatClient(
    host="https://maat.example.com",
    resource_path="/resourceInventoryManagement/v4.0.0/resource",
    kc_base_url="https://keycloak.example.com",
    kc_client_id="client_id",
    kc_client_secret="client_secret",
    kc_realm="realm",
    kc_username="user",
    kc_password="password"
)
```

## Core Classes

### MaatClient

Main client for communicating with the Maat API.

#### Constructor

```python
MaatClient(
    host="https://localhost",
    resource_path="/resourceInventoryManagement/v4.0.0/resource",
    username=os.getenv("USER"),
    password=None,
    verify=True,
    request_timeout=None,
    kc_base_url=None,
    kc_client_id=None,
    kc_client_secret=None,
    kc_realm=None,
    kc_grant_type="password",
    kc_username=None,
    kc_password=None,
    kc_token_refresh_margin=30
)
```

**Parameters:**
- `host` - Maat server address (default: `https://localhost`)
- `resource_path` - Resource path (default: `/resourceInventoryManagement/v4.0.0/resource`)
- `username` - Username for basic authentication (default: `os.getenv("USER")`)
- `password` - Password for basic authentication
- `verify` - SSL certificate verification (default: `True`)
- `request_timeout` - Request timeout
- `kc_base_url` - Keycloak address
- `kc_client_id` - Keycloak client ID
- `kc_client_secret` - Keycloak client secret
- `kc_realm` - Keycloak realm
- `kc_grant_type` - Keycloak grant type (`password` or `client_credentials`)
- `kc_username` - Keycloak username
- `kc_password` - Keycloak password
- `kc_token_refresh_margin` - Token refresh margin in seconds (default: `30`)

#### Methods

##### `find(_query_params: dict)`

Search for resources in the Maat database.

**Parameters:**
- `_query_params` - Dictionary with filter rules

**Returns:** List of matching resources

**Example:**
```python
resources = client.find({"name": "example-resource"})
```

##### `get_resource(_resource_id: str, _query_params: dict = None)`

Retrieve a single resource from the Maat database.

**Parameters:**
- `_resource_id` - Maat resource ID
- `_query_params` - Optional filter rules

**Returns:** Resource as a dictionary

**Example:**
```python
resource = client.get_resource("resource-id-123")
```

##### `add_resource(_resource) -> str`

Add a resource to the Maat database.

**Parameters:**
- `_resource` - Resource object with `get_active_params()` method

**Returns:** ID of the newly created resource

**Example:**
```python
from maat_client import PhysicalResource

resource = PhysicalResource(name="example", type="example-type")
resource_id = client.add_resource(resource)
```

##### `update_resource(_resource_id: str, _resource)`

Update an existing resource, merging `resourceCharacteristic` lists.

**Parameters:**
- `_resource_id` - Maat resource ID
- `_resource` - Resource object with `get_active_params()` method

**Example:**
```python
resource = PhysicalResource(name="updated-name")
client.update_resource("resource-id-123", resource)
```

##### `delete_resource(_resource_id: str) -> bool`

Delete a resource from the Maat database.

**Parameters:**
- `_resource_id` - Maat resource ID

**Returns:** `True` on success

**Example:**
```python
client.delete_resource("resource-id-123")
```

### Characteristic

Resource characteristic (name-value pair).

#### Constructor

```python
Characteristic(name=None, value=None)
```

**Parameters:**
- `name` - Characteristic name
- `value` - Characteristic value

#### Methods

- `to_dict()` - Convert object to dictionary
- `to_str()` - String representation
- `__repr__()` - String representation for `print` and `pprint`

### BaseResource

Base class for resources.

#### Constructor

```python
BaseResource(
    category=None,
    description=None,
    href=None,
    id=None,
    name=None,
    resource_characteristic=None,
    resource_relationship=None,
    schema_location=None,
    type=None
)
```

**Parameters:**
- `category` - Resource category
- `description` - Resource description
- `href` - Resource href
- `id` - Resource ID
- `name` - Resource name
- `resource_characteristic` - List of characteristics (`list[Characteristic]`)
- `resource_relationship` - List of relationships (`list[ResourceRelationship]`)
- `schema_location` - Schema location
- `type` - Resource type

#### Methods

- `to_dict()` - Convert object to dictionary
- `to_str()` - String representation
- `__repr__()` - String representation for `print` and `pprint`

### PhysicalResource

Physical resource.

#### Constructor

```python
PhysicalResource(
    category=None,
    description=None,
    href=None,
    id=None,
    name=None,
    place=None,
    resource_characteristic=None,
    resource_relationship=None,
    schema_location=None,
    type=None,
    serial_number=None,
    operational_state=None,
    resource_status=None,
    usage_state=None
)
```

**Parameters:**
- `category` - Resource category
- `description` - Resource description
- `href` - Resource href
- `id` - Resource ID
- `name` - Resource name
- `place` - Resource location
- `resource_characteristic` - List of characteristics (`list[Characteristic]`)
- `resource_relationship` - List of relationships (`list[ResourceRelationship]`)
- `schema_location` - Schema location
- `type` - Resource type
- `serial_number` - Serial number
- `operational_state` - Operational state
- `resource_status` - Resource status
- `usage_state` - Usage state

#### Methods

- `to_dict()` - Convert object to dictionary
- `get_active_params()` - Get active (non-None) parameters
- `to_str()` - String representation
- `__repr__()` - String representation for `print` and `pprint`

### Service

Service.

#### Constructor

```python
Service(
    category=None,
    description=None,
    href=None,
    id=None,
    name=None,
    service_characteristic=None,
    service_relationship=None,
    resource_relationship=None,
    schema_location=None,
    type=None
)
```

**Parameters:**
- `category` - Service category
- `description` - Service description
- `href` - Service href
- `id` - Service ID
- `name` - Service name
- `service_characteristic` - List of service characteristics (`list[Characteristic]`)
- `service_relationship` - List of service relationships
- `resource_relationship` - List of resource relationships (`list[ResourceRelationship]`)
- `schema_location` - Schema location
- `type` - Service type

#### Methods

- `to_dict()` - Convert object to dictionary
- `get_active_params()` - Get active (non-None) parameters
- `to_str()` - String representation
- `__repr__()` - String representation for `print` and `pprint`

### ResourceRelationship

Relationship between resources.

#### Constructor

```python
ResourceRelationship(relationshipType=None, resource=None)
```

**Parameters:**
- `relationshipType` - Relationship type
- `resource` - Dictionary with resource information

#### Methods

- `to_dict()` - Convert object to dictionary
- `to_str()` - String representation
- `__repr__()` - String representation for `print` and `pprint`

## Usage Examples

### Creating and adding a physical resource

```python
from maat_client import MaatClient, PhysicalResource

# Initialize client
client = MaatClient(
    host="https://maat.example.com",
    username="user",
    password="password"
)

# Create physical resource
resource = PhysicalResource(
    name="example-router",
    type="router",
    serial_number="SN123456",
    operational_state="active",
    resource_characteristic=[
        Characteristic(name="interface-count", value="24"),
        Characteristic(name="vendor", value="Cisco")
    ]
)

# Add resource
resource_id = client.add_resource(resource)
print(f"Created resource with ID: {resource_id}")
```

### Creating and adding a service

```python
from maat_client import MaatClient, Service, Characteristic

# Initialize client
client = MaatClient(
    host="https://maat.example.com",
    username="user",
    password="password"
)

# Create service
service = Service(
    name="example-service",
    type="connectivity",
    service_characteristic=[
        Characteristic(name="bandwidth", value="1Gbps"),
        Characteristic(name="latency", value="10ms")
    ]
)

# Add service
service_id = client.add_resource(service)
print(f"Created service with ID: {service_id}")
```

### Searching for resources

```python
# Search for resources by name
resources = client.find({"name": "example-resource"})

# Search for resources by type
resources = client.find({"type": "router"})

# Search for resources with multiple criteria
resources = client.find({"name": "example", "type": "router"})
```

### Updating a resource

```python
from maat_client import PhysicalResource

# Retrieve existing resource
resource = client.get_resource("resource-id-123")

# Create update object
updated_resource = PhysicalResource(
    name="updated-name",
    resource_characteristic=[
        Characteristic(name="new-characteristic", value="value")
    ]
)

# Update resource
client.update_resource("resource-id-123", updated_resource)
```

### Deleting a resource

```python
# Delete resource
client.delete_resource("resource-id-123")
```

## Errors

The library defines two main exception types:

- `MaatAuthError` - Authentication errors (e.g., invalid Keycloak credentials)
- `MaatAPIError` - API errors (e.g., invalid HTTP status code)

## License

This project is distributed under the MIT License. See the LICENSE file for details.
