pulumi / pulumi-cdk

Pulumi/CDK Interop Library
Apache License 2.0
61 stars 5 forks source link

Support SST constructs #64

Open lukehoban opened 1 year ago

lukehoban commented 1 year ago

Serverless Stack (https://sst.dev) defines a collection of nice high-level CDK constructs for Serverless workloads.

It would be very nice to be able to deploy these via Pulumi.

In trying to use them via this Pulumi AWS CDK bridge, I ran into a few problems:

  1. SST constructs don't work with vanilla cdk.Stack and cdk.App - they must be used with sst.Stack and sst.App which derive from the CDK equivalents.
  2. The above is challenging because pulumicdk.Stack also inherits from cdk.Stack, and there is no way to chain these three together currently. I was able to hack around this for at least one usecase, but we'll need to think about whether we can make it possible to use pulumicdk bridge with stacks that must be subclasses of cdk.Stack.
  3. The above is also challenging because currently pulumicdk.Stack creates the cdk.App automatically. We should instead allow users to pass in the App (or at the very least, the App constructor), so that an sst.App can be constructed and used as the app for the Pulumi stack.

I was ultimately able to get this to work:

import * as pulumi from "@pulumi/pulumi"
import * as pulumicdk from "@pulumi/cdk";
import { App, Api, Stack } from "@serverless-stack/resources";

class LambdaStack extends pulumicdk.Stack {
  url: pulumi.Output<string>;
  constructor(id: string, options?: pulumicdk.StackOptions) {
    super(id, options);

    // Needed to workaround the fact that we aren't inheriting from sst.Stack.
    (this as any).defaultFunctionProps = [{}];

    // Create an sst.Api
    const api = new Api(this, "Api", {
      routes: {
        "GET    /notes": "src/list.main",
        "POST   /notes": "src/create.main",
      },
    });
    this.url = this.asOutput(api.url);

    // Finalize the stack and deploy its resources.
    this.synth();
  }
}

// Manually construct an sst.App
const app = new App();
// Workaround the fact that we aren't using sst.Stack, but sst constructs require that they follow a specific 
// naming convention that sst.Stack establishes.
const id = app.logicalPrefixedName('teststack');
const stack = new LambdaStack(id, {
  app,
  props: {
    env: {
      account: "111111111111",
    }
  }
});
export const url = stack.url;
thdxr commented 1 year ago

hey!

cool prototype - we definitely can make this easier. with SST2 a lot of this might get more difficult but we paved the way to not needing sst.App and sst.Stack

if those two dependencies are gone this should "just work" like any other CDK construct right?

lukehoban commented 1 year ago

Thanks @thdxr!

if those two dependencies are gone this should "just work" like any other CDK construct right?

Yes - I would expect so. The only challenges today are that when sst constructs are used from within vanilla cdk.App and cdk.Stack they fail due to assumptions these constructs make that the stack/app they are a part of has certain SST-specific features.

I do think we should be able to address this on the Pulumi bridge layer side as well - in principle there is no reason you shouldn't be able to use sst.Stack and sst.App with our bridge.

BTW - do you have any canonical examples of using SST constructs entirely outside of SST, from within a "normal AWS CDK" stack? Like if I wanted to use SST constructs but without using the sst CLI for workflow? I'd love to try porting a few of those to deploy via Pulumi as an alternative option (both to make sure it's possible, and to compare performance and highlight some of the other benefits - like mixing and matching across other providers, etc.).

corymhall commented 2 months ago

sst v3 (Ion) is now built on Pulumi and uses Pulumi components instead of CDK constructs. Looking into this a little, it looks like the components are not published anywhere so I don't think it is easy to use them.

It looks like the sst cli might download the source code for the components locally so it might be possible to use them in a pulumi app, but it will take some more investigation.