summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/tfstated/get.go35
-rw-r--r--cmd/tfstated/main.go21
-rw-r--r--cmd/tfstated/post.go32
-rw-r--r--cmd/tfstated/routes.go13
4 files changed, 99 insertions, 2 deletions
diff --git a/cmd/tfstated/get.go b/cmd/tfstated/get.go
new file mode 100644
index 0000000..6de78a5
--- /dev/null
+++ b/cmd/tfstated/get.go
@@ -0,0 +1,35 @@
+package main
+
+import (
+ "database/sql"
+ "errors"
+ "fmt"
+ "net/http"
+
+ "git.adyxax.org/adyxax/tfstated/pkg/database"
+)
+
+func handleGet(db *database.DB) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Cache-Control", "no-store, no-cache")
+ w.Header().Set("Content-Type", "application/json")
+
+ if r.URL.Path == "/" {
+ w.WriteHeader(http.StatusBadRequest)
+ _, _ = w.Write([]byte("{\"msg\": \"No state path provided, cannot GET /\"}"))
+ return
+ }
+
+ if data, err := db.GetState(r.URL.Path); err != nil {
+ if errors.Is(err, sql.ErrNoRows) {
+ w.WriteHeader(http.StatusNotFound)
+ } else {
+ w.WriteHeader(http.StatusInternalServerError)
+ }
+ _, _ = w.Write([]byte(fmt.Sprintf("{\"msg\": \"%+v\"}", err)))
+ } else {
+ w.WriteHeader(http.StatusOK)
+ _, _ = w.Write(data)
+ }
+ })
+}
diff --git a/cmd/tfstated/main.go b/cmd/tfstated/main.go
index e0b33a5..61248bc 100644
--- a/cmd/tfstated/main.go
+++ b/cmd/tfstated/main.go
@@ -12,6 +12,8 @@ import (
"os/signal"
"sync"
"time"
+
+ "git.adyxax.org/adyxax/tfstated/pkg/database"
)
type Config struct {
@@ -22,6 +24,7 @@ type Config struct {
func run(
ctx context.Context,
config *Config,
+ db *database.DB,
args []string,
getenv func(string) string,
stdin io.Reader,
@@ -30,10 +33,20 @@ func run(
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
defer cancel()
+ dataEncryptionKey := getenv("DATA_ENCRYPTION_KEY")
+ if dataEncryptionKey == "" {
+ return fmt.Errorf("the DATA_ENCRYPTION_KEY environment variable is not set")
+ }
+ if err := db.SetDataEncryptionKey(dataEncryptionKey); err != nil {
+ return err
+ }
+
mux := http.NewServeMux()
addRoutes(
mux,
+ db,
)
+
httpServer := &http.Server{
Addr: net.JoinHostPort(config.Host, config.Port),
Handler: mux,
@@ -79,9 +92,17 @@ func main() {
Port: "8080",
}
+ db, err := database.NewDB(ctx, "./tfstate.db?_txlock=immediate")
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "database init error: %+v\n", err)
+ os.Exit(1)
+ }
+ defer db.Close()
+
if err := run(
ctx,
&config,
+ db,
os.Args,
os.Getenv,
os.Stdin,
diff --git a/cmd/tfstated/post.go b/cmd/tfstated/post.go
new file mode 100644
index 0000000..e47f5ad
--- /dev/null
+++ b/cmd/tfstated/post.go
@@ -0,0 +1,32 @@
+package main
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+
+ "git.adyxax.org/adyxax/tfstated/pkg/database"
+)
+
+func handlePost(db *database.DB) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ if r.URL.Path == "/" {
+ w.WriteHeader(http.StatusBadRequest)
+ _, _ = w.Write([]byte("{\"msg\": \"No state path provided, cannot POST /\"}"))
+ return
+ }
+ data, err := io.ReadAll(r.Body)
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ _, _ = w.Write([]byte(fmt.Sprintf("{\"msg\": \"failed to read request body: %+v\"}", err)))
+ return
+ }
+ if err := db.SetState(r.URL.Path, data); err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ _, _ = w.Write([]byte(fmt.Sprintf("{\"msg\": \"%+v\"}", err)))
+ } else {
+ w.WriteHeader(http.StatusOK)
+ }
+ })
+}
diff --git a/cmd/tfstated/routes.go b/cmd/tfstated/routes.go
index f583fc7..32ab111 100644
--- a/cmd/tfstated/routes.go
+++ b/cmd/tfstated/routes.go
@@ -1,7 +1,16 @@
package main
-import "net/http"
+import (
+ "net/http"
-func addRoutes(mux *http.ServeMux) {
+ "git.adyxax.org/adyxax/tfstated/pkg/database"
+)
+
+func addRoutes(
+ mux *http.ServeMux,
+ db *database.DB,
+) {
mux.Handle("GET /healthz", handleHealthz())
+ mux.Handle("GET /", handleGet(db))
+ mux.Handle("POST /", handlePost(db))
}