Files
threshold/internal/bsr/convert/convert.go
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

94 lines
3.1 KiB
Go
Raw Normal View History

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package convert
import (
"context"
2023-05-11 20:41:18 +00:00
"fmt"
"io"
"github.com/hashicorp/boundary/internal/bsr"
2023-05-11 20:41:18 +00:00
"github.com/hashicorp/boundary/internal/bsr/internal/is"
"github.com/hashicorp/boundary/internal/bsr/ssh"
"github.com/hashicorp/boundary/internal/storage"
)
// ToAsciicast accepts a bsr.Session and will convert the underlying BSR connection or channel file to an asciinema file.
// The tempFs will be used to write the asciinema file to disk
// It returns an io.Reader to the converted asciinema file.
// This supports the following options:
// - WithChannelId to indicate this conversion should occur on a channel on a multiplexed session
// - WithMinWidth to set a minimum width for the asciicast
// - WithMinHeigh to set a minimum height for the asciicast
2023-05-11 20:41:18 +00:00
func ToAsciicast(ctx context.Context, session *bsr.Session, tmp storage.TempFile, connectionId string, options ...Option) (io.ReadCloser, error) {
const op = "convert.ToAsciicast"
switch {
case is.Nil(session):
return nil, fmt.Errorf("%s: missing session: %w", op, bsr.ErrInvalidParameter)
case is.Nil(session.Meta):
return nil, fmt.Errorf("%s: missing session meta: %w", op, bsr.ErrInvalidParameter)
case is.Nil(tmp):
return nil, fmt.Errorf("%s: missing temp file: %w", op, bsr.ErrInvalidParameter)
case connectionId == "":
return nil, fmt.Errorf("%s: missing connection id: %w", op, bsr.ErrInvalidParameter)
}
opts := getOpts(options...)
switch session.Meta.Protocol {
case ssh.Protocol:
chanId := opts.withChannelId
switch {
case chanId == "":
return nil, fmt.Errorf("%s: protocol %q requires channel id to convert: %w", op, ssh.Protocol, bsr.ErrInvalidParameter)
}
conn, err := session.OpenConnection(ctx, connectionId)
if err != nil {
return nil, fmt.Errorf("%s: %w", op, err)
}
2023-07-31 17:13:24 -04:00
defer conn.Close(ctx)
2023-05-11 20:41:18 +00:00
ch, err := conn.OpenChannel(ctx, chanId)
if err != nil {
return nil, fmt.Errorf("%s: %w", op, err)
}
2023-07-31 17:13:24 -04:00
defer ch.Close(ctx)
2023-05-11 20:41:18 +00:00
switch chs := ch.Summary.(type) {
case *ssh.ChannelSummary:
switch chs.SessionProgram {
case ssh.Shell, ssh.Exec:
reqScanner, err := ch.OpenRequestScanner(ctx, bsr.Inbound)
if err != nil {
2023-07-31 17:13:24 -04:00
if !is.Nil(reqScanner) {
reqScanner.Close()
}
return nil, fmt.Errorf("%s: %w", op, err)
}
2023-07-31 17:13:24 -04:00
defer reqScanner.Close()
2023-05-11 20:41:18 +00:00
msgScanner, err := ch.OpenMessageScanner(ctx, bsr.Outbound)
if err != nil {
2023-07-31 17:13:24 -04:00
if !is.Nil(msgScanner) {
msgScanner.Close()
}
return nil, fmt.Errorf("%s: %w", op, err)
}
2023-07-31 17:13:24 -04:00
defer msgScanner.Close()
return sshChannelToAsciicast(ctx, reqScanner, msgScanner, tmp, options...)
case "":
return nil, fmt.Errorf("%s: session program not set for asciicast conversion", op)
default:
return nil, fmt.Errorf("%s: unsupported %q session program for asciicast conversion", op, chs.SessionProgram)
}
default:
return nil, fmt.Errorf("%s: unexpected error occurred with channel summary. possibly a malformed Boundary Session Recording", op)
2023-05-11 20:41:18 +00:00
}
default:
return nil, fmt.Errorf("%s: %w", op, ErrUnsupportedProtocol)
}
}