diff --git a/cli/login_test.go b/cli/login_test.go index 3bda6bcd1d..8150dc5d94 100644 --- a/cli/login_test.go +++ b/cli/login_test.go @@ -3,6 +3,8 @@ package cli_test import ( "context" "fmt" + "net/http" + "net/http/httptest" "runtime" "testing" @@ -36,6 +38,39 @@ func TestLogin(t *testing.T) { require.ErrorContains(t, err, errMsg) }) + t.Run("InitialUserNonCoderURLFail", func(t *testing.T) { + t.Parallel() + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte("Not Found")) + })) + defer ts.Close() + + badLoginURL := ts.URL + root, _ := clitest.New(t, "login", badLoginURL) + err := root.Run() + errMsg := fmt.Sprintf("Failed to check server %q for first user, is the URL correct and is coder accessible from your browser?", badLoginURL) + require.ErrorContains(t, err, errMsg) + }) + + t.Run("InitialUserNonCoderURLSuccess", func(t *testing.T) { + t.Parallel() + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Coder-Build-Version", "something") + w.WriteHeader(http.StatusNotFound) + w.Write([]byte("Not Found")) + })) + defer ts.Close() + + badLoginURL := ts.URL + root, _ := clitest.New(t, "login", badLoginURL) + err := root.Run() + // this means we passed the check for a valid coder server + require.ErrorContains(t, err, "the initial user cannot be created in non-interactive mode") + }) + t.Run("InitialUserTTY", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) diff --git a/codersdk/users.go b/codersdk/users.go index c11846ebda..de8d1565d5 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -190,7 +190,15 @@ func (c *Client) HasFirstUser(ctx context.Context) (bool, error) { return false, err } defer res.Body.Close() + if res.StatusCode == http.StatusNotFound { + // ensure we are talking to coder and not + // some other service that returns 404 + v := res.Header.Get("X-Coder-Build-Version") + if v == "" { + return false, xerrors.Errorf("missing build version header, not a coder instance") + } + return false, nil } if res.StatusCode != http.StatusOK {