diff --git a/x-pack/elastic-agent/CHANGELOG.asciidoc b/x-pack/elastic-agent/CHANGELOG.asciidoc index e7616a8b620..4a8082daf3f 100644 --- a/x-pack/elastic-agent/CHANGELOG.asciidoc +++ b/x-pack/elastic-agent/CHANGELOG.asciidoc @@ -52,6 +52,7 @@ - Remove support for logs type and use logfile {pull}19761[19761] - Avoid comparing uncomparable types on enroll {issue}19976[19976] - Fix issues with merging of elastic-agent.yml and fleet.yml {pull}20026[20026] +- Unzip failures on Windows 8/Windows server 2012 {pull}20088[20088] - Fix failing unit tests on windows {pull}20127[20127] - Prevent closing closed reader {pull}20214[20214] - Improve GRPC stop to be more relaxed {pull}20118[20118] diff --git a/x-pack/elastic-agent/pkg/artifact/install/zip/zip_installer.go b/x-pack/elastic-agent/pkg/artifact/install/zip/zip_installer.go index 451cd701627..ffc90f2dce8 100644 --- a/x-pack/elastic-agent/pkg/artifact/install/zip/zip_installer.go +++ b/x-pack/elastic-agent/pkg/artifact/install/zip/zip_installer.go @@ -7,11 +7,12 @@ package zip import ( "archive/zip" "context" - "fmt" + "io" "os" - "os/exec" "path/filepath" + "github.com/hashicorp/go-multierror" + "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/errors" "github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/artifact" ) @@ -47,7 +48,7 @@ func (i *Installer) Install(_ context.Context, programName, version, installDir os.RemoveAll(installDir) } - if err := i.unzip(artifactPath, programName, version); err != nil { + if err := i.unzip(artifactPath); err != nil { return err } @@ -67,14 +68,59 @@ func (i *Installer) Install(_ context.Context, programName, version, installDir return nil } -func (i *Installer) unzip(artifactPath, programName, version string) error { - if _, err := os.Stat(artifactPath); err != nil { - return errors.New(fmt.Sprintf("artifact for '%s' version '%s' could not be found at '%s'", programName, version, artifactPath), errors.TypeFilesystem, errors.M(errors.MetaKeyPath, artifactPath)) +func (i *Installer) unzip(artifactPath string) error { + r, err := zip.OpenReader(artifactPath) + if err != nil { + return err + } + defer r.Close() + + if err := os.MkdirAll(i.config.InstallPath, 0755); err != nil && !os.IsExist(err) { + // failed to create install dir + return err + } + + unpackFile := func(f *zip.File) (err error) { + rc, err := f.Open() + if err != nil { + return err + } + defer func() { + if cerr := rc.Close(); cerr != nil { + err = multierror.Append(err, cerr) + } + }() + + path := filepath.Join(i.config.InstallPath, f.Name) + + if f.FileInfo().IsDir() { + os.MkdirAll(path, f.Mode()) + } else { + os.MkdirAll(filepath.Dir(path), f.Mode()) + f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) + if err != nil { + return err + } + defer func() { + if cerr := f.Close(); cerr != nil { + err = multierror.Append(err, cerr) + } + }() + + if _, err = io.Copy(f, rc); err != nil { + return err + } + } + return nil } - powershellArg := fmt.Sprintf("Expand-Archive -LiteralPath \"%s\" -DestinationPath \"%s\"", artifactPath, i.config.InstallPath) - installCmd := exec.Command("powershell", "-command", powershellArg) - return installCmd.Run() + for _, f := range r.File { + if err := unpackFile(f); err != nil { + return err + } + } + + return nil } // retrieves root directory from zip archive