diff options
author | Martin Polden <mpolden@mpolden.no> | 2021-10-06 14:36:27 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2021-10-07 09:33:53 +0200 |
commit | 27df9f15770e537a65466ef1a753dc60b8ec6163 (patch) | |
tree | 61fc60e6c0699ba0ca46885ce03e76be3b3537c4 /client/go/cmd/prod.go | |
parent | a3530f08a4611542f5a318563d96fec63dbf0bb9 (diff) |
Implement vespa prod submit
Diffstat (limited to 'client/go/cmd/prod.go')
-rw-r--r-- | client/go/cmd/prod.go | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/client/go/cmd/prod.go b/client/go/cmd/prod.go index 15d9edc18a7..382ede0fae8 100644 --- a/client/go/cmd/prod.go +++ b/client/go/cmd/prod.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io/ioutil" + "log" "os" "path/filepath" "strings" @@ -20,6 +21,7 @@ import ( func init() { rootCmd.AddCommand(prodCmd) prodCmd.AddCommand(prodInitCmd) + prodCmd.AddCommand(prodSubmitCmd) } var prodCmd = &cobra.Command{ @@ -60,7 +62,7 @@ https://cloud.vespa.ai/en/reference/deployment`, } if pkg.IsZip() { fatalErrHint(fmt.Errorf("Cannot modify compressed application package %s", pkg.Path), - "Try running 'mvn clean' and re-running this command") + "Try running 'mvn clean' and run this command again") return } @@ -95,6 +97,69 @@ https://cloud.vespa.ai/en/reference/deployment`, }, } +var prodSubmitCmd = &cobra.Command{ + Use: "submit", + Short: "Submit your application for production deployment", + Long: `Submit your application for production deployment. + +This commands uploads your application package to Vespa Cloud and deploys it to +the production zones specified in deployment.xml. + +Nodes are allocated to your application according to resources specified in +services.xml. + +While submitting an application from a local development environment is +supported, it's strongly recommended that production deployments are performed +by a continuous build system. + +For more information about production deployments in Vespa Cloud see: +https://cloud.vespa.ai/en/getting-to-production +https://cloud.vespa.ai/en/automated-deployments`, + DisableAutoGenTag: true, + Example: `$ mvn package +$ vespa prod submit`, + Run: func(cmd *cobra.Command, args []string) { + target := getTarget() + if target.Type() != "cloud" { + fatalErr(fmt.Errorf("%s target cannot deploy to Vespa Cloud", target.Type())) + return + } + appSource := applicationSource(args) + pkg, err := vespa.FindApplicationPackage(appSource, true) + if err != nil { + fatalErr(err) + return + } + cfg, err := LoadConfig() + if err != nil { + fatalErr(err, "Could not load config") + return + } + if !pkg.HasDeployment() { + fatalErrHint(fmt.Errorf("No deployment.xml found"), "Try creating one with vespa prod init") + return + } + if !pkg.IsJava() { + // TODO: Loosen this requirement when we start supporting applications with Java in production + fatalErrHint(fmt.Errorf("No jar files found in %s", pkg.Path), "Only applications containing Java components are currently supported") + return + } + isCI := os.Getenv("CI") != "" + if !isCI { + fmt.Fprintln(stderr, color.Yellow("Warning:"), "Submitting from a non-CI environment is discouraged") + printErrHint(nil, "See https://cloud.vespa.ai/en/getting-to-production for best practices") + } + opts := getDeploymentOpts(cfg, pkg, target) + if err := vespa.Submit(opts); err != nil { + fatalErr(err, "Could not submit application for deployment") + } else { + printSuccess("Submitted ", color.Cyan(pkg.Path), " for deployment") + log.Printf("See %s for deployment progress\n", color.Cyan(fmt.Sprintf("%s/tenant/%s/application/%s/prod/deployment", + getConsoleURL(), opts.Deployment.Application.Tenant, opts.Deployment.Application.Application))) + } + }, +} + func writeWithBackup(pkg vespa.ApplicationPackage, filename, contents string) error { dst := filepath.Join(pkg.Path, filename) if util.PathExists(dst) { @@ -133,6 +198,13 @@ func updateRegions(r *bufio.Reader, deploymentXML xml.Deployment) xml.Deployment if err := deploymentXML.Replace("prod", "region", regionElements); err != nil { fatalErr(err, "Could not update region elements in deployment.xml") } + // TODO: Some sample apps come with production <test> elements, but not necessarily working production tests, we + // therefore remove <test> elements here. + // This can be improved by supporting <test> elements in xml package and allow specifying testing as part of + // region prompt, e.g. region1;test,region2 + if err := deploymentXML.Replace("prod", "test", nil); err != nil { + fatalErr(err, "Could not remove test elements in deployment.xml") + } return deploymentXML } @@ -152,7 +224,7 @@ func promptRegions(r *bufio.Reader, deploymentXML xml.Deployment) string { validator := func(input string) error { regions := strings.Split(input, ",") for _, r := range regions { - if !xml.ValidProdRegion(r) { + if !xml.IsProdRegion(r, getSystem()) { return fmt.Errorf("invalid region %s", r) } } |