Seth Geoghegan
12/16/2021, 9:35 PMSeth Geoghegan
12/16/2021, 9:36 PMSeth Geoghegan
12/16/2021, 9:38 PM// only provision an RDS database for specific stages
if (['prod','stage'].includes(scope.stage)){
// generate a secret to be used as credentials for our database
const databaseCredentialsSecret = new secretsManager.Secret(...)
new ssm.StringParameter(this, 'DBCredentialsArn', {
parameterName: `${this.stage}-credentials-arn`,
stringValue: databaseCredentialsSecret.secretArn,
});
const rdsConfig = {...}
new rds.DatabaseInstance(this, `${this.stage}-instance`, rdsConfig);
}
// provision things for all stages here...
Simon Reilly
12/16/2021, 9:39 PMbin/index.ts
Seth Geoghegan
12/16/2021, 9:40 PMSeth Geoghegan
12/16/2021, 9:42 PMSeth Geoghegan
12/16/2021, 9:43 PMSimon Reilly
12/16/2021, 9:43 PMCREATE DATABASE <service name>_<pr number>
Seth Geoghegan
12/16/2021, 9:43 PMSimon Reilly
12/16/2021, 9:43 PMSeth Geoghegan
12/16/2021, 9:44 PMSeth Geoghegan
12/16/2021, 9:44 PMSimon Reilly
12/16/2021, 9:44 PMSimon Reilly
12/16/2021, 9:45 PMSeth Geoghegan
12/16/2021, 9:45 PMSeth Geoghegan
12/16/2021, 9:46 PMSimon Reilly
12/16/2021, 9:47 PMSeth Geoghegan
12/16/2021, 9:48 PMSeth Geoghegan
12/16/2021, 9:51 PMSimon Reilly
12/16/2021, 9:52 PMJay
Seth Geoghegan
12/29/2021, 2:57 PMsst start
. I feel like I'm missing a step, like looking up a database by ARN or ??
// index.ts
export default function main(app: <http://sst.App|sst.App>): void {
let database = undefined;
if (process.env.IS_LOCAL){
// create a database for development purposes
const devDbStack = new DbStack(app,`my-dev-db-stack`,{...});
database = devDbStack.database;
}
const myStack = new MyServiceStack(app, "my-service-stack",{
database: database
});
}
// MyServiceStack.ts
export default class MyServiceStack extends sst.Stack {
public readonly database: rds.DatabaseInstance;
constructor(scope: <http://sst.App|sst.App>, id: string, props: MyServiceProps) {
super(scope, id);
if (!props.database){
// create a database if not provided
const dbStack = new DbStack(scope,`my-db-stack`,{...});
this.database = dbStack.database
}else{
this.database = props.database
}
}
}
Simon Reilly
12/29/2021, 6:11 PMSeth Geoghegan
12/29/2021, 6:29 PMsst start --stage <username>
when developing locally. I want that command to create a long lived dev
RDS instance, or re-use the existing dev
RDS if it already exists. I will be using the SST Script construct to create a database unique to the user once the stack is deployed. I mostly have the SST Script construct working properly. However, I'm not sure I understand the different ways to conditionally deploy an RDS dev instance while also supporting other stages like prod/staging/test/etc.Seth Geoghegan
12/29/2021, 6:32 PMSimon Reilly
12/29/2021, 10:23 PMimport { DatabaseCluster } from '@aws-cdk/aws-rds';
import * as sst from '@serverless-stack/resources';
import ServiceA from './service-a';
import ServiceB from './service-b';
import { ServiceDev } from './service-dev';
export interface MultiStackProps extends sst.StackProps {
cluster: DatabaseCluster | null;
}
const DEFAULT_DEV_PROPS = { cluster: null };
const FULL_ENVIRONMENT_STAGES = ['staging', 'prod'];
export default function main(app: <http://sst.App|sst.App>): void {
// Set default runtime for all functions
app.setDefaultFunctionProps({
runtime: 'nodejs14.x',
});
// Conditionally deploy the dev stack when not pointing at the prod
// environment.
//
// You might refactor this condition to be an AWS account number etc.
const { cluster } = FULL_ENVIRONMENT_STAGES.includes(app.stage)
? DEFAULT_DEV_PROPS
: new ServiceDev(app, 'dev-stack', {
// This stack becomes static, deployed only once per AWS account
// and subsequent stages do updates
stackName: 'dev-stack',
});
// Dependnency inject the cluster into the service A
new ServiceA(app, 'ServiceAStack', {
cluster,
});
// Dependnency inject the cluster into the service B
new ServiceB(app, 'ServiceBStack', {
cluster,
});
}
Though SST makes this a no-go, because it requires all stacks to contain the stage name.
@thdxr and @Frank I guess this is deliberate to encourage good naming conventions, but it means the solution here requires 2 separate sst apps, which wouldn't play well with each other in a monorepo to my knowledge? Its potentially highlighting a smaell, that if the shared dev rds is managed as a different lifecycle, then it should live in a separate application. I do however, like the simplicity of just being allowed to name stacks whatever I want, does it creating some breaking effects?
Error: Stack "dev-stack" is not parameterized with the stage name. The stack name needs to either start with "$stage-", end in "-$stage", or contain the stage name "-$stage-".
Simon Reilly
12/29/2021, 10:29 PMSimon Reilly
12/29/2021, 10:31 PMdev-stack
and someone runs yarn sst deploy --stage pr-1234
then stack dev-stack
would get diff'd and updated, instead of deployed. Its not a nice pattern, but because sst is top down its maybe one of the few lifecycling hacks that would be possibleSeth Geoghegan
12/29/2021, 10:33 PMSimon Reilly
12/29/2021, 10:37 PM1234-service-a
etc. I like the idea of a readily available RDS instance, but because you don't want someone to run yarn sst destroy --stage <pr-number>
and take down an instance shared between a whole team, it could be wise to manage the RDS outside the sst app, as a base layer infrastructure; and use imports as you suggested earlier.Seth Geoghegan
12/29/2021, 10:46 PMSimon Reilly
12/29/2021, 10:59 PM