summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2022-03-03 10:33:42 +0100
committerGitHub <noreply@github.com>2022-03-03 10:33:42 +0100
commitd1a257211a98e1ca80ff7f929dd35262caa40bec (patch)
treed9dfe003e41753169456b640c1b7546ae18e5ccd /client
parentce7024db1a6772d5716157c5850fb8bb6bafe57d (diff)
parent003ac733ee70daf3354f9aa5fdb52239b1b97b6c (diff)
Merge pull request #21506 from vespa-engine/ean/print-config-change-requirements
Print log lines sent as response to Application Prepare request
Diffstat (limited to 'client')
-rw-r--r--client/go/cmd/deploy.go34
-rw-r--r--client/go/vespa/deploy.go69
2 files changed, 70 insertions, 33 deletions
diff --git a/client/go/cmd/deploy.go b/client/go/cmd/deploy.go
index 207a0177de8..43b3abcbee9 100644
--- a/client/go/cmd/deploy.go
+++ b/client/go/cmd/deploy.go
@@ -70,9 +70,9 @@ $ vespa deploy -t cloud -z perf.aws-us-east-1c`,
return err
}
- var sessionOrRunID int64
+ var result vespa.PrepareResult
err = util.Spinner(stderr, "Uploading application package ...", func() error {
- sessionOrRunID, err = vespa.Deploy(opts)
+ result, err = vespa.Deploy(opts)
return err
})
if err != nil {
@@ -81,9 +81,10 @@ $ vespa deploy -t cloud -z perf.aws-us-east-1c`,
log.Println()
if opts.IsCloud() {
- printSuccess("Triggered deployment of ", color.Cyan(pkg.Path), " with run ID ", color.Cyan(sessionOrRunID))
+ printSuccess("Triggered deployment of ", color.Cyan(pkg.Path), " with run ID ", color.Cyan(result.ID))
} else {
printSuccess("Deployed ", color.Cyan(pkg.Path))
+ printPrepareLog(result)
}
if opts.IsCloud() {
log.Printf("\nUse %s for deployment status, or follow this deployment at", color.Cyan("vespa status"))
@@ -91,9 +92,9 @@ $ vespa deploy -t cloud -z perf.aws-us-east-1c`,
opts.Target.Deployment().System.ConsoleURL,
opts.Target.Deployment().Application.Tenant, opts.Target.Deployment().Application.Application, opts.Target.Deployment().Application.Instance,
opts.Target.Deployment().Zone.Environment, opts.Target.Deployment().Zone.Region,
- sessionOrRunID)))
+ result.ID)))
}
- return waitForQueryService(sessionOrRunID)
+ return waitForQueryService(result.ID)
},
}
@@ -116,9 +117,9 @@ var prepareCmd = &cobra.Command{
if err != nil {
return err
}
- var sessionID int64
+ var result vespa.PrepareResult
err = util.Spinner(stderr, "Uploading application package ...", func() error {
- sessionID, err = vespa.Prepare(vespa.DeploymentOptions{
+ result, err = vespa.Prepare(vespa.DeploymentOptions{
ApplicationPackage: pkg,
Target: target,
})
@@ -127,10 +128,11 @@ var prepareCmd = &cobra.Command{
if err != nil {
return err
}
- if err := cfg.WriteSessionID(vespa.DefaultApplication, sessionID); err != nil {
+ if err := cfg.WriteSessionID(vespa.DefaultApplication, result.ID); err != nil {
return fmt.Errorf("could not write session id: %w", err)
}
- printSuccess("Prepared ", color.Cyan(pkg.Path), " with session ", sessionID)
+ printSuccess("Prepared ", color.Cyan(pkg.Path), " with session ", result.ID)
+ printPrepareLog(result)
return nil
},
}
@@ -177,3 +179,17 @@ func waitForQueryService(sessionOrRunID int64) error {
}
return nil
}
+
+func printPrepareLog(result vespa.PrepareResult) {
+ for _, entry := range result.LogLines {
+ switch l := entry.Level; l {
+ case "ERROR":
+ fmt.Fprint(stderr, color.Red(l))
+ case "WARNING":
+ fmt.Fprint(stderr, color.Yellow(l))
+ default:
+ fmt.Fprint(stderr, color.Reset(l))
+ }
+ fmt.Fprintf(stderr, " %s", entry.Message)
+ }
+}
diff --git a/client/go/vespa/deploy.go b/client/go/vespa/deploy.go
index bc72ca1ba70..2a6d51c7b9f 100644
--- a/client/go/vespa/deploy.go
+++ b/client/go/vespa/deploy.go
@@ -45,6 +45,18 @@ type DeploymentOptions struct {
Timeout time.Duration
}
+type LogLinePrepareResponse struct {
+ Time int64
+ Level string
+ Message string
+}
+
+type PrepareResult struct {
+ // Session or Run ID
+ ID int64
+ LogLines []LogLinePrepareResponse
+}
+
func (a ApplicationID) String() string {
return fmt.Sprintf("%s.%s.%s", a.Tenant, a.Application, a.Instance)
}
@@ -91,36 +103,36 @@ func ZoneFromString(s string) (ZoneID, error) {
}
// Prepare deployment and return the session ID
-func Prepare(deployment DeploymentOptions) (int64, error) {
+func Prepare(deployment DeploymentOptions) (PrepareResult, error) {
if deployment.IsCloud() {
- return 0, fmt.Errorf("prepare is not supported with %s target", deployment.Target.Type())
+ return PrepareResult{}, fmt.Errorf("prepare is not supported with %s target", deployment.Target.Type())
}
sessionURL, err := deployment.url("/application/v2/tenant/default/session")
if err != nil {
- return 0, err
+ return PrepareResult{}, err
}
- sessionID, err := uploadApplicationPackage(sessionURL, deployment)
+ result, err := uploadApplicationPackage(sessionURL, deployment)
if err != nil {
- return 0, err
+ return PrepareResult{}, err
}
- prepareURL, err := deployment.url(fmt.Sprintf("/application/v2/tenant/default/session/%d/prepared", sessionID))
+ prepareURL, err := deployment.url(fmt.Sprintf("/application/v2/tenant/default/session/%d/prepared", result.ID))
if err != nil {
- return 0, err
+ return PrepareResult{}, err
}
req, err := http.NewRequest("PUT", prepareURL.String(), nil)
if err != nil {
- return 0, err
+ return PrepareResult{}, err
}
serviceDescription := "Deploy service"
response, err := util.HttpDo(req, time.Second*30, serviceDescription)
if err != nil {
- return 0, err
+ return PrepareResult{}, err
}
defer response.Body.Close()
if err := checkResponse(req, response, serviceDescription); err != nil {
- return 0, err
+ return PrepareResult{}, err
}
- return sessionID, nil
+ return result, nil
}
// Activate deployment with sessionID from a past prepare
@@ -145,14 +157,14 @@ func Activate(sessionID int64, deployment DeploymentOptions) error {
return checkResponse(req, response, serviceDescription)
}
-func Deploy(opts DeploymentOptions) (int64, error) {
+func Deploy(opts DeploymentOptions) (PrepareResult, error) {
path := "/application/v2/tenant/default/prepareandactivate"
if opts.IsCloud() {
if err := checkDeploymentOpts(opts); err != nil {
- return 0, err
+ return PrepareResult{}, err
}
if opts.Target.Deployment().Zone.Environment == "" || opts.Target.Deployment().Zone.Region == "" {
- return 0, fmt.Errorf("%s: missing zone", opts)
+ return PrepareResult{}, fmt.Errorf("%s: missing zone", opts)
}
path = fmt.Sprintf("/application/v4/tenant/%s/application/%s/instance/%s/deploy/%s-%s",
opts.Target.Deployment().Application.Tenant,
@@ -163,7 +175,7 @@ func Deploy(opts DeploymentOptions) (int64, error) {
}
u, err := opts.url(path)
if err != nil {
- return 0, err
+ return PrepareResult{}, err
}
return uploadApplicationPackage(u, opts)
}
@@ -246,10 +258,10 @@ func checkDeploymentOpts(opts DeploymentOptions) error {
return nil
}
-func uploadApplicationPackage(url *url.URL, opts DeploymentOptions) (int64, error) {
+func uploadApplicationPackage(url *url.URL, opts DeploymentOptions) (PrepareResult, error) {
zipReader, err := opts.ApplicationPackage.zipReader(false)
if err != nil {
- return 0, err
+ return PrepareResult{}, err
}
header := http.Header{}
header.Add("Content-Type", "application/zip")
@@ -261,33 +273,42 @@ func uploadApplicationPackage(url *url.URL, opts DeploymentOptions) (int64, erro
}
service, err := opts.Target.Service(DeployService, opts.Timeout, 0, "")
if err != nil {
- return 0, err
+ return PrepareResult{}, err
}
keyID := opts.Target.Deployment().Application.SerializedForm()
if err := opts.Target.SignRequest(request, keyID); err != nil {
- return 0, err
+ return PrepareResult{}, err
}
response, err := service.Do(request, time.Minute*10)
if err != nil {
- return 0, err
+ return PrepareResult{}, err
}
defer response.Body.Close()
var jsonResponse struct {
SessionID string `json:"session-id"` // Config server
RunID int64 `json:"run"` // Controller
+
+ Log []LogLinePrepareResponse `json:"log"`
}
jsonResponse.SessionID = "0" // Set a default session ID for responses that don't contain int (e.g. cloud deployment)
if err := checkResponse(request, response, service.Description()); err != nil {
- return 0, err
+ return PrepareResult{}, err
}
jsonDec := json.NewDecoder(response.Body)
jsonDec.Decode(&jsonResponse) // Ignore error in case this is a non-JSON response
- if jsonResponse.RunID > 0 {
- return jsonResponse.RunID, nil
+ id := jsonResponse.RunID
+ if id == 0 {
+ id, err = strconv.ParseInt(jsonResponse.SessionID, 10, 64)
+ if err != nil {
+ return PrepareResult{}, err
+ }
}
- return strconv.ParseInt(jsonResponse.SessionID, 10, 64)
+ return PrepareResult{
+ ID: id,
+ LogLines: jsonResponse.Log,
+ }, err
}
func checkResponse(req *http.Request, response *http.Response, serviceDescription string) error {