parent
95e9383138
commit
8432135f3d
6
Makefile
6
Makefile
|
@ -8,6 +8,12 @@ LDFLAGS=-ldflags "-X main.Version=${VERSION} -X main.Build=${BUILD} -w"
|
|||
|
||||
default: build
|
||||
|
||||
clean:
|
||||
rm -rf dist
|
||||
|
||||
run: build
|
||||
$(shell cd dist; ./${PROJ} -log configui.log)
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
go build ${LDFLAGS} -o dist/${PROJ}
|
35
README.md
35
README.md
|
@ -2,6 +2,41 @@
|
|||
|
||||
a web app to edit and action on update
|
||||
|
||||
```
|
||||
Usage: configui [options]
|
||||
-bind string
|
||||
address to bind (default "localhost:8000")
|
||||
-c string
|
||||
cmd to apply
|
||||
-f string
|
||||
path to config file
|
||||
-log string
|
||||
log to file
|
||||
-n string
|
||||
alias of file
|
||||
-p string
|
||||
path to file, precedence over config
|
||||
-v show version
|
||||
```
|
||||
|
||||
## Config
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"path": "configui.log",
|
||||
"ro": true
|
||||
},
|
||||
{
|
||||
"path": "etc/test.ini",
|
||||
"name": "test",
|
||||
"action": "myip local -P"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
`configui -f PATH/TO/CONFIG`
|
||||
|
||||
## Api
|
||||
|
||||
### Files
|
||||
|
|
59
api.go
59
api.go
|
@ -11,8 +11,7 @@ import (
|
|||
func ListFiles(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := json.Marshal(files)
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
w.Write(data)
|
||||
|
@ -22,14 +21,12 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
|
|||
name := r.URL.Query().Get("name")
|
||||
file, ok := files[name]
|
||||
if name == "" || !ok {
|
||||
w.WriteHeader(404)
|
||||
w.Write([]byte("file not found"))
|
||||
HttpWriter(w, 404, "file not found")
|
||||
return
|
||||
}
|
||||
data, err := file.Read()
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
response, err := json.Marshal(map[string]string{
|
||||
|
@ -39,8 +36,7 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
|
|||
"data": string(data),
|
||||
})
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
@ -51,25 +47,21 @@ func PostFile(w http.ResponseWriter, r *http.Request) {
|
|||
data, err := ioutil.ReadAll(r.Body)
|
||||
r.Body.Close()
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
f := configui.File{}
|
||||
if err := json.Unmarshal(data, &f); err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
file, ok := files[f.Alias]
|
||||
if !ok {
|
||||
w.WriteHeader(404)
|
||||
w.Write([]byte("file not found"))
|
||||
HttpWriter(w, 404, "file not found")
|
||||
return
|
||||
}
|
||||
if err := file.Write([]byte(f.Data)); err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
w.Write([]byte("ok"))
|
||||
|
@ -79,14 +71,12 @@ func Apply(w http.ResponseWriter, r *http.Request) {
|
|||
name := r.URL.Query().Get("name")
|
||||
file, ok := files[name]
|
||||
if name == "" || !ok {
|
||||
w.WriteHeader(404)
|
||||
w.Write([]byte("file not found"))
|
||||
HttpWriter(w, 404, "file not found")
|
||||
return
|
||||
}
|
||||
result, err := file.Do()
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
w.Write([]byte(result))
|
||||
|
@ -100,3 +90,32 @@ func Download(w http.ResponseWriter, r *http.Request) {
|
|||
w.Header().Set("Content-Disposition", `attachment; filename="export.tar.gz"`)
|
||||
bundle(w, fs, false)
|
||||
}
|
||||
|
||||
func LoadConfig(w http.ResponseWriter, r *http.Request) {
|
||||
data, err := ioutil.ReadAll(r.Body)
|
||||
r.Body.Close()
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
ftmp, err := configui.ReadConfig(string(data))
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
files = configui.GetFileMap(ftmp)
|
||||
w.Write([]byte("ok"))
|
||||
}
|
||||
|
||||
func GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config := []configui.File{}
|
||||
for _, f := range files {
|
||||
config = append(config, *f)
|
||||
}
|
||||
data, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
HttpWriter(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
w.Write(data)
|
||||
}
|
||||
|
|
|
@ -70,6 +70,11 @@ func ReadConfig(confstr string) ([]File, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range conf {
|
||||
if conf[i].Alias == "" {
|
||||
conf[i].Alias = conf[i].Path
|
||||
}
|
||||
}
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
21
main.go
21
main.go
|
@ -3,7 +3,6 @@ package main
|
|||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"html/template"
|
||||
|
@ -28,8 +27,11 @@ var (
|
|||
|
||||
flagBind string
|
||||
flagLogFile string
|
||||
flagVer bool
|
||||
)
|
||||
|
||||
var Version = "0.0.0"
|
||||
var Build = "alpha"
|
||||
var files = map[string]*configui.File{}
|
||||
|
||||
func init() {
|
||||
|
@ -41,6 +43,7 @@ func init() {
|
|||
flag.StringVar(&flagAction, "c", "", "cmd to apply")
|
||||
flag.StringVar(&flagLogFile, "log", "", "log to file")
|
||||
flag.StringVar(&flagBind, "bind", "localhost:8000", "address to bind")
|
||||
flag.BoolVar(&flagVer, "v", false, "show version")
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "Usage: configui [options]\n")
|
||||
flag.PrintDefaults()
|
||||
|
@ -50,6 +53,10 @@ func init() {
|
|||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if flagVer {
|
||||
fmt.Printf("%v - %v\n", Version, Build)
|
||||
}
|
||||
|
||||
// setup logging
|
||||
if flagLogFile != "" {
|
||||
f, err := os.OpenFile(flagLogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||
|
@ -72,7 +79,7 @@ func main() {
|
|||
Action: flagAction,
|
||||
}
|
||||
} else if flagConfigPath == "" {
|
||||
log.Fatalln(errors.New("no config found"))
|
||||
log.Println("no config found")
|
||||
} else {
|
||||
conf, err := os.ReadFile(flagConfigPath)
|
||||
if err != nil {
|
||||
|
@ -87,7 +94,15 @@ func main() {
|
|||
|
||||
// setup routes
|
||||
mux := http.NewServeMux()
|
||||
// mux.
|
||||
mux.HandleFunc("/api/conf", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "GET" {
|
||||
GetConfig(w, r)
|
||||
} else if r.Method == "POST" {
|
||||
LoadConfig(w, r)
|
||||
} else {
|
||||
w.WriteHeader(404)
|
||||
}
|
||||
})
|
||||
mux.HandleFunc("/api/files", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "GET" {
|
||||
ListFiles(w, r)
|
||||
|
|
18
util.go
18
util.go
|
@ -7,11 +7,19 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func LogMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
log.Println("panic", r)
|
||||
w.WriteHeader(500)
|
||||
}
|
||||
}()
|
||||
next.ServeHTTP(w, r)
|
||||
log.Printf("%s %s %s %s\n", r.RemoteAddr, r.Method, r.URL, r.Header.Get("User-Agent"))
|
||||
},
|
||||
|
@ -47,6 +55,11 @@ func bundle(buf io.Writer, paths []string, flat bool) error {
|
|||
// not be preserved
|
||||
// https://golang.org/src/archive/tar/common.go?#L626
|
||||
if !flat {
|
||||
if !strings.HasPrefix(file, "/") {
|
||||
file = "configui/" + file
|
||||
} else {
|
||||
file = "configui" + file
|
||||
}
|
||||
header.Name = file
|
||||
}
|
||||
|
||||
|
@ -70,3 +83,8 @@ func bundle(buf io.Writer, paths []string, flat bool) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func HttpWriter(w http.ResponseWriter, status int, errStr string) {
|
||||
w.WriteHeader(status)
|
||||
w.Write([]byte(errStr))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue