diff --git a/cmd/dkl-local-server/data.go b/cmd/dkl-local-server/data.go index 187688d..c395b59 100644 --- a/cmd/dkl-local-server/data.go +++ b/cmd/dkl-local-server/data.go @@ -12,8 +12,10 @@ var ( configFromDir = flag.String("config-from-dir", "", "Build configuration from this directory") ) -func readConfig() (config *localconfig.Config, err error) { - configFile := filepath.Join(*dataDir, "config.yaml") - - return localconfig.FromFile(configFile) +func configFilePath() string { + return filepath.Join(*dataDir, "config.yaml") +} + +func readConfig() (config *localconfig.Config, err error) { + return localconfig.FromFile(configFilePath()) } diff --git a/cmd/dkl-local-server/http.go b/cmd/dkl-local-server/http.go index 6b94676..11e697e 100644 --- a/cmd/dkl-local-server/http.go +++ b/cmd/dkl-local-server/http.go @@ -3,11 +3,16 @@ package main import ( "encoding/json" "flag" + "io" + "io/ioutil" "log" "net" "net/http" + "os" + "path/filepath" "regexp" "strings" + "time" "novit.nc/direktil/pkg/localconfig" ) @@ -248,3 +253,59 @@ func serveCluster(w http.ResponseWriter, r *http.Request) { http.NotFound(w, r) } } + +func uploadConfig(w http.ResponseWriter, r *http.Request) { + if !authorizeHosts(r) { // FIXME admin token instead + forbidden(w, r) + return + } + + if r.Method != "POST" { + http.NotFound(w, r) + return + } + + out, err := ioutil.TempFile(*dataDir, ".config-upload") + if err != nil { + writeError(w, err) + return + } + + defer os.Remove(out.Name()) + + func() { + defer out.Close() + if _, err = io.Copy(out, r.Body); err != nil { + writeError(w, err) + return + } + }() + + archivesPath := filepath.Join(*dataDir, "archives") + cfgPath := configFilePath() + + err = os.MkdirAll(archivesPath, 0700) + if err != nil { + writeError(w, err) + return + } + + backupPath := filepath.Join(archivesPath, "config."+time.Now().Format(time.RFC3339)+".yaml") + err = os.Rename(cfgPath, backupPath) + if err != nil { + writeError(w, err) + return + } + + err = os.Rename(out.Name(), configFilePath()) + if err != nil { + writeError(w, err) + return + } +} + +func writeError(w http.ResponseWriter, err error) { + log.Print("request failed: ", err) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(http.StatusText(http.StatusInternalServerError))) +} diff --git a/cmd/dkl-local-server/main.go b/cmd/dkl-local-server/main.go index 5b419d6..a2278d1 100644 --- a/cmd/dkl-local-server/main.go +++ b/cmd/dkl-local-server/main.go @@ -36,6 +36,8 @@ func main() { // by default, serve a host resource by its IP http.HandleFunc("/", serveHostByIP) + http.HandleFunc("/configs", uploadConfig) + http.HandleFunc("/hosts", serveHosts) http.HandleFunc("/hosts/", serveHost)