fix: chef connection secret sync fns

This commit is contained in:
Piyush Gupta
2025-10-30 20:36:01 +05:30
parent 30c0cfb8c2
commit 0661efee3e
2 changed files with 30 additions and 15 deletions
@@ -2,7 +2,14 @@ import { getChefDataBagItem, updateChefDataBagItem } from "@app/services/app-con
import { matchesSchema } from "@app/services/secret-sync/secret-sync-fns"; import { matchesSchema } from "@app/services/secret-sync/secret-sync-fns";
import { TSecretMap } from "@app/services/secret-sync/secret-sync-types"; import { TSecretMap } from "@app/services/secret-sync/secret-sync-types";
import { ChefSecret, TChefDataBagItemContent, TChefSyncWithCredentials, TGetChefSecrets } from "./chef-sync-types"; import {
ChefSecret,
TChefDataBagItemContent,
TChefSecret,
TChefSecrets,
TChefSyncWithCredentials,
TGetChefSecrets
} from "./chef-sync-types";
const getChefSecretsRaw = async ({ const getChefSecretsRaw = async ({
serverUrl, serverUrl,
@@ -29,7 +36,7 @@ const getChefSecretsRaw = async ({
return dataBagItem; return dataBagItem;
}; };
const getChefSecrets = async (secretSync: TChefSyncWithCredentials): Promise<ChefSecret[]> => { const getChefSecrets = async (secretSync: TChefSyncWithCredentials): Promise<TChefSecrets> => {
const { const {
connection, connection,
destinationConfig: { dataBagName, dataBagItemName } destinationConfig: { dataBagName, dataBagItemName }
@@ -46,21 +53,23 @@ const getChefSecrets = async (secretSync: TChefSyncWithCredentials): Promise<Che
dataBagItemName dataBagItemName
}); });
const { id, ...existingSecrets } = dataBagItem;
// Convert data bag item to key-value pairs // Convert data bag item to key-value pairs
// Exclude the 'id' field as it's metadata
const secrets: ChefSecret[] = []; const secrets: ChefSecret[] = [];
Object.entries(dataBagItem).forEach(([key, value]) => { Object.entries(existingSecrets).forEach(([key, value]) => {
if (key !== "id" && value !== null && value !== undefined) { if (key !== "id" && value !== null && value !== undefined) {
secrets.push({ key, value: String(value) }); secrets.push({ key, value: String(value) });
} }
}); });
return secrets; return { id, secrets };
}; };
const updateChefSecrets = async ( const updateChefSecrets = async (
secretSync: TChefSyncWithCredentials, secretSync: TChefSyncWithCredentials,
secrets: Record<string, string | number | boolean> id: string,
secrets: Record<string, TChefSecret>
) => { ) => {
const { const {
connection, connection,
@@ -71,7 +80,7 @@ const updateChefSecrets = async (
// Chef data bag items must have an 'id' field // Chef data bag items must have an 'id' field
const dataBagItemContent: TChefDataBagItemContent = { const dataBagItemContent: TChefDataBagItemContent = {
id: dataBagItemName, id,
...secrets ...secrets
}; };
@@ -93,7 +102,7 @@ export const ChefSyncFns = {
syncOptions: { disableSecretDeletion, keySchema } syncOptions: { disableSecretDeletion, keySchema }
} = secretSync; } = secretSync;
const secrets = await getChefSecrets(secretSync); const { id, secrets } = await getChefSecrets(secretSync);
// Create a map of the existing secrets // Create a map of the existing secrets
const updatedSecretsMap = new Map(secrets.map((secret) => [secret.key, secret.value])); const updatedSecretsMap = new Map(secrets.map((secret) => [secret.key, secret.value]));
@@ -117,27 +126,26 @@ export const ChefSyncFns = {
// Convert map to object for Chef API // Convert map to object for Chef API
const updatedSecrets = Object.fromEntries(updatedSecretsMap.entries()); const updatedSecrets = Object.fromEntries(updatedSecretsMap.entries());
await updateChefSecrets(secretSync, updatedSecrets); await updateChefSecrets(secretSync, id, updatedSecrets);
}, },
async getSecrets(secretSync: TChefSyncWithCredentials): Promise<TSecretMap> { async getSecrets(secretSync: TChefSyncWithCredentials): Promise<TSecretMap> {
const secrets = await getChefSecrets(secretSync); const { secrets } = await getChefSecrets(secretSync);
return Object.fromEntries(secrets.map((secret) => [secret.key, { value: secret.value }])); return Object.fromEntries(secrets.map((secret) => [secret.key, { value: secret.value }]));
}, },
async removeSecrets(secretSync: TChefSyncWithCredentials, secretMap: TSecretMap) { async removeSecrets(secretSync: TChefSyncWithCredentials, secretMap: TSecretMap) {
const existingSecrets = await getChefSecrets(secretSync); const { id, secrets: existingSecrets } = await getChefSecrets(secretSync);
const newSecrets = existingSecrets.filter((secret) => !Object.hasOwn(secretMap, secret.key)); const newSecrets = existingSecrets.filter((secret) => !Object.hasOwn(secretMap, secret.key));
// If nothing changed, return early
if (newSecrets.length === existingSecrets.length) { if (newSecrets.length === existingSecrets.length) {
return; return;
} }
// Convert to object for Chef API
const updatedSecrets = Object.fromEntries(newSecrets.map((secret) => [secret.key, secret.value])); const updatedSecrets = Object.fromEntries(newSecrets.map((secret) => [secret.key, secret.value]));
await updateChefSecrets(secretSync, updatedSecrets); await updateChefSecrets(secretSync, id, updatedSecrets);
} }
}; };
@@ -23,9 +23,16 @@ export type TGetChefSecrets = {
dataBagItemName: string; dataBagItemName: string;
}; };
export type TChefSecret = string | number | boolean | null;
export type TChefDataBagItemContent = { export type TChefDataBagItemContent = {
id: string; id: string;
[key: string]: string | number | boolean | null; [key: string]: TChefSecret;
};
export type TChefSecrets = {
id: string;
secrets: ChefSecret[];
}; };
export type ChefSecret = { export type ChefSecret = {