Repository: kestra-io/kestra
Issue: Extend the `secret()` function to return null if the secret cannot be found 
Labels: enhancement

### Feature description

## Motivation

At one point in a flow we pass/set a password as an env variable via the `env` property of the `io.kestra.plugin.scripts.python.Commands` task.

Now I want to switch between passwords and i want to use `secret()`. Depending on where the flow is run (locally or in producation), the first password (defined as an env variable called `SECRETS_PASSWORD_A`) may not exist. 

In this case I want to use the second (which is some default). I tried: 

`USER_PASSWORD: {{ secret('password_a') ?? 'default_password'}}` 

This does not work because `secret()` complains that 'password_a' is not defined (which is correct in this case). I guess my question is: Can I somehow wrap this in an if-statement that does somehting like1. if password_a exists, use secret() on it and set this to be USER_PASSWORD

2. if `password_a` does not exist use `default_password` and skip using `secrets()`

## Suggested solution 

In the slack #help channel Ludovic suggested to add an argument `failedOnMissing=false`

See: [the conversation on the slack #help channel](https://app.slack.com/client/T01JX6XH5KN/activity)

Issue comments:
I believe failing will not help here. The secret function will need to return null if the secret is not found 

Pull request review comments:

Patch that resolved the issue:
diff --git a/core/src/main/java/io/kestra/core/runners/RunContextLogger.java b/core/src/main/java/io/kestra/core/runners/RunContextLogger.java
index 5f219e2749..3c92d450a5 100644
--- a/core/src/main/java/io/kestra/core/runners/RunContextLogger.java
+++ b/core/src/main/java/io/kestra/core/runners/RunContextLogger.java
@@ -126,7 +126,9 @@ private static Throwable throwable(ILoggingEvent event) {
     }
 
     public void usedSecret(String secret) {
-        this.useSecrets.add(secret);
+        if (secret != null) {
+            this.useSecrets.add(secret);
+        }
     }
 
     public org.slf4j.Logger logger() {
diff --git a/core/src/main/java/io/kestra/core/secret/SecretService.java b/core/src/main/java/io/kestra/core/secret/SecretService.java
index a852f4cc1a..f32dda4715 100644
--- a/core/src/main/java/io/kestra/core/secret/SecretService.java
+++ b/core/src/main/java/io/kestra/core/secret/SecretService.java
@@ -8,7 +8,6 @@
 import java.io.IOException;
 import java.util.Base64;
 import java.util.Map;
-import java.util.Optional;
 import java.util.stream.Collectors;
 
 @Singleton
@@ -36,11 +35,6 @@ private void postConstruct() {
     }
 
     public String findSecret(String tenantId, String namespace, String key) throws IOException, IllegalVariableEvaluationException {
-        return Optional
-            .ofNullable(decodedSecrets.get(key.toUpperCase()))
-            .orElseThrow(() -> new IllegalVariableEvaluationException("Unable to find secret '" + key + "'. " +
-                "You should add it in your environment variables as '" + SECRET_PREFIX + key.toUpperCase() +
-                "' with base64-encoded value."
-            ));
+        return decodedSecrets.get(key.toUpperCase());
     }
 }


Test patch:
diff --git a/core/src/test/java/io/kestra/core/runners/RunContextLoggerTest.java b/core/src/test/java/io/kestra/core/runners/RunContextLoggerTest.java
index c888b741dd..3192945c60 100644
--- a/core/src/test/java/io/kestra/core/runners/RunContextLoggerTest.java
+++ b/core/src/test/java/io/kestra/core/runners/RunContextLoggerTest.java
@@ -103,6 +103,7 @@ void secrets() throws InterruptedException {
 
         runContextLogger.usedSecret("doe.com");
         runContextLogger.usedSecret("myawesomepass");
+        runContextLogger.usedSecret(null);
 
         Logger logger = runContextLogger.logger();
         // exception are not handle and secret will not be replaced
diff --git a/core/src/test/java/io/kestra/core/secret/SecretFunctionTest.java b/core/src/test/java/io/kestra/core/secret/SecretFunctionTest.java
index bf7fee5cf0..d6e1a558d6 100644
--- a/core/src/test/java/io/kestra/core/secret/SecretFunctionTest.java
+++ b/core/src/test/java/io/kestra/core/secret/SecretFunctionTest.java
@@ -15,13 +15,13 @@
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
 
+import java.io.IOException;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.TimeoutException;
 
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.*;
 
 @MicronautTest
 public class SecretFunctionTest extends AbstractMemoryRunnerTest {
@@ -51,11 +51,9 @@ void getSecret() throws TimeoutException {
     }
 
     @Test
-    void getUnknownSecret() {
-        IllegalVariableEvaluationException exception = Assertions.assertThrows(IllegalVariableEvaluationException.class, () ->
-            secretService.findSecret(null, null, "unknown_secret_key")
-        );
+    void getUnknownSecret() throws IllegalVariableEvaluationException, IOException {
+        String secret = secretService.findSecret(null, null, "unknown_secret_key");
 
-        assertThat(exception.getMessage(), containsString("Unable to find secret 'unknown_secret_key'"));
+        assertThat(secret, nullValue());
     }
 }