Skip to content

Commit

Permalink
[Elastic Agent] Adjust installation path in container (#27396) (#27432)
Browse files Browse the repository at this point in the history
* Adjust atomic installer to extract in the install directory, removing the need to rename across filesystem boundaries.

* Add comment.

* Add changelog.

* Fix install path on k8s.

* Fix issue with paths.

* Cleanup temps.

* Add changelog.

(cherry picked from commit 9ce228f)

Co-authored-by: Blake Rouse <blake.rouse@elastic.co>
  • Loading branch information
mergify[bot] and blakerouse authored Aug 17, 2021
1 parent 178ff4b commit e3348df
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 10 deletions.
2 changes: 2 additions & 0 deletions x-pack/elastic-agent/CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
- Fix apm-server supported outputs not being in sync with supported output types. {pull}26885[26885]
- Set permissions during installation {pull}26665[26665]
- Disable monitoring during fleet-server bootstrapping. {pull}27222[27222]
- Fix issue with atomic extract running in K8s {pull}27396[27396]
- Fix issue with install directory in state path in K8s {pull}27396[27396]

==== New features

Expand Down
30 changes: 30 additions & 0 deletions x-pack/elastic-agent/pkg/agent/application/paths/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ var (
configPath string
configFilePath string
logsPath string
downloadsPath string
installPath string
unversionedHome bool
tmpCreator sync.Once
)
Expand All @@ -44,6 +46,8 @@ func init() {
fs.StringVar(&configPath, "path.config", configPath, "Config path is the directory Agent looks for its config file")
fs.StringVar(&configFilePath, "c", DefaultConfigName, "Configuration file, relative to path.config")
fs.StringVar(&logsPath, "path.logs", logsPath, "Logs path contains Agent log output")
fs.StringVar(&downloadsPath, "path.downloads", downloadsPath, "Downloads path contains binaries Agent downloads")
fs.StringVar(&installPath, "path.install", installPath, "Install path contains binaries Agent extracts")
}

// Top returns the top directory for Elastic Agent, all the versioned
Expand Down Expand Up @@ -139,6 +143,32 @@ func VersionedHome(base string) string {
return filepath.Join(base, "data", fmt.Sprintf("elastic-agent-%s", release.ShortCommit()))
}

// Downloads returns the downloads directory for Agent
func Downloads() string {
if downloadsPath == "" {
return filepath.Join(Home(), "downloads")
}
return downloadsPath
}

// SetDownloads updates the path for the downloads.
func SetDownloads(path string) {
downloadsPath = path
}

// Install returns the install directory for Agent
func Install() string {
if installPath == "" {
return filepath.Join(Home(), "install")
}
return installPath
}

// SetInstall updates the path for the install.
func SetInstall(path string) {
installPath = path
}

// initialTop returns the initial top-level path for the binary
//
// When nested in top-level/data/elastic-agent-${hash}/ the result is top-level/.
Expand Down
2 changes: 2 additions & 0 deletions x-pack/elastic-agent/pkg/agent/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ func NewCommandWithArgs(args []string, streams *cli.IOStreams) *cobra.Command {
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.config"))
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("c"))
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.logs"))
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.downloads"))
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("path.install"))

// logging flags
cmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("v"))
Expand Down
12 changes: 10 additions & 2 deletions x-pack/elastic-agent/pkg/agent/cmd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,12 @@ func buildEnrollArgs(cfg setupConfig, token string, policyID string) ([]string,
"--path.config", paths.Config(),
"--path.logs", paths.Logs(),
}
if paths.Downloads() != "" {
args = append(args, "--path.downloads", paths.Downloads())
}
if paths.Install() != "" {
args = append(args, "--path.install", paths.Install())
}
if !paths.IsVersionHome() {
args = append(args, "--path.home.unversioned")
}
Expand Down Expand Up @@ -704,16 +710,18 @@ func setPaths(statePath, configPath, logsPath string, writePaths bool) error {
}
}
// sync the downloads to the data directory
srcDownloads := filepath.Join(paths.Home(), "downloads")
destDownloads := filepath.Join(statePath, "data", "downloads")
if err := syncDir(srcDownloads, destDownloads); err != nil {
if err := syncDir(paths.Downloads(), destDownloads); err != nil {
return fmt.Errorf("syncing download directory to STATE_PATH(%s) failed: %s", statePath, err)
}
originalInstall := paths.Install()
originalTop := paths.Top()
paths.SetTop(topPath)
paths.SetConfig(configPath)
// when custom top path is provided the home directory is not versioned
paths.SetVersionHome(false)
// install path stays on container default mount (otherwise a bind mounted directory could have noexec set)
paths.SetInstall(originalInstall)
// set LOGS_PATH is given
logsPath = envWithDefault(logsPath, "LOGS_PATH")
if logsPath != "" {
Expand Down
6 changes: 6 additions & 0 deletions x-pack/elastic-agent/pkg/agent/cmd/enroll_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,12 @@ func (c *enrollCmd) startAgent(ctx context.Context) (<-chan *os.ProcessState, er
"--path.home", paths.Top(), "--path.config", paths.Config(),
"--path.logs", paths.Logs(),
}
if paths.Downloads() != "" {
args = append(args, "--path.downloads", paths.Downloads())
}
if paths.Install() != "" {
args = append(args, "--path.install", paths.Install())
}
if !paths.IsVersionHome() {
args = append(args, "--path.home.unversioned")
}
Expand Down
6 changes: 2 additions & 4 deletions x-pack/elastic-agent/pkg/artifact/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package artifact

import (
"path/filepath"
"runtime"
"strings"
"time"
Expand Down Expand Up @@ -43,16 +42,15 @@ type Config struct {

// DefaultConfig creates a config with pre-set default values.
func DefaultConfig() *Config {
homePath := paths.Home()
transport := httpcommon.DefaultHTTPTransportSettings()

// binaries are a getting bit larger it might take >30s to download them
transport.Timeout = 120 * time.Second

return &Config{
SourceURI: "https://artifacts.elastic.co/downloads/",
TargetDirectory: filepath.Join(homePath, "downloads"),
InstallPath: filepath.Join(homePath, "install"),
TargetDirectory: paths.Downloads(),
InstallPath: paths.Install(),
HTTPTransportSettings: transport,
}
}
Expand Down
4 changes: 2 additions & 2 deletions x-pack/elastic-agent/pkg/artifact/download/fs/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,13 @@ func (e *Downloader) downloadFile(filename, fullPath string) (string, error) {
func getDropPath(cfg *artifact.Config) string {
// if drop path is not provided fallback to beats subfolder
if cfg == nil || cfg.DropPath == "" {
return filepath.Join(paths.Home(), "downloads")
return paths.Downloads()
}

// if droppath does not exist fallback to beats subfolder
stat, err := os.Stat(cfg.DropPath)
if err != nil || !stat.IsDir() {
return filepath.Join(paths.Home(), "downloads")
return paths.Downloads()
}

return cfg.DropPath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/hashicorp/go-multierror"

"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/program"
)

Expand All @@ -37,10 +36,19 @@ func NewInstaller(i embeddedInstaller) (*Installer, error) {
// Install performs installation of program in a specific version.
func (i *Installer) Install(ctx context.Context, spec program.Spec, version, installDir string) error {
// tar installer uses Dir of installDir to determine location of unpack
tempDir, err := ioutil.TempDir(paths.TempDir(), "elastic-agent-install")
//
// installer is ran inside a tmp directory created in the parent installDir, this is so the atomic
// rename always occurs on the same mount path that holds the installation directory
tempDir, err := ioutil.TempDir(filepath.Dir(installDir), "tmp")
if err != nil {
return err
}

// always remove the entire tempDir
defer func() {
os.RemoveAll(tempDir)
}()

tempInstallDir := filepath.Join(tempDir, filepath.Base(installDir))

// cleanup install directory before Install
Expand Down

0 comments on commit e3348df

Please sign in to comment.