Skip to content

Commit

Permalink
extract common part
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolk committed Dec 12, 2024
1 parent 1c51fc8 commit 4d5bcf1
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 112 deletions.
74 changes: 14 additions & 60 deletions packages/backend-function/src/factory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
FunctionOutput,
functionOutputKey,
} from '@aws-amplify/backend-output-schemas';
import { AttributionMetadataStorage } from '@aws-amplify/backend-output-storage';
import { FunctionOutput } from '@aws-amplify/backend-output-schemas';
import {
AmplifyUserError,
CallerDirectoryExtractor,
Expand All @@ -20,16 +16,15 @@ import {
GenerateContainerEntryProps,
LogLevel,
LogRetention,
ResourceAccessAcceptor,
ResourceAccessAcceptorFactory,
ResourceNameValidator,
ResourceProvider,
SsmEnvironmentEntry,
StackProvider,
} from '@aws-amplify/plugin-types';
import { Duration, Stack, Tags } from 'aws-cdk-lib';
import { Duration, Tags } from 'aws-cdk-lib';
import { Rule } from 'aws-cdk-lib/aws-events';
import * as targets from 'aws-cdk-lib/aws-events-targets';
import { Policy } from 'aws-cdk-lib/aws-iam';
import {
CfnFunction,
IFunction,
Expand All @@ -41,7 +36,6 @@ import { NodejsFunction, OutputFormat } from 'aws-cdk-lib/aws-lambda-nodejs';
import { Construct } from 'constructs';
import { readFileSync } from 'fs';
import { createRequire } from 'module';
import { fileURLToPath } from 'node:url';
import { EOL } from 'os';
import * as path from 'path';
import { FunctionEnvironmentTranslator } from './function_env_translator.js';
Expand All @@ -53,8 +47,8 @@ import {
ProvidedFunctionFactory,
ProvidedFunctionProps,
} from './provided_function_factory.js';

const functionStackType = 'function-Lambda';
import { AmplifyFunctionBase } from './function_construct_base.js';
import { FunctionResourceAccessAcceptor } from './resource_access_acceptor.js';

export type AddEnvironmentFactory = {
addEnvironment: (key: string, value: string | BackendSecret) => void;
Expand Down Expand Up @@ -459,14 +453,10 @@ class FunctionGenerator implements ConstructContainerEntryGenerator {
}

class AmplifyFunction
extends Construct
implements
ResourceProvider<FunctionResources>,
ResourceAccessAcceptorFactory,
AddEnvironmentFactory
extends AmplifyFunctionBase
implements AddEnvironmentFactory
{
readonly resources: FunctionResources;
readonly stack: Stack;
private readonly functionEnvironmentTranslator: FunctionEnvironmentTranslator;
constructor(
scope: Construct,
Expand All @@ -475,9 +465,7 @@ class AmplifyFunction
backendSecretResolver: BackendSecretResolver,
outputStorageStrategy: BackendOutputStorageStrategy<FunctionOutput>
) {
super(scope, id);

this.stack = Stack.of(scope);
super(scope, id, outputStorageStrategy);

const runtime = nodeVersionMap[props.runtime];

Expand Down Expand Up @@ -597,52 +585,18 @@ class AmplifyFunction
},
};

this.storeOutput(outputStorageStrategy);

new AttributionMetadataStorage().storeAttributionMetadata(
Stack.of(this),
functionStackType,
fileURLToPath(new URL('../package.json', import.meta.url))
);
this.storeOutput();
}

addEnvironment = (key: string, value: string | BackendSecret) => {
this.functionEnvironmentTranslator.addEnvironmentEntry(key, value);
};

getResourceAccessAcceptor = () => ({
identifier: `${this.node.id}LambdaResourceAccessAcceptor`,
acceptResourceAccess: (
policy: Policy,
ssmEnvironmentEntries: SsmEnvironmentEntry[]
) => {
const role = this.resources.lambda.role;
if (!role) {
// This should never happen since we are using the Function L2 construct
throw new Error(
'No execution role found to attach lambda permissions to'
);
}
policy.attachToRole(role);
ssmEnvironmentEntries.forEach(({ name, path }) => {
this.functionEnvironmentTranslator.addSsmEnvironmentEntry(name, path);
});
},
});

/**
* Store storage outputs using provided strategy
*/
private storeOutput = (
outputStorageStrategy: BackendOutputStorageStrategy<FunctionOutput>
): void => {
outputStorageStrategy.appendToBackendOutputList(functionOutputKey, {
version: '1',
payload: {
definedFunctions: this.resources.lambda.functionName,
},
});
};
getResourceAccessAcceptor = (): ResourceAccessAcceptor =>
new FunctionResourceAccessAcceptor(
this,
this.functionEnvironmentTranslator
);
}

const isWholeNumberBetweenInclusive = (
Expand Down
58 changes: 58 additions & 0 deletions packages/backend-function/src/function_construct_base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Construct } from 'constructs';
import {
BackendOutputStorageStrategy,
FunctionResources,
ResourceAccessAcceptor,
ResourceAccessAcceptorFactory,
ResourceProvider,
} from '@aws-amplify/plugin-types';
import { Stack } from 'aws-cdk-lib';
import {
FunctionOutput,
functionOutputKey,
} from '@aws-amplify/backend-output-schemas';
import { AttributionMetadataStorage } from '@aws-amplify/backend-output-storage';
import { fileURLToPath } from 'node:url';

const functionStackType = 'function-Lambda';

/**
* A base class for function constructs.
*/
export abstract class AmplifyFunctionBase
extends Construct
implements ResourceProvider<FunctionResources>, ResourceAccessAcceptorFactory
{
readonly stack: Stack;
abstract resources: FunctionResources;

abstract getResourceAccessAcceptor: () => ResourceAccessAcceptor;

/**
* Creates base function construct.
*/
protected constructor(
scope: Construct,
id: string,
private readonly outputStorageStrategy: BackendOutputStorageStrategy<FunctionOutput>
) {
super(scope, id);

this.stack = Stack.of(scope);

new AttributionMetadataStorage().storeAttributionMetadata(
Stack.of(this),
functionStackType,
fileURLToPath(new URL('../package.json', import.meta.url))
);
}

protected storeOutput = (): void => {
this.outputStorageStrategy.appendToBackendOutputList(functionOutputKey, {
version: '1',
payload: {
definedFunctions: this.resources.lambda.functionName,
},
});
};
}
62 changes: 10 additions & 52 deletions packages/backend-function/src/provided_function_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,15 @@ import {
ConstructFactoryGetInstanceProps,
FunctionResources,
GenerateContainerEntryProps,
ResourceAccessAcceptorFactory,
ResourceProvider,
ResourceAccessAcceptor,
} from '@aws-amplify/plugin-types';
import { Construct } from 'constructs';
import { CfnFunction, IFunction } from 'aws-cdk-lib/aws-lambda';
import {
FunctionOutput,
functionOutputKey,
} from '@aws-amplify/backend-output-schemas';
import { Stack, Tags } from 'aws-cdk-lib';
import { FunctionOutput } from '@aws-amplify/backend-output-schemas';
import { Tags } from 'aws-cdk-lib';
import { AmplifyUserError, TagName } from '@aws-amplify/platform-core';
import { AttributionMetadataStorage } from '@aws-amplify/backend-output-storage';
import { fileURLToPath } from 'node:url';
import { Policy } from 'aws-cdk-lib/aws-iam';
import { AmplifyFunctionBase } from './function_construct_base.js';
import { FunctionResourceAccessAcceptor } from './resource_access_acceptor.js';

export type ProvidedFunctionProps = {
/**
Expand Down Expand Up @@ -117,21 +112,15 @@ class ProvidedFunctionGenerator implements ConstructContainerEntryGenerator {
};
}

class ProvidedAmplifyFunction
extends Construct
implements ResourceProvider<FunctionResources>, ResourceAccessAcceptorFactory
{
class ProvidedAmplifyFunction extends AmplifyFunctionBase {
readonly resources: FunctionResources;
readonly stack: Stack;
constructor(
scope: Construct,
id: string,
outputStorageStrategy: BackendOutputStorageStrategy<FunctionOutput>,
providedFunction: IFunction
) {
super(scope, id);

this.stack = Stack.of(scope);
super(scope, id, outputStorageStrategy);

const cfnFunction = providedFunction.node.findChild(
'Resource'
Expand All @@ -146,40 +135,9 @@ class ProvidedAmplifyFunction
},
};

this.storeOutput(outputStorageStrategy);

new AttributionMetadataStorage().storeAttributionMetadata(
Stack.of(this),
'provided-function-Lambda',
fileURLToPath(new URL('../package.json', import.meta.url))
);
this.storeOutput();
}

getResourceAccessAcceptor = () => ({
identifier: `${this.node.id}LambdaResourceAccessAcceptor`,
acceptResourceAccess: (policy: Policy) => {
const role = this.resources.lambda.role;
if (!role) {
// This should never happen since we are using the Function L2 construct
throw new Error(
'No execution role found to attach lambda permissions to'
);
}
policy.attachToRole(role);
},
});

/**
* Store storage outputs using provided strategy
*/
private storeOutput = (
outputStorageStrategy: BackendOutputStorageStrategy<FunctionOutput>
): void => {
outputStorageStrategy.appendToBackendOutputList(functionOutputKey, {
version: '1',
payload: {
definedFunctions: this.resources.lambda.functionName,
},
});
};
getResourceAccessAcceptor = (): ResourceAccessAcceptor =>
new FunctionResourceAccessAcceptor(this);
}
43 changes: 43 additions & 0 deletions packages/backend-function/src/resource_access_acceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {
ResourceAccessAcceptor,
SsmEnvironmentEntry,
} from '@aws-amplify/plugin-types';
import { FunctionEnvironmentTranslator } from './function_env_translator.js';
import { AmplifyFunctionBase } from './function_construct_base.js';
import { Policy } from 'aws-cdk-lib/aws-iam';

/**
* A function resource acceptor.
*/
export class FunctionResourceAccessAcceptor implements ResourceAccessAcceptor {
readonly identifier: string;

/**
* Creates function resource acceptor.
*/
constructor(
private readonly func: AmplifyFunctionBase,
private readonly functionEnvironmentTranslator?: FunctionEnvironmentTranslator
) {
this.identifier = `${func.node.id}LambdaResourceAccessAcceptor`;
}

acceptResourceAccess = (
policy: Policy,
ssmEnvironmentEntries: SsmEnvironmentEntry[]
) => {
const role = this.func.resources.lambda.role;
if (!role) {
// This should never happen since we are using the Function L2 construct
throw new Error(
'No execution role found to attach lambda permissions to'
);
}
policy.attachToRole(role);
if (this.functionEnvironmentTranslator) {
for (const { name, path } of ssmEnvironmentEntries) {
this.functionEnvironmentTranslator.addSsmEnvironmentEntry(name, path);
}
}
};
}

0 comments on commit 4d5bcf1

Please sign in to comment.