Skip to content

WIP - Feature/v2 initial modules rest client #11

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 26 commits into from
Mar 17, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b0381d9
move existing example into v1 folder and introducing v2 for the new i…
iButcat Mar 9, 2025
352d2ea
follow go structure with pkg, adding payloads, config, services with …
iButcat Mar 9, 2025
05f6c85
introduce testing & uuid.
iButcat Mar 9, 2025
beea62c
add internal for shared component across version that are not necessa…
iButcat Mar 9, 2025
e5c7ab8
add v2 with generic client and xo client for the rest api.
iButcat Mar 9, 2025
d41d2c1
add go-version when using goenv.
iButcat Mar 9, 2025
abd9216
remove go.mod & go.sum, we can compile and run from the root director…
iButcat Mar 11, 2025
71d3f0a
remove value of fallback and instead return an error when the necessa…
iButcat Mar 11, 2025
81e848e
config returns an error if the necessary env aren't available.
iButcat Mar 11, 2025
dfd7c0e
docs for the v2 including example about how to add new service logic,…
iButcat Mar 11, 2025
7814ab3
Remove docs and add them in docs directory instead.
iButcat Mar 11, 2025
49edad2
remove comments and add them in docs instead.
iButcat Mar 11, 2025
7867df9
Add more context for the project, also add the docs directory, how to…
iButcat Mar 11, 2025
e26aa04
fix tests for new added method. Comments out Create, fix later since …
iButcat Mar 11, 2025
c7e3a6f
Add makefile tests, run examples and other good to have for generatin…
iButcat Mar 11, 2025
fb8a842
Add package for go env var, easier for development purpose since it l…
iButcat Mar 11, 2025
48240fb
add path builder instead of concatenate. Can be used in service to bu…
iButcat Mar 11, 2025
44f5164
Add const for rest v0 path and import it in client.
iButcat Mar 11, 2025
361dafc
uses the new path builder.
iButcat Mar 11, 2025
84139e4
fix bad markdown formatting.
iButcat Mar 11, 2025
9d7e3ea
Fix documentation from Cyrille suggestion.
iButcat Mar 15, 2025
a7a091e
upgrade go version following the upgrade of the go.mod to fix the lin…
iButcat Mar 15, 2025
d6d6fcf
fix linter and docs.
iButcat Mar 15, 2025
e923222
tidy to add the dependency in direct instead of undirect.
iButcat Mar 17, 2025
5112df8
fix linter issue, also remove hardcoded vm name in the task polling, …
iButcat Mar 17, 2025
6998431
fix 404 version not found for pipeline.
iButcat Mar 17, 2025
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
24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
# <p align="center">Golang client for XenOrchestra API</p>

This is a Golang module for the [XenOrchestra](https://github.com/vatesfr/xen-orchestra) JSON-RPC API.
This is a Golang module for the [XenOrchestra](https://github.com/vatesfr/xen-orchestra) API. It provides two client implementations:

It is used in the [terraform-provider-xenorchestra](https://github.com/vatesfr/terraform-provider-xenorchestra) Terraform provider.
- **v1**: Uses the JSON-RPC API (legacy)
- **v2**: Uses the REST API (WIP, should be used in parallel with v1 for missing endpoints, until v2 is fully released)

## 📚 Documentation

TODO
### v1 Documentation

The v1 client uses the JSON-RPC API and is primarily used in the [terraform-provider-xenorchestra](https://github.com/vatesfr/terraform-provider-xenorchestra) Terraform provider.

### v2 Documentation

The v2 client uses the REST API and provides a more modern, type-safe interface. Comprehensive documentation is available in the `docs/v2` directory:

- [Overview](docs/v2/01-overview.md) - Introduction and key features
- [Architecture](docs/v2/02-architecture.md) - Design patterns and components
- [Migration Guide](docs/v2/03-migration-guide.md) - How to migrate from v1 to v2
- [Service Implementation Guide](docs/v2/04-service-implementation.md) - How to add new services

## 🧑🏻‍💻 Usage

```shell
go get github.com/vatesfr/xenorchestra-go-sdk
```

See [examples](https://github.com/vatesfr/xenorchestra-go-sdk/tree/main/examples).
### Examples

The SDK includes examples for both v1 and v2 clients:

- [v1 Examples](examples/v1) - Examples using the JSON-RPC API
- [v2 Examples](examples/v2) - Examples using the REST API

## 🍰 Contributing

Expand Down
85 changes: 85 additions & 0 deletions docs/v2/01-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Xen Orchestra Go SDK v2

## Overview

The Xen Orchestra Go SDK v2 provides a modern, type-safe interface to interact with the Xen Orchestra API. This version moves from the JSON-RPC API used in v1 to a REST API implementation, offering significant improvements in usability, maintainability, and type safety.

## Key Features

- **REST API Support**: Uses Xen Orchestra's modern REST API
- **Type Safety**: Leverages Go generics for type-safe API interactions
- **Method Chaining**: Improved API ergonomics with `client.VM().Create()` pattern
- **Context Support**: All operations support context for better timeout and cancellation handling
- **UUID Support**: Native UUID type support instead of string IDs
- **Structured Logging**: Built-in logging with configurable verbosity levels
- **Interface-Based Design**: Clean interfaces for better testability and mocking
- **Go Mocking**: Mocking is supported for all interfaces by adding the `//go:generate mockgen` tag in the interface file

## Installation

```bash
go get github.com/vatesfr/xenorchestra-go-sdk/v2
```

## Quick Start

```go
package main

import (
"context"
"fmt"
"time"

"github.com/vatesfr/xenorchestra-go-sdk/pkg/config"
v2 "github.com/vatesfr/xenorchestra-go-sdk/v2"
)

func main() {
// Create a context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()

// Initialize configuration
cfg, err := config.New()
if err != nil {
panic(err)
}

// Create client
client, err := v2.New(cfg)
if err != nil {
panic(err)
}

// List all VMs
vms, err := client.VM().List(ctx)
if err != nil {
panic(err)
}

// Display VMs
fmt.Printf("Found %d VMs\n", len(vms))
for i, vm := range vms {
fmt.Printf("%d. %s (ID: %s, Power: %s)\n", i+1, vm.NameLabel, vm.ID, vm.PowerState)
}
}
```

## Environment Variables

The SDK uses the following environment variables for configuration:

- `XOA_URL`: URL of the Xen Orchestra server
- `XOA_USER`: Username for authentication
- `XOA_PASSWORD`: Password for authentication
- `XOA_INSECURE`: Set to "true" to skip TLS certificate verification
- `XOA_DEVELOPMENT`: Set to "true" to enable development mode with additional logging
- `XOA_RETRY_MODE`: Retry strategy ("none" or "backoff")
- `XOA_RETRY_MAX_TIME`: Maximum time to wait between retries (default: 5 minutes)

## Next Steps

- [Architecture Guide](02-architecture.md) - Learn about the design patterns used in the SDK
- [Migration Guide](03-migration-guide.md) - Migrate from v1 to v2
- [Service Implementation Guide](04-service-implementation.md) - Learn how to add new services
213 changes: 213 additions & 0 deletions docs/v2/02-architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# Architecture Guide

The v2 SDK uses a clean, interface-based architecture that makes it easy to use, test, and extend. This document explains the key architectural components.

## Component Overview


The SDK consists of these main components:

```
v2/
├── client/ # HTTP client implementation
├── xo.go # Main client entry point
pkg/
├── config/ # Configuration handling
├── payloads/ # API data structures
├── services/ # Service implementations
├── library/ # Service interfaces
├── vm/ # VM service implementation
└── ... # Other service implementations
internal/
└── common/ # Shared utilities
├── core/ # Core types and constants
└── logger/ # Logging implementation
```


## Key Design Patterns

### Interface-Based Design

The SDK uses interfaces to define service contracts in the `library` package. These interfaces define the operations available for each resource type.

Example from `library/vm.go`:

```go
type VM interface {
GetByID(ctx context.Context, id uuid.UUID) (*payloads.VM, error)
List(ctx context.Context) ([]*payloads.VM, error)
Create(ctx context.Context, vm *payloads.VM) (*payloads.VM, error)
// ... other methods
}
```

This approach allows for:
- Clear API documentation
- Easy mocking for tests
- Swappable implementations

### Service Registry Pattern

The `XOClient` struct acts as a registry for service implementations, providing a coherent API for accessing different services:

```go
// In v2/xo.go
type XOClient struct {
vmService library.VM
// other services will be added here
}

func (c *XOClient) VM() library.VM {
return c.vmService
}
```

This allows for method chaining like `client.VM().Create(...)`.

### Generic HTTP Methods

The client package uses Go generics to provide type-safe HTTP methods:

```go
// In client/client.go
func TypedGet[P any, R any](ctx context.Context, c *Client, endpoint string, params P, result *R) error {
// implementation
}
```

This makes service implementations cleaner and more type-safe.

### Payload Structs

API data structures are defined in the `payloads` package, separate from service logic:

```go
// In pkg/payloads/vm.go
type VM struct {
ID uuid.UUID `json:"id,omitempty"`
NameLabel string `json:"name_label"`
NameDescription string `json:"name_description"`
// ... other fields
}
```

## Client Initialization Flow

1. Configuration is loaded from environment variables or provided directly
2. The HTTP client is created with the appropriate authentication
3. Service implementations are initialized
4. The main client registers all services
5. The client is ready to use

## Async Operations

Some API operations (like VM creation) are asynchronous. The SDK handles this by:

1. Making the initial request that returns a task URL
2. Polling the task status until completion
3. Retrieving the final result when the task succeeds

This is encapsulated in service methods for a clean API.

## Error Handling

Errors are propagated from the HTTP client to the service methods and finally to the caller. Detailed error information is available to help diagnose issues.

## Logging

The SDK uses a structured logger based on zap for efficient and informative logging. Log levels are automatically adjusted based on whether the SDK is in development or production mode.


## Key Design Patterns

### Interface-Based Design

The SDK uses interfaces to define service contracts in the `library` package. These interfaces define the operations available for each resource type.

Example from `library/vm.go`:

```go
type VM interface {
GetByID(ctx context.Context, id uuid.UUID) (*payloads.VM, error)
List(ctx context.Context) ([]*payloads.VM, error)
Create(ctx context.Context, vm *payloads.VM) (*payloads.VM, error)
// ... other methods
}
```

This approach allows for:
- Clear API documentation
- Easy mocking for tests
- Swappable implementations

### Service Registry Pattern

The `XOClient` struct acts as a registry for service implementations, providing a coherent API for accessing different services:

```go
// In v2/xo.go
type XOClient struct {
vmService library.VM
// other services will be added here
}

func (c *XOClient) VM() library.VM {
return c.vmService
}
```

This allows for method chaining like `client.VM().Create(...)`.

### Generic HTTP Methods

The client package uses Go generics to provide type-safe HTTP methods:

```go
// In client/client.go
func TypedGet[P any, R any](ctx context.Context, c *Client, endpoint string, params P, result *R) error {
// implementation
}
```

This makes service implementations cleaner and more type-safe.

### Payload Structs

API data structures are defined in the `payloads` package, separate from service logic:

```go
// In pkg/payloads/vm.go
type VM struct {
ID uuid.UUID `json:"id,omitempty"`
NameLabel string `json:"name_label"`
NameDescription string `json:"name_description"`
// ... other fields
}
```

## Client Initialization Flow

1. Configuration is loaded from environment variables or provided directly
2. The HTTP client is created with the appropriate authentication
3. Service implementations are initialized
4. The main client registers all services
5. The client is ready to use

## Async Operations

Some API operations (like VM creation) are asynchronous. The SDK handles this by:

1. Making the initial request that returns a task URL
2. Polling the task status until completion
3. Retrieving the final result when the task succeeds

This is encapsulated in service methods for a clean API.

## Error Handling

Errors are propagated from the HTTP client to the service methods and finally to the caller. Detailed error information is available to help diagnose issues.

## Logging

The SDK uses a structured logger based on zap for efficient and informative logging. Log levels are automatically adjusted based on whether the SDK is in development or production mode.
Loading
Loading