Skip to main content

Opinionated CDK Project “Framework”

Project description



Alma CDK Project

npm i -D @alma-cdk/project

Opinionated CDK “framework” with constructs & utilities for:

  • deploying multiple environments to multiple accounts (with many-to-many relationship)

  • managing account configuration through standardized props (no more random config files)

  • querying account and/or environment specific information within your CDK code

  • enabling dynamic & short-lived “feature-environments”

  • enabling well-defined tagging

  • providing structure & common conventions to CDK projects

  • choosing the target account & environment by passing in runtime context:

    npx cdk deploy -c account=dev -c environment=feature/abc-123
    

    ... which means you don't need to define all the possibile environments ahead of time!


Account Strategies

Depending on the use case, you may choose a configuration between 1-3 AWS accounts with the following environments:

  1. Shared account (shared):

    default-multi

  2. Multi-account (dev+prod)– RECOMMENDED:

    default-multi


  1. Multi-account (dev+preprod+prod):

    default-multi


Getting Started

Steps required to define a environmental project resources; At first, it might seem complex but once you get into the habbit of defining your projects this way it starts to make sense:

  1. Choose your Account Strategy

  2. Initialize a new Project instead of cdk.App:

    // bin/app.ts
    import { Project, AccountStrategy } from '@alma-cdk/project';
    
    const project = new Project({
      // Basic info, you could also read these from package.json if you want
      name: 'my-cool-project',
      author: {
        organization: 'Acme Corp',
        name: 'Mad Scientists',
        email: 'mad.scientists@acme.example.com',
      },
    
      // If not set, defaults to one of: $CDK_DEFAULT_REGION, $AWS_REGION or us-east-1
      defaultRegion: 'eu-west-1',
    
      // Configures the project to use 2 AWS accounts (recommended)
      accounts: AccountStrategy.two({
        dev: {
          id: '111111111111',
          config: {
            // whatever you want here as [string]: any
            baseDomain: 'example.net',
          },
        },
        prod: {
          id: '222222222222',
          config: {
            // whatever you want here as [string]: any
            baseDomain: 'example.com',
          },
        },
      }),
    })
    
  3. Define a stack which extends SmartStack with resources:

    // lib/my-stack.ts
    import { Construct } from 'constructs';
    import { StackProps, RemovalPolicy } from 'aws-cdk-lib';
    import { SmartStack, Name, UrlName, PathName, EC } from '@alma-cdk/project';
    
    export class MyStack extends SmartStack {
      constructor(scope: Construct, id: string, props: StackProps) {
        super(scope, id, props);
    
        new dynamodb.Table(this, 'Table', {
          removalPolicy: EC.isStable(this) ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY,
    
          tableName: Name.it(this, 'MyTable'),
          partitionKey: {
            type: dynamodb.AttributeType.STRING,
            name: 'pk',
          },
          // StagingMyTable
        });
    
        new events.EventBus(this, 'EventBus', {
          eventBusName: Name.withProject(this, 'MyEventBus'),
          // MyCoolProjectStagingMyEventBus
        });
    
        new s3.Bucket(this, 'Bucket', {
    
          removalPolicy: EC.isStable(this) ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY,
          autoDeleteObjects: EC.isStable(this) ? false : true,
    
          bucketName: UrlName.globally(this, 'MyBucket'),
          // acme-corp-my-cool-project-feature-foo-bar-my-bucket
        });
    
        new ssm.StringParameter(this, 'Parameter', {
          stringValue: 'Foo',
          tier: ssm.ParameterTier.ADVANCED,
          parameterName: PathName.withProject(this, 'MyNamespace/MyParameter'),
          // /MyCoolProject/Staging/MyNamespace/MyParameter
        });
      }
    }
    
  4. Define a new environmental which extends EnvironmentWrapper and initialize all your environmental SmartStack stacks within:

    // lib/environment.ts
    import { Construct } from 'constructs';
    import { EnvironmentWrapper } from '@alma-cdk/project';
    import { MyStack } from './my-stack';
    
    export class Environment extends EnvironmentWrapper {
      constructor(scope: Construct) {
        super(scope);
        new MyStack(this, 'MyStack', { description: 'This is required' });
      }
    }
    

    Resulting Stack properties (given environment=staging):

    Property Example value
    stackName "MyCoolProject-Environment-Staging-MyExampleStack"
    terminationProtection true
    env.account "111111111111"
    env.region "eu-west-1"

    Resulting Tags for the Stack and its resources (given environment=staging):

    Property Example value
    Account dev
    Environment staging
    Project my-cool-project
    Author Mad Scientists
    Organization Acme Corp
    Contact mad.scientists@acme.example.com
  5. Finally initialize the environment with the Project scope:

    // bin/app.ts
    import { Project, Accounts } from '@alma-cdk/project';
    import { Environment } from '../lib/environment';
    
    const project = new Project({/* removed for brevity, see step 1 */})
    
    new Environment(project);
    

Documentation

See detailed documentation for specific classes & methods at constructs.dev.

Generally speaking you would be most interested in the following:

  • Project
  • AccountStrategy
  • SmartStack
  • AccountWrapper & EnvironmentWrapper
  • AccountContext (AC)
  • EnvironmentContext (EC)
  • Name / UrlName / PathName

Migration

v0 to v1

Tagging behavior

Due to a bug in v0, the Contact and Organization tags were NOT applied as they should have. This means that by default, upgrading from v0→v1 introduces CloudFormation diff. Basically adding the Contact and Organization tags to all resources. This should be safe operation, but we allow disabling it via a feature flag (note that Contact and Organization tags will most likely be enforced in future v2).

// cdk.json
{
  "context": {
    // existing context keys
+   "@alma-cdk/project:compatibility:v0:tags": true
  },
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

alma_cdk_project-1.0.0b10.tar.gz (865.1 kB view details)

Uploaded Source

Built Distribution

alma_cdk.project-1.0.0b10-py3-none-any.whl (863.5 kB view details)

Uploaded Python 3

File details

Details for the file alma_cdk_project-1.0.0b10.tar.gz.

File metadata

  • Download URL: alma_cdk_project-1.0.0b10.tar.gz
  • Upload date:
  • Size: 865.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for alma_cdk_project-1.0.0b10.tar.gz
Algorithm Hash digest
SHA256 77464983df1098d36d79c34b44191c35c55b3dc2ea47cb9c67cda8bbb6bdb5fa
MD5 98cb157ddeb92302fb491b7db8fe412d
BLAKE2b-256 6746ab14f8cd44ebdd0fa83aa660c2c71c493ae151222f9071e6bd676e91a180

See more details on using hashes here.

File details

Details for the file alma_cdk.project-1.0.0b10-py3-none-any.whl.

File metadata

File hashes

Hashes for alma_cdk.project-1.0.0b10-py3-none-any.whl
Algorithm Hash digest
SHA256 c8fd45e90c8a9c246ee01d4e349ecdfb5bf91cb1490e34eee605307b7bfaff11
MD5 4b11f8cb8c9d35761079b6658ed2690a
BLAKE2b-256 adef5c8969c604240f36d7b91b5a7823ed46f60c4798b8b7044ac6679ad51dc4

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page