Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x](backport #6212) Enhancement/5832 deb rpm docker tests #6422

Merged
merged 3 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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())
})
}
Loading