Writing Plugins
Lulo is plugin based so without plugins Lulo doesn't do anything. Writing plugins is fairly straight forward depending on your use case. A simple Custom Resource takes a matter of minutes to create while more complex cases can easily become, well, complex. It comes down to what you want your plugin to do.
Migrating Plugins to V4
If you have an existing plugin and need to update it to be v4 compatible, please refer to the migration documentation.
Plugin API
Each plugin module must export the following properties:
schema; // Optional
async validateEvent(event): void; // Optional (recommended)
async createResource(event, context): object; // Required
async deleteResource(event, context): object; // Required
async updateResource(event, context): object; // Required
Schema (object)
Schema is an optional object that can be exported by your plugin.
If provided, the schema
property should indicate type specific information about
event.ResourceProperties
.
CloudFormation casts all event input values to strings regardless of how it was initially provided in the template.
In some cases this can be a problem as the aws-sdk will complain that "true" !== true
.
Schema allows you to focus more on what your plugin should be doing and less on type casting.
The schema property can define if event input should be cast to another primitive type including boolean, integer and numeric (numeric allows both integer and float). Structurally the schema supports primitive types, primitive arrays, complex arrays and objects. Properties that are not represented in the schema are passed on as is, i.e. as string values. Properties defined in the schema but that are not represented in the event are ignored.
If schema is provided, the resulting type casted event is provided to all other methods in your plugin.
Note: Schema is not for validation!
Example
This example shows how to flag the different supported types and what the schema is expected to look like.
schema = {
BooleanParameter: { type: 'boolean' },
IntegerParameter: { type: 'integer' },
NumericParameter: { type: 'numeric' },
Nested: {
type: 'object',
schema: {
NumericParameter: { type: 'integer' }
}
},
PrimitiveArray: { type: 'array', schema: 'integer' },
ComplexArray: {
type: 'array',
schema: {
BooleanParameter: { type: 'boolean' },
IntegerParameter: { type: 'integer' },
PrimitiveArray: {
type: 'array',
schema: 'boolean'
}
}
}
};
validateEvent(event)
Optionally validate the incoming event.
Validate is not expected to return anything but it is expected to
throw Error(message)
on validation error.
Validate is not required but highly recommended to catch obvious input errors.
Validate is not invoked on Delete requests.
createResource(event, context): object
Invoked when the resource is created.
updateResource(event, context): object
Invoked when the custom resource is updated.
deleteResource(event, context): object
Invoked when the custom resource is deleted.
Errors Return values
Errors should be thrown by the respective function.
Response DataThe response parameter is optional. If not provided, an empty response will be returned.
If provided, the response parameter should be a flat object, keys cannot be nested.
If you need to namespace return values from a plugin, use dot.notation in the object keys.
These values are referenced using
!GetAtt 'ResourceName.ReturnValueKey
or
!GetAtt 'ResourceName.NestedReturnValue.ReturnValueKey'
If you want to set the PhysicalResourceId of the CustomResource, set
response.physicalResourceId
to the value you want.
If you set the physicalResourceId, this value can be referenced directly via { "Ref": "ResourceName" }
If not set it will default to the value of the Lambda invocation logStream, a nonsensical value that cannot be used as a reference.
Lambda Runtimes
Your plugins are expected to run on the supported nodejs Lambda runtimes >= 18.x.
IAM permissions
Document any additional IAM permissions that your plugin requires.
Dependencies
Do not bundle the aws-sdk, add it to your dev dependencies.
Keeping the plugins small will decrease the cold start time.
List your plugin on the project page
Update plugins.html and submit a pull request to get your plugin listed on the project page.