Skip to content

Commit 1623fb2

Browse files
authored
Explicitly install packages on system tests (#1281)
This will allow to earlier detect if one is not testing the version they currently have in the working copy. From 8.7.0 version, it builds and install the zip package. On older versions it installs whatever is in the configured package registry. In that case, if the version of the package is not available in the repository, test execution will fail.
1 parent 641f6cf commit 1623fb2

File tree

7 files changed

+231
-209
lines changed

7 files changed

+231
-209
lines changed

cmd/install.go

Lines changed: 24 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,11 @@
55
package cmd
66

77
import (
8-
"fmt"
9-
10-
"github.com/Masterminds/semver/v3"
118
"github.com/pkg/errors"
129
"github.com/spf13/cobra"
1310

14-
"github.com/elastic/package-spec/v2/code/go/pkg/validator"
15-
16-
"github.com/elastic/elastic-package/internal/builder"
1711
"github.com/elastic/elastic-package/internal/cobraext"
1812
"github.com/elastic/elastic-package/internal/kibana"
19-
"github.com/elastic/elastic-package/internal/logger"
2013
"github.com/elastic/elastic-package/internal/packages"
2114
"github.com/elastic/elastic-package/internal/packages/installer"
2215
)
@@ -25,8 +18,6 @@ const installLongDescription = `Use this command to install the package in Kiban
2518
2619
The command uses Kibana API to install the package in Kibana. The package must be exposed via the Package Registry or built locally in zip format so they can be installed using --zip parameter. Zip packages can be installed directly in Kibana >= 8.7.0. More details in this [HOWTO guide](https://github.com/elastic/elastic-package/blob/main/docs/howto/install_package.md).`
2720

28-
var semver8_7_0 = semver.MustParse("8.7.0")
29-
3021
func setupInstallCommand() *cobraext.Command {
3122
cmd := &cobra.Command{
3223
Use: "install",
@@ -60,23 +51,27 @@ func installCommandAction(cmd *cobra.Command, _ []string) error {
6051
if err != nil {
6152
return errors.Wrap(err, "could not create kibana client")
6253
}
63-
kibanaVersion, err := kibanaClient.Version()
64-
if err != nil {
65-
return err
66-
}
67-
v, err := semver.NewVersion(kibanaVersion.Number)
68-
if err != nil {
69-
return fmt.Errorf("invalid Kibana version")
70-
}
7154

72-
installer, err := newInstaller(zipPathFile, packageRootPath, v, skipValidation)
73-
if err != nil {
74-
return err
55+
if zipPathFile == "" && packageRootPath == "" {
56+
var found bool
57+
var err error
58+
packageRootPath, found, err = packages.FindPackageRoot()
59+
if !found {
60+
return errors.New("package root not found")
61+
}
62+
if err != nil {
63+
return errors.Wrap(err, "locating package root failed")
64+
}
7565
}
7666

77-
manifest, err := installer.manifest()
67+
installer, err := installer.NewForPackage(installer.Options{
68+
Kibana: kibanaClient,
69+
RootPath: packageRootPath,
70+
SkipValidation: skipValidation,
71+
ZipPath: zipPathFile,
72+
})
7873
if err != nil {
79-
return err
74+
return errors.Wrap(err, "package installation failed")
8075
}
8176

8277
// Check conditions
@@ -85,6 +80,11 @@ func installCommandAction(cmd *cobra.Command, _ []string) error {
8580
return errors.Wrap(err, "can't process check-condition flag")
8681
}
8782
if len(keyValuePairs) > 0 {
83+
manifest, err := installer.Manifest()
84+
if err != nil {
85+
return err
86+
}
87+
8888
cmd.Println("Check conditions for package")
8989
err = packages.CheckConditions(*manifest, keyValuePairs)
9090
if err != nil {
@@ -95,116 +95,6 @@ func installCommandAction(cmd *cobra.Command, _ []string) error {
9595
return nil
9696
}
9797

98-
return installer.install(cmd, manifest.Name, manifest.Version)
99-
}
100-
101-
type packageInstaller interface {
102-
manifest() (*packages.PackageManifest, error)
103-
install(cmd *cobra.Command, name, version string) error
104-
}
105-
106-
func newInstaller(zipPath, packageRootPath string, kibanaVersion *semver.Version, skipValidation bool) (packageInstaller, error) {
107-
if zipPath != "" {
108-
if kibanaVersion.LessThan(semver8_7_0) {
109-
return nil, fmt.Errorf("not supported uploading zip packages in Kibana %s", kibanaVersion)
110-
}
111-
if !skipValidation {
112-
logger.Debugf("Validating built .zip package (path: %s)", zipPath)
113-
err := validator.ValidateFromZip(zipPath)
114-
if err != nil {
115-
return nil, errors.Wrapf(err, "invalid content found in built zip package")
116-
}
117-
}
118-
logger.Debug("Skip validation of the built .zip package")
119-
return zipPackage{zipPath: zipPath}, nil
120-
}
121-
if packageRootPath == "" {
122-
var found bool
123-
var err error
124-
packageRootPath, found, err = packages.FindPackageRoot()
125-
if !found {
126-
return nil, errors.New("package root not found")
127-
}
128-
if err != nil {
129-
return nil, errors.Wrap(err, "locating package root failed")
130-
}
131-
}
132-
133-
if kibanaVersion.LessThan(semver8_7_0) {
134-
return localPackage{rootPath: packageRootPath}, nil
135-
}
136-
137-
// build and install
138-
target, err := builder.BuildPackage(builder.BuildOptions{
139-
PackageRoot: packageRootPath,
140-
CreateZip: true,
141-
SignPackage: false,
142-
SkipValidation: skipValidation,
143-
})
144-
if err != nil {
145-
return nil, errors.Wrap(err, "building package failed")
146-
}
147-
logger.Infof("Built package path: %s", target)
148-
149-
return zipPackage{zipPath: target}, nil
150-
}
151-
152-
type localPackage struct {
153-
rootPath string
154-
}
155-
156-
func (l localPackage) manifest() (*packages.PackageManifest, error) {
157-
logger.Debugf("Reading package manifest from %s", l.rootPath)
158-
manifest, err := packages.ReadPackageManifestFromPackageRoot(l.rootPath)
159-
if err != nil {
160-
return nil, errors.Wrapf(err, "reading package manifest failed (path: %s)", l.rootPath)
161-
}
162-
return manifest, nil
163-
}
164-
165-
func (l localPackage) install(cmd *cobra.Command, name, version string) error {
166-
aInstaller, err := installer.CreateForManifest(name, version)
167-
if err != nil {
168-
return errors.Wrap(err, "can't create the package installer")
169-
}
170-
171-
cmd.Println("Install the package")
172-
return installPackage(cmd, aInstaller)
173-
}
174-
175-
type zipPackage struct {
176-
zipPath string
177-
}
178-
179-
func (z zipPackage) manifest() (*packages.PackageManifest, error) {
180-
logger.Debugf("Reading package manifest from %s", z.zipPath)
181-
manifest, err := packages.ReadPackageManifestFromZipPackage(z.zipPath)
182-
if err != nil {
183-
return nil, errors.Wrapf(err, "reading package manifest failed (path: %s)", z.zipPath)
184-
}
185-
return manifest, nil
186-
}
187-
188-
func (z zipPackage) install(cmd *cobra.Command, name, version string) error {
189-
aInstaller, err := installer.CreateForZip(z.zipPath, name, version)
190-
if err != nil {
191-
return errors.Wrap(err, "can't create the package installer")
192-
}
193-
194-
cmd.Printf("Install zip package: %s\n", z.zipPath)
195-
return installPackage(cmd, aInstaller)
196-
}
197-
198-
func installPackage(cmd *cobra.Command, packageInstaller installer.Installer) error {
199-
installedPackage, err := packageInstaller.Install()
200-
if err != nil {
201-
return errors.Wrap(err, "can't install the package")
202-
}
203-
204-
cmd.Println("Installed assets:")
205-
for _, asset := range installedPackage.Assets {
206-
cmd.Printf("- %s (type: %s)\n", asset.ID, asset.Type)
207-
}
208-
cmd.Println("Done")
209-
return nil
98+
_, err = installer.Install()
99+
return err
210100
}

cmd/uninstall.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/spf13/cobra"
1010

1111
"github.com/elastic/elastic-package/internal/cobraext"
12+
"github.com/elastic/elastic-package/internal/kibana"
1213
"github.com/elastic/elastic-package/internal/packages"
1314
"github.com/elastic/elastic-package/internal/packages/installer"
1415
)
@@ -37,12 +38,11 @@ func uninstallCommandAction(cmd *cobra.Command, args []string) error {
3738
return errors.Wrap(err, "locating package root failed")
3839
}
3940

40-
m, err := packages.ReadPackageManifestFromPackageRoot(packageRootPath)
41+
kibanaClient, err := kibana.NewClient()
4142
if err != nil {
42-
return errors.Wrapf(err, "reading package manifest failed (path: %s)", packageRootPath)
43+
return errors.Wrap(err, "could not create kibana client")
4344
}
44-
45-
packageInstaller, err := installer.CreateForManifest(m.Name, m.Version)
45+
packageInstaller, err := installer.CreateForManifest(kibanaClient, packageRootPath)
4646
if err != nil {
4747
return errors.Wrap(err, "can't create the package installer")
4848
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
package installer
6+
7+
import (
8+
"errors"
9+
"fmt"
10+
11+
"github.com/Masterminds/semver/v3"
12+
13+
"github.com/elastic/package-spec/v2/code/go/pkg/validator"
14+
15+
"github.com/elastic/elastic-package/internal/builder"
16+
"github.com/elastic/elastic-package/internal/kibana"
17+
"github.com/elastic/elastic-package/internal/logger"
18+
"github.com/elastic/elastic-package/internal/packages"
19+
)
20+
21+
var semver8_7_0 = semver.MustParse("8.7.0")
22+
23+
// Installer is responsible for installation/uninstallation of the package.
24+
type Installer interface {
25+
Install() (*InstalledPackage, error)
26+
Uninstall() error
27+
28+
Manifest() (*packages.PackageManifest, error)
29+
}
30+
31+
// Options are the parameters used to build an installer.
32+
type Options struct {
33+
Kibana *kibana.Client
34+
RootPath string
35+
ZipPath string
36+
SkipValidation bool
37+
}
38+
39+
// NewForPackage creates a new installer for a package, given its root path, or its prebuilt zip.
40+
// If a zip path is given, this package is validated and installed as is. This fails on versions
41+
// of Kibana lower than 8.7.0.
42+
// When no zip is given, package is built as zip and installed if version is at least 8.7.0,
43+
// or from the package registry otherwise.
44+
func NewForPackage(options Options) (Installer, error) {
45+
if options.Kibana == nil {
46+
return nil, errors.New("missing kibana client")
47+
}
48+
if options.RootPath == "" && options.ZipPath == "" {
49+
return nil, errors.New("missing package root path or pre-built zip package")
50+
}
51+
52+
version, err := kibanaVersion(options.Kibana)
53+
if err != nil {
54+
return nil, fmt.Errorf("failed to get kibana version: %w", err)
55+
}
56+
57+
supportsZip := !version.LessThan(semver8_7_0)
58+
if options.ZipPath != "" {
59+
if !supportsZip {
60+
return nil, fmt.Errorf("not supported uploading zip packages in Kibana %s (%s required)", version, semver8_7_0)
61+
}
62+
if !options.SkipValidation {
63+
logger.Debugf("Validating built .zip package (path: %s)", options.ZipPath)
64+
err := validator.ValidateFromZip(options.ZipPath)
65+
if err != nil {
66+
return nil, fmt.Errorf("invalid content found in built zip package: %w", err)
67+
}
68+
}
69+
logger.Debug("Skip validation of the built .zip package")
70+
return CreateForZip(options.Kibana, options.ZipPath)
71+
}
72+
73+
target, err := builder.BuildPackage(builder.BuildOptions{
74+
PackageRoot: options.RootPath,
75+
CreateZip: supportsZip,
76+
SignPackage: false,
77+
SkipValidation: options.SkipValidation,
78+
})
79+
if err != nil {
80+
return nil, fmt.Errorf("failed to build package: %v", err)
81+
}
82+
83+
if supportsZip {
84+
return CreateForZip(options.Kibana, target)
85+
}
86+
return CreateForManifest(options.Kibana, target)
87+
}
88+
89+
func kibanaVersion(kibana *kibana.Client) (*semver.Version, error) {
90+
version, err := kibana.Version()
91+
if err != nil {
92+
return nil, err
93+
}
94+
sv, err := semver.NewVersion(version.Number)
95+
if err != nil {
96+
return nil, fmt.Errorf("invalid kibana version: %w", err)
97+
}
98+
return sv, nil
99+
}

0 commit comments

Comments
 (0)