kestra-io / kestra-io/plugin-ovhcloud

[plugin-ovhcloud] Compute — Public Cloud instances, bare metal servers, and Managed Kubernetes

Open
#3 0 comments 0 reactions 0 assignees View on GitHub
area/plugin
Dominant language
Java
Stars
0
Forks
0
Avg merge
18h 6m
Merged PRs (30d)
1

Description

## Summary

Implement the `compute` sub-plugin for `plugin-ovhcloud`, giving Kestra users full lifecycle control over OVHcloud Compute resources: Public Cloud virtual instances (via the Nova-compatible OVH API), bare metal dedicated servers, and Managed Kubernetes (OVH MKS) clusters and node pools. Teams can use this plugin to spin up instances for batch workloads, provision Kubernetes clusters for ML pipelines, or automate bare metal server reinstalls as part of infrastructure flows.

## Motivation

Platform and infrastructure teams running on OVHcloud today rely on shell scripts or custom Python tasks to manage compute resources. A native Kestra plugin eliminates the glue code, brings retry/error handling, and makes compute provisioning a first-class step in data and platform pipelines. Kubernetes cluster management in particular complements Kestra's existing task-runner integrations.

## Context

Part of the OVHcloud plugin EPIC: https://github.com/kestra-io/plugin-ovhcloud/issues/2.
Reference implementation: `plugin-gcp` (GCE instances + GKE clusters) for task structure and connection patterns. The OVH API uses a 3-key HMAC signature; a shared `OvhConnection` abstract base class should be implemented once (see EPIC) and reused here.

## API Reference

- **Official docs**: https://eu.api.ovh.com/console/?section=%2Fcloud&branch=v1 (Public Cloud + Kubernetes) · https://eu.api.ovh.com/console/?section=%2Fdedicated%2Fserver&branch=v1 (Bare metal)
- **Authentication**: OVH 3-key HMAC — `X-Ovh-Application`, `X-Ovh-Consumer`, `X-Ovh-Timestamp`, `X-Ovh-Signature` headers. OAuth2 service-account bearer token also supported via `https://www.ovh.com/auth/oauth2/token`.
- **Base URL pattern**: `https://eu.api.ovh.com/1.0/` (EU) · `https://ca.api.ovh.com/1.0/` (CA) · `https://api.us.ovhcloud.com/1.0/` (US)
- **SDK / client library**: `net.minidev:ovh-java-sdk-core:1.0.17` (HMAC signing) + `net.minidev:ovh-java-sdk-cloud:1.0.17` (typed models for Public Cloud)

## Gradle Dependencies

Add to `build.gradle`:

```groovy
// OVH management plane — HMAC signing and typed Public Cloud models
implementation 'net.minidev:ovh-java-sdk-core:1.0.17'
implementation 'net.minidev:ovh-java-sdk-cloud:1.0.17'

// OpenStack4j for Nova data-plane (optional — can use OVH REST directly)
implementation 'org.openstack4j:openstack4j-core:3.11'
implementation 'org.openstack4j:openstack4j-httpclient:3.11'
```

> Use the latest stable version available on Maven Central.

## Plugin Structure

- **Repository**: `plugin-ovhcloud`
- **Namespace**: `io.kestra.plugin.ovhcloud`
- **Sub-plugins**: `compute.instance`, `compute.kube`, `compute.baremetal`

## Suggested Tasks

1. Implement `OvhConnection` abstract base class (shared with all other sub-plugins)
2. **`compute.instance`** — `List`, `Get`, `Create`, `Delete`; `Reboot` action
3. **`compute.instance`** — query available `Flavor` and `Image` catalogs
4. **`compute.kube`** — `ListClusters`, `CreateCluster`, `DeleteCluster`; `AddNode`, `RemoveNode`
5. **`compute.baremetal`** — `List`, `Get`, `Reboot`, `Reinstall`; poll task status
6. Add polling trigger `compute.instance.InstanceStateTrigger` (watches for instance state changes)
7. Write unit + integration tests
8. Add `package-info.java` with `@PluginSubGroup(category = PluginSubGroup.PluginCategory.CLOUD)`
9. Add `metadata/index.yaml` and plugin icon SVG
10. Add YAML examples and plugin documentation

## YAML Examples

### Example 1 — Create a Public Cloud instance and wait for it to be active

```yaml
id: provision_ovhcloud_instance
namespace: company.team

inputs:
- id: project_id
type: STRING
- id: region
type: STRING
defaults: GRA11

tasks:
- id: create_instance
type: io.kestra.plugin.ovhcloud.compute.instance.Create
endpoint: "{{ secret('OVH_ENDPOINT') }}"
applicationKey: "{{ secret('OVH_APP_KEY') }}"
applicationSecret: "{{ secret('OVH_APP_SECRET') }}"
consumerKey: "{{ secret('OVH_CONSUMER_KEY') }}"
projectId: "{{ inputs.project_id }}"
region: "{{ inputs.region }}"
flavorId: "b2-7"
imageId: "{{ secret('UBUNTU_24_IMAGE_ID') }}"
name: "kestra-batch-worker"
sshKeyId: "{{ secret('SSH_KEY_ID') }}"

- id: log_instance
type: io.kestra.plugin.core.log.Log
message: "Instance {{ outputs.create_instance.instanceId }} is {{ outputs.create_instance.status }}"
```

### Example 2 — Create a Managed Kubernetes cluster and add a node pool

```yaml
id: provision_k8s_cluster
namespace: company.team

inputs:
- id: project_id
type: STRING

tasks:
- id: create_cluster
type: io.kestra.plugin.ovhcloud.compute.kube.CreateCluster
endpoint: "{{ secret('OVH_ENDPOINT') }}"
applicationKey: "{{ secret('OVH_APP_KEY') }}"
applicationSecret: "{{ secret('OVH_APP_SECRET') }}"
consumerKey: "{{ secret('OVH_CONSUMER_KEY') }}"
projectId: "{{ inputs.project_id }}"
region: "GRA"
version: "1.30"
name: "kestra-ml-cluster"

- id: add_node_pool
type: io.kestra.plugin.ovhcloud.compute.kube.AddNode
endpoint: "{{ secret('OVH_ENDPOINT') }}"
applicationKey: "{{ secret('OVH_APP_KEY') }}"
applicationSecret: "{{ secret('OVH_APP_SECRET') }}"
consumerKey: "{{ secret('OVH_CONSUMER_KEY') }}"
projectId: "{{ inputs.project_id }}"
clusterId: "{{ outputs.create_cluster.clusterId }}"
flavorName: "b2-15"
desiredNodes: 3
```

### Example 3 — React when an instance changes state (e.g. goes ACTIVE)

```yaml
id: on_instance_active
namespace: company.team

triggers:
- id: watch_instance_state
type: io.kestra.plugin.ovhcloud.compute.instance.InstanceStateTrigger
endpoint: "{{ secret('OVH_ENDPOINT') }}"
applicationKey: "{{ secret('OVH_APP_KEY') }}"
applicationSecret: "{{ secret('OVH_APP_SECRET') }}"
consumerKey: "{{ secret('OVH_CONSUMER_KEY') }}"
projectId: "{{ secret('OVH_PROJECT_ID') }}"
instanceId: "{{ secret('INSTANCE_ID') }}"
targetStatus: ACTIVE
interval: PT30S

tasks:
- id: notify
type: io.kestra.plugin.core.log.Log
message: "Instance {{ trigger.instanceId }} is now {{ trigger.status }}"
```

## Acceptance Criteria

- [ ] `OvhConnection` abstract base class with HMAC + OAuth2 support implemented
- [ ] CRUD tasks for Public Cloud instances (`List`, `Get`, `Create`, `Delete`, `Reboot`)
- [ ] Flavor and Image catalog query tasks
- [ ] CRUD tasks for Managed Kubernetes clusters and node management
- [ ] Bare metal `List`, `Get`, `Reboot`, `Reinstall` tasks with task-status polling
- [ ] At least one polling trigger (`InstanceStateTrigger`)
- [ ] All `Property` fields support Kestra expression language
- [ ] Unit + integration tests pass (`./gradlew test`)
- [ ] `package-info.java` with `@PluginSubGroup`
- [ ] `metadata/index.yaml` and plugin icon SVG present
- [ ] Build passes with `./gradlew build`

---

## Repository Setup Checklist

### 1. Scaffold the repository

Create the repository using the Kestra plugin scaffold tool:
https://github.com/kestra-io/plugins-devtools#kestra-plugin-scaffold

### 2. Add to Sanity check page

Add this plugin to the [Sanity check Notion page](https://www.notion.so/kestra-io/32736907f7b580cbb00dc7c061e624b1?v=32736907f7b58002ac2b000ccc63d8a2).

### 3. Run scoped Terraform apply

Run the following from `infra/terraform/github`:

```bash
terraform apply \
-target='github_repository.repo["plugin-ovhcloud"]' \
-target='github_issue_labels.plugins["plugin-ovhcloud"]' \
-target='github_repository_ruleset.branch["plugin-ovhcloud"]'
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the plugin scaffold and compare the reference plugin-gcp structure, then review build.gradle and the shared OvhConnection design described in the issue. The work spans compute.instance, compute.kube, compute.baremetal, package-info.java, metadata/index.yaml, documentation, and tests. Done means all listed tasks, authentication paths, polling, metadata, examples, and acceptance checks pass with ./gradlew test and ./gradlew build.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
cloud
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.