kestra-io / kestra-io/plugin-scaleway
Add Kubernetes Kapsule tasks for Scaleway Plugin
- Dominant language
- Java
- Stars
- 0
- Forks
- 0
- Avg merge
- 7h 18m
- Merged PRs (30d)
- 2
Description
## Summary
[Scaleway Kubernetes Kapsule](https://www.scaleway.com/en/kubernetes-kapsule/) is Scaleway's managed Kubernetes offering. This sub-plugin lets Kestra flows provision, scale, and tear down Kapsule clusters and node pools directly from a flow, and retrieve the kubeconfig needed to hand off to downstream Kubernetes-native tasks.
## Motivation
Teams running Kapsule today either click through the Scaleway console or script around the CLI/Terraform to manage cluster lifecycle. Wiring cluster provisioning into a Kestra flow lets platform teams:
- Spin up ephemeral Kapsule clusters as part of a CI/CD or data-pipeline flow, then tear them down when done
- Scale node pools up/down on a schedule or in response to load signals
- Pull a fresh kubeconfig into internal storage for downstream `kubectl`/Helm tasks in the same flow
This complements the EPIC's other compute-adjacent sub-plugins (`instance`, `containers`, `functions`) by covering Scaleway's managed-Kubernetes surface.
## Context
Part of the Scaleway plugin EPIC: https://github.com/kestra-io/plugin-scaleway/issues/2. Uses the shared `AbstractScalewayConnection` base class defined in that EPIC for credentials and client construction.
## API Reference
- **Official docs**: https://www.scaleway.com/en/developers/api/kubernetes/
- **Authentication**: `X-Auth-Token: ` — same IAM API key pattern as the rest of the plugin (see EPIC).
- **Base URL pattern**: regional — `https://api.scaleway.com/k8s/v1/regions/{region}/` (`fr-par`, `nl-ams`, `pl-waw`)
- **SDK / client library**: none official for Java. Scaleway ships only Go, Python, and JS/TS SDKs plus Terraform (https://www.scaleway.com/en/docs/scaleway-sdk/) — use Kestra's internal HTTP client.
## Gradle Dependencies
None required. Kestra's internal HTTP client (`io.kestra.core.http.client`) and Jackson serializers are already provided by the framework — no new dependency needed for this REST-based API.
## Plugin Structure
- **Repository**: `plugin-scaleway` (existing)
- **Namespace**: `io.kestra.plugin.scaleway.kubernetes`
- **Sub-plugins**: none — flat sub-package
- **Categories**: CLOUD
> **Task class naming**: task class names must not repeat the plugin or package name. Use `Create`, `Get`, `List`, `Delete` for clusters; `CreatePool`, `ResizePool`, `DeletePool` for node pools; `GetKubeconfig` for kubeconfig retrieval.
## Suggested Tasks
1. Extend `AbstractScalewayConnection` for cluster/pool tasks
2. `Create` — create a Kapsule cluster (`POST /clusters`)
3. `Get` / `List` — fetch or list clusters (`GET /clusters/{id}`, `GET /clusters`)
4. `Delete` — delete a cluster (`DELETE /clusters/{id}`)
5. `CreatePool` / `ResizePool` / `DeletePool` — manage node pools (`POST|PATCH|DELETE /clusters/{id}/pools[/{pool_id}]`)
6. `GetKubeconfig` — retrieve kubeconfig (`GET /clusters/{id}/kubeconfig`), stored via `FetchType.STORE` to internal storage
7. Polling trigger on cluster status (e.g. wait for `ready`, `pool_required`, `deleting`, error states)
8. Write unit + integration tests
9. Add `package-info.java` with `@PluginSubGroup(category = PluginSubGroup.PluginCategory.CLOUD)`
10. Add `metadata/kubernetes.yaml` and plugin icon SVG
11. Add YAML examples and plugin documentation
## YAML Examples
### Example 1 — Create a Kapsule cluster
```yaml
id: create_kapsule_cluster
namespace: company.team
inputs:
- id: cluster_name
type: STRING
tasks:
- id: create_cluster
type: io.kestra.plugin.scaleway.kubernetes.Create
secretKey: "{{ secret('SCW_SECRET_KEY') }}"
region: "fr-par"
name: "{{ inputs.cluster_name }}"
version: "1.31"
```
### Example 2 — List clusters and log node pool counts
```yaml
id: list_kapsule_clusters
namespace: company.team
tasks:
- id: list_clusters
type: io.kestra.plugin.scaleway.kubernetes.List
secretKey: "{{ secret('SCW_SECRET_KEY') }}"
region: "fr-par"
- id: log_results
type: io.kestra.plugin.core.log.Log
message: "Found {{ outputs.list_clusters.total }} Kapsule clusters"
```
### Example 3 — Wait for cluster readiness after creation
```yaml
id: wait_for_kapsule_ready
namespace: company.team
triggers:
- id: on_cluster_ready
type: io.kestra.plugin.scaleway.kubernetes.Trigger
secretKey: "{{ secret('SCW_SECRET_KEY') }}"
region: "fr-par"
clusterId: "{{ vars.cluster_id }}"
interval: PT30S
tasks:
- id: handle_ready
type: io.kestra.plugin.core.log.Log
message: "Cluster status: {{ trigger.status }}"
```
## Acceptance Criteria
### Functional
- [ ] Cluster CRUD tasks (`Create`, `Get`, `List`, `Delete`) extending `AbstractScalewayConnection`
- [ ] Node pool tasks (`CreatePool`, `ResizePool`, `DeletePool`)
- [ ] `GetKubeconfig` task storing the kubeconfig via `FetchType.STORE`
- [ ] Polling trigger on cluster status
- [ ] Unit + integration tests pass (`./gradlew test`)
- [ ] Build passes with `./gradlew build`
### Kestra Plugin Coding Standards
- [ ] HTTP calls use Kestra's internal HTTP client (`io.kestra.core.http.client`) — no OkHttp, Apache HttpClient, or similar
- [ ] All new properties use `Property`
- [ ] `secretKey` annotated with `@PluginProperty(secret = true)`
- [ ] Every property and output has a `@Schema` annotation
- [ ] Task classes carry the five mandatory Lombok annotations (`@SuperBuilder`, `@ToString`, `@EqualsAndHashCode`, `@Getter`, `@NoArgsConstructor`)
- [ ] Logging via `runContext.logger()` only
- [ ] JSON serialization uses Jackson mappers from `io.kestra.core.serializers`
### Documentation & Structure
- [ ] `@Plugin(examples = ...)` entries each set `full = true` with a complete runnable flow
- [ ] Sensitive values in examples use `{{ secret('SCW_SECRET_KEY') }}`
- [ ] `package-info.java` with `@PluginSubGroup(category = PluginSubGroup.PluginCategory.CLOUD)`
- [ ] `metadata/kubernetes.yaml` and plugin icon SVG present
---
*[View as Artifact](https://claude.ai/code/artifact/ff57cf0f-a378-4f9d-9ef5-92281e924861)*
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.