steadybit
Version:
Command-line interface to interact with the Steadybit API
334 lines • 13.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.handlers = exports.EXPERIMENTS = exports.setValidationFailures = exports.resetExperiments = void 0;
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2022 Steadybit GmbH
const msw_1 = require("msw");
const url = __importStar(require("node:url"));
let retryCount = 0;
let runSequence = 1;
let experimentSequence = 1;
let experimentStore = {};
let validationFailuresRemaining = 0;
const resetExperiments = () => {
retryCount = 0;
experimentSequence = 1;
runSequence = 1;
experimentStore = { 'TST-1': exports.EXPERIMENTS['TST-1'] };
validationFailuresRemaining = 0;
};
exports.resetExperiments = resetExperiments;
const setValidationFailures = (count) => {
validationFailuresRemaining = count;
};
exports.setValidationFailures = setValidationFailures;
exports.EXPERIMENTS = {
'TST-1': {
key: 'TST-1',
name: 'Verify TTR fashion bestseller',
team: 'TST',
environment: 'Global',
lanes: [
{
steps: [
{
type: 'action',
ignoreFailure: false,
parameters: {
graceful: 'true',
},
actionType: 'container-stop-attack',
radius: {
targetType: 'container',
predicate: {
operator: 'AND',
predicates: [
{
key: 'k8s.namespace',
operator: 'EQUALS',
values: ['steadybit-demo'],
},
{
key: 'k8s.deployment',
operator: 'EQUALS',
values: ['fashion-bestseller'],
},
],
},
query: null,
percentage: 50,
},
},
],
},
],
},
NEW: {
name: 'Verify TTR fashion bestseller',
team: 'TST',
environment: 'Global',
lanes: [
{
steps: [
{
type: 'action',
ignoreFailure: false,
parameters: {
graceful: 'true',
},
actionType: 'container-stop-attack',
radius: {
targetType: 'container',
predicate: {
operator: 'AND',
predicates: [
{
key: 'k8s.namespace',
operator: 'EQUALS',
values: ['steadybit-demo'],
},
{
key: 'k8s.deployment',
operator: 'EQUALS',
values: ['fashion-bestseller'],
},
],
},
query: null,
percentage: 50,
},
},
],
},
],
},
};
const getTooManyRequestsHandler = msw_1.http.get('http://example.com/api/status', (_a) => __awaiter(void 0, [_a], void 0, function* ({ request }) {
const headers = {};
const query = url.parse(request.url, true).query;
const reset = query.reset && String(query.reset);
const times = Number(query.times);
let code = Number(query.code) || 200;
if (reset) {
headers['RateLimit-Reset'] = reset;
}
if (times) {
if (retryCount < times) {
retryCount++;
}
else {
code = 200;
}
}
return msw_1.HttpResponse.text(String(query.body), { status: code, headers: headers });
}));
const getExperimentHandler = msw_1.http.get('http://example.com/api/experiments/:key', (_a) => __awaiter(void 0, [_a], void 0, function* ({ params }) {
const experiment = experimentStore[String(params.key)];
if (experiment) {
return msw_1.HttpResponse.json(experiment);
}
else {
return msw_1.HttpResponse.json('', { status: 404 });
}
}));
const deleteExperimentHandler = msw_1.http.delete('http://example.com/api/experiments/:key', (_a) => __awaiter(void 0, [_a], void 0, function* ({ params }) {
const experiment = experimentStore[String(params.key)];
delete experimentStore[String(params.key)];
return msw_1.HttpResponse.json('', { status: experiment ? 200 : 404 });
}));
const updateExperimentHandler = msw_1.http.post('http://example.com/api/experiments/:key', (_a) => __awaiter(void 0, [_a], void 0, function* ({ request, params }) {
const experiment = experimentStore[String(params.key)];
if (experiment) {
experimentStore[String(params.key)] = request.json();
}
return msw_1.HttpResponse.json('', { status: experiment ? 200 : 404 });
}));
const upsertExperimentHandler = msw_1.http.post('http://example.com/api/experiments', (_a) => __awaiter(void 0, [_a], void 0, function* ({ request }) {
const key = `NEW-${experimentSequence++}`;
experimentStore[key] = request.json();
return msw_1.HttpResponse.json('', { status: 201, headers: { location: `http://example.com/api/experiments/${key}` } });
}));
const executeExperimentHandler = msw_1.http.post('http://example.com/api/experiments/:key/execute', ({ params, request }) => {
const experiment = experimentStore[String(params.key)];
const requestUrl = new URL(request.url);
const forcePersist = requestUrl.searchParams.get('forcePersist');
if (validationFailuresRemaining > 0 && forcePersist === 'false') {
validationFailuresRemaining--;
return msw_1.HttpResponse.json({
type: 'https://steadybit.com/problems/experiment-invalid-exception',
title: 'Had validation errors (lanes[0].steps[0].blastRadius.predicate: Please specify a query to select targets).',
status: 422,
instance: `/api/experiments/${params.key}/execute`,
}, { status: 422 });
}
const run = runSequence++;
if (experiment) {
return msw_1.HttpResponse.json({
key: params.key,
executionId: run,
apiLocation: `http://example.com/api/experiments/executions/${run}`,
uiLocation: `http://example.com/experiments/edit/${params.key}/executions/${run}?tenant=example&team=EXAMPLE`,
}, {
status: 201,
headers: { location: `http://example.com/api/experiments/executions/${run}` },
});
}
else {
return msw_1.HttpResponse.json('', { status: 404 });
}
});
const executeUpsertExperimentHandler = msw_1.http.post('http://example.com/api/experiments/execute', ({ request }) => {
const requestUrl = new URL(request.url);
const forcePersist = requestUrl.searchParams.get('forcePersist');
if (validationFailuresRemaining > 0 && forcePersist === 'false') {
validationFailuresRemaining--;
return msw_1.HttpResponse.json({
type: 'https://steadybit.com/problems/experiment-invalid-exception',
title: 'Had validation errors (lanes[0].steps[0].blastRadius.predicate: Please specify a query to select targets).',
status: 422,
instance: '/api/experiments/execute',
}, { status: 422 });
}
const key = `NEW-${experimentSequence++}`;
const run = runSequence++;
experimentStore[key] = request.json();
return msw_1.HttpResponse.json({
key: key,
executionId: run,
apiLocation: `http://example.com/api/experiments/executions/${run}`,
uiLocation: `http://example.com/experiments/edit/${key}/executions/${run}?tenant=example&team=EXAMPLE`,
}, { status: 201, headers: { location: `http://example.com/api/experiments/executions/${run}` } });
});
const fetchAdviceHandler = msw_1.http.post('http://example.com/api/advice', (_a) => __awaiter(void 0, [_a], void 0, function* ({ request }) {
const body = (yield request.json());
if (body.query === 'mock.response=ok') {
const response = {
totalItems: 1,
items: [
{
target: {
reference: 'target-1-ref',
label: 'target-1',
type: 'host',
},
advice: {
type: 'advice-type-1',
label: 'advice-1',
status: 'Implemented',
},
url: 'http://example.com/api/advice/1111',
},
],
};
return msw_1.HttpResponse.json(response);
}
if (body.offset === 0) {
const response = {
nextOffset: 2,
totalItems: 3,
items: [
{
target: {
reference: 'target-1-ref',
label: 'target-1',
type: 'host',
},
advice: {
type: 'advice-type-1',
label: 'advice-1',
status: 'Validation needed',
},
url: 'http://example.com/api/advice/1111',
},
{
target: {
reference: 'target-2-ref',
label: 'target-2',
type: 'host',
},
advice: {
type: 'advice-type-2',
label: 'advice-2',
status: 'Implemented',
},
url: 'http://example.com/api/advice/2222',
},
],
};
return msw_1.HttpResponse.json(response);
}
else {
const response = {
totalItems: 3,
items: [
{
target: {
reference: 'target-3-ref',
label: 'target-3',
type: 'host',
},
advice: {
type: 'advice-type-3',
label: 'advice-3',
status: 'Action needed',
},
url: 'http://example.com/api/advice/3333',
},
],
};
return msw_1.HttpResponse.json(response);
}
}));
exports.handlers = [
executeUpsertExperimentHandler,
executeExperimentHandler,
upsertExperimentHandler,
updateExperimentHandler,
deleteExperimentHandler,
getExperimentHandler,
fetchAdviceHandler,
getTooManyRequestsHandler,
];
//# sourceMappingURL=handlers.js.map