mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Ignore agent pprof port in listening ports (#6515)
* feat: Ignore agent pprof port in listening ports
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -51,6 +52,7 @@ func workspaceAgent() *cobra.Command {
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parse %q: %w", rawURL, err)
|
||||
}
|
||||
agentPorts := map[int]string{}
|
||||
|
||||
isLinux := runtime.GOOS == "linux"
|
||||
|
||||
@@ -122,6 +124,10 @@ func workspaceAgent() *cobra.Command {
|
||||
_ = pprof.Handler
|
||||
pprofSrvClose := serveHandler(ctx, logger, nil, pprofAddress, "pprof")
|
||||
defer pprofSrvClose()
|
||||
// Do a best effort here. If this fails, it's not a big deal.
|
||||
if port, err := urlPort(pprofAddress); err == nil {
|
||||
agentPorts[port] = "pprof"
|
||||
}
|
||||
|
||||
// exchangeToken returns a session token.
|
||||
// This is abstracted to allow for the same looping condition
|
||||
@@ -202,6 +208,7 @@ func workspaceAgent() *cobra.Command {
|
||||
EnvironmentVariables: map[string]string{
|
||||
"GIT_ASKPASS": executablePath,
|
||||
},
|
||||
AgentPorts: agentPorts,
|
||||
})
|
||||
<-ctx.Done()
|
||||
return closer.Close()
|
||||
@@ -264,3 +271,35 @@ func (c *closeWriter) Write(p []byte) (int, error) {
|
||||
}
|
||||
return c.w.Write(p)
|
||||
}
|
||||
|
||||
// extractPort handles different url strings.
|
||||
// - localhost:6060
|
||||
// - http://localhost:6060
|
||||
func extractPort(u string) (int, error) {
|
||||
port, firstError := urlPort(u)
|
||||
if firstError == nil {
|
||||
return port, nil
|
||||
}
|
||||
|
||||
// Try with a scheme
|
||||
port, err := urlPort("http://" + u)
|
||||
if err == nil {
|
||||
return port, nil
|
||||
}
|
||||
return -1, xerrors.Errorf("invalid url %q: %w", u, firstError)
|
||||
}
|
||||
|
||||
// urlPort extracts the port from a valid URL.
|
||||
func urlPort(u string) (int, error) {
|
||||
parsed, err := url.Parse(u)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("invalid url %q: %w", u, err)
|
||||
}
|
||||
if parsed.Port() != "" {
|
||||
port, err := strconv.ParseInt(parsed.Port(), 10, 64)
|
||||
if err == nil && port > 0 {
|
||||
return int(port), nil
|
||||
}
|
||||
}
|
||||
return -1, xerrors.Errorf("invalid port: %s", u)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_extractPort(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
urlString string
|
||||
want int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Empty",
|
||||
urlString: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "NoScheme",
|
||||
urlString: "localhost:6060",
|
||||
want: 6060,
|
||||
},
|
||||
{
|
||||
name: "WithScheme",
|
||||
urlString: "http://localhost:6060",
|
||||
want: 6060,
|
||||
},
|
||||
{
|
||||
name: "NoPort",
|
||||
urlString: "http://localhost",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "NoPortNoScheme",
|
||||
urlString: "localhost",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "OnlyPort",
|
||||
urlString: "6060",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got, err := extractPort(tt.urlString)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err, fmt.Sprintf("extractPort(%v)", tt.urlString))
|
||||
} else {
|
||||
require.NoError(t, err, fmt.Sprintf("extractPort(%v)", tt.urlString))
|
||||
require.Equal(t, tt.want, got, fmt.Sprintf("extractPort(%v)", tt.urlString))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user