Skip to content

Commit

Permalink
Update will cleanup unneeded artifacts.
Browse files Browse the repository at this point in the history
The update process will cleanup unneeded artifacts. When an update
starts all artifacts that do not have the current version number in it's
name will be removed. If artifact retrieval fails, downloaded artifacts
are removed. On a successful upgrade, all contents of the downloads dir
will be removed.
  • Loading branch information
michel-laterman committed Jul 20, 2022
1 parent 8ef98f1 commit 02a4aa8
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
- Allow ':' characters in dynamic variables {issue}624[624] {pull}680[680]
- Allow the - char to appear as part of variable names in eql expressions. {issue}709[709] {pull}710[710]
- Allow the / char in variable names in eql and transpiler. {issue}715[715] {pull}718[718]
- Agent updates will clean up unneeded artifacts. {issue}693[693] {issue}694[694] {pull}752[752]

==== New features

Expand Down
49 changes: 49 additions & 0 deletions internal/pkg/agent/application/upgrade/cleanup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package upgrade

import (
"os"
"path/filepath"
"strings"

"github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
)

// preUpgradeCleanup will remove files that do not have the passed version number from the downloads directory.
func preUpgradeCleanup(version string) error {
files, err := os.ReadDir(paths.Downloads())
if err != nil {
return err
}
for _, file := range files {
if file.IsDir() {
continue
}
if !strings.Contains(file.Name(), version) {
if err := os.Remove(filepath.Join(paths.Downloads(), file.Name())); err != nil {
return err
}
}
}
return nil
}

// cleanAllDownloads will remove all files from the downloads directory
func cleanAllDownloads() error {
files, err := os.ReadDir(paths.Downloads())
if err != nil {
return err
}
for _, file := range files {
if file.IsDir() {
continue
}
if err := os.Remove(filepath.Join(paths.Downloads(), file.Name())); err != nil {
return err
}
}
return nil
}
61 changes: 61 additions & 0 deletions internal/pkg/agent/application/upgrade/cleanup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package upgrade

import (
"os"
"path/filepath"
"testing"

"github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"

"github.com/stretchr/testify/require"
)

func setupDir(t *testing.T) {
t.Helper()
dir := t.TempDir()
paths.SetDownloads(dir)

err := os.WriteFile(filepath.Join(dir, "test-8.3.0-file"), []byte("hello, world!"), 0640)
if err != nil {
t.Fatal(err)
}
err = os.WriteFile(filepath.Join(dir, "test-8.4.0-file"), []byte("hello, world!"), 0640)
if err != nil {
t.Fatal(err)
}
err = os.WriteFile(filepath.Join(dir, "test-8.5.0-file"), []byte("hello, world!"), 0640)
if err != nil {
t.Fatal(err)
}
err = os.WriteFile(filepath.Join(dir, "test-hash-file"), []byte("hello, world!"), 0640)
if err != nil {
t.Fatal(err)
}
}

func TestPreUpgradeCleanup(t *testing.T) {
setupDir(t)
err := preUpgradeCleanup("8.4.0")
require.NoError(t, err)

files, err := os.ReadDir(paths.Downloads())
require.NoError(t, err)
require.Len(t, files, 1)
require.Equal(t, "test-8.4.0-file", files[0].Name())
fi, err := files[0].Info()
require.NoError(t, err)
require.Greater(t, fi.Size(), int64(0))
}

func TestCleanAllDownloads(t *testing.T) {
setupDir(t)
err := cleanAllDownloads()
require.NoError(t, err)
files, err := os.ReadDir(paths.Downloads())
require.NoError(t, err)
require.Len(t, files, 0)
}
17 changes: 17 additions & 0 deletions internal/pkg/agent/application/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ func (u *Upgrader) Upgrade(ctx context.Context, a Action, reexecNow bool) (_ ree
"running under control of the systems supervisor")
}

err = preUpgradeCleanup(a.Version())
if err != nil {
u.log.Errorf("Unable to clean downloads dir %q before update: %v", paths.Downloads(), err)
}

if u.caps != nil {
if _, err := u.caps.Apply(a); errors.Is(err, capabilities.ErrBlocked) {
return nil, nil
Expand All @@ -137,6 +142,11 @@ func (u *Upgrader) Upgrade(ctx context.Context, a Action, reexecNow bool) (_ ree
sourceURI := u.sourceURI(a.SourceURI())
archivePath, err := u.downloadArtifact(ctx, a.Version(), sourceURI)
if err != nil {
// Run the same preUpgradeCleanup task to get rid of any newly downloaded files
// This may have an issue if users are upgrading to the same version number.
if dErr := preUpgradeCleanup(a.Version()); dErr != nil {
u.log.Errorf("Unable to remove file after verification failure: %v", dErr)
}
return nil, err
}

Expand Down Expand Up @@ -184,6 +194,13 @@ func (u *Upgrader) Upgrade(ctx context.Context, a Action, reexecNow bool) (_ ree
return nil, nil
}

// Clean everything from the downloads dir
// If we wanted to be a bit simpler we could call os.RemoveAll to remove the dir + children
err = cleanAllDownloads()
if err != nil {
u.log.Errorf("Unable to clean downloads dir %q after update: %v", paths.Downloads(), err)
}

return cb, nil
}

Expand Down

0 comments on commit 02a4aa8

Please sign in to comment.