Skip to content

Commit

Permalink
Add custom stabilization timeout in handlers schema (#61)
Browse files Browse the repository at this point in the history
* split CUD and RL operation handler definitions

* make unit tests less brittle and update README

* update README/schema docs

* allow timeoutInMinutes for read and list for consistency
  • Loading branch information
aygold92 authored and tobywf committed Jan 9, 2020
1 parent bb28cbd commit 45ad76f
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ We have taken an opinion on certain aspects of the core JSON Schema and introduc
### New Schema-Level Properties

#### insertionOrder

Array types can define a boolean `insertionOrder`, which specifies whether the order in which elements are specified should be honored when processing a diff between two sets of properties. If `insertionOrder` is true, then a change in order of the elements will constitute a diff. The default for `insertionOrder` is true.

Together with the `uniqueItems` property (which is native to JSON Schema), complex array types can be defined, as in the following table:
Expand All @@ -143,6 +144,18 @@ Together with the `uniqueItems` property (which is native to JSON Schema), compl
* **`properties` and `patternProperties`** it is not valid to use both properties and patternProperties together in the same shape, as a shape should not contain both defined and undefined values. In order to implement this, the set of undefined values should itself be a subshape.
* **`items` and `additionalItems`** the `items` in an array may only have one schema and may not use a list of schemas, as an ordered tuple of different objects is confusing for both developers and customers. This should be expressed as key:value object pairs. Similarly, `additionalItems` is not allowed.

## handlers

The `handlers` section of the schema allows you to specify which CRUDL operations (create, read, update, delete, list) are available for your resource, as well as some additional metadata about each handler.

### permissions

For each handler, you should define a list of API `permissions` required to perform the operation. Currently, this is used to generate IAM policy templates and is assumed to be AWS API permissions, but you may list 3rd party APIs here as well.

### timeoutInMinutes

For each handler, you may define a `timeoutInMinutes` property, which defines the *maximum* timeout of the operation. This timeout is used by the invoker of the handler (such as CloudFormation) to stop listening and cancel the operation. Note that the handler may of course decide to timeout and return a failure prior to this max timeout period. Currently, this value is only used for `Create`, `Update`, and `Delete` handlers, while `Read` and `List` handlers are expected to return synchronously within 30 seconds.

## License

This library is licensed under the Apache 2.0 License.
7 changes: 7 additions & 0 deletions src/main/resources/schema/provider.definition.schema.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
"type": "string"
},
"additionalItems": false
},
"timeoutInMinutes": {
"description": "Defines the timeout for the entire operation to be interpreted by the invoker of the handler. The default is 120 (2 hours).",
"type": "integer",
"minimum": 2,
"maximum": 720,
"default": 120
}
},
"additionalProperties": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,46 @@ public void validateDefinition_invalidHandlerSection_shouldThrow() {
.withNoCause().withMessage("#/handlers/read: required key [permissions] not found");
}

@ParameterizedTest
@ValueSource(ints = { 1, 721 })
public void validateDefinition_invalidTimeout_shouldThrow(final int timeout) {
// modifying the valid-with-handlers.json to add invalid timeout
final JSONObject definition = new JSONObject(new JSONTokener(this.getClass()
.getResourceAsStream("/valid-with-handlers.json")));

final JSONObject createDefinition = definition.getJSONObject("handlers").getJSONObject("create");
createDefinition.put("timeoutInMinutes", timeout);

final String keyword = timeout == 1 ? "minimum" : "maximum";

assertThatExceptionOfType(ValidationException.class).isThrownBy(() -> validator.validateResourceDefinition(definition))
.withNoCause().withMessageContaining("#/handlers/create/timeoutInMinutes").withMessageContaining(keyword);
}

@ParameterizedTest
@ValueSource(ints = { 2, 120, 720 })
public void validateDefinition_withTimeout_shouldNotThrow(final int timeout) {
final JSONObject definition = new JSONObject(new JSONTokener(this.getClass()
.getResourceAsStream("/valid-with-handlers.json")));

final JSONObject createDefinition = definition.getJSONObject("handlers").getJSONObject("create");
createDefinition.put("timeoutInMinutes", timeout);

validator.validateResourceDefinition(definition);
}

@ParameterizedTest
@ValueSource(strings = { "create", "update", "delete", "read", "list" })
public void validateDefinition_timeoutAllowed_shouldNotThrow(final String handlerType) {
final JSONObject definition = new JSONObject(new JSONTokener(this.getClass()
.getResourceAsStream("/valid-with-handlers.json")));

final JSONObject handlerDefinition = definition.getJSONObject("handlers").getJSONObject(handlerType);
handlerDefinition.put("timeoutInMinutes", 30);

validator.validateResourceDefinition(definition);
}

@Test
public void validateDefinition_validHandlerSection_shouldNotThrow() {
final JSONObject definition = new JSONObject(new JSONTokener(this.getClass()
Expand Down

0 comments on commit 45ad76f

Please sign in to comment.