mirror of https://github.com/coder/coder.git
fix(site): add workspace proxy section to health page (#10862)
* Adds workspace proxy section to health page * Conditionally places workspace proxy warnings in errors or warnings based on calculated severity * Adds some more stories we were missing for HealthPage
This commit is contained in:
parent
6c67add2d9
commit
b73397e08c
|
@ -238,6 +238,34 @@ func TestHealthcheck(t *testing.T) {
|
|||
severity: health.SeverityError,
|
||||
healthy: false,
|
||||
failingSections: []string{healthcheck.SectionWorkspaceProxy},
|
||||
}, {
|
||||
name: "ProxyWarn",
|
||||
checker: &testChecker{
|
||||
DERPReport: derphealth.Report{
|
||||
Healthy: true,
|
||||
Severity: health.SeverityOK,
|
||||
},
|
||||
AccessURLReport: healthcheck.AccessURLReport{
|
||||
Healthy: true,
|
||||
Severity: health.SeverityOK,
|
||||
},
|
||||
WebsocketReport: healthcheck.WebsocketReport{
|
||||
Healthy: true,
|
||||
Severity: health.SeverityOK,
|
||||
},
|
||||
DatabaseReport: healthcheck.DatabaseReport{
|
||||
Healthy: true,
|
||||
Severity: health.SeverityOK,
|
||||
},
|
||||
WorkspaceProxyReport: healthcheck.WorkspaceProxyReport{
|
||||
Healthy: true,
|
||||
Warnings: []string{"foobar"},
|
||||
Severity: health.SeverityWarning,
|
||||
},
|
||||
},
|
||||
severity: health.SeverityWarning,
|
||||
healthy: true,
|
||||
failingSections: []string{},
|
||||
}, {
|
||||
name: "AllFail",
|
||||
healthy: false,
|
||||
|
|
|
@ -2,8 +2,9 @@ package healthcheck
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
|
@ -78,6 +79,7 @@ func (r *WorkspaceProxyReport) Run(ctx context.Context, opts *WorkspaceProxyRepo
|
|||
})
|
||||
|
||||
var total, healthy int
|
||||
var errs []string
|
||||
for _, proxy := range r.WorkspaceProxies.Regions {
|
||||
total++
|
||||
if proxy.Healthy {
|
||||
|
@ -86,34 +88,40 @@ func (r *WorkspaceProxyReport) Run(ctx context.Context, opts *WorkspaceProxyRepo
|
|||
|
||||
if len(proxy.Status.Report.Errors) > 0 {
|
||||
for _, err := range proxy.Status.Report.Errors {
|
||||
r.appendError(xerrors.New(err))
|
||||
errs = append(errs, fmt.Sprintf("%s: %s", proxy.Name, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.Severity = calculateSeverity(total, healthy)
|
||||
r.Healthy = r.Severity.Value() < health.SeverityError.Value()
|
||||
switch r.Severity {
|
||||
case health.SeverityWarning, health.SeverityOK:
|
||||
r.Warnings = append(r.Warnings, errs...)
|
||||
case health.SeverityError:
|
||||
r.appendError(errs...)
|
||||
}
|
||||
|
||||
// Versions _must_ match. Perform this check last. This will clobber any other severity.
|
||||
for _, proxy := range r.WorkspaceProxies.Regions {
|
||||
if vErr := checkVersion(proxy, opts.CurrentVersion); vErr != nil {
|
||||
r.Healthy = false
|
||||
r.Severity = health.SeverityError
|
||||
r.appendError(vErr)
|
||||
r.appendError(fmt.Sprintf("%s: %s", proxy.Name, vErr.Error()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// appendError appends errs onto r.Error.
|
||||
// We only have one error, so multiple errors need to be squashed in there.
|
||||
func (r *WorkspaceProxyReport) appendError(errs ...error) {
|
||||
if len(errs) == 0 {
|
||||
func (r *WorkspaceProxyReport) appendError(es ...string) {
|
||||
if len(es) == 0 {
|
||||
return
|
||||
}
|
||||
if r.Error != nil {
|
||||
errs = append([]error{xerrors.New(*r.Error)}, errs...)
|
||||
es = append([]string{*r.Error}, es...)
|
||||
}
|
||||
r.Error = ptr.Ref(errors.Join(errs...).Error())
|
||||
r.Error = ptr.Ref(strings.Join(es, "\n"))
|
||||
}
|
||||
|
||||
func checkVersion(proxy codersdk.WorkspaceProxy, currentVersion string) error {
|
||||
|
|
|
@ -9,8 +9,6 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func Test_WorkspaceProxyReport_appendErrors(t *testing.T) {
|
||||
|
@ -20,7 +18,7 @@ func Test_WorkspaceProxyReport_appendErrors(t *testing.T) {
|
|||
name string
|
||||
expected string
|
||||
prevErr string
|
||||
errs []error
|
||||
errs []string
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
|
@ -29,24 +27,24 @@ func Test_WorkspaceProxyReport_appendErrors(t *testing.T) {
|
|||
{
|
||||
name: "one error",
|
||||
expected: assert.AnError.Error(),
|
||||
errs: []error{assert.AnError},
|
||||
errs: []string{assert.AnError.Error()},
|
||||
},
|
||||
{
|
||||
name: "one error, one prev",
|
||||
prevErr: "previous error",
|
||||
expected: "previous error\n" + assert.AnError.Error(),
|
||||
errs: []error{assert.AnError},
|
||||
errs: []string{assert.AnError.Error()},
|
||||
},
|
||||
{
|
||||
name: "two errors",
|
||||
expected: assert.AnError.Error() + "\nanother error",
|
||||
errs: []error{assert.AnError, xerrors.Errorf("another error")},
|
||||
errs: []string{assert.AnError.Error(), "another error"},
|
||||
},
|
||||
{
|
||||
name: "two errors, one prev",
|
||||
prevErr: "previous error",
|
||||
expected: "previous error\n" + assert.AnError.Error() + "\nanother error",
|
||||
errs: []error{assert.AnError, xerrors.Errorf("another error")},
|
||||
errs: []string{assert.AnError.Error(), "another error"},
|
||||
},
|
||||
} {
|
||||
tt := tt
|
||||
|
|
|
@ -19,14 +19,106 @@ type Story = StoryObj<typeof HealthPageView>;
|
|||
|
||||
export const Example: Story = {};
|
||||
|
||||
export const AccessURLUnhealthy: Story = {
|
||||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
healthy: false,
|
||||
severity: "error",
|
||||
access_url: {
|
||||
...MockHealth.access_url,
|
||||
healthy: false,
|
||||
error: "ouch",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const AccessURLWarning: Story = {
|
||||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
healthy: true,
|
||||
severity: "warning",
|
||||
access_url: {
|
||||
...MockHealth.access_url,
|
||||
healthy: true,
|
||||
warnings: ["foobar"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const DatabaseUnhealthy: Story = {
|
||||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
healthy: false,
|
||||
severity: "error",
|
||||
database: {
|
||||
...MockHealth.database,
|
||||
healthy: false,
|
||||
error: "ouch",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const DatabaseWarning: Story = {
|
||||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
healthy: true,
|
||||
severity: "warning",
|
||||
database: {
|
||||
...MockHealth.database,
|
||||
healthy: true,
|
||||
warnings: ["foobar"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const WebsocketUnhealthy: Story = {
|
||||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
healthy: false,
|
||||
severity: "error",
|
||||
websocket: {
|
||||
...MockHealth.websocket,
|
||||
healthy: false,
|
||||
error: "ouch",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const WebsocketWarning: Story = {
|
||||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
healthy: true,
|
||||
severity: "warning",
|
||||
websocket: {
|
||||
...MockHealth.websocket,
|
||||
healthy: true,
|
||||
warnings: ["foobar"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const UnhealthyDERP: Story = {
|
||||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
healthy: false,
|
||||
severity: "error",
|
||||
derp: {
|
||||
...MockHealth.derp,
|
||||
healthy: false,
|
||||
error: "ouch",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -36,6 +128,7 @@ export const DERPWarnings: Story = {
|
|||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
severity: "warning",
|
||||
derp: {
|
||||
...MockHealth.derp,
|
||||
warnings: ["foobar"],
|
||||
|
@ -43,3 +136,31 @@ export const DERPWarnings: Story = {
|
|||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const ProxyUnhealthy: Story = {
|
||||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
severity: "error",
|
||||
healthy: false,
|
||||
workspace_proxy: {
|
||||
...MockHealth.workspace_proxy,
|
||||
healthy: false,
|
||||
error: "ouch",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const ProxyWarning: Story = {
|
||||
args: {
|
||||
healthStatus: {
|
||||
...MockHealth,
|
||||
severity: "warning",
|
||||
workspace_proxy: {
|
||||
...MockHealth.workspace_proxy,
|
||||
warnings: ["foobar"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@ const sections = {
|
|||
access_url: "Access URL",
|
||||
websocket: "Websocket",
|
||||
database: "Database",
|
||||
workspace_proxy: "Workspace Proxy",
|
||||
} as const;
|
||||
|
||||
export default function HealthPage() {
|
||||
|
|
Loading…
Reference in New Issue