expose PATCH /config
parent
af42db6803
commit
c663b1a12c
|
|
@ -6,27 +6,32 @@ import (
|
||||||
patch "github.com/evanphx/json-patch/v5"
|
patch "github.com/evanphx/json-patch/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type (
|
||||||
Feedback struct {
|
config struct {
|
||||||
|
Feedback configFeedback
|
||||||
|
Users map[string]configUser
|
||||||
|
Players []configPlayer
|
||||||
|
Quiet bool
|
||||||
|
}
|
||||||
|
|
||||||
|
configFeedback struct {
|
||||||
Addr string
|
Addr string
|
||||||
TTSURL string
|
TTSURL string
|
||||||
}
|
}
|
||||||
Users map[string]struct {
|
|
||||||
|
configUser struct {
|
||||||
Player int
|
Player int
|
||||||
Message string
|
Message string
|
||||||
}
|
}
|
||||||
Players []struct {
|
|
||||||
|
configPlayer struct {
|
||||||
Transformation transformation
|
Transformation transformation
|
||||||
}
|
}
|
||||||
Quiet bool
|
)
|
||||||
}
|
|
||||||
|
|
||||||
func (cfg config) WithJSONPatch(v interface{}) config {
|
func (cfg config) WithPatch(v interface{}) config {
|
||||||
originalData, _ := json.Marshal(cfg)
|
originalData, _ := json.Marshal(cfg)
|
||||||
patchData, err := json.Marshal(v)
|
patchData, _ := json.Marshal(v)
|
||||||
if err != nil {
|
|
||||||
return cfg
|
|
||||||
}
|
|
||||||
patcher, err := patch.DecodePatch(patchData)
|
patcher, err := patch.DecodePatch(patchData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cfg
|
return cfg
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ func TestConfigPatch(t *testing.T) {
|
||||||
for name, d := range cases {
|
for name, d := range cases {
|
||||||
c := d
|
c := d
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
got := c.cfg.WithJSONPatch(c.patch)
|
got := c.cfg.WithPatch(c.patch)
|
||||||
if fmt.Sprintf("%+v", got) != fmt.Sprintf("%+v", c.want) {
|
if fmt.Sprintf("%+v", got) != fmt.Sprintf("%+v", c.want) {
|
||||||
t.Errorf("(%+v).Patch(%+v) want %+v, got %+v", c.cfg, c.patch, c.want, got)
|
t.Errorf("(%+v).Patch(%+v) want %+v, got %+v", c.cfg, c.patch, c.want, got)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
package v01
|
package v01
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"mayhem-party/src/device/input/wrap"
|
"mayhem-party/src/device/input/wrap"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (v01 *V01) listen() {
|
func (v01 *V01) listen() {
|
||||||
|
|
@ -55,6 +59,8 @@ func (v01 *V01) serveHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
v01.getUserFeedback(w, r)
|
v01.getUserFeedback(w, r)
|
||||||
case "/broadcast":
|
case "/broadcast":
|
||||||
v01.putBroadcast(w, r)
|
v01.putBroadcast(w, r)
|
||||||
|
case "/config":
|
||||||
|
v01.patchConfig(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,6 +79,21 @@ func (v01 *V01) putBroadcast(w http.ResponseWriter, r *http.Request) {
|
||||||
v01.cfg.Users["broadcast"] = v
|
v01.cfg.Users["broadcast"] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v01 *V01) patchConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
|
b, _ := io.ReadAll(r.Body)
|
||||||
|
var v []interface{}
|
||||||
|
if err := json.Unmarshal(b, &v); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v01.cfg = v01.cfg.WithPatch(v)
|
||||||
|
if b, err := yaml.Marshal(v01.cfg); err == nil && FlagParseV01Config != "" {
|
||||||
|
if err := os.WriteFile(FlagParseV01Config, b, os.ModePerm); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (v01 *V01) globalQueries(r *http.Request) {
|
func (v01 *V01) globalQueries(r *http.Request) {
|
||||||
v01.globalQuerySay(r)
|
v01.globalQuerySay(r)
|
||||||
v01.globalQueryRefresh(r)
|
v01.globalQueryRefresh(r)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package v01
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPatchConfig(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
p := path.Join(dir, t.Name()+".yaml")
|
||||||
|
cases := map[string]struct {
|
||||||
|
was config
|
||||||
|
patch string
|
||||||
|
want config
|
||||||
|
}{
|
||||||
|
"replace entire doc": {
|
||||||
|
was: config{
|
||||||
|
Feedback: configFeedback{Addr: "a", TTSURL: "a"},
|
||||||
|
Users: map[string]configUser{"a": configUser{Player: 1, Message: "a"}},
|
||||||
|
Players: []configPlayer{configPlayer{Transformation: transformation{"a": "a"}}},
|
||||||
|
Quiet: true,
|
||||||
|
},
|
||||||
|
patch: `[{"op": "replace", "path": "", "value": {
|
||||||
|
"Feedback": {"Addr": "b", "TTSURL": "b"},
|
||||||
|
"Users": {"b": {"Player": 2, "Message": "b"}},
|
||||||
|
"Players": [{"Transformation": {"b": "b"}}],
|
||||||
|
"Quiet": false
|
||||||
|
}}]`,
|
||||||
|
want: config{
|
||||||
|
Feedback: configFeedback{Addr: "b", TTSURL: "b"},
|
||||||
|
Users: map[string]configUser{"b": configUser{Player: 2, Message: "b"}},
|
||||||
|
Players: []configPlayer{configPlayer{Transformation: transformation{"b": "b"}}},
|
||||||
|
Quiet: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, d := range cases {
|
||||||
|
c := d
|
||||||
|
for _, usesdisk := range []bool{false, true} {
|
||||||
|
t.Run(fmt.Sprintf("%s disk=%v", name, usesdisk), func(t *testing.T) {
|
||||||
|
b, _ := yaml.Marshal(c.was)
|
||||||
|
os.WriteFile(p, b, os.ModePerm)
|
||||||
|
FlagParseV01Config = ""
|
||||||
|
if usesdisk {
|
||||||
|
FlagParseV01Config = p
|
||||||
|
}
|
||||||
|
v01 := &V01{cfg: c.was}
|
||||||
|
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
r := httptest.NewRequest(http.MethodPatch, "/config", strings.NewReader(c.patch))
|
||||||
|
v01.patchConfig(w, r)
|
||||||
|
if fmt.Sprintf("%+v", c.want) != fmt.Sprintf("%+v", v01.cfg) {
|
||||||
|
t.Errorf("want \n\t%+v, got \n\t%+v", c.want, v01.cfg)
|
||||||
|
}
|
||||||
|
if usesdisk {
|
||||||
|
b, _ := os.ReadFile(p)
|
||||||
|
var got config
|
||||||
|
yaml.Unmarshal(b, &got)
|
||||||
|
if fmt.Sprintf("%+v", c.want) != fmt.Sprintf("%+v", v01.cfg) {
|
||||||
|
t.Errorf("want \n\t%+v, got \n\t%+v", c.want, v01.cfg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue