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 default: build
clean:
rm -rf dist
run: build
$(shell cd dist; ./${PROJ} -log configui.log)
.PHONY: build .PHONY: build
build: build:
go build ${LDFLAGS} -o dist/${PROJ} go build ${LDFLAGS} -o dist/${PROJ}

View File

@ -2,6 +2,41 @@
a web app to edit and action on update 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 ## Api
### Files ### Files

59
api.go
View File

@ -11,8 +11,7 @@ import (
func ListFiles(w http.ResponseWriter, r *http.Request) { func ListFiles(w http.ResponseWriter, r *http.Request) {
data, err := json.Marshal(files) data, err := json.Marshal(files)
if err != nil { if err != nil {
w.WriteHeader(500) HttpWriter(w, 500, err.Error())
w.Write([]byte(err.Error()))
return return
} }
w.Write(data) w.Write(data)
@ -22,14 +21,12 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name") name := r.URL.Query().Get("name")
file, ok := files[name] file, ok := files[name]
if name == "" || !ok { if name == "" || !ok {
w.WriteHeader(404) HttpWriter(w, 404, "file not found")
w.Write([]byte("file not found"))
return return
} }
data, err := file.Read() data, err := file.Read()
if err != nil { if err != nil {
w.WriteHeader(500) HttpWriter(w, 500, err.Error())
w.Write([]byte(err.Error()))
return return
} }
response, err := json.Marshal(map[string]string{ response, err := json.Marshal(map[string]string{
@ -39,8 +36,7 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
"data": string(data), "data": string(data),
}) })
if err != nil { if err != nil {
w.WriteHeader(500) HttpWriter(w, 500, err.Error())
w.Write([]byte(err.Error()))
return return
} }
w.Header().Set("Content-Type", "application/json") 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) data, err := ioutil.ReadAll(r.Body)
r.Body.Close() r.Body.Close()
if err != nil { if err != nil {
w.WriteHeader(500) HttpWriter(w, 500, err.Error())
w.Write([]byte(err.Error()))
return return
} }
f := configui.File{} f := configui.File{}
if err := json.Unmarshal(data, &f); err != nil { if err := json.Unmarshal(data, &f); err != nil {
w.WriteHeader(500) HttpWriter(w, 500, err.Error())
w.Write([]byte(err.Error()))
return return
} }
file, ok := files[f.Alias] file, ok := files[f.Alias]
if !ok { if !ok {
w.WriteHeader(404) HttpWriter(w, 404, "file not found")
w.Write([]byte("file not found"))
return return
} }
if err := file.Write([]byte(f.Data)); err != nil { if err := file.Write([]byte(f.Data)); err != nil {
w.WriteHeader(500) HttpWriter(w, 500, err.Error())
w.Write([]byte(err.Error()))
return return
} }
w.Write([]byte("ok")) w.Write([]byte("ok"))
@ -79,14 +71,12 @@ func Apply(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name") name := r.URL.Query().Get("name")
file, ok := files[name] file, ok := files[name]
if name == "" || !ok { if name == "" || !ok {
w.WriteHeader(404) HttpWriter(w, 404, "file not found")
w.Write([]byte("file not found"))
return return
} }
result, err := file.Do() result, err := file.Do()
if err != nil { if err != nil {
w.WriteHeader(500) HttpWriter(w, 500, err.Error())
w.Write([]byte(err.Error()))
return return
} }
w.Write([]byte(result)) 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"`) w.Header().Set("Content-Disposition", `attachment; filename="export.tar.gz"`)
bundle(w, fs, false) 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 { if err != nil {
return nil, err return nil, err
} }
for i := range conf {
if conf[i].Alias == "" {
conf[i].Alias = conf[i].Path
}
}
return conf, nil 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 ( import (
"bytes" "bytes"
"embed" "embed"
"errors"
"flag" "flag"
"fmt" "fmt"
"html/template" "html/template"
@ -28,8 +27,11 @@ var (
flagBind string flagBind string
flagLogFile string flagLogFile string
flagVer bool
) )
var Version = "0.0.0"
var Build = "alpha"
var files = map[string]*configui.File{} var files = map[string]*configui.File{}
func init() { func init() {
@ -41,6 +43,7 @@ func init() {
flag.StringVar(&flagAction, "c", "", "cmd to apply") flag.StringVar(&flagAction, "c", "", "cmd to apply")
flag.StringVar(&flagLogFile, "log", "", "log to file") flag.StringVar(&flagLogFile, "log", "", "log to file")
flag.StringVar(&flagBind, "bind", "localhost:8000", "address to bind") flag.StringVar(&flagBind, "bind", "localhost:8000", "address to bind")
flag.BoolVar(&flagVer, "v", false, "show version")
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: configui [options]\n") fmt.Fprintf(os.Stderr, "Usage: configui [options]\n")
flag.PrintDefaults() flag.PrintDefaults()
@ -50,6 +53,10 @@ func init() {
func main() { func main() {
flag.Parse() flag.Parse()
if flagVer {
fmt.Printf("%v - %v\n", Version, Build)
}
// setup logging // setup logging
if flagLogFile != "" { if flagLogFile != "" {
f, err := os.OpenFile(flagLogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) f, err := os.OpenFile(flagLogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
@ -72,7 +79,7 @@ func main() {
Action: flagAction, Action: flagAction,
} }
} else if flagConfigPath == "" { } else if flagConfigPath == "" {
log.Fatalln(errors.New("no config found")) log.Println("no config found")
} else { } else {
conf, err := os.ReadFile(flagConfigPath) conf, err := os.ReadFile(flagConfigPath)
if err != nil { if err != nil {
@ -87,7 +94,15 @@ func main() {
// setup routes // setup routes
mux := http.NewServeMux() 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) { mux.HandleFunc("/api/files", func(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" { if r.Method == "GET" {
ListFiles(w, r) ListFiles(w, r)

18
util.go
View File

@ -7,11 +7,19 @@ import (
"log" "log"
"net/http" "net/http"
"os" "os"
"strings"
) )
func LogMiddleware(next http.Handler) http.Handler { func LogMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc( return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) { 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) next.ServeHTTP(w, r)
log.Printf("%s %s %s %s\n", r.RemoteAddr, r.Method, r.URL, r.Header.Get("User-Agent")) 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 // not be preserved
// https://golang.org/src/archive/tar/common.go?#L626 // https://golang.org/src/archive/tar/common.go?#L626
if !flat { if !flat {
if !strings.HasPrefix(file, "/") {
file = "configui/" + file
} else {
file = "configui" + file
}
header.Name = file header.Name = file
} }
@ -70,3 +83,8 @@ func bundle(buf io.Writer, paths []string, flat bool) error {
return nil return nil
} }
func HttpWriter(w http.ResponseWriter, status int, errStr string) {
w.WriteHeader(status)
w.Write([]byte(errStr))
}