diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e299f2..e6d88c7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 22.4.x + node-version: 22.5.x - name: Install dependencies run: yarn install --check-files - name: build @@ -95,7 +95,7 @@ jobs: steps: - uses: actions/setup-node@v4 with: - node-version: 22.4.x + node-version: 22.5.x - name: Download build artifacts uses: actions/download-artifact@v4 with: @@ -129,7 +129,7 @@ jobs: steps: - uses: actions/setup-node@v4 with: - node-version: 22.4.x + node-version: 22.5.x - uses: actions/setup-python@v5 with: python-version: 3.x diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 38672a3..125b8fc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,7 +31,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 22.4.x + node-version: 22.5.x - name: Install dependencies run: yarn install --check-files --frozen-lockfile - name: release @@ -71,7 +71,7 @@ jobs: steps: - uses: actions/setup-node@v4 with: - node-version: 22.4.x + node-version: 22.5.x - name: Download build artifacts uses: actions/download-artifact@v4 with: @@ -97,7 +97,7 @@ jobs: steps: - uses: actions/setup-node@v4 with: - node-version: 22.4.x + node-version: 22.5.x - name: Download build artifacts uses: actions/download-artifact@v4 with: @@ -137,7 +137,7 @@ jobs: steps: - uses: actions/setup-node@v4 with: - node-version: 22.4.x + node-version: 22.5.x - uses: actions/setup-python@v5 with: python-version: 3.x diff --git a/.github/workflows/upgrade-main.yml b/.github/workflows/upgrade-main.yml index 002c331..7f08db1 100644 --- a/.github/workflows/upgrade-main.yml +++ b/.github/workflows/upgrade-main.yml @@ -21,7 +21,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 22.4.x + node-version: 22.5.x - name: Install dependencies run: yarn install --check-files --frozen-lockfile - name: Upgrade dependencies diff --git a/.projen/deps.json b/.projen/deps.json index 2097d2b..c790743 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -91,6 +91,11 @@ "version": "5.5.x", "type": "build" }, + { + "name": "@gammarers/aws-resource-naming", + "version": "^0.8.0", + "type": "peer" + }, { "name": "aws-cdk-lib", "version": "^2.145.0", diff --git a/.projen/tasks.json b/.projen/tasks.json index 82bb081..b3d1b3a 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -291,7 +291,7 @@ "exec": "yarn install --check-files" }, { - "exec": "yarn upgrade @stylistic/eslint-plugin @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser commit-and-tag-version eslint-import-resolver-typescript eslint-plugin-import eslint jest jest-junit jsii-diff jsii-docgen jsii-pacmak jsii-rosetta jsii projen ts-jest ts-node typescript aws-cdk-lib constructs" + "exec": "yarn upgrade @stylistic/eslint-plugin @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser commit-and-tag-version eslint-import-resolver-typescript eslint-plugin-import eslint jest jest-junit jsii-diff jsii-docgen jsii-pacmak jsii-rosetta jsii projen ts-jest ts-node typescript @gammarers/aws-resource-naming aws-cdk-lib constructs" }, { "exec": "npx projen" diff --git a/.projenrc.ts b/.projenrc.ts index f94b601..576780d 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -9,10 +9,19 @@ const project = new awscdk.AwsCdkConstructLibrary({ name: '@gammarers/aws-codeconnections-host-custom-resource', projenrcTs: true, repositoryUrl: 'https://github.com/gammarers/aws-codeconnections-host-custom-resource.git', + // deps: [ + // '@gammarers/aws-resource-naming@^0.8.0', + // ], + // devDeps: [ + // '@gammarers/aws-resource-naming@0.8.0', + // ], + peerDeps: [ + '@gammarers/aws-resource-naming@^0.8.0', + ], releaseToNpm: true, npmAccess: javascript.NpmAccess.PUBLIC, minNodeVersion: '18.0.0', - workflowNodeVersion: '22.4.x', + workflowNodeVersion: '22.5.x', depsUpgradeOptions: { workflowOptions: { labels: ['auto-approve', 'auto-merge'], diff --git a/API.md b/API.md index 1109502..4a816e8 100644 --- a/API.md +++ b/API.md @@ -208,6 +208,7 @@ const codeConnectionsHostCustomResourceProps: CodeConnectionsHostCustomResourceP | name | string | *No description.* | | providerEndpoint | string | *No description.* | | providerType | CodeConnectionsHostProviderType | *No description.* | +| resouceNamingOption | CustomNaming \| @gammarers/aws-resource-naming.ResourceDefaultNaming \| @gammarers/aws-resource-naming.ResourceAutoNaming | *No description.* | --- @@ -241,6 +242,66 @@ public readonly providerType: CodeConnectionsHostProviderType; --- +##### `resouceNamingOption`Optional + +```typescript +public readonly resouceNamingOption: CustomNaming | ResourceDefaultNaming | ResourceAutoNaming; +``` + +- *Type:* CustomNaming | @gammarers/aws-resource-naming.ResourceDefaultNaming | @gammarers/aws-resource-naming.ResourceAutoNaming + +--- + +### CustomNaming + +#### Initializer + +```typescript +import { CustomNaming } from '@gammarers/aws-codeconnections-host-custom-resource' + +const customNaming: CustomNaming = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| functionName | string | *No description.* | +| functionRoleName | string | *No description.* | +| type | @gammarers/aws-resource-naming.ResourceNamingType | *No description.* | + +--- + +##### `functionName`Required + +```typescript +public readonly functionName: string; +``` + +- *Type:* string + +--- + +##### `functionRoleName`Required + +```typescript +public readonly functionRoleName: string; +``` + +- *Type:* string + +--- + +##### `type`Required + +```typescript +public readonly type: ResourceNamingType; +``` + +- *Type:* @gammarers/aws-resource-naming.ResourceNamingType + +--- + ## Enums diff --git a/package.json b/package.json index 2749142..8ea7915 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "organization": false }, "devDependencies": { + "@gammarers/aws-resource-naming": "0.8.0", "@stylistic/eslint-plugin": "^2", "@types/jest": "^29.5.14", "@types/node": "^18", @@ -59,6 +60,7 @@ "typescript": "5.5.x" }, "peerDependencies": { + "@gammarers/aws-resource-naming": "^0.8.0", "aws-cdk-lib": "^2.145.0", "constructs": "^10.0.5" }, diff --git a/src/index.ts b/src/index.ts index b3511ec..14de492 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import * as crypto from 'crypto'; +import { ResourceAutoNaming, ResourceDefaultNaming, ResourceNaming, ResourceNamingOptions, ResourceNamingType } from '@gammarers/aws-resource-naming'; import * as cdk from 'aws-cdk-lib'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as cr from 'aws-cdk-lib/custom-resources'; @@ -17,10 +17,66 @@ export enum ResponseField { HOST_ARN = 'HostArn', } +//export type Names = { +// functionName: string; +// functionRoleName: string; +//} +//export interface Names { +// readonly functionName: string; +// readonly functionRoleName: string; +//} +// +//export type CustomNaming = { +// type: ResourceNaming.NamingType.CUSTOM; +// // functionName: string; +// // functionRoleName: string; +// names: Names; +//} + +//export interface ResourceNamingOptions { +// readonly naming: ResourceNaming.AutoNaming | ResourceNaming.DefaultNaming | { +// type: ResourceNaming.NamingType.CUSTOM; +// names: { +// functionName: string; +// functionRoleName: string; +// }; +// }; +//} + +//export interface ResourceNamingOptions { +// readonly naming: ResourceNaming.AutoNaming | ResourceNaming.DefaultNaming; +//} +//export type Naming = { type: ResourceNaming.NamingType.DEFAULT } | { type: ResourceNaming.NamingType.AUTO } | CustomNaming; +//export type Naming = { type: ResourceNaming.NamingType.DEFAULT } | { type: ResourceNaming.NamingType.AUTO } | CustomNaming; +//export type Naming = CustomNaming; + +//export interface ResourceNamingOptions { +// readonly naming: Naming; +//} +//export interface DefaultNamingOption { +// readonly type: ResourceNaming.NamingType.DEFAULT; +//} +// +//export interface AutoNamingOption { +// readonly type: ResourceNaming.NamingType.AUTO; +//} + +export interface CustomNaming { + readonly type: ResourceNamingType.CUSTOM; + // readonly names: Names; // CUSTOM の場合に必須 + readonly functionName: string; // フラット化 + readonly functionRoleName: string; // フラット化 +} + +export type ResourceNamingOption = ResourceDefaultNaming | ResourceAutoNaming | CustomNaming; + export interface CodeConnectionsHostCustomResourceProps { readonly name: string; readonly providerEndpoint: string; readonly providerType: CodeConnectionsHostProviderType; + //readonly resouceNamingOption?: ResourceNamingOptions; + // readonly resouceNamingOption?: { type: ResourceNaming.NamingType.DEFAULT } | { type: ResourceNaming.NamingType.AUTO } | CustomNaming; + readonly resouceNamingOption?: ResourceNamingOption; } export class CodeConnectionsHostCustomResource extends cr.AwsCustomResource { @@ -28,15 +84,21 @@ export class CodeConnectionsHostCustomResource extends cr.AwsCustomResource { constructor(scope: Construct, id: string, props: CodeConnectionsHostCustomResourceProps) { // 👇 Create random 8 length string - const random: string = crypto.createHash('shake256', { outputLength: 4 }) - .update(`${cdk.Names.uniqueId(scope)}.${props.name}.${props.providerEndpoint}.${props.providerType}`) - .digest('hex'); + const random = ResourceNaming.createRandomString(`${cdk.Names.uniqueId(scope)}.${props.name}.${props.providerEndpoint}.${props.providerType}`); + const autoNaming = { + functionName: `custom-resource-codeconnection-host-${random}-func`, + functionRoleName: `custom-resource-codeconnection-host-${random}-func-exc-role`, + }; + const names = ResourceNaming.naming(autoNaming, props.resouceNamingOption as ResourceNamingOptions); + // const naming = { + // names: autoNaming, + // }; const account = cdk.Stack.of(scope).account; const region = cdk.Stack.of(scope).region; const functionRole = new iam.Role(scope, 'FunctionRole', { - roleName: `custom-resource-codeconnection-host-${random}-func-exc-role`, + roleName: names.functionRoleName, description: 'Custom Resource Function Execution Role.', assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), managedPolicies: [ @@ -62,10 +124,11 @@ export class CodeConnectionsHostCustomResource extends cr.AwsCustomResource { }); super(scope, id, { - functionName: `custom-resource-codeconnection-host-${random}-func`, + functionName: names.functionName, role: functionRole, timeout: cdk.Duration.seconds(15), installLatestAwsSdk: true, + //logGroup: todo onCreate: { service: 'CodeConnections', action: 'createHost', diff --git a/test/__snapshots__/custom-resource.bitbucket.default.test.ts.snap b/test/__snapshots__/custom-resource.bitbucket.default.test.ts.snap new file mode 100644 index 0000000..ce5cd3b --- /dev/null +++ b/test/__snapshots__/custom-resource.bitbucket.default.test.ts.snap @@ -0,0 +1,144 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CustomResource Testing Should match snapshot 1`] = ` +{ + "Parameters": { + "BootstrapVersion": { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": { + "AWS679f53fac002430cb0da5b7982bd22872D164C4C": { + "DependsOn": [ + "FunctionRole111A5701", + ], + "Properties": { + "Code": { + "S3Bucket": "cdk-hnb659fds-assets-123456789012-us-east-1", + "S3Key": "97f30e67419a1676a2215492723e5add1aa491caf0cbe2dd878fc4fab0468cd4.zip", + }, + "Handler": "index.handler", + "MemorySize": 512, + "Role": { + "Fn::GetAtt": [ + "FunctionRole111A5701", + "Arn", + ], + }, + "Runtime": "nodejs18.x", + "Timeout": 15, + }, + "Type": "AWS::Lambda::Function", + }, + "BitBucketCodeConnectionsHostCustomResource983A9F6A": { + "DeletionPolicy": "Delete", + "Properties": { + "Create": "{"service":"CodeConnections","action":"createHost","parameters":{"Name":"bitbucket.example.com","ProviderEndpoint":"https://bitbucket.example.com","ProviderType":"Bitbucket"},"physicalResourceId":{"responsePath":"HostArn"}}", + "Delete": "{"service":"CodeConnections","action":"deleteHost","parameters":{"HostArn":"PHYSICAL:RESOURCEID:"}}", + "InstallLatestAwsSdk": true, + "ServiceToken": { + "Fn::GetAtt": [ + "AWS679f53fac002430cb0da5b7982bd22872D164C4C", + "Arn", + ], + }, + "Update": "{"service":"CodeConnections","action":"updateHost","parameters":{"HostArn":"PHYSICAL:RESOURCEID:","ProviderEndpoint":"https://bitbucket.example.com"}}", + }, + "Type": "Custom::AWS", + "UpdateReplacePolicy": "Delete", + }, + "Connection": { + "Properties": { + "ConnectionName": "example-bitbucket-connection", + "HostArn": { + "Fn::GetAtt": [ + "BitBucketCodeConnectionsHostCustomResource983A9F6A", + "HostArn", + ], + }, + }, + "Type": "AWS::CodeConnections::Connection", + }, + "FunctionRole111A5701": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "Description": "Custom Resource Function Execution Role.", + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + "Policies": [ + { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codeconnections:CreateHost", + "codeconnections:UpdateHost", + "codeconnections:DeleteHost", + ], + "Effect": "Allow", + "Resource": "arn:aws:codeconnections:us-east-1:123456789012:*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "CustomResourcePolicy", + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5", + ], + { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; diff --git a/test/__snapshots__/custom-resource.bitbucket.test.ts.snap b/test/__snapshots__/custom-resource.bitbucket.option.test.ts.snap similarity index 100% rename from test/__snapshots__/custom-resource.bitbucket.test.ts.snap rename to test/__snapshots__/custom-resource.bitbucket.option.test.ts.snap diff --git a/test/__snapshots__/custom-resource.github-enterprise.test.ts.snap b/test/__snapshots__/custom-resource.github-enterprise.test.ts.snap index 0f44cb8..87872cc 100644 --- a/test/__snapshots__/custom-resource.github-enterprise.test.ts.snap +++ b/test/__snapshots__/custom-resource.github-enterprise.test.ts.snap @@ -19,7 +19,6 @@ exports[`CustomResource Testing Should match snapshot 1`] = ` "S3Bucket": "cdk-hnb659fds-assets-123456789012-us-east-1", "S3Key": "97f30e67419a1676a2215492723e5add1aa491caf0cbe2dd878fc4fab0468cd4.zip", }, - "FunctionName": "custom-resource-codeconnection-host-bf36cfd3-func", "Handler": "index.handler", "MemorySize": 512, "Role": { @@ -93,7 +92,6 @@ exports[`CustomResource Testing Should match snapshot 1`] = ` "PolicyName": "CustomResourcePolicy", }, ], - "RoleName": "custom-resource-codeconnection-host-bf36cfd3-func-exc-role", }, "Type": "AWS::IAM::Role", }, diff --git a/test/__snapshots__/custom-resource.github.test.ts.snap b/test/__snapshots__/custom-resource.github.test.ts.snap index b86a560..e1b8904 100644 --- a/test/__snapshots__/custom-resource.github.test.ts.snap +++ b/test/__snapshots__/custom-resource.github.test.ts.snap @@ -19,7 +19,6 @@ exports[`CustomResource Testing Should match snapshot 1`] = ` "S3Bucket": "cdk-hnb659fds-assets-123456789012-us-east-1", "S3Key": "97f30e67419a1676a2215492723e5add1aa491caf0cbe2dd878fc4fab0468cd4.zip", }, - "FunctionName": "custom-resource-codeconnection-host-3183eaa3-func", "Handler": "index.handler", "MemorySize": 512, "Role": { @@ -93,7 +92,6 @@ exports[`CustomResource Testing Should match snapshot 1`] = ` "PolicyName": "CustomResourcePolicy", }, ], - "RoleName": "custom-resource-codeconnection-host-3183eaa3-func-exc-role", }, "Type": "AWS::IAM::Role", }, diff --git a/test/__snapshots__/custom-resource.gitlab-self-managed.test.ts.snap b/test/__snapshots__/custom-resource.gitlab-self-managed.test.ts.snap index c257e84..ee360a5 100644 --- a/test/__snapshots__/custom-resource.gitlab-self-managed.test.ts.snap +++ b/test/__snapshots__/custom-resource.gitlab-self-managed.test.ts.snap @@ -19,7 +19,6 @@ exports[`CustomResource Testing Should match snapshot 1`] = ` "S3Bucket": "cdk-hnb659fds-assets-123456789012-us-east-1", "S3Key": "97f30e67419a1676a2215492723e5add1aa491caf0cbe2dd878fc4fab0468cd4.zip", }, - "FunctionName": "custom-resource-codeconnection-host-ede7e92c-func", "Handler": "index.handler", "MemorySize": 512, "Role": { @@ -93,7 +92,6 @@ exports[`CustomResource Testing Should match snapshot 1`] = ` "PolicyName": "CustomResourcePolicy", }, ], - "RoleName": "custom-resource-codeconnection-host-ede7e92c-func-exc-role", }, "Type": "AWS::IAM::Role", }, diff --git a/test/__snapshots__/custom-resource.gitlab.test.ts.snap b/test/__snapshots__/custom-resource.gitlab.test.ts.snap index 2c25d8d..b61b3bf 100644 --- a/test/__snapshots__/custom-resource.gitlab.test.ts.snap +++ b/test/__snapshots__/custom-resource.gitlab.test.ts.snap @@ -19,7 +19,6 @@ exports[`CustomResource Testing Should match snapshot 1`] = ` "S3Bucket": "cdk-hnb659fds-assets-123456789012-us-east-1", "S3Key": "97f30e67419a1676a2215492723e5add1aa491caf0cbe2dd878fc4fab0468cd4.zip", }, - "FunctionName": "custom-resource-codeconnection-host-4a813def-func", "Handler": "index.handler", "MemorySize": 512, "Role": { @@ -93,7 +92,6 @@ exports[`CustomResource Testing Should match snapshot 1`] = ` "PolicyName": "CustomResourcePolicy", }, ], - "RoleName": "custom-resource-codeconnection-host-4a813def-func-exc-role", }, "Type": "AWS::IAM::Role", }, diff --git a/test/custom-resource.bitbucket.test.ts b/test/custom-resource.bitbucket.default.test.ts similarity index 100% rename from test/custom-resource.bitbucket.test.ts rename to test/custom-resource.bitbucket.default.test.ts diff --git a/test/custom-resource.bitbucket.option.test.ts b/test/custom-resource.bitbucket.option.test.ts new file mode 100644 index 0000000..6947f14 --- /dev/null +++ b/test/custom-resource.bitbucket.option.test.ts @@ -0,0 +1,44 @@ +import { ResourceNamingType } from '@gammarers/aws-resource-naming'; +import { App, Stack } from 'aws-cdk-lib'; +import { Template } from 'aws-cdk-lib/assertions'; +import * as codeconnections from 'aws-cdk-lib/aws-codeconnections'; +import { AwsCustomResource } from 'aws-cdk-lib/custom-resources'; +import { CodeConnectionsHostCustomResource, CodeConnectionsHostProviderType } from '../src'; + +describe('CustomResource Testing', () => { + + const app = new App(); + const stack = new Stack(app, 'TestingStack', { + env: { + account: '123456789012', + region: 'us-east-1', + }, + }); + + const bitbucketConnectionHostCustomResource = new CodeConnectionsHostCustomResource(stack, 'BitBucketCodeConnectionsHostCustomResource', { + name: 'bitbucket.example.com', + providerEndpoint: 'https://bitbucket.example.com', + providerType: CodeConnectionsHostProviderType.BIT_BUCKET, + resouceNamingOption: { + type: ResourceNamingType.AUTO, + }, + }); + + const hostArn = bitbucketConnectionHostCustomResource.findHostArn(); + + new codeconnections.CfnConnection(stack, 'Connection', { + connectionName: 'example-bitbucket-connection', + hostArn, + }); + + const template = Template.fromStack(stack); + + it('Is Bitbucket Connection Host CustomResource', () => { + expect(bitbucketConnectionHostCustomResource).toBeInstanceOf(AwsCustomResource); + }); + + it('Should match snapshot', () => { + expect(template.toJSON()).toMatchSnapshot(); + }); + +}); diff --git a/yarn.lock b/yarn.lock index f22ef39..84bc64c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -358,6 +358,11 @@ dependencies: levn "^0.4.1" +"@gammarers/aws-resource-naming@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@gammarers/aws-resource-naming/-/aws-resource-naming-0.8.0.tgz#8a9be5ac99d14dacc9655f4fb5e54f332189655e" + integrity sha512-tEoHISz2N/O0CTMEWt++sGTUoBlnUfhKa1sCcTiWfawZ2lN5+3K0Jr2PsaQzJ6BOhHWqXi/CMRas6x3UN7oNUQ== + "@humanfs/core@^0.19.1": version "0.19.1" resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77"