agentsdk

package
v0.0.0-...-560f09a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 18, 2023 License: AGPL-3.0 Imports: 34 Imported by: 0

Documentation

Index

Constants

View Source
const (
	TailnetSSHPort             = 1
	TailnetReconnectingPTYPort = 2
	TailnetSpeedtestPort       = 3
	// TailnetStatisticsPort serves a HTTP server with endpoints for gathering
	// agent statistics.
	TailnetStatisticsPort = 4

	// MinimumListeningPort is the minimum port that the listening-ports
	// endpoint will return to the client, and the minimum port that is accepted
	// by the proxy applications endpoint. Coder consumes ports 1-4 at the
	// moment, and we reserve some extra ports for future use. Port 9 and up are
	// available for the user.
	//
	// This is not enforced in the CLI intentionally as we don't really care
	// *that* much. The user could bypass this in the CLI by using SSH instead
	// anyways.
	MinimumListeningPort = 9
)
View Source
const (
	AgentTokenHeader  = "Gigo-Agent-Token"
	WorkspaceIDHeader = "Gigo-Workspace-Id"
)

These cookies are Gigo-specific. If a new one is added or changed, the name shouldn't be likely to conflict with any user-application set cookies. Be sure to strip additional cookies in httpapi.StripCoderCookies!

Variables

View Source
var IgnoredListeningPorts = map[uint16]struct{}{
	0: {},

	1: {},
	2: {},
	3: {},
	4: {},
	5: {},
	6: {},
	7: {},
	8: {},

	20: {},
	21: {},

	22: {},

	23: {},

	25: {},

	53: {},

	110: {},

	143: {},

	179: {},

	389: {},
	636: {},

	631: {},

	465: {},

	587: {},

	989: {},
	990: {},

	993: {},

	995: {},

	3306: {},

	3389: {},

	5432: {},

	5890: {},
	5990: {},

	6060: {},

	6379: {},

	13337: {},

	13338: {},

	27017: {},
	27018: {},
	27019: {},
	28017: {},
}

IgnoredListeningPorts contains a list of ports in the global ignore list. This list contains common TCP ports that are not HTTP servers, such as databases, SSH, FTP, etc.

This is implemented as a map for fast lookup.

View Source
var (
	// TailnetIP is a static IPv6 address with the Tailscale prefix that is used to route
	// connections from clients to this node. A dynamic address is not required because a Tailnet
	// client only dials a single agent at a time.
	TailnetIP = netip.MustParseAddr("fd7a:115c:a1e0:49d6:b259:b7ac:b1b2:48f4")
)

Functions

func IsConnectionErr

func IsConnectionErr(err error) bool

IsConnectionErr is a convenience function for checking if the source of an error is due to a 'connection refused', 'no such host', etc.

func Write

func Write(ctx context.Context, rw http.ResponseWriter, status int, response interface{})

Write outputs a standardized format to an HTTP response body. ctx is used for tracing and can be nil for tracing to be disabled. Tracing this function is helpful because JSON marshaling can sometimes take a non-insignificant amount of time, and could help us catch outliers. Additionally, we can enrich span data a bit more since we have access to the actual interface{} we're marshaling, such as the number of elements in an array, which could help us spot routes that need to be paginated.

Types

type AgentAuth

type AgentAuth struct {
	WorkspaceID int64
	Token       string
}

type AgentClient

type AgentClient struct {
	HTTPClient *http.Client
	URL        *url.URL

	// Logger can be provided to log requests. Request method, URL and response
	// status code will be logged by default.
	Logger slog.Logger
	// LogBodies determines whether the request and response bodies are logged
	// to the provided Logger. This is useful for debugging or testing.
	LogBodies bool
	// contains filtered or unexported fields
}

AgentClient is an HTTP caller for methods to the Gigo agent API.

func New

func New(serverURL *url.URL) *AgentClient

New creates a Gigo agent client for the provided URL.

func (*AgentClient) AgentReportStats

func (c *AgentClient) AgentReportStats(
	ctx context.Context,
	log slog.Logger,
	statsChan <-chan *AgentStats,
	setInterval func(time.Duration),
) (io.Closer, error)

AgentReportStats begins a stat streaming connection with the Coder server. It is resilient to network failures and intermittent coderd issues.

func (*AgentClient) Clone

func (c *AgentClient) Clone() *AgentClient

func (*AgentClient) DialWorkspaceAgent

func (c *AgentClient) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, options *DialWorkspaceAgentOptions) (*AgentConn, error)

DialWorkspaceAgent

Not Implemented - goes nowhere

func (*AgentClient) InitializeWorkspaceAgent

func (c *AgentClient) InitializeWorkspaceAgent(ctx context.Context) (WorkspaceAgentMetadata, error)

InitializeWorkspaceAgent fetches metadata for the currently authenticated workspace agent.

func (*AgentClient) ListenWorkspaceAgent

func (c *AgentClient) ListenWorkspaceAgent(ctx context.Context) (net.Conn, error)

func (*AgentClient) PostAgentPorts

func (c *AgentClient) PostAgentPorts(ctx context.Context, req *AgentPorts) error

func (*AgentClient) PostAgentStats

func (c *AgentClient) PostAgentStats(ctx context.Context, stats *AgentStats) (AgentStatsResponse, error)

func (*AgentClient) PostWorkspaceAgentState

func (c *AgentClient) PostWorkspaceAgentState(ctx context.Context, state models.WorkspaceAgentState) error

func (*AgentClient) PostWorkspaceAgentVersion

func (c *AgentClient) PostWorkspaceAgentVersion(ctx context.Context, version string) error

func (*AgentClient) Request

func (c *AgentClient) Request(ctx context.Context, method, path string, body interface{}, opts ...RequestOption) (*http.Response, error)

Request performs a HTTP request with the body provided. The caller is responsible for closing the response body.

func (*AgentClient) SessionAuth

func (c *AgentClient) SessionAuth() AgentAuth

func (*AgentClient) SetSessionAuth

func (c *AgentClient) SetSessionAuth(workspaceId int64, token string)

func (*AgentClient) WorkspaceGetCtExtension

func (c *AgentClient) WorkspaceGetCtExtension(ctx context.Context, extPath string) error

func (*AgentClient) WorkspaceGetExtension

func (c *AgentClient) WorkspaceGetExtension(ctx context.Context, extPath string) error

func (*AgentClient) WorkspaceGetHolidayThemeExtension

func (c *AgentClient) WorkspaceGetHolidayThemeExtension(ctx context.Context, extPath string, holiday int) error

func (*AgentClient) WorkspaceGetOpenVsxExtension

func (c *AgentClient) WorkspaceGetOpenVsxExtension(ctx context.Context, extId, version, vscVersion, extPath string) error

func (*AgentClient) WorkspaceGetThemeExtension

func (c *AgentClient) WorkspaceGetThemeExtension(ctx context.Context, extPath string) error

func (*AgentClient) WorkspaceInitializationFailure

func (c *AgentClient) WorkspaceInitializationFailure(ctx context.Context, req PostWorkspaceInitFailure) error

func (*AgentClient) WorkspaceInitializationStepCompleted

func (c *AgentClient) WorkspaceInitializationStepCompleted(ctx context.Context, state models.WorkspaceInitState) error

type AgentConn

type AgentConn struct {
	*tailnet.Conn
	CloseFunc func()
}

func (*AgentConn) AwaitReachable

func (c *AgentConn) AwaitReachable(ctx context.Context) bool

func (*AgentConn) Close

func (c *AgentConn) Close() error

func (*AgentConn) CloseWithError

func (c *AgentConn) CloseWithError(_ error) error

func (*AgentConn) DialContext

func (c *AgentConn) DialContext(ctx context.Context, network string, addr string) (net.Conn, error)

func (*AgentConn) Ping

Ping pings the agent and returns the round-trip time. The bool returns true if the ping was made P2P.

func (*AgentConn) ReconnectingPTY

func (c *AgentConn) ReconnectingPTY(ctx context.Context, id uuid.UUID, height, width uint16, command string) (net.Conn, error)

func (*AgentConn) SSH

func (c *AgentConn) SSH(ctx context.Context) (net.Conn, error)

func (*AgentConn) SSHClient

func (c *AgentConn) SSHClient(ctx context.Context) (*ssh.Client, error)

SSHClient calls SSH to create a client that uses a weak cipher for high throughput.

func (*AgentConn) Speedtest

func (c *AgentConn) Speedtest(ctx context.Context, direction speedtest.Direction, duration time.Duration) ([]speedtest.Result, error)

type AgentPorts

type AgentPorts struct {
	Ports []ListeningPort `json:"ports"`
}

type AgentStats

type AgentStats struct {
	// ConnsByProto is a count of connections by protocol.
	ConnsByProto map[string]int64 `json:"conns_by_proto"`
	// NumConns is the number of connections received by an agent.
	NumConns int64 `json:"num_comms"`
	// RxPackets is the number of received packets.
	RxPackets int64 `json:"rx_packets"`
	// RxBytes is the number of received bytes.
	RxBytes int64 `json:"rx_bytes"`
	// TxPackets is the number of transmitted bytes.
	TxPackets int64 `json:"tx_packets"`
	// TxBytes is the number of transmitted bytes.
	TxBytes int64 `json:"tx_bytes"`
}

Stats records the Agent's network connection statistics for use in user-facing metrics and debugging.

type AgentStatsResponse

type AgentStatsResponse struct {
	// ReportInterval is the duration after which the agent should send stats
	// again.
	ReportInterval time.Duration `json:"report_interval"`
}

type DialWorkspaceAgentOptions

type DialWorkspaceAgentOptions struct {
	Logger        logging.Logger
	SnowflakeNode *snowflake.Node
	// BlockEndpoints forced a direct connection through DERP.
	BlockEndpoints bool
}

type Error

type Error struct {
	Response

	Helper string
	// contains filtered or unexported fields
}

Error represents an unaccepted or invalid request to the API.

func AsError

func AsError(err error) (*Error, bool)

func (*Error) Error

func (e *Error) Error() string

func (*Error) StatusCode

func (e *Error) StatusCode() int

type Holiday

type Holiday int
const (
	NoHoliday Holiday = iota
	Halloween
	Christmas
	NewYears
	Valentine
	Easter
	Independence
)

func (Holiday) String

func (h Holiday) String() string

type ListeningPort

type ListeningPort struct {
	ProcessName string               `json:"process_name"` // may be empty
	Network     ListeningPortNetwork `json:"network"`      // only "tcp" at the moment
	Port        uint16               `json:"port"`
}

func (*ListeningPort) String

func (l *ListeningPort) String() string

type ListeningPortNetwork

type ListeningPortNetwork string
const (
	ListeningPortNetworkTCP ListeningPortNetwork = "tcp"
)

type PostWorkspaceAgentState

type PostWorkspaceAgentState struct {
	State models.WorkspaceAgentState `json:"state"`
}

type PostWorkspaceAgentVersionRequest

type PostWorkspaceAgentVersionRequest struct {
	Version string `json:"version"`
}

type PostWorkspaceInitFailure

type PostWorkspaceInitFailure struct {
	State   models.WorkspaceInitState `json:"state"`
	Command string                    `json:"command"`
	Status  int                       `json:"status"`
	Stdout  string                    `json:"stdout"`
	Stderr  string                    `json:"stderr"`
}

type PostWorkspaceInitStateCompleted

type PostWorkspaceInitStateCompleted struct {
	State models.WorkspaceInitState `json:"state"`
}

type ReconnectingPTYInit

type ReconnectingPTYInit struct {
	ID      uuid.UUID
	Height  uint16
	Width   uint16
	Command string
}

type ReconnectingPTYRequest

type ReconnectingPTYRequest struct {
	Data   string `json:"data"`
	Height uint16 `json:"height"`
	Width  uint16 `json:"width"`
}

ReconnectingPTYRequest is sent from the client to the server to pipe data to a PTY.

type RequestOption

type RequestOption func(*http.Request)

type Response

type Response struct {
	// Message is an actionable message that depicts actions the request took.
	// These messages should be fully formed sentences with proper punctuation.
	// Examples:
	// - "A user has been created."
	// - "Failed to create a user."
	Message string `json:"message"`
	// Detail is a debug message that provides further insight into why the
	// action failed. This information can be technical and a regular golang
	// err.Error() text.
	// - "database: too many open connections"
	// - "stat: too many open files"
	Detail string `json:"detail,omitempty"`
	// Validations are form field-specific friendly error messages. They will be
	// shown on a form field in the UI. These can also be used to add additional
	// context if there is a set of errors in the primary 'Message'.
	Validations []ValidationError `json:"validations,omitempty"`
}

Response represents a generic HTTP response.

type ValidationError

type ValidationError struct {
	Field  string `json:"field" validate:"required"`
	Detail string `json:"detail" validate:"required"`
}

ValidationError represents a scoped error to a user input.

func (ValidationError) Error

func (e ValidationError) Error() string

type WorkspaceAgentConnectionInfo

type WorkspaceAgentConnectionInfo struct {
	DERPMap *tailcfg.DERPMap `json:"derp_map"`
}

WorkspaceAgentConnectionInfo returns required information for establishing a connection with a workspace.

type WorkspaceAgentMetadata

type WorkspaceAgentMetadata struct {
	WorkspaceID        int64                                     `json:"workspace_id"`
	WorkspaceIDString  string                                    `json:"workspace_id_string"`
	Repo               string                                    `json:"repo"`
	Commit             string                                    `json:"commit"`
	GitToken           string                                    `json:"git_token"`
	GitEmail           string                                    `json:"git_email"`
	GitName            string                                    `json:"git_name"`
	Expiration         int64                                     `json:"expiration"`
	OwnerID            int64                                     `json:"owner_id"`
	OwnerIDString      string                                    `json:"owner_id_string"`
	WorkspaceSettings  *models.WorkspaceSettings                 `json:"workspace_settings"`
	VSCodePortProxyURI string                                    `json:"vscode_port_proxy_uri"`
	DERPMap            *tailcfg.DERPMap                          `json:"derpmap"`
	LastInitState      models.WorkspaceInitState                 `json:"last_init_state"`
	WorkspaceState     models.WorkspaceState                     `json:"workspace_state"`
	GigoConfig         workspace_config.GigoWorkspaceConfigAgent `json:"gigo_config"`
	UserStatus         models.UserStatus                         `json:"user_status"`
	HolidaySeason      Holiday                                   `json:"holiday_season"`
	ChallengeType      models.ChallengeType                      `json:"challenge_type"`
	UserHolidayTheme   bool                                      `json:"user_holiday_theme"`
	Hosts              map[string]string                         `json:"hosts"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL