Code was restructurised again. Moved out back to root dir.
Ditched JSON configuration file. Replaced with simple key = value format. Added indented_output option to format output with indent.
This commit is contained in:
parent
b1c3066d4c
commit
c7fe073623
108
confguration.go
Normal file
108
confguration.go
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Configuration holds a list of process names to be tracked and a listen address.
|
||||||
|
type Configuration struct {
|
||||||
|
ListenAddress string
|
||||||
|
IndentedOutput bool
|
||||||
|
Processes []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadConfiguration loads configuration from a file.
|
||||||
|
func LoadConfiguration(path string) (conf *Configuration, err error) {
|
||||||
|
conf = &Configuration{}
|
||||||
|
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
s := bufio.NewScanner(file)
|
||||||
|
s.Split(bufio.ScanLines)
|
||||||
|
|
||||||
|
for s.Scan() {
|
||||||
|
kv := strings.Split(s.Text(), " = ")
|
||||||
|
switch kv[0] {
|
||||||
|
case "listen_address":
|
||||||
|
conf.ListenAddress = kv[1]
|
||||||
|
case "indented_output":
|
||||||
|
v, err := strconv.ParseBool(kv[1])
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("WARN: could not parse \"indented_output\", valid values are true or false. Defaulted to false.\n")
|
||||||
|
}
|
||||||
|
conf.IndentedOutput = v
|
||||||
|
case "processes":
|
||||||
|
if kv[1] != "" {
|
||||||
|
conf.Processes = strings.Split(kv[1], " ")
|
||||||
|
} else {
|
||||||
|
log.Printf("WARN: \"processes\" list is empty.\n")
|
||||||
|
conf.Processes = []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StoreConfiguration writes Configuration into a file.
|
||||||
|
func (conf *Configuration) StoreConfiguration(path string) (err error) {
|
||||||
|
var config strings.Builder
|
||||||
|
|
||||||
|
config.WriteString("listen_address = ")
|
||||||
|
config.WriteString(conf.ListenAddress)
|
||||||
|
config.WriteByte('\n')
|
||||||
|
config.WriteString("indented_output = ")
|
||||||
|
config.WriteString(strconv.FormatBool(conf.IndentedOutput))
|
||||||
|
config.WriteByte('\n')
|
||||||
|
config.WriteString("processes = ")
|
||||||
|
config.WriteString(strings.Join(conf.Processes, " "))
|
||||||
|
|
||||||
|
if err := ioutil.WriteFile(path, []byte(config.String()), 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddProcessToList appends a new given process into a configuration file.
|
||||||
|
func (conf *Configuration) AddProcessToList(process string, configPath string) error {
|
||||||
|
for _, v := range conf.Processes {
|
||||||
|
if v == process {
|
||||||
|
return ErrIsOnList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.Processes = append(conf.Processes, process)
|
||||||
|
if err := conf.StoreConfiguration(configPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveProcessFromList removes a given process from a configuration file.
|
||||||
|
func (conf *Configuration) RemoveProcessFromList(process string, configPath string) error {
|
||||||
|
for k, v := range conf.Processes {
|
||||||
|
if v == process {
|
||||||
|
newlist := make([]string, len(conf.Processes)-1)
|
||||||
|
newlist = append(conf.Processes[:k], conf.Processes[k+1:]...)
|
||||||
|
conf.Processes = newlist
|
||||||
|
if err := conf.StoreConfiguration(configPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrNotFound
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package prog
|
package main
|
||||||
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
10
main.go
10
main.go
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
. "httpprocwatchd/prog"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -36,8 +35,9 @@ func main() {
|
|||||||
|
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
|
|
||||||
flag.StringVar(&oConfigPath, "config", "config.json", "path to configuration file")
|
flag.StringVar(&oConfigPath, "config", "config.conf", "path to configuration file")
|
||||||
flag.StringVar(&oConfigPath, "c", "config.json", "path to configuration file (shorthand)")
|
flag.StringVar(&oConfigPath, "c", "config.conf", "path to configuration file (shorthand)")
|
||||||
|
|
||||||
flag.BoolVar(&oShowVersion, "version", false, "show version")
|
flag.BoolVar(&oShowVersion, "version", false, "show version")
|
||||||
flag.BoolVar(&oShowVersion, "v", false, "show version (shorthand)")
|
flag.BoolVar(&oShowVersion, "v", false, "show version (shorthand)")
|
||||||
|
|
||||||
@ -68,14 +68,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if oAddProcess != "" {
|
if oAddProcess != "" {
|
||||||
err := AddProcessToList(oAddProcess, conf, oConfigPath)
|
err := conf.AddProcessToList(oAddProcess, oConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Cannot add process: %s\n", err)
|
log.Fatalf("Cannot add process: %s\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if oRemoveProcess != "" {
|
if oRemoveProcess != "" {
|
||||||
err := RemoveProcessFromList(oRemoveProcess, conf, oConfigPath)
|
err := conf.RemoveProcessFromList(oRemoveProcess, oConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Cannot remove process: %s\n", err)
|
log.Fatalf("Cannot remove process: %s\n", err)
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package prog
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
@ -1,77 +0,0 @@
|
|||||||
package prog
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Configuration holds a list of process names to be tracked and a listen address.
|
|
||||||
type Configuration struct {
|
|
||||||
ListenAddress string `json:"listen_address"`
|
|
||||||
Processes []string `json:"processes"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadConfiguration loads configuration from a JSON file.
|
|
||||||
func LoadConfiguration(path string) (conf *Configuration, err error) {
|
|
||||||
conf = &Configuration{}
|
|
||||||
|
|
||||||
file, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(file, conf); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StoreConfiguration writes Configuration into a JSON file.
|
|
||||||
func StoreConfiguration(path string, conf *Configuration) (err error) {
|
|
||||||
config, err := json.Marshal(*conf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ioutil.WriteFile(path, config, 0644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddProcessToList appends a new given process into a configuration file.
|
|
||||||
func AddProcessToList(process string, conf *Configuration, configPath string) error {
|
|
||||||
for _, v := range conf.Processes {
|
|
||||||
if v == process {
|
|
||||||
return ErrIsOnList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conf.Processes = append(conf.Processes, process)
|
|
||||||
if err := StoreConfiguration(configPath, conf); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveProcessFromList removes a given process from a configuration file.
|
|
||||||
func RemoveProcessFromList(process string, conf *Configuration, configPath string) error {
|
|
||||||
for k, v := range conf.Processes {
|
|
||||||
if v == process {
|
|
||||||
newlist := make([]string, len(conf.Processes)-1)
|
|
||||||
newlist = append(conf.Processes[:k], conf.Processes[k+1:]...)
|
|
||||||
conf.Processes = newlist
|
|
||||||
if err := StoreConfiguration(configPath, conf); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrNotFound
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package prog
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
func CreateAndStartHTTPServer(conf *Configuration) *http.Server {
|
func CreateAndStartHTTPServer(conf *Configuration) *http.Server {
|
||||||
router := http.NewServeMux()
|
router := http.NewServeMux()
|
||||||
router.HandleFunc("/processes", AreProcessesUp(&conf.Processes))
|
router.HandleFunc("/processes", AreProcessesUp(&conf.Processes, conf.IndentedOutput))
|
||||||
|
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
Addr: conf.ListenAddress,
|
Addr: conf.ListenAddress,
|
||||||
@ -42,7 +42,7 @@ func ShutdownHTTPServer(srv *http.Server) {
|
|||||||
|
|
||||||
// AreProcessesUp handles a GET /processes request and sends back status of given
|
// AreProcessesUp handles a GET /processes request and sends back status of given
|
||||||
// processes.
|
// processes.
|
||||||
func AreProcessesUp(processes *[]string) func(http.ResponseWriter, *http.Request) {
|
func AreProcessesUp(processes *[]string, indented bool) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == http.MethodGet {
|
if r.Method == http.MethodGet {
|
||||||
proclist := NewProcessList()
|
proclist := NewProcessList()
|
||||||
@ -55,12 +55,16 @@ func AreProcessesUp(processes *[]string) func(http.ResponseWriter, *http.Request
|
|||||||
if hdr := r.Header.Get("Accept"); hdr == "application/xml" {
|
if hdr := r.Header.Get("Accept"); hdr == "application/xml" {
|
||||||
w.Header().Add("Content-Type", "application/xml")
|
w.Header().Add("Content-Type", "application/xml")
|
||||||
enc := xml.NewEncoder(w)
|
enc := xml.NewEncoder(w)
|
||||||
|
if indented {
|
||||||
enc.Indent("", "\t")
|
enc.Indent("", "\t")
|
||||||
|
}
|
||||||
enc.Encode(proclist)
|
enc.Encode(proclist)
|
||||||
} else {
|
} else {
|
||||||
w.Header().Add("Content-Type", "application/json")
|
w.Header().Add("Content-Type", "application/json")
|
||||||
enc := json.NewEncoder(w)
|
enc := json.NewEncoder(w)
|
||||||
|
if indented {
|
||||||
enc.SetIndent("", "\t")
|
enc.SetIndent("", "\t")
|
||||||
|
}
|
||||||
enc.Encode(proclist)
|
enc.Encode(proclist)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
@ -1,9 +1,10 @@
|
|||||||
package prog
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetProcessPIDs(name string) ([]int, error) {
|
func GetProcessPIDs(name string) ([]int, error) {
|
||||||
@ -22,7 +23,7 @@ func GetProcessPIDs(name string) ([]int, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if name == string(f[:len(f)-1]) {
|
if strings.Contains(string(f[:len(f)-1]), name) {
|
||||||
pids = append(pids, pid)
|
pids = append(pids, pid)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user