https://serverless-stack.com/ logo
#random
Title
# random
t

thdxr

01/21/2022, 3:24 AM
What would you guys think of an entirely functional api to create stacks:
Copy code
export async function TableStack(props) {
  const table = new sst.Table(props.stack, ...);

  return { table };
}

export async function StackB(props) {
  const { table } = use(TableStack);
  new sst.Function(props.stack, { environment:  { MYTABLE: table } })
}
It would be totally typesafe + support async functions
s

Sam Hulick

01/21/2022, 3:54 AM
this probably comes down to personal preference/coding style, yeah? I know some people are big fans of functional programming. I’m more in the OOP camp.. classes just feel more natural to me
t

thdxr

01/21/2022, 4:00 AM
A little bit of style but it's also nice to return exports simply with type inference. The above is pretty verbose in sst today because you have to be explicit about all the types. Functional approach infers everything, zero types you have to write
Copy code
class TableStack extends sst.Stack {
  public readonly table: sst.Table
  constructor(...) { 
    super(..)
    this.table = new sst.Table(...)
  }
}

class StackB extends sst.Stack {
  constructor(app, props: { table: sst.Table }) {
    super(...)
  
  }
}

const tableStack = new TableStack(app)
new StackB(app, { table: tableStack.table })
functional approach also allows async and we can auto initialize them in the right order for you so you wouldn't need anything in your main outside of setting defaults
s

Sam Hulick

01/21/2022, 5:07 AM
I mean, if it adds more functionality to SST, then I’m all for it 🙂
t

thdxr

01/21/2022, 5:08 AM
we'd probably add this as an experimental syntax
g

Garret Harp

01/21/2022, 10:42 AM
This would be amazing
d

Devin

01/21/2022, 11:52 AM
This is not a game changer for me. However, I would probably switch. Since I no longer use classes on the frontend and consistency is good for my brain.
j

Joe Kendal

01/21/2022, 12:26 PM
Nice
m

Matt Morgan

01/21/2022, 2:17 PM
So async in that
TableStack
gets deployed before
StackB
begins to synth? If not that, then what? CDK is synchronous by design.
(fwiw I already do something similar to this, but not async)
t

thdxr

01/21/2022, 2:27 PM
No they all get synthed first and then deployed. Because CDK is constructor based you can't have async functions, but this is an arbitrary constraint. It's annoying for us in a few places since we can't call esbuild.build() since it returns a promise and I imagine others have other issues like that as well
m

Matt Morgan

01/21/2022, 2:29 PM
I got around that with
execSync
, though if somebody said that's a hack, I wouldn't really disagree. I'd just be wary of anything that might make it non-deterministic. Having the whole thing be synchronous was a design goal of the CDK.
r

Ross Gerbasi

01/21/2022, 4:26 PM
@thdxr would be into this for sure as I tend to work this way in general. Having async stack construction would be nicer then needing to do all async in index and passing values around.
a

Adam Fanello

01/21/2022, 5:49 PM
I'm a fan of classes, even if not OOP it helps organize related functions. The fact that stacks (and constructs) have to do all their work in the constructor makes them essentially just functions though, so I like this simplification.
t

thdxr

01/21/2022, 5:51 PM
@Matt Morgan yeah I don't really know why you'd need async work I just have that one esbuild example where we have to wrap it in execSync. So it's a secondary concern, my primary thing is to make it less verbose for passing things around and get proper typing through inference instead of writing it out
r

Ross Gerbasi

01/21/2022, 5:51 PM
async has been needed for SSM for me.
t

thdxr

01/21/2022, 5:53 PM
Yeah true storing everything in SSM means you don't need to put stuff in your CI environment which is great
r

Ross Gerbasi

01/21/2022, 5:53 PM
yeah, thats the route we are going here, we went with SSM injected into the CF instead of calling it at runtime
do you know if you could perform async operations in the class? for example if the constructor called
this.createStack(scope, id)
and
createStack
was async.
t

thdxr

01/21/2022, 5:55 PM
No you can't
s

Sam Hulick

01/21/2022, 5:56 PM
@Ross Gerbasi what kinds of things are you injecting into the stack from SSM?
r

Ross Gerbasi

01/21/2022, 5:56 PM
Figured, but i am still not sure how it works in
index.ts
How is it that you can have callbacks and promises in your default index handler?? how does it know to wait haha i am very curious
@Sam Hulick secret keys for APIs and tokens and such
SSM -> Stack -> Lambda ENV
t

thdxr

01/21/2022, 5:57 PM
The limitation is coming from JS technically. Constructors in JS have to be synchronous, it's not an overall limitation in CDK. So we just spawn a normal node process to execute
main
and wait for all async work to finish before exiting
s

Sam Hulick

01/21/2022, 5:57 PM
interesting. I’ve been fetching those in the Lambda code at runtime. I figured if I injected them into the stack, changing keys would require a redeploy
t

thdxr

01/21/2022, 5:57 PM
hm ross I don't think that pattern is actually good because your secrets leak in a few places
r

Ross Gerbasi

01/21/2022, 5:58 PM
e understand that
and we understand it requires a deploy
j

Joe Kendal

01/21/2022, 5:58 PM
@Sam Hulick you are doing it the best way I believe
t

thdxr

01/21/2022, 5:58 PM
We're working on making secret management first class in SST so you can just define them and they'll be auto injected into your function (with typing!) and letting you manage them in console
r

Ross Gerbasi

01/21/2022, 5:58 PM
however calling them at runtime adds another delay to the pipeline. Everytime we wanna use that key we need to lookup from SSM first
s

Sam Hulick

01/21/2022, 5:58 PM
I wrote a
getSsmParameter
function that also memoizes the values it fetches. just cache it so it’s there for any warm starts
r

Ross Gerbasi

01/21/2022, 5:59 PM
we would rather secure our CI and be cautious with our CF security VS have every customer pay extra per request
s

Sam Hulick

01/21/2022, 5:59 PM
the delay is microscopic
r

Ross Gerbasi

01/21/2022, 5:59 PM
yeah caching for warm start is an always regardlkess
but we have seen sporadic SSM delays seconds even. Simply not worth it
we will just be better with our stack security
we will likely be using github acttions to deploy our code, if someone manages to get in there and read our CF files we just have plans in place to re-roll keys.
t

thdxr

01/21/2022, 6:01 PM
I do wish AWS would make a managed way to do this
They can optimize it so everything is injected when the lambda is starting and it's as fast as it can be
r

Ross Gerbasi

01/21/2022, 6:01 PM
I agree, Another option is to use cloud formations dynamic SMM references.
We are considering moving to something like this, but again we have weighed our security concerns and are ok with the current path right now
a

Adam Fanello

01/21/2022, 6:02 PM
Might help my use case? I have an sst.Script (custom resource) just to upload resulting files with endpoints and OpenAPI for clients to access. Would be nice if each API stack could directly upload these files.
r

Ross Gerbasi

01/21/2022, 6:04 PM
@thdxr I wonder if SST could help with this. injecting
{{resolve}}
into ENVS so we are never passing alot plaintext secrets
Something like they are doing here, https://stackoverflow.com/a/56040646
t

thdxr

01/21/2022, 6:05 PM
That's sort of what the solution we're working on does.
well no we still choose to resolve it at runtime because we don't want to expose it in the lambda function's env variables
r

Ross Gerbasi

01/21/2022, 6:05 PM
That would likely be ideal, no runtime cost + secure secrets all the way down.
t

thdxr

01/21/2022, 6:05 PM
those are readable in a lot of places
We could probably add an option to disable runtime resolving
r

Ross Gerbasi

01/21/2022, 6:06 PM
I am not sure I am as worried about ENV variables though. They are encrypted at rest anyway
If someone can get into AWS to see them, they can likely cause more damage. I guess you could make the case maybe a dev has access to a lambda but not SSM.
t

thdxr

01/21/2022, 6:09 PM
Yeah I'm not opinionated on this, depending on your setup you might choose to be more practical. We can probably make your setup more built in
r

Ross Gerbasi

01/21/2022, 6:10 PM
That would be great 🙂 Obviously my workflow doesnt work for folks that are rotating keys. There is likely a mix here folks could use. some "static" keys and some dynamic ones.
c

Carlos Daniel

01/21/2022, 6:29 PM
that’d be great - specially because I’ve been ignoring linter errors when creating stacks with classes that wouldn’t happen if we had this funcional approach
a

Adam Fanello

01/21/2022, 7:36 PM
Just ran across this @Ross Gerbasi Useful?
r

Ross Gerbasi

01/21/2022, 7:41 PM
@Adam Fanello very interesting, i will try this out. Might be a bit rough with JSON in a secret, but i guess we could just parse it in the Fn.... gonna try this for sure. thanks!
2 Views