Skip to content

Commit

Permalink
Enhancement/5832 deb rpm docker tests (#6212)
Browse files Browse the repository at this point in the history
* enhancement(5832): added integration tests

* enhancement(5832): updated fixture install, updated assertions

* enhancement(5832): added kubernetes test

* enhancement(5832): ran mage update

* enhancement(5832): execute rpm test in default group

* Revert "enhancement(5832): execute rpm test in default group"

This reverts commit fa93a8e.

* enhancement(5832): debugging ci issues

* enahancement(5832): added logs to see if any other agent is running, commented out other integration tests

* enhancement(5832): added cleanup steps to rpm tests

* enhancement(5832): trying 777 permission

* enhancement(5832): removed diagnostics, added rpm cleanup step that purges all agent files

* enhancement(5832): running all tests

* enhancement(5832): uncommented integration test pipeline

* enhancement(5832): reverting unnecessary changes

* enhancement(5832): uncommenting integration tests

* enhancement(5832): reverted integration_tests.sh changes

* enhancement(5832): reverted fixture_install.go changes

* enhancement(5832): remove print

* enhancement(5832): logging output if cleanup fails

* enhancement(5832): updated k8s test, refactored upgrade test into test step
  • Loading branch information
kaanyalti authored Dec 20, 2024
1 parent 6062cb9 commit 3f608bf
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 6 deletions.
48 changes: 42 additions & 6 deletions pkg/testing/fixture_install.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@ func (i *InstallOpts) ToCmdArgs() []string {
// - the combined output of Install command stdout and stderr
// - an error if any.
func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ...process.CmdOption) ([]byte, error) {
return f.installFunc(ctx, installOpts, true, opts...)
}

func (f *Fixture) InstallWithoutEnroll(ctx context.Context, installOpts *InstallOpts, opts ...process.CmdOption) ([]byte, error) {
return f.installFunc(ctx, installOpts, false, opts...)
}

func (f *Fixture) installFunc(ctx context.Context, installOpts *InstallOpts, shouldEnroll bool, opts ...process.CmdOption) ([]byte, error) {
f.t.Logf("[test %s] Inside fixture install function", f.t.Name())

// check for running agents before installing, but only if not installed into a namespace whose point is allowing two agents at once.
Expand All @@ -184,11 +192,11 @@ func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ..

switch f.packageFormat {
case "targz", "zip":
return f.installNoPkgManager(ctx, installOpts, opts)
return f.installNoPkgManager(ctx, installOpts, shouldEnroll, opts)
case "deb":
return f.installDeb(ctx, installOpts, opts)
return f.installDeb(ctx, installOpts, shouldEnroll, opts)
case "rpm":
return f.installRpm(ctx, installOpts, opts)
return f.installRpm(ctx, installOpts, shouldEnroll, opts)
default:
return nil, fmt.Errorf("package format %s isn't supported yet", f.packageFormat)
}
Expand All @@ -202,14 +210,25 @@ func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ..
// It returns:
// - the combined output of Install command stdout and stderr
// - an error if any.
func (f *Fixture) installNoPkgManager(ctx context.Context, installOpts *InstallOpts, opts []process.CmdOption) ([]byte, error) {
func (f *Fixture) installNoPkgManager(ctx context.Context, installOpts *InstallOpts, shouldEnroll bool, opts []process.CmdOption) ([]byte, error) {
f.t.Logf("[test %s] Inside fixture installNoPkgManager function", f.t.Name())
if installOpts == nil {
// default options when not provided
installOpts = &InstallOpts{}
}

// Removes install params to prevent enrollment
removeEnrollParams := func(installOpts *InstallOpts) {
installOpts.URL = ""
installOpts.EnrollmentToken = ""
installOpts.ESHost = ""
}

installArgs := []string{"install"}
if !shouldEnroll {
removeEnrollParams(installOpts)
}

installArgs = append(installArgs, installOpts.ToCmdArgs()...)
out, err := f.Exec(ctx, installArgs, opts...)
if err != nil {
Expand Down Expand Up @@ -410,7 +429,7 @@ func getProcesses(t *gotesting.T, regex string) []runningProcess {
// It returns:
// - the combined output of Install command stdout and stderr
// - an error if any.
func (f *Fixture) installDeb(ctx context.Context, installOpts *InstallOpts, opts []process.CmdOption) ([]byte, error) {
func (f *Fixture) installDeb(ctx context.Context, installOpts *InstallOpts, shouldEnroll bool, opts []process.CmdOption) ([]byte, error) {
f.t.Logf("[test %s] Inside fixture installDeb function", f.t.Name())
// Prepare so that the f.srcPackage string is populated
err := f.EnsurePrepared(ctx)
Expand Down Expand Up @@ -456,6 +475,10 @@ func (f *Fixture) installDeb(ctx context.Context, installOpts *InstallOpts, opts
return out, fmt.Errorf("systemctl start elastic-agent failed: %w", err)
}

if !shouldEnroll {
return nil, nil
}

// apt install doesn't enroll, so need to do that
enrollArgs := []string{"elastic-agent", "enroll"}
if installOpts.Force {
Expand Down Expand Up @@ -491,7 +514,7 @@ func (f *Fixture) installDeb(ctx context.Context, installOpts *InstallOpts, opts
// It returns:
// - the combined output of Install command stdout and stderr
// - an error if any.
func (f *Fixture) installRpm(ctx context.Context, installOpts *InstallOpts, opts []process.CmdOption) ([]byte, error) {
func (f *Fixture) installRpm(ctx context.Context, installOpts *InstallOpts, shouldEnroll bool, opts []process.CmdOption) ([]byte, error) {
f.t.Logf("[test %s] Inside fixture installRpm function", f.t.Name())
// Prepare so that the f.srcPackage string is populated
err := f.EnsurePrepared(ctx)
Expand All @@ -507,6 +530,7 @@ func (f *Fixture) installRpm(ctx context.Context, installOpts *InstallOpts, opts

f.t.Cleanup(func() {
f.t.Logf("[test %s] Inside fixture installRpm cleanup function", f.t.Name())

uninstallCtx, uninstallCancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer uninstallCancel()
// stop elastic-agent, non fatal if error, might have been stopped before this.
Expand All @@ -522,6 +546,14 @@ func (f *Fixture) installRpm(ctx context.Context, installOpts *InstallOpts, opts
f.t.Logf("failed to 'sudo rpm -e elastic-agent': %s, output: %s", err, string(out))
f.t.FailNow()
}

f.t.Logf("removing installed agent files")
out, err = exec.CommandContext(uninstallCtx, "sudo", "rm", "-rf", "/var/lib/elastic-agent", "/var/log/elastic-agent", "/etc/elastic-agent").CombinedOutput()
if err != nil {
f.t.Log(string(out))
f.t.Logf("failed to 'sudo rm -rf /var/lib/elastic-agent /var/log/elastic-agent/ /etc/elastic-agent'")
f.t.FailNow()
}
})

// start elastic-agent
Expand All @@ -530,6 +562,10 @@ func (f *Fixture) installRpm(ctx context.Context, installOpts *InstallOpts, opts
return out, fmt.Errorf("systemctl start elastic-agent failed: %w", err)
}

if !shouldEnroll {
return nil, nil
}

// rpm install doesn't enroll, so need to do that
enrollArgs := []string{"elastic-agent", "enroll"}
if installOpts.Force {
Expand Down
23 changes: 23 additions & 0 deletions testing/integration/kubernetes_agent_standalone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import (
"helm.sh/helm/v3/pkg/cli"
helmKube "helm.sh/helm/v3/pkg/kube"

"github.com/elastic/elastic-agent/internal/pkg/agent/application/coordinator"
aclient "github.com/elastic/elastic-agent/pkg/control/v2/client"
atesting "github.com/elastic/elastic-agent/pkg/testing"
"github.com/elastic/elastic-agent/pkg/testing/define"
Expand Down Expand Up @@ -288,6 +289,7 @@ func TestKubernetesAgentHelm(t *testing.T) {
k8sStepCheckAgentStatus("name=agent-pernode-helm-agent", schedulableNodeCount, "agent", nil),
k8sStepCheckAgentStatus("name=agent-clusterwide-helm-agent", 1, "agent", nil),
k8sStepCheckAgentStatus("name=agent-ksmsharded-helm-agent", 1, "agent", nil),
k8sStepCheckRestrictUpgrade("name=agent-pernode-helm-agent", schedulableNodeCount, "agent"),
k8sStepRunInnerTests("name=agent-pernode-helm-agent", schedulableNodeCount, "agent"),
k8sStepRunInnerTests("name=agent-clusterwide-helm-agent", 1, "agent"),
k8sStepRunInnerTests("name=agent-ksmsharded-helm-agent", 1, "agent"),
Expand Down Expand Up @@ -320,6 +322,7 @@ func TestKubernetesAgentHelm(t *testing.T) {
k8sStepCheckAgentStatus("name=agent-pernode-helm-agent", schedulableNodeCount, "agent", nil),
k8sStepCheckAgentStatus("name=agent-clusterwide-helm-agent", 1, "agent", nil),
k8sStepCheckAgentStatus("name=agent-ksmsharded-helm-agent", 1, "agent", nil),
k8sStepCheckRestrictUpgrade("name=agent-pernode-helm-agent", schedulableNodeCount, "agent"),
k8sStepRunInnerTests("name=agent-pernode-helm-agent", schedulableNodeCount, "agent"),
k8sStepRunInnerTests("name=agent-clusterwide-helm-agent", 1, "agent"),
k8sStepRunInnerTests("name=agent-ksmsharded-helm-agent", 1, "agent"),
Expand Down Expand Up @@ -1335,3 +1338,23 @@ func k8sStepHintsRedisDelete() k8sTestStep {
require.NoError(t, err, "failed to delete redis k8s objects")
}
}

func k8sStepCheckRestrictUpgrade(agentPodLabelSelector string, expectedPodNumber int, containerName string) k8sTestStep {
return func(t *testing.T, ctx context.Context, kCtx k8sContext, namespace string) {
perNodePodList := &corev1.PodList{}
err := kCtx.client.Resources(namespace).List(ctx, perNodePodList, func(opt *metav1.ListOptions) {
opt.LabelSelector = agentPodLabelSelector
})
require.NoError(t, err, "failed to list pods with selector ", perNodePodList)
require.NotEmpty(t, perNodePodList.Items, "no pods found with selector ", perNodePodList)
require.Equal(t, expectedPodNumber, len(perNodePodList.Items), "unexpected number of pods found with selector ", perNodePodList)
for _, pod := range perNodePodList.Items {
var stdout, stderr bytes.Buffer

command := []string{"elastic-agent", "upgrade", "1.0.0"}
err := kCtx.client.Resources().ExecInPod(ctx, namespace, pod.Name, containerName, command, &stdout, &stderr)
require.Error(t, err)
require.Contains(t, stderr.String(), coordinator.ErrNotUpgradable.Error())
}
}
}
59 changes: 59 additions & 0 deletions testing/integration/restrict_upgrade_deb_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License 2.0;
// you may not use this file except in compliance with the Elastic License 2.0.

//go:build integration

package integration

import (
"context"
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/elastic/elastic-agent/internal/pkg/agent/application/coordinator"
atesting "github.com/elastic/elastic-agent/pkg/testing"
"github.com/elastic/elastic-agent/pkg/testing/define"
)

func TestRestrictUpgradeDeb(t *testing.T) {
define.Require(t, define.Requirements{
Group: Deb,
Stack: &define.Stack{},
Sudo: true,
OS: []define.OS{
{
Type: define.Linux,
Distro: "ubuntu",
},
},
})
t.Run("when agent is deployed via deb, a user should not be able to upgrade the agent using the cli", func(t *testing.T) {
ctx := context.Background()

fixture, err := define.NewFixtureFromLocalBuild(t, define.Version(), atesting.WithPackageFormat("deb"))
require.NoError(t, err)
installOpts := atesting.InstallOpts{
NonInteractive: true,
Privileged: true,
Force: true,
}

_, err = fixture.InstallWithoutEnroll(ctx, &installOpts)
require.NoError(t, err)

require.Eventuallyf(t, func() bool {
err = fixture.IsHealthy(ctx)
return err == nil
}, 5*time.Minute, time.Second,
"Elastic-Agent did not report healthy. Agent status error: \"%v\"",
err,
)

out, err := fixture.Exec(ctx, []string{"upgrade", "1.0.0"})
require.Error(t, err)
require.Contains(t, string(out), coordinator.ErrNotUpgradable.Error())
})
}
59 changes: 59 additions & 0 deletions testing/integration/restrict_upgrade_rpm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License 2.0;
// you may not use this file except in compliance with the Elastic License 2.0.

//go:build integration

package integration

import (
"context"
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/elastic/elastic-agent/internal/pkg/agent/application/coordinator"
atesting "github.com/elastic/elastic-agent/pkg/testing"
"github.com/elastic/elastic-agent/pkg/testing/define"
)

func TestRestrictUpgradeRPM(t *testing.T) {
define.Require(t, define.Requirements{
Group: RPM,
Stack: &define.Stack{},
Sudo: true,
OS: []define.OS{
{
Type: define.Linux,
Distro: "rhel",
},
},
})
t.Run("when agent is deployed via rpm, a user should not be able to upgrade the agent using the cli", func(t *testing.T) {
ctx := context.Background()

fixture, err := define.NewFixtureFromLocalBuild(t, define.Version(), atesting.WithPackageFormat("rpm"))
require.NoError(t, err)
installOpts := atesting.InstallOpts{
NonInteractive: true,
Privileged: true,
Force: true,
}

_, err = fixture.InstallWithoutEnroll(ctx, &installOpts)
require.NoError(t, err)

require.Eventuallyf(t, func() bool {
err = fixture.IsHealthy(ctx)
return err == nil
}, 5*time.Minute, time.Second,
"Elastic-Agent did not report healthy. Agent status error: \"%v\"",
err,
)

out, err := fixture.Exec(ctx, []string{"upgrade", "1.0.0"})
require.Error(t, err)
require.Contains(t, string(out), coordinator.ErrNotUpgradable.Error())
})
}

0 comments on commit 3f608bf

Please sign in to comment.