feat/prism
Evan Chen 2021-10-18 23:53:49 +08:00
parent 95e9383138
commit 8432135f3d
7 changed files with 122 additions and 23 deletions

View File

@ -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}

View File

@ -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
View File

@ -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)
}

View File

@ -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
}

1
insomnia.json Normal file

File diff suppressed because one or more lines are too long

21
main.go
View File

@ -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
View File

@ -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))
}