Skip to content

architect plugins / macro hooks brainstorm #1051

@filmaj

Description

@filmaj

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/create and hydrate. 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 main create function works by:
    1. retrieving an @architect/inventory instance and looking at the core supported Lambda-backed arc pragmas
    2. creates any directories for the lambda-backed pragmas (using an implied src parameter provided by inventory to figure out the path to said directory)
    3. writes out a stub handler file using templates hard coded into @architect/create.
    • One idea on how to implement create support 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 inventory and perhaps which exists within the macro at module.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 src property (pointing to the directory of the lambda code. Using the IoT Rules macro i've recently created, this would look like src/rules/name-of-rule)
        • a body property containing the template of the lambda handler file
      • Finally, create could use this macro output and leverage the existing src/lambda code (with minor adjustments) to create default handler directories and files for macros.
  • @architect/hydrate. Not much would need to be changed here as hydrate's implementation is pragma-agnostic. The only hiccup would be that, currently, any lambda directories not listed in inventory.lambdaSrcDirs get 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 above create implementation suggestion, hydrate could invoke the macro's create hook 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 via map(o => o.src)), or perhaps by allowing macros to modify the inventory (more on that below).
  • @architect/logs. The get Logical Id module inside logs hardcodes two things:
    1. whether to read logs from a path based on whether inventory has the path registered inside lambdaSrcDirs (so same limitation as hydrate)
    2. which pragmas to read logs from (so same limitation as create)
    • ... both of these are solvable problems, as discussed above.
  • @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 how http, events and tables are supported in sandbox, it looks like there is a start() and end() method for each of these services. Perhaps we could use this same approach for macros too? On sandbox startup, macros could be required in, and if they contain a start function handler, that would then be executed. We could do the same thing on sandbox shutdown, pull the macros in, and if they contain an end function handler, then that gets executed.
  • @architect/inventory. Perhaps it is worth providing macros a hook into inventory as well? In hydrate and logs, inv.lambdaSrcDirs is used to filter out which locations to operate on. Thus, perhaps there is benefit in allowing macros to modify lambdaSrcDirs to 'register' their own lambda source directories (if applicable to the macro) - and thus get support for macro hooks into both hydrate and logs '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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions