aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--api/api.go29
-rw-r--r--api/docker.go58
-rw-r--r--go.mod29
-rw-r--r--nonsense-time.go1
4 files changed, 116 insertions, 1 deletions
diff --git a/api/api.go b/api/api.go
index c74723d..957651e 100644
--- a/api/api.go
+++ b/api/api.go
@@ -3,9 +3,11 @@ package api
import (
"context"
"encoding/json"
+ "io"
"log/slog"
"net/http"
"os"
+ "strconv"
"time"
)
@@ -40,7 +42,7 @@ func respondOnline(w http.ResponseWriter, status ServerStatus) {
jsonData, err := json.Marshal(status)
if err != nil {
http.Error(w, "Error constructing response", http.StatusInternalServerError)
- Logger.Error("Error marshalling site status data")
+ Logger.Error("Error marshalling site status data", slog.Any("err", err))
return
}
@@ -61,6 +63,31 @@ func VttRedirect(w http.ResponseWriter, req *http.Request) {
http.Redirect(w, req, VTT_URL, http.StatusMovedPermanently)
}
+func VttLogs(w http.ResponseWriter, req *http.Request) {
+ var lines uint = 0
+
+ linesParam := req.URL.Query().Get("lines")
+ if linesParam != "" {
+ lines_64, err := strconv.ParseUint(linesParam, 10, 64)
+ if err != nil {
+ Logger.ErrorContext(req.Context(), "Invalid line count in vtt logs request", slog.Any("err", err))
+ http.Error(w, "Invalid line count in request", http.StatusBadRequest)
+ return
+ }
+
+ lines = uint(lines_64)
+ }
+
+ logReader, err := vttLogs(req.Context(), lines)
+ if err != nil {
+ http.Error(w, "Error occured while getting logs", http.StatusInternalServerError)
+ return
+ }
+ defer logReader.Close()
+
+ io.Copy(w, logReader)
+}
+
func SiteOnline(w http.ResponseWriter, req *http.Request) {
const URL string = "https://dnd.jpappel.xyz"
diff --git a/api/docker.go b/api/docker.go
new file mode 100644
index 0000000..21d5c26
--- /dev/null
+++ b/api/docker.go
@@ -0,0 +1,58 @@
+package api
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "log/slog"
+
+ "github.com/docker/docker/api/types/container"
+ "github.com/docker/docker/client"
+)
+
+const vttContainerId string = "foundry-foundry-1"
+
+func stopVtt(ctx context.Context) error {
+ apiClient, err := client.NewClientWithOpts(client.FromEnv)
+ if err != nil {
+ Logger.ErrorContext(ctx, "Failed to get docker api client", slog.Any("err", err))
+ return err
+ }
+
+ Logger.InfoContext(ctx, "Stopping foundry container")
+ err = apiClient.ContainerStop(ctx, vttContainerId, container.StopOptions{})
+ if err != nil {
+ Logger.ErrorContext(ctx, "Error occured while stopping foundry container", slog.Any("err", err))
+ return err
+ }
+
+ return nil
+}
+
+// Get readcloser for logs
+// If lines is zero, returns all logs.
+func vttLogs(ctx context.Context, lines uint) (io.ReadCloser, error) {
+ apiClient, err := client.NewClientWithOpts(client.FromEnv)
+ if err != nil {
+ Logger.ErrorContext(ctx, "Failed to get docker api client", slog.Any("err", err))
+ return nil, err
+ }
+
+ opts := container.LogsOptions{
+ ShowStdout: true,
+ ShowStderr: true,
+ Timestamps: true,
+ }
+ if lines != 0 {
+ opts.Tail = fmt.Sprint(lines)
+ }
+
+ Logger.DebugContext(ctx, "Getting container logs")
+ r, err := apiClient.ContainerLogs(ctx, vttContainerId, opts)
+ if err != nil {
+ Logger.ErrorContext(ctx, "Failed to get foundry container's logs", slog.Any("err", err))
+ return nil, err
+ }
+
+ return r, nil
+}
diff --git a/go.mod b/go.mod
index 6f84195..d5a8df3 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,32 @@
module nonsense-time
go 1.23.0
+
+require github.com/docker/docker v27.3.1+incompatible
+
+require (
+ github.com/Microsoft/go-winio v0.4.14 // indirect
+ github.com/containerd/log v0.1.0 // indirect
+ github.com/distribution/reference v0.6.0 // indirect
+ github.com/docker/go-connections v0.5.0 // indirect
+ github.com/docker/go-units v0.5.0 // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
+ github.com/go-logr/logr v1.4.2 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/moby/docker-image-spec v1.3.1 // indirect
+ github.com/moby/term v0.5.0 // indirect
+ github.com/morikuni/aec v1.0.0 // indirect
+ github.com/opencontainers/go-digest v1.0.0 // indirect
+ github.com/opencontainers/image-spec v1.1.0 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect
+ go.opentelemetry.io/otel v1.30.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 // indirect
+ go.opentelemetry.io/otel/metric v1.30.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.30.0 // indirect
+ go.opentelemetry.io/otel/trace v1.30.0 // indirect
+ golang.org/x/sys v0.25.0 // indirect
+ golang.org/x/time v0.7.0 // indirect
+ gotest.tools/v3 v3.5.1 // indirect
+)
diff --git a/nonsense-time.go b/nonsense-time.go
index 94c0a30..3ffff11 100644
--- a/nonsense-time.go
+++ b/nonsense-time.go
@@ -70,6 +70,7 @@ func main() {
mux.Handle("GET /site/status", site)
mux.HandleFunc("GET /", dashboard.Index)
mux.HandleFunc("GET /static/", dashboard.StaticHandler)
+ mux.HandleFunc("GET /vtt/logs", api.VttLogs)
logger.Info(fmt.Sprint("Listening on ", addr))
logger.Info(http.ListenAndServe(addr, mux).Error())