Compare commits
No commits in common. "main" and "v0.0.5" have entirely different histories.
|
@ -1,36 +0,0 @@
|
||||||
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'
|
|
|
@ -1,40 +0,0 @@
|
||||||
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'
|
|
|
@ -15,8 +15,11 @@ builds:
|
||||||
#- darwin
|
#- darwin
|
||||||
goarch:
|
goarch:
|
||||||
- amd64
|
- amd64
|
||||||
ldflags:
|
archives:
|
||||||
- -X main.version={{ .Version }}
|
- replacements:
|
||||||
|
darwin: Darwin
|
||||||
|
386: i386
|
||||||
|
amd64: x86_64
|
||||||
checksum:
|
checksum:
|
||||||
name_template: 'checksums.txt'
|
name_template: 'checksums.txt'
|
||||||
changelog:
|
changelog:
|
||||||
|
@ -47,6 +50,3 @@ nfpms:
|
||||||
dst: /etc/systemd/system/http-server-status.service
|
dst: /etc/systemd/system/http-server-status.service
|
||||||
- src: config.yml
|
- 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"
|
|
17
Readme.md
17
Readme.md
|
@ -1,32 +1,19 @@
|
||||||
# HTTP Server Status
|
# HTTP Server Status
|
||||||
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.
|
Status Page for your VM or HDD Server to montiro with an external tool like uptimerobot.com
|
||||||
|
|
||||||
|
|
||||||
# Installation
|
# 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
|
dpkg -i http-server-status.deb
|
||||||
```
|
```
|
||||||
|
|
||||||
# Config
|
|
||||||
|
|
||||||
Copy the config sample and edit the config.
|
Copy the config sample and edit the config.
|
||||||
```bigquery
|
```bigquery
|
||||||
cp /etc/http-server-status/config.yml.sample /etc/http-server-status/config.yml
|
cp /etc/http-server-status/config.yml.sample /etc/http-server-status/config.yml
|
||||||
nano /etc/http-server-status/config.yml
|
nano /etc/http-server-status/config.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
# Run
|
|
||||||
|
|
||||||
After this start the server
|
After this start the server
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
11
config.go
11
config.go
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
"http-server-status/internal/pkg/checks"
|
"http-server-status/internal/pkg/checks"
|
||||||
|
@ -14,21 +15,15 @@ type Config struct {
|
||||||
HTTP struct{
|
HTTP struct{
|
||||||
Listen string `yaml:"listen"`
|
Listen string `yaml:"listen"`
|
||||||
} `yaml:"http"`
|
} `yaml:"http"`
|
||||||
Auth struct{
|
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
Username string `yaml:"username"`
|
|
||||||
Password string `yaml:"password"`
|
|
||||||
} `yaml:"auth"`
|
|
||||||
Checks struct{
|
Checks struct{
|
||||||
HDD checks.HDDConfig `yaml:"hdd"`
|
HDD checks.HDDConfig `yaml:"hdd"`
|
||||||
Load checks.LoadConfig `yaml:"load"`
|
Load checks.LoadConfig `yaml:"load"`
|
||||||
Memory checks.MemoryConfig `yaml:"memory"`
|
Memory checks.MemoryConfig `yaml:"memory"`
|
||||||
Systemd checks.SystemdConf `yaml:"systemd"`
|
|
||||||
Version checks.VersionConfig `yaml:"version"`
|
|
||||||
} `yaml:"checks"`
|
} `yaml:"checks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func readConfig() {
|
func readConfig() {
|
||||||
|
fmt.Println(os.Args)
|
||||||
filename := "/etc/http-server-status/config.yml"
|
filename := "/etc/http-server-status/config.yml"
|
||||||
if len(os.Args) > 1 {
|
if len(os.Args) > 1 {
|
||||||
filename = os.Args[1]
|
filename = os.Args[1]
|
||||||
|
@ -44,6 +39,4 @@ func readConfig() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Msg("Cant parse yaml file")
|
log.Fatal().Err(err).Msg("Cant parse yaml file")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Checks.Version.Version = version
|
|
||||||
}
|
}
|
19
config.yml
19
config.yml
|
@ -1,27 +1,12 @@
|
||||||
http:
|
http:
|
||||||
listen: ":3003"
|
listen: ":3003"
|
||||||
|
|
||||||
auth:
|
|
||||||
enabled: false
|
|
||||||
username: test
|
|
||||||
password: test
|
|
||||||
|
|
||||||
checks:
|
checks:
|
||||||
hdd:
|
hdd:
|
||||||
enabled: true
|
max_percent: 100
|
||||||
max_percent: 80
|
|
||||||
load:
|
load:
|
||||||
enabled: true
|
|
||||||
max_load_1: 10
|
max_load_1: 10
|
||||||
max_load_5: 8
|
max_load_5: 8
|
||||||
max_load_15: 5
|
max_load_15: 5
|
||||||
memory:
|
memory:
|
||||||
enabled: true
|
max: 70
|
||||||
max: 80
|
|
||||||
max_swap: 80
|
|
||||||
systemd:
|
|
||||||
enabled: true
|
|
||||||
services:
|
|
||||||
- sshd
|
|
||||||
version:
|
|
||||||
enabled: true
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=HTTP Status Server
|
Description=Go Mail Admin
|
||||||
After=syslog.target
|
After=syslog.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
User=http-server-status
|
User=root
|
||||||
ExecStart=/usr/bin/http-server-status
|
ExecStart=/usr/local/bin/http-server-status
|
||||||
SyslogIdentifier=http-server-status
|
SyslogIdentifier=http-server-status
|
||||||
StandardOutput=syslog
|
StandardOutput=syslog
|
||||||
StandardError=syslog
|
StandardError=syslog
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
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
|
|
|
@ -1,12 +1,12 @@
|
||||||
package checks
|
package checks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/shirou/gopsutil/disk"
|
"github.com/shirou/gopsutil/disk"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HDDConfig struct {
|
type HDDConfig struct {
|
||||||
MaxPercent int `yaml:"max_percent"`
|
MaxPercent int `yaml:"max_percent"`
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type HDD struct {
|
type HDD struct {
|
||||||
|
@ -14,11 +14,9 @@ type HDD struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h HDD) Execute() (ok bool, data interface{}, err error) {
|
func (h HDD) Execute() (ok bool, data interface{}, err error) {
|
||||||
if h.Config.Enabled == false {
|
|
||||||
return true, nil, nil
|
|
||||||
}
|
|
||||||
success := true
|
success := true
|
||||||
parts, _ := disk.Partitions(false)
|
parts, _ := disk.Partitions(true)
|
||||||
|
log.Debug().Int("max_percent", h.Config.MaxPercent).Msg("Execute HDD Check")
|
||||||
usage := make(map[string]float64)
|
usage := make(map[string]float64)
|
||||||
for _, p := range parts {
|
for _, p := range parts {
|
||||||
device := p.Mountpoint
|
device := p.Mountpoint
|
||||||
|
@ -34,5 +32,5 @@ func (h HDD) Execute() (ok bool, data interface{}, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h HDD) Name() string {
|
func (h HDD) Name() string {
|
||||||
return "DiscSpace"
|
return "Disc space"
|
||||||
}
|
}
|
|
@ -8,7 +8,6 @@ type LoadConfig struct {
|
||||||
MaxLoad1 float64 `yaml:"max_load_1"`
|
MaxLoad1 float64 `yaml:"max_load_1"`
|
||||||
MaxLoad5 float64 `yaml:"max_load_5"`
|
MaxLoad5 float64 `yaml:"max_load_5"`
|
||||||
MaxLoad15 float64 `yaml:"max_load_15"`
|
MaxLoad15 float64 `yaml:"max_load_15"`
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Load struct {
|
type Load struct {
|
||||||
|
@ -16,9 +15,6 @@ type Load struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Load) Execute() (ok bool, data interface{}, err error) {
|
func (h Load) Execute() (ok bool, data interface{}, err error) {
|
||||||
if h.Config.Enabled == false {
|
|
||||||
return true, nil, nil
|
|
||||||
}
|
|
||||||
load, err := loadavg.Get()
|
load, err := loadavg.Get()
|
||||||
if load.Loadavg1 > h.Config.MaxLoad1 {
|
if load.Loadavg1 > h.Config.MaxLoad1 {
|
||||||
return false,load, nil
|
return false,load, nil
|
||||||
|
@ -36,5 +32,5 @@ func (h Load) Execute() (ok bool, data interface{}, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Load) Name() string {
|
func (h Load) Name() string {
|
||||||
return "SystemLoad"
|
return "System Load"
|
||||||
}
|
}
|
|
@ -1,14 +1,11 @@
|
||||||
package checks
|
package checks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/mackerelio/go-osstat/memory"
|
"github.com/mackerelio/go-osstat/memory"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MemoryConfig struct {
|
type MemoryConfig struct {
|
||||||
Max float64 `yaml:"max"`
|
Max float64 `yaml:"max"`
|
||||||
MaxSwap float64 `yaml:"max_swap"`
|
|
||||||
Enabled bool `yaml:"enabled"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Memory struct {
|
type Memory struct {
|
||||||
|
@ -16,32 +13,15 @@ type Memory struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Memory) Execute() (ok bool, data interface{}, err error) {
|
func (h Memory) Execute() (ok bool, data interface{}, err error) {
|
||||||
if h.Config.Enabled == false {
|
|
||||||
return true, nil, nil
|
|
||||||
}
|
|
||||||
memory, err := memory.Get()
|
memory, err := memory.Get()
|
||||||
fmt.Println(memory)
|
|
||||||
p := float64(100) / float64(memory.Total) * float64(memory.Used)
|
p := float64(100) / float64(memory.Total) * float64(memory.Used)
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(ps)
|
|
||||||
if p > h.Config.Max {
|
if p > h.Config.Max {
|
||||||
return false, res, nil
|
return false, memory, nil
|
||||||
}
|
|
||||||
if ps > h.Config.MaxSwap {
|
|
||||||
return false, res, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, res,nil
|
return true, memory,nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Memory) Name() string {
|
func (h Memory) Name() string {
|
||||||
return "MemoryUsage"
|
return "Memory usage"
|
||||||
}
|
}
|
|
@ -1,63 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
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
72
main.go
|
@ -1,74 +1,27 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/rs/zerolog"
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
checks "http-server-status/internal/pkg/checks"
|
checks "http-server-status/internal/pkg/checks"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed template/index.html
|
|
||||||
var s string
|
|
||||||
|
|
||||||
var (
|
|
||||||
version = "development"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var checkList []checks.Check
|
var checkList []checks.Check
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
readConfig()
|
readConfig()
|
||||||
pp := log.Output(zerolog.ConsoleWriter{Out: os.Stdout})
|
log.Debug().Int("max_percent", c.Checks.HDD.MaxPercent).Msg("HDD CHECK")
|
||||||
multi := zerolog.MultiLevelWriter(pp)
|
checkList = append(checkList, checks.HDD{c.Checks.HDD}, checks.Memory{Config: c.Checks.Memory}, checks.Load{Config: c.Checks.Load})
|
||||||
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() {
|
func main() {
|
||||||
|
|
||||||
http.HandleFunc("/", auth(func(writer http.ResponseWriter, request *http.Request) {
|
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
|
||||||
res, gloableRes := checkSystem()
|
http.Redirect(writer, request, "/data.json", http.StatusSeeOther)
|
||||||
if gloableRes == false {
|
})
|
||||||
writer.WriteHeader(http.StatusInternalServerError)
|
http.HandleFunc("/data.json", handler)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
err := http.ListenAndServe(c.HTTP.Listen, nil)
|
||||||
log.Fatal().Err(err).Msg("Shutdown")
|
log.Fatal().Err(err).Msg("Shutdown")
|
||||||
}
|
}
|
||||||
|
@ -84,7 +37,7 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
resJson, err := json.Marshal(httpResposne)
|
resJson, err := json.Marshal(httpResposne)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Err(err).Interface("httpResponse", ResultReturn{}).Msg("Check Error")
|
log.Fatal().Err(err).Msg("Check Error")
|
||||||
}
|
}
|
||||||
if gloableRes {
|
if gloableRes {
|
||||||
w.Write(resJson)
|
w.Write(resJson)
|
||||||
|
@ -94,7 +47,6 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type ResultReturn struct {
|
type ResultReturn struct {
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
Data interface{} `json:"data"`
|
Data interface{} `json:"data"`
|
||||||
|
@ -104,26 +56,18 @@ func checkSystem() (map[string]ResultReturn, bool) {
|
||||||
globaleResult := true
|
globaleResult := true
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
res := make(map[string]ResultReturn)
|
res := make(map[string]ResultReturn)
|
||||||
mutex := sync.Mutex{}
|
|
||||||
for _, c := range checkList {
|
for _, c := range checkList {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(check checks.Check) {
|
go func(check checks.Check) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
s, data, err := check.Execute()
|
s, data, _ := 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 {
|
if s == false {
|
||||||
globaleResult = false
|
globaleResult = false
|
||||||
}
|
}
|
||||||
mutex.Lock()
|
|
||||||
res[check.Name()] = ResultReturn{
|
res[check.Name()] = ResultReturn{
|
||||||
Success: s,
|
Success: s,
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
mutex.Unlock()
|
|
||||||
}(c)
|
}(c)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
|
@ -1,12 +1,2 @@
|
||||||
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 daemon-reload
|
||||||
STATUS="$(systemctl is-active tomcat.service)"
|
systemctl restart http-server-status
|
||||||
if [ "${STATUS}" = "active" ]; then
|
|
||||||
systemctl restart http-server-status
|
|
||||||
echo "Restart Service"
|
|
||||||
fi
|
|
|
@ -1,4 +0,0 @@
|
||||||
#/bin/sh
|
|
||||||
if ! id -u http-server-status > /dev/null 2>&1; then
|
|
||||||
adduser --system http-server-status
|
|
||||||
fi
|
|
|
@ -1,156 +0,0 @@
|
||||||
<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>
|
|
Loading…
Reference in New Issue