From 9284e20b85a96f1bca9fb1d891611de81454b047 Mon Sep 17 00:00:00 2001 From: Fred Cox Date: Mon, 27 Mar 2023 19:13:59 +0300 Subject: [PATCH] fix: correct merging of config files so that keys from each file are kept (#4388) --- .../src/mergeConfigFiles.spec.ts | 25 +++++++++++++++++++ .../src/mergeConfigFiles.ts | 20 +++++++++++++++ .../src/parseKnownFiles.spec.ts | 24 ++++++++++++------ .../src/parseKnownFiles.ts | 6 ++--- 4 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 packages/shared-ini-file-loader/src/mergeConfigFiles.spec.ts create mode 100644 packages/shared-ini-file-loader/src/mergeConfigFiles.ts diff --git a/packages/shared-ini-file-loader/src/mergeConfigFiles.spec.ts b/packages/shared-ini-file-loader/src/mergeConfigFiles.spec.ts new file mode 100644 index 000000000000..2da612162720 --- /dev/null +++ b/packages/shared-ini-file-loader/src/mergeConfigFiles.spec.ts @@ -0,0 +1,25 @@ +import { mergeConfigFiles } from "./mergeConfigFiles"; + +describe(mergeConfigFiles.name, () => { + it("merges profiles that are in multiple files", () => { + const mockConfigFile = { + profileName1: { configKey: "configValue1" }, + }; + const mockCredentialsFile = { + profileName1: { credsKey: "configValue1" }, + profileName2: { credsKey: "credsValue1" }, + }; + + expect(mergeConfigFiles(mockConfigFile, mockCredentialsFile)).toMatchInlineSnapshot(` + Object { + "profileName1": Object { + "configKey": "configValue1", + "credsKey": "configValue1", + }, + "profileName2": Object { + "credsKey": "credsValue1", + }, + } + `); + }); +}); diff --git a/packages/shared-ini-file-loader/src/mergeConfigFiles.ts b/packages/shared-ini-file-loader/src/mergeConfigFiles.ts new file mode 100644 index 000000000000..8dc14911a20d --- /dev/null +++ b/packages/shared-ini-file-loader/src/mergeConfigFiles.ts @@ -0,0 +1,20 @@ +import { ParsedIniData } from "@aws-sdk/types"; + +/** + * Merge multiple profile config files such that settings each file are kept together + * + * @internal + */ +export const mergeConfigFiles = (...files: ParsedIniData[]): ParsedIniData => { + const merged: ParsedIniData = {}; + for (const file of files) { + for (const [key, values] of Object.entries(file)) { + if (merged[key] !== undefined) { + Object.assign(merged[key], values); + } else { + merged[key] = values; + } + } + } + return merged; +}; diff --git a/packages/shared-ini-file-loader/src/parseKnownFiles.spec.ts b/packages/shared-ini-file-loader/src/parseKnownFiles.spec.ts index d4e2e1a11b02..c427208d6c76 100644 --- a/packages/shared-ini-file-loader/src/parseKnownFiles.spec.ts +++ b/packages/shared-ini-file-loader/src/parseKnownFiles.spec.ts @@ -5,12 +5,12 @@ jest.mock("./loadSharedConfigFiles"); describe(parseKnownFiles.name, () => { const mockConfigFile = { - mockConfigProfileName1: { configKey1: "configValue1" }, - mockConfigProfileName2: { configKey2: "configValue2" }, + profileName1: { configKey1: "configValue1" }, + profileName2: { configKey2: "configValue2" }, }; const mockCredentialsFile = { - mockCredentialsProfileName1: { credsKey1: "credsValue1" }, - mockCredentialsProfileName2: { credsKey2: "credsValue2" }, + profileName1: { credsKey1: "credsValue1" }, + profileName2: { credsKey2: "credsValue2" }, }; afterEach(() => { @@ -28,9 +28,17 @@ describe(parseKnownFiles.name, () => { const parsedFiles = await parseKnownFiles(mockInit); expect(loadSharedConfigFiles).toHaveBeenCalledWith(mockInit); - expect(parsedFiles).toEqual({ - ...mockConfigFile, - ...mockCredentialsFile, - }); + expect(parsedFiles).toMatchInlineSnapshot(` + Object { + "profileName1": Object { + "configKey1": "configValue1", + "credsKey1": "credsValue1", + }, + "profileName2": Object { + "configKey2": "configValue2", + "credsKey2": "credsValue2", + }, + } + `); }); }); diff --git a/packages/shared-ini-file-loader/src/parseKnownFiles.ts b/packages/shared-ini-file-loader/src/parseKnownFiles.ts index b3966d201a25..fb9bbc99a9b3 100644 --- a/packages/shared-ini-file-loader/src/parseKnownFiles.ts +++ b/packages/shared-ini-file-loader/src/parseKnownFiles.ts @@ -1,6 +1,7 @@ import { ParsedIniData } from "@aws-sdk/types"; import { loadSharedConfigFiles, SharedConfigInit } from "./loadSharedConfigFiles"; +import { mergeConfigFiles } from "./mergeConfigFiles"; export interface SourceProfileInit extends SharedConfigInit { /** @@ -17,8 +18,5 @@ export interface SourceProfileInit extends SharedConfigInit { */ export const parseKnownFiles = async (init: SourceProfileInit): Promise => { const parsedFiles = await loadSharedConfigFiles(init); - return { - ...parsedFiles.configFile, - ...parsedFiles.credentialsFile, - }; + return mergeConfigFiles(parsedFiles.configFile, parsedFiles.credentialsFile); };