package cmd import ( "bytes" "io" "os" "path/filepath" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/vespa-engine/vespa/client/go/mock" "github.com/vespa-engine/vespa/client/go/util" "github.com/vespa-engine/vespa/client/go/vespa" ) func TestProdInit(t *testing.T) { pkgDir := filepath.Join(t.TempDir(), "app") createApplication(t, pkgDir, false) answers := []string{ // Regions "invalid input", "aws-us-west-2a,aws-eu-west-1a", // Node count: qrs "invalid input", "4", // Node resources: qrs "invalid input", "auto", // Node count: music "invalid input", "6", // Node resources: music "invalid input", "vcpu=16,memory=64Gb,disk=100Gb", } var buf bytes.Buffer buf.WriteString(strings.Join(answers, "\n") + "\n") cli, _, _ := newTestCLI(t) cli.Stdin = &buf assert.Nil(t, cli.Run("prod", "init", pkgDir)) // Verify contents deploymentPath := filepath.Join(pkgDir, "src", "main", "application", "deployment.xml") deploymentXML := readFileString(t, deploymentPath) assert.Contains(t, deploymentXML, `aws-us-west-2a`) assert.Contains(t, deploymentXML, `aws-eu-west-1a`) servicesPath := filepath.Join(pkgDir, "src", "main", "application", "services.xml") servicesXML := readFileString(t, servicesPath) containerFragment := ` ` assert.Contains(t, servicesXML, containerFragment) contentFragment := ` 2 ` assert.Contains(t, servicesXML, contentFragment) // Backups are created assert.True(t, util.PathExists(deploymentPath+".1.bak")) assert.True(t, util.PathExists(servicesPath+".1.bak")) } func readFileString(t *testing.T, filename string) string { content, err := os.ReadFile(filename) if err != nil { t.Fatal(err) } return string(content) } func createApplication(t *testing.T, pkgDir string, java bool) { appDir := filepath.Join(pkgDir, "src", "main", "application") targetDir := filepath.Join(pkgDir, "target") if err := os.MkdirAll(appDir, 0755); err != nil { t.Fatal(err) } deploymentXML := ` aws-us-east-1c ` if err := os.WriteFile(filepath.Join(appDir, "deployment.xml"), []byte(deploymentXML), 0644); err != nil { t.Fatal(err) } servicesXML := ` 2 ` if err := os.WriteFile(filepath.Join(appDir, "services.xml"), []byte(servicesXML), 0644); err != nil { t.Fatal(err) } if err := os.MkdirAll(targetDir, 0755); err != nil { t.Fatal(err) } if java { if err := os.WriteFile(filepath.Join(pkgDir, "pom.xml"), []byte(""), 0644); err != nil { t.Fatal(err) } } else { testsDir := filepath.Join(pkgDir, "src", "test", "application", "tests") testBytes, _ := io.ReadAll(strings.NewReader("{\"steps\":[{}]}")) writeTest(filepath.Join(testsDir, "system-test", "test.json"), testBytes, t) writeTest(filepath.Join(testsDir, "staging-setup", "test.json"), testBytes, t) writeTest(filepath.Join(testsDir, "staging-test", "test.json"), testBytes, t) } } func writeTest(path string, content []byte, t *testing.T) { if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { t.Fatal(err) } if err := os.WriteFile(path, content, 0644); err != nil { t.Fatal(err) } } func TestProdSubmit(t *testing.T) { pkgDir := filepath.Join(t.TempDir(), "app") createApplication(t, pkgDir, false) httpClient := &mock.HTTPClient{} httpClient.NextResponseString(200, `ok`) cli, stdout, _ := newTestCLI(t, "CI=true") cli.httpClient = httpClient 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("auth", "api-key")) assert.Nil(t, cli.Run("auth", "cert", pkgDir)) // Remove certificate as it's not required for submission (but it must be part of the application package) if path, err := cli.config.privateKeyPath(app); err == nil { os.RemoveAll(path) } else { require.Nil(t, err) } if path, err := cli.config.certificatePath(app); err == nil { os.RemoveAll(path) } else { require.Nil(t, err) } // Zipping requires relative paths, so must let command run from pkgDir, then reset cwd for subsequent tests. if cwd, err := os.Getwd(); err != nil { t.Fatal(err) } else { defer os.Chdir(cwd) } if err := os.Chdir(pkgDir); err != nil { t.Fatal(err) } stdout.Reset() cli.Environment["VESPA_CLI_API_KEY_FILE"] = filepath.Join(cli.config.homeDir, "t1.api-key.pem") assert.Nil(t, cli.Run("prod", "submit")) assert.Contains(t, stdout.String(), "Success: Submitted") assert.Contains(t, stdout.String(), "See https://console.vespa-cloud.com/tenant/t1/application/a1/prod/deployment for deployment progress") } func TestProdSubmitWithJava(t *testing.T) { pkgDir := filepath.Join(t.TempDir(), "app") createApplication(t, pkgDir, true) httpClient := &mock.HTTPClient{} httpClient.NextResponseString(200, `ok`) cli, stdout, _ := newTestCLI(t, "CI=true") cli.httpClient = httpClient assert.Nil(t, cli.Run("config", "set", "application", "t1.a1.i1")) assert.Nil(t, cli.Run("config", "set", "target", "cloud")) assert.Nil(t, cli.Run("auth", "api-key")) assert.Nil(t, cli.Run("auth", "cert", pkgDir)) // Copy an application package pre-assembled with mvn package testAppDir := filepath.Join("testdata", "applications", "withDeployment", "target") zipFile := filepath.Join(testAppDir, "application.zip") copyFile(t, filepath.Join(pkgDir, "target", "application.zip"), zipFile) testZipFile := filepath.Join(testAppDir, "application-test.zip") copyFile(t, filepath.Join(pkgDir, "target", "application-test.zip"), testZipFile) stdout.Reset() cli.Environment["VESPA_CLI_API_KEY_FILE"] = filepath.Join(cli.config.homeDir, "t1.api-key.pem") assert.Nil(t, cli.Run("prod", "submit", pkgDir)) assert.Contains(t, stdout.String(), "Success: Submitted") assert.Contains(t, stdout.String(), "See https://console.vespa-cloud.com/tenant/t1/application/a1/prod/deployment for deployment progress") } func copyFile(t *testing.T, dstFilename, srcFilename string) { dst, err := os.Create(dstFilename) if err != nil { t.Fatal(err) } defer dst.Close() src, err := os.Open(srcFilename) if err != nil { t.Fatal(err) } defer src.Close() if _, err := io.Copy(dst, src); err != nil { t.Fatal(err) } }