diff --git a/cmd/keystored/main.go b/cmd/keystored/main.go index 4cdb544956088eda8bdcc0f68240596a9f9880e0..5fe0b892bdaa957f62957c4f04e4e0f790b459e5 100644 --- a/cmd/keystored/main.go +++ b/cmd/keystored/main.go @@ -28,6 +28,7 @@ var ( // server config in a single object for YAML deserialization. type Config struct { server.Config `yaml:",inline"` + StateFile string `yaml:"state_file"` ServerConfig *serverutil.ServerConfig `yaml:"http_server"` } @@ -45,6 +46,39 @@ func loadConfig() (*Config, error) { return &config, nil } +func loadState(ks *server.KeyStore, path string) error { + f, err := os.Open(path) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + defer f.Close() + + log.Printf("loading state from %s", path) + if err := ks.Load(f); err != nil { + return err + } + + if err := os.Remove(path); err != nil { + // Non-fatal error. + log.Printf("error removing state file: %v", err) + } + return nil +} + +func dumpState(ks *server.KeyStore, path string) error { + f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return err + } + defer f.Close() + + log.Printf("dumping state to %s", path) + return ks.Dump(f) +} + func main() { log.SetFlags(0) flag.Parse() @@ -60,9 +94,21 @@ func main() { } prometheus.MustRegister(server.NewKeystoreCollector(ks)) + if config.StateFile != "" { + if err := loadState(ks, config.StateFile); err != nil { + log.Printf("error loading state: %v", err) + } + } + srv := server.NewServer(ks) if err := serverutil.Serve(srv, config.ServerConfig, *addr); err != nil { log.Fatal(err) } + + if config.StateFile != "" { + if err := dumpState(ks, config.StateFile); err != nil { + log.Fatalf("error dumping state: %v", err) + } + } }