diff options
author | Martin Polden <mpolden@mpolden.no> | 2022-03-03 10:33:42 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-03 10:33:42 +0100 |
commit | d1a257211a98e1ca80ff7f929dd35262caa40bec (patch) | |
tree | d9dfe003e41753169456b640c1b7546ae18e5ccd /client | |
parent | ce7024db1a6772d5716157c5850fb8bb6bafe57d (diff) | |
parent | 003ac733ee70daf3354f9aa5fdb52239b1b97b6c (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.go | 34 | ||||
-rw-r--r-- | client/go/vespa/deploy.go | 69 |
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 { |