Compare commits

...

55 Commits
v0.0.5 ... main

Author SHA1 Message Date
Kekskurse 94d1f90722
ci: fix pipeline
/ Release (push) Has started running Details
2023-07-24 01:53:14 +02:00
Kekskurse 383ce965a0
ci: fix pipeline
/ Release (push) Has started running Details
2023-07-24 01:50:56 +02:00
Kekskurse 3fde27f83b
stuff
/ Release (push) Successful in 1m10s Details
2023-07-21 16:11:16 +02:00
Kekskurse 28b5ccca8e
stuff
/ Release (push) Successful in 1m14s Details
2023-07-21 16:02:35 +02:00
Kekskurse 280a9559f6
Default config
/ Release (push) Successful in 1m8s Details
2023-07-21 13:31:00 +02:00
Kekskurse a80fcb5d4c
Default config
/ Release (push) Successful in 1m7s Details
2023-07-21 13:25:35 +02:00
Kekskurse 40d601f5b4
docs: Update Readme
/ Release (push) Successful in 1m14s Details
2023-07-21 12:38:29 +02:00
Kekskurse 2ebe72790f
docs: Update Readme
/ Release (push) Successful in 1m9s Details
2023-07-21 12:38:12 +02:00
Kekskurse 1d09eef545
Publish Tag
/ Release (push) Successful in 1m11s Details
2023-07-21 12:31:36 +02:00
Kekskurse 387ba50c26
ci: release
/ Release (push) Failing after 27s Details
2023-07-21 12:26:43 +02:00
Kekskurse 8a06fe56cf
ci: run
/ Release (push) Successful in 1m6s Details
2023-07-21 12:24:07 +02:00
Kekskurse ab83e1ff5e
ci: run
/ Release (push) Failing after 1m8s Details
2023-07-21 12:19:16 +02:00
Kekskurse 1d54f47988
ci: run
/ Release (push) Successful in 1m9s Details
2023-07-21 12:05:18 +02:00
Kekskurse eaaee5c3ef
ci: run
/ Release (push) Failing after 5s Details
2023-07-21 12:04:49 +02:00
Kekskurse b65aff651c
ci: run
/ Release (push) Successful in 1m4s Details
2023-07-21 12:03:25 +02:00
Kekskurse a49ed9a9a7
ci: run
/ Release (push) Failing after 25s Details
2023-07-21 12:02:31 +02:00
Kekskurse 4a54b35510
ci: run
/ Release (push) Failing after 25s Details
2023-07-21 12:01:21 +02:00
Kekskurse ee5075f47f
ci: run 2023-07-21 12:00:41 +02:00
Kekskurse 711a0714a4
ci: trigger 2023-07-21 11:59:05 +02:00
Kekskurse 5b815e1932
ci: new pipeline 2023-07-21 11:58:08 +02:00
Kekskurse 326b2e459e
Update logging 2023-07-21 11:52:30 +02:00
Kekskurse 4b41ef1c55
Fix
continuous-integration/drone/push Build is passing Details
2022-03-10 20:05:49 +01:00
Kekskurse 6ff70bd77b
#1 fix version check
continuous-integration/drone/push Build is passing Details
2022-03-10 19:42:57 +01:00
Kekskurse b93ac4639d
Fix Versions Cehck Template issue
continuous-integration/drone/push Build is passing Details
2021-11-29 07:33:34 +01:00
Kekskurse 07cd22131f
Versions Check
continuous-integration/drone/push Build is passing Details
2021-11-29 07:31:30 +01:00
Kekskurse 2199301dc7
Update Readme
continuous-integration/drone/push Build is passing Details
2021-11-29 07:13:19 +01:00
Kekskurse 3fe3f39bea
Remove postinstall
continuous-integration/drone/push Build is passing Details
2021-11-29 07:09:13 +01:00
Kekskurse 47da117ca3
Update Readme
continuous-integration/drone/push Build is passing Details
2021-11-29 07:00:18 +01:00
Kekskurse b9188f5006
Update install script 2021-11-29 06:59:09 +01:00
Kekskurse 827b4a8fce
install python3
continuous-integration/drone/push Build is passing Details
2021-11-29 06:54:08 +01:00
Kekskurse fa4a4a6678
Remove postremove!
continuous-integration/drone/push Build is passing Details
2021-11-29 06:51:39 +01:00
Kekskurse 6d42aac7b9
Install script
continuous-integration/drone/push Build is passing Details
2021-11-29 06:50:09 +01:00
Kekskurse 1ec4407008
Run as non-root-user
continuous-integration/drone/push Build is passing Details
2021-11-29 06:12:26 +01:00
Kekskurse 554593a045
Need to enabled checks
continuous-integration/drone/push Build is passing Details
2021-11-29 06:02:41 +01:00
Kekskurse 9df2804eb8
Add HTTP Basic Auth
continuous-integration/drone/push Build is passing Details
2021-11-29 05:53:12 +01:00
Kekskurse f84f300488
Version
continuous-integration/drone/push Build is passing Details
2021-11-25 02:35:17 +01:00
Kekskurse be95054f69
Fix width
continuous-integration/drone/push Build is passing Details
2021-11-25 02:12:32 +01:00
Kekskurse 09e479201b
config hdd fix
continuous-integration/drone/push Build is passing Details
2021-11-25 02:05:36 +01:00
Kekskurse ec1303988f
remove js libs
continuous-integration/drone/push Build is passing Details
2021-11-25 02:03:54 +01:00
Kekskurse 1558252809
Remove all Javascript
continuous-integration/drone/push Build is passing Details
2021-11-25 02:01:27 +01:00
Kekskurse 8d6b4d6db6
Add Systemd Check
continuous-integration/drone/push Build is passing Details
2021-10-21 12:15:55 +02:00
Kekskurse 193d863ef4
gui add load
continuous-integration/drone/push Build is passing Details
2021-09-20 23:59:44 +02:00
Kekskurse 9e4445314f
fix error handling 2021-09-20 23:52:07 +02:00
Kekskurse 1b1dd543e0
add postinstall script
continuous-integration/drone/push Build is passing Details
2021-09-20 23:39:24 +02:00
Kekskurse bb14c6215b
gui http status code
continuous-integration/drone/push Build is passing Details
2021-09-20 23:28:24 +02:00
Kekskurse 27929b8039
fix memory swap issue
continuous-integration/drone/push Build is passing Details
2021-09-20 23:22:02 +02:00
Kekskurse 4f861883fc
stuff
continuous-integration/drone/push Build is passing Details
2021-09-20 23:14:52 +02:00
Kekskurse 50fff7b5ad
dev: add more info for logging
continuous-integration/drone/push Build is passing Details
2021-09-20 23:12:07 +02:00
Kekskurse d6747cd8ce
dev: add more info for logging
continuous-integration/drone/push Build is passing Details
2021-09-20 23:03:07 +02:00
Kekskurse 532a654c9f
responsive
continuous-integration/drone/push Build is passing Details
2021-09-20 16:48:13 +02:00
Kekskurse 96ee365569
add swap
continuous-integration/drone/push Build is passing Details
2021-09-20 16:45:34 +02:00
Kekskurse b5196312d2
change memoer check output
continuous-integration/drone/push Build is passing Details
2021-09-20 16:27:05 +02:00
Kekskurse a1d2a82742
fix bug if everything is ok 2021-09-20 16:09:52 +02:00
Kekskurse 21b8dd0529
gui
continuous-integration/drone/push Build is passing Details
2021-09-20 15:45:01 +02:00
Kekskurse a4a6c9c261
dev: hdd just physical stuff
continuous-integration/drone/push Build is passing Details
2021-09-20 14:06:11 +02:00
17 changed files with 509 additions and 33 deletions

View File

@ -0,0 +1,36 @@
run-name: ${{ github.actor }} is testing
on: ["push"]
jobs:
Release:
runs-on: docker
#container:
# image: goreleaser/goreleaser
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
#- run: goreleaser release --skip-publish --snapshot --rm-dist --debug
- name: Setup Go environment
uses: https://github.com/actions/setup-go@v2.1.3
with:
go-version: 1.20
- name: Run GoReleaser
uses: https://github.com/goreleaser/goreleaser-action@v4
with:
# either 'goreleaser' (default) or 'goreleaser-pro'
distribution: goreleaser
version: latest
args: release --skip-publish --snapshot --rm-dist --debug --clean
env:
GORELEASER_FORCE_TOKEN: "gitea"
- name: Copy deb to publish folder
run: mkdir publish; cp dist/*deb publish/last.deb
- name: Upload to s3
uses: https://github.com/shallwefootball/s3-upload-action@master
with:
aws_key_id: ${{ secrets.AWS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY}}
aws_bucket: 'kekscloud-releases'
source_dir: 'publish/'
destination_dir: 'http-server-status/'
endpoint: 's3.eu-central-003.backblazeb2.com'

View File

@ -0,0 +1,40 @@
run-name: ${{ github.actor }} is testing
on:
push:
tags:
- '*'
jobs:
Release:
runs-on: docker
#container:
# image: goreleaser/goreleaser
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
#- run: goreleaser release --skip-publish --snapshot --rm-dist --debug
- name: Setup Go environment
uses: https://github.com/actions/setup-go@v2.1.3
with:
go-version: 1.20
- name: Run GoReleaser
uses: https://github.com/goreleaser/goreleaser-action@v4
with:
# either 'goreleaser' (default) or 'goreleaser-pro'
distribution: goreleaser
version: latest
args: release --clean
env:
GORELEASER_FORCE_TOKEN: "gitea"
GITEA_TOKEN: "${{ secrets.GITEA }}"
- name: Copy deb to publish folder
run: mkdir publish; cp dist/*deb publish/stable.deb; cp dist/*deb publish/
- name: Upload to s3
uses: https://github.com/shallwefootball/s3-upload-action@master
with:
aws_key_id: ${{ secrets.AWS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY}}
aws_bucket: 'kekscloud-releases'
source_dir: 'publish/'
destination_dir: 'http-server-status/'
endpoint: 's3.eu-central-003.backblazeb2.com'

View File

@ -15,11 +15,8 @@ builds:
#- darwin
goarch:
- amd64
archives:
- replacements:
darwin: Darwin
386: i386
amd64: x86_64
ldflags:
- -X main.version={{ .Version }}
checksum:
name_template: 'checksums.txt'
changelog:
@ -49,4 +46,7 @@ nfpms:
- src: init/http-server-status.service
dst: /etc/systemd/system/http-server-status.service
- src: config.yml
dst: /etc/http-server-status/config.yml.sample
dst: /etc/http-server-status/config.yml.sample
scripts:
postinstall: "scripts/postinstall.sh"
preinstall: "scripts/preinstall.sh"

View File

@ -1,19 +1,32 @@
# HTTP Server Status
Status Page for your VM or HDD Server to montiro with an external tool like uptimerobot.com
Status Page with your Server informations (HDD usage, ram usage, load, systemd) which returns a http Status 500 if a limit is reached. With this Service you can monitor your Server with a external tool like uptimerobot.com.
# Installation
To Install the Server Montiroing download the last .deb File from the Release page and save it as http-server-status.deb on your server. Than install the package with dpkg
## Dowanload URLs:
* Last Dev Build: `https://kekscloud-releases.s3.eu-central-003.backblazeb2.com/http-server-status/last.deb`
* Last Release Build: `https://kekscloud-releases.s3.eu-central-003.backblazeb2.com/http-server-status/stable.deb`
* Special Version: `https://kekscloud-releases.s3.eu-central-003.backblazeb2.com/http-server-status/http-server-status_1.0.7_linux_amd64.deb` (Bigger than 1.0.7)
To Install the Server Montiroing download the last .deb File from the Release page or the links above and save it as http-server-status.deb on your server. Than install the package with dpkg
```
dpkg -i http-server-status.deb
```
# Config
Copy the config sample and edit the config.
```bigquery
cp /etc/http-server-status/config.yml.sample /etc/http-server-status/config.yml
nano /etc/http-server-status/config.yml
```
# Run
After this start the server
```

View File

@ -1,7 +1,6 @@
package main
import (
"fmt"
"github.com/rs/zerolog/log"
"gopkg.in/yaml.v2"
"http-server-status/internal/pkg/checks"
@ -15,15 +14,21 @@ type Config struct {
HTTP struct{
Listen string `yaml:"listen"`
} `yaml:"http"`
Auth struct{
Enabled bool `yaml:"enabled"`
Username string `yaml:"username"`
Password string `yaml:"password"`
} `yaml:"auth"`
Checks struct{
HDD checks.HDDConfig `yaml:"hdd"`
Load checks.LoadConfig `yaml:"load"`
Memory checks.MemoryConfig `yaml:"memory"`
Systemd checks.SystemdConf `yaml:"systemd"`
Version checks.VersionConfig `yaml:"version"`
} `yaml:"checks"`
}
func readConfig() {
fmt.Println(os.Args)
filename := "/etc/http-server-status/config.yml"
if len(os.Args) > 1 {
filename = os.Args[1]
@ -39,4 +44,6 @@ func readConfig() {
if err != nil {
log.Fatal().Err(err).Msg("Cant parse yaml file")
}
c.Checks.Version.Version = version
}

View File

@ -1,12 +1,27 @@
http:
listen: ":3003"
auth:
enabled: false
username: test
password: test
checks:
hdd:
max_percent: 100
enabled: true
max_percent: 80
load:
enabled: true
max_load_1: 10
max_load_5: 8
max_load_15: 5
memory:
max: 70
enabled: true
max: 80
max_swap: 80
systemd:
enabled: true
services:
- sshd
version:
enabled: true

View File

@ -1,11 +1,11 @@
[Unit]
Description=Go Mail Admin
Description=HTTP Status Server
After=syslog.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/http-server-status
User=http-server-status
ExecStart=/usr/bin/http-server-status
SyslogIdentifier=http-server-status
StandardOutput=syslog
StandardError=syslog

5
install.sh Normal file
View File

@ -0,0 +1,5 @@
URL=`python3 -c 'import urllib.request;import json;f = urllib.request.urlopen("https://git.keks.cloud/api/v1/repos/kekskurse/http-server-status/releases?limit=1");d = json.loads(f.read().decode("utf-8"));
for asset in d[0]["assets"]: x = asset["browser_download_url"] if asset["name"][-4:] == ".deb" else ""; print(x, end="");'`
wget -O hss.deb $URL
dpkg -i hss.deb
rm hss.deb

View File

@ -1,12 +1,12 @@
package checks
import (
"github.com/rs/zerolog/log"
"github.com/shirou/gopsutil/disk"
)
type HDDConfig struct {
MaxPercent int `yaml:"max_percent"`
Enabled bool `yaml:"enabled"`
}
type HDD struct {
@ -14,9 +14,11 @@ type HDD struct {
}
func (h HDD) Execute() (ok bool, data interface{}, err error) {
if h.Config.Enabled == false {
return true, nil, nil
}
success := true
parts, _ := disk.Partitions(true)
log.Debug().Int("max_percent", h.Config.MaxPercent).Msg("Execute HDD Check")
parts, _ := disk.Partitions(false)
usage := make(map[string]float64)
for _, p := range parts {
device := p.Mountpoint
@ -32,5 +34,5 @@ func (h HDD) Execute() (ok bool, data interface{}, err error) {
}
func (h HDD) Name() string {
return "Disc space"
return "DiscSpace"
}

View File

@ -8,6 +8,7 @@ type LoadConfig struct {
MaxLoad1 float64 `yaml:"max_load_1"`
MaxLoad5 float64 `yaml:"max_load_5"`
MaxLoad15 float64 `yaml:"max_load_15"`
Enabled bool `yaml:"enabled"`
}
type Load struct {
@ -15,6 +16,9 @@ type Load struct {
}
func (h Load) Execute() (ok bool, data interface{}, err error) {
if h.Config.Enabled == false {
return true, nil, nil
}
load, err := loadavg.Get()
if load.Loadavg1 > h.Config.MaxLoad1 {
return false,load, nil
@ -32,5 +36,5 @@ func (h Load) Execute() (ok bool, data interface{}, err error) {
}
func (h Load) Name() string {
return "System Load"
return "SystemLoad"
}

View File

@ -1,11 +1,14 @@
package checks
import (
"fmt"
"github.com/mackerelio/go-osstat/memory"
)
type MemoryConfig struct {
Max float64 `yaml:"max"`
MaxSwap float64 `yaml:"max_swap"`
Enabled bool `yaml:"enabled"`
}
type Memory struct {
@ -13,15 +16,32 @@ type Memory struct {
}
func (h Memory) Execute() (ok bool, data interface{}, err error) {
if h.Config.Enabled == false {
return true, nil, nil
}
memory, err := memory.Get()
fmt.Println(memory)
p := float64(100) / float64(memory.Total) * float64(memory.Used)
if p > h.Config.Max {
return false, memory, nil
ps := float64(100) / float64(memory.SwapTotal) * float64(memory.SwapUsed)
res := make(map[string]interface{})
res["row"] = memory
res["ram"] = p
res["swap"] = ps
if memory.SwapTotal == 0 {
res["swap"] = 100
}
return true, memory,nil
fmt.Println(ps)
if p > h.Config.Max {
return false, res, nil
}
if ps > h.Config.MaxSwap {
return false, res, nil
}
return true, res,nil
}
func (h Memory) Name() string {
return "Memory usage"
return "MemoryUsage"
}

View File

@ -0,0 +1,63 @@
package checks
import (
"github.com/rs/zerolog/log"
"os/exec"
"strings"
)
type SystemdConf struct {
Services []string `yaml:"services"`
Enabled bool `yaml:"enabled"`
}
type Systemd struct {
Config SystemdConf
}
func (h Systemd) Execute() (ok bool, data interface{}, err error) {
if h.Config.Enabled == false {
return true, nil, nil
}
success := true
servicelist := make(map[string]bool)
for _, service := range h.Config.Services {
res, err := h.getStatus(service)
if err != nil {
return false, nil, err
}
if res == false {
success = false
}
servicelist[service] = res
}
return success, servicelist,nil
}
func (h Systemd) Name() string {
return "SystemdStatus"
}
func (h Systemd) getStatus(name string) (bool, error) {
cmd := exec.Command("systemctl", "check", name)
out, err := cmd.CombinedOutput()
if err != nil {
log.Debug().Err(err).Msg("Error in systemd communication")
if exitErr, ok := err.(*exec.ExitError); ok {
if exitErr.ExitCode() == 3 {
return false, nil
}
}
return false, err
}
s := string(out)
s = strings.Trim(s, "\n")
if s == "active" {
return true, nil
}
return false, nil
}

View File

@ -0,0 +1,45 @@
package checks
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
type VersionConfig struct {
Enabled bool `yaml:"enabled"`
Version string
}
type Version struct {
Config VersionConfig
}
func (h Version) Execute() (ok bool, data interface{}, err error) {
if h.Config.Enabled == false {
return true, nil, nil
}
resp, err := http.Get("https://git.keks.cloud/api/v1/repos/kekskurse/http-server-status/releases?limit=1")
defer resp.Body.Close()
var g []struct {
TagName string `json:"tag_name"`
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return false, nil, err
}
json.Unmarshal(body, &g)
if g[0].TagName == fmt.Sprintf("v%v", h.Config.Version) {
return true, map[string]string{"version": g[0].TagName}, nil
}
return false, map[string]string{"version": g[0].TagName}, nil
}
func (h Version) Name() string {
return "Version"
}

72
main.go
View File

@ -1,27 +1,74 @@
package main
import (
_ "embed"
"encoding/json"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
checks "http-server-status/internal/pkg/checks"
"net/http"
"os"
"sync"
"text/template"
)
//go:embed template/index.html
var s string
var (
version = "development"
)
var checkList []checks.Check
func init() {
readConfig()
log.Debug().Int("max_percent", c.Checks.HDD.MaxPercent).Msg("HDD CHECK")
checkList = append(checkList, checks.HDD{c.Checks.HDD}, checks.Memory{Config: c.Checks.Memory}, checks.Load{Config: c.Checks.Load})
pp := log.Output(zerolog.ConsoleWriter{Out: os.Stdout})
multi := zerolog.MultiLevelWriter(pp)
log.Logger = zerolog.New(multi).With().Timestamp().Caller().Logger()
checkList = append(checkList, checks.HDD{c.Checks.HDD}, checks.Memory{Config: c.Checks.Memory}, checks.Load{Config: c.Checks.Load}, checks.Systemd{Config: c.Checks.Systemd}, checks.Version{Config: c.Checks.Version})
}
func auth(fn http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if c.Auth.Enabled {
user, pass, _ := r.BasicAuth()
if !check(user, pass) {
w.Header().Set("WWW-Authenticate", `Basic realm="MY REALM"`)
http.Error(w, "Unauthorized.", 401)
return
}
}
fn(w, r)
}
}
func check(u, p string) bool {
if u == c.Auth.Username && p == c.Auth.Password {
return true
}
return false
}
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
http.Redirect(writer, request, "/data.json", http.StatusSeeOther)
})
http.HandleFunc("/data.json", handler)
http.HandleFunc("/", auth(func(writer http.ResponseWriter, request *http.Request) {
res, gloableRes := checkSystem()
if gloableRes == false {
writer.WriteHeader(http.StatusInternalServerError)
}
t, err := template.New("todos").Parse(s)
if err != nil {
panic(err)
}
t.Execute(writer, map[string]interface{}{"checks":res, "version": version})
//writer.Write([]byte(s))
}))
http.HandleFunc("/data.json", auth(handler))
err := http.ListenAndServe(c.HTTP.Listen, nil)
log.Fatal().Err(err).Msg("Shutdown")
}
@ -37,7 +84,7 @@ func handler(w http.ResponseWriter, r *http.Request) {
resJson, err := json.Marshal(httpResposne)
if err != nil {
log.Fatal().Err(err).Msg("Check Error")
log.Fatal().Err(err).Interface("httpResponse", ResultReturn{}).Msg("Check Error")
}
if gloableRes {
w.Write(resJson)
@ -47,6 +94,7 @@ func handler(w http.ResponseWriter, r *http.Request) {
}
type ResultReturn struct {
Success bool `json:"success"`
Data interface{} `json:"data"`
@ -56,18 +104,26 @@ func checkSystem() (map[string]ResultReturn, bool) {
globaleResult := true
wg := sync.WaitGroup{}
res := make(map[string]ResultReturn)
mutex := sync.Mutex{}
for _, c := range checkList {
wg.Add(1)
go func(check checks.Check) {
defer wg.Done()
s, data, _ := check.Execute()
s, data, err := check.Execute()
if err != nil {
log.Error().Err(err).Msg("Cant execute check")
return
}
log.Debug().Str("check", check.Name()).Bool("status", s).Interface("Data", data).Msg("Executed Check, got Results")
if s == false {
globaleResult = false
}
mutex.Lock()
res[check.Name()] = ResultReturn{
Success: s,
Data: data,
}
mutex.Unlock()
}(c)
}
wg.Wait()

View File

@ -1,2 +1,12 @@
if [ -f "/etc/http-server-status/config.yml" ]; then
echo "Config exists"
else
cp /etc/http-server-status/config.yml.sample /etc/http-server-status/config.yml
fi
systemctl daemon-reload
systemctl restart http-server-status
STATUS="$(systemctl is-active tomcat.service)"
if [ "${STATUS}" = "active" ]; then
systemctl restart http-server-status
echo "Restart Service"
fi

4
scripts/preinstall.sh Normal file
View File

@ -0,0 +1,4 @@
#/bin/sh
if ! id -u http-server-status > /dev/null 2>&1; then
adduser --system http-server-status
fi

156
template/index.html Normal file
View File

@ -0,0 +1,156 @@
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>HTTP Status Page</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<h1>HTTP Status Page</h1>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header {{if .checks.DiscSpace.Success }}bg-success{{else}}bg-danger{{end}}" id="hddtitle">
Check HDD
</div>
<div class="card-body" id="hddpercent">
<table class="table">
{{range $key, $val := .checks.DiscSpace.Data}}
<tr>
<td style="width: 20%">{{ $key }}</td>
<td>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{ $val }}%;" aria-valuenow="{{ $val }}" aria-valuemin="0" aria-valuemax="100">{{ $val }}%</div>
</div>
</td>
</tr>
{{end }}
</table>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header {{if .checks.MemoryUsage.Success }}bg-success{{else}}bg-danger{{end}}" id="ramtitle">
Check RAM
</div>
<div class="card-body">
{{ if .checks.MemoryUsage.Data }}
<table class="table">
<tr>
<th style="width: 20%">Ram</th>
<td>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{ .checks.MemoryUsage.Data.ram }}%;" aria-valuenow="{{ .checks.MemoryUsage.Data.ram }}" aria-valuemin="0" aria-valuemax="100">{{ .checks.MemoryUsage.Data.ram }}%</div>
</div>
</td>
</tr>
<tr>
<th style="width: 20%">Swap</th>
<td>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: {{ .checks.MemoryUsage.Data.swap }}%;" aria-valuenow="{{ .checks.MemoryUsage.Data.swap }}" aria-valuemin="0" aria-valuemax="100">{{ .checks.MemoryUsage.Data.swap }}%</div>
</div>
</td>
</tr>
</table>
{{ end }}
</div>
</div>
</div>
</div>
<div class="row" style="margin-top: 20px;">
<div class="col-md-6">
<div class="card">
<div class="card-header {{if .checks.SystemLoad.Success }}bg-success{{else}}bg-danger{{end}}" id="loadtitle">
Check Load
</div>
<div class="card-body">
{{ if .checks.SystemLoad.Data }}
<table class="table">
<tr>
<th style="width: 20%">1</th>
<td>{{ .checks.SystemLoad.Data.Loadavg1 }}</td>
</tr>
<tr>
<th style="width: 20%">5</th>
<td>{{ .checks.SystemLoad.Data.Loadavg5 }}</td>
</tr>
<tr>
<th style="width: 20%">15</th>
<td>{{ .checks.SystemLoad.Data.Loadavg15 }}</td>
</tr>
</table>
{{ end }}
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header {{if .checks.SystemdStatus.Success }}bg-success{{else}}bg-danger{{end}}" id="systemdtitle">
Systemd Check
</div>
<div class="card-body">
<table class="table">
{{range $key, $val := .checks.SystemdStatus.Data}}
<tr>
<td>{{ $key }}</td>
<td>
{{ $val }}
</td>
</tr>
{{end }}
</table>
</div>
</div>
</div>
</div>
<div class="row" style="margin-top: 20px;">
<div class="col-md-6">
<div class="card">
<div class="card-header {{if .checks.Version.Success }}bg-success{{else}}bg-danger{{end}}" id="loadtitle">
Version
</div>
<div class="card-body">
{{ if .checks.Version.Data }}
Newest Version: {{ .checks.Version.Data.version }}
{{ end }}
</div>
</div>
</div>
<div class="col-md-6">
</div>
</div>
</div>
</div>
<div class="container">
<footer class="d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
<div class="col-md-4 d-flex align-items-center">
<a href="/" class="mb-3 me-2 mb-md-0 text-muted text-decoration-none lh-1">
<svg class="bi" width="30" height="24"><use xlink:href="#bootstrap"/></svg>
</a>
<span class="text-muted">Version: {{ .version }}</span>
</div>
<ul class="nav col-md-4 justify-content-end list-unstyled d-flex">
<li><a href="https://git.keks.cloud/kekskurse/http-server-status">Git/Source Code</a></li>
</ul>
</footer>
</div>
</body>
</html>