Skip to main content

Extending Booster with Rockets!

You can extend Booster by creating rockets. A rocket is just a node package that implements the public Booster rocket interfaces. You can use them for many things:

  1. Extend your infrastructure: You can write a rocket that adds provider resources to your application stack.
  2. Runtime extensions (Not yet implemented): Add new annotations and interfaces, which combined with infrastructure extensions, could implement new abstractions on top of highly requested use cases.
  3. Deploy and init hooks (Not yet implemented): Run custom scripts before or after deployment, or before a Booster application is loaded.

This extension mechanism is very new, but we're planning to port most of the functionality as rockets. This has two benefits:

  • Composability: You can use the default rockets or configure your application to suit your needs without adding anything extra.
  • Easier to manage feature sets in different providers: It would be really hard for the core team and contributors to implement and test every new feature in every supported provider, so by providing functionality like rockets, you'll have access to the most advanced features for your provider faster, and the rockets library can be built on-demand for each provider.

Create your own Rocket

A rocket is nothing more than an npm package that extends your current Booster architecture. The structure is simple, and it mainly has 2 methods: mountStack and unmountStack. We'll explain what they are shortly.

Rockets are usually composed of many packages, so we recommend using Lerna for development and publishing.

Infrastructure Rocket interfaces are provider-dependant, so Infrastructure Rockets must import the corresponding booster infrastructure package for their chosen provider. For AWS, that's @boostercloud/framework-provider-aws-infrastructure. Notice that, as the only thing we use of that package is the InfrastructureRocket interface, you can import it as a dev dependency to avoid including that big package in your deployed lambdas.

So let's start by creating a new package and adding this dependency:`

mkdir rocket-your-rocket-name-aws-infrastructure
cd rocket-your-rocket-name-aws-infrastructure
npm init
...
npm install --save @boostercloud/framework-provider-aws-infrastructure

The basic structure of an Infrastructure Rocket project is quite simple as you can see here:

rocket-your-rocket-name-aws-infrastructure
├── package.json
├── src
├── index.ts
└── your-main-class.ts

<your-main-class>.ts can be named as you want and this is where we define the mountStack and unmount methods.

export class YourMainClass {
public static mountStack(params: YourRocketParams, stack: Stack, config: BoosterConfig): void {
/* CDK code to expand your Booster infrastructure */
}
public static unmountStack?(params: YourRocketParams, utils: RocketUtils): void {
/* Optional code that runs before removing the stack */
}
}

Let's look in more detail these two special functions:

  • mountStack: Whenever we are deploying our Booster application (boost deploy) this method will also be run. It receives three params:

    • params: The parameters required by your Infrastructure Rocket initializator, you will receive them from your Booster app's config.ts file.
    • stack: An initialized AWS CDK stack that you can use to add new resources. Check out the Stack API in the official CDK documentation. This is the same stack instance that Booster uses to deploy its resources, so your resources will automatically be deployed along with the Booster's ones on the same stack.
    • config: It includes properties of the Booster project (e.g. project name) that come in handy for your rocket.
  • unmountStack: It will run when you run the boost nuke command. When you nuke your Booster application, all the resources added by your rocket are automatically destroyed along with the application stack, but there are some situations where you might or need to specify any additional step in the deletion process. The unmountStack function will run the code you intend for this purpose. For instance, in AWS, before destroying your stack (where you have some S3 buckets) you need to first empty them in order to delete them. You can accomplish this action in the unmountStack method.

We also have an index.ts file to export these two functions:

export interface InfrastructureRocket {
mountStack: (stack: Stack, config: BoosterConfig) => void
unmountStack?: (utils: RocketUtils) => void
}

You'll have to implement a default exported function that accepts a parameters object and returns an initialized InfrastructureRocket object:

const YourRocketInitializator = (params: YourRocketParams): InfrastructureRocket => ({
mountStack: SomePrivateObject.mountStack.bind(null, params),
unmountStack: SomePrivateObject.unmountStack.bind(null, params),
})

export default YourRocketInitializator

Notice that Infrastructure Rockets should not be included in the Booster application code to avoid including the CDK and other unused dependencies in the lambdas, as there are some strict restrictions on code size on most platforms. That's why Infrastructure Rockets are dynamically loaded by Booster passing the package names as strings in the application config file:

src/config/production.ts:

Booster.configure('development', (config: BoosterConfig): void => {
config.appName = 'my-store'
config.providerPackage = '@boostercloud/framework-provider-aws'
config.rockets = [
{
packageName: 'rocket-your-rocket-name-aws-infrastructure', // The name of your infrastructure rocket package
parameters: {
// An arbitrary object with the parameters required by your infrastructure rocket initializator
hello: 'world',
},
},
]
})

Naming recommendations

There are no restrictions on how you name your rocket packages, but we propose the following naming convention to make it easier to find your extensions in the vast npm library and find related packages (code and infrastructure extensions cannot be distributed in the same package).

  • rocket-{rocket-name}-{provider}: A rocket that adds runtime functionality or init scripts. This code will be deployed along with your application code to the lambdas.
  • rocket-{rocket-name}-{provider}-infrastructure: A rocket that provides infrastructure extensions or implements deploy hooks. This code will only be used on developer's or CI/CD systems machines and won't be deployed to lambda with the rest of the application code.

Notice that some functionalities, for instance an S3 uploader, might require both runtime and infrastructure extensions. In these cases, the convention is to use the same name rocket-name and add the suffix -infrastructure to the infrastructure rocket. It's recommended, but not required, to manage these dependent packages in a monorepo and ensure that the versions match on each release.

If you want to support the same functionality in several providers, it could be handy to also have a package named rocket-{rocket-name}-{provider}-core where you can have cross-provider code that you can use from all the provider-specific implementations. For instance, a file uploader rocket that supports both AWS and Azure could have an structure like this:

  • rocket-file-uploader-core: Defines abstract decorators and interfaces to handle uploaded files.
  • rocket-file-uploader-aws: Implements the API calls to S3 to get the uploaded files.
  • rocket-file-uploader-aws-infrastructure: Adds a dedicated S3 bucket.
  • rocket-file-uploader-azure: Implements the API calls to Azure Storage to get the uploaded files.
  • rocket-file-uploader-azure-infrastructure: Configures file storage.

How to publish a Rocket

  1. Upload your rocket to a git repository.
  2. Run :
        > lerna bootstrap
    This will bootstrap the packages, install all their dependencies and link any cross-dependencies.
  3. Ensure you have the option publishConfig.access set to public in the package.json file of every package.
  4. Make sure you are logged into NPM by running:
         > npm login
  5. Run :
        > lerna publish
    Creates a new release of the packages that have been updated. It will update all the packages in git and npm, and it will prompt for a new version of the rocket package.
  6. If the previous step finished successfully, the package will be available in NPM.

Booster Rockets list

Here you can check out the official Booster Rockets developed at this time: