-
Notifications
You must be signed in to change notification settings - Fork 49
[Fix #928] Adding config and secret manager #931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,9 @@ | |
| import io.serverlessworkflow.api.types.SchemaInline; | ||
| import io.serverlessworkflow.api.types.Workflow; | ||
| import io.serverlessworkflow.impl.additional.WorkflowAdditionalObject; | ||
| import io.serverlessworkflow.impl.config.ConfigManager; | ||
| import io.serverlessworkflow.impl.config.SecretManager; | ||
| import io.serverlessworkflow.impl.config.SystemPropertyConfigManager; | ||
| import io.serverlessworkflow.impl.events.EventConsumer; | ||
| import io.serverlessworkflow.impl.events.EventPublisher; | ||
| import io.serverlessworkflow.impl.events.InMemoryEvents; | ||
|
|
@@ -37,6 +40,7 @@ | |
| import java.util.ArrayList; | ||
| import java.util.Collection; | ||
| import java.util.Collections; | ||
| import java.util.HashMap; | ||
| import java.util.HashSet; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
|
|
@@ -64,6 +68,8 @@ public class WorkflowApplication implements AutoCloseable { | |
| private final WorkflowModelFactory modelFactory; | ||
| private final WorkflowScheduler scheduler; | ||
| private final Map<String, WorkflowAdditionalObject<?>> additionalObjects; | ||
| private final ConfigManager configManager; | ||
| private final SecretManager secretManager; | ||
|
|
||
| private WorkflowApplication(Builder builder) { | ||
| this.taskFactory = builder.taskFactory; | ||
|
|
@@ -82,6 +88,8 @@ private WorkflowApplication(Builder builder) { | |
| this.modelFactory = builder.modelFactory; | ||
| this.scheduler = builder.scheduler; | ||
| this.additionalObjects = builder.additionalObjects; | ||
| this.configManager = builder.configManager; | ||
| this.secretManager = builder.secretManager; | ||
| } | ||
|
|
||
| public TaskExecutorFactory taskFactory() { | ||
|
|
@@ -158,6 +166,8 @@ public SchemaValidator getValidator(SchemaInline inline) { | |
| private boolean lifeCycleCEPublishingEnabled = true; | ||
| private WorkflowModelFactory modelFactory; | ||
| private Map<String, WorkflowAdditionalObject<?>> additionalObjects; | ||
| private SecretManager secretManager; | ||
| private ConfigManager configManager; | ||
|
|
||
| private Builder() {} | ||
|
|
||
|
|
@@ -226,10 +236,20 @@ public Builder withEventPublisher(EventPublisher eventPublisher) { | |
| return this; | ||
| } | ||
|
|
||
| public Builder withSecretManager(SecretManager secretManager) { | ||
| this.secretManager = secretManager; | ||
| return this; | ||
| } | ||
|
|
||
| public Builder withConfigManager(ConfigManager configManager) { | ||
| this.configManager = configManager; | ||
| return this; | ||
| } | ||
|
|
||
| public <T> Builder withAdditionalObject( | ||
| String name, WorkflowAdditionalObject<T> additionalObject) { | ||
| if (additionalObjects == null) { | ||
| additionalObjects = new ConcurrentHashMap<>(); | ||
| additionalObjects = new HashMap<>(); | ||
| } | ||
| additionalObjects.put(name, additionalObject); | ||
| return this; | ||
|
|
@@ -286,7 +306,18 @@ public WorkflowApplication build() { | |
| if (additionalObjects == null) { | ||
| additionalObjects = Collections.emptyMap(); | ||
| } | ||
|
|
||
| if (configManager == null) { | ||
| configManager = | ||
| ServiceLoader.load(ConfigManager.class) | ||
| .findFirst() | ||
| .orElseGet(() -> new SystemPropertyConfigManager()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By default properties are java system properties |
||
| } | ||
| if (secretManager == null) { | ||
| secretManager = | ||
| ServiceLoader.load(SecretManager.class) | ||
| .findFirst() | ||
| .orElseGet(() -> s -> configManager.config(s, String.class)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By default secrets are properties! |
||
| } | ||
| return new WorkflowApplication(this); | ||
| } | ||
| } | ||
|
|
@@ -348,6 +379,14 @@ public WorkflowScheduler scheduler() { | |
| return scheduler; | ||
| } | ||
|
|
||
| public ConfigManager configManager() { | ||
| return configManager; | ||
| } | ||
|
|
||
| public SecretManager secretManager() { | ||
| return secretManager; | ||
| } | ||
|
|
||
| public <T> Optional<T> additionalObject( | ||
| String name, WorkflowContext workflowContext, TaskContext taskContext) { | ||
| return Optional.ofNullable(additionalObjects.get(name)) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,35 +20,36 @@ | |
| public record WorkflowError( | ||
| String type, int status, String instance, String title, String details) { | ||
|
|
||
| public static final Errors.Standard RUNTIME_TYPE = Errors.RUNTIME; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those two ones were never used. I was trying to avoid accesing Errors from runtime context, but at the end is kind of confusing |
||
| public static final Errors.Standard COMM_TYPE = Errors.COMMUNICATION; | ||
|
|
||
| public static Builder error(String type, int status) { | ||
| return new Builder(type, status); | ||
| } | ||
|
|
||
| public static Builder authorization() { | ||
| return error(Errors.AUTHORIZATION.toString(), Errors.AUTHORIZATION.status()); | ||
| } | ||
|
|
||
| public static Builder communication(int status, TaskContext context, Exception ex) { | ||
| return communication(status, context, ex.getMessage()); | ||
| } | ||
|
|
||
| public static Builder communication(int status, TaskContext context, String title) { | ||
| return new Builder(COMM_TYPE.toString(), status) | ||
| return new Builder(Errors.COMMUNICATION.toString(), status) | ||
| .instance(context.position().jsonPointer()) | ||
| .title(title); | ||
| } | ||
|
|
||
| public static Builder communication(TaskContext context, String title) { | ||
| return communication(COMM_TYPE.status(), context, title); | ||
| return communication(Errors.COMMUNICATION.status(), context, title); | ||
| } | ||
|
|
||
| public static Builder runtime(int status, TaskContext context, Exception ex) { | ||
| return new Builder(RUNTIME_TYPE.toString(), status) | ||
| return new Builder(Errors.RUNTIME.toString(), status) | ||
| .instance(context.position().jsonPointer()) | ||
| .title(ex.getMessage()); | ||
| } | ||
|
|
||
| public static Builder runtime(TaskContext context, Exception ex) { | ||
| return runtime(RUNTIME_TYPE.status(), context, ex); | ||
| return runtime(Errors.RUNTIME.status(), context, ex); | ||
| } | ||
|
|
||
| public static class Builder { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| /* | ||
| * Copyright 2020-Present The Serverless Workflow Specification Authors | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package io.serverlessworkflow.impl.config; | ||
|
|
||
| import java.time.Instant; | ||
| import java.time.OffsetDateTime; | ||
| import java.util.Optional; | ||
|
|
||
| public abstract class AbstractConfigManager implements ConfigManager { | ||
|
|
||
| @Override | ||
| public <T> Optional<T> config(String propName, Class<T> propClass) { | ||
| return Optional.ofNullable(get(propName)).map(v -> convert(v, propClass)); | ||
| } | ||
|
|
||
| protected abstract String get(String propName); | ||
|
|
||
| protected <T> T convert(String value, Class<T> propClass) { | ||
| Object result; | ||
| if (String.class.isAssignableFrom(propClass)) { | ||
| result = value; | ||
| } else if (Boolean.class.isAssignableFrom(propClass)) { | ||
| result = Boolean.parseBoolean(value); | ||
| } else if (Integer.class.isAssignableFrom(propClass)) { | ||
| result = Integer.parseInt(value); | ||
| } else if (Long.class.isAssignableFrom(propClass)) { | ||
| result = Long.parseLong(value); | ||
| } else if (Double.class.isAssignableFrom(propClass)) { | ||
| result = Double.parseDouble(value); | ||
| } else if (Float.class.isAssignableFrom(propClass)) { | ||
| result = Float.parseFloat(value); | ||
| } else if (Short.class.isAssignableFrom(propClass)) { | ||
| result = Short.parseShort(value); | ||
| } else if (Byte.class.isAssignableFrom(propClass)) { | ||
| result = Byte.parseByte(value); | ||
| } else if (Instant.class.isAssignableFrom(propClass)) { | ||
| result = Instant.parse(value); | ||
| } else if (OffsetDateTime.class.isAssignableFrom(propClass)) { | ||
| result = OffsetDateTime.parse(value); | ||
| } else { | ||
| result = convertComplex(value, propClass); | ||
| } | ||
| return propClass.cast(result); | ||
| } | ||
|
|
||
| protected abstract <T> T convertComplex(String value, Class<T> propClass); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| /* | ||
| * Copyright 2020-Present The Serverless Workflow Specification Authors | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package io.serverlessworkflow.impl.config; | ||
|
|
||
| import io.serverlessworkflow.impl.ServicePriority; | ||
| import java.util.Optional; | ||
|
|
||
| public interface ConfigManager extends ServicePriority { | ||
| <T> Optional<T> config(String propName, Class<T> propClass); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| * Copyright 2020-Present The Serverless Workflow Specification Authors | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package io.serverlessworkflow.impl.config; | ||
|
|
||
| import io.serverlessworkflow.impl.ServicePriority; | ||
| import java.util.Optional; | ||
|
|
||
| @FunctionalInterface | ||
| public interface SecretManager extends ServicePriority { | ||
| Optional<String> secret(String secretName); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /* | ||
| * Copyright 2020-Present The Serverless Workflow Specification Authors | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package io.serverlessworkflow.impl.config; | ||
|
|
||
| public class SystemPropertyConfigManager extends AbstractConfigManager { | ||
|
|
||
| @Override | ||
| protected String get(String propName) { | ||
| return System.getProperty(propName); | ||
| } | ||
|
|
||
| @Override | ||
| protected <T> T convertComplex(String value, Class<T> propClass) { | ||
| throw new UnsupportedOperationException( | ||
| "Conversion of property " + value + " to class " + propClass + " is not supported"); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated, but this can be a regular hashmap, since syncrhonization is not required for unvariant hashmap like this one once the application is built