1password deploys reuse the sdk client to cut api calls
This commit is contained in:
1 file changed
+27
-3
@@ -19,12 +19,27 @@ import type { SecretProvider, ServiceAccountConfig, TestConnectionResult } from
|
|||||||
const INTEGRATION_NAME = 'Dockhand';
|
const INTEGRATION_NAME = 'Dockhand';
|
||||||
const INTEGRATION_VERSION = '1.0.0';
|
const INTEGRATION_VERSION = '1.0.0';
|
||||||
|
|
||||||
|
// createClient does a ~2s handshake, and one deploy builds a client for the bulk
|
||||||
|
// pull and again for inline refs. Reuse a client per token for a few seconds so a
|
||||||
|
// single deploy (and back-to-back retries) pay that cost once, not per call.
|
||||||
|
const CLIENT_TTL_MS = 30_000;
|
||||||
|
interface CachedClient {
|
||||||
|
client: Awaited<ReturnType<typeof createClient>>;
|
||||||
|
expiresAt: number;
|
||||||
|
}
|
||||||
|
const clientCache = new Map<string, CachedClient>();
|
||||||
|
|
||||||
async function makeClient(token: string) {
|
async function makeClient(token: string) {
|
||||||
return createClient({
|
const now = Date.now();
|
||||||
|
const hit = clientCache.get(token);
|
||||||
|
if (hit && hit.expiresAt > now) return hit.client;
|
||||||
|
const client = await createClient({
|
||||||
auth: token,
|
auth: token,
|
||||||
integrationName: INTEGRATION_NAME,
|
integrationName: INTEGRATION_NAME,
|
||||||
integrationVersion: INTEGRATION_VERSION
|
integrationVersion: INTEGRATION_VERSION
|
||||||
});
|
});
|
||||||
|
clientCache.set(token, { client, expiresAt: now + CLIENT_TTL_MS });
|
||||||
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const serviceAccountProvider: SecretProvider<ServiceAccountConfig> = {
|
export const serviceAccountProvider: SecretProvider<ServiceAccountConfig> = {
|
||||||
@@ -62,16 +77,25 @@ export const serviceAccountProvider: SecretProvider<ServiceAccountConfig> = {
|
|||||||
}
|
}
|
||||||
const client = await makeClient(token);
|
const client = await makeClient(token);
|
||||||
const response = await client.secrets.resolveAll(refs);
|
const response = await client.secrets.resolveAll(refs);
|
||||||
|
const skipped: string[] = [];
|
||||||
for (const [ref, item] of Object.entries(response.individualResponses)) {
|
for (const [ref, item] of Object.entries(response.individualResponses)) {
|
||||||
if (item.error) {
|
if (item.error) {
|
||||||
const detail = item.error.message ?? item.error.type ?? 'unknown error';
|
skipped.push(ref);
|
||||||
console.warn(`${logPrefix} Skipping op:// reference ${ref}: ${detail}`);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (item.content?.secret !== undefined) {
|
if (item.content?.secret !== undefined) {
|
||||||
result.set(ref, item.content.secret);
|
result.set(ref, item.content.secret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// One summary line instead of one warning per bad ref, so a handful of
|
||||||
|
// malformed references don't flood the log across repeated deploys.
|
||||||
|
if (skipped.length > 0) {
|
||||||
|
const total = Object.keys(response.individualResponses).length;
|
||||||
|
console.warn(
|
||||||
|
`${logPrefix} Skipped ${skipped.length} of ${total} op:// reference(s) - ` +
|
||||||
|
`malformed or not found (need op://<vault>/<item>/<field>): ${skipped.join(', ')}`
|
||||||
|
);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user