-
Notifications
You must be signed in to change notification settings - Fork 102
Description
Is your feature request related to a problem? Please describe.
I would like for macros to have the ability to do more than augment the cloudformation JSON. For example, for macros that add new Lambda functions, it would be nice to hook into @architect/create so that the lambda function directories can be generated if missing.
Describe the solution you'd like
Macros currently allow into @architect/deploy's lifecycle - after @architect/package has run to generate a baseline CloudFormation JSON template, but before the deploy is executed. In this manner, macros can "augment" the CloudFormation template pre-deploy.
Given this macro baseline, it feels natural to extend the ability for macros to do other things. Some ideas on what kind of lifecycle events / hooks for macros would be cool, with some initial implementation notes:
@architect/createandhydrate. Have arc create (and hydrate) lambda function directories for the macros that add new lambdas to your project.@architect/sandbox. Support for local dev for your macros!@architect.logs. Pull logs down from the cloud for the macros that interact with other AWS services.
How could this look like? Currently a macro is a node module that exports a function with a particular parameter signature:
module.exports = async function mymacro (arc, sam, stage='staging') {
// modify sam cloudformation here
console.log({ arc, sam, stage })
return sam
}
Perhaps this function could be augmented with specific properties, themselves functions, that then get looked for in the various @architect packages. Some implementation ideas for the specific use cases covered above:
-
@architect/create. The maincreatefunction works by:- retrieving an
@architect/inventoryinstance and looking at the core supported Lambda-backed arc pragmas - creates any directories for the lambda-backed pragmas (using an implied
srcparameter provided byinventoryto figure out the path to said directory) - writes out a stub handler file using templates hard coded into
@architect/create.
- One idea on how to implement
createsupport for macros:- Also look up the macros from the inventory (alongside the core supported pragmas) and
require()them. - Have a macro additional function, which gets passed an instance of
inventoryand perhaps which exists within the macro atmodule.exports.create, that returns an array of objects. Each object represents a lambda-backed directory that the macro needs within the arc project. These objects would contain:- a
srcproperty (pointing to the directory of the lambda code. Using the IoT Rules macro i've recently created, this would look likesrc/rules/name-of-rule) - a
bodyproperty containing the template of the lambda handler file
- a
- Finally,
createcould use this macro output and leverage the existingsrc/lambdacode (with minor adjustments) to create default handler directories and files for macros.
- Also look up the macros from the inventory (alongside the core supported pragmas) and
- retrieving an
-
@architect/hydrate. Not much would need to be changed here ashydrate's implementation is pragma-agnostic. The only hiccup would be that, currently, any lambda directories not listed ininventory.lambdaSrcDirsget ignored and not hydrated - so this filter either needs to be augmented to allow for macro directories to also not be ignored (by e.g. using the abovecreateimplementation suggestion, hydrate could invoke the macro'screatehook to determine which additional source directories the macro registered that may also need hydration (i.e.require('./src/macros/macro-iot-rules').create(inventory)would return e.g.[ { src: 'src/rules/device-connections', body: 'module.exports = function() {}' } ], which could then be mapped to an array of macro-specific lambda source directories viamap(o => o.src)), or perhaps by allowing macros to modify the inventory (more on that below). -
@architect/logs. The get Logical Id module insidelogshardcodes two things:- whether to read logs from a path based on whether
inventoryhas the path registered insidelambdaSrcDirs(so same limitation ashydrate) - which pragmas to read logs from (so same limitation as
create)
- ... both of these are solvable problems, as discussed above.
- whether to read logs from a path based on whether
-
@architect/sandbox. This is the doozy! Local dev support for macros is the holy grail to chase in this issue. Looking at the pattern for howhttp,eventsandtablesare supported in sandbox, it looks like there is astart()andend()method for each of these services. Perhaps we could use this same approach for macros too? On sandbox startup, macros could berequired in, and if they contain astartfunction handler, that would then be executed. We could do the same thing on sandbox shutdown, pull the macros in, and if they contain anendfunction handler, then that gets executed. -
@architect/inventory. Perhaps it is worth providing macros a hook intoinventoryas well? Inhydrateandlogs,inv.lambdaSrcDirsis used to filter out which locations to operate on. Thus, perhaps there is benefit in allowing macros to modifylambdaSrcDirsto 'register' their own lambda source directories (if applicable to the macro) - and thus get support for macro hooks into bothhydrateandlogs'for free' in that sense? - Tests for all the above package changes.
- Documentation for plugin authors.
There are probably also arguments to be had to support hooks for other arc packages (deploy and destroy), but I lack specific use cases for these for now so I will leave them out.
FYI, I intend to prototype support for these in forks in the coming days / weeks.
Describe alternatives you've considered
This issue is a starting point, but certainly would like to collect more thoughts on this!
Additional context or notes
Started as a conversation in Slack: https://architecture-as-text.slack.com/archives/CMK98634P/p1610647437008800