Skip to content

Commit c2c5e68

Browse files
Merge master into feature/v2-to-v3-migration
2 parents 95e6e61 + d908b6e commit c2c5e68

File tree

13 files changed

+99
-0
lines changed

13 files changed

+99
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "Add conditional Tenant ID field to Local Invoke panel for multi-tenant Lambda functions. The field appears when SAM template contains TenancyConfig and passes the value to SAM CLI as --tenant-id argument."
4+
}

packages/core/package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"AWS.configuration.description.awssam.debug.memoryMb": "The amount of memory (in Mb) the Lambda function has access to.",
6060
"AWS.configuration.description.awssam.debug.runtime": "The Lambda Function's runtime",
6161
"AWS.configuration.description.awssam.debug.timeout": "The amount of time (in seconds) that Lambda allows a function to run before stopping it.",
62+
"AWS.configuration.description.awssam.debug.tenantId": "Tenant ID for multi-tenant Lambda functions",
6263
"AWS.configuration.description.awssam.debug.aws": "AWS connection details",
6364
"AWS.configuration.description.awssam.debug.credentials": "The AWS credentials provider and name to use during the invocation. Example: credential profile \"default\" would be entered as `profile:default`.",
6465
"AWS.configuration.description.awssam.debug.credentials.cn": "The Amazon credentials provider and name to use during the invocation. Example: credential profile \"default\" would be entered as `profile:default`.",

packages/core/src/awsService/appBuilder/explorer/samProject.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface FunctionResourceEntity extends BaseResourceEntity {
4141
}
4242
CapacityProviderConfig?: string
4343
Architectures?: string
44+
TenancyConfig?: string
4445
}
4546

4647
export interface CapacityProviderResourceEntity extends BaseResourceEntity {
@@ -123,6 +124,7 @@ function createResourceEntity(logicalId: string, resource: any, template: any):
123124
CapacityProviderConfig:
124125
resource.Properties?.CapacityProviderConfig ?? template?.Globals?.Function?.CapacityProviderConfig,
125126
Architectures: resource.Properties?.Architectures?.[0] ?? template?.Globals?.Function?.Architectures?.[0],
127+
TenancyConfig: resource.Properties?.TenancyConfig ?? template?.Globals?.Function?.TenancyConfig,
126128
}
127129
return functionEntity
128130
}

packages/core/src/lambda/vue/configEditor/samInvokeBackend.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export interface ResourceData {
4848
runtime: string
4949
stackName: string
5050
source: string
51+
hasTenancyConfig?: boolean
5152
environment?: {
5253
Variables: Record<string, any>
5354
}
@@ -456,6 +457,7 @@ export async function registerSamDebugInvokeVueCommand(
456457
stackName: resource.stackName ?? '',
457458
environment: resource.resource.Environment,
458459
source: source,
460+
hasTenancyConfig: !!resource.resource.TenancyConfig,
459461
})
460462
await telemetry.sam_openConfigUi.run(async (span) => {
461463
telemetry.record({ source: 'AppBuilderDebugger' }),

packages/core/src/lambda/vue/configEditor/samInvokeComponent.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,21 @@
9797
</div>
9898
</div>
9999
</div>
100+
<div
101+
class="config-item"
102+
v-if="resourceData?.hasTenancyConfig && launchConfig.invokeTarget.target !== 'api'"
103+
>
104+
<label for="tenant-id">Tenant ID</label>
105+
<input
106+
name="tenant-id"
107+
id="tenant-id"
108+
type="text"
109+
v-model="launchConfig.lambda.tenantId"
110+
placeholder="Enter tenant ID (required for invocation)"
111+
style="width: 100%"
112+
/>
113+
<span class="data-view">Tenant ID from data: {{ launchConfig.lambda.tenantId }}</span>
114+
</div>
100115
<div class="config-item">
101116
<label for="target-type-selector">Invoke target type</label>
102117
<select name="target-types" id="target-type-selector" v-model="launchConfig.invokeTarget.target">

packages/core/src/lambda/vue/configEditor/samInvokeFrontend.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ function newLaunchConfig(existingConfig?: AwsSamDebuggerConfiguration): AwsSamDe
7474
memoryMb: undefined,
7575
timeoutSec: undefined,
7676
environmentVariables: {},
77+
tenantId: undefined,
7778
...existingConfig?.lambda,
7879
payload: {
7980
json: existingConfig?.lambda?.payload?.json ? existingConfig.lambda.payload.json : {},
@@ -430,6 +431,7 @@ export default defineComponent({
430431
json: payloadJson,
431432
},
432433
environmentVariables: environmentVariablesJson,
434+
tenantId: launchConfig.lambda?.tenantId,
433435
},
434436
sam: {
435437
...launchConfig.sam,

packages/core/src/shared/sam/cli/samCliLocalInvoke.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ export interface SamCliLocalInvokeInvocationArguments {
222222
region?: string
223223
/** Overrides the template-specified runtime. */
224224
runtime?: Runtime
225+
/** Tenant ID for multi-tenant Lambda functions */
226+
tenantId?: string
225227
}
226228

227229
/**
@@ -262,6 +264,7 @@ export class SamCliLocalInvokeInvocation {
262264
pushIf(invokeArgs, !!this.args.debugArgs, '--debug-args', ...(this.args.debugArgs ?? []))
263265
pushIf(invokeArgs, !!this.args.containerEnvFile, '--container-env-vars', this.args.containerEnvFile)
264266
pushIf(invokeArgs, !!this.args.region, '--region', this.args.region)
267+
pushIf(invokeArgs, !!this.args.tenantId, '--tenant-id', this.args.tenantId!)
265268

266269
pushIf(
267270
invokeArgs,

packages/core/src/shared/sam/debugger/awsSamDebugConfiguration.gen.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ export interface LambdaProperties {
138138
* The amount of time (in seconds) that Lambda allows a function to run before stopping it.
139139
*/
140140
timeoutSec?: number;
141+
/**
142+
* Tenant ID for multi-tenant Lambda functions
143+
*/
144+
tenantId?: string;
141145
pathMappings?: PathMapping[];
142146
}
143147
export interface PathMapping {

packages/core/src/shared/sam/localLambdaRunner.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ async function invokeLambdaHandler(
249249
name: config.name,
250250
region: config.region,
251251
runtime: config.lambda?.runtime as Runtime,
252+
tenantId: config.lambda?.tenantId,
252253
}
253254

254255
// sam local invoke ...

packages/core/src/test/awsService/appBuilder/explorer/samProject.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import {
1717
samconfigInvalidData,
1818
validTemplateData,
1919
capacityProviderTemplateData,
20+
functionLevelTenancyConfigTemplateData,
21+
globalTenancyConfigTemplateData,
2022
} from '../../../shared/sam/samTestUtils'
2123
import { assertLogsContain } from '../../../globalSetup.test'
2224
import { getTestWindow } from '../../../shared/vscode/window'
@@ -186,5 +188,27 @@ describe('samProject', () => {
186188
assert('Fn::GetAtt' in config.Arn)
187189
assert.deepStrictEqual(config.Arn['Fn::GetAtt'], ['MyCapacityProvider', 'Arn'])
188190
})
191+
192+
it('detects TenancyConfig from function-level properties', async () => {
193+
await testFolder.write('template.yaml', functionLevelTenancyConfigTemplateData)
194+
const { resourceTree } = await getApp(mockSamAppLocation)
195+
196+
assert.strictEqual(resourceTree.length, 1)
197+
const functionNode = resourceTree[0]
198+
assert.strictEqual(functionNode.Type, 'AWS::Serverless::Function')
199+
assert('TenancyConfig' in functionNode)
200+
assert.deepStrictEqual(functionNode.TenancyConfig, { TenantIsolationMode: 'PER_TENANT' })
201+
})
202+
203+
it('detects TenancyConfig from Globals section', async () => {
204+
await testFolder.write('template.yaml', globalTenancyConfigTemplateData)
205+
const { resourceTree } = await getApp(mockSamAppLocation)
206+
207+
assert.strictEqual(resourceTree.length, 1)
208+
const functionNode = resourceTree[0]
209+
assert.strictEqual(functionNode.Type, 'AWS::Serverless::Function')
210+
assert('TenancyConfig' in functionNode)
211+
assert.deepStrictEqual(functionNode.TenancyConfig, { TenantIsolationMode: 'PER_TENANT' })
212+
})
189213
})
190214
})

0 commit comments

Comments
 (0)