Skip to main content

Python SDK for Graphiant NaaS

Project description

Graphiant SDK Python

PyPI version Python 3.9+ License: MIT Documentation CI/CD

A comprehensive Python SDK for Graphiant Network-as-a-Service (NaaS) offerings, providing seamless integration with Graphiant's network automation platform.

Refer Graphiant Docs to get started with Graphiant Network-as-a-Service (NaaS) offerings.

📚 Documentation

✨ Features

  • Complete API Coverage: Full access to all Graphiant REST API endpoints
  • Authentication: Built-in bearer token authentication
  • Device Management: Comprehensive device configuration and monitoring
  • Network Operations: Circuit management, interface configuration, and routing
  • Error Handling: Robust exception handling with detailed error messages
  • Type Safety: Full type hints and validation using Pydantic models
  • CLI Support: Command-line interface for quick operations

🚀 Quick Start

Installation

Install the package from PyPI:

pip install graphiant-sdk

Basic Usage

import graphiant_sdk
from graphiant_sdk.exceptions import (
    ApiException, BadRequestException, UnauthorizedException, 
    ForbiddenException, NotFoundException, ServiceException
)

# Create client configuration
config = graphiant_sdk.Configuration(
    host="https://api.graphiant.com",
    username="your_username",
    password="your_password"
)

# Initialize API client
api_client = graphiant_sdk.ApiClient(config)
api = graphiant_sdk.DefaultApi(api_client)

# Authenticate and get bearer token
auth_request = graphiant_sdk.V1AuthLoginPostRequest(
    username=config.username,
    password=config.password
)

try:
    auth_response = api.v1_auth_login_post(v1_auth_login_post_request=auth_request)
    bearer_token = f'Bearer {auth_response.token}'
    print(f"Authentication successful")
except Exception as e:
    print(f"Authentication failed: {e}")
    exit(1)

# Get device summary
try:
    edges_summary = api.v1_edges_summary_get(authorization=bearer_token)
    print(f"Found {len(edges_summary.edges_summary)} devices")
    
    for device in edges_summary.edges_summary:
        print(f"Device: {device.hostname}, Status: {device.status}")
        
except Exception as e:
    print(f"Failed to get device summary: {e}")

🔄 Migration Guide: Upgrading from 25.10.2 to 25.11.1+

The 25.11.1+ API is optimized to reuse redundant schemas, which results in changes to inner class types. You may need to update your existing scripts to use the newer class names.

Benefits of Upgrading

The new API specification (25.11.1+) brings significant improvements:

  • Reduced Specification Size: The API specification file size has been reduced from 9.8M to 1.5M (~85% reduction) through schema optimization and reuse
  • Enhanced Documentation: The new spec includes more comprehensive documentation for better developer experience
  • Cleaner Class Names: Response classes no longer include HTTP status codes, making imports and type references more intuitive
  • Reusable Schemas: Inner classes now use reusable schema names, meaning common schemas share the same inner class names across different endpoints. This reduces code duplication, improves maintainability, and allows you to reuse the same imports and type references for similar data structures

Important Changes

1. Remove Status Code from Class Names

Response class names no longer include HTTP status codes. Update your imports and type references:

Before (25.11.1):

from graphiant_sdk.models.v1_edges_summary_get200_response import V1EdgesSummaryGet200Response
from graphiant_sdk.models.v1_global_summary_post200_response import V1GlobalSummaryPost200Response
from graphiant_sdk.models.v1_devices_device_id_config_put202_response import V1DevicesDeviceIdConfigPut202Response

After (25.11.1):

from graphiant_sdk.models.v1_edges_summary_get_response import V1EdgesSummaryGetResponse
from graphiant_sdk.models.v1_global_summary_post_response import V1GlobalSummaryPostResponse
from graphiant_sdk.models.v1_devices_device_id_config_put_response import V1DevicesDeviceIdConfigPutResponse

Common patterns to update:

  • Post200ResponsePostResponse
  • Get200ResponseGetResponse
  • Put202ResponsePutResponse
  • Put204ResponsePutResponse
  • Post201ResponsePostResponse

Note: The vast majority of response classes have been updated. A few exceptions may remain (e.g., V1AuthRefreshGet200Response), but these are rare edge cases. When in doubt, check the current API file (graphiant_sdk/api/default_api.py) or the model documentation.

2. Find and Rename Inner Property Class Names

Inner classes have been renamed to use reusable schema names. Because schemas are now reused, common schemas will share the same inner class names across different endpoints. This means you can reuse the same import and type references for similar data structures.

To find the new class name:

  1. Step 1: Find the top-level class name by removing the status code (if it exists) and trimming to Response:

    • V1GlobalSummaryPost200ResponseV1GlobalSummaryPostResponse
  2. Step 2: Check the documentation for the inner property's new class name:

    • Open docs/V1GlobalSummaryPostResponse.md
    • Find the property (e.g., summaries)
    • Note the new class name (e.g., ManaV2GlobalObjectSummary)

Key Benefit: If multiple endpoints use the same schema structure, they will now share the same inner class name. For example, if both V1GlobalSummaryPostResponse and V1EdgesSummaryGetResponse use the same summary schema, they will both use ManaV2GlobalObjectSummary as the inner class type.

Example Migration:

Before (25.11.1):

from graphiant_sdk.models.v1_global_summary_post200_response import V1GlobalSummaryPost200Response
from graphiant_sdk.models.v1_global_summary_post200_response_summaries_inner import V1GlobalSummaryPost200ResponseSummariesInner

response = api.v1_global_summary_post(...)
for summary in response.summaries:
    # summary is V1GlobalSummaryPost200ResponseSummariesInner
    print(summary.name)

After (25.11.1):

from graphiant_sdk.models.v1_global_summary_post_response import V1GlobalSummaryPostResponse
from graphiant_sdk.models.mana_v2_global_object_summary import ManaV2GlobalObjectSummary
# or
from graphiant_sdk.models import ManaV2GlobalObjectSummary

response = api.v1_global_summary_post(...)
for summary in response.summaries:
    # summary is ManaV2GlobalObjectSummary
    print(summary.name)

3. Finding Endpoint Request/Response Models

To find all endpoints and their request/response models:

  • API Reference: See graphiant_sdk/api/default_api.py or docs/DefaultApi.md
  • Model Documentation: Check individual model files in docs/ directory (e.g., docs/V1GlobalSummaryPostResponse.md)

Migration Checklist

  • Search and replace all 200Response, 202Response, 201Response, 204Response patterns
  • Update imports for response classes
  • Find and update inner class references (check documentation files)
  • Test all API calls with new class names
  • Update type hints and annotations

Need Help?

  • Check the API Reference for endpoint details
  • Review model documentation in the docs/ directory
  • See Support section for additional resources

🔧 Advanced Usage

Device Configuration Management

# Verify device portal status before configuration
def verify_device_portal_status(api, bearer_token, device_id):
    """Verify device is ready for configuration updates"""
    edges_summary = api.v1_edges_summary_get(authorization=bearer_token)
    
    for edge in edges_summary.edges_summary:
        if edge.device_id == device_id:
            if edge.portal_status == "Ready" and edge.tt_conn_count == 2:
                return True
            else:
                raise Exception(f"Device {device_id} not ready. "
                              f"Status: {edge.portal_status}, "
                              f"TT Connections: {edge.tt_conn_count}")
    return False

# Configure device interfaces
def configure_device_interfaces(api, bearer_token, device_id):
    """Configure device interfaces with circuits and subinterfaces"""
    
    # Define circuits
    circuits = {
        "c-gigabitethernet5-0-0": {
            "name": "c-gigabitethernet5-0-0",
            "description": "c-gigabitethernet5-0-0",
            "linkUpSpeedMbps": 50,
            "linkDownSpeedMbps": 100,
            "connectionType": "internet_dia",
            "label": "internet_dia_4",
            "qosProfile": "gold25",
            "qosProfileType": "balanced",
            "diaEnabled": False,
            "lastResort": False,
            "patAddresses": {},
            "staticRoutes": {}
        }
    }
    
    # Define interfaces
    interfaces = {
        "GigabitEthernet5/0/0": {
            "interface": {
                "adminStatus": True,
                "maxTransmissionUnit": 1500,
                "circuit": "c-gigabitethernet5-0-0",
                "description": "wan_1",
                "alias": "primary_wan",
                "ipv4": {"dhcp": {"dhcpClient": True}},
                "ipv6": {"dhcp": {"dhcpClient": True}}
            }
        },
        "GigabitEthernet8/0/0": {
            "interface": {
                "subinterfaces": {
                    "18": {
                        "interface": {
                            "lan": "lan-7-test",
                            "vlan": 18,
                            "description": "lan-7",
                            "alias": "non_production",
                            "adminStatus": True,
                            "ipv4": {"address": {"address": "10.2.7.1/24"}},
                            "ipv6": {"address": {"address": "2001:10:2:7::1/64"}}
                        }
                    }
                }
            }
        }
    }
    
    # Create configuration request
    edge_config = graphiant_sdk.ManaV2EdgeDeviceConfig(
        circuits=circuits,
        interfaces=interfaces
    )
    
    config_request = graphiant_sdk.V1DevicesDeviceIdConfigPutRequest(
        edge=edge_config
    )
    
    try:
        # Verify device is ready
        verify_device_portal_status(api, bearer_token, device_id)
        
        # Push configuration
        response = api.v1_devices_device_id_config_put(
            authorization=bearer_token,
            device_id=device_id,
            v1_devices_device_id_config_put_request=config_request
        )
        
        print(f"Configuration job submitted. Job ID: {response.job_id}")
        return response
        
    except ForbiddenException as e:
        print(f"Permission denied: {e}")
    except Exception as e:
        print(f"Configuration failed: {e}")

Error Handling

def handle_api_errors(func):
    """Decorator for consistent error handling"""
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except BadRequestException as e:
            print(f"Bad Request: {e}")
        except UnauthorizedException as e:
            print(f"Unauthorized: {e}")
        except ForbiddenException as e:
            print(f"Forbidden: {e}")
        except NotFoundException as e:
            print(f"Not Found: {e}")
        except ServiceException as e:
            print(f"Service Error: {e}")
        except ApiException as e:
            print(f"API Error: {e}")
    return wrapper

@handle_api_errors
def get_device_info(api, bearer_token, device_id):
    """Get detailed device information"""
    return api.v1_devices_device_id_get(
        authorization=bearer_token,
        device_id=device_id
    )

🛠️ Development

Prerequisites

  • Python 3.9+ (3.12+ recommended)
  • Git
  • OpenAPI Generator (for code generation)

CI/CD Workflows

This repository uses GitHub Actions for continuous integration and deployment:

  • Linting (lint.yml): Runs Flake8 and MyPy type checking on pull requests and pushes
  • Testing (test.yml): Runs pytest with coverage across Python 3.9, 3.10, 3.11, 3.12, and 3.13
  • Building (build.yml): Builds wheel and source distributions
  • Releasing (release.yml): Publishes to PyPI (manual trigger, admin-only)

See .github/workflows/README.md for detailed workflow documentation.

Building from Source

# Clone repository
git clone git@github.com:Graphiant-Inc/graphiant-sdk-python.git
cd graphiant-sdk-python

# Create virtual environment
python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt

# Build distribution
python setup.py sdist bdist_wheel

# Install locally
pip install dist/*.tar.gz

Code Generation

To regenerate the SDK from the latest API specification:

# Install OpenAPI Generator
brew install openapi-generator  # macOS
# or download from: https://github.com/OpenAPITools/openapi-generator

# Generate SDK
openapi-generator generate \
    -i graphiant_api_docs_v26.1.1.json \
    -g python \
    --git-user-id Graphiant-Inc \
    --git-repo-id graphiant-sdk-python \
    --package-name graphiant_sdk \
    --additional-properties=packageVersion=26.1.1

Note: Latest API documentation can be downloaded from the Graphiant portal under "Support Hub" > "Developer Tools".

Testing

# Run tests
python -m pytest tests/

# Run with coverage
python -m pytest tests/ --cov=graphiant_sdk --cov-report=html

📖 API Reference

Core Classes

  • Configuration: Client configuration with authentication
  • ApiClient: HTTP client for API requests
  • DefaultApi: Main API interface with all endpoints

Key Models

  • V1AuthLoginPostRequest: Authentication request
  • V1AuthLoginPostResponse: Authentication response
  • V1EdgesSummaryGetResponse: Device summary response
  • V1DevicesDeviceIdConfigPutRequest: Device configuration request
  • V1DevicesDeviceIdConfigPutResponse: Device configuration response
  • V1GlobalSummaryPostResponse: Global summary response (uses ManaV2GlobalObjectSummary for inner items)

Common Endpoints

Endpoint Method Description
/v1/auth/login POST Authenticate and get bearer token
/v1/edges/summary GET Get all device summaries
/v1/devices/{device_id} GET Get device details
/v1/devices/{device_id}/config PUT Update device configuration
/v1/circuits GET List circuits
/v1/alarms GET Get system alarms

🔐 Security

  • Authentication: Bearer token-based authentication
  • HTTPS: All API communications use HTTPS
  • Credentials: Store credentials securely using environment variables
  • Token Management: Bearer tokens expire and should be refreshed as needed

Environment Variables

export GRAPHIANT_HOST="https://api.graphiant.com"
export GRAPHIANT_USERNAME="your_username"
export GRAPHIANT_PASSWORD="your_password"
import os

username = os.getenv("GRAPHIANT_USERNAME")
password = os.getenv("GRAPHIANT_PASSWORD")
host = os.getenv("GRAPHIANT_HOST", "https://api.graphiant.com")

Note: For detailed security policies, vulnerability reporting, and security best practices, see SECURITY.md.

🤝 Contributing

We welcome contributions! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes and ensure they pass local tests:
    # Run linting
    flake8 graphiant_sdk/
    mypy graphiant_sdk/
    
    # Run tests
    pytest --cov=graphiant_sdk
    
  4. Commit your changes with a clear message (git commit -m 'Add amazing feature')
  5. Push to the branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

Note: All pull requests automatically run CI/CD checks (linting, testing across multiple Python versions). Ensure all checks pass before requesting review.

See CONTRIBUTING.md for detailed contribution guidelines.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🆘 Support

🔗 Related Projects


Made with ❤️ by the Graphiant Team

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graphiant_sdk-26.1.1.tar.gz (935.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

graphiant_sdk-26.1.1-py3-none-any.whl (4.1 MB view details)

Uploaded Python 3

File details

Details for the file graphiant_sdk-26.1.1.tar.gz.

File metadata

  • Download URL: graphiant_sdk-26.1.1.tar.gz
  • Upload date:
  • Size: 935.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for graphiant_sdk-26.1.1.tar.gz
Algorithm Hash digest
SHA256 34c49884eac33510b6d1c6ef4744d4f0595053cefc9e05c8bc8a50717cfee9ee
MD5 508773f844a749385f2e78c364d69f0c
BLAKE2b-256 0ad36583b841e9a39f59a3ff7630391da4c7d242da5e1e2fb5d409336db08349

See more details on using hashes here.

File details

Details for the file graphiant_sdk-26.1.1-py3-none-any.whl.

File metadata

  • Download URL: graphiant_sdk-26.1.1-py3-none-any.whl
  • Upload date:
  • Size: 4.1 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for graphiant_sdk-26.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6d5215ee738257991cf6edb7aa03f27478f450743177b41c7e6ad7dd13e71938
MD5 6144fee8ec0311fc4f9201eb4d037b4f
BLAKE2b-256 f0c093ed344722cfd2cd99ac9ad23f5c55206cb3efacf32ac112297c36ad4fe9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page