feat(tests): redeploy tf-docs через Nubes API (Bearer, CFS-параметры)
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* redeploy.js — запуск операции redeploy для инстанса tf-docs через Nubes API.
|
||||
*
|
||||
* Авторизация: Bearer-токен из tf_provider/secrets/test.token.
|
||||
* Токен НЕ печатается.
|
||||
*
|
||||
* Запуск: node llm_project/tests/redeploy.js [--uid <instanceUid>] [--profile test]
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const argv = process.argv.slice(2);
|
||||
function arg(name, def) {
|
||||
const i = argv.indexOf('--' + name);
|
||||
return i !== -1 && argv[i + 1] ? argv[i + 1] : def;
|
||||
}
|
||||
|
||||
const UID = arg('uid', '7a48a863-9b40-4cef-a352-033ee9dde8de');
|
||||
const TOKEN_FILE = arg('token', '/home/naeel/TF/tf_provider/secrets/test.token');
|
||||
const BASE = arg('base', 'https://lk-api-gateway-test.ngcloud.ru/api/v1/svc');
|
||||
const ACTION = arg('action', 'redeploy');
|
||||
|
||||
const HEADERS = () => ({
|
||||
Authorization: 'Bearer ' + fs.readFileSync(TOKEN_FILE, 'utf8').trim(),
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'Mozilla/5.0',
|
||||
});
|
||||
|
||||
async function api(method, path, body) {
|
||||
const opts = { method, headers: HEADERS() };
|
||||
if (body !== undefined) opts.body = JSON.stringify(body);
|
||||
const resp = await fetch(BASE + path, opts);
|
||||
const text = await resp.text();
|
||||
let json = null;
|
||||
try { json = JSON.parse(text); } catch { /* не JSON */ }
|
||||
return { status: resp.status, text, json, location: resp.headers.get('location') };
|
||||
}
|
||||
|
||||
/** Извлекает UID из заголовка Location (последний сегмент пути). */
|
||||
function uidFromLocation(loc) {
|
||||
if (!loc) return '';
|
||||
const clean = loc.split('?')[0].replace(/\/+$/, '');
|
||||
const parts = clean.split('/');
|
||||
return parts[parts.length - 1] || '';
|
||||
}
|
||||
|
||||
function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
|
||||
|
||||
async function main() {
|
||||
console.log('Инстанс:', UID, '| операция:', ACTION);
|
||||
|
||||
// 1) Состояние инстанса: доступные операции + текущие params.
|
||||
const st = await api('GET', `/instances/${UID}`);
|
||||
if (st.status !== 200) {
|
||||
console.error('Ошибка GET /instances:', st.status, st.text.slice(0, 300));
|
||||
process.exit(1);
|
||||
}
|
||||
const inst = (st.json && st.json.instance) || {};
|
||||
console.log('Статус:', inst.explainedStatus, '| inProgress:', inst.operationIsInProgress, '| pending:', inst.operationIsPending);
|
||||
const instanceParams = (inst.state && inst.state.params) || {};
|
||||
|
||||
const ops = inst.availableOperations || [];
|
||||
const op = ops.find((o) => String(o.operation).toLowerCase() === ACTION.toLowerCase());
|
||||
if (!op) {
|
||||
console.error('Операция', ACTION, 'недоступна. Доступные:', ops.map((o) => o.operation).join(', '));
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('svcOperationId:', op.svcOperationId);
|
||||
|
||||
// 2) Создать операцию.
|
||||
const created = await api('POST', '/instanceOperations', {
|
||||
instanceUid: UID,
|
||||
svcOperationId: op.svcOperationId,
|
||||
operation: ACTION,
|
||||
});
|
||||
let opUid = '';
|
||||
if (created.json && (created.json.uid || created.json.instanceOperationUid || created.json.opUid)) {
|
||||
opUid = created.json.uid || created.json.instanceOperationUid || created.json.opUid;
|
||||
}
|
||||
if (!opUid) opUid = uidFromLocation(created.location);
|
||||
if (!opUid) opUid = created.text.replace(/^"|"$/g, '').trim();
|
||||
console.log('Создана операция:', created.status, '| opUid:', opUid);
|
||||
if (!opUid || opUid.length < 8) {
|
||||
console.error('Не удалось получить opUid. Ответ:', created.text.slice(0, 300));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// 2б) Установить требуемые CFS-параметры (например startupConfiguration) из live-состояния.
|
||||
const cfs = await api('GET', `/instanceOperations/${opUid}?fields=cfsParams`);
|
||||
const cfsParams = (cfs.json && cfs.json.instanceOperation && cfs.json.instanceOperation.cfsParams) || [];
|
||||
for (const p of cfsParams) {
|
||||
const val = instanceParams[p.svcOperationCfsParam];
|
||||
if (val === undefined) {
|
||||
console.log(' параметр', p.svcOperationCfsParam, '(id=' + p.svcOperationCfsParamId + ') — в состоянии нет, пропуск');
|
||||
continue;
|
||||
}
|
||||
const paramValue = typeof val === 'string' ? val : JSON.stringify(val);
|
||||
const pr = await api('POST', '/instanceOperationCfsParams', {
|
||||
instanceOperationUid: opUid,
|
||||
svcOperationCfsParamId: p.svcOperationCfsParamId,
|
||||
paramValue: paramValue,
|
||||
});
|
||||
console.log(' параметр', p.svcOperationCfsParam, '=', paramValue, '->', pr.status);
|
||||
}
|
||||
|
||||
// 3) Запустить операцию.
|
||||
const run = await api('POST', `/instanceOperations/${opUid}/run`, {});
|
||||
console.log('Запуск:', run.status, run.text.slice(0, 120));
|
||||
|
||||
// 4) Ждать завершения.
|
||||
const deadline = Date.now() + 6 * 60 * 1000;
|
||||
let last = '';
|
||||
while (Date.now() < deadline) {
|
||||
await sleep(5000);
|
||||
const o = await api('GET', `/instanceOperations/${opUid}?fields=dtFinish,isSuccessful,errorLog,isInProgress,isPending,duration,stages`);
|
||||
if (o.status !== 200) { console.log(' poll:', o.status); continue; }
|
||||
const d = (o.json && (o.json.instanceOperation || o.json)) || {};
|
||||
const line = ` inProgress=${d.isInProgress} pending=${d.isPending} finish=${d.dtFinish || '—'} ok=${d.isSuccessful}`;
|
||||
if (line !== last) { console.log(line); last = line; }
|
||||
if (d.dtFinish && !d.isInProgress && !d.isPending) {
|
||||
if (d.isSuccessful) {
|
||||
console.log('РЕДЕПЛОЙ ЗАВЕРШЁН УСПЕШНО');
|
||||
} else {
|
||||
console.error('РЕДЕПЛОЙ ЗАВЕРШЁН С ОШИБКОЙ:', d.errorLog || '(нет errorLog)');
|
||||
process.exit(2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.error('Таймаут ожидания операции');
|
||||
process.exit(3);
|
||||
}
|
||||
|
||||
main().catch((e) => { console.error('FATAL', e.message); process.exit(1); });
|
||||
Reference in New Issue
Block a user