Initial implementation

This commit is contained in:
Timothée Floure 2021-04-07 09:49:38 +02:00
commit fa4d417bf7
Signed by: tfloure
GPG Key ID: 4502C902C00A1E12
7 changed files with 190 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.html

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Recycled Cloud Status Page
Simple status page for the Recycled Cloud Infrastructure.

7
assets/bootstrap-grid.min.css vendored Normal file

File diff suppressed because one or more lines are too long

8
assets/bootstrap-reboot.min.css vendored Normal file
View File

@ -0,0 +1,8 @@
/*!
* Bootstrap Reboot v4.5.3 (https://getbootstrap.com/)
* Copyright 2011-2020 The Bootstrap Authors
* Copyright 2011-2020 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

1
assets/cloud.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 274.75 150.78"><defs><style>.cls-1{fill:#1e3c6c;}.cls-2{fill:#fff;stroke:#1e3c6c;stroke-miterlimit:10;}.cls-2,.cls-3{stroke-width:2px;}.cls-3{fill:#aecf70;stroke:#1a408c;stroke-miterlimit:6.4;}</style></defs><g id="logo_final_vectorisé_rvb" data-name="logo final vectorisé rvb"><path class="cls-1" d="M277.56,46.18a38.32,38.32,0,0,0-5.87-18.81c-4.49-6.83-11.08-10.75-18.09-10.78h0A19.6,19.6,0,0,0,243,19.71C229.31,11.29,211.1,6.52,191.93,6.45h-.35c-17.89,0-35.15,4.13-48.64,11.63-10.85,6-18.73,14-23,22.86a22.47,22.47,0,0,0-3.84-.34h0c-7.07,0-23.49,3.64-29.34,14.92l-.41.85a56.35,56.35,0,0,0-16.92-2.6h-.19c-25,0-44.69,15.27-44.76,34.82,0,9.7,5.08,19,14,25.6,8,5.86,18.35,9.2,29.38,9.48,12.81,20.14,45.36,33.42,83.62,33.56h.37c27.21,0,52.12-6.76,68.78-18.4a25.1,25.1,0,0,0,17.45,7.56h0c11.92,0,17.47-9.93,20.52-19.16a21.33,21.33,0,0,0,6.59,1.38h.09c18.62,0,33.82-19.05,33.9-42.52C299.3,67.93,290.51,52.31,277.56,46.18ZM265.64,112c-.93-.19-3.18-.95-8.58-3.33l-9.74-4.26-2.3,9.69c-3.25,13.65-5.7,15.69-6.84,15.69h0c-3.18,0-6.46-2.54-8.77-6.75l-5.32-9.26h0l-8.83-15.87-13.9,7.73,10.59,19c-13.68,9.95-36,16-60,16h-.32c-33.83-.12-63.77-12.21-71.21-28.75L78,106.53l-5.79.41c-1,.07-1.94.1-2.9.1h0c-7.88,0-15.49-2.31-20.88-6.26-2.71-2-7.25-6.22-7.23-12.13,0-9.9,12.9-18.23,28.12-18.23h.13c8.11,0,16.61,1.71,22,5.87l11.12-10.71c-.21-.3-1.27-1.84-1-2.4,1.38-2.67,9.4-5.94,14.5-5.94h0a7.69,7.69,0,0,1,4.33,1.52l10.77,7.48,2.18-12.94c2.86-17,28.4-30.21,58.22-30.21h.29c14.9.05,29.35,3.54,40.22,9.52l-11,14.93,13.35,9.82,12.39-18,3.22-3.9c1.18-1.43,2.46-2.25,3.49-2.25h0c1.3,0,2.88,1.23,4.22,3.27A22.82,22.82,0,0,1,261,48.75c0,.84-.06,1.68-.14,2.51l-.76,7.55,7.45,1.45c8.49,1.65,15.1,13,15.07,25.78C282.57,100,274.81,111.74,265.64,112Z" transform="translate(-24.5 -6.45)"/><path class="cls-2" d="M272,48.8a36.86,36.86,0,0,0-5.65-17.88c-4.34-6.61-10.74-10.41-17.55-10.44h0a19.11,19.11,0,0,0-10,2.9c-13.1-8-30.44-12.49-48.67-12.56h-.33c-17.1,0-33.61,3.95-46.52,11.13-10.29,5.73-17.8,13.23-21.89,21.68a23.23,23.23,0,0,0-3.43-.29h0C108.05,43.34,99.26,49.73,94,60a53.29,53.29,0,0,0-20.63-4.12h-.17c-24.08,0-43,14.71-43,33.55,0,9.37,4.9,18.38,13.52,24.71,7.6,5.58,17.49,8.79,28,9.09,12.36,19.2,43.41,31.84,79.86,32h.35c25.86,0,49.54-6.39,65.47-17.4A24.21,24.21,0,0,0,234,144.89h0c10,0,18.88-6.58,23.78-17q1,.07,2,.09H260c17.95,0,32.61-18.32,32.68-40.89C292.7,69.71,284.33,54.78,272,48.8Zm-12,62.51h0a10.53,10.53,0,0,1-4.13-.9l-9.13-4-2.3,9.69c-1.68,7-6,12.15-10.31,12.15h0c-2.89,0-5.88-2.34-8-6.22l-5.33-9.27-6.7-12L226,94.08a3,3,0,0,0-.8-5.49l-27.83-6.16a3,3,0,0,0-3.42,1.84l-10.44,27.44a3,3,0,0,0,4.22,3.65l12.44-6.92,8.45,15.19c-13,9.32-34,14.94-56.67,14.94h-.31c-32.07-.12-60.43-11.54-67.45-27.15l-2.38-5.3-5.8.41c-.92.06-1.88.11-2.76.09-7.43,0-14.59-2.16-19.66-5.89C51,98.88,46.82,95,46.84,89.5c0-9.21,12.1-17,26.38-17h.12c7.65,0,15,2.27,20,6.18l8.73,6.7,8.15,6.34-9.46,9.08a3,3,0,0,0,2.06,5.11H103l28.49-1.12a3,3,0,0,0,2.84-2.65L137.41,73a3,3,0,0,0-5-2.46L121.85,80.64l-14-10.89C110.18,63.9,114,60,117.79,60h0a7,7,0,0,1,3.9,1.38l10.77,7.48,2.18-12.93c2.69-16,26.84-28.45,55-28.45H190c13.95.05,27.49,3.26,37.73,8.79l-8.49,11.53L206,40.38a3,3,0,0,0-4.25,3.56l9.38,26.93a3,3,0,0,0,2.8,2,3.64,3.64,0,0,0,.56,0l28.83-5.54a3,3,0,0,0,.89-5.5l-11-6.15,9.2-12.5,3.29-4a4.62,4.62,0,0,1,3-2h0c1.09,0,2.51,1.13,3.7,2.94a21.21,21.21,0,0,1,3,11.44c0,.78,0,1.57-.12,2.34l-.77,7.56L262,62.86C269.88,64.39,276,75,276,87,276,100.2,268.62,111.31,260,111.31Z" transform="translate(-24.5 -6.45)"/></g><g id="cloud_txt_around" data-name="cloud txt around"><path class="cls-3" d="M-105.48-657.69" transform="translate(-24.5 -6.45)"/><path class="cls-3" d="M-1014.59-679.48" transform="translate(-24.5 -6.45)"/></g></svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

39
assets/main.css Normal file
View File

@ -0,0 +1,39 @@
body {
width: 400px;
margin: auto !important;
}
#header {
text-align: center;
margin-top: 20px;
}
#header #logo {
width: 150px;
margin: 5px;
}
.location {
text-align: center;
}
.location h3 {
font-size: 1em;
}
.location ul {
list-style: none;
padding: 0;
}
.up {
color: green;
}
.down {
color: red;
}
.unknown {
color: orange;
}

131
generate.sh Executable file
View File

@ -0,0 +1,131 @@
#!/bin/sh
TITLE="Recycled Cloud Status"
LOCATIONS="lnth.ch lsne.ch fvil.ch"
EXTERNAL_PROMETHEUS_ADDR=http://localhost:9090
query () {
endpoint="$1/api/v1/query"
query=$2
curl "$endpoint" --data-urlencode "query=$query" | jq --raw-output .data.result[].value[1]
}
get_state () {
case "$1" in
0)
echo "down"
;;
1)
echo "up"
;;
*)
echo "unknown"
;;
esac
}
get_canary_state () {
location=$1
inet=$2
instance="canary.$location.recycled.cloud"
job="blackbox-external-v$inet"
result=$(query $EXTERNAL_PROMETHEUS_ADDR \
"probe_success{instance=\"$instance\", job=\"$job\"}")
get_state "$result"
}
get_edge_state () {
location=$1
edge=$2
instance="edge$edge-$(echo "$location" | cut -d. -f1).transfer.recycled.cloud"
result=$(query $EXTERNAL_PROMETHEUS_ADDR \
"probe_success{instance=\"$instance\"}")
get_state "$result"
}
cat << EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>${TITLE:?}</title>
<link rel="stylesheet" href="assets/main.css">
<link rel="stylesheet" href="assets/bootstrap-reboot.min.css">
<link rel="stylesheet" href="assets/bootstrap-grid.min.css">
</head>
<body>
<div id="header">
<img src="assets/cloud.svg" id="logo" />
<h1>${TITLE:?}</h1>
<p>This page reports the status of the <a
href="https://recycled.cloud">Recycled Cloud</a> infrastructure,
regenerated every minute.
</p>
<p>
States:
<span class="up">up</span>
<span class="down">down</span>
<span class="unknown">unknown</span>
</p>
<p>
Last refresh on <b>$(date)</b>.
</p>
</div>
EOF
for location in $LOCATIONS; do
canary_v6=$(get_canary_state "$location" 6)
canary_v4=$(get_canary_state "$location" 4)
edge1_transfer=$(get_edge_state "$location" 1)
edge2_transfer=$(get_edge_state "$location" 2)
cat <<- EOF
<div class="location">
<hr />
<h2>$location</h2>
<div class="row">
<div class="col-6">
<h3>Routers</h3>
<ul>
<li>edge1 <span class="$edge1_transfer">$edge1_transfer</span></li>
<li>edge2 <span class="$edge2_transfer">$edge2_transfer</span></li>
</ul>
</div>
<div class="col-6">
<h3>Canary VM</h3>
<ul>
<li>IPv6 <span class="$canary_v6">$canary_v6</span></li>
<li>IPv4 <span class="$canary_v4">$canary_v4</span></li>
</ul>
</div>
</div>
<!-- not implemented yet
<h3>Capacity</h3>
<div class="row">
<div class="col-6">
<p>Used RAM: X / XX GB</p>
</div>
<div class="col-6">
<p>Used Storage: X / XX GB</p>
</div>
</div>
-->
</div>
EOF
done
cat << EOF
</body>
</html>
EOF