Skip to content

Commit f3c9c05

Browse files
authored
fix: add retained secrets to syncSecretDeltas (#13300)
* fix: add retained secrets to syncSecretDeltas * test: add e2e test * chore: revert yarn bump
1 parent 540dd7f commit f3c9c05

File tree

3 files changed

+91
-9
lines changed

3 files changed

+91
-9
lines changed

packages/amplify-category-function/src/provider-utils/awscloudformation/secrets/functionSecretsStateManager.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,11 @@ export class FunctionSecretsStateManager {
100100
return;
101101
}
102102
const cloudSecretNames = await this.getCloudFunctionSecretNames(functionName);
103-
const addedSecrets = localSecretNames.filter((name) => !cloudSecretNames.includes(name));
103+
const retainedSecrets: string[] = [];
104+
const addedSecrets: string[] = [];
105+
106+
localSecretNames.forEach((name) => (cloudSecretNames.includes(name) ? retainedSecrets.push(name) : addedSecrets.push(name)));
107+
104108
if (!addedSecrets.length) {
105109
return;
106110
}
@@ -118,8 +122,12 @@ export class FunctionSecretsStateManager {
118122
link: 'https://docs.amplify.aws/cli/reference/ssm-parameter-store/#manually-creating-parameters',
119123
});
120124
}
125+
126+
const current = secretNamesToSecretDeltas(retainedSecrets);
121127
const delta = await prePushMissingSecretsWalkthrough(functionName, addedSecrets);
122-
await this.syncSecretDeltas(delta, functionName);
128+
const secretDeltas = { ...current, ...delta };
129+
130+
await this.syncSecretDeltas(secretDeltas, functionName);
123131
};
124132

125133
/**

packages/amplify-e2e-core/src/categories/lambda-function.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,26 @@ const updateFunctionCore = (cwd: string, chain: ExecutionContext, settings: Core
116116
}
117117
}
118118
if (settings.secretsConfig) {
119-
if (settings.secretsConfig.operation === 'add') {
120-
throw new Error('Secrets update walkthrough only supports update and delete');
121-
}
122-
// this walkthrough assumes 1 existing secret is configured for the function
123119
const actions = ['Add a secret', 'Update a secret', 'Remove secrets', "I'm done"];
124-
const action = settings.secretsConfig.operation === 'delete' ? actions[2] : actions[1];
120+
const operation = settings.secretsConfig.operation;
121+
let action: string;
122+
if (operation === 'add') {
123+
action = actions[0];
124+
} else if (operation === 'delete') {
125+
action = actions[2];
126+
} else {
127+
action = actions[1];
128+
}
125129
chain.wait('What do you want to do?');
126130
singleSelect(chain, action, actions);
127-
switch (settings.secretsConfig.operation) {
131+
switch (operation) {
132+
case 'add': {
133+
chain.wait('Enter a secret name');
134+
chain.sendLine(settings.secretsConfig.name);
135+
chain.wait('Enter the value for');
136+
chain.sendLine(settings.secretsConfig.value);
137+
break;
138+
}
128139
case 'delete': {
129140
chain.wait('Select the secrets to delete:');
130141
chain.sendLine(' '); // assumes one secret
@@ -137,8 +148,17 @@ const updateFunctionCore = (cwd: string, chain: ExecutionContext, settings: Core
137148
break;
138149
}
139150
}
151+
140152
chain.wait('What do you want to do?');
141153
chain.sendCarriageReturn(); // "I'm done"
154+
155+
if (operation === 'add') {
156+
// assumes function is already pushed to the cloud
157+
chain.wait('This will immediately update secret values in the cloud');
158+
chain.sendCarriageReturn(); // "Yes"
159+
chain.wait('Do you want to edit the local lambda function now');
160+
chain.sendCarriageReturn(); // "No"
161+
}
142162
}
143163
};
144164

packages/amplify-e2e-tests/src/__tests__/function_7.test.ts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
setCategoryParameters,
1717
updateFunction,
1818
} from '@aws-amplify/amplify-e2e-core';
19-
import { addEnvironmentYes, removeEnvironment } from '../environment/env';
19+
import { addEnvironmentYes, checkoutEnvironment, removeEnvironment } from '../environment/env';
2020

2121
describe('function secret value', () => {
2222
let projRoot: string;
@@ -279,6 +279,60 @@ describe('function secret value', () => {
279279
// check that old value is removed and new one is added
280280
await expectParams([{ name: 'A_NEW_SECRET', value: 'anewtestsecretvalue' }], ['TEST_SECRET'], region, appId, 'integtest', funcName);
281281
});
282+
283+
it('keeps old secrets when pushing secrets added in another env', async () => {
284+
// add func w/ secret
285+
const envName = 'enva';
286+
await initJSProjectWithProfile(projRoot, { envName, disableAmplifyAppCreation: false });
287+
const funcName = `secretsTest${generateRandomShortId()}`;
288+
const funcSecretName = 'TEST_SECRET';
289+
await addFunction(
290+
projRoot,
291+
{
292+
functionTemplate: 'Hello World',
293+
name: funcName,
294+
secretsConfig: {
295+
operation: 'add',
296+
name: funcSecretName,
297+
value: 'testsecretvalue',
298+
},
299+
},
300+
'nodejs',
301+
);
302+
303+
await amplifyPushAuth(projRoot);
304+
305+
// add new env and add new secret to func
306+
await addEnvironmentYes(projRoot, { envName: 'envb' });
307+
await amplifyPushAuth(projRoot);
308+
const newFuncSecretName = 'NEW_TEST_SECRET';
309+
await updateFunction(
310+
projRoot,
311+
{
312+
secretsConfig: {
313+
operation: 'add',
314+
name: newFuncSecretName,
315+
value: 'testsecretvalue',
316+
},
317+
},
318+
'nodejs',
319+
);
320+
321+
// push updated func w/ new secret
322+
await amplifyPushAuth(projRoot);
323+
324+
await checkoutEnvironment(projRoot, { envName });
325+
326+
// check contents of function-parameters.json for new secret
327+
const expectedFuncSecrets = [funcSecretName, newFuncSecretName];
328+
const funcParams = getCategoryParameters(projRoot, 'function', funcName);
329+
expect(funcParams.secretNames).toEqual(expectedFuncSecrets);
330+
331+
// push with original env and assert all secrets are in function-parameters.json
332+
await amplifyPushMissingFuncSecret(projRoot, 'anewtestsecretvalue');
333+
const funcParamsPostPush = getCategoryParameters(projRoot, 'function', funcName);
334+
expect(funcParamsPostPush.secretNames).toEqual(expectedFuncSecrets);
335+
});
282336
});
283337

284338
const expectParams = async (

0 commit comments

Comments
 (0)