Checklist
- User Stories Documented
- User Stories Reviewed
- Design Reviewed
- APIs reviewed
- Release priorities assigned
- Test cases reviewed
- Blog post
Introduction
CDAP pipeline is composed of various plugins that can be configured by users as CDAP pipelines are being developed. While building CDAP pipelines, pipeline developer can provide invalid plugin configurations. For example, the BigQuery sink plugin can have schema which does not match with an underlying BigQuery table. CDAP pipeline developer can use new validation endpoint to validate the stages before deploying the pipeline. In order to fail fast, validation endpoint should return all the validation errors from a given stage when this endpoint is called.
Data pipeline app exposes various exceptions to plugins so that appropriate exception is thrown while validating the plugins. In future releases, new exception types can be introduced. Data pipeline app should be modified so that app artifacts does not need to be replaced for every new type of exception.
Goals
To fail fast, introduce a new api to collect multiple error messages from plugins at configure time
- Decouple various validation exception types from data pipeline app
Instrument plugins to use this api to return multiple error messages for validation endpoint
User Stories
- As a CDAP pipeline developer, if a pipeline contains plugin configurations which are invalid, I will like it to fail early with appropriate error message specific to the field or config property.
- As a CDAP pipeline developer, I should be able to incorporate new types of exceptions that are exposed by Data pipeline app in custom plugins without replacing data pipeline artifacts.
API Changes for Plugin Validation
Plugin Validation
Plugin validation endpoint is used to surface all the stage level errors at once. To collect multiple stage validation errors from the stage, StageConfigurer, MultiInputStageConfigurer and MultiOutputStageConfigurer can be modified as below. If there are one or more errors added to stage configurer, the pipeline deployment will fail.
public interface StageConfigurer { /** * get the input schema for this stage, or null if its unknown * * @return input schema */ @Nullable Schema getInputSchema(); /** * set the output schema for this stage, or null if its unknown * * @param outputSchema output schema for this stage */ void setOutputSchema(@Nullable Schema outputSchema); /** * set the error schema for this stage, or null if its unknown. * If no error schema is set, it will default to the input schema for the stage. Note that since source * plugins do not have an input schema, it will default to null for sources. * * @param errorSchema error schema for this stage */ void setErrorSchema(@Nullable Schema errorSchema); /** * add errors for this stage to the configurer if pipeline stage is invalid. * * @param error {@link ValidationException} when a pipeline stage is invalid for any reason. */ void addStageError(ValidationException error); } where ValidationException can be defined as below: /** * Exception thrown while validating a plugin. */ @Beta public class ValidationException extends RuntimeException { private static final String ERROR = "ERROR"; protected final String type; public ValidationException(String message) { super(message); this.type = getType(); } public ValidationException(String message, Throwable cause) { super(message, cause); this.type = getType(); } /** * Returns type of the exception. */ public String getType() { return ERROR; } /** * Returns json string which should include type, message and other attributes of the validation exception. */ public String toJson() { // return json string containing type, error message return "{\"message\" : \"" + getMessage() + "\", \"type\" : \"" + getType() + "\"}"; } }
A new module will be introduced so that whenever new type of exception is added, data pipeline artifact does not need to be updated. Below are some of the exceptions that will be added to the new module.
/** * Exception used for invalid stage property. */ @Beta public class InvalidStagePropertyException extends ValidationException { private final String property; private static final String STAGE_ERROR = "STAGE_ERROR"; public InvalidStagePropertyException(String message, String property) { super(message); this.property = property; } public InvalidStagePropertyException(String message, Throwable cause, String property) { super(message, cause); this.property = property; } public String getProperty() { return property; } @Override public String getType() { return STAGE_ERROR; } @Override public String toJson() { return "{\"message\" : \"" + getMessage() + "\", \"type\" : \"" + getType() + "\", \"property\" : \"" + property + "\"}"; } }
Sources and sinks can have schema mismatch with underlying storage. A new type of exception can be introduced so that invalid schema fields can be highlighted when schema mismatch occurs:
/** * Exception used for invalid schema field. */ @Beta public class InvalidSchemaFieldException extends ValidationException { private final String field; private static final String SCHEMA_ERROR = "SCHEMA_ERROR"; public InvalidSchemaFieldException(String message, String field) { super(message); this.field = field; } public InvalidSchemaFieldException(String message, Throwable cause, String field) { super(message, cause); this.field = field; } public String getField() { return field; } @Override public String getType() { return SCHEMA_ERROR; } @Override public String toJson() { return "{\"message\" : \"" + getMessage() + "\", \"type\" : \"" + getType() + "\", \"field\" : \"" + field + "\"}"; } }
In order to validate plugins, this api can be used in plugins as below:
@Override public void configurePipeline(PipelineConfigurer pipelineConfigurer) { pipelineConfigurer.createDataset(conf.destinationFileset, FileSet.class); StageConfigurer stageConfigurer = pipelineConfigurer.getStageConfigurer(); try { Pattern.compile(conf.filterRegex); } catch (Exception e) { stageConfigurer.addStageError(new InvalidStagePropertyException(e.getMessage(), "filterRegex")); } if (conf.sourceFileset.equals(conf.destinationFileset)) { stageConfigurer.addStageError(new ValidationException("source and destination filesets must be different")); } }
Deprecated APIs
Following exception apis will be deprecated:
ValidationError
ValidationErrorSerDe
PluginNotFoundError
InvalidConfigPropertyError
StageValidationError
StageValidationResponse
Impact on UI
UI should be able to handle new error types that are introduced. For example, for invalid stage properties, UI should highlight all the invalid properties for a given stage. For schema mismatch, UI should be able to highlight schema fields that are mismatching. UI should also handle type that are not
Test Scenarios
Test ID | Test Description | Expected Results |
---|---|---|
Releases
Release 6.1.0
Related Work
- Work #1
- Work #2
- Work #3