Skip to content
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

[Backport 2.x] Moved workflow-steps.json to Enum #529

Merged
merged 1 commit into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
CHANGELOG

# CHANGELOG
All notable changes to this project are documented in this file.

Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)

2.12.0 Initial Release
## [Unreleased]
### Added
- Github workflow for changelog verification ([#440](https://github.com/opensearch-project/flow-framework/pull/440))

### Changed

### Deprecated

### Removed

### Fixed

### Security


[Unreleased]: https://github.com/opensearch-project/flow-framework/compare/2.x...HEAD
## [Unreleased 3.0](https://github.com/opensearch-project/flow-framework/compare/2.x...HEAD)
### Features
### Enhancements
### Bug Fixes
### Infrastructure
### Documentation
### Maintenance
### Refactoring

## [Unreleased 2.x](https://github.com/opensearch-project/flow-framework/compare/2.12...2.x)
### Features
### Enhancements
### Bug Fixes
### Infrastructure
### Documentation
### Maintenance
### Refactoring
- Moved workflow-steps.json to Enum ([#523](https://github.com/opensearch-project/flow-framework/pull/523))
2 changes: 1 addition & 1 deletion DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,6 @@ To add functionality to workflows, add new Workflow Steps to the [`org.opensearc
1. Implement the [Workflow](https://github.com/opensearch-project/flow-framework/blob/main/src/main/java/org/opensearch/flowframework/workflow/WorkflowStep.java) interface. See existing steps for examples for input, output, and API execution.
2. Choose a unique name for the step which is not used by other steps. This will align with the `step_type` field in the templates and should be descriptive of what the step does.
3. Add a constructor and call it from the [WorkflowStepFactory](https://github.com/opensearch-project/flow-framework/blob/main/src/main/java/org/opensearch/flowframework/workflow/WorkflowStepFactory.java).
4. Add a configuration to the [`workflow-steps.json`](https://github.com/opensearch-project/flow-framework/blob/main/src/main/resources/mappings/workflow-steps.json) file specifying required inputs, outputs, required plugins, and optionally a different timeout than the default.
4. Add an entry to the [WorkflowStepFactory](https://github.com/opensearch-project/flow-framework/blob/main/src/main/java/org/opensearch/flowframework/workflow/WorkflowStepFactory.java) enum specifying required inputs, outputs, required plugins, and optionally a different timeout than the default.
5. If your step provisions a resource that should be deprovisioned, create the corresponding step and add both steps to the [`WorkflowResources`](https://github.com/opensearch-project/flow-framework/blob/main/src/main/java/org/opensearch/flowframework/common/WorkflowResources.java) enum.
6. Write unit and integration tests.
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,6 @@ private CommonValue() {}
public static final String RESOURCE_TYPE = "resource_type";
/** The field name for the resource id */
public static final String RESOURCE_ID = "resource_id";
/** The field name for the opensearch-ml plugin */
public static final String OPENSEARCH_ML = "opensearch-ml";
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,12 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.opensearch.common.unit.TimeValue;
import org.opensearch.core.rest.RestStatus;
import org.opensearch.core.xcontent.ToXContentObject;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.core.xcontent.XContentParser;
import org.opensearch.flowframework.exception.FlowFrameworkException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken;

/**
* This represents an object of workflow steps json which maps each step to expected inputs and outputs
*/
Expand All @@ -39,81 +33,34 @@ public class WorkflowStepValidator implements ToXContentObject {
/** Timeout field name */
private static final String TIMEOUT = "timeout";

private String workflowStep;
private List<String> inputs;
private List<String> outputs;
private List<String> requiredPlugins;
private TimeValue timeout;

/**
* Instantiate the object representing a Workflow Step validator
* @param workflowStep name of the workflow step
* @param inputs the workflow step inputs
* @param outputs the workflow step outputs
* @param requiredPlugins the required plugins for this workflow step
* @param timeout the timeout for this workflow step
*/
public WorkflowStepValidator(List<String> inputs, List<String> outputs, List<String> requiredPlugins, TimeValue timeout) {
public WorkflowStepValidator(
String workflowStep,
List<String> inputs,
List<String> outputs,
List<String> requiredPlugins,
TimeValue timeout
) {
this.workflowStep = workflowStep;
this.inputs = inputs;
this.outputs = outputs;
this.requiredPlugins = requiredPlugins;
this.timeout = timeout;
}

/**
* Parse raw json content into a WorkflowStepValidator instance
* @param parser json based content parser
* @return an instance of the WorkflowStepValidator
* @throws IOException if the content cannot be parsed correctly
*/
public static WorkflowStepValidator parse(XContentParser parser) throws IOException {
List<String> parsedInputs = new ArrayList<>();
List<String> parsedOutputs = new ArrayList<>();
List<String> requiredPlugins = new ArrayList<>();
TimeValue timeout = null;

ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser);
while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
String fieldName = parser.currentName();
parser.nextToken();
switch (fieldName) {
case INPUTS_FIELD:
ensureExpectedToken(XContentParser.Token.START_ARRAY, parser.currentToken(), parser);
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
parsedInputs.add(parser.text());
}
break;
case OUTPUTS_FIELD:
ensureExpectedToken(XContentParser.Token.START_ARRAY, parser.currentToken(), parser);
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
parsedOutputs.add(parser.text());
}
break;
case REQUIRED_PLUGINS:
ensureExpectedToken(XContentParser.Token.START_ARRAY, parser.currentToken(), parser);
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
requiredPlugins.add(parser.text());
}
break;
case TIMEOUT:
try {
timeout = TimeValue.parseTimeValue(parser.text(), TIMEOUT);
} catch (IllegalArgumentException e) {
logger.error("Failed to parse TIMEOUT value for field [{}]", fieldName, e);
throw new FlowFrameworkException(
"Failed to parse workflow-step.json file for field [" + fieldName + "]",
RestStatus.INTERNAL_SERVER_ERROR
);
}
break;
default:
throw new FlowFrameworkException(
"Unable to parse field [" + fieldName + "] in a WorkflowStepValidator object.",
RestStatus.BAD_REQUEST
);
}
}
return new WorkflowStepValidator(parsedInputs, parsedOutputs, requiredPlugins, timeout);
}

/**
* Get the required inputs
* @return the inputs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,10 @@
import org.opensearch.common.xcontent.json.JsonXContent;
import org.opensearch.core.xcontent.ToXContentObject;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.core.xcontent.XContentParser;
import org.opensearch.flowframework.util.ParseUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken;

/**
* This represents the workflow steps json which maps each step to expected inputs and outputs
*/
Expand All @@ -35,37 +30,6 @@ public WorkflowValidator(Map<String, WorkflowStepValidator> workflowStepValidato
this.workflowStepValidators = workflowStepValidators;
}

/**
* Parse raw json content into a WorkflowValidator instance
* @param parser json based content parser
* @return an instance of the WorkflowValidator
* @throws IOException if the content cannot be parsed correctly
*/
public static WorkflowValidator parse(XContentParser parser) throws IOException {

Map<String, WorkflowStepValidator> workflowStepValidators = new HashMap<>();

ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser);
while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
String type = parser.currentName();
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
workflowStepValidators.put(type, WorkflowStepValidator.parse(parser));
}
return new WorkflowValidator(workflowStepValidators);
}

/**
* Parse a workflow step JSON file into a WorkflowValidator object
*
* @param file the file name of the workflow step json
* @return A {@link WorkflowValidator} represented by the JSON
* @throws IOException on failure to read and parse the json file
*/
public static WorkflowValidator parse(String file) throws IOException {
String json = ParseUtils.resourceToString("/" + file);
return parse(ParseUtils.jsonToParser(json));
}

/**
* Output this object in a compact JSON string.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.opensearch.core.xcontent.ToXContentObject;
import org.opensearch.core.xcontent.XContentBuilder;
import org.opensearch.flowframework.model.WorkflowValidator;
import org.opensearch.flowframework.workflow.WorkflowStepFactory;

import java.io.IOException;

Expand All @@ -23,6 +24,7 @@
public class GetWorkflowStepResponse extends ActionResponse implements ToXContentObject {

private WorkflowValidator workflowValidator;
private WorkflowStepFactory workflowStepFactory;

/**
* Instantiates a new GetWorkflowStepResponse from an input stream
Expand All @@ -31,7 +33,7 @@
*/
public GetWorkflowStepResponse(StreamInput in) throws IOException {
super(in);
this.workflowValidator = WorkflowValidator.parse(in.readString());
this.workflowValidator = this.workflowStepFactory.getWorkflowValidator();

Check warning on line 36 in src/main/java/org/opensearch/flowframework/transport/GetWorkflowStepResponse.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/opensearch/flowframework/transport/GetWorkflowStepResponse.java#L36

Added line #L36 was not covered by tests
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.opensearch.core.action.ActionListener;
import org.opensearch.flowframework.exception.FlowFrameworkException;
import org.opensearch.flowframework.model.WorkflowValidator;
import org.opensearch.flowframework.workflow.WorkflowStepFactory;
import org.opensearch.tasks.Task;
import org.opensearch.transport.TransportService;

Expand All @@ -27,21 +28,29 @@
public class GetWorkflowStepTransportAction extends HandledTransportAction<ActionRequest, GetWorkflowStepResponse> {

private final Logger logger = LogManager.getLogger(GetWorkflowStepTransportAction.class);
private final WorkflowStepFactory workflowStepFactory;

/**
* Instantiates a new GetWorkflowStepTransportAction instance
* @param transportService the transport service
* @param actionFilters action filters
* @param workflowStepFactory The factory instantiating workflow steps
*/
@Inject
public GetWorkflowStepTransportAction(TransportService transportService, ActionFilters actionFilters) {
public GetWorkflowStepTransportAction(
TransportService transportService,
ActionFilters actionFilters,
WorkflowStepFactory workflowStepFactory
) {
super(GetWorkflowStepAction.NAME, transportService, actionFilters, WorkflowRequest::new);
this.workflowStepFactory = workflowStepFactory;
}

@Override
protected void doExecute(Task task, ActionRequest request, ActionListener<GetWorkflowStepResponse> listener) {
try {
listener.onResponse(new GetWorkflowStepResponse(WorkflowValidator.parse("mappings/workflow-steps.json")));
WorkflowValidator workflowValidator = this.workflowStepFactory.getWorkflowValidator();
listener.onResponse(new GetWorkflowStepResponse(workflowValidator));
} catch (Exception e) {
logger.error("Failed to retrieve workflow step json.", e);
listener.onFailure(new FlowFrameworkException(e.getMessage(), ExceptionsHelper.status(e)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ private Map<String, String> getToolsParametersMap(
Map<String, String> previousNodeInputs,
Map<String, WorkflowData> outputs
) {
@SuppressWarnings("unchecked")
Map<String, String> parametersMap = (Map<String, String>) parameters;
Optional<String> previousNodeModel = previousNodeInputs.entrySet()
.stream()
Expand Down
Loading
Loading