diff options
Diffstat (limited to 'client/go/internal/cli/cmd/status_test.go')
-rw-r--r-- | client/go/internal/cli/cmd/status_test.go | 193 |
1 files changed, 152 insertions, 41 deletions
diff --git a/client/go/internal/cli/cmd/status_test.go b/client/go/internal/cli/cmd/status_test.go index 76efea55503..36f51ff5073 100644 --- a/client/go/internal/cli/cmd/status_test.go +++ b/client/go/internal/cli/cmd/status_test.go @@ -5,10 +5,12 @@ package cmd import ( + "io" "testing" "github.com/stretchr/testify/assert" "github.com/vespa-engine/vespa/client/go/internal/mock" + "github.com/vespa-engine/vespa/client/go/internal/vespa" ) func TestStatusDeployCommand(t *testing.T) { @@ -23,63 +25,184 @@ func TestStatusDeployCommandWithLocalTarget(t *testing.T) { assertDeployStatus("http://127.0.0.1:19071", []string{"-t", "local"}, t) } -func TestStatusQueryCommand(t *testing.T) { - assertQueryStatus("http://127.0.0.1:8080", []string{}, t) +func TestStatusCommand(t *testing.T) { + assertStatus("http://127.0.0.1:8080", []string{}, t) } -func TestStatusQueryCommandWithUrlTarget(t *testing.T) { - assertQueryStatus("http://mycontainertarget:8080", []string{"-t", "http://mycontainertarget:8080"}, t) +func TestStatusCommandMultiCluster(t *testing.T) { + client := &mock.HTTPClient{} + cli, stdout, stderr := newTestCLI(t) + cli.httpClient = client + + mockServiceStatus(client) + assert.NotNil(t, cli.Run("status")) + assert.Equal(t, "Error: no services exist\nHint: Deployment may not be ready yet\nHint: Try 'vespa status deployment'\n", stderr.String()) + + mockServiceStatus(client, "foo", "bar") + assert.Nil(t, cli.Run("status")) + assert.Equal(t, `Container bar at http://127.0.0.1:8080 is ready +Container foo at http://127.0.0.1:8080 is ready +`, stdout.String()) + + stdout.Reset() + mockServiceStatus(client, "foo", "bar") + assert.Nil(t, cli.Run("status", "--cluster", "foo")) + assert.Equal(t, "Container foo at http://127.0.0.1:8080 is ready\n", stdout.String()) +} + +func TestStatusCommandWithUrlTarget(t *testing.T) { + assertStatus("http://mycontainertarget:8080", []string{"-t", "http://mycontainertarget:8080"}, t) +} + +func TestStatusCommandWithLocalTarget(t *testing.T) { + assertStatus("http://127.0.0.1:8080", []string{"-t", "local"}, t) +} + +func TestStatusError(t *testing.T) { + client := &mock.HTTPClient{} + mockServiceStatus(client, "default") + client.NextStatus(500) + cli, _, stderr := newTestCLI(t) + cli.httpClient = client + assert.NotNil(t, cli.Run("status", "container")) + assert.Equal(t, + "Error: unhealthy container default: status 500 at http://127.0.0.1:8080/ApplicationStatus: wait timed out\n", + stderr.String()) + + stderr.Reset() + client.NextResponseError(io.EOF) + assert.NotNil(t, cli.Run("status", "container", "-t", "http://example.com")) + assert.Equal(t, + "Error: unhealthy container at http://example.com/ApplicationStatus: EOF\n", + stderr.String()) } -func TestStatusQueryCommandWithLocalTarget(t *testing.T) { - assertQueryStatus("http://127.0.0.1:8080", []string{"-t", "local"}, t) +func TestStatusLocalDeployment(t *testing.T) { + client := &mock.HTTPClient{} + cli, stdout, stderr := newTestCLI(t) + cli.httpClient = client + resp := mock.HTTPResponse{ + URI: "/application/v2/tenant/default/application/default/environment/prod/region/default/instance/default/serviceconverge", + Status: 200, + } + // Latest generation + resp.Body = []byte(`{"currentGeneration": 42, "converged": true}`) + client.NextResponse(resp) + assert.Nil(t, cli.Run("status", "deployment")) + assert.Equal(t, "", stderr.String()) + assert.Equal(t, "Deployment is ready on config generation 42\n", stdout.String()) + + // Latest generation without convergence + resp.Body = []byte(`{"currentGeneration": 42, "converged": false}`) + client.NextResponse(resp) + assert.NotNil(t, cli.Run("status", "deployment")) + assert.Equal(t, "Error: deployment not converged on latest generation after waiting 0s: wait timed out\n", stderr.String()) + + // Explicit generation + stderr.Reset() + client.NextResponse(resp) + assert.NotNil(t, cli.Run("status", "deployment", "41")) + assert.Equal(t, "Error: deployment not converged on generation 41 after waiting 0s: wait timed out\n", stderr.String()) } -func TestStatusDocumentCommandWithLocalTarget(t *testing.T) { - assertDocumentStatus("http://127.0.0.1:8080", []string{"-t", "local"}, t) +func TestStatusCloudDeployment(t *testing.T) { + cli, stdout, stderr := newTestCLI(t, "CI=true") + app := vespa.ApplicationID{Tenant: "t1", Application: "a1", Instance: "i1"} + assert.Nil(t, cli.Run("config", "set", "application", app.String())) + assert.Nil(t, cli.Run("config", "set", "target", "cloud")) + assert.Nil(t, cli.Run("config", "set", "zone", "dev.us-north-1")) + assert.Nil(t, cli.Run("auth", "api-key")) + stdout.Reset() + client := &mock.HTTPClient{} + cli.httpClient = client + // Latest run + client.NextResponse(mock.HTTPResponse{ + URI: "/application/v4/tenant/t1/application/a1/instance/i1/job/dev-us-north-1?limit=1", + Status: 200, + Body: []byte(`{"runs": [{"id": 1337}]}`), + }) + client.NextResponse(mock.HTTPResponse{ + URI: "/application/v4/tenant/t1/application/a1/instance/i1/job/dev-us-north-1/run/1337?after=-1", + Status: 200, + Body: []byte(`{"active": false, "status": "success"}`), + }) + assert.Nil(t, cli.Run("status", "deployment")) + assert.Equal(t, "", stderr.String()) + assert.Equal(t, + "Deployment run 1337 has completed\nSee https://console.vespa-cloud.com/tenant/t1/application/a1/dev/instance/i1/job/dev-us-north-1/run/1337 for more details\n", + stdout.String()) + // Explicit run + client.NextResponse(mock.HTTPResponse{ + URI: "/application/v4/tenant/t1/application/a1/instance/i1/job/dev-us-north-1/run/42?after=-1", + Status: 200, + Body: []byte(`{"active": false, "status": "failure"}`), + }) + assert.NotNil(t, cli.Run("status", "deployment", "42")) + assert.Equal(t, "Error: deployment run 42 incomplete after waiting 0s: run 42 ended with unsuccessful status: failure\n", stderr.String()) } -func TestStatusErrorResponse(t *testing.T) { - assertQueryStatusError("http://127.0.0.1:8080", []string{}, t) +func isLocalTarget(args []string) bool { + for i := 0; i < len(args)-1; i++ { + if args[i] == "-t" { + return args[i+1] == "local" + } + } + return true // local is default } -func assertDeployStatus(target string, args []string, t *testing.T) { +func assertDeployStatus(expectedTarget string, args []string, t *testing.T) { + t.Helper() client := &mock.HTTPClient{} + client.NextResponse(mock.HTTPResponse{ + URI: "/status.html", + Status: 200, + }) cli, stdout, _ := newTestCLI(t) cli.httpClient = client statusArgs := []string{"status", "deploy"} assert.Nil(t, cli.Run(append(statusArgs, args...)...)) assert.Equal(t, - "Deploy API at "+target+" is ready\n", - stdout.String(), - "vespa status config-server") - assert.Equal(t, target+"/status.html", client.LastRequest.URL.String()) + "Deploy API at "+expectedTarget+" is ready\n", + stdout.String()) + assert.Equal(t, expectedTarget+"/status.html", client.LastRequest.URL.String()) } -func assertQueryStatus(target string, args []string, t *testing.T) { +func assertStatus(expectedTarget string, args []string, t *testing.T) { + t.Helper() client := &mock.HTTPClient{} + clusterName := "" + for i := 0; i < 2; i++ { + if isLocalTarget(args) { + clusterName = "foo" + mockServiceStatus(client, clusterName) + } + client.NextResponse(mock.HTTPResponse{URI: "/ApplicationStatus", Status: 200}) + } cli, stdout, _ := newTestCLI(t) cli.httpClient = client - statusArgs := []string{"status", "query"} + statusArgs := []string{"status"} assert.Nil(t, cli.Run(append(statusArgs, args...)...)) - assert.Equal(t, - "Container (query API) at "+target+" is ready\n", - stdout.String(), - "vespa status container") - assert.Equal(t, target+"/ApplicationStatus", client.LastRequest.URL.String()) - - statusArgs = []string{"status"} + prefix := "Container" + if clusterName != "" { + prefix += " " + clusterName + } + assert.Equal(t, prefix+" at "+expectedTarget+" is ready\n", stdout.String()) + assert.Equal(t, expectedTarget+"/ApplicationStatus", client.LastRequest.URL.String()) + + // Test legacy command + statusArgs = []string{"status query"} stdout.Reset() assert.Nil(t, cli.Run(append(statusArgs, args...)...)) - assert.Equal(t, - "Container (query API) at "+target+" is ready\n", - stdout.String(), - "vespa status (the default)") - assert.Equal(t, target+"/ApplicationStatus", client.LastRequest.URL.String()) + assert.Equal(t, prefix+" at "+expectedTarget+" is ready\n", stdout.String()) + assert.Equal(t, expectedTarget+"/ApplicationStatus", client.LastRequest.URL.String()) } func assertDocumentStatus(target string, args []string, t *testing.T) { + t.Helper() client := &mock.HTTPClient{} + if isLocalTarget(args) { + mockServiceStatus(client, "default") + } cli, stdout, _ := newTestCLI(t) cli.httpClient = client assert.Nil(t, cli.Run("status", "document")) @@ -89,15 +212,3 @@ func assertDocumentStatus(target string, args []string, t *testing.T) { "vespa status container") assert.Equal(t, target+"/ApplicationStatus", client.LastRequest.URL.String()) } - -func assertQueryStatusError(target string, args []string, t *testing.T) { - client := &mock.HTTPClient{} - client.NextStatus(500) - cli, _, stderr := newTestCLI(t) - cli.httpClient = client - assert.NotNil(t, cli.Run("status", "container")) - assert.Equal(t, - "Error: Container (query API) at "+target+" is not ready: status 500\n", - stderr.String(), - "vespa status container") -} |