5862a46b00
Module path now gitea.lerkolabs.com/lerko/uptop. Binary moves to cmd/uptop. All imports, display strings, CI config, and docs updated.
159 lines
3.4 KiB
Go
159 lines
3.4 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"gitea.lerkolabs.com/lerko/uptop/internal/models"
|
|
"gitea.lerkolabs.com/lerko/uptop/internal/store"
|
|
"os"
|
|
"sort"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func Export(s store.Store) (*File, error) {
|
|
dbAlerts, err := s.GetAllAlerts()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("load alerts: %w", err)
|
|
}
|
|
|
|
dbSites, err := s.GetSites()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("load sites: %w", err)
|
|
}
|
|
|
|
alertIDToName := make(map[int]string, len(dbAlerts))
|
|
var yamlAlerts []Alert
|
|
for _, a := range dbAlerts {
|
|
alertIDToName[a.ID] = a.Name
|
|
yamlAlerts = append(yamlAlerts, Alert{
|
|
Name: a.Name,
|
|
Type: a.Type,
|
|
Settings: a.Settings,
|
|
})
|
|
}
|
|
|
|
groups := make(map[int]models.Site)
|
|
children := make(map[int][]models.Site)
|
|
var topLevel []models.Site
|
|
|
|
for _, s := range dbSites {
|
|
switch {
|
|
case s.Type == "group":
|
|
groups[s.ID] = s
|
|
case s.ParentID > 0:
|
|
children[s.ParentID] = append(children[s.ParentID], s)
|
|
default:
|
|
topLevel = append(topLevel, s)
|
|
}
|
|
}
|
|
|
|
var yamlMonitors []Monitor
|
|
|
|
groupIDs := make([]int, 0, len(groups))
|
|
for id := range groups {
|
|
groupIDs = append(groupIDs, id)
|
|
}
|
|
sort.Ints(groupIDs)
|
|
|
|
for _, gid := range groupIDs {
|
|
g := groups[gid]
|
|
ym := siteToMonitor(g, alertIDToName)
|
|
kids := children[gid]
|
|
sort.Slice(kids, func(i, j int) bool { return kids[i].ID < kids[j].ID })
|
|
for _, child := range kids {
|
|
ym.Monitors = append(ym.Monitors, siteToMonitor(child, alertIDToName))
|
|
}
|
|
yamlMonitors = append(yamlMonitors, ym)
|
|
}
|
|
|
|
sort.Slice(topLevel, func(i, j int) bool { return topLevel[i].ID < topLevel[j].ID })
|
|
for _, s := range topLevel {
|
|
yamlMonitors = append(yamlMonitors, siteToMonitor(s, alertIDToName))
|
|
}
|
|
|
|
return &File{Alerts: yamlAlerts, Monitors: yamlMonitors}, nil
|
|
}
|
|
|
|
func siteToMonitor(s models.Site, alertIDToName map[int]string) Monitor {
|
|
m := Monitor{
|
|
Name: s.Name,
|
|
Type: s.Type,
|
|
Interval: s.Interval,
|
|
}
|
|
|
|
if s.AlertID > 0 {
|
|
if name, ok := alertIDToName[s.AlertID]; ok {
|
|
m.Alert = name
|
|
}
|
|
}
|
|
|
|
if s.URL != "" {
|
|
m.URL = s.URL
|
|
}
|
|
if s.Hostname != "" {
|
|
m.Hostname = s.Hostname
|
|
}
|
|
if s.Port != 0 {
|
|
m.Port = s.Port
|
|
}
|
|
if s.Timeout != 0 {
|
|
m.Timeout = s.Timeout
|
|
}
|
|
if s.Description != "" {
|
|
m.Description = s.Description
|
|
}
|
|
if s.DNSResolveType != "" {
|
|
m.DNSResolveType = s.DNSResolveType
|
|
}
|
|
if s.DNSServer != "" {
|
|
m.DNSServer = s.DNSServer
|
|
}
|
|
|
|
if s.Method != "" && s.Method != "GET" {
|
|
m.Method = s.Method
|
|
}
|
|
if s.AcceptedCodes != "" && s.AcceptedCodes != "200-299" {
|
|
m.AcceptedCodes = s.AcceptedCodes
|
|
}
|
|
if s.ExpiryThreshold != 0 && s.ExpiryThreshold != 7 {
|
|
m.ExpiryThreshold = s.ExpiryThreshold
|
|
}
|
|
if s.MaxRetries != 0 {
|
|
m.MaxRetries = s.MaxRetries
|
|
}
|
|
|
|
m.CheckSSL = s.CheckSSL
|
|
m.IgnoreTLS = s.IgnoreTLS
|
|
m.Paused = s.Paused
|
|
|
|
if s.Regions != "" {
|
|
m.Regions = s.Regions
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
func WriteFile(f *File, path string) error {
|
|
data, err := yaml.Marshal(f)
|
|
if err != nil {
|
|
return fmt.Errorf("marshal yaml: %w", err)
|
|
}
|
|
if path == "-" || path == "" {
|
|
_, err = os.Stdout.Write(data)
|
|
return err
|
|
}
|
|
return os.WriteFile(path, data, 0644) //nolint:gosec // config files should be group-readable
|
|
}
|
|
|
|
func LoadFile(path string) (*File, error) {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read %s: %w", path, err)
|
|
}
|
|
var f File
|
|
if err := yaml.Unmarshal(data, &f); err != nil {
|
|
return nil, fmt.Errorf("parse %s: %w", path, err)
|
|
}
|
|
return &f, nil
|
|
}
|