diff --git a/src/main/java/io/kestra/plugin/kubernetes/AbstractConnection.java b/src/main/java/io/kestra/plugin/kubernetes/AbstractConnection.java index a7650a0..b915b47 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/AbstractConnection.java +++ b/src/main/java/io/kestra/plugin/kubernetes/AbstractConnection.java @@ -14,6 +14,7 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.experimental.SuperBuilder; +import io.kestra.core.models.annotations.PluginProperty; @SuperBuilder @ToString @@ -25,6 +26,7 @@ public abstract class AbstractConnection extends Task { title = "Kubernetes connection", description = "Connection settings for the cluster. If omitted, the client resolves credentials in order: system properties, environment variables, kubeconfig, then in-cluster service account." ) + @PluginProperty(group = "advanced") private Connection connection; @Schema( @@ -33,6 +35,7 @@ public abstract class AbstractConnection extends Task { ) @NotNull @Builder.Default + @PluginProperty(group = "main") protected final Property waitUntilRunning = Property.ofValue(Duration.ofMinutes(10)); @Schema( @@ -41,6 +44,7 @@ public abstract class AbstractConnection extends Task { ) @NotNull @Builder.Default + @PluginProperty(group = "main") protected final Property waitRunning = Property.ofValue(Duration.ofHours(1)); protected ListOptions listOptions(RunContext runContext) throws IllegalVariableEvaluationException { diff --git a/src/main/java/io/kestra/plugin/kubernetes/AbstractPod.java b/src/main/java/io/kestra/plugin/kubernetes/AbstractPod.java index f2bd212..d0ffa3c 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/AbstractPod.java +++ b/src/main/java/io/kestra/plugin/kubernetes/AbstractPod.java @@ -54,6 +54,7 @@ public abstract class AbstractPod extends AbstractConnection { ) @NotNull @Builder.Default + @PluginProperty(group = "main") protected Property namespace = Property.ofValue("default"); @Schema( @@ -61,13 +62,14 @@ public abstract class AbstractPod extends AbstractConnection { description = "Only files created inside the `kestra/working-dir` directory of the container can be retrieved.\n" + "Must be a list of [glob](https://en.wikipedia.org/wiki/Glob_(programming)) expressions relative to the current working directory, some examples: `my-dir/**`, `my-dir/*/**` or `my-dir/my-file.txt`.." ) + @PluginProperty(group = "destination") protected Property> outputFiles; @Schema( title = "The files to create on the local filesystem – it can be a map or a JSON object.", description = "The files will be available inside the `kestra/working-dir` directory of the container. You can use the special variable `{{workingDir}}` in your command to refer to it." ) - @PluginProperty( + @PluginProperty(group = "source", additionalProperties = String.class, dynamic = true ) @@ -76,7 +78,7 @@ public abstract class AbstractPod extends AbstractConnection { @Schema( title = "The configuration of the file sidecar container that handles the download and upload of files" ) - @PluginProperty + @PluginProperty(group = "advanced") @Builder.Default protected SideCar fileSidecar = SideCar.builder().build(); @@ -88,6 +90,7 @@ public abstract class AbstractPod extends AbstractConnection { "Supports Pods, StatefulSets, and custom resources that use the Ready condition. " + "Note: Deployments are not supported as they use the Available condition instead of Ready." ) + @PluginProperty(group = "advanced") protected Property waitUntilReady = Property.ofValue(Duration.ZERO); @Schema( @@ -132,6 +135,7 @@ public abstract class AbstractPod extends AbstractConnection { ``` """ ) + @PluginProperty(group = "advanced") protected Property> containerDefaultSpec; @SuppressWarnings("ResultOfMethodCallIgnored") diff --git a/src/main/java/io/kestra/plugin/kubernetes/core/PodCreate.java b/src/main/java/io/kestra/plugin/kubernetes/core/PodCreate.java index 4099ad7..6ce4673 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/core/PodCreate.java +++ b/src/main/java/io/kestra/plugin/kubernetes/core/PodCreate.java @@ -258,7 +258,7 @@ public class PodCreate extends AbstractPod implements RunnableTask metadata; @Schema( @@ -274,7 +274,7 @@ public class PodCreate extends AbstractPod implements RunnableTask spec; @@ -284,6 +284,7 @@ public class PodCreate extends AbstractPod implements RunnableTask delete = Property.ofValue(true); @Schema( @@ -292,6 +293,7 @@ public class PodCreate extends AbstractPod implements RunnableTask resume = Property.ofValue(true); @Schema( @@ -300,6 +302,7 @@ public class PodCreate extends AbstractPod implements RunnableTask waitForLogInterval = Property.ofValue(Duration.ofSeconds(30)); // Constants for file paths and working directory @@ -308,9 +311,13 @@ public class PodCreate extends AbstractPod implements RunnableTask currentPodName = new AtomicReference<>(); + @PluginProperty(group = "source") private volatile String currentNamespace; + @PluginProperty(group = "connection") private volatile Connection currentConnection; /** diff --git a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Apply.java b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Apply.java index 76ddcc3..ff7c668 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Apply.java +++ b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Apply.java @@ -21,6 +21,7 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.experimental.SuperBuilder; +import io.kestra.core.models.annotations.PluginProperty; @SuperBuilder @ToString @@ -183,6 +184,7 @@ public class Apply extends AbstractPod implements RunnableTask { title = "Resource manifest", description = "YAML or JSON manifest to apply. Can include multiple documents separated by '---'. Supports template expressions before apply." ) + @PluginProperty(group = "main") private Property spec; @Override diff --git a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Delete.java b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Delete.java index f670466..1edf2d4 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Delete.java +++ b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Delete.java @@ -20,6 +20,7 @@ import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.SuperBuilder; +import io.kestra.core.models.annotations.PluginProperty; @SuperBuilder @ToString @@ -88,6 +89,7 @@ public class Delete extends AbstractPod implements RunnableTask { description = "Kubernetes kind (e.g., Pod, Deployment, Service). Case-insensitive." ) @NotNull + @PluginProperty(group = "main") private Property resourceType; @Schema( @@ -95,18 +97,21 @@ public class Delete extends AbstractPod implements RunnableTask { description = "List of resource names to delete in the target namespace." ) @NotNull + @PluginProperty(group = "main") private Property> resourcesNames; @Schema( title = "API group", description = "Group for the resource kind (empty for core resources)." ) + @PluginProperty(group = "advanced") private Property apiGroup; @Schema( title = "API version", description = "Version for the resource kind. Defaults to v1 when omitted." ) + @PluginProperty(group = "advanced") private Property apiVersion; @Override diff --git a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Get.java b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Get.java index 6228a28..963d51b 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Get.java +++ b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Get.java @@ -37,6 +37,7 @@ import reactor.core.publisher.FluxSink; import static io.kestra.core.models.tasks.common.FetchType.NONE; +import io.kestra.core.models.annotations.PluginProperty; @SuperBuilder @ToString @@ -177,24 +178,28 @@ public class Get extends AbstractPod implements RunnableTask { description = "Kubernetes kind (e.g., Pod, Deployment, Service). Case-insensitive." ) @NotNull + @PluginProperty(group = "main") private Property resourceType; @Schema( title = "Resource names", description = "Optional list of names to fetch. When empty, all resources of the kind in the namespace are returned." ) + @PluginProperty(group = "source") private Property> resourcesNames; @Schema( title = "API group", description = "Group for the resource kind (empty for core resources)." ) + @PluginProperty(group = "advanced") private Property apiGroup; @Schema( title = "API version", description = "Version for the resource kind. Defaults to v1 when omitted." ) + @PluginProperty(group = "advanced") private Property apiVersion; @Schema( @@ -203,6 +208,7 @@ public class Get extends AbstractPod implements RunnableTask { ) @NotNull @Builder.Default + @PluginProperty(group = "processing") protected Property fetchType = Property.ofValue(NONE); @Override diff --git a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Patch.java b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Patch.java index 7e8440e..ab0759f 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Patch.java +++ b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Patch.java @@ -21,6 +21,7 @@ import jakarta.validation.constraints.NotNull; import lombok.*; import lombok.experimental.SuperBuilder; +import io.kestra.core.models.annotations.PluginProperty; @SuperBuilder @ToString @@ -216,12 +217,14 @@ public class Patch extends AbstractPod implements RunnableTask { title = "Resource kind", description = "Namespaced Kubernetes kind (e.g., Deployment, StatefulSet, Pod). Cluster-scoped kinds are not supported." ) + @PluginProperty(group = "main") private Property resourceType; @NotNull @Schema( title = "Resource name" ) + @PluginProperty(group = "main") private Property resourceName; @NotNull @@ -229,6 +232,7 @@ public class Patch extends AbstractPod implements RunnableTask { title = "Patch content", description = "The format depends on the patchStrategy. For STRATEGIC_MERGE and JSON_MERGE, provide a JSON object with the fields to update. For JSON_PATCH, provide a JSON array of operations with 'op', 'path', and 'value' fields." ) + @PluginProperty(group = "main") private Property patch; @Builder.Default @@ -236,18 +240,21 @@ public class Patch extends AbstractPod implements RunnableTask { title = "Patch strategy", description = "STRATEGIC_MERGE (default): Kubernetes strategic merge patch, most user-friendly. Understands K8s resource structure and intelligently merges lists by merge keys. JSON_MERGE: Simple merge with null-deletion semantics (RFC 7386). JSON_PATCH: Precision operations with add/remove/replace/test (RFC 6902)." ) + @PluginProperty(group = "advanced") private Property patchStrategy = Property.ofValue(PatchStrategy.STRATEGIC_MERGE); @Schema( title = "API group", description = "Group for the resource kind. Leave empty for core resources." ) + @PluginProperty(group = "advanced") private Property apiGroup; @Schema( title = "API version", description = "Version for the resource kind (e.g., v1). Defaults to v1 when omitted." ) + @PluginProperty(group = "advanced") private Property apiVersion; @Override diff --git a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Restart.java b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Restart.java index 2a11658..4051628 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/kubectl/Restart.java +++ b/src/main/java/io/kestra/plugin/kubernetes/kubectl/Restart.java @@ -20,6 +20,7 @@ import lombok.NoArgsConstructor; import lombok.ToString; import lombok.experimental.SuperBuilder; +import io.kestra.core.models.annotations.PluginProperty; @SuperBuilder @ToString @@ -58,10 +59,12 @@ public class Restart extends AbstractPod implements RunnableTask { @Schema(title = "Workload type", description = "Deployment or StatefulSet.") @NotNull + @PluginProperty(group = "main") private Property resourceType; @Schema(title = "Resource names", description = "Names of workloads to restart in the namespace.") @NotNull + @PluginProperty(group = "main") private Property> resourcesNames; @Override diff --git a/src/main/java/io/kestra/plugin/kubernetes/models/Connection.java b/src/main/java/io/kestra/plugin/kubernetes/models/Connection.java index 5db11db..f5f3fb8 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/models/Connection.java +++ b/src/main/java/io/kestra/plugin/kubernetes/models/Connection.java @@ -18,12 +18,14 @@ public class Connection { title = "Trust all certificates", description = "When true, skips TLS cert validation. Use only for testing." ) + @PluginProperty(group = "advanced") private final Property trustCerts; @Schema( title = "Disable hostname verification", description = "Disables TLS hostname checks. Avoid in production clusters." ) + @PluginProperty(group = "advanced") private final Property disableHostnameVerification; @Schema( @@ -31,6 +33,7 @@ public class Connection { description = "API server endpoint. Default `https://kubernetes.default.svc`." ) @Builder.Default + @PluginProperty(group = "connection") private final Property masterUrl = Property.ofValue("https://kubernetes.default.svc"); @Schema( @@ -38,46 +41,54 @@ public class Connection { description = "API group version used by the client. Default v1." ) @Builder.Default + @PluginProperty(group = "advanced") private final Property apiVersion = Property.ofValue("v1"); @Schema( title = "Default namespace", description = "Namespace used when resources omit a namespace." ) + @PluginProperty(group = "connection") private final Property namespace; @Schema( title = "CA certificate file", description = "Path to a PEM CA bundle." ) + @PluginProperty(group = "advanced") private final Property caCertFile; @Schema( title = "CA certificate data", description = "Base64-encoded PEM CA bundle. Whitespace is stripped automatically." ) + @PluginProperty(group = "advanced") private final Property caCertData; @Schema( title = "Client certificate file" ) + @PluginProperty(group = "advanced") private final Property clientCertFile; @Schema( title = "Client certificate data", description = "Base64-encoded client cert. Whitespace is stripped automatically." ) + @PluginProperty(group = "advanced") private final Property clientCertData; @Schema( title = "Client key file" ) + @PluginProperty(group = "advanced") private final Property clientKeyFile; @Schema( title = "Client key data", description = "Base64-encoded client key. Whitespace is stripped automatically." ) + @PluginProperty(group = "advanced") private final Property clientKeyData; @Schema( @@ -85,52 +96,61 @@ public class Connection { description = "Algorithm for the client key. Default RSA." ) @Builder.Default + @PluginProperty(group = "advanced") private final Property clientKeyAlgo = Property.ofValue("RSA"); @Schema( title = "Client key passphrase" ) + @PluginProperty(group = "advanced") private final Property clientKeyPassphrase; @Schema( title = "Truststore file" ) + @PluginProperty(group = "advanced") private final Property trustStoreFile; @Schema( title = "Truststore passphrase" ) + @PluginProperty(group = "advanced") private final Property trustStorePassphrase; @Schema( title = "Keystore file" ) + @PluginProperty(group = "advanced") private final Property keyStoreFile; @Schema( title = "Keystore passphrase" ) + @PluginProperty(group = "advanced") private final Property keyStorePassphrase; @Schema( title = "OAuth token" ) + @PluginProperty(group = "connection") private final Property oauthToken; @Schema( title = "OAuth token provider" ) - @PluginProperty + @PluginProperty(group = "connection") private final OAuthTokenProvider oauthTokenProvider; @Schema( title = "Username" ) + @PluginProperty(group = "connection") private Property username; @Schema( title = "Password" ) + @PluginProperty(group = "connection") private Property password; public Config toConfig(RunContext runContext) throws IllegalVariableEvaluationException { diff --git a/src/main/java/io/kestra/plugin/kubernetes/models/Metadata.java b/src/main/java/io/kestra/plugin/kubernetes/models/Metadata.java index c5129f0..f184f8d 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/models/Metadata.java +++ b/src/main/java/io/kestra/plugin/kubernetes/models/Metadata.java @@ -10,6 +10,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Getter; +import io.kestra.core.models.annotations.PluginProperty; @Builder @Getter @@ -17,81 +18,97 @@ public class Metadata { @Schema( title = "Generated UUID of this resource" ) + @PluginProperty(group = "advanced") private String uid; @Schema( title = "Resource name" ) + @PluginProperty(group = "advanced") private final String name; @Schema( title = "Resource namespace" ) + @PluginProperty(group = "connection") private final String namespace; @Schema( title = "Cluster name" ) + @PluginProperty(group = "advanced") private final String clusterName; @Schema( title = "Resource annotations" ) + @PluginProperty(group = "advanced") private final Map annotations; @Schema( title = "Resource labels" ) + @PluginProperty(group = "advanced") private final Map labels; @Schema( title = "Creation timestamp" ) + @PluginProperty(group = "advanced") private final Instant creationTimestamp; @Schema( title = "Deletion grace period in seconds" ) + @PluginProperty(group = "advanced") private final Long deletionGracePeriodSeconds; @Schema( title = "Deletion timestamp" ) + @PluginProperty(group = "advanced") private final Instant deletionTimestamp; @Schema( title = "Finalizers" ) + @PluginProperty(group = "advanced") private final List finalizers; @Schema( title = "Generated name prefix" ) + @PluginProperty(group = "advanced") private final String generateName; @Schema( title = "Generation" ) + @PluginProperty(group = "advanced") private final Long generation; @Schema( title = "Managed fields" ) + @PluginProperty(group = "advanced") private final List managedFields; @Schema( title = "Owner references" ) + @PluginProperty(group = "advanced") private final List ownerReferences; @Schema( title = "Resource version" ) + @PluginProperty(group = "advanced") private final String resourceVersion; @Schema( title = "Self link" ) + @PluginProperty(group = "advanced") private final String selfLink; public static Metadata from(ObjectMeta meta) { diff --git a/src/main/java/io/kestra/plugin/kubernetes/models/OAuthTokenProvider.java b/src/main/java/io/kestra/plugin/kubernetes/models/OAuthTokenProvider.java index de02933..75a08aa 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/models/OAuthTokenProvider.java +++ b/src/main/java/io/kestra/plugin/kubernetes/models/OAuthTokenProvider.java @@ -31,7 +31,7 @@ public class OAuthTokenProvider implements io.fabric8.kubernetes.client.OAuthTok and re-fetch a token on every request.\ """ ) - @PluginProperty + @PluginProperty(group = "advanced") @Builder.Default private Duration cache = Duration.ofMinutes(5); diff --git a/src/main/java/io/kestra/plugin/kubernetes/models/ResourceStatus.java b/src/main/java/io/kestra/plugin/kubernetes/models/ResourceStatus.java index ed332bb..683914e 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/models/ResourceStatus.java +++ b/src/main/java/io/kestra/plugin/kubernetes/models/ResourceStatus.java @@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Getter; +import io.kestra.core.models.annotations.PluginProperty; @Builder @Getter @@ -14,6 +15,7 @@ public class ResourceStatus { title = "The status of the Kubernetes resource", description = "Contains the current state of the resource as a generic map structure" ) + @PluginProperty(group = "advanced") private final Map status; /** diff --git a/src/main/java/io/kestra/plugin/kubernetes/models/SideCar.java b/src/main/java/io/kestra/plugin/kubernetes/models/SideCar.java index 74f4c49..42d0239 100644 --- a/src/main/java/io/kestra/plugin/kubernetes/models/SideCar.java +++ b/src/main/java/io/kestra/plugin/kubernetes/models/SideCar.java @@ -8,6 +8,7 @@ import lombok.Builder; import lombok.Getter; import lombok.extern.jackson.Jacksonized; +import io.kestra.core.models.annotations.PluginProperty; @Getter @Builder @@ -18,12 +19,14 @@ public class SideCar { description = "Container image used by the init/sidecar that handles file transfer. Defaults to busybox." ) @Builder.Default + @PluginProperty(group = "advanced") private Property image = Property.ofValue("busybox"); @Schema( title = "Configure sidecar resource requests/limits", description = "Optional Kubernetes resources block applied to the file transfer sidecar." ) + @PluginProperty(group = "advanced") private Property> resources; @Schema( @@ -42,5 +45,6 @@ public class SideCar { mountPath: /tmp """ ) + @PluginProperty(group = "advanced") private Property> defaultSpec; }