package api import ( "context" "fmt" "io" "log/slog" "regexp" "time" "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" ) const vttContainerId string = "foundry-foundry-1" // Strip ansi control characters from source // // The source reader is automatically closed when stripper reader is type ansiStripper struct { regex regexp.Regexp source io.ReadCloser } func NewAnsiStripper(source io.ReadCloser) *ansiStripper { striper := new(ansiStripper) striper.regex = *regexp.MustCompile(`\x1b[[0-9;]*m`) striper.source = source return striper } func (rc ansiStripper) Read(p []byte) (int, error) { n, err := rc.source.Read(p) if err != io.EOF && err != nil { return n, err } stripped := rc.regex.ReplaceAll(p[:n], []byte("")) n = copy(p, stripped) return n, err } func (rc ansiStripper) Close() error { return rc.source.Close() } func stopVtt(ctx context.Context) error { apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { Logger.ErrorContext(ctx, "Failed to get docker api client", slog.Any("err", err)) return err } defer apiClient.Close() 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, client.WithAPIVersionNegotiation()) if err != nil { Logger.ErrorContext(ctx, "Failed to get docker api client", slog.Any("err", err)) return nil, err } defer apiClient.Close() opts := container.LogsOptions{ ShowStdout: true, // ShowStderr: 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 } func vttStatus(ctx context.Context) ServerStatus { status := ServerStatus{} status.Site = VTT_URL status.Timestamp = time.Now() apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { Logger.ErrorContext(ctx, "Failed to get docker api client", slog.Any("err", err)) return status } defer apiClient.Close() json, err := apiClient.ContainerInspect(ctx, vttContainerId) if err != nil { Logger.ErrorContext(ctx, "Error occured while geting foundry container stats", slog.Any("err", err)) return status } status.Online = json.State.Running return status }