Skip to content

Commit

Permalink
Write container-paths.yml into the STATE_PATH (#4995)
Browse files Browse the repository at this point in the history
* Don't write container paths.

* Clean up.

* Add changelog.

* Store container-paths.yml in STATE_PATH.

* Update 1719266012-Don't-fail-when-unable-to-write-container-paths.yaml

* fix issue with empty value

* Fix test.
  • Loading branch information
blakerouse authored Jul 2, 2024
1 parent 5c44e02 commit c46a379
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Kind can be one of:
# - breaking-change: a change to previously-documented behavior
# - deprecation: functionality that is being removed in a later release
# - bug-fix: fixes a problem in a previous version
# - enhancement: extends functionality but does not break or fix existing behavior
# - feature: new functionality
# - known-issue: problems that we are aware of in a given version
# - security: impacts on the security of a product or a user’s deployment.
# - upgrade: important information for someone upgrading from a prior version
# - other: does not fit into any of the other categories
kind: bug-fix

# Change summary; a 80ish characters long description of the change.
summary: Allow Elastic Agent container to work with a read-only filesystem

# Long description; in case the summary is not enough to describe the change
# this field accommodate a description without length limits.
# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment.
#description:

# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc.
component:

# PR URL; optional; the PR number that added the changeset.
# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added.
# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number.
# Please provide it if you are adding a fragment for a different PR.
pr: https://github.com/elastic/elastic-agent/pull/4995

# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of).
# If not present is automatically filled by the tooling with the issue linked to the PR number.
#issue: https://github.com/owner/repo/1234
13 changes: 8 additions & 5 deletions internal/pkg/agent/cmd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,6 @@ func setPaths(statePath, configPath, logsPath, socketPath string, writePaths boo
}

originalInstall := paths.Install()
originalTop := paths.Top()
paths.SetTop(topPath)
paths.SetConfig(configPath)
paths.SetControlSocket(socketPath)
Expand All @@ -830,7 +829,7 @@ func setPaths(statePath, configPath, logsPath, socketPath string, writePaths boo

// persist the paths so other commands in the container will use the correct paths
if writePaths {
if err := writeContainerPaths(originalTop, statePath, configPath, logsPath, socketPath); err != nil {
if err := writeContainerPaths(statePath, configPath, logsPath, socketPath); err != nil {
return err
}
}
Expand All @@ -844,8 +843,8 @@ type containerPaths struct {
SocketPath string `config:"socket_path" yaml:"socket_path,omitempty"`
}

func writeContainerPaths(original, statePath, configPath, logsPath, socketPath string) error {
pathFile := filepath.Join(original, "container-paths.yml")
func writeContainerPaths(statePath, configPath, logsPath, socketPath string) error {
pathFile := filepath.Join(statePath, "container-paths.yml")
fp, err := os.Create(pathFile)
if err != nil {
return fmt.Errorf("failed creating %s: %w", pathFile, err)
Expand All @@ -867,7 +866,11 @@ func writeContainerPaths(original, statePath, configPath, logsPath, socketPath s
}

func tryContainerLoadPaths() error {
pathFile := filepath.Join(paths.Top(), "container-paths.yml")
statePath := envWithDefault("", "STATE_PATH")
if statePath == "" {
statePath = defaultStateDirectory
}
pathFile := filepath.Join(statePath, "container-paths.yml")
_, err := os.Stat(pathFile)
if os.IsNotExist(err) {
// no container-paths.yml file exists, so nothing to do
Expand Down
25 changes: 21 additions & 4 deletions testing/integration/container_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/elastic/elastic-agent-libs/kibana"
"github.com/elastic/elastic-agent/pkg/core/process"
atesting "github.com/elastic/elastic-agent/pkg/testing"
"github.com/elastic/elastic-agent/pkg/testing/define"
"github.com/elastic/elastic-agent/pkg/testing/tools/fleettools"
Expand Down Expand Up @@ -115,6 +116,11 @@ func TestContainerCMD(t *testing.T) {
agentFixture, err := define.NewFixtureFromLocalBuild(t, define.Version())
require.NoError(t, err)

// prepare must be called otherwise `agentFixture.WorkDir()` will be empty
// and it must be set so the `STATE_PATH` below gets a valid path.
err = agentFixture.Prepare(ctx)
require.NoError(t, err)

fleetURL, err := fleettools.DefaultURL(ctx, info.KibanaClient)
if err != nil {
t.Fatalf("could not get Fleet URL: %s", err)
Expand Down Expand Up @@ -147,7 +153,7 @@ func TestContainerCMD(t *testing.T) {
// the agent logs will be present in the error message
// which should help to explain why the agent was not
// healthy.
err = agentFixture.IsHealthy(ctx)
err = agentFixture.IsHealthy(ctx, withEnv(env))
return err == nil
},
5*time.Minute, time.Second,
Expand Down Expand Up @@ -225,7 +231,7 @@ func TestContainerCMDWithAVeryLongStatePath(t *testing.T) {
// the agent logs will be present in the error message
// which should help to explain why the agent was not
// healthy.
err = agentFixture.IsHealthy(ctx)
err = agentFixture.IsHealthy(ctx, withEnv(env))
return err == nil
},
1*time.Minute, time.Second,
Expand All @@ -245,16 +251,27 @@ func TestContainerCMDWithAVeryLongStatePath(t *testing.T) {
if _, err := os.Stat(tc.expectedSocketPath); err != nil {
t.Errorf("cannot stat expected socket path ('%s'): %s", tc.expectedSocketPath, err)
}
containerPaths := filepath.Join(tc.expectedStatePath, "container-paths.yml")
if _, err := os.Stat(tc.expectedSocketPath); err != nil {
t.Errorf("cannot stat expected container-paths.yml path ('%s'): %s", containerPaths, err)
}

if t.Failed() {
containerPaths, err := os.ReadFile(filepath.Join(agentFixture.WorkDir(), "container-paths.yml"))
containerPathsContent, err := os.ReadFile(containerPaths)
if err != nil {
t.Fatalf("could not read container-paths.yml: %s", err)
}

t.Log("contents of 'container-paths-yml'")
t.Log(string(containerPaths))
t.Log(string(containerPathsContent))
}
})
}
}

func withEnv(env []string) process.CmdOption {
return func(c *exec.Cmd) error {
c.Env = append(os.Environ(), env...)
return nil
}
}

0 comments on commit c46a379

Please sign in to comment.