Merge pull request #53 from lucky-sideburn/feature/programmming_mode

Feature/programmming mode
This commit is contained in:
Eugenio Marzo
2022-10-21 08:34:36 +02:00
committed by GitHub
10 changed files with 361 additions and 29 deletions
+4 -1
View File
@@ -11,7 +11,7 @@ RUN apt-get -y install --no-install-recommends wget gnupg ca-certificates jq ope
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
RUN apt-get -y install openresty luarocks libssl-dev git vim lua-json lua-socket
RUN apt-get -y install openresty luarocks libssl-dev git vim lua-json lua-socket python3 python3-pip
RUN apt-get update --fix-missing
RUN chmod 777 /usr/local/openresty/nginx
RUN luarocks install luasec
@@ -48,7 +48,10 @@ 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/programming_mode /opt/programming_mode/
RUN pip3 install -r /opt/programming_mode/requirements.txt
COPY nginx/KubeInvaders.conf /etc/nginx/conf.d/KubeInvaders.conf
RUN chmod g+rwx /var/cache/nginx /var/run /var/log/nginx /var/www/html /etc/nginx/conf.d
Binary file not shown.
+137 -23
View File
@@ -115,26 +115,52 @@
<div class="starter-template">
<div class="container" style="margin-bottom: 2%;">
<div class="row" style="margin-top: 2%;">
<div class="row">
<div class="row" style="margin-bottom: 1%;">
<div class="col text-center">
<button type="button" id="controlAutoPilotButton" class="btn btn-light" onclick="controlAutoPilot()">Start</button>
<button type="button" id="gameModeButton" class="btn btn-light" onclick="startGameMode()">Game Mode</button>
</div>
<div class="col text-center">
<input type="range" id="randomFactorInput" name="randomFactorInput" min="0" max="100" value="50" onclick="changeRandomFactor()">
<div id="programming-mode-buttons" style="display: none;">
<button type="button" id="runProgrammingModeButton" class="btn btn-dark" onclick="runChaosProgram()">RUN</button>
</div>
</div>
<div class="col text-center">
<label for="randomFactorInput">Random Factor:&nbsp;<span id="currentRandomFactor">50</span></label>
<button type="button" id="programmingModeButton" class="btn btn-light" onclick="startProgrammingMode()">Programming Mode</button>
</div>
</div>
<div class="row" style="margin-top: 1%;">
<div class="col text-center">
<button type="button" id="buttonShuffle" class="btn btn-light btn-sm" onclick="buttonShuffleHelper()">Disable Shuffle</button>
<div id="programming-mode-buttons" style="display: none;">
<div class="row">
<div class="col text-center">
</div>
<div class="col text-center">
</div>
<div class="col text-center">
</div>
</div>
<div class="col text-center">
<button type="button" id="namespacesJumpButton" class="btn btn-light btn-sm" onclick="namespacesJumpControl()">Enable Auto NS Switch</button>
</div>
<div id="game-buttons" style="display: none;">
<div class="row">
<div class="col text-center">
<button type="button" id="controlAutoPilotButton" class="btn btn-light" onclick="controlAutoPilot()">Start</button>
</div>
<div class="col text-center">
<input type="range" id="randomFactorInput" name="randomFactorInput" min="0" max="100" value="50" onclick="changeRandomFactor()">
</div>
<div class="col text-center">
<label for="randomFactorInput">Random Factor:&nbsp;<span id="currentRandomFactor">50</span></label>
</div>
</div>
<div class="col text-center">
<button type="button" id="buttonOnlyPodName" class="btn btn-light btn-sm" onclick="showPodNameControl()">Hide Pods Name</button>
<div class="row" style="margin-top: 1%;">
<div class="col text-center">
<button type="button" id="buttonShuffle" class="btn btn-light btn-sm" onclick="buttonShuffleHelper()">Disable Shuffle</button>
</div>
<div class="col text-center">
<button type="button" id="namespacesJumpButton" class="btn btn-light btn-sm" onclick="namespacesJumpControl()">Enable Auto NS Switch</button>
</div>
<div class="col text-center">
<button type="button" id="buttonOnlyPodName" class="btn btn-light btn-sm" onclick="showPodNameControl()">Hide Pods Name</button>
</div>
</div>
</div>
</div>
@@ -148,23 +174,67 @@
<span style="color: #000000">Latest Replicas State Delay:&nbsp;&nbsp;<span id="latest_fewer_replicas_seconds" style="color: #8f00bb">0</span><font color="#4f4f4f">&nbsp;sec</font>&nbsp;</span>
</div>
</div>
<div class="row">
<canvas id="myCanvas" width="720" height="480"></canvas>
</div>
<div class="row">
<div class="col text-center">
</div>
<div class="col text-center">
<input type="button" style="margin-top: 2%" class="btn btn-light" id="zoomInGameScreenInput" name="zoomInGameScreenInput" value="+" onclick="zoomIn()">
<input type="button" style="margin-top: 2%" class="btn btn-light" id="zoomOutGameScreenInput" name="zoomOutGameScreenInput" value="-" onclick="zoomOut()">
</div>
<div class="col text-center">
<div id="chaos-program-screen" style="display: none;">
<div class="row" style="margin-top: 1%;">
<form>
<div id="alert_placeholder" style="margin-top: 3%;"></div>
<div class="form-group">
<label for="chaosProgramTextArea"></label>
<textarea class="form-control" id="chaosProgramTextArea" rows="20" style="font-family: Courier, monospace;">
jobs:
cpu-attack:
image: docker.io/luckysideburn/kubeinvaders-stress-ng:latest
command: "stress-ng"
args:
- --help
mem-attack:
image: docker.io/luckysideburn/kubeinvaders-stress-ng:latest
command: "stress-ng"
args:
- --help
experiments:
- name: cpu-attack-exp
job: cpu-attack
loop: 5
after:
check_url: https://google.it
check_payload: ''
check_tls_ignore: true
- name: mem-attack-exp
job: mem-attack
loop: 5
after:
check_url: https://google.it
check_payload: ''
check_tls_ignore: true
</textarea>
</div>
</form>
</div>
</div>
<div id="game-screen" style="display: none;">
<div class="row">
<canvas id="myCanvas" width="720" height="480"></canvas>
</div>
<div class="row">
<div class="col text-center">
</div>
<div class="col text-center">
<input type="button" style="margin-top: 2%" class="btn btn-light" id="zoomInGameScreenInput" name="zoomInGameScreenInput" value="+" onclick="zoomIn()">
<input type="button" style="margin-top: 2%" class="btn btn-light" id="zoomOutGameScreenInput" name="zoomOutGameScreenInput" value="-" onclick="zoomOut()">
</div>
<div class="col text-center">
</div>
</div>
</div>
<div id="alert_placeholder" style="margin-top: 3%;"></div>
</div>
<div id="alert_placeholder" style="margin-top: 3%;"></div>
</div>
<div id="footer" style="margin-top: 5%;">
<div class="container text-center">
@@ -211,6 +281,50 @@
}
}
function startGameMode() {
if (game_mode_switch) {
game_mode_switch = false;
} else {
game_mode_switch = true;
}
if (game_buttons.style.display === "none") {
game_buttons.style.display = "block";
} else {
game_buttons.style.display = "none";
}
if (game_screen.style.display === "none") {
game_screen.style.display = "block";
} else {
game_screen.style.display = "none";
}
chaos_program_screen.style.display = "none";
programming_mode_buttons.style.display = "none";
}
function startProgrammingMode() {
if (chaos_program_screen.style.display === "none") {
chaos_program_screen.style.display = "block";
} else {
chaos_program_screen.style.display = "none";
}
if (programming_mode_buttons.style.display === "none") {
programming_mode_buttons.style.display = "block";
} else {
programming_mode_buttons.style.display = "none";
}
game_buttons.style.display = "none";
game_screen.style.display = "none";
}
function showSpecialKeys() {
$('#showSpecialKeysModal').modal('show');
modal_opened = true;
+28 -5
View File
@@ -21,6 +21,12 @@ var spaceshipxOld = 0;
var randomFactor = 10;
// pods list from kubernetes
var pods = [];
var game_mode_switch = false;
var game_buttons = document.getElementById("game-buttons");
var game_screen = document.getElementById("game-screen");
var chaos_program_screen = document.getElementById("chaos-program-screen");
var programming_mode_buttons = document.getElementById("programming-mode-buttons");
// nodes list from kubernetes
var nodes = [];
@@ -194,6 +200,19 @@ function setChaosContainer() {
}
}
function runChaosProgram() {
var oReq = new XMLHttpRequest();
oReq.open("POST", "https://" + clu_endpoint + "/kube/chaos/programming_mode", true);
oReq.onreadystatechange = function () {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
//console.log(this.responseText);
$('#alert_placeholder2').text('New Chaos Program has been started.');
}
};;
oReq.setRequestHeader("Content-Type", "application/json");
oReq.send($('#chaosProgramTextArea').val());
}
function startChaosNode(node_name) {
var oReq = new XMLHttpRequest();
oReq.onload = function () {
@@ -252,13 +271,15 @@ function getNodes() {
}
}
window.setInterval(function getKubeItems() {
getNodes();
getPods();
window.setInterval(function getKubeItems() {
if (game_mode_switch) {
getNodes();
getPods();
}
}, 1000)
function keyDownHandler(e) {
if (!modal_opened) {
if (!modal_opened && game_mode_switch) {
e.preventDefault();
if(e.key == "Right" || e.key == "ArrowRight") {
rightPressed = true;
@@ -682,7 +703,9 @@ window.setInterval(function setAliens() {
}, 1000)
window.setInterval(function metrics() {
getMetrics()
if (game_mode_switch) {
getMetrics()
}
}, 2000)
getEndpoint();
BIN
View File
Binary file not shown.
+4
View File
@@ -20,6 +20,10 @@ server {
sub_filter endpoint_placeholder $endpoint;
}
location /kube/chaos/programming_mode {
access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/programming_mode.lua";
}
location /kube/pods {
access_by_lua_file "/usr/local/openresty/nginx/conf/kubeinvaders/pod.lua";
}
+32
View File
@@ -0,0 +1,32 @@
local https = require "ssl.https"
local ltn12 = require "ltn12"
local json = require 'lunajson'
local redis = require "resty.redis"
if os.getenv("KUBERNETES_SERVICE_HOST") then
k8s_url = "https://" .. os.getenv("KUBERNETES_SERVICE_HOST") .. ":" .. os.getenv("KUBERNETES_SERVICE_PORT_HTTPS")
else
k8s_url = os.getenv("ENDPOINT")
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.ERR, "[programming_mode]" .. body_data)
file = io.open("/tmp/experiments.yaml", "w")
io.output(file)
io.write(body_data)
io.close(file)
local handle = io.popen("python3 /opt/programming_mode/start.py")
local result = handle:read("*a")
ngx.say("Chaos program has been started...")
+53
View File
@@ -0,0 +1,53 @@
jobs:
# cpu-attack:
# image: docker.io/luckysideburn/kubeinvaders-stress-ng:latest
# command: "stress-ng"
# args:
# - --cpu
# - 4
# - --io
# - 2
# - --vm
# - 1
# - --vm-bytes
# - 1G
# - --timeout
# - 10s
# - --metrics-brief
# mem-attack:
# image: docker.io/luckysideburn/kubeinvaders-stress-ng:latest
# command: "stress-ng"
# args:
# - --vm
# - 2
# - --vm-bytes
# - 1G
cpu-attack:
image: docker.io/luckysideburn/kubeinvaders-stress-ng:latest
command: "stress-ng"
args:
- --help
mem-attack:
image: docker.io/luckysideburn/kubeinvaders-stress-ng:latest
command: "stress-ng"
args:
- --help
experiments:
- name: cpu-attack-exp
job: cpu-attack
loop: 5
after:
check_url: https://google.it
check_payload: ''
check_tls_ignore: true
- name: mem-attack-exp
job: mem-attack
loop: 5
after:
check_url: https://google.it
check_payload: ''
check_tls_ignore: true
@@ -0,0 +1,3 @@
yaml
requests
kubernetes
+100
View File
@@ -0,0 +1,100 @@
from asyncio.log import logger
import yaml
import logging
import os
from kubernetes import client, config
from kubernetes.client.rest import ApiException
import requests
from string import Template
import string
import random
def create_container(image, name, command, args):
container = client.V1Container(
image=image,
name=name,
image_pull_policy='IfNotPresent',
args=args,
command=command,
)
logging.info(
f"Created container with name: {container.name}, "
f"image: {container.image} and args: {container.args}"
)
return container
def create_pod_template(pod_name, container):
pod_template = client.V1PodTemplateSpec(
spec=client.V1PodSpec(restart_policy="Never", containers=[container]),
metadata=client.V1ObjectMeta(name=pod_name, labels={"pod_name": pod_name, "approle": "chaosnode"}),
)
return pod_template
def create_job(job_name, pod_template):
metadata = client.V1ObjectMeta(name=job_name, labels={"job_name": job_name, "approle": "chaosnode"})
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')
with open("./experiments.yaml", 'r') as stream:
try:
parsed_yaml=yaml.safe_load(stream)
logging.info(f"Parsed yaml => {parsed_yaml}")
except yaml.YAMLError as exc:
print(exc)
configuration = client.Configuration()
token = os.environ["TOKEN"]
configuration.api_key = {"authorization": f"Bearer {token}"}
configuration.host = os.environ["ENDPOINT"]
configuration.insecure_skip_tls_verify = True
configuration.verify_ssl = False
client.Configuration.set_default(configuration)
client.Configuration.set_default(configuration)
api_instance = client.CoreV1Api()
batch_api = client.BatchV1Api()
namespace = "kubeinvaders"
for job in parsed_yaml["jobs"]:
logging.info(f"Found job {job}")
for exp in parsed_yaml["experiments"]:
logging.info(f"Processing the experiment {exp}")
job_attrs = parsed_yaml["jobs"][exp["job"]]
args = []
for arg in job_attrs['args']:
args.append(str(arg))
logging.info(f"args = {args}")
logging.info(f"command = {job_attrs['command']}")
container = create_container(
image = job_attrs['image'],
name = exp['name'],
command = [job_attrs['command']],
args = args
)
letters = string.ascii_lowercase
rand_suffix = ''.join(random.choice(letters) for i in range(5))
job_name = f"{exp['name']}-{rand_suffix}"
pod_template = create_pod_template(exp["name"], container)
logging.info(f"Creating job {job_name}")
job_def = create_job(job_name, pod_template)
batch_api.create_namespaced_job('kubeinvaders', job_def)