fixed programming mode

This commit is contained in:
luckysideburn
2024-08-20 11:56:07 +00:00
parent 32051e54d9
commit 3801a51f63
12 changed files with 10589 additions and 187 deletions
+1 -36
View File
@@ -1,39 +1,4 @@
FROM nginx:stable
# Update repo and install some utilities and prerequisites
RUN apt-get update -y
RUN apt-get -y install git vim wget curl at gnupg procps
RUN apt-get -y install ca-certificates jq openssl task-spooler apt-transport-https python3 python3-pip redis libssl-dev
RUN apt-get -y install python3-yaml python3-kubernetes python3-redis python3-requests
# Install kubectl
RUN curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
RUN chmod +x ./kubectl
RUN mv ./kubectl /usr/local/bin/kubectl
# Install Openresty
RUN wget -O - https://openresty.org/package/pubkey.gpg | apt-key add -
RUN codename=`grep -Po 'VERSION="[0-9]+ \(\K[^)]+' /etc/os-release` && echo "deb http://openresty.org/package/debian $codename openresty" | tee /etc/apt/sources.list.d/openresty.list
RUN apt-get update -y
RUN apt-get -y install openresty
RUN chmod 777 /usr/local/openresty/nginx
# Install LUA Module
RUN apt-get -y install luarocks lua-json lua-socket libyaml-dev
RUN apt-get update --fix-missing
RUN luarocks install luasec
RUN luarocks install lunajson
RUN luarocks install lyaml
# Install kube-linter
RUN curl -L -O https://github.com/stackrox/kube-linter/releases/download/0.6.0/kube-linter-linux.tar.gz
RUN tar -xvf kube-linter-linux.tar.gz && rm -f kube-linter-linux.tar.gz
RUN cp kube-linter /usr/local/bin/ && chmod 775 /usr/local/bin/kube-linter
RUN mkdir /tmp/kube-linter-pods && chmod 777 /tmp/kube-linter-pods
# Installl parser script for kubelinter
COPY kube-linter/kube-linter-parser.sh /opt/kube-linter-parser.sh
RUN chmod +x /opt/kube-linter-parser.sh
FROM 10.10.10.3:5000/local/kubeinvaders_base:develop
# Install KubeInvaders (html and js)
COPY html5/ /var/www/html
+77
View File
@@ -0,0 +1,77 @@
FROM nginx:stable
# Update repo and install some utilities and prerequisites
RUN apt-get update -y
RUN apt-get -y install git vim wget curl at gnupg procps
RUN apt-get -y install ca-certificates jq openssl task-spooler apt-transport-https python3 python3-pip redis libssl-dev
RUN apt-get -y install python3-yaml python3-kubernetes python3-redis python3-requests
# Install kubectl
RUN curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"
RUN chmod +x ./kubectl
RUN mv ./kubectl /usr/local/bin/kubectl
# Install Openresty
RUN wget -O - https://openresty.org/package/pubkey.gpg | apt-key add -
RUN codename=`grep -Po 'VERSION="[0-9]+ \(\K[^)]+' /etc/os-release` && echo "deb http://openresty.org/package/debian $codename openresty" | tee /etc/apt/sources.list.d/openresty.list
RUN apt-get update -y
RUN apt-get -y install openresty
RUN chmod 777 /usr/local/openresty/nginx
# Install LUA Module
RUN apt-get -y install luarocks lua-json lua-socket libyaml-dev
RUN apt-get update --fix-missing
RUN luarocks install luasec
RUN luarocks install lunajson
RUN luarocks install lyaml
# Install kube-linter
RUN curl -L -O https://github.com/stackrox/kube-linter/releases/download/0.6.0/kube-linter-linux.tar.gz
RUN tar -xvf kube-linter-linux.tar.gz && rm -f kube-linter-linux.tar.gz
RUN cp kube-linter /usr/local/bin/ && chmod 775 /usr/local/bin/kube-linter
RUN mkdir /tmp/kube-linter-pods && chmod 777 /tmp/kube-linter-pods
# Installl parser script for kubelinter
COPY kube-linter/kube-linter-parser.sh /opt/kube-linter-parser.sh
RUN chmod +x /opt/kube-linter-parser.sh
# Install KubeInvaders (html and js)
COPY html5/ /var/www/html
# Configure Redis
COPY confs/redis/redis.conf /etc/redis/redis.conf
# Configure Nginx and KubeInvaders conf
RUN sed -i.bak 's/listen\(.*\)80;/listen 8081;/' /etc/nginx/conf.d/default.conf
RUN mkdir -p /usr/local/openresty/nginx/conf/kubeinvaders/data
COPY nginx/nginx.conf /etc/nginx/nginx.conf
COPY nginx/KubeInvaders.conf /etc/nginx/conf.d/KubeInvaders.conf
RUN chmod g+rwx /var/cache/nginx /var/run /var/log/nginx /etc/nginx/conf.d
RUN chmod 777 /var/www/html
# Copy LUA scripts
COPY scripts/metrics.lua /usr/local/openresty/nginx/conf/kubeinvaders/metrics.lua
COPY scripts/pod.lua /usr/local/openresty/nginx/conf/kubeinvaders/pod.lua
COPY scripts/ingress.lua /usr/local/openresty/nginx/conf/kubeinvaders/ingress.lua
COPY scripts/node.lua /usr/local/openresty/nginx/conf/kubeinvaders/node.lua
COPY scripts/kube-linter.lua /usr/local/openresty/nginx/conf/kubeinvaders/kube-linter.lua
COPY scripts/chaos-node.lua /usr/local/openresty/nginx/conf/kubeinvaders/chaos-node.lua
COPY scripts/chaos-containers.lua /usr/local/openresty/nginx/conf/kubeinvaders/chaos-containers.lua
COPY scripts/programming_mode.lua /usr/local/openresty/nginx/conf/kubeinvaders/programming_mode.lua
COPY scripts/config_kubeinv.lua /usr/local/openresty/lualib/config_kubeinv.lua
COPY scripts/data/codenames.txt /usr/local/openresty/nginx/conf/kubeinvaders/data/codenames.txt
# Copy Python helpers
COPY scripts/programming_mode /opt/programming_mode/
COPY scripts/metrics_loop /opt/metrics_loop/
COPY scripts/logs_loop /opt/logs_loop/
EXPOSE 8080
ENV PATH=/usr/local/openresty/nginx/sbin:$PATH
COPY ./entrypoint.sh /
RUN chmod a+rwx ./entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
+42
View File
@@ -0,0 +1,42 @@
FROM 10.10.10.3:5000/local/kubeinvaders_base:develop
# Install KubeInvaders (html and js)
COPY html5/ /var/www/html
# Configure Redis
COPY confs/redis/redis.conf /etc/redis/redis.conf
# Configure Nginx and KubeInvaders conf
RUN sed -i.bak 's/listen\(.*\)80;/listen 8081;/' /etc/nginx/conf.d/default.conf
RUN mkdir -p /usr/local/openresty/nginx/conf/kubeinvaders/data
COPY nginx/nginx.conf /etc/nginx/nginx.conf
COPY nginx/KubeInvaders.conf /etc/nginx/conf.d/KubeInvaders.conf
RUN chmod g+rwx /var/cache/nginx /var/run /var/log/nginx /etc/nginx/conf.d
RUN chmod 777 /var/www/html
# Copy LUA scripts
COPY scripts/metrics.lua /usr/local/openresty/nginx/conf/kubeinvaders/metrics.lua
COPY scripts/pod.lua /usr/local/openresty/nginx/conf/kubeinvaders/pod.lua
COPY scripts/ingress.lua /usr/local/openresty/nginx/conf/kubeinvaders/ingress.lua
COPY scripts/node.lua /usr/local/openresty/nginx/conf/kubeinvaders/node.lua
COPY scripts/kube-linter.lua /usr/local/openresty/nginx/conf/kubeinvaders/kube-linter.lua
COPY scripts/chaos-node.lua /usr/local/openresty/nginx/conf/kubeinvaders/chaos-node.lua
COPY scripts/chaos-containers.lua /usr/local/openresty/nginx/conf/kubeinvaders/chaos-containers.lua
COPY scripts/programming_mode.lua /usr/local/openresty/nginx/conf/kubeinvaders/programming_mode.lua
COPY scripts/config_kubeinv.lua /usr/local/openresty/lualib/config_kubeinv.lua
COPY scripts/data/codenames.txt /usr/local/openresty/nginx/conf/kubeinvaders/data/codenames.txt
# Copy Python helpers
COPY scripts/programming_mode /opt/programming_mode/
COPY scripts/metrics_loop /opt/metrics_loop/
COPY scripts/logs_loop /opt/logs_loop/
EXPOSE 8080
ENV PATH=/usr/local/openresty/nginx/sbin:$PATH
COPY ./entrypoint.sh /
RUN chmod a+rwx ./entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
+344
View File
@@ -0,0 +1,344 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
color: black;
direction: ltr;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror-cursor {
border-left: 1px solid black;
border-right: none;
width: 0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0 !important;
background: #7e7;
}
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-fat-cursor .CodeMirror-line::selection,
.cm-fat-cursor .CodeMirror-line > span::selection,
.cm-fat-cursor .CodeMirror-line > span > span::selection { background: transparent; }
.cm-fat-cursor .CodeMirror-line::-moz-selection,
.cm-fat-cursor .CodeMirror-line > span::-moz-selection,
.cm-fat-cursor .CodeMirror-line > span > span::-moz-selection { background: transparent; }
.cm-fat-cursor { caret-color: transparent; }
@-moz-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@-webkit-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror-overwrite .CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-rulers {
position: absolute;
left: 0; right: 0; top: -50px; bottom: 0;
overflow: hidden;
}
.CodeMirror-ruler {
border-left: 1px solid #ccc;
top: 0; bottom: 0;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
.CodeMirror-composing { border-bottom: 2px solid; }
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
position: relative;
overflow: hidden;
background: white;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 50px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -50px; margin-right: -50px;
padding-bottom: 50px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
z-index: 0;
}
.CodeMirror-sizer {
position: relative;
border-right: 50px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
outline: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
min-height: 100%;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: -50px;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: contextual;
font-variant-ligatures: contextual;
}
.CodeMirror-wrap pre.CodeMirror-line,
.CodeMirror-wrap pre.CodeMirror-line-like {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
padding: 0.1px; /* Force widget margins to stay inside of the container */
}
.CodeMirror-widget {}
.CodeMirror-rtl pre { direction: rtl; }
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-cursor {
position: absolute;
pointer-events: none;
}
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching {
background-color: #ffa;
background-color: rgba(255, 255, 0, .4);
}
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }
+9884
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -8,6 +8,9 @@
<link rel="stylesheet" href="./bootstrap-5.0.0-dist/css/bootstrap.min.css">
<link rel="stylesheet" href="./style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<link rel="stylesheet" href="./codemirror.css">
<script src="./codemirror.js"></script>
<style>
/* Adjust styling for sidebar */
*, button, div, canvas,a,p,h1,h2,h3,h4,h5 {
@@ -110,7 +113,6 @@
<!-- Main content -->
<div class="main-content">
<!-- Navbar -->
<span style="color:white" class="toggler-icon" onclick="toggleSidebar()">
<i class="fas fa-bars"></i>
</span>
@@ -475,7 +477,6 @@ k8s_jobs:
additional-labels:
chaos-controller: kubeinvaders
chaos-type: stress-ng
chaos-codename: CODENAME_PLACEHOLDER
image: docker.io/luckysideburn/kubeinvaders-stress-ng:latest
command: "stress-ng"
args:
@@ -484,7 +485,6 @@ k8s_jobs:
additional-labels:
chaos-controller: kubeinvaders
chaos-type: stress-ng
chaos-codename: CODENAME_PLACEHOLDER
image: docker.io/luckysideburn/kubeinvaders-stress-ng:latest
command: "stress-ng"
args:
+30 -14
View File
@@ -39,6 +39,7 @@ var randomFactor = 10;
var pods = [];
var game_mode_switch = false;
var programming_mode_switch = false;
var chaos_program_valid = false;
var now = "";
var game_buttons = document.getElementById("game-buttons");
var game_screen = document.getElementById("game-screen");
@@ -48,7 +49,8 @@ var log_tail_switch = false;
var log_tail_div = document.getElementById("logTailDiv");
var log_tail_screen = document.getElementById("logTailScreen");
var random_code = (Math.random() + 1).toString(36).substring(7);
var change_codename = false;
var latest_sent_chaos_program = "";
// nodes list from kubernetes
var nodes = [];
@@ -128,19 +130,31 @@ var chart_status_code_dict = {
};
function getCodeName() {
var oReq = new XMLHttpRequest();
oReq.onreadystatechange = function () {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
codename = this.responseText.trim();
if (codename == "") {
$('#alert_placeholder').replaceWith(alert_div + 'Error getting codename from backend. </div>');
codename = "error_fix_getcodename_from_backend";
}
}
};;
oReq.open("GET", k8s_url + "/codename");
oReq.send();
const prefixes = ['astro', 'cosmo', 'space', 'star', 'nova', 'nebula', 'galaxy', 'super', 'hyper', 'quantum'];
const suffixes = ['nova', 'tron', 'wave', 'core', 'pulse', 'jump', 'drive', 'ship', 'gate', 'hole'];
const prefix = prefixes[Math.floor(Math.random() * prefixes.length)];
const suffix = suffixes[Math.floor(Math.random() * suffixes.length)];
const  
codename = prefix + suffix;
return codename;
}
// function getCodeName() {
// var oReq = new XMLHttpRequest();
// oReq.onreadystatechange = function () {
// if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
// codename = this.responseText.trim();
// if (codename == "") {
// $('#alert_placeholder').replaceWith(alert_div + 'Error getting codename from backend. </div>');
// codename = "error_fix_getcodename_from_backend";
// }
// }
// };;
// oReq.open("GET", k8s_url + "/codename");
// oReq.send();
// }
function setCodeNameToTextInput(elementId) {
var oReq = new XMLHttpRequest();
@@ -871,6 +885,8 @@ window.setInterval(function backgroundTasks() {
chaosProgram = $('#chaosProgramTextArea').val();
chaosProgramWithCodename = chaosProgram.replace(codename_regex, "chaos-codename: " + codename);
$('#chaosProgramTextArea').val(chaosProgramWithCodename);
$('#chaosProgramTextArea').text(chaosProgramWithCodename);
chaosProgram = chaosProgramWithCodename;
codename_configured = true;
}
@@ -885,7 +901,7 @@ window.setInterval(function backgroundTasks() {
getTotalLogsPos();
}
if (programming_mode_switch) {
if (programming_mode_switch && chaos_program_valid) {
drawChaosProgramFlow();
}
+7 -1
View File
@@ -36,7 +36,6 @@ function startGameMode() {
}
function startProgrammingMode() {
if (is_demo_mode()) {
demo_mode_alert();
return;
@@ -67,4 +66,11 @@ function startProgrammingMode() {
}
game_buttons.style.display = "none";
game_screen.style.display = "none";
// var editor = CodeMirror.fromTextArea(chaosProgramTextArea, {
// lineNumbers: true,
// theme: "dracula"
// });
//editor.setSize("100%", "100%");
}
+69 -46
View File
@@ -1,3 +1,12 @@
function replaceDivWithContent(divId, content) {
document.getElementById(divId).innerHTML = content;
}
function getChaosProgTextAreaValue() {
const chaosProgramTextArea = document.getElementById('chaosProgramTextArea');
const textValue = chaosProgramTextArea.value;
return textValue;
}
/* Programming Mode Functions */
function IsJsonString(str) {
try {
@@ -10,24 +19,7 @@ function IsJsonString(str) {
/* TODO: this is very bad... change asap :D */
loadPresetsCodeJson = `{
"default": "Y2hhb3MtY29kZW5hbWU6IGxpdGhpdW0Kam9iczoKICBjcHUtYXR0YWNrLWpvYjoKICAgIGFkZGl0aW9uYWwtbGFiZWxzOgogICAgICBjaGFvcy1jb250cm9sbGVyOiBrdWJlaW52YWRlcnMKICAgICAgY2hhb3MtdHlwZTogc3RyZXNzLW5nCiAgICAgIGNoYW9zLWNvZGVuYW1lOiBsaXRoaXVtCiAgICBpbWFnZTogZG9ja2VyLmlvL2x1Y2t5c2lkZWJ1cm4va3ViZWludmFkZXJzLXN0cmVzcy1uZzpsYXRlc3QKICAgIGNvbW1hbmQ6ICJzdHJlc3MtbmciCiAgICBhcmdzOgogICAgICAtIC0taGVscAoKICBtZW0tYXR0YWNrLWpvYjoKICAgIGFkZGl0aW9uYWwtbGFiZWxzOgogICAgICBjaGFvcy1jb250cm9sbGVyOiBrdWJlaW52YWRlcnMKICAgICAgY2hhb3MtdHlwZTogc3RyZXNzLW5nCiAgICAgIGNoYW9zLWNvZGVuYW1lOiBsaXRoaXVtCiAgICBpbWFnZTogZG9ja2VyLmlvL2x1Y2t5c2lkZWJ1cm4va3ViZWludmFkZXJzLXN0cmVzcy1uZzpsYXRlc3QKICAgIGNvbW1hbmQ6ICJzdHJlc3MtbmciCiAgICBhcmdzOgogICAgICAtIC0taGVscAoKZXhwZXJpbWVudHM6CiAgLSBuYW1lOiBjcHUtYXR0YWNrLWV4cAogICAgam9iOiBjcHUtYXR0YWNrLWpvYgogICAgbG9vcDogNQoKICAtIG5hbWU6IG1lbS1hdHRhY2stZXhwCiAgICBqb2I6IG1lbS1hdHRhY2stam9iCiAgICBsb29wOiA1CiAK",
"cassandra": "ZnJvbSBjYXNzYW5kcmEuY2x1c3RlciBpbXBvcnQgQ2x1c3Rlcgpmcm9tIHJhbmRvbSBpbXBvcnQgcmFuZGludAppbXBvcnQgdGltZQoKZGVmIG1haW4oKToKICAgIGNsdXN0ZXIgPSBDbHVzdGVyKFsnMTI3LjAuMC4xJ10pCiAgICBzZXNzaW9uID0gY2x1c3Rlci5jb25uZWN0KCkKCiAgICBzZXNzaW9uLmV4ZWN1dGUoIkNSRUFURSBLRVlTUEFDRSBJRiBOT1QgRVhJU1RTIHRlc3QgV0lUSCBSRVBMSUNBVElPTiA9IHsgJ2NsYXNzJzogJ1NpbXBsZVN0cmF0ZWd5JywgJ3JlcGxpY2F0aW9uX2ZhY3Rvcic6IDEgfSIpCiAgICBzZXNzaW9uLmV4ZWN1dGUoIkNSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIHRlc3QubWVzc2FnZXMgKGlkIGludCBQUklNQVJZIEtFWSwgbWVzc2FnZSB0ZXh0KSIpCgogICAgZm9yIGkgaW4gcmFuZ2UoMTAwMCk6CiAgICAgICAgc2Vzc2lvbi5leGVjdXRlKCJJTlNFUlQgSU5UTyB0ZXN0Lm1lc3NhZ2VzIChpZCwgbWVzc2FnZSkgVkFMVUVTICglcywgJyVzJykiICUgKGksIHN0cihyYW5kaW50KDAsIDEwMDApKSkpCiAgICAgICAgdGltZS5zbGVlcCgwLjAwMSkKCiAgICBjbHVzdGVyLnNodXRkb3duKCkKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBtYWluKCk=",
"consul": "aW1wb3J0IHRpbWUKaW1wb3J0IGNvbnN1bAoKIyBDb25uZWN0IHRvIHRoZSBDb25zdWwgY2x1c3RlcgpjbGllbnQgPSBjb25zdWwuQ29uc3VsKCkKCiMgQ29udGludW91c2x5IHJlZ2lzdGVyIGFuZCBkZXJlZ2lzdGVyIGEgc2VydmljZQp3aGlsZSBUcnVlOgogICAgIyBSZWdpc3RlciB0aGUgc2VydmljZQogICAgY2xpZW50LmFnZW50LnNlcnZpY2UucmVnaXN0ZXIoCiAgICAgICAgInN0cmVzcy10ZXN0LXNlcnZpY2UiLAogICAgICAgIHBvcnQ9ODA4MCwKICAgICAgICB0YWdzPVsic3RyZXNzLXRlc3QiXSwKICAgICAgICBjaGVjaz1jb25zdWwuQ2hlY2soKS50Y3AoImxvY2FsaG9zdCIsIDgwODAsICIxMHMiKQogICAgKQoKICAgICMgRGVyZWdpc3RlciB0aGUgc2VydmljZQogICAgY2xpZW50LmFnZW50LnNlcnZpY2UuZGVyZWdpc3Rlcigic3RyZXNzLXRlc3Qtc2VydmljZSIpCgogICAgdGltZS5zbGVlcCgxKQoK",
"elasticsearch": "aW1wb3J0IHRpbWUKZnJvbSBlbGFzdGljc2VhcmNoIGltcG9ydCBFbGFzdGljc2VhcmNoCgojIENvbm5lY3QgdG8gdGhlIEVsYXN0aWNzZWFyY2ggY2x1c3RlcgplcyA9IEVsYXN0aWNzZWFyY2goWyJsb2NhbGhvc3QiXSkKCiMgQ29udGludW91c2x5IGluZGV4IGFuZCBkZWxldGUgZG9jdW1lbnRzCndoaWxlIFRydWU6CiAgICAjIEluZGV4IGEgZG9jdW1lbnQKICAgIGVzLmluZGV4KGluZGV4PSJ0ZXN0LWluZGV4IiwgZG9jX3R5cGU9InRlc3QtdHlwZSIsIGlkPTEsIGJvZHk9eyJ0ZXN0IjogInRlc3QifSkKCiAgICAjIERlbGV0ZSB0aGUgZG9jdW1lbnQKICAgIGVzLmRlbGV0ZShpbmRleD0idGVzdC1pbmRleCIsIGRvY190eXBlPSJ0ZXN0LXR5cGUiLCBpZD0xKQoKICAgIHRpbWUuc2xlZXAoMSkKCg==",
"etcd3": "aW1wb3J0IHRpbWUKaW1wb3J0IGV0Y2QzCgojIENvbm5lY3QgdG8gdGhlIGV0Y2QzIGNsdXN0ZXIKY2xpZW50ID0gZXRjZDMuY2xpZW50KCkKCiMgQ29udGludW91c2x5IHNldCBhbmQgZGVsZXRlIGtleXMKd2hpbGUgVHJ1ZToKICAgICMgU2V0IGEga2V5CiAgICBjbGllbnQucHV0KCIvc3RyZXNzLXRlc3Qta2V5IiwgInN0cmVzcyB0ZXN0IHZhbHVlIikKCiAgICAjIERlbGV0ZSB0aGUga2V5CiAgICBjbGllbnQuZGVsZXRlKCIvc3RyZXNzLXRlc3Qta2V5IikKCiAgICB0aW1lLnNsZWVwKDEpCgo=",
"gitlab": "aW1wb3J0IGdpdGxhYgppbXBvcnQgcmVxdWVzdHMKaW1wb3J0IHRpbWUKCmdsID0gZ2l0bGFiLkdpdGxhYignaHR0cHM6Ly9naXRsYWIuZXhhbXBsZS5jb20nLCBwcml2YXRlX3Rva2VuPSdteV9wcml2YXRlX3Rva2VuJykKCmRlZiBjcmVhdGVfcHJvamVjdCgpOgogICAgcHJvamVjdCA9IGdsLnByb2plY3RzLmNyZWF0ZSh7J25hbWUnOiAnTXkgUHJvamVjdCd9KQogICAgcHJpbnQoIkNyZWF0ZWQgcHJvamVjdDogIiwgcHJvamVjdC5uYW1lKQoKZGVmIG1haW4oKToKICAgIGZvciBpIGluIHJhbmdlKDEwMDApOgogICAgICAgIGNyZWF0ZV9wcm9qZWN0KCkKICAgICAgICB0aW1lLnNsZWVwKDAuMDAxKQoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIG1haW4oKQ==",
"http": "aW1wb3J0IHRpbWUKaW1wb3J0IHJlcXVlc3RzCgojIFNldCB1cCB0aGUgVVJMIHRvIHNlbmQgcmVxdWVzdHMgdG8KdXJsID0gJ2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC8nCgojIFNldCB1cCB0aGUgbnVtYmVyIG9mIHJlcXVlc3RzIHRvIHNlbmQKbnVtX3JlcXVlc3RzID0gMTAwMDAKCiMgU2V0IHVwIHRoZSBwYXlsb2FkIHRvIHNlbmQKcGF5bG9hZCA9IHsna2V5JzogJ3ZhbHVlJ30KCiMgU2VuZCB0aGUgcmVxdWVzdHMKc3RhcnRfdGltZSA9IHRpbWUudGltZSgpCmZvciBpIGluIHJhbmdlKG51bV9yZXF1ZXN0cyk6CiAgICByZXF1ZXN0cy5wb3N0KHVybCwganNvbj1wYXlsb2FkKQplbmRfdGltZSA9IHRpbWUudGltZSgpCgojIENhbGN1bGF0ZSB0aGUgdGhyb3VnaHB1dAp0aHJvdWdocHV0ID0gbnVtX3JlcXVlc3RzIC8gKGVuZF90aW1lIC0gc3RhcnRfdGltZSkKcHJpbnQoZidUaHJvdWdocHV0OiB7dGhyb3VnaHB1dH0gcmVxdWVzdHMvc2Vjb25kJykKCg==",
"jira": "aW1wb3J0IHRpbWUKZnJvbSBqaXJhIGltcG9ydCBKSVJBCgojIENvbm5lY3QgdG8gdGhlIEppcmEgaW5zdGFuY2UKamlyYSA9IEpJUkEoCiAgICBzZXJ2ZXI9Imh0dHBzOi8vamlyYS5leGFtcGxlLmNvbSIsCiAgICBiYXNpY19hdXRoPSgidXNlciIsICJwYXNzd29yZCIpCikKCiMgQ29udGludW91c2x5IGNyZWF0ZSBhbmQgZGVsZXRlIGlzc3Vlcwp3aGlsZSBUcnVlOgogICAgIyBDcmVhdGUgYW4gaXNzdWUKICAgIGlzc3VlID0gamlyYS5jcmVhdGVfaXNzdWUoCiAgICAgICAgcHJvamVjdD0iUFJPSkVDVCIsCiAgICAgICAgc3VtbWFyeT0iU3RyZXNzIHRlc3QgaXNzdWUiLAogICAgICAgIGRlc2NyaXB0aW9uPSJUaGlzIGlzIGEgc3RyZXNzIHRlc3QgaXNzdWUuIiwKICAgICAgICBpc3N1ZXR5cGU9eyJuYW1lIjogIkJ1ZyJ9CiAgICApCgogICAgIyBEZWxldGUgdGhlIGlzc3VlCiAgICBqaXJhLmRlbGV0ZV9pc3N1ZShpc3N1ZSkKCiAgICB0aW1lLnNsZWVwKDEpCgo=",
"kafka": "aW1wb3J0IHRpbWUKaW1wb3J0IHJhbmRvbQoKZnJvbSBrYWZrYSBpbXBvcnQgS2Fma2FQcm9kdWNlcgoKIyBTZXQgdXAgdGhlIEthZmthIHByb2R1Y2VyCnByb2R1Y2VyID0gS2Fma2FQcm9kdWNlcihib290c3RyYXBfc2VydmVycz1bJ2xvY2FsaG9zdDo5MDkyJ10pCgojIFNldCB1cCB0aGUgdG9waWMgdG8gc2VuZCBtZXNzYWdlcyB0bwp0b3BpYyA9ICd0ZXN0JwoKIyBTZXQgdXAgdGhlIG51bWJlciBvZiBtZXNzYWdlcyB0byBzZW5kCm51bV9tZXNzYWdlcyA9IDEwMDAwCgojIFNldCB1cCB0aGUgcGF5bG9hZCB0byBzZW5kCnBheWxvYWQgPSBiJ2EnICogMTAwMDAwMAoKIyBTZW5kIHRoZSBtZXNzYWdlcwpzdGFydF90aW1lID0gdGltZS50aW1lKCkKZm9yIGkgaW4gcmFuZ2UobnVtX21lc3NhZ2VzKToKICAgIHByb2R1Y2VyLnNlbmQodG9waWMsIHBheWxvYWQpCmVuZF90aW1lID0gdGltZS50aW1lKCkKCiMgQ2FsY3VsYXRlIHRoZSB0aHJvdWdocHV0CnRocm91Z2hwdXQgPSBudW1fbWVzc2FnZXMgLyAoZW5kX3RpbWUgLSBzdGFydF90aW1lKQpwcmludChmJ1Rocm91Z2hwdXQ6IHt0aHJvdWdocHV0fSBtZXNzYWdlcy9zZWNvbmQnKQoKIyBGbHVzaCBhbmQgY2xvc2UgdGhlIHByb2R1Y2VyCnByb2R1Y2VyLmZsdXNoKCkKcHJvZHVjZXIuY2xvc2UoKQo=",
"kubernetes": "aW1wb3J0IHRpbWUKaW1wb3J0IGt1YmVybmV0ZXMKCiMgQ3JlYXRlIGEgS3ViZXJuZXRlcyBjbGllbnQKY2xpZW50ID0ga3ViZXJuZXRlcy5jbGllbnQuQ29yZVYxQXBpKCkKCiMgQ29udGludW91c2x5IGNyZWF0ZSBhbmQgZGVsZXRlIHBvZHMKd2hpbGUgVHJ1ZToKICAgICMgQ3JlYXRlIGEgcG9kCiAgICBwb2QgPSBrdWJlcm5ldGVzLmNsaWVudC5WMVBvZCgKICAgICAgICBtZXRhZGF0YT1rdWJlcm5ldGVzLmNsaWVudC5WMU9iamVjdE1ldGEobmFtZT0ic3RyZXNzLXRlc3QtcG9kIiksCiAgICAgICAgc3BlYz1rdWJlcm5ldGVzLmNsaWVudC5WMVBvZFNwZWMoCiAgICAgICAgICAgIGNvbnRhaW5lcnM9W2t1YmVybmV0ZXMuY2xpZW50LlYxQ29udGFpbmVyKAogICAgICAgICAgICAgICAgbmFtZT0ic3RyZXNzLXRlc3QtY29udGFpbmVyIiwKICAgICAgICAgICAgICAgIGltYWdlPSJuZ2lueDpsYXRlc3QiCiAgICAgICAgICAgICldCiAgICAgICAgKQogICAgKQogICAgY2xpZW50LmNyZWF0ZV9uYW1lc3BhY2VkX3BvZChuYW1lc3BhY2U9ImRlZmF1bHQiLCBib2R5PXBvZCkKCiAgICAjIERlbGV0ZSB0aGUgcG9kCiAgICBjbGllbnQuZGVsZXRlX25hbWVzcGFjZWRfcG9kKG5hbWU9InN0cmVzcy10ZXN0LXBvZCIsIG5hbWVzcGFjZT0iZGVmYXVsdCIpCgogICAgdGltZS5zbGVlcCgxKQoK",
"mongodb": "aW1wb3J0IHRpbWUKaW1wb3J0IHJhbmRvbQpmcm9tIHB5bW9uZ28gaW1wb3J0IE1vbmdvQ2xpZW50CgojIFNldCB1cCB0aGUgTW9uZ29EQiBjbGllbnQKY2xpZW50ID0gTW9uZ29DbGllbnQoJ21vbmdvZGI6Ly9sb2NhbGhvc3Q6MjcwMTcvJykKCiMgU2V0IHVwIHRoZSBkYXRhYmFzZSBhbmQgY29sbGVjdGlvbiB0byB1c2UKZGIgPSBjbGllbnRbJ3Rlc3QnXQpjb2xsZWN0aW9uID0gZGJbJ3Rlc3QnXQoKIyBTZXQgdXAgdGhlIG51bWJlciBvZiBkb2N1bWVudHMgdG8gaW5zZXJ0Cm51bV9kb2N1bWVudHMgPSAxMDAwMAoKIyBTZXQgdXAgdGhlIHBheWxvYWQgdG8gaW5zZXJ0CnBheWxvYWQgPSB7J2tleSc6ICdhJyAqIDEwMDAwMDB9CgojIEluc2VydCB0aGUgZG9jdW1lbnRzCnN0YXJ0X3RpbWUgPSB0aW1lLnRpbWUoKQpmb3IgaSBpbiByYW5nZShudW1fZG9jdW1lbnRzKToKICAgIGNvbGxlY3Rpb24uaW5zZXJ0X29uZShwYXlsb2FkKQplbmRfdGltZSA9IHRpbWUudGltZSgpCgojIENhbGN1bGF0ZSB0aGUgdGhyb3VnaHB1dAp0aHJvdWdocHV0ID0gbnVtX2RvY3VtZW50cyAvIChlbmRfdGltZSAtIHN0YXJ0X3RpbWUpCnByaW50KGYnVGhyb3VnaHB1dDoge3Rocm91Z2hwdXR9IGRvY3VtZW50cy9zZWNvbmQnKQoKIyBDbG9zZSB0aGUgY2xpZW50CmNsaWVudC5jbG9zZSgpCgo=",
"mysql": "aW1wb3J0IHRpbWUKaW1wb3J0IG15c3FsLmNvbm5lY3RvcgoKIyBDb25uZWN0IHRvIHRoZSBNeVNRTCBkYXRhYmFzZQpjbnggPSBteXNxbC5jb25uZWN0b3IuY29ubmVjdCgKICAgIGhvc3Q9ImxvY2FsaG9zdCIsCiAgICB1c2VyPSJyb290IiwKICAgIHBhc3N3b3JkPSJwYXNzd29yZCIsCiAgICBkYXRhYmFzZT0idGVzdCIKKQpjdXJzb3IgPSBjbnguY3Vyc29yKCkKCiMgQ29udGludW91c2x5IGluc2VydCByb3dzIGludG8gdGhlICJ0ZXN0X3RhYmxlIiB0YWJsZQp3aGlsZSBUcnVlOgogICAgY3Vyc29yLmV4ZWN1dGUoIklOU0VSVCBJTlRPIHRlc3RfdGFibGUgKGNvbDEsIGNvbDIpIFZBTFVFUyAoJXMsICVzKSIsICgxLCAyKSkKICAgIGNueC5jb21taXQoKQogICAgdGltZS5zbGVlcCgxKQoKIyBDbG9zZSB0aGUgZGF0YWJhc2UgY29ubmVjdGlvbgpjbnguY2xvc2UoKQoK",
"nomad": "aW1wb3J0IHRpbWUKaW1wb3J0IG5vbWFkCgojIENyZWF0ZSBhIE5vbWFkIGNsaWVudApjbGllbnQgPSBub21hZC5Ob21hZCgpCgojIENyZWF0ZSBhIGJhdGNoIG9mIGpvYnMgdG8gc3VibWl0IHRvIE5vbWFkCmpvYnMgPSBbewogICAgIk5hbWUiOiAic3RyZXNzLXRlc3Qtam9iIiwKICAgICJUeXBlIjogImJhdGNoIiwKICAgICJEYXRhY2VudGVycyI6IFsiZGMxIl0sCiAgICAiVGFza0dyb3VwcyI6IFt7CiAgICAgICAgIk5hbWUiOiAic3RyZXNzLXRlc3QtdGFzay1ncm91cCIsCiAgICAgICAgIlRhc2tzIjogW3sKICAgICAgICAgICAgIk5hbWUiOiAic3RyZXNzLXRlc3QtdGFzayIsCiAgICAgICAgICAgICJEcml2ZXIiOiAicmF3X2V4ZWMiLAogICAgICAgICAgICAiQ29uZmlnIjogewogICAgICAgICAgICAgICAgImNvbW1hbmQiOiAic2xlZXAgMTAiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJSZXNvdXJjZXMiOiB7CiAgICAgICAgICAgICAgICAiQ1BVIjogNTAwLAogICAgICAgICAgICAgICAgIk1lbW9yeU1CIjogNTEyCiAgICAgICAgICAgIH0KICAgICAgICB9XQogICAgfV0KfV0KCiMgQ29udGludW91c2x5IHN1Ym1pdCB0aGUgYmF0Y2ggb2Ygam9icyB0byBOb21hZAp3aGlsZSBUcnVlOgogICAgZm9yIGpvYiBpbiBqb2JzOgogICAgICAgIGNsaWVudC5qb2JzLmNyZWF0ZShqb2IpCiAgICB0aW1lLnNsZWVwKDEpCgo=",
"postgresql": "aW1wb3J0IHRpbWUKaW1wb3J0IHJhbmRvbQppbXBvcnQgcHN5Y29wZzIKCiMgU2V0IHVwIHRoZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMKcGFyYW1zID0gewogICAgJ2hvc3QnOiAnbG9jYWxob3N0JywKICAgICdwb3J0JzogJzU0MzInLAogICAgJ2RhdGFiYXNlJzogJ3Rlc3QnLAogICAgJ3VzZXInOiAncG9zdGdyZXMnLAogICAgJ3Bhc3N3b3JkJzogJ3Bhc3N3b3JkJwp9CgojIENvbm5lY3QgdG8gdGhlIGRhdGFiYXNlCmNvbm4gPSBwc3ljb3BnMi5jb25uZWN0KCoqcGFyYW1zKQoKIyBTZXQgdXAgdGhlIGN1cnNvcgpjdXIgPSBjb25uLmN1cnNvcigpCgojIFNldCB1cCB0aGUgdGFibGUgYW5kIHBheWxvYWQgdG8gaW5zZXJ0CnRhYmxlX25hbWUgPSAndGVzdCcKcGF5bG9hZCA9ICdhJyAqIDEwMDAwMDAKCiMgU2V0IHVwIHRoZSBudW1iZXIgb2Ygcm93cyB0byBpbnNlcnQKbnVtX3Jvd3MgPSAxMDAwMAoKIyBJbnNlcnQgdGhlIHJvd3MKc3RhcnRfdGltZSA9IHRpbWUudGltZSgpCmZvciBpIGluIHJhbmdlKG51bV9yb3dzKToKICAgIGN1ci5leGVjdXRlKGYiSU5TRVJUIElOVE8ge3RhYmxlX25hbWV9IChjb2wpIFZBTFVFUyAoJ3twYXlsb2FkfScpIikKY29ubi5jb21taXQoKQplbmRfdGltZSA9IHRpbWUudGltZSgpCgojIENhbGN1bGF0ZSB0aGUgdGhyb3VnaHB1dAp0aHJvdWdocHV0ID0gbnVtX3Jvd3MgLyAoZW5kX3RpbWUgLSBzdGFydF90aW1lKQpwcmludChmJ1Rocm91Z2hwdXQ6IHt0aHJvdWdocHV0fSByb3dzL3NlY29uZCcpCgojIENsb3NlIHRoZSBjdXJzb3IgYW5kIGNvbm5lY3Rpb24KY3VyLmNsb3NlKCkKY29ubi5jbG9zZSgpCgo=",
"prometheus": "aW1wb3J0IHRpbWUKaW1wb3J0IHJhbmRvbQpmcm9tIHByb21ldGhldXNfY2xpZW50IGltcG9ydCBDb2xsZWN0b3JSZWdpc3RyeSwgR2F1Z2UsIHB1c2hfdG9fZ2F0ZXdheQoKIyBTZXQgdXAgdGhlIG1ldHJpY3MgcmVnaXN0cnkKcmVnaXN0cnkgPSBDb2xsZWN0b3JSZWdpc3RyeSgpCgojIFNldCB1cCB0aGUgbWV0cmljIHRvIHB1c2gKZ2F1Z2UgPSBHYXVnZSgndGVzdF9nYXVnZScsICdBIHRlc3QgZ2F1Z2UnLCByZWdpc3RyeT1yZWdpc3RyeSkKCiMgU2V0IHVwIHRoZSBwdXNoIGdhdGV3YXkgVVJMCnB1c2hfZ2F0ZXdheSA9ICdodHRwOi8vbG9jYWxob3N0OjkwOTEnCgojIFNldCB1cCB0aGUgbnVtYmVyIG9mIHB1c2hlcyB0byBzZW5kCm51bV9wdXNoZXMgPSAxMDAwMAoKIyBTZXQgdXAgdGhlIG1ldHJpYyB2YWx1ZSB0byBwdXNoCnZhbHVlID0gcmFuZG9tLnJhbmRvbSgpCgojIFB1c2ggdGhlIG1ldHJpYwpzdGFydF90aW1lID0gdGltZS50aW1lKCkKZm9yIGkgaW4gcmFuZ2UobnVtX3B1c2hlcyk6CiAgICBnYXVnZS5zZXQodmFsdWUpCiAgICBwdXNoX3RvX2dhdGV3YXkocHVzaF9nYXRld2F5LCBqb2I9J3Rlc3Rfam9iJywgcmVnaXN0cnk9cmVnaXN0cnkpCmVuZF90aW1lID0gdGltZS50aW1lKCkKCiMgQ2FsY3VsYXRlIHRoZSB0aHJvdWdocHV0CnRocm91Z2hwdXQgPSBudW1fcHVzaGVzIC8gKGVuZF90aW1lIC0gc3RhcnRfdGltZSkKcHJpbnQoZidUaHJvdWdocHV0OiB7dGhyb3VnaHB1dH0gcHVzaGVzL3NlY29uZCcpCgo=",
"rabbit": "aW1wb3J0IHBpa2EKaW1wb3J0IHRpbWUKCmRlZiBzZW5kX21lc3NhZ2UoY2hhbm5lbCwgbWVzc2FnZSk6CiAgICBjaGFubmVsLmJhc2ljX3B1Ymxpc2goZXhjaGFuZ2U9JycsIHJvdXRpbmdfa2V5PSd0ZXN0X3F1ZXVlJywgYm9keT1tZXNzYWdlKQogICAgcHJpbnQoIlNlbnQgbWVzc2FnZTogIiwgbWVzc2FnZSkKCmRlZiBtYWluKCk6CiAgICBjb25uZWN0aW9uID0gcGlrYS5CbG9ja2luZ0Nvbm5lY3Rpb24ocGlrYS5Db25uZWN0aW9uUGFyYW1ldGVycygnbG9jYWxob3N0JykpCiAgICBjaGFubmVsID0gY29ubmVjdGlvbi5jaGFubmVsKCkKICAgIGNoYW5uZWwucXVldWVfZGVjbGFyZShxdWV1ZT0ndGVzdF9xdWV1ZScpCgogICAgZm9yIGkgaW4gcmFuZ2UoMTAwMCk6CiAgICAgICAgc2VuZF9tZXNzYWdlKGNoYW5uZWwsIHN0cihpKSkKICAgICAgICB0aW1lLnNsZWVwKDAuMDAxKQoKICAgIGNvbm5lY3Rpb24uY2xvc2UoKQoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIG1haW4oKQ==",
"SSH": "aW1wb3J0IHBhcmFtaWtvCgojIERlZmluZSBzZXJ2ZXJzIGFycmF5CnNlcnZlcnMgPSBbJ3NlcnZlcjEnLCAnc2VydmVyMicsICdzZXJ2ZXIzJ10KCmZvciBzZXJ2ZXIgaW4gc2VydmVyczoKICAgIHB1YmxpY19rZXkgPSBwYXJhbWlrby5SU0FLZXkoZGF0YT1iJ3lvdXItcHVibGljLWtleS1zdHJpbmcnKQogICAgc3NoID0gcGFyYW1pa28uU1NIQ2xpZW50KCkKICAgIHNzaC5zZXRfbWlzc2luZ19ob3N0X2tleV9wb2xpY3kocGFyYW1pa28uQXV0b0FkZFBvbGljeSgpKQogICAgc3NoLmNvbm5lY3QoaG9zdG5hbWU9J3lvdXItc2VydmVyLW5hbWUnLCB1c2VybmFtZT0neW91ci11c2VybmFtZScsIHBrZXk9cHVibGljX2tleSkKICAgIHN0ZGluLCBzdGRvdXQsIHN0ZGVyciA9IHNzaC5leGVjX2NvbW1hbmQoJ3lvdXItY29tbWFuZCcpCiAgICBwcmludChzdGRvdXQucmVhZCgpKQogICAgc3NoLmNsb3NlKCkK",
"vault": "aW1wb3J0IHRpbWUKaW1wb3J0IGh2YWMKCiMgQ29ubmVjdCB0byB0aGUgVmF1bHQgaW5zdGFuY2UKY2xpZW50ID0gaHZhYy5DbGllbnQoKQpjbGllbnQuYXV0aF9hcHByb2xlKGFwcHJvbGVfaWQ9ImFwcHJvbGUtaWQiLCBzZWNyZXRfaWQ9InNlY3JldC1pZCIpCgojIENvbnRpbnVvdXNseSByZWFkIGFuZCB3cml0ZSBzZWNyZXRzCndoaWxlIFRydWU6CiAgICAjIFdyaXRlIGEgc2VjcmV0CiAgICBjbGllbnQud3JpdGUoInNlY3JldC9zdHJlc3MtdGVzdCIsIHZhbHVlPSJzZWNyZXQgdmFsdWUiKQoKICAgICMgUmVhZCB0aGUgc2VjcmV0CiAgICBjbGllbnQucmVhZCgic2VjcmV0L3N0cmVzcy10ZXN0IikKCiAgICB0aW1lLnNsZWVwKDEpCgo="
"SSH": "aW1wb3J0IHBhcmFtaWtvCgojIERlZmluZSBzZXJ2ZXJzIGFycmF5CnNlcnZlcnMgPSBbJ3NlcnZlcjEnLCAnc2VydmVyMicsICdzZXJ2ZXIzJ10KCmZvciBzZXJ2ZXIgaW4gc2VydmVyczoKICAgIHB1YmxpY19rZXkgPSBwYXJhbWlrby5SU0FLZXkoZGF0YT1iJ3lvdXItcHVibGljLWtleS1zdHJpbmcnKQogICAgc3NoID0gcGFyYW1pa28uU1NIQ2xpZW50KCkKICAgIHNzaC5zZXRfbWlzc2luZ19ob3N0X2tleV9wb2xpY3kocGFyYW1pa28uQXV0b0FkZFBvbGljeSgpKQogICAgc3NoLmNvbm5lY3QoaG9zdG5hbWU9J3lvdXItc2VydmVyLW5hbWUnLCB1c2VybmFtZT0neW91ci11c2VybmFtZScsIHBrZXk9cHVibGljX2tleSkKICAgIHN0ZGluLCBzdGRvdXQsIHN0ZGVyciA9IHNzaC5leGVjX2NvbW1hbmQoJ3lvdXItY29tbWFuZCcpCiAgICBwcmludChzdGRvdXQucmVhZCgpKQogICAgc3NoLmNsb3NlKCkK"
}`;
function loadPreset(tool, lang) {
@@ -70,29 +62,54 @@ function loadPreset(tool, lang) {
}
function runChaosProgram() {
chaosProgram = $('#chaosProgramTextArea').val();
chaosProgramWithCodename = chaosProgram.replace(codename_regex, "chaos-codename: " + codename);
$('#chaosProgramTextArea').val(chaosProgramWithCodename);
codename_configured = true;
// if (chaosProgramWithCodename != $('#chaosProgramTextArea').text()) {
// random_code = (Math.random() + 1).toString(36).substring(7);
// codename = getCodeName();
// console.log("[RUN-CHAOS-PROGRAM] Running chaos program with codename: " + codename);
// }
//var now = new Date().toLocaleString().replace(',','')
//$('#alert_placeholder_programming_mode').replaceWith(alert_div + 'Chaos Program launched at ' + now + ' </div>');
//chaosProgramWithCodename = chaosProgram.replace(codename_regex, "chaos-codename: " + codename);
// $('#chaosProgramTextArea').val(chaosProgramWithCodename);
// $('#chaosProgramTextArea').text(chaosProgramWithCodename);
//codename_configured = true;
// Regex per estrarre il valore dopo "chaos-codename:"
//random_code = (Math.random() + 1).toString(36).substring(7);
const regex = /^chaos-codename:\s+(.*)$/m;
const match = chaosProgram.match(regex);
if (match) {
codename = match[1];
console.log(codename);
} else {
console.log("Valore chaos-codename non trovato");
}
var oReq = new XMLHttpRequest();
oReq.open("POST", k8s_url + "/kube/chaos/programming_mode?id=" + random_code, true);
oReq.onreadystatechange = function () {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
now = new Date().toLocaleString().replace(',','')
if (this.responseText.includes("Invalid")) {
$('#alert_placeholder_programming_mode').replaceWith(alert_div + this.responseText + ' </div>');
}
else {
$('#alert_placeholder_programming_mode').replaceWith(alert_div + this.responseText + 'Chaos Program loaded at ' + now + ' </div>');
}
}
if (this.readyState === XMLHttpRequest.DONE && this.status == 200) {
//console.log("[PROGRAMMING_MODE] Chaos program loaded... HTTP Status code: " + this.status);
now = new Date().toLocaleString().replace(',','')
if (this.responseText.includes("Invalid")) {
replaceDivWithContent('alert_placeholder_programming_mode', alert_div + this.responseText + ' </div>');
chaos_program_valid = false;
}
else {
// console.log("[PROGRAMMING_MODE] Write new status update of the latest loaded chaos program");
replaceDivWithContent('alert_placeholder_programming_mode', alert_div + '[PROGRAMMING_MODE] Chaos program ' + codename + ' loaded at ' + now + ' </div>');
chaos_program_valid = true;
}
}
else if (this.readyState === XMLHttpRequest.DONE && this.status != 200) {
replaceDivWithContent('alert_placeholder_programming_mode', alert_div + "[PROGRAMMING_MODE] Invalid chaos program code, please check yaml syntax or kubeinvaders logs</div>");
// console.log("[PROGRAMMING_MODE] Error. HTTP return code: " + this.status);
}
};;
oReq.setRequestHeader("Content-Type", "application/json");
oReq.send($('#chaosProgramTextArea').val());
console.log("Sending this program: " + getChaosProgTextAreaValue());
oReq.send(getChaosProgTextAreaValue());
}
function savePreset(action) {
@@ -106,7 +123,7 @@ function savePreset(action) {
presetName = codename + "-" + rand_id();
latest_preset_lang = "k-inv";
console.log("[SAVE-PRESET-CHAOSPROGRAM] lang: " + presetLang + " name:" + presetName);
presetBody = $('#chaosProgramTextArea').val();
presetBody = $('#chaosProgramTextArea').text();
document.getElementById("resetToDefaultButton").style.display = "none";
document.getElementById("deleteChaosProgramButton").style.display = "block";
}
@@ -134,17 +151,13 @@ function savePreset(action) {
oReq.onreadystatechange = function () {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200 && (action == "apply" || action == "save-chaos-program")) {
if (latest_preset_lang == "k-inv") {
// console.log("[SAVE-PRESET-CHAOSPROGRAM] Payload: " + $('#currentLoadTest').val());
if ($('#currentLoadTest').val() != "") {
presetBody = $('#currentLoadTest').val();
}
//$('#chaosProgramTextArea').val(presetBody);
document.getElementById("chaosProgramTextArea").value = presetBody;
}
//document.getElementById("chaosProgramTextArea").text = presetBody;
}
else {
presetBody = $('#chaosProgramTextArea').val(`chaos-codename: ${codename}
presetBody = $('#chaosProgramTextArea').text(`chaos-codename: ${codename}
jobs:
${presetName}-job:
additional-labels:
@@ -190,7 +203,7 @@ loop: 5`);
}
function drawChaosProgramFlow() {
var chaosProgram = "";
//var chaosProgram = "";
chaosProgram = $('#chaosProgramTextArea').val();
var oReq = new XMLHttpRequest();
@@ -199,7 +212,16 @@ function drawChaosProgramFlow() {
oReq.onreadystatechange = function () {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
if (IsJsonString(this.responseText)){
if (this.responseText.includes("Invalid")) {
$('#alert_placeholder_programming_mode').replaceWith(alert_div + this.responseText + ' </div>');
chaos_program_valid = false;
return;
}
var flow = JSON.parse(this.responseText);
// console.log("[DRAW-PROGRAM-FLOW] Drawing flow for " + codename);
// console.log("[DRAW-PROGRAM-FLOW] Drawing: " + JSON.stringify(flow));
var flow_html = "";
let i = 0;
var times = "";
@@ -271,9 +293,10 @@ function getSavedPresets() {
// document.getElementById(buttonId).classList.add('btn-light-saved');
}
}
} else {
console.log("[GET-PRESETS] There is no saved presets in Redis");
}
}
// else {
// console.log("[GET-PRESETS] There is no saved presets in Redis");
// }
}
};;
oReq.open("GET", k8s_url + "/chaos/loadpreset/savedpresets");
+55 -45
View File
@@ -3,6 +3,7 @@ server {
listen 8080 default_server;
root /var/www/html/;
index index.html;
access_log off;
set_by_lua_block $endpoint {
return os.getenv("ENDPOINT")
@@ -559,68 +560,77 @@ server {
local lyaml = require "lyaml"
local json = require 'lunajson'
math.randomseed(os.clock()*100000000000)
local rand = math.random(999, 9999)
local file_name = "/tmp/chaosprogram" .. rand
ngx.header['Access-Control-Allow-Origin'] = '*'
ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'
ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range';
ngx.req.read_body()
local data = ngx.req.get_body_data()
-- ngx.log(ngx.INFO, "[PROGRAMMING-MODE-DIAGRAM] data sent from web interface => " .. data)
math.randomseed(os.clock()*100000000000)
local rand = math.random(999, 9999)
local filename = "/tmp/chaosprogram" .. rand
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Chaos program payload sent from client: " .. data)
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Write temp file: " .. file_name)
-- ngx.log(ngx.INFO, "[PROGRAMMING-MODE-DIAGRAM] write temp file " .. filename)
local yamlfile = io.open(filename, "w")
local yamlfile = io.open(file_name, "w")
yamlfile:write(data)
yamlfile:close()
local handle = io.popen("python3 -c 'import yaml, sys; print(yaml.safe_load(sys.stdin))' < " .. filename)
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Checking if " .. file_name .. " is a valid YAML file")
local handle = io.popen("python3 -c 'import yaml, sys; print(yaml.safe_load(sys.stdin))' < " .. file_name .. " ; echo $? > " .. file_name .. ".check")
local result = handle:read("*a")
local rc = handle:close()
-- ngx.log(ngx.INFO, "[PROGRAMMING-MODE-DIAGRAM] Result of yaml syntax check =>||" .. result .. "||")
handle = io.popen("cat " .. file_name .. ".check")
result = handle:read("*a")
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Exit code for checking YAML syntax of " .. file_name .. " is " .. result)
if data == nil then
error = "[PROGRAMMING-MODE-DIAGRAM] No chaos program already loaded."
-- ngx.log(ngx.INFO, error)
ngx.say(error)
elseif not string.match(result, '{.*}') then
error = "[PROGRAMMING-MODE-DIAGRAM] Chaos program seems not correct. Please check yaml syntax."
-- ngx.log(ngx.INFO, error)
ngx.say(error)
if result == "0\n" then
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] YAML Syntax is OK")
else
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] YAML Syntax is NOT OK")
handle = io.popen("rm -f " .. file_name .. ".check")
handle:read("*a")
ngx.status = 400
ngx.say("Invalid YAML Chaos Program")
end
local yaml_data = lyaml.load(data)
if not key_exists(yaml_data, "k8s_jobs") then
error = "[PROGRAMMING-MODE-DIAGRAM] Chaos program does not contain 'jobs' key. Please fix yaml definition."
-- ngx.log(ngx.INFO, error)
ngx.say(error)
elseif not key_exists(yaml_data, "experiments") then
error = "[PROGRAMMING-MODE-DIAGRAM] Chaos program does not contain 'experiments' key. Please fix yaml definition"
-- ngx.log(ngx.INFO, error)
ngx.say(error)
elseif is_key_empty(yaml_data, "k8s_jobs") then
error = "[PROGRAMMING-MODE-DIAGRAM] Chaos program does not contain valid 'jobs' key. Please fix yaml definition, add jobs"
-- ngx.log(ngx.INFO, error)
ngx.say(error)
elseif is_key_empty(yaml_data, "experiments") then
error = "[PROGRAMMING-MODE-DIAGRAM] Chaos program does not contain valid 'experiments' key. Please fix yaml definition, add experiments"
-- ngx.log(ngx.INFO, error)
ngx.say(error)
if data == nil then
error = "[PROGRAMMING_MODE] No chaos program already loaded."
ngx.status = 400
ngx.say(error)
else
os.remove(filename)
local response = json.encode(yaml_data)
ngx.say(response)
local yaml_data = lyaml.load(data)
if not key_exists(yaml_data, "k8s_jobs") then
error = "[PROGRAMMING_MODE] Chaos program does not contain 'jobs' key."
ngx.status = 400
ngx.say(error)
elseif not key_exists(yaml_data, "experiments") then
error = "[PROGRAMMING_MODE] Chaos program does not contain 'experiments' key."
ngx.status = 400
ngx.say(error)
elseif is_key_empty(yaml_data, "k8s_jobs") then
error = "[PROGRAMMING_MODE] Chaos program does not contain valid 'jobs' key."
ngx.status = 400
ngx.say(error)
elseif is_key_empty(yaml_data, "experiments") then
error = "[PROGRAMMING_MODE] Chaos program does not contain valid 'experiments' key."
ngx.status = 400
ngx.say(error)
else
os.remove(file_name)
local response = json.encode(yaml_data)
ngx.log(ngx.INFO, response)
ngx.status = 200
ngx.say(response)
end
end
}
}
+48 -18
View File
@@ -4,14 +4,6 @@ local json = require 'lunajson'
local redis = require "resty.redis"
local red = redis:new()
local okredis, errredis = red:connect("unix:/tmp/redis.sock")
if okredis then
ngx.log(ngx.INFO, "Connection to Redis is ok")
else
ngx.log(ngx.INFO, "Connection to Redis is not ok")
ngx.log(ngx.INFO, errredis)
end
local k8s_url = ""
if os.getenv("KUBERNETES_SERVICE_HOST") then
@@ -20,17 +12,24 @@ else
k8s_url = os.getenv("ENDPOINT")
end
if okredis then
ngx.log(ngx.INFO, "Connection to Redis is ok")
else
ngx.log(ngx.INFO, errredis)
ngx.say("Connection to Redis is not ok")
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) -- 500 Internal Server Error
end
ngx.header['Access-Control-Allow-Origin'] = '*'
ngx.header['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
ngx.header['Access-Control-Allow-Headers'] = 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'
ngx.header['Access-Control-Expose-Headers'] = 'Content-Length,Content-Range';
ngx.req.read_body()
local token = os.getenv("TOKEN")
local arg = ngx.req.get_uri_args()
local body_data = ngx.req.get_body_data()
ngx.log(ngx.INFO, "[programming_mode]" .. body_data)
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Payload sent by client: " .. body_data)
math.randomseed(os.clock()*100000000000)
local rand = math.random(999, 9999)
@@ -40,18 +39,49 @@ io.output(file)
io.write(body_data)
io.close(file)
ngx.log(ngx.INFO, "[programming_mode] set programming_mode Redis key")
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Set programming_mode Redis key to 1")
red:set("programming_mode", "1")
--ngx.log(ngx.INFO, "[programming_mode] remove do_not_clean_log:" ..arg['id'] .. " Redis key")
--red:del("do_not_clean_log:" .. arg['id'])
ngx.log(ngx.INFO, "[programming_mode] set logs_enabled:" .. arg['id'] .. " Redis key")
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Set logs_enabled for " .. arg['id'] .. " as Redis key")
red:set("logs_enabled:" .. arg['id'], "1")
red:expire("logs_enabled:" .. arg['id'], "10")
local handle = io.popen("python3 /opt/programming_mode/start.py " .. file_name .. " " .. k8s_url)
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Checking if " .. file_name .. " is a valid YAML file")
local handle = io.popen("python3 -c 'import yaml, sys; print(yaml.safe_load(sys.stdin))' < " .. file_name .. " ; echo $? > " .. file_name .. ".check")
local result = handle:read("*a")
ngx.say(result)
handle = io.popen("cat " .. file_name .. ".check")
result = handle:read("*a")
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Exit code for checking YAML syntax of " .. file_name .. " is " .. result)
if result == "0\n" then
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] YAML Syntax is OK")
else
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] YAML Syntax is NOT OK")
handle = io.popen("rm -f " .. file_name .. ".check")
handle:read("*a")
handle = io.popen("rm -f " .. file_name)
handle:read("*a")
ngx.status = 400
ngx.say("Invalid YAML Chaos Program")
end
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Starting Chaos Program using /opt/programming_mode/start.py")
handle = io.popen("python3 /opt/programming_mode/start.py " .. file_name .. " " .. k8s_url .. "; echo $? > " .. file_name .. ".check")
result = handle:read("*a")
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Output for starting Chaos Program is " .. result)
handle = io.popen("cat " .. file_name .. ".check")
result = handle:read("*a")
if result == "0\n" then
ngx.log(ngx.INFO, "[PROGRAMMING_MODE] Chaos program successfully loaded")
ngx.say("[PROGRAMMING_MODE] Chaos program successfully loaded")
ngx.exit(ngx.HTTP_OK) -- 200 OK
else
handle = io.popen("rm -f " .. file_name .. ".check")
handle:read("*a")
ngx.status = 500
ngx.say("[PROGRAMMING_MODE] Error in loading Chaos Program. Please check the YAML syntax of kubeinvaders logs" .. result)
end
+29 -24
View File
@@ -22,45 +22,49 @@ def create_container(image, name, command, args):
)
logging.info(
f"Created container with name: {container.name}, "
f"image: {container.image} and args: {container.args}"
f"[PROGRAMMING_MODE] Created container with name: {container.name}, "
f"[PROGRAMMING_MODE] Image: {container.image} and Args: {container.args}"
)
return container
def create_pod_template(pod_name, additional_labels, container, exp_name):
pod_labels = {"chaos-controller": "kubeinvaders", "experiment-name": exp_name}
pod_labels = {"chaos-controller": "kubeinvaders", "experiment-name": exp_name, "chaos-codename": codename}
pod_labels.update(additional_labels)
pod_template = client.V1PodTemplateSpec(
spec=client.V1PodSpec(restart_policy="Never", containers=[container]),
metadata=client.V1ObjectMeta(name=pod_name, labels=pod_labels),
)
#logging.info(f"pod_template {pod_template}")
return pod_template
def create_job(job_name, pod_template):
metadata = client.V1ObjectMeta(name=job_name, labels={"chaos-controller": "kubeinvaders"})
metadata = client.V1ObjectMeta(name=job_name, labels={"chaos-controller": "kubeinvaders", "chaos-codename": codename})
job = client.V1Job(
api_version="batch/v1",
kind="Job",
metadata=metadata,
spec=client.V1JobSpec(backoff_limit=0, template=pod_template),
)
#logger.info(job)
return job
# create logger
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))
logging.info('Starting script for KubeInvaders programming mode')
logging.info('[PROGRAMMING_MODE] Starting script...')
if os.path.exists(sys.argv[1]) == False:
logging.info("[PROGRAMMING_MODE] Chaos program not found, please check the path...")
exit(0)
with open(sys.argv[1], 'r') as stream:
try:
logging.info('[PROGRAMMING_MODE] Trying to parse chaos program...')
parsed_yaml=yaml.safe_load(stream)
logging.info(f"Parsed yaml => {parsed_yaml}")
#logging.info(f"Parsed yaml => {parsed_yaml}")
except yaml.YAMLError as exc:
print(exc + " ")
ret = f"[PROGRAMMING_MODE] Invalid YAML syntax, please fix choas program code..."
logging.info(ret)
print(ret)
quit()
r = redis.Redis(unix_socket_path='/tmp/redis.sock')
@@ -79,11 +83,12 @@ batch_api = client.BatchV1Api()
namespace = "kubeinvaders"
k8s_regex = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"
prom_regex = "[a-zA-Z_:][a-zA-Z0-9_:]*"
codename = parsed_yaml["chaos-codename"]
for job in parsed_yaml["k8s_jobs"]:
logging.info(f"Found job {job}")
if not re.fullmatch(k8s_regex, job):
ret = f"Invalid name for k8s_jobs: {job}, please match Kubernetes name format '[a-z0-9]([-a-z0-9]*[a-z0-9])?'"
ret = f"[PROGRAMMING_MODE] Invalid name for k8s_jobs: {job}, please match Kubernetes name format '[a-z0-9]([-a-z0-9]*[a-z0-9])?'"
logging.info(ret)
print(ret)
quit()
@@ -91,19 +96,16 @@ for job in parsed_yaml["k8s_jobs"]:
for exp in parsed_yaml["experiments"]:
for _ in range(exp["loop"]):
logging.info(f"Processing the experiment {exp}")
logging.info(f"[PROGRAMMING_MODE] Processing the experiment {exp}")
job_attrs = parsed_yaml["k8s_jobs"][exp["k8s_job"]]
args = []
for arg in job_attrs['args']:
args.append(str(arg))
logging.info(f"args = {args}")
logging.info(f"command = {job_attrs['command']}")
logging.info(f"image = {job_attrs['image']}")
logging.info(f"k8s_job = {exp['k8s_job']}")
logging.info(f"[PROGRAMMING_MODE] args = {args}, command = {job_attrs['command']}, image = {job_attrs['image']}, k8s_job = {exp['k8s_job']}")
if not re.fullmatch(prom_regex, exp["name"]):
ret = f"Invalid name for experiment: {exp['name']}, please match Prometheus metric name format '[a-zA-Z_:][a-zA-Z0-9_:]*'"
ret = f"[PROGRAMMING_MODE] Invalid name for experiment: {exp['name']}, please match Prometheus metric name format '[a-zA-Z_:][a-zA-Z0-9_:]*'"
logging.info(ret)
print(ret)
quit()
@@ -130,14 +132,17 @@ for exp in parsed_yaml["experiments"]:
try:
batch_api.create_namespaced_job('kubeinvaders', job_def)
logging.info(f"[PROGRAMMING_MODE] Job {job_name} created successfully")
except ApiException as e:
logging.info(e)
logging.info(f"[PROGRAMMING_MODE] Error creating job: {e}")
quit()
if 'additional-labels' in job_attrs and 'chaos-codename' in job_attrs['additional-labels']:
codename = job_attrs['additional-labels']['chaos-codename']
metric_job_name = job_name.replace("-","_");
r.set(f"chaos_jobs_status:{codename}:{exp['name']}:{metric_job_name}", 0.0)
# if 'additional-labels' in job_attrs and 'chaos-codename' in job_attrs['additional-labels']:
# logging.info(f"[PROGRAMMING_MODE] Setting Redis keys for chaos-codename: {job_attrs['additional-labels']['chaos-codename']}")
# codename = job_attrs['additional-labels']['chaos-codename']
metric_job_name = job_name.replace("-","_");
r.set(f"chaos_jobs_status:{codename}:{exp['name']}:{metric_job_name}", 0.0)
if r.exists('chaos_node_jobs_total') == 1:
r.incr('chaos_node_jobs_total')