summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2021-08-31 11:05:32 +0200
committerJon Bratseth <bratseth@gmail.com>2021-08-31 11:05:32 +0200
commit2ded6dbdc3cab62862c1ce448c1903cab9182916 (patch)
tree2f76136936777162b30530dcd36ee42d3c7ab9db /client
parent7f4537e1cad5ce9b0e1031697af3680cd348a8e0 (diff)
Extract application package error
Diffstat (limited to 'client')
-rw-r--r--client/go/cmd/deploy_test.go29
-rw-r--r--client/go/cmd/document.go3
-rw-r--r--client/go/vespa/deploy.go25
3 files changed, 48 insertions, 9 deletions
diff --git a/client/go/cmd/deploy_test.go b/client/go/cmd/deploy_test.go
index fdd1d9f5613..d4fddf11f99 100644
--- a/client/go/cmd/deploy_test.go
+++ b/client/go/cmd/deploy_test.go
@@ -54,8 +54,27 @@ func TestDeployApplicationDirectoryWithPomAndEmptyTarget(t *testing.T) {
executeCommand(t, client, []string{"deploy", "testdata/applications/withEmptyTarget"}, []string{}))
}
-func TestDeployApplicationPackageError(t *testing.T) {
- assertApplicationPackageError(t, 401, "Application package error")
+func TestDeployApplicationPackageErrorWithUnexpectedNonJson(t *testing.T) {
+ assertApplicationPackageError(t, 401,
+ "Raw text error",
+ "Raw text error")
+}
+
+func TestDeployApplicationPackageErrorWithUnexpectedJson(t *testing.T) {
+ assertApplicationPackageError(t, 401,
+ `{
+ "some-unexpected-json": "Invalid XML, error in services.xml: element \"nosuch\" not allowed here"
+}`,
+ `{"some-unexpected-json": "Invalid XML, error in services.xml: element \"nosuch\" not allowed here"}`)
+}
+
+func TestDeployApplicationPackageErrorWithExpectedFormat(t *testing.T) {
+ assertApplicationPackageError(t, 400,
+ "Invalid XML, error in services.xml:\nelement \"nosuch\" not allowed here",
+ `{
+ "error-code": "INVALID_APPLICATION_PACKAGE",
+ "message": "Invalid XML, error in services.xml: element \"nosuch\" not allowed here\n"
+ }`)
}
func TestDeployError(t *testing.T) {
@@ -81,10 +100,10 @@ func assertDeployRequestMade(target string, client *mockHttpClient, t *testing.T
assert.Equal(t, "PK\x03\x04\x14\x00\b", string(buf))
}
-func assertApplicationPackageError(t *testing.T, status int, errorMessage string) {
- client := &mockHttpClient{nextStatus: status, nextBody: errorMessage}
+func assertApplicationPackageError(t *testing.T, status int, expectedMessage string, returnBody string) {
+ client := &mockHttpClient{nextStatus: status, nextBody: returnBody}
assert.Equal(t,
- "Error: Invalid application package (Status "+strconv.Itoa(status)+"):\n"+errorMessage+"\n",
+ "Error: Invalid application package (Status "+strconv.Itoa(status)+")\n\n"+expectedMessage+"\n",
executeCommand(t, client, []string{"deploy", "testdata/applications/withTarget/target/application.zip"}, []string{}))
}
diff --git a/client/go/cmd/document.go b/client/go/cmd/document.go
index 9aa50b60f56..71114fc8df6 100644
--- a/client/go/cmd/document.go
+++ b/client/go/cmd/document.go
@@ -70,7 +70,8 @@ func post(documentId string, jsonFile string) {
fileReader, fileError := os.Open(jsonFile)
if fileError != nil {
- log.Printf("Could not open file at %s: %s", color.Cyan(jsonFile), fileError)
+ log.Print(color.Red("Error: "), "Could not open file '", color.Cyan(jsonFile), "'")
+ log.Print(color.Brown(fileError))
return
}
diff --git a/client/go/vespa/deploy.go b/client/go/vespa/deploy.go
index 037c92b5458..9955c3dfbff 100644
--- a/client/go/vespa/deploy.go
+++ b/client/go/vespa/deploy.go
@@ -6,6 +6,8 @@ package vespa
import (
"archive/zip"
+ "bytes"
+ "encoding/json"
"errors"
"fmt"
"io"
@@ -126,7 +128,7 @@ func Prepare(deployment Deployment) (string, error) {
if deployment.IsCloud() {
return "", fmt.Errorf("%s: prepare is not supported", deployment)
}
- // TODO: This doesn't work. A session ID must be explicitly created and then passed to the prepare call
+ // TODO: Save session id in .vespa
// https://docs.vespa.ai/en/cloudconfig/deploy-rest-api-v2.html
u, err := url.Parse(deployment.TargetURL + "/application/v2/tenant/default/prepare")
if err != nil {
@@ -139,7 +141,7 @@ func Activate(deployment Deployment) (string, error) {
if deployment.IsCloud() {
return "", fmt.Errorf("%s: activate is not supported", deployment)
}
- // TODO: This doesn't work. A session ID must be explicitly created and then passed to the activate call
+ // TODO: Look up session id in .vespa
// https://docs.vespa.ai/en/cloudconfig/deploy-rest-api-v2.html
u, err := url.Parse(deployment.TargetURL + "/application/v2/tenant/default/activate")
if err != nil {
@@ -210,7 +212,7 @@ func postApplicationPackage(url *url.URL, zipReader io.Reader) error {
defer response.Body.Close()
if response.StatusCode/100 == 4 {
- return fmt.Errorf("Invalid application package (%s):\n%s", response.Status, util.ReaderToJSON(response.Body))
+ return fmt.Errorf("Invalid application package (%s)\n\n%s", response.Status, extractError(response.Body))
} else if response.StatusCode != 200 {
return fmt.Errorf("Error from %s at %s (%s):\n%s", strings.ToLower(serviceDescription), request.URL.Host, response.Status, util.ReaderToJSON(response.Body))
}
@@ -270,3 +272,20 @@ func zipDir(dir string, destination string) error {
}
return filepath.Walk(dir, walker)
}
+
+// Returns the error message in the given JSON, or the entire content if it could not be extracted
+func extractError(reader io.Reader) string {
+ responseData := util.ReaderToBytes(reader)
+ var response map[string]interface{}
+ json.Unmarshal(responseData, &response)
+ if response["error-code"] == "INVALID_APPLICATION_PACKAGE" {
+ return strings.ReplaceAll(response["message"].(string), ": ", ":\n")
+ } else {
+ var prettyJSON bytes.Buffer
+ parseError := json.Indent(&prettyJSON, responseData, "", " ")
+ if parseError != nil { // Not JSON: Print plainly
+ return string(responseData)
+ }
+ return string(prettyJSON.Bytes())
+ }
+}