kestra-io / kestra-io/plugin-oci

[Plugin] OCI — Compute (Instances & Instance Pools)

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

Description

## Summary

The OCI Compute sub-plugin for `plugin-oci` enables Kestra flows to manage Oracle Cloud VM instances and instance pools — launching, starting, stopping, and terminating compute resources without leaving the workflow. This covers the most fundamental OCI automation need: elastic compute lifecycle management driven by orchestration logic.

## Motivation

Platform and DevOps teams currently manage OCI compute through shell scripts wrapping the OCI CLI or custom Python tasks using the OCI SDK. Without a native Kestra plugin, these teams cannot express conditional scaling logic, fan-out instance creation, or cleanup steps as typed, testable flow tasks. A Compute sub-plugin closes that gap and makes OCI a first-class citizen alongside AWS EC2 and GCP Compute Engine.

## Context

Part of the OCI Plugin Suite EPIC: https://github.com/kestra-io/plugin-oci/issues/2
Reference implementation to model after: `plugin-aws` Compute tasks (EC2 start/stop/run).

## API Reference

- **Official docs**: https://docs.oracle.com/en-us/iaas/api/#/en/iaas/latest/Instance
- **Authentication**: Config-file (`~/.oci/config`), instance principal, or `SimpleAuthenticationDetailsProvider` (env-var / secrets-driven)
- **Base URL pattern**: `https://iaas.{region}.oraclecloud.com/20160918/`
- **SDK**: OCI Java SDK v3.87.0 via BOM

## Gradle Dependencies

Add to `build.gradle`:

```groovy
// OCI Java SDK BOM
implementation platform("com.oracle.oci.sdk:oci-java-sdk-bom:3.87.0")
// Compute + Block Storage (shared core module)
implementation "com.oracle.oci.sdk:oci-java-sdk-core"
implementation "com.oracle.oci.sdk:oci-java-sdk-common"
```

> Use the latest stable version available on Maven Central.

## Plugin Structure

- **Repository**: `plugin-oci`
- **Namespace**: `io.kestra.plugin.oci.compute`
- **Sub-plugins**: `compute` (instances, instance pools)

## Suggested Tasks

1. Implement shared `OciConnection` abstract base class (region, auth provider, tenancy OCID)
2. `LaunchInstance` — create a new VM instance from shape + image
3. `TerminateInstance` — terminate an instance by OCID
4. `StartInstance` — start a stopped instance
5. `StopInstance` — gracefully stop a running instance
6. `RebootInstance` — reboot a running instance
7. `GetInstance` — fetch instance details and emit as output
8. `ListInstances` — list instances in a compartment with optional filters
9. `CreateInstancePool` — create an instance pool from an instance configuration
10. Add `InstanceStateChangeTrigger` — poll until instance reaches a target lifecycle state
11. Write unit + integration tests
12. Add `package-info.java` with `@PluginSubGroup(category = PluginSubGroup.PluginCategory.CLOUD)`

## YAML Examples

### Example 1 — Launch a VM and wait for it to reach RUNNING state

```yaml
id: launch_oci_instance
namespace: company.platform

inputs:
- id: compartment_ocid
type: STRING
- id: image_ocid
type: STRING

tasks:
- id: launch
type: io.kestra.plugin.oci.compute.LaunchInstance
region: eu-frankfurt-1
tenancyOcid: "{{ secret('OCI_TENANCY_OCID') }}"
userId: "{{ secret('OCI_USER_OCID') }}"
fingerprint: "{{ secret('OCI_FINGERPRINT') }}"
privateKey: "{{ secret('OCI_PRIVATE_KEY') }}"
compartmentId: "{{ inputs.compartment_ocid }}"
availabilityDomain: AD-1
shape: VM.Standard.E4.Flex
imageId: "{{ inputs.image_ocid }}"
displayName: kestra-worker-{{ execution.id }}

- id: log_instance
type: io.kestra.plugin.core.log.Log
message: "Instance launched: {{ outputs.launch.instanceId }} — state: {{ outputs.launch.lifecycleState }}"
```

### Example 2 — Stop and terminate a list of instances

```yaml
id: cleanup_oci_instances
namespace: company.platform

tasks:
- id: list_instances
type: io.kestra.plugin.oci.compute.ListInstances
region: eu-frankfurt-1
tenancyOcid: "{{ secret('OCI_TENANCY_OCID') }}"
userId: "{{ secret('OCI_USER_OCID') }}"
fingerprint: "{{ secret('OCI_FINGERPRINT') }}"
privateKey: "{{ secret('OCI_PRIVATE_KEY') }}"
compartmentId: "{{ secret('OCI_COMPARTMENT_OCID') }}"
lifecycleState: RUNNING
displayNameFilter: kestra-worker-

- id: terminate_each
type: io.kestra.plugin.core.flow.ForEach
values: "{{ outputs.list_instances.instances }}"
tasks:
- id: terminate
type: io.kestra.plugin.oci.compute.TerminateInstance
region: eu-frankfurt-1
tenancyOcid: "{{ secret('OCI_TENANCY_OCID') }}"
userId: "{{ secret('OCI_USER_OCID') }}"
fingerprint: "{{ secret('OCI_FINGERPRINT') }}"
privateKey: "{{ secret('OCI_PRIVATE_KEY') }}"
instanceId: "{{ taskrun.value.id }}"
```

### Example 3 — Trigger a flow when an instance changes lifecycle state

```yaml
id: on_instance_state_change
namespace: company.platform

triggers:
- id: instance_state_watcher
type: io.kestra.plugin.oci.compute.InstanceStateChangeTrigger
region: eu-frankfurt-1
tenancyOcid: "{{ secret('OCI_TENANCY_OCID') }}"
userId: "{{ secret('OCI_USER_OCID') }}"
fingerprint: "{{ secret('OCI_FINGERPRINT') }}"
privateKey: "{{ secret('OCI_PRIVATE_KEY') }}"
compartmentId: "{{ secret('OCI_COMPARTMENT_OCID') }}"
targetLifecycleState: STOPPED
interval: PT2M

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

## Acceptance Criteria

- [ ] Shared `OciConnection` abstract base class with all auth fields and `AuthenticationDetailsProvider` builder
- [ ] `LaunchInstance`, `TerminateInstance`, `StartInstance`, `StopInstance`, `RebootInstance`, `GetInstance`, `ListInstances` tasks implemented
- [ ] `CreateInstancePool` task implemented
- [ ] `InstanceStateChangeTrigger` polling trigger implemented
- [ ] All `Property` fields support Kestra expression language (template rendering)
- [ ] Unit + integration tests pass (`./gradlew test`)
- [ ] `package-info.java` with `@PluginSubGroup(category = PluginSubGroup.PluginCategory.CLOUD)`
- [ ] Build passes with `./gradlew build`

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with build.gradle and the plugin-aws Compute tasks referenced as the model. Review the OCI Java SDK dependency setup and the listed task and trigger requirements, then run ./gradlew test and ./gradlew build. Done means the specified compute tasks, instance pool task, polling trigger, expression support, tests, and package-info.java are implemented and the build passes.

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
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.