Stand vor Einführung des Nacht-Agenten
This commit is contained in:
commit
4763548bfb
168 changed files with 12726 additions and 0 deletions
60
packages/connector-mock/src/index.ts
Normal file
60
packages/connector-mock/src/index.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import { ConnectorError, CONTRACT_VERSION, type Connector, type ConnectorContext, type NormalizedResource } from '@kc/connector-sdk';
|
||||
|
||||
/**
|
||||
* Mock-Connector für Entwicklung und Tests. Alle Daten sind erfundene Testdaten und klar mit "[Mock]" gekennzeichnet.
|
||||
* Zustand lebt im Speicher des jeweiligen Prozesses (Worker) und geht bei Neustart verloren.
|
||||
* config.simulateOutage = "true" simuliert einen Providerausfall.
|
||||
*/
|
||||
const state = new Map<string, Map<string, NormalizedResource>>();
|
||||
const seed = (): Map<string, NormalizedResource> => new Map<string, NormalizedResource>([
|
||||
['m-1', { externalRef: 'm-1', type: 'license', name: '[Mock] Beispiel-Lizenz Pro', state: 'active', validFrom: '2026-01-01T00:00:00.000Z', validUntil: '2027-01-01T00:00:00.000Z', limits: { users: 5 }, details: { mock: true } }],
|
||||
['m-2', { externalRef: 'm-2', type: 'license', name: '[Mock] Beispiel-Lizenz Basic', state: 'active', validFrom: '2026-03-01T00:00:00.000Z', validUntil: '2026-12-31T00:00:00.000Z', limits: { users: 1 }, details: { mock: true } }],
|
||||
['m-3', { externalRef: 'm-3', type: 'hosting_account', name: '[Mock] Hosting-Konto', state: 'active', limits: { storageMb: 10240 }, usage: { storageMb: 1234 }, details: { mock: true } }],
|
||||
]);
|
||||
const store = (ctx: ConnectorContext) => { const k = String(ctx.config.instance ?? 'default'); if (!state.has(k)) state.set(k, seed()); return state.get(k)!; };
|
||||
const outage = (ctx: ConnectorContext) => { if (String(ctx.config.simulateOutage) === 'true') throw new ConnectorError('UNREACHABLE', 'simulierter Ausfall'); };
|
||||
export const resetMock = () => state.clear();
|
||||
|
||||
export const mockConnector: Connector = {
|
||||
contractVersion: CONTRACT_VERSION, key: 'mock', displayName: 'Mock (Testdaten)',
|
||||
configFields: [{ name: 'instance', label: 'Instanzname', placeholder: 'default' }, { name: 'simulateOutage', label: 'Ausfall simulieren (true/false)', placeholder: 'false' }],
|
||||
capabilities: () => ['catalog.list', 'resources.list', 'resources.get', 'status.read', 'usage.read', 'lifecycle.suspend', 'lifecycle.unsuspend', 'lifecycle.extend', 'lifecycle.terminate', 'lifecycle.create', 'license.key_prefix', 'license.expiry', 'secret.reveal'],
|
||||
async healthCheck(ctx) {
|
||||
try { outage(ctx); return { ok: true, latencyMs: 1, message: 'Mock', version: '1' }; } catch (e) { return { ok: false, latencyMs: 1, message: (e as ConnectorError).userMessage }; }
|
||||
},
|
||||
validateProvisioning(params) {
|
||||
if ('failCreate' in params && typeof params.failCreate !== 'string') return 'failCreate muss Text sein';
|
||||
return null;
|
||||
},
|
||||
/** Legt eine Mock-Ressource an. params.failCreate = "timeout" | "unreachable" simuliert Fehler (nur für Tests). */
|
||||
async provision(ctx, req) {
|
||||
outage(ctx);
|
||||
if (req.params.failCreate === 'timeout') throw new ConnectorError('TIMEOUT');
|
||||
if (req.params.failCreate === 'unreachable') throw new ConnectorError('UNREACHABLE', 'ECONNREFUSED simuliert');
|
||||
const s = store(ctx);
|
||||
const ref = `m-${req.idempotencyKey.slice(0, 8)}`; // gleicher Schlüssel => gleiche Ressource (Mock ist idempotent)
|
||||
if (!s.has(ref)) s.set(ref, { externalRef: ref, type: 'license', name: `[Mock] ${req.label}`, state: 'active', validFrom: new Date().toISOString(), validUntil: req.params.validityDays ? new Date(Date.now() + Number(req.params.validityDays) * 86400000).toISOString() : req.params.durationType === 'YEAR' ? new Date(Date.now() + 365 * 86400000).toISOString() : req.params.durationType === 'MONTH' ? new Date(Date.now() + 30 * 86400000).toISOString() : null, limits: { users: Number(req.params.userLimit ?? 1) }, details: { mock: true, edition: String(req.params.keyPrefix ?? 'UNLIMITED'), context: req.context ?? null } });
|
||||
return { resource: { ...s.get(ref)! } };
|
||||
},
|
||||
async reveal(ctx, ref) { outage(ctx); if (!store(ctx).has(ref)) throw new ConnectorError('NOT_FOUND'); return [{ label: 'Lizenzschlüssel', value: `MOCK-KEY-${ref}` }]; },
|
||||
async listCatalog(ctx) {
|
||||
outage(ctx);
|
||||
return [
|
||||
{ externalRef: 'mock-prog-1', name: '[Mock] Programm Alpha', description: 'Testprogramm', category: 'license', provisioning: { userLimit: 5 }, hints: [{ label: '5 Benutzer', provisioning: { userLimit: 5 }, count: 2 }] },
|
||||
{ externalRef: 'mock-prog-2', name: '[Mock] Programm Beta', description: null, category: 'license', provisioning: { userLimit: 1 } },
|
||||
];
|
||||
},
|
||||
async listResources(ctx) { outage(ctx); return [...store(ctx).values()].map((r) => ({ ...r })); },
|
||||
async execute(ctx, req) {
|
||||
outage(ctx);
|
||||
const r = store(ctx).get(req.externalRef);
|
||||
if (!r) throw new ConnectorError('NOT_FOUND');
|
||||
// Zielzustand setzen: bei Wiederholung mit gleichem Schlüssel wirkungsgleich
|
||||
if (req.action === 'suspend') r.state = 'suspended';
|
||||
else if (req.action === 'unsuspend') r.state = 'active';
|
||||
else if (req.action === 'extend') { const u = String(req.params?.until ?? ''); if (Number.isNaN(Date.parse(u))) throw new ConnectorError('BAD_CONFIG', 'until fehlt'); r.validUntil = new Date(u).toISOString(); }
|
||||
else if (req.action === 'terminate') { store(ctx).delete(req.externalRef); return {}; }
|
||||
else throw new ConnectorError('UNSUPPORTED');
|
||||
return { resource: { ...r } };
|
||||
},
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue