mirror of
https://github.com/lucky-sideburn/kubeinvaders.git
synced 2026-05-06 08:46:56 +00:00
404 lines
23 KiB
HTML
404 lines
23 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<title>KubeInvaders</title>
|
|
<link rel="icon" type="image/x-icon" href="./images/favicon.ico">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link rel="stylesheet" href="./bootstrap-5.0.0-dist/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="./style.css">
|
|
</head>
|
|
<body id="kinvBody">
|
|
<nav class="navbar navbar-expand-lg navbar-li bg-dark navbar-collapse">
|
|
<div class="container-fluid">
|
|
<button style="color: #ffffff; border-color: #ffffff; border-width: 3px;" class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDarkDropdown" aria-controls="navbarNavDarkDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
<div class="collapse navbar-collapse" id="navbarNavDarkDropdown">
|
|
<ul class="navbar-nav mr-auto">
|
|
|
|
<li class="nav-item" style="margin-top: 0.2%;">
|
|
<a class="nav-link" href="#" id="navbarDarkDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
<font style="color: #ffffff;">Menu</font>
|
|
</a>
|
|
<ul class="dropdown-menu dropdown-menu-light" aria-labelledby="navbarDarkDropdownMenuLink">
|
|
<!-- <li><a class="dropdown-item" href="#" onclick="runKubeLinter()">Run KubeLinter On Current Namespace</a></li> -->
|
|
<li><a class="dropdown-item" href="#" onclick="showSpecialKeys()">Show Special Keys</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="showCurrentChaosContainer()">Show Current Chaos Container for nodes</a></li>
|
|
<li><a class="dropdown-item" href="#" onclick="showSetCurrentChaosContainer()">Set Custom Chaos Container for nodes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="#" onclick="switchColorMode()" id="switchColorModeLink">
|
|
<svg xmlns="http://www.w3.org/2000/svg" style="color: #ffffff;" width="16" height="16" fill="currentColor" class="bi bi-moon-fill" viewBox="0 0 16 16">
|
|
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/>
|
|
</svg>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<!-- Modal -->
|
|
<div class="modal fade" id="currentChaosContainerModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-body">
|
|
<pre id="currentChaosContainerYaml"></pre>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" id="closeButton1" class="btn btn-light" data-dismiss="modal" onclick="closeCurrentChaosJobModal()">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal -->
|
|
<div class="modal" id="kubeLinterModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
|
<div class="modal-dialog modal-xl modal-dialog-scrollable" role="document">
|
|
<div class="modal-body">
|
|
<p id="currentKubeLinterResult"></hp>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" id="closeButton2" class="btn btn-light" data-dismiss="modal" onclick="closeKubeLinterModal()">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal -->
|
|
<div class="modal fade" id="setChaosContainerModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-body">
|
|
<form>
|
|
<div class="form-group">
|
|
<label for="exampleFormControlTextarea1" style="margin-bottom: 3%;">Chaos Container Definition</label>
|
|
<textarea class="form-control" id="currentChaosContainerJsonTextArea" rows="20"></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<p id="alert_placeholder2" style="color: #161616; font-family: 'Courier New', Courier, monospace; margin-top: 3%;"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" id="saveButton" class="btn btn-light" onclick="setChaosContainer()">Save</button>
|
|
<button type="button" id="closeButton3" class="btn btn-dark" data-dismiss="modal" onclick="closeSetChaosContainerModal()">Close</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal -->
|
|
<div class="modal fade" id="setLoadTestModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
|
<div class="modal-dialog modal-xl" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-body">
|
|
<form>
|
|
<div class="form-group">
|
|
|
|
<label for="exampleFormControlTextarea1" style="margin-bottom: 1%;">Load Test Code</label><br>
|
|
|
|
<label for="presetName">Name</label>
|
|
<input type="text" id="presetName" value="foobar" readonly="true" style="margin-bottom: 1%;"><br>
|
|
|
|
<label for="presetLangText">Programming Language</label>
|
|
<input type="text" id="presetLang" value="Python3" readonly="true" style="margin-bottom: 1%;">
|
|
|
|
<textarea class="form-control" id="currentLoadTest" rows="20" style="color: #161616; font-family: 'Courier New', Courier, monospace;"></textarea>
|
|
|
|
</div>
|
|
<div class="form-group">
|
|
<p id="alert_placeholder2" style="color: #161616; font-family: 'Courier New', Courier, monospace; margin-top: 3%;"></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" id="saveAndApplyButton" class="btn btn-light" onclick="savePreset('apply')">Save and apply</button>
|
|
<button type="button" id="savePresetButton" class="btn btn-light" onclick="savePreset('save')">Save</button>
|
|
<button type="button" id="resetToDefaultButton" class="btn btn-light-saved" onclick="resetPreset('preset')">Reset to default</button>
|
|
<button type="button" id="deleteChaosProgramButton" class="btn btn-dark" onclick="resetPreset('k-inv')">Delete</button>
|
|
<button type="button" id="closeButton4" class="btn btn-dark" data-dismiss="modal" onclick="closeSetLoadTestModal()">Close</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal -->
|
|
<div class="modal fade" id="showSpecialKeysModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-body">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
Special Keys
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="card-text">
|
|
h => Activate or deactivate help<br>
|
|
s => Activate or deactivate shuffle for aliens<br>
|
|
n => Change namespace<br>
|
|
p => Activate or deactivate chaos engineering against pods<br>
|
|
c => Activate or deactivate chaos engineering against nodes
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" id="closeButton5" class="btn btn-secondary" data-dismiss="modal" onclick="closeSpecialKeysModal()">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="container" id="gameContainer" style="width: 50%; height: 50%;">
|
|
<!-- START FIRST ROW -->
|
|
<div class="row" style="margin-top: 2%;">
|
|
<!-- START SWITCH BUTTONS FOR MODE (GAME, PROGRAMMING)-->
|
|
<div class="row" style="margin-bottom: 2%;">
|
|
<div class="col text-center" style="margin-bottom: 2%;">
|
|
<button type="button" id="gameModeButton" class="btn btn-light btn-green" onclick="startGameMode()">Game Mode</button>
|
|
</div>
|
|
<div class="col text-center" style="margin-bottom: 2%;">
|
|
<button type="button" id="programmingModeButton" class="btn btn-light btn-green" onclick="startProgrammingMode()">Programming Mode</button>
|
|
</div>
|
|
</div>
|
|
<!-- END SWITCH BUTTONS FOR MODE (GAME, PROGRAMMING)-->
|
|
|
|
<!-- START CHAOS PROGRAM BUTTONS -->
|
|
<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>
|
|
<!-- END CHAOS PROGRAMM BUTTONS -->
|
|
</div>
|
|
<!-- END FIRST ROW -->
|
|
|
|
<!-- START GAME MODE BUTTONS -->
|
|
<div id="game-buttons" style="display: none;">
|
|
<div class="row container">
|
|
<div class="col text-center">
|
|
<button type="button" id="controlAutoPilotButton" class="btn btn-light" onclick="controlAutoPilot()">Start</button>
|
|
</div>
|
|
<div class="col">
|
|
<input type="range" id="randomFactorInput" name="randomFactorInput" min="0" max="100" value="50" onclick="changeRandomFactor()">
|
|
</div>
|
|
<div class="col text-center">
|
|
<label for="randomFactorInput" class="text-kinv" id="randomFactorText">Random Factor: <span id="currentRandomFactor">50</span></label>
|
|
</div>
|
|
</div>
|
|
<div class="row container" style="margin-top: 1%;">
|
|
<div class="col text-center">
|
|
<button style="margin-bottom: 2%" type="button" id="buttonShuffle" class="btn btn-light btn-sm" onclick="buttonShuffleHelper()">Disable Shuffle</button>
|
|
</div>
|
|
<div class="col text-center">
|
|
<button style="margin-bottom: 2%" type="button" id="namespacesJumpButton" class="btn btn-light btn-sm" onclick="namespacesJumpControl()">Enable Auto NS Switch</button>
|
|
</div>
|
|
<div class="col text-center">
|
|
<button style="margin-bottom: 2%" type="button" id="buttonOnlyPodName" class="btn btn-light btn-sm" onclick="showPodNameControl()">Hide Pods Name</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END GAME MODE BUTTONS -->
|
|
|
|
<!-- START METRICS ROW -->
|
|
<div class="row text-justify" align="center" id="metricsPresetsRow">
|
|
<div style="margin-top: 1%;" class="custom-btn-group text-justify" id="metricsGroup">
|
|
|
|
<span style="color: #000000;" class="text-kinv text-wrap" id="currentGameNamespaceLabel">Selected Namespace: <span id="currentGameNamespace" style="color: #3ac961;" class="text-break">NULL</span></span><br>
|
|
<span style="color: #000000;" class="text-kinv" id="deletedPodsTotalText">Deleted Pods Total: <span id="deleted_pods_total" style="color: #3ac961">0</span></span><br>
|
|
<span style="color: #000000" class="text-kinv" id="chaosJobTotalText">Chaos Jobs Total: <span id="chaos_jobs_total" style="color: #3ac961">0</span></span><br>
|
|
|
|
<span style="color: #000000" class="text-kinv" id="currentChaosPodsText">Current Chaos Pods: <span id="current_chaos_job_pod" style="color: #3ac961">0</span></span><br>
|
|
<span style="color: #000000" class="text-kinv" id="podNotRunningText">Not Running Pods: <span id="pods_not_running_on" style="color: #3ac961">0</span></span><br>
|
|
|
|
<span style="color: #000000" class="text-kinv" id="currentReplicasStateDelayText">Current Replicas State Delay: </span><span id="fewer_replicas_seconds" style="color: #3ac961">0</span><font color="#4f4f4f"> sec</font></span><br>
|
|
<span style="color: #000000" class="text-kinv" id="latestReplicasStateDelayText">Latest Replicas State Delay: <span id="latest_fewer_replicas_seconds" style="color: #3ac961">0</span><font color="#4f4f4f"> sec</font> </span><br>
|
|
<!-- <span style="color: #000000" class="text-kinv" id="podsMatchRegexText">PODs match regex: </span><span id="pods_match_regex" style="color: #3ac961">0</span><font color="#4f4f4f"> </font></span> -->
|
|
</div>
|
|
</div>
|
|
<!-- END METRICS ROW -->
|
|
|
|
<!-- START CHAOS PROGRAMMING MODE SCREEN -->
|
|
<div id="chaos-program-screen" style="display: none;">
|
|
<div class="">
|
|
<div class="row" style="margin-top: 2%;">
|
|
<font size="2" class="text-kinv" id="loadTestingPresetsText">Load Testing Presets & Chaos Programs</font>
|
|
</div>
|
|
<div class="row">
|
|
<div class="btn-group" id="loadButtonGroup" role="group" aria-label="Basic example" style="overflow-x: scroll; width: 100%; padding-bottom: 2%; padding-top: 2%; scrollbar-color: dark;">
|
|
<button type="button" id="loadDefault" class="btn btn-light btn-md" onclick="loadPreset('default', 'k-inv')">Default</button>
|
|
<button type="button" id="loadCassandra" class="btn btn-light btn-md" onclick="loadPreset('cassandra', 'python')">Cassandra</button>
|
|
<button type="button" id="loadConsul" class="btn btn-light btn-md" onclick="loadPreset('consul', 'python')">Consul</button>
|
|
<button type="button" id="loadElasticsearch" class="btn btn-light btn-md" onclick="loadPreset('elasticsearch', 'python')">Elasticsearch</button>
|
|
<button type="button" id="loadEtcd3" class="btn btn-light btn-md" onclick="loadPreset('etcd3', 'python')">Etcd3</button>
|
|
<button type="button" id="loadGitlab" class="btn btn-light btn-md" onclick="loadPreset('gitlab', 'python')">Gitlab</button>
|
|
<button type="button" id="loadHttp" class="btn btn-light btn-md" onclick="loadPreset('http', 'python')">Http</button>
|
|
<button type="button" id="loadJira" class="btn btn-light btn-md" onclick="loadPreset('jira', 'python')">Jira</button>
|
|
<button type="button" id="loadKafka" class="btn btn-light btn-md" onclick="loadPreset('kafka', 'python')">Kafka</button>
|
|
<button type="button" id="loadKubernetes" class="btn btn-light btn-md" onclick="loadPreset('kubernetes', 'python')">Kubernetes</button>
|
|
<button type="button" id="loadMongodb" class="btn btn-light btn-md" onclick="loadPreset('mongodb', 'python')">Mongodb</button>
|
|
<button type="button" id="loadMysql" class="btn btn-light btn-md" onclick="loadPreset('mysql', 'python')">Mysql</button>
|
|
<button type="button" id="loadNomad" class="btn btn-light btn-md" onclick="loadPreset('nomad', 'python')">Nomad</button>
|
|
<button type="button" id="loadPostgresql" class="btn btn-light btn-md" onclick="loadPreset('postgresql', 'python')">Postgresql</button>
|
|
<button type="button" id="loadPrometheus" class="btn btn-light btn-md" onclick="loadPreset('prometheus', 'python')">Prometheus</button>
|
|
<button type="button" id="loadRabbit" class="btn btn-light btn-md" onclick="loadPreset('rabbit', 'python')">Rabbit</button>
|
|
<button type="button" id="loadSSH" class="btn btn-light btn-md" onclick="loadPreset('SSH', 'python')">SSH</button>
|
|
<button type="button" id="loadVault" class="btn btn-light btn-md" onclick="loadPreset('vault', 'python')">Vault</button>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="btn-group" id="loadChaosProgramButtonGroup" role="group" aria-label="Basic example" style="overflow-x: scroll; width: 100%; padding-bottom: 2.0%; padding-top: 0.5%; scrollbar-color: dark;">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row" style="margin-top: 1%;">
|
|
<div id="alert_placeholder_programming_mode" style="margin-top: 1%; margin-bottom: 1%;"></div>
|
|
<div class="col">
|
|
<div class="row" width="10px">
|
|
<div class="col text-center">
|
|
<button type="button" id="saveChaosProgramButton" class="btn btn-light" onclick="savePreset('save-chaos-program')">SAVE</button>
|
|
</div>
|
|
<div class="col text-center">
|
|
<button type="button" id="runChaosProgramButton" class="btn btn-dark" onclick="runChaosProgram()">RUN</button>
|
|
</div>
|
|
</div>
|
|
<form>
|
|
<div class="form-group">
|
|
<label for="chaosProgramTextArea"></label>
|
|
<textarea class="form-control chaos-prog-area" id="chaosProgramTextArea" rows="50" style="min-width: 100%; font-family: Courier, monospace;">
|
|
chaos-codename: CODENAME_PLACEHOLDER
|
|
jobs:
|
|
cpu-attack-job:
|
|
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:
|
|
- --version
|
|
|
|
mem-attack-job:
|
|
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:
|
|
- --version
|
|
|
|
experiments:
|
|
- name: cpu-attack-exp
|
|
job: cpu-attack-job
|
|
loop: 5
|
|
|
|
- name: mem-attack-exp
|
|
job: mem-attack-job
|
|
loop: 5
|
|
</textarea>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="col" style="margin-top: 4%; overflow-y: scroll; height:900px;">
|
|
<div id="chaosProgramFlow">
|
|
<div class="row"><div class="alert alert-light alert-kinv" id="exampleAlert1" role="alert" style="border-color: #000000; border-width: 1.5px;">test attack 1</div></div>
|
|
<img src="images/down-arrow.png" width="30" height="30" style="margin-bottom: 2%;">
|
|
<div class="row"><div class="alert alert-light alert-kinv" id="exampleAlert2" role="alert" style="border-color: #000000; border-width: 1.5px;">test attack 2</div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END CHAOS PROGRAMMING MODE SCREEN -->
|
|
|
|
<!-- START GAME MODE SCREEN -->
|
|
<div id="game-screen" style="display: none;">
|
|
<div class="row" style="margin-top: 2%;">
|
|
<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" id="zoomInButton" style="margin-top: 2%" class="btn btn-light" id="zoomInGameScreenInput" name="zoomInGameScreenInput" value="+" onclick="zoomIn()">
|
|
<input type="button" id="zoomOutButton" style="margin-top: 2%" class="btn btn-light" id="zoomOutGameScreenInput" name="zoomOutGameScreenInput" value="-" onclick="zoomOut()">
|
|
</div>
|
|
<div class="col text-center">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END GAME MODE SCREEN -->
|
|
|
|
<!-- HELPER ALERT -->
|
|
<div class="row">
|
|
<div id="alert_placeholder" style="margin-top: 3%;"></div>
|
|
<div id="alert_placeholder3" style="margin-top: 3%;"></div>
|
|
</div>
|
|
|
|
<!-- LOG TAIL ROW -->
|
|
<!-- <div class="logtail-group">
|
|
<div class="row" style="margin-top: 1%;">
|
|
<div class="col text-center">
|
|
<button type="button" id="logConsoleButton" class="btn btn-light" onclick="setLogConsole()">Start Logs Tail</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col text-center">
|
|
</div>
|
|
<div class="col text-center">
|
|
<input type="button" id="zoomInButton2" style="margin-top: 2%" class="btn btn-light" id="zoomInGameScreenInput2" name="zoomInGameScreenInput2" value="+" onclick="zoomIn()">
|
|
<input type="button" id="zoomOutButton2" style="margin-top: 2%" class="btn btn-light" id="zoomOutGameScreenInput2" name="zoomOutGameScreenInput2" value="-" onclick="zoomOut()">
|
|
</div>
|
|
<div class="col text-center">
|
|
</div>
|
|
</div>
|
|
|
|
<div id="logTailRegexInput" style="display: block;">
|
|
<div class="row" style="margin-top: 2%; padding-left: 2%; padding-right: 2%;">
|
|
<input type="text" style="font-family: Courier New, Courier, monospace;" id="logTailRegex" value='{"pod_logs_sec": "60", "pod_start_time_sec": "60", "pod":".*", "namespace":"kube-system", "labels":".*", "annotations":".*", "containers":".*"}'/>
|
|
</div>
|
|
<div class="row" style="margin-top: 1%;">
|
|
<div class="col text-center">
|
|
<button type="button" style="width: 10em;" id="scroll_backwards" class="btn btn-sm btn-dark ext-center" onclick="scroll_backwards()"><<<</button>
|
|
<button type="button" style="width: 10em;" id="logConsoleRegex" class="btn btn-sm btn-dark ext-center" onclick="setLogRegex()">Set Regex</button>
|
|
<button type="button" style="width: 10em;" id="scroll_forward" class="btn btn-sm btn-dark ext-center" onclick="scroll_forward()">>>></button>
|
|
</div>
|
|
<div class="row" style="margin-top: 1%;">
|
|
<span style="color: #000000" class="text-kinv" id="chaosLogsTotalPos">Total Logs Position: <span id="total_logs_pos" style="color: #3ac961">0</span><font color="#4f4f4f"> </font> </span>
|
|
<span style="color: #000000" class="text-kinv" id="chaosLogsCurrentPos">Current Logs Position: <span id="current_log_pos" style="color: #3ac961">0</span><font color="#4f4f4f"> </font> </span>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="logTailScreen" style="display: none;">
|
|
<div class="row">
|
|
<div id="logTailDiv" style="margin-top: 2%; overflow-y: scroll; height:700px; display: none; padding-left: 3%; padding-right: 3%;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> -->
|
|
</div>
|
|
|
|
<div id="footer" style="margin-top: 5%;">
|
|
<div class="container text-center">
|
|
<div class="container text-center" style="margin-top: 20%;">
|
|
<div>
|
|
<img style="scale: 60%" src="images/kubeinvaders_spaceship2.png" id="spaceShip">
|
|
<p class="text-muted credit" style="color:#fff;">version: v1.9.6</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="./utils.js"></script>
|
|
<script src="./kubeinvaders.js"></script>
|
|
<script src="./bootstrap-5.0.0-dist/js/bootstrap.min.js"></script>
|
|
<script src="./js/jquery-3.6.0.min.js"></script>
|
|
<script src="./js/popper.min.js"></script>
|
|
</body>
|
|
</html>
|