Git Product home page Git Product logo

cdk-ssm-document's Introduction

CDK SSM Document

Source Test GitHub Docs

npm package PyPI package

Downloads npm PyPI

AWS CDK L3 construct for managing SSM Documents.

DEPRECATED! CloudFormation now natively supports document updates. CDK supports this since 2.29.0. This package will no longer be maintained.

CloudFormation's support for SSM Documents currently is lacking updating functionality. Instead of updating a document, CFN will replace it. The old document is destroyed and a new one is created with a different name. This is problematic because:

  • When names potentially change, you cannot directly reference a document
  • Old versions are permanently lost

This construct provides document support in a way you'd expect it:

  • Changes on documents will cerate new versions
  • Versions cannot be deleted

Installation

This package has peer dependencies, which need to be installed along in the expected version.

For TypeScript/NodeJS, add these to your dependencies in package.json. For Python, add these to your requirements.txt:

  • cdk-ssm-document
  • aws-cdk-lib (^2.0.0)
  • constructs (^10.0.0)

CDK compatibility

  • Version 3.x is compatible with the CDK v2.
  • Version 2.x is compatible with the CDK v1. There won't be regular updates for this.

Usage

Creating a document from a YAML or JSON file

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Document } from 'cdk-ssm-document';
import fs = require('fs');
import path = require('path');

export class TestStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    const file = path.join(__dirname, '../documents/hello-world.yml');
    new Document(this, 'SSM-Document-HelloWorld', {
      name: 'HelloWorld',
      content: fs.readFileSync(file).toString(),
    });
  }
}

Creating a document via inline definition

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Document } from 'cdk-ssm-document';
import fs = require('fs');
import path = require('path');

export class TestStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    new Document(this, 'SSM-Document-HelloWorld', {
      name: 'HelloWorld',
      content: {
        schemaVersion: '2.2',
        description: 'Echo Hello World!',
        parameters: {
          text: {
            default: 'Hello World!',
            description: 'Text to echo',
            type: 'String',
          },
        },
        mainSteps: [
          {
            name: 'echo',
            action: 'aws:runShellScript',
            inputs: {
              runCommand: ['echo "{{text}}"'],
            },
            precondition: {
              StringEquals: ['platformType', 'Linux'],
            },
          },
        ],
      },
    });
  }
}

Deploy all YAML/JSON files from a directory

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Document } from 'cdk-ssm-document';
import fs = require('fs');
import path = require('path');

export class TestStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) {
    super(scope, id, props);

    const dir = path.join(__dirname, '../documents');
    const files = fs.readdirSync(dir);

    for (const i in files) {
      const name = files[i];
      const shortName = name.split('.').slice(0, -1).join('.'); // removes file extension
      const file = `${dir}/${name}`;

      new Document(this, `SSM-Document-${shortName}`, {
        name: shortName,
        content: fs.readFileSync(file).toString(),
      });
    }
  }
}

Creating a distributor package

import { aws_iam, aws_s3, aws_s3_deployment, Stack, StackProps } from 'aws-cdk-lib';
import { Document } from 'cdk-ssm-document';
import { Construct } from 'constructs';
import fs = require('fs');
import path = require('path');

export class TestStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    const bucketName = `${Stack.of(this).account}-cdk-ssm-document-storage`;
    const bucket = new aws_s3.Bucket(this, 'DistributorPackages', {
      bucketName: bucketName,
    });
    const packageDeploy = new aws_s3_deployment.BucketDeployment(
      this,
      'distribution-packages',
      {
        sources: [aws_s3_deployment.Source.asset('../location/to/distributor/packages')],
        destinationBucket: bucket,
      }
    );

    const file = path.join(
      __dirname,
      '../location/to/distributor/packages/v1/manifest.json'
    );
    const doc = new Document(this, `SSM-Distribution-Package`, {
      documentType: 'Package',
      name: 'Test-Distribution-Package',
      content: fs.readFileSync(file).toString(),
      versionName: '1.0-Custom-Name',
      attachments: [{ key: 'SourceUrl', values: [`s3://${bucketName}/v1`] }],
    });

    /**
     * The owner/creator of the document must have read access to the
     * s3 files that make up a distribution. Since that is the lambda in this
     * case we must give it `GetObject` permissions before they will can become `Active`.
     *
     * If access is not granted to the role that created the document you may see
     * an error like the following :
     *
     * ```
     * Permanent download error: Source URL 's3://cdk-ssm-document-storage/v1/package.zip' reported:
     * Access Denied (Service: Amazon S3; Status Code: 403;
     * Error Code: AccessDenied; Request  *ID:DES1XEHZTJ9R; S3 Extended Request ID:
     * A+u8sTGQ6bZpAwl2eXDLq4KTkoeYyQR2XEV+I=; Proxy: null)
     * ```
     */
    doc.lambda.role?.addToPrincipalPolicy(
      new aws_iam.PolicyStatement({
        actions: ['s3:GetObject'],
        resources: [`${bucket.arnForObjects('*')}`],
      })
    );
    doc.node.addDependency(packageDeploy);
  }
}

Deploying many documents in a single stack

When you want to create multiple documents in the same stack, you will quickly exceed the SSM API rate limit. One ugly but working solution for this is to ensure that only a single document is created/updated at a time by adding resource dependencies. When document C depends on document B and B depends on document A, the documents will be created/updated in that order.

const docA = new Document(this, 'doc-A', {...})
const docB = new Document(this, 'doc-B', {...})
const docC = new Document(this, 'doc-C', {...})

docC.node.addDependency(docB);
docB.node.addDependency(docA);

When looping through a directory of documents it could look like this:

var last: Document | undefined = undefined;
for (const i in files) {
  const doc = new Document(this, `SSM-Document-${shortName}`, {...});
  if (typeof last !== 'undefined') {
    last.node.addDependency(doc);
  }
  last = doc;
}

Using the Lambda as a custom resource in CloudFormation - without CDK

If you're still not convinced to use the AWS CDK, you can still use the Lambda as a custom resource in your CFN template. Here is how:

  1. Create a zip file for the Lambda:

    To create a zip from the Lambda source run:

    lambda/build

    This will generate the file lambda/code.zip.

  2. Upload the Lambda function:

    Upload this zip file to an S3 bucket via cli, Console or however you like.

    Example via cli:

    aws s3 cp lambda/code.zip s3://example-bucket/code.zip
  3. Deploy a CloudFormation stack utilizing the zip as a custom resource provider:

    Example CloudFormation template:

    ---
    AWSTemplateFormatVersion: "2010-09-09"
    Resources:
      SSMDocExecutionRole:
        Type: AWS::IAM::Role
        Properties:
          RoleName: CFN-Resource-Custom-SSM-Document
          AssumeRolePolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Principal:
                  Service: lambda.amazonaws.com
                Action: sts:AssumeRole
          ManagedPolicyArns:
            - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
            - Ref: SSMDocExecutionPolicy
    
      SSMDocExecutionPolicy:
        Type: AWS::IAM::ManagedPolicy
        Properties:
          ManagedPolicyName: CFN-Resource-Custom-SSM-Document
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - ssm:ListDocuments
                  - ssm:ListTagsForResource
                Resource: "*"
              - Effect: Allow
                Action:
                  - ssm:CreateDocument
                  - ssm:AddTagsToResource
                Resource: "*"
                Condition:
                  StringEquals:
                    aws:RequestTag/CreatedByCfnCustomResource: CFN::Resource::Custom::SSM-Document
              - Effect: Allow
                Action:
                  - ssm:DeleteDocument
                  - ssm:DescribeDocument
                  - ssm:GetDocument
                  - ssm:ListDocumentVersions
                  - ssm:ModifyDocumentPermission
                  - ssm:UpdateDocument
                  - ssm:UpdateDocumentDefaultVersion
                  - ssm:AddTagsToResource
                  - ssm:RemoveTagsFromResource
                Resource: "*"
                Condition:
                  StringEquals:
                    aws:ResourceTag/CreatedByCfnCustomResource: CFN::Resource::Custom::SSM-Document
    
      SSMDocFunction:
        Type: AWS::Lambda::Function
        Properties:
          FunctionName: CFN-Resource-Custom-SSM-Document-Manager
          Code:
            S3Bucket: example-bucket
            S3Key: code.zip
          Handler: index.handler
          Runtime: nodejs10.x
          Timeout: 3
          Role: !GetAtt SSMDocExecutionRole.Arn
    
      MyDocument:
        Type: Custom::SSM-Document
        Properties:
          Name: MyDocument
          ServiceToken: !GetAtt SSMDocFunction.Arn
          StackName: !Ref AWS::StackName
          UpdateDefaultVersion: true # default: true
          Content:
            schemaVersion: "2.2"
            description: Echo Hello World!
            parameters:
              text:
                type: String
                description: Text to echo
                default: Hello World!
            mainSteps:
              - name: echo
                action: aws:runShellScript
                inputs:
                  runCommand:
                    - echo "{{text}}"
                precondition:
                  StringEquals:
                    - platformType
                    - Linux
          DocumentType: Command # default: Command
          TargetType: / # default: /
          Tags:
            CreatedByCfnCustomResource: CFN::Resource::Custom::SSM-Document # required, see above policy conditions

cdk-ssm-document's People

Contributors

actions-user avatar jeffsideddie avatar udondan avatar zendern avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

cdk-ssm-document's Issues

Rollback can fail due to failed Document deletion

While instantiating a stack for the first time, my SSM document had an error in it that wasn't identified during the pre-deploy checks. During rollback, the Lambda function tried to delete the (non-existent) document anyway, and failed.

The error message below suggests that the IAM policy forbade it -- most likely due to the Condition key in the policy -- but even if the Condition key wasn't there, the DeleteDocument call probably would have failed anyway because the document failed to create in the first place.

Received response status [FAILED] from custom resource. Message returned: User: arn:aws:sts::xxxxxxxxx:assumed-role/xxxxxxxxxxxStack-CFN-Resource-Custom-SSM-Document/xxxxxxxxxxxxxxBuilderStack-CFN-Resource-Custom-SSM-Document is not authorized to perform: ssm:DeleteDocument on
resource: arn:aws:ssm:us-west-2:xxxxxxxxx:document/xxxxxxx because no identity-based policy allows the ssm:DeleteDocument action | Full error in CloudWatch 2022/03/24/[$LATEST]xxxxxxxxxxxxxx (RequestId:xxxxxxxxxxxx)

Cannot use inline definition with python

Issue:

When trying to use python with an inline definition it fails with the following message.

1:41:57 PM | CREATE_FAILED        | Custom::SSM-Document    | SSMDocumentHelloWorldE1940275
Received response status [FAILED] from custom resource. Message returned: Missing "action" in step detail. at Line: 1, Column:
166 | Full error in CloudWatch 2022/02/06/[$LATEST]903dbd363cb440a19d79c087dc5fac00 (RequestId: 4155a91d-ee94-4920-b010-d95af0
861ea1)

Assumption of what is happening:

Typescript definition for mainSteps is as follows :

/**
 * Steps include one or more actions, an optional precondition, a unique name of the action, and inputs (parameters) for those actions.
 *
 * For more information about documents, including information about creating documents and the differences between schema versions, see https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-plugins.html
 */
export interface DocumentMainStep {
  [key: string]: any;
}

This does not translate into anything from jsii into python. Below is the generated python code.

@jsii.data_type(
    jsii_type="cdk-ssm-document.DocumentMainStep",
    jsii_struct_bases=[],
    name_mapping={},
)
class DocumentMainStep:
    def __init__(self) -> None:
        '''Steps include one or more actions, an optional precondition, a unique name of the action, and inputs (parameters) for those actions.

        For more information about documents, including information about creating documents and the differences between schema versions, see https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-plugins.html
        '''
        self._values: typing.Dict[str, typing.Any] = {}

    def __eq__(self, rhs: typing.Any) -> builtins.bool:
        return isinstance(rhs, self.__class__) and rhs._values == self._values

    def __ne__(self, rhs: typing.Any) -> builtins.bool:
        return not (rhs == self)

    def __repr__(self) -> str:
        return "DocumentMainStep(%s)" % ", ".join(
            k + "=" + repr(v) for k, v in self._values.items()
        )

Sample code:

from aws_cdk import (
    Stack,
)
import json
from constructs import Construct
from cdk_ssm_document import DocumentContent, DocumentParameter, DocumentMainStep
import aws_cdk as cdk
from constructs import Construct
from cdk_ssm_document import Document


class DoingThingsStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        Document(
            self,
            "SSM-Document-HelloWorld",
            name="HelloWorld",
            # content=json.dumps(
            #     dict(
            #         schemaVersion="2.2",
            #         description="Echo Hello World!",
            #         parameters={
            #             "text": dict(
            #                 default="Hello World!",
            #                 description="Text to echo",
            #                 type="String",
            #             )
            #         },
            #         mainSteps=[
            #             {
            #                 "name": "echo",
            #                 "action": "aws:runShellScript",
            #                 "inputs": {
            #                     "runCommand": ['echo "THIS WORKS {{text}}"'],
            #                 },
            #                 "precondition": {"StringEquals": ["platformType", "Linux"]},
            #             }
            #         ],
            #     )
            # ),
            content=DocumentContent(
                schema_version="2.2",
                description="Echo Hello World!",
                parameters={
                    "text": DocumentParameter(
                        default="Hello World!",
                        description="Text to echo",
                        type="String",
                    )
                },
                main_steps=[
                    {
                        "name": "echo",
                        "action": "aws:runShellScript",
                        "inputs": {"run_command": ['echo "DOESNT WORK {{text}}"']},
                        "precondition": {"StringEquals": ["platformType", "Linux"]},
                    }
                ],
            ),
        )

Commented out version works but its cheating in that it's just building a string and passing it to content which will take the json/yaml and turn it into an object. Which I suspect works b/c the yaml -> object conversion will just set anything on the internal _values property.

Possible solution

Instead of using a dynamic key/value pair at a minimum have the interface outline the top level property keys. Would look something like this. All would be set as optional since mainStep varies depending on the document/automation/command you are building out.

We would also leave the [key: string]: any; as it should allow it to also contain any other property that is needed but we can make the lives of the library users nicer with some auto complete and well make python just work :)

export interface DocumentMainStep {
  readonly name?: string;
  readonly action?: string;
  readonly inputs?: any;
  readonly precondition?: any;
  readonly outputs?: any;
  readonly maxAttempts?: number;
  readonly timeoutSeconds?: number;
  readonly isCritical?: boolean;
  readonly isEnd?: boolean;
  readonly onCancel?: string;
  readonly onFailure?: string;
  readonly nextStep?: string;
  [key: string]: any;
}

inputs, precondition and outputs are all marked as any and are just json blobs that can differ in may ways. inputs especially.

Pulled these properties from a few places

BUG: Package does not work with latest version of `aws-cdk-lib`

When I try to run cdk synth or cdk deploy, I get the following error.

> "cdk synth"

/Users/tim/workplace/ma-mono/common/temp/node_modules/.pnpm/[email protected]_ff8e2a29703a7cffac9ed3bbb4473395/node_modules/cdk-iam-floyd/lib/shared/policy-statement/6-principals.js:29
        this.principals = {};
                        ^

TypeError: Cannot set property principals of [object Object] which has only a getter
    at new PolicyStatementWithPrincipal (/Users/tim/workplace/ma-mono/common/temp/node_modules/.pnpm/[email protected]_ff8e2a29703a7cffac9ed3bbb4473395/node_modules/cdk-iam-floyd/lib/shared/policy-statement/6-principals.js:29:25)

This is what my package.json looks like

 "dependencies": {
    "aws-cdk-lib": "^2.0.0",
    "constructs": "^10.0.0",
    "cdk-ssm-document": "^3.1.0",
    "cdk-iam-floyd": "^0.300.0",
  },

This is what my code looks like

  private _createSMDocuments(): void {
  const cfnDoc = new Document(this._stack, 'SSMDoc', {
    name: `${this._stack.stackName}-SSMDoc`,
    documentType: 'Automation',
    content: fs
      .readFileSync(join(__dirname, `../../src/SSM.yaml`), 'utf8')
      .toString()
  });
}

If I set aws-cdk-lib to be explicitly 2.0.0, I no longer get the error.

 "dependencies": {
    "aws-cdk-lib": "2.0.0",
    "constructs": "^10.0.0",
    "cdk-ssm-document": "^3.1.0",
    "cdk-iam-floyd": "^0.300.0",
  },

Help building Lambda

Can you give some more instructions on the prerequisites required to run the lambda/build script for someone with no dev environment?

Add support for Document Attachments

Problem statement :

Cannot create a SSM Document that can be used with AWS Distributor since attachments cannot be added to the definition.

See an example of what the SSM Document looks like for a Distributor package using Cloudformation:

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-document.html#aws-resource-ssm-document--examples--Create_a__Distributor_package

Solution:

Happy to create a PR to implement this.

Problem with BooleanEquals

Similar issue to #14, this is valid JSON for a choice step assuming that DoSomething was defined as Boolean input parameter:

             {
                "name": "DoSomethingCheck",
                "action": "aws:branch",
                "inputs": {
                   "Choices": [
                      {
                         "NextStep": "DoSomething",
                         "Variable": "{{DoSomething}}",
                         "BooleanEquals": true
                      },
                      {
                         "NextStep": "DoSomethingElse",
                         "Variable": "{{DoSomething}}",
                         "BooleanEquals": false
                      }
                   ]
                }
             },

This fails for the same reason: "Failed to update resource. Input true is of type String, but expected type is Boolean."

Add some logging to the custom resource lambda

Feature Request

Add some logging of the event that is sent to the lambda as well as the request objects that are sent to the api calls.

Reason

When debugging a misconfigured json blob elements mainSteps and its' children there are not enough details to understand the failure.

Current details are only this:

022-02-07T14:07:42.451Z	c7bcb752-d1ba-423c-a527-4d4d64cf1150	ERROR	InvalidDocumentContent: JSON not well-formed. at Line: 1, Column: 610    
at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:52:27)    
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)    
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)    
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:688:14)    
at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)    
at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)    
at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10    
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)    
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:690:12)    
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {  code: 'InvalidDocumentContent',  time: 2022-02-07T14:07:42.448Z,  requestId: 'b35ffedf-86ad-4e56-b889-dfe75f290c79',  statusCode: 400,  retryable: false,  retryDelay: 61.14163968992787} InvalidDocumentContent: JSON not well-formed. at Line: 1, Column: 610    
at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:52:27)    
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)    
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)    
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:688:14)   
at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)    
at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)    
at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10   
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)    
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:690:12)    
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:116:18) 

Cannot find module 'js-yaml'

For Python import of the Document throws next exception:

PS C:\Users\XXX\cdk-ssm> cdk ls
jsii.errors.JavaScriptError:
internal/modules/cjs/loader.js:638
throw err;
^

Error: Cannot find module 'js-yaml'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object. (C:\Users\XXX\AppData\Local\Temp\jsii-kernel-w7ZNRI\node_modules\cdk-ssm-document\lib\index.js:11:14)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Module._load (internal/modules/cjs/loader.js:585:3)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "C:\Users\XXX\cdk-ssm\app.py", line 6, in
from cdk_ssm.cdk_ssm_stack import CdkSsmStack
File "C:\Users\XXX\cdk-ssm\cdk_ssm\cdk_ssm_stack.py", line 5, in
from cdk_ssm_document import Document
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\cdk_ssm_document_init_.py", line 297, in
from .jsii import *
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\cdk_ssm_document_jsii_init
.py", line 18, in
jsii_assembly = jsii.JSIIAssembly.load(
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\jsii_runtime.py", line 43, in load
kernel.load(assembly.name, assembly.version, os.fspath(assembly_path))
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\jsii_kernel_init
.py", line 254, in load
self.provider.load(LoadRequest(name=name, version=version, tarball=tarball))
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\jsii_kernel\providers\process.py", line 338, in load
return self._process.send(request, LoadResponse)
File "C:\Users\XXX\AppData\Local\Programs\Python\Python39\lib\site-packages\jsii_kernel\providers\process.py", line 326, in send
raise JSIIError(resp.error) from JavaScriptError(resp.stack)
jsii.errors.JSIIError: Cannot find module 'js-yaml'


PS C:\Users\XXX\cdk-ssm> npm list -g
C:\Users\XXX\AppData\Roaming\npm
+-- [email protected]
| +-- @aws-cdk/[email protected]
| | +-- [email protected]
| | -- [email protected] deduped | +-- @aws-cdk/[email protected] | | +-- @aws-cdk/[email protected] | | | -- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | -- [email protected] | | +-- [email protected] deduped | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] | | | +-- [email protected] | | | -- [email protected] deduped
| | -- [email protected] | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | +-- [email protected] deduped | | -- [email protected] deduped
| +-- @aws-cdk/[email protected]
| | +-- @aws-cdk/[email protected] deduped
| | -- [email protected] deduped | +-- @aws-cdk/[email protected] | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] deduped | | | +-- [email protected] | | | | -- [email protected]
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | +-- [email protected] deduped
| | | | -- [email protected] deduped | | | +-- [email protected] | | | +-- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] | | | +-- [email protected] | | | +-- [email protected] | | | -- [email protected]
| | | +-- [email protected]
| | | +-- [email protected] deduped
| | | +-- [email protected] deduped
| | | +-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | | -- [email protected] deduped | | | -- [email protected] deduped
| | +-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | | +-- [email protected] deduped
| | | +-- [email protected]
| | | | -- [email protected] | | | -- [email protected]
| | +-- [email protected]
| | | -- [email protected] deduped | | +-- [email protected] | | | +-- [email protected] | | | | +-- [email protected] | | | | | +-- [email protected] deduped | | | | | -- [email protected]
| | | | +-- [email protected] deduped
| | | | -- [email protected] deduped | | | +-- [email protected] | | | | -- [email protected] deduped
| | | +-- [email protected]
| | | +-- [email protected] deduped
| | | -- [email protected] deduped | | -- [email protected]
| | +-- [email protected] deduped
| | +-- [email protected]
| | | +-- [email protected] deduped
| | | +-- [email protected]
| | | | +-- [email protected]
| | | | | +-- [email protected]
| | | | | -- [email protected] | | | | -- [email protected] deduped
| | | +-- [email protected] deduped
| | | -- [email protected] deduped | | -- [email protected] deduped
| +-- [email protected]
| | +-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | -- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] | | | -- [email protected] deduped
| | +-- [email protected]
| | -- [email protected] | | +-- [email protected] | | -- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- @aws-cdk/[email protected] deduped
| | +-- @aws-cdk/[email protected] deduped
| | +-- [email protected] deduped
| | +-- [email protected] deduped
| | +-- [email protected] deduped
| | -- [email protected] deduped | +-- [email protected] | +-- [email protected] | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | | -- [email protected] deduped
| | -- [email protected] | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | | -- [email protected]
| | +-- [email protected]
| | +-- [email protected] deduped
| | +-- [email protected]
| | | -- [email protected] deduped | | -- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | | -- [email protected] | | +-- [email protected] | | | -- [email protected]
| | -- [email protected] | | -- [email protected]
| +-- [email protected]
| | -- [email protected] | | +-- [email protected] | | -- [email protected]
| +-- [email protected]
| | -- [email protected] | | -- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | | -- [email protected] deduped | | +-- [email protected] | | | -- [email protected]
| | +-- [email protected]
| | | +-- @tootallnate/[email protected]
| | | +-- [email protected] deduped
| | | -- [email protected] deduped | | +-- [email protected] | | | +-- [email protected] deduped | | | -- [email protected] deduped
| | +-- [email protected]
| | | -- [email protected] | | +-- [email protected] | | | +-- @tootallnate/[email protected] deduped | | | +-- [email protected] deduped | | | +-- [email protected] deduped | | | +-- [email protected] | | | | +-- @tootallnate/[email protected] deduped | | | | +-- [email protected] | | | | +-- [email protected] deduped | | | | +-- [email protected] | | | | +-- [email protected] | | | | | +-- [email protected] deduped | | | | | +-- [email protected] | | | | | | -- [email protected] deduped
| | | | | -- [email protected] | | | | -- [email protected]
| | | | +-- [email protected]
| | | | | +-- [email protected] deduped
| | | | | +-- [email protected] deduped
| | | | | +-- [email protected]
| | | | | -- [email protected] | | | | -- [email protected]
| | | +-- [email protected] deduped
| | | +-- [email protected] deduped
| | | +-- [email protected]
| | | | +-- [email protected]
| | | | | +-- [email protected]
| | | | | | -- [email protected] | | | | | +-- [email protected] | | | | | | +-- [email protected] deduped | | | | | | +-- [email protected] | | | | | | +-- [email protected] | | | | | | +-- [email protected] | | | | | | | +-- [email protected] | | | | | | | +-- [email protected] | | | | | | | +-- [email protected] | | | | | | | | +-- [email protected] deduped | | | | | | | | -- [email protected] deduped
| | | | | | | +-- [email protected]
| | | | | | | +-- [email protected]
| | | | | | | | -- [email protected] deduped | | | | | | | -- [email protected]
| | | | | | -- [email protected] deduped | | | | | -- [email protected]
| | | | +-- [email protected]
| | | | -- [email protected] | | | +-- [email protected] | | | | +-- [email protected] | | | | +-- [email protected] | | | | | +-- [email protected] | | | | | +-- [email protected] deduped | | | | | +-- [email protected] | | | | | +-- [email protected] | | | | | -- [email protected]
| | | | +-- [email protected]
| | | | | -- [email protected] | | | | -- [email protected]
| | | -- [email protected] deduped | | +-- [email protected] | | -- [email protected]
| | +-- [email protected] deduped
| | +-- [email protected] deduped
| | -- [email protected] | | +-- [email protected] deduped | | -- [email protected]
| +-- [email protected]
| | -- [email protected] | | -- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | -- [email protected] | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] | | | +-- [email protected] | | | -- [email protected]
| | | -- [email protected] | | +-- [email protected] | | | -- [email protected]
| | | +-- [email protected]
| | | -- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] | | | | -- [email protected] deduped
| | | -- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | +-- [email protected] | | | +-- [email protected] deduped | | | +-- [email protected] | | | -- [email protected] deduped
| | -- [email protected] deduped | +-- [email protected] | +-- [email protected] | | +-- [email protected] | | | -- [email protected]
| | | -- [email protected] | | +-- [email protected] deduped | | -- [email protected]
| | -- [email protected] | +-- [email protected] | -- [email protected]
| +-- [email protected]
| | +-- [email protected] deduped
| | +-- [email protected] deduped
| | -- [email protected] deduped | +-- [email protected] | +-- [email protected] | +-- [email protected] | +-- [email protected] deduped | +-- [email protected] | -- [email protected]
+-- [email protected]
| `-- [email protected]

Function name cannot be longer than 64 characters

In ensureLambda() you're creating a function whose name is constructed from the stack name and the resource type. If this name exceeds 64 characters, CDK throws an error.

Example:

export class StackWithAReallyRidiculouslyLongName extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) { 
    # ...
   new Document(this, 'Document', {
      # ...
   })
  }
}

The function created in ensureLambda() will construct a function name of StackWithAReallyRidiculouslyLongName-CFN-Resource-Custom-SSM-Document, which is longer than 64 characters.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.