Skip to content

Commit e019058

Browse files
authored
fix: avoid emitting version warning when connection error encountered (#3082)
1 parent 5b78251 commit e019058

File tree

4 files changed

+91
-2
lines changed

4 files changed

+91
-2
lines changed

cli/root.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,11 @@ func checkVersions(cmd *cobra.Command, client *codersdk.Client) error {
455455
clientVersion := buildinfo.Version()
456456

457457
info, err := client.BuildInfo(cmd.Context())
458+
// Avoid printing errors that are connection-related.
459+
if codersdk.IsConnectionErr(err) {
460+
return nil
461+
}
462+
458463
if err != nil {
459464
return xerrors.Errorf("build info: %w", err)
460465
}

codersdk/error.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package codersdk
22

3+
import (
4+
"net"
5+
6+
"golang.org/x/xerrors"
7+
)
8+
39
// Response represents a generic HTTP response.
410
type Response struct {
511
// Message is an actionable message that depicts actions the request took.
@@ -25,3 +31,16 @@ type ValidationError struct {
2531
Field string `json:"field" validate:"required"`
2632
Detail string `json:"detail" validate:"required"`
2733
}
34+
35+
// IsConnectionErr is a convenience function for checking if the source of an
36+
// error is due to a 'connection refused', 'no such host', etc.
37+
func IsConnectionErr(err error) bool {
38+
var (
39+
// E.g. no such host
40+
dnsErr *net.DNSError
41+
// Eg. connection refused
42+
opErr *net.OpError
43+
)
44+
45+
return xerrors.As(err, &dnsErr) || xerrors.As(err, &opErr)
46+
}

codersdk/error_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package codersdk_test
2+
3+
import (
4+
"net"
5+
"os"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
"golang.org/x/xerrors"
10+
11+
"github.com/coder/coder/codersdk"
12+
)
13+
14+
func TestIsConnectionErr(t *testing.T) {
15+
t.Parallel()
16+
17+
type tc = struct {
18+
name string
19+
err error
20+
expectedResult bool
21+
}
22+
23+
cases := []tc{
24+
{
25+
// E.g. "no such host"
26+
name: "DNSError",
27+
err: &net.DNSError{
28+
Err: "no such host",
29+
Name: "foofoo",
30+
Server: "1.1.1.1:53",
31+
IsTimeout: false,
32+
IsTemporary: false,
33+
IsNotFound: true,
34+
},
35+
expectedResult: true,
36+
},
37+
{
38+
// E.g. "connection refused"
39+
name: "OpErr",
40+
err: &net.OpError{
41+
Op: "dial",
42+
Net: "tcp",
43+
Source: nil,
44+
Addr: nil,
45+
Err: &os.SyscallError{},
46+
},
47+
expectedResult: true,
48+
},
49+
{
50+
name: "OpaqueError",
51+
err: xerrors.Errorf("I'm opaque!"),
52+
expectedResult: false,
53+
},
54+
}
55+
56+
for _, c := range cases {
57+
c := c
58+
59+
t.Run(c.name, func(t *testing.T) {
60+
t.Parallel()
61+
62+
require.Equal(t, c.expectedResult, codersdk.IsConnectionErr(c.err))
63+
})
64+
}
65+
}

site/src/api/typesGenerated.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ export interface PutExtendWorkspaceRequest {
250250
readonly deadline: string
251251
}
252252

253-
// From codersdk/error.go:4:6
253+
// From codersdk/error.go:10:6
254254
export interface Response {
255255
readonly message: string
256256
readonly detail?: string
@@ -386,7 +386,7 @@ export interface UsersRequest extends Pagination {
386386
readonly q?: string
387387
}
388388

389-
// From codersdk/error.go:24:6
389+
// From codersdk/error.go:30:6
390390
export interface ValidationError {
391391
readonly field: string
392392
readonly detail: string

0 commit comments

Comments
 (0)