mirror of https://github.com/coder/coder.git
fix: allow ports in wildcard url configuration (#11657)
* fix: allow ports in wildcard url configuration This just forwards the port to the ui that generates urls. Our existing parsing + regex already supported ports for subdomain app requests.
This commit is contained in:
parent
1f0e6ba6c6
commit
6bb1a34a37
|
@ -3,7 +3,6 @@ package agentapi
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
@ -108,19 +107,14 @@ func (a *ManifestAPI) GetManifest(ctx context.Context, _ *agentproto.GetManifest
|
||||||
return nil, xerrors.Errorf("fetching workspace agent data: %w", err)
|
return nil, xerrors.Errorf("fetching workspace agent data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
appHost := appurl.ApplicationURL{
|
appSlug := appurl.ApplicationURL{
|
||||||
AppSlugOrPort: "{{port}}",
|
AppSlugOrPort: "{{port}}",
|
||||||
AgentName: workspaceAgent.Name,
|
AgentName: workspaceAgent.Name,
|
||||||
WorkspaceName: workspace.Name,
|
WorkspaceName: workspace.Name,
|
||||||
Username: owner.Username,
|
Username: owner.Username,
|
||||||
}
|
}
|
||||||
vscodeProxyURI := a.AccessURL.Scheme + "://" + strings.ReplaceAll(a.AppHostname, "*", appHost.String())
|
|
||||||
if a.AppHostname == "" {
|
vscodeProxyURI := vscodeProxyURI(appSlug, a.AccessURL, a.AppHostname)
|
||||||
vscodeProxyURI += a.AccessURL.Hostname()
|
|
||||||
}
|
|
||||||
if a.AccessURL.Port() != "" {
|
|
||||||
vscodeProxyURI += fmt.Sprintf(":%s", a.AccessURL.Port())
|
|
||||||
}
|
|
||||||
|
|
||||||
var gitAuthConfigs uint32
|
var gitAuthConfigs uint32
|
||||||
for _, cfg := range a.ExternalAuthConfigs {
|
for _, cfg := range a.ExternalAuthConfigs {
|
||||||
|
@ -155,6 +149,17 @@ func (a *ManifestAPI) GetManifest(ctx context.Context, _ *agentproto.GetManifest
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func vscodeProxyURI(app appurl.ApplicationURL, accessURL *url.URL, appHost string) string {
|
||||||
|
// This will handle the ports from the accessURL or appHost.
|
||||||
|
appHost = appurl.SubdomainAppHost(appHost, accessURL)
|
||||||
|
// If there is no appHost, then we want to use the access url as the proxy uri.
|
||||||
|
if appHost == "" {
|
||||||
|
appHost = accessURL.Host
|
||||||
|
}
|
||||||
|
// Return the url with a scheme and any wildcards replaced with the app slug.
|
||||||
|
return accessURL.Scheme + "://" + strings.ReplaceAll(appHost, "*", app.String())
|
||||||
|
}
|
||||||
|
|
||||||
func dbAgentMetadataToProtoDescription(metadata []database.WorkspaceAgentMetadatum) []*agentproto.WorkspaceAgentMetadata_Description {
|
func dbAgentMetadataToProtoDescription(metadata []database.WorkspaceAgentMetadatum) []*agentproto.WorkspaceAgentMetadata_Description {
|
||||||
ret := make([]*agentproto.WorkspaceAgentMetadata_Description, len(metadata))
|
ret := make([]*agentproto.WorkspaceAgentMetadata_Description, len(metadata))
|
||||||
for i, metadatum := range metadata {
|
for i, metadatum := range metadata {
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
package agentapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_vscodeProxyURI(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
coderAccessURL, err := url.Parse("https://coder.com")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
accessURLWithPort, err := url.Parse("https://coder.com:8080")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
basicApp := appurl.ApplicationURL{
|
||||||
|
Prefix: "prefix",
|
||||||
|
AppSlugOrPort: "slug",
|
||||||
|
AgentName: "agent",
|
||||||
|
WorkspaceName: "workspace",
|
||||||
|
Username: "user",
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
Name string
|
||||||
|
App appurl.ApplicationURL
|
||||||
|
AccessURL *url.URL
|
||||||
|
AppHostname string
|
||||||
|
Expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
// No hostname proxies through the access url.
|
||||||
|
Name: "NoHostname",
|
||||||
|
AccessURL: coderAccessURL,
|
||||||
|
AppHostname: "",
|
||||||
|
App: basicApp,
|
||||||
|
Expected: coderAccessURL.String(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NoHostnameAccessURLPort",
|
||||||
|
AccessURL: accessURLWithPort,
|
||||||
|
AppHostname: "",
|
||||||
|
App: basicApp,
|
||||||
|
Expected: accessURLWithPort.String(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Hostname",
|
||||||
|
AccessURL: coderAccessURL,
|
||||||
|
AppHostname: "*.apps.coder.com",
|
||||||
|
App: basicApp,
|
||||||
|
Expected: fmt.Sprintf("https://%s.apps.coder.com", basicApp.String()),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "HostnameWithAccessURLPort",
|
||||||
|
AccessURL: accessURLWithPort,
|
||||||
|
AppHostname: "*.apps.coder.com",
|
||||||
|
App: basicApp,
|
||||||
|
Expected: fmt.Sprintf("https://%s.apps.coder.com:%s", basicApp.String(), accessURLWithPort.Port()),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "HostnameWithPort",
|
||||||
|
AccessURL: coderAccessURL,
|
||||||
|
AppHostname: "*.apps.coder.com:4444",
|
||||||
|
App: basicApp,
|
||||||
|
Expected: fmt.Sprintf("https://%s.apps.coder.com:%s", basicApp.String(), "4444"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Port from hostname takes precedence over access url port.
|
||||||
|
Name: "HostnameWithPortAccessURLWithPort",
|
||||||
|
AccessURL: accessURLWithPort,
|
||||||
|
AppHostname: "*.apps.coder.com:4444",
|
||||||
|
App: basicApp,
|
||||||
|
Expected: fmt.Sprintf("https://%s.apps.coder.com:%s", basicApp.String(), "4444"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
c := c
|
||||||
|
t.Run(c.Name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
require.NotNilf(t, c.AccessURL, "AccessURL is required")
|
||||||
|
|
||||||
|
output := vscodeProxyURI(c.App, c.AccessURL, c.AppHostname)
|
||||||
|
require.Equal(t, c.Expected, output)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -93,7 +93,7 @@ type Options struct {
|
||||||
// AppHostname should be the wildcard hostname to use for workspace
|
// AppHostname should be the wildcard hostname to use for workspace
|
||||||
// applications INCLUDING the asterisk, (optional) suffix and leading dot.
|
// applications INCLUDING the asterisk, (optional) suffix and leading dot.
|
||||||
// It will use the same scheme and port number as the access URL.
|
// It will use the same scheme and port number as the access URL.
|
||||||
// E.g. "*.apps.coder.com" or "*-apps.coder.com".
|
// E.g. "*.apps.coder.com" or "*-apps.coder.com" or "*.apps.coder.com:8080".
|
||||||
AppHostname string
|
AppHostname string
|
||||||
// AppHostnameRegex contains the regex version of options.AppHostname as
|
// AppHostnameRegex contains the regex version of options.AppHostname as
|
||||||
// generated by appurl.CompileHostnamePattern(). It MUST be set if
|
// generated by appurl.CompileHostnamePattern(). It MUST be set if
|
||||||
|
|
|
@ -3,7 +3,6 @@ package coderd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -32,13 +31,8 @@ import (
|
||||||
// @Router /applications/host [get]
|
// @Router /applications/host [get]
|
||||||
// @Deprecated use api/v2/regions and see the primary proxy.
|
// @Deprecated use api/v2/regions and see the primary proxy.
|
||||||
func (api *API) appHost(rw http.ResponseWriter, r *http.Request) {
|
func (api *API) appHost(rw http.ResponseWriter, r *http.Request) {
|
||||||
host := api.AppHostname
|
|
||||||
if host != "" && api.AccessURL.Port() != "" {
|
|
||||||
host += fmt.Sprintf(":%s", api.AccessURL.Port())
|
|
||||||
}
|
|
||||||
|
|
||||||
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.AppHostResponse{
|
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.AppHostResponse{
|
||||||
Host: host,
|
Host: appurl.SubdomainAppHost(api.AppHostname, api.AccessURL),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -963,6 +963,38 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
|
||||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("WildcardPortOK", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Manually specifying a port should override the access url port on
|
||||||
|
// the app host.
|
||||||
|
appDetails := setupProxyTest(t, &DeploymentOptions{
|
||||||
|
// Just throw both the wsproxy and primary to same url.
|
||||||
|
AppHost: "*.test.coder.com:4444",
|
||||||
|
PrimaryAppHost: "*.test.coder.com:4444",
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
u := appDetails.SubdomainAppURL(appDetails.Apps.Owner)
|
||||||
|
t.Logf("url: %s", u)
|
||||||
|
require.Equal(t, "4444", u.Port(), "port should be 4444")
|
||||||
|
|
||||||
|
// Assert the api response the UI uses has the port.
|
||||||
|
apphost, err := appDetails.SDKClient.AppHost(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "*.test.coder.com:4444", apphost.Host, "apphost has port")
|
||||||
|
|
||||||
|
resp, err := requestWithRetries(ctx, t, appDetails.AppClient(t), http.MethodGet, u.String(), nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, proxyTestAppBody, string(body))
|
||||||
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("SuffixWildcardNotMatch", func(t *testing.T) {
|
t.Run("SuffixWildcardNotMatch", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ const (
|
||||||
// DeploymentOptions are the options for creating a *Deployment with a
|
// DeploymentOptions are the options for creating a *Deployment with a
|
||||||
// DeploymentFactory.
|
// DeploymentFactory.
|
||||||
type DeploymentOptions struct {
|
type DeploymentOptions struct {
|
||||||
|
PrimaryAppHost string
|
||||||
AppHost string
|
AppHost string
|
||||||
DisablePathApps bool
|
DisablePathApps bool
|
||||||
DisableSubdomainApps bool
|
DisableSubdomainApps bool
|
||||||
|
@ -407,7 +408,7 @@ func createWorkspaceWithApps(t *testing.T, client *codersdk.Client, orgID uuid.U
|
||||||
Username: me.Username,
|
Username: me.Username,
|
||||||
}
|
}
|
||||||
proxyURL := "http://" + appHost.String() + strings.ReplaceAll(primaryAppHost.Host, "*", "")
|
proxyURL := "http://" + appHost.String() + strings.ReplaceAll(primaryAppHost.Host, "*", "")
|
||||||
require.Equal(t, proxyURL, manifest.VSCodePortProxyURI)
|
require.Equal(t, manifest.VSCodePortProxyURI, proxyURL)
|
||||||
}
|
}
|
||||||
agentCloser := agent.New(agent.Options{
|
agentCloser := agent.New(agent.Options{
|
||||||
Client: agentClient,
|
Client: agentClient,
|
||||||
|
|
|
@ -3,6 +3,7 @@ package appurl
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -20,6 +21,36 @@ var (
|
||||||
validHostnameLabelRegex = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`)
|
validHostnameLabelRegex = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SubdomainAppHost returns the URL of the apphost for subdomain based apps.
|
||||||
|
// It will omit the scheme.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// apphost: Expected to contain a wildcard, example: "*.coder.com"
|
||||||
|
// accessURL: The access url for the deployment.
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// 'apphost:port'
|
||||||
|
//
|
||||||
|
// For backwards compatibility and for "accessurl=localhost:0" purposes, we need
|
||||||
|
// to use the port from the accessurl if the apphost doesn't have a port.
|
||||||
|
// If the user specifies a port in the apphost, we will use that port instead.
|
||||||
|
func SubdomainAppHost(apphost string, accessURL *url.URL) string {
|
||||||
|
if apphost == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if apphost != "" && accessURL.Port() != "" {
|
||||||
|
// This should always parse if we prepend a scheme. We should add
|
||||||
|
// the access url port if the apphost doesn't have a port specified.
|
||||||
|
appHostU, err := url.Parse(fmt.Sprintf("https://%s", apphost))
|
||||||
|
if err != nil || (err == nil && appHostU.Port() == "") {
|
||||||
|
apphost += fmt.Sprintf(":%s", accessURL.Port())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return apphost
|
||||||
|
}
|
||||||
|
|
||||||
// ApplicationURL is a parsed application URL hostname.
|
// ApplicationURL is a parsed application URL hostname.
|
||||||
type ApplicationURL struct {
|
type ApplicationURL struct {
|
||||||
Prefix string
|
Prefix string
|
||||||
|
@ -140,9 +171,7 @@ func CompileHostnamePattern(pattern string) (*regexp.Regexp, error) {
|
||||||
if strings.Contains(pattern, "http:") || strings.Contains(pattern, "https:") {
|
if strings.Contains(pattern, "http:") || strings.Contains(pattern, "https:") {
|
||||||
return nil, xerrors.Errorf("hostname pattern must not contain a scheme: %q", pattern)
|
return nil, xerrors.Errorf("hostname pattern must not contain a scheme: %q", pattern)
|
||||||
}
|
}
|
||||||
if strings.Contains(pattern, ":") {
|
|
||||||
return nil, xerrors.Errorf("hostname pattern must not contain a port: %q", pattern)
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(pattern, ".") || strings.HasSuffix(pattern, ".") {
|
if strings.HasPrefix(pattern, ".") || strings.HasSuffix(pattern, ".") {
|
||||||
return nil, xerrors.Errorf("hostname pattern must not start or end with a period: %q", pattern)
|
return nil, xerrors.Errorf("hostname pattern must not start or end with a period: %q", pattern)
|
||||||
}
|
}
|
||||||
|
@ -155,6 +184,16 @@ func CompileHostnamePattern(pattern string) (*regexp.Regexp, error) {
|
||||||
if !strings.HasPrefix(pattern, "*") {
|
if !strings.HasPrefix(pattern, "*") {
|
||||||
return nil, xerrors.Errorf("hostname pattern must only contain an asterisk at the beginning: %q", pattern)
|
return nil, xerrors.Errorf("hostname pattern must only contain an asterisk at the beginning: %q", pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there is a hostname:port, we only care about the hostname. For hostname
|
||||||
|
// pattern reasons, we do not actually care what port the client is requesting.
|
||||||
|
// Any port provided here is used for generating urls for the ui, not for
|
||||||
|
// validation.
|
||||||
|
hostname, _, err := net.SplitHostPort(pattern)
|
||||||
|
if err == nil {
|
||||||
|
pattern = hostname
|
||||||
|
}
|
||||||
|
|
||||||
for i, label := range strings.Split(pattern, ".") {
|
for i, label := range strings.Split(pattern, ".") {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
// We have to allow the asterisk to be a valid hostname label, so
|
// We have to allow the asterisk to be a valid hostname label, so
|
||||||
|
|
|
@ -193,11 +193,6 @@ func TestCompileHostnamePattern(t *testing.T) {
|
||||||
pattern: "https://*.hi.com",
|
pattern: "https://*.hi.com",
|
||||||
errorContains: "must not contain a scheme",
|
errorContains: "must not contain a scheme",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "Invalid_ContainsPort",
|
|
||||||
pattern: "*.hi.com:8080",
|
|
||||||
errorContains: "must not contain a port",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "Invalid_StartPeriod",
|
name: "Invalid_StartPeriod",
|
||||||
pattern: ".hi.com",
|
pattern: ".hi.com",
|
||||||
|
@ -249,6 +244,13 @@ func TestCompileHostnamePattern(t *testing.T) {
|
||||||
errorContains: "contains invalid label",
|
errorContains: "contains invalid label",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "Valid_ContainsPort",
|
||||||
|
pattern: "*.hi.com:8080",
|
||||||
|
// Although a port is provided, the regex already matches any port.
|
||||||
|
// So it is ignored for validation purposes.
|
||||||
|
expectedRegex: `([^.]+)\.hi\.com`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Valid_Simple",
|
name: "Valid_Simple",
|
||||||
pattern: "*.hi",
|
pattern: "*.hi",
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/coder/coder/v2/coderd/database"
|
"github.com/coder/coder/v2/coderd/database"
|
||||||
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
||||||
"github.com/coder/coder/v2/coderd/httpapi"
|
"github.com/coder/coder/v2/coderd/httpapi"
|
||||||
|
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
|
||||||
"github.com/coder/coder/v2/codersdk"
|
"github.com/coder/coder/v2/codersdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ func (api *API) PrimaryRegion(ctx context.Context) (codersdk.Region, error) {
|
||||||
IconURL: proxy.IconUrl,
|
IconURL: proxy.IconUrl,
|
||||||
Healthy: true,
|
Healthy: true,
|
||||||
PathAppURL: api.AccessURL.String(),
|
PathAppURL: api.AccessURL.String(),
|
||||||
WildcardHostname: api.AppHostname,
|
WildcardHostname: appurl.SubdomainAppHost(api.AppHostname, api.AccessURL),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package coderd_test
|
package coderd_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
@ -44,7 +45,7 @@ func TestRegions(t *testing.T) {
|
||||||
require.NotEmpty(t, regions[0].IconURL)
|
require.NotEmpty(t, regions[0].IconURL)
|
||||||
require.True(t, regions[0].Healthy)
|
require.True(t, regions[0].Healthy)
|
||||||
require.Equal(t, client.URL.String(), regions[0].PathAppURL)
|
require.Equal(t, client.URL.String(), regions[0].PathAppURL)
|
||||||
require.Equal(t, appHostname, regions[0].WildcardHostname)
|
require.Equal(t, fmt.Sprintf("%s:%s", appHostname, client.URL.Port()), regions[0].WildcardHostname)
|
||||||
|
|
||||||
// Ensure the primary region ID is constant.
|
// Ensure the primary region ID is constant.
|
||||||
regions2, err := client.Regions(ctx)
|
regions2, err := client.Regions(ctx)
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestRegions(t *testing.T) {
|
||||||
require.NotEmpty(t, regions[0].IconURL)
|
require.NotEmpty(t, regions[0].IconURL)
|
||||||
require.True(t, regions[0].Healthy)
|
require.True(t, regions[0].Healthy)
|
||||||
require.Equal(t, client.URL.String(), regions[0].PathAppURL)
|
require.Equal(t, client.URL.String(), regions[0].PathAppURL)
|
||||||
require.Equal(t, appHostname, regions[0].WildcardHostname)
|
require.Equal(t, fmt.Sprintf("%s:%s", appHostname, client.URL.Port()), regions[0].WildcardHostname)
|
||||||
|
|
||||||
// Ensure the primary region ID is constant.
|
// Ensure the primary region ID is constant.
|
||||||
regions2, err := client.Regions(ctx)
|
regions2, err := client.Regions(ctx)
|
||||||
|
@ -149,7 +149,7 @@ func TestRegions(t *testing.T) {
|
||||||
require.NotEmpty(t, regions[0].IconURL)
|
require.NotEmpty(t, regions[0].IconURL)
|
||||||
require.True(t, regions[0].Healthy)
|
require.True(t, regions[0].Healthy)
|
||||||
require.Equal(t, client.URL.String(), regions[0].PathAppURL)
|
require.Equal(t, client.URL.String(), regions[0].PathAppURL)
|
||||||
require.Equal(t, appHostname, regions[0].WildcardHostname)
|
require.Equal(t, fmt.Sprintf("%s:%s", appHostname, client.URL.Port()), regions[0].WildcardHostname)
|
||||||
|
|
||||||
// Ensure non-zero fields of the default proxy
|
// Ensure non-zero fields of the default proxy
|
||||||
require.NotZero(t, primary.Name)
|
require.NotZero(t, primary.Name)
|
||||||
|
|
|
@ -449,10 +449,13 @@ func TestWorkspaceProxyWorkspaceApps(t *testing.T) {
|
||||||
<-proxyStatsCollectorFlushDone
|
<-proxyStatsCollectorFlushDone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.PrimaryAppHost == "" {
|
||||||
|
opts.PrimaryAppHost = "*.primary.test.coder.com"
|
||||||
|
}
|
||||||
client, closer, api, user := coderdenttest.NewWithAPI(t, &coderdenttest.Options{
|
client, closer, api, user := coderdenttest.NewWithAPI(t, &coderdenttest.Options{
|
||||||
Options: &coderdtest.Options{
|
Options: &coderdtest.Options{
|
||||||
DeploymentValues: deploymentValues,
|
DeploymentValues: deploymentValues,
|
||||||
AppHostname: "*.primary.test.coder.com",
|
AppHostname: opts.PrimaryAppHost,
|
||||||
IncludeProvisionerDaemon: true,
|
IncludeProvisionerDaemon: true,
|
||||||
RealIPConfig: &httpmw.RealIPConfig{
|
RealIPConfig: &httpmw.RealIPConfig{
|
||||||
TrustedOrigins: []*net.IPNet{{
|
TrustedOrigins: []*net.IPNet{{
|
||||||
|
|
Loading…
Reference in New Issue