diff options
Diffstat (limited to 'client/go')
-rw-r--r-- | client/go/internal/cli/cmd/cert_test.go | 12 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/deploy_test.go | 4 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/prod.go | 2 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/prod_test.go | 47 | ||||
-rw-r--r-- | client/go/internal/cli/cmd/testdata/applications/withTarget/target/application/.gitkeep | 0 | ||||
-rw-r--r-- | client/go/internal/vespa/application.go | 120 | ||||
-rw-r--r-- | client/go/internal/vespa/deploy_test.go | 14 |
7 files changed, 98 insertions, 101 deletions
diff --git a/client/go/internal/cli/cmd/cert_test.go b/client/go/internal/cli/cmd/cert_test.go index 0a20ab8eb1a..491857f2bf2 100644 --- a/client/go/internal/cli/cmd/cert_test.go +++ b/client/go/internal/cli/cmd/cert_test.go @@ -50,12 +50,6 @@ func testCert(t *testing.T, subcommand []string) { } func TestCertCompressedPackage(t *testing.T) { - t.Run("auth cert", func(t *testing.T) { - testCertCompressedPackage(t, []string{"auth", "cert"}) - }) -} - -func testCertCompressedPackage(t *testing.T, subcommand []string) { _, pkgDir := mock.ApplicationPackageDir(t, true, false) zipFile := filepath.Join(pkgDir, "target", "application.zip") err := os.MkdirAll(filepath.Dir(zipFile), 0755) @@ -68,16 +62,14 @@ func testCertCompressedPackage(t *testing.T, subcommand []string) { stdout.Reset() stderr.Reset() - args := append(subcommand, pkgDir) - err = cli.Run(args...) + err = cli.Run("auth", "cert", zipFile) assert.NotNil(t, err) assert.Contains(t, stderr.String(), "Error: cannot add certificate to compressed application package") err = os.Remove(zipFile) assert.Nil(t, err) - args = append(subcommand, "-f", pkgDir) - err = cli.Run(args...) + err = cli.Run("auth", "cert", "-f", pkgDir) assert.Nil(t, err) assert.Contains(t, stdout.String(), "Success: Certificate written to") assert.Contains(t, stdout.String(), "Success: Private key written to") diff --git a/client/go/internal/cli/cmd/deploy_test.go b/client/go/internal/cli/cmd/deploy_test.go index d578b2a4629..d2aa52bc08f 100644 --- a/client/go/internal/cli/cmd/deploy_test.go +++ b/client/go/internal/cli/cmd/deploy_test.go @@ -133,7 +133,7 @@ func TestDeployApplicationDirectoryWithSource(t *testing.T) { } func TestDeployApplicationDirectoryWithPomAndTarget(t *testing.T) { - assertDeploy("testdata/applications/withTarget/target/application.zip", + assertDeploy("testdata/applications/withTarget/target/application", []string{"deploy", "--wait=0", "testdata/applications/withTarget"}, t) } @@ -141,7 +141,7 @@ func TestDeployApplicationDirectoryWithPomAndEmptyTarget(t *testing.T) { cli, _, stderr := newTestCLI(t) assert.NotNil(t, cli.Run("deploy", "--wait=0", "testdata/applications/withEmptyTarget")) assert.Equal(t, - "Error: found pom.xml, but target/application.zip does not exist: run 'mvn package' first\n", + "Error: found pom.xml, but testdata/applications/withEmptyTarget/target/application does not exist: run 'mvn package' first\n", stderr.String()) } diff --git a/client/go/internal/cli/cmd/prod.go b/client/go/internal/cli/cmd/prod.go index 1a2f88311b6..5337a346654 100644 --- a/client/go/internal/cli/cmd/prod.go +++ b/client/go/internal/cli/cmd/prod.go @@ -147,7 +147,7 @@ $ vespa prod deploy`, if err != nil { return err } - if !pkg.HasDeployment() { + if !pkg.HasDeploymentSpec() { return errHint(fmt.Errorf("no deployment.xml found"), "Try creating one with vespa prod init") } if err := verifyTests(cli, pkg); err != nil { diff --git a/client/go/internal/cli/cmd/prod_test.go b/client/go/internal/cli/cmd/prod_test.go index 944f09b3d42..4cca54a76c8 100644 --- a/client/go/internal/cli/cmd/prod_test.go +++ b/client/go/internal/cli/cmd/prod_test.go @@ -50,12 +50,12 @@ func TestProdInit(t *testing.T) { assert.Nil(t, cli.Run("prod", "init", pkgDir)) // Verify contents - deploymentPath := filepath.Join(pkgDir, "src", "main", "application", "deployment.xml") + deploymentPath := filepath.Join(pkgDir, "deployment.xml") deploymentXML := readFileString(t, deploymentPath) assert.Contains(t, deploymentXML, `<region>aws-us-west-2a</region>`) assert.Contains(t, deploymentXML, `<region>aws-eu-west-1a</region>`) - servicesPath := filepath.Join(pkgDir, "src", "main", "application", "services.xml") + servicesPath := filepath.Join(pkgDir, "services.xml") servicesXML := readFileString(t, servicesPath) containerFragment := `<container id="qrs" version="1.0"> <document-api></document-api> @@ -80,6 +80,7 @@ func TestProdInit(t *testing.T) { } func readFileString(t *testing.T, filename string) string { + t.Helper() content, err := os.ReadFile(filename) if err != nil { t.Fatal(err) @@ -88,12 +89,15 @@ func readFileString(t *testing.T, filename string) string { } func createApplication(t *testing.T, pkgDir string, java bool, skipTests bool) { - appDir := filepath.Join(pkgDir, "src", "main", "application") - targetDir := filepath.Join(pkgDir, "target") + appDir := pkgDir + testsDir := pkgDir + if java { + appDir = filepath.Join(pkgDir, "target", "application") + testsDir = filepath.Join(pkgDir, "target", "application-test") + } if err := os.MkdirAll(appDir, 0755); err != nil { t.Fatal(err) } - deploymentXML := `<deployment version="1.0"> <prod> <region>aws-us-east-1c</region> @@ -102,7 +106,6 @@ func createApplication(t *testing.T, pkgDir string, java bool, skipTests bool) { if err := os.WriteFile(filepath.Join(appDir, "deployment.xml"), []byte(deploymentXML), 0644); err != nil { t.Fatal(err) } - servicesXML := `<services version="1.0" xmlns:deploy="vespa" xmlns:preprocess="properties"> <container id="qrs" version="1.0"> <document-api/> @@ -123,19 +126,16 @@ func createApplication(t *testing.T, pkgDir string, java bool, skipTests bool) { 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 skipTests { - t.Fatalf("skipTests=%t has no effect when java=%t", skipTests, java) - } if err := os.WriteFile(filepath.Join(pkgDir, "pom.xml"), []byte(""), 0644); err != nil { t.Fatal(err) } - } else if !skipTests { - testsDir := filepath.Join(pkgDir, "src", "test", "application", "tests") - testBytes, _ := io.ReadAll(strings.NewReader("{\"steps\":[{}]}")) + } + if !skipTests { + if err := os.MkdirAll(testsDir, 0755); err != nil { + t.Fatal(err) + } + testBytes := []byte("{\"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) @@ -203,23 +203,17 @@ func TestProdDeployWithJava(t *testing.T) { httpClient := &mock.HTTPClient{} httpClient.NextResponseString(200, `ok`) - cli, stdout, _ := newTestCLI(t, "CI=true") + cli, stdout, stderr := 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", "--no-add")) - // 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", "deploy", pkgDir)) + assert.Nil(t, cli.Run("prod", "deploy", "--add-cert", pkgDir)) + assert.Equal(t, "", stderr.String()) assert.Contains(t, stdout.String(), "Success: Deployed") assert.Contains(t, stdout.String(), "See https://console.vespa-cloud.com/tenant/t1/application/a1/prod/deployment for deployment progress") } @@ -240,11 +234,8 @@ func TestProdDeployInvalidZip(t *testing.T) { // Copy an invalid application package containing relative file names testAppDir := filepath.Join("testdata", "applications", "withInvalidEntries", "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) - assert.NotNil(t, cli.Run("prod", "deploy", pkgDir)) + assert.NotNil(t, cli.Run("prod", "deploy", zipFile)) assert.Equal(t, "Error: found invalid path inside zip: ../../../../../../../tmp/foo\n", stderr.String()) } diff --git a/client/go/internal/cli/cmd/testdata/applications/withTarget/target/application/.gitkeep b/client/go/internal/cli/cmd/testdata/applications/withTarget/target/application/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/client/go/internal/cli/cmd/testdata/applications/withTarget/target/application/.gitkeep diff --git a/client/go/internal/vespa/application.go b/client/go/internal/vespa/application.go index b6b5b9427b3..dd1b580517b 100644 --- a/client/go/internal/vespa/application.go +++ b/client/go/internal/vespa/application.go @@ -17,49 +17,57 @@ type ApplicationPackage struct { TestPath string } -func (ap *ApplicationPackage) HasCertificate() bool { - return ap.hasFile(filepath.Join("security", "clients.pem"), "security/clients.pem") -} +func (ap *ApplicationPackage) HasCertificate() bool { return ap.hasFile("security", "clients.pem") } -func (ap *ApplicationPackage) HasDeployment() bool { return ap.hasFile("deployment.xml", "") } +func (ap *ApplicationPackage) HasDeploymentSpec() bool { return ap.hasFile("deployment.xml", "") } -func (ap *ApplicationPackage) hasFile(filename, zipName string) bool { - if zipName == "" { - zipName = filename +func (ap *ApplicationPackage) hasFile(pathSegment ...string) bool { + if !ap.IsZip() { + return util.PathExists(filepath.Join(append([]string{ap.Path}, pathSegment...)...)) } - if ap.IsZip() { - r, err := zip.OpenReader(ap.Path) - if err != nil { - return false - } - defer r.Close() - for _, f := range r.File { - if f.Name == zipName { - return true - } - } + zipName := filepath.Join(pathSegment...) + return ap.hasZipEntry(func(name string) bool { return zipName == name }) +} + +func (ap *ApplicationPackage) hasZipEntry(matcher func(zipName string) bool) bool { + r, err := zip.OpenReader(ap.Path) + if err != nil { return false } - return util.PathExists(filepath.Join(ap.Path, filename)) + defer r.Close() + for _, f := range r.File { + if matcher(f.Name) { + return true + } + } + return false } func (ap *ApplicationPackage) IsZip() bool { return isZip(ap.Path) } func (ap *ApplicationPackage) IsJava() bool { if ap.IsZip() { - r, err := zip.OpenReader(ap.Path) - if err != nil { - return false - } - defer r.Close() - for _, f := range r.File { - if filepath.Ext(f.Name) == ".jar" { - return true - } + return ap.hasZipEntry(func(name string) bool { return filepath.Ext(name) == ".jar" }) + } + return util.PathExists(filepath.Join(ap.Path, "pom.xml")) +} + +func (ap *ApplicationPackage) Validate() error { + if !ap.IsZip() { + return nil + } + invalidPath := "" + invalid := ap.hasZipEntry(func(name string) bool { + if !validPath(name) { + invalidPath = name + return true } return false + }) + if invalid { + return fmt.Errorf("found invalid path inside zip: %s", invalidPath) } - return util.PathExists(filepath.Join(ap.Path, "pom.xml")) + return nil } func isZip(filename string) bool { return filepath.Ext(filename) == ".zip" } @@ -166,9 +174,6 @@ func (ap *ApplicationPackage) Unzip(test bool) (string, error) { } defer f.Close() for _, f := range f.File { - if !validPath(f.Name) { - return "", fmt.Errorf("found invalid path inside zip: %s", f.Name) - } dst := filepath.Join(tmp, f.Name) if f.FileInfo().IsDir() { if err := os.Mkdir(dst, f.FileInfo().Mode()); err != nil { @@ -220,36 +225,42 @@ func copyFile(src *zip.File, dst string) error { // Package to use is preferred in this order: // 1. Given path, if it's a zip // 2. target/application -// 3. target/application.zip -// 4. src/main/application -// 5. Given path, if it contains services.xml +// 3. src/main/application +// 4. Given path, if it contains services.xml func FindApplicationPackage(zipOrDir string, requirePackaging bool) (ApplicationPackage, error) { + pkg, err := findApplicationPackage(zipOrDir, requirePackaging) + if err != nil { + return ApplicationPackage{}, err + } + if err := pkg.Validate(); err != nil { + return ApplicationPackage{}, err + } + return pkg, nil +} + +func findApplicationPackage(zipOrDir string, requirePackaging bool) (ApplicationPackage, error) { if isZip(zipOrDir) { return ApplicationPackage{Path: zipOrDir}, nil } - // Prefer uncompressed application because this allows us to add security/clients.pem to the package on-demand - if path := filepath.Join(zipOrDir, "target", "application"); util.PathExists(path) { - return ApplicationPackage{Path: path}, nil - } - appZip := filepath.Join(zipOrDir, "target", "application.zip") - if util.PathExists(filepath.Join(zipOrDir, "pom.xml")) || util.PathExists(appZip) { - if util.PathExists(appZip) { - if testZip := filepath.Join(zipOrDir, "target", "application-test.zip"); util.PathExists(testZip) { - return ApplicationPackage{Path: appZip, TestPath: testZip}, nil - } - return ApplicationPackage{Path: appZip}, nil + // Pre-packaged application. We prefer the uncompressed application because this allows us to add + // security/clients.pem to the package on-demand + hasPOM := util.PathExists(filepath.Join(zipOrDir, "pom.xml")) + if hasPOM { + path := filepath.Join(zipOrDir, "target", "application") + if util.PathExists(path) { + testPath := existingPath(filepath.Join(zipOrDir, "target", "application-test")) + return ApplicationPackage{Path: path, TestPath: testPath}, nil } if requirePackaging { - return ApplicationPackage{}, errors.New("found pom.xml, but target/application.zip does not exist: run 'mvn package' first") + return ApplicationPackage{}, fmt.Errorf("found pom.xml, but %s does not exist: run 'mvn package' first", path) } } + // Application with Maven directory structure, but with no POM or no hard requirement on packaging if path := filepath.Join(zipOrDir, "src", "main", "application"); util.PathExists(path) { - testPath := "" - if d := filepath.Join(zipOrDir, "src", "test", "application"); util.PathExists(d) { - testPath = d - } + testPath := existingPath(filepath.Join(zipOrDir, "src", "test", "application")) return ApplicationPackage{Path: path, TestPath: testPath}, nil } + // Application without Java components if util.PathExists(filepath.Join(zipOrDir, "services.xml")) { testPath := "" if util.PathExists(filepath.Join(zipOrDir, "tests")) { @@ -259,3 +270,10 @@ func FindApplicationPackage(zipOrDir string, requirePackaging bool) (Application } return ApplicationPackage{}, fmt.Errorf("could not find an application package source in '%s'", zipOrDir) } + +func existingPath(path string) string { + if util.PathExists(path) { + return path + } + return "" +} diff --git a/client/go/internal/vespa/deploy_test.go b/client/go/internal/vespa/deploy_test.go index 693d4527624..ff278578e8a 100644 --- a/client/go/internal/vespa/deploy_test.go +++ b/client/go/internal/vespa/deploy_test.go @@ -151,18 +151,14 @@ func TestFindApplicationPackage(t *testing.T) { fail: true, }) assertFindApplicationPackage(t, dir, pkgFixture{ - expectedPath: filepath.Join(dir, "target", "application.zip"), - existingFiles: []string{filepath.Join(dir, "pom.xml"), filepath.Join(dir, "target", "application.zip")}, - requirePackaging: true, - }) - assertFindApplicationPackage(t, dir, pkgFixture{ - expectedPath: filepath.Join(dir, "target", "application.zip"), - existingFiles: []string{filepath.Join(dir, "target", "application.zip")}, - }) - assertFindApplicationPackage(t, dir, pkgFixture{ expectedPath: filepath.Join(dir, "target", "application"), existingFiles: []string{filepath.Join(dir, "target", "application"), filepath.Join(dir, "target", "application.zip")}, }) + assertFindApplicationPackage(t, dir, pkgFixture{ + expectedPath: filepath.Join(dir, "target", "application"), + expectedTestPath: filepath.Join(dir, "target", "application-test"), + existingFiles: []string{filepath.Join(dir, "target", "application"), filepath.Join(dir, "target", "application-test")}, + }) zip := filepath.Join(dir, "myapp.zip") assertFindApplicationPackage(t, zip, pkgFixture{ expectedPath: zip, |