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

Fix flaky install/uninstall test #260

Merged
merged 2 commits into from
Mar 21, 2023
Merged
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
96 changes: 49 additions & 47 deletions test/integration/install/install_uninstall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package install

import (
"context"
"errors"
"io"
"os"
"path"
Expand All @@ -11,7 +12,7 @@ import (
"time"

"github.com/nginx/agent/test/integration/utils"
"github.com/shirou/gopsutil/process"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
Expand All @@ -33,21 +34,8 @@ var (
// Verifies that agent installs with correct output and files.
// Verifies that agent uninstalls and removes all the files.
func TestAgentManualInstallUninstall(t *testing.T) {
// Check the environment variable $PACKAGE_NAME is set
require.NotEmpty(t, AGENT_PACKAGE_FILENAME, "Environment variable $PACKAGE_NAME not set")

testContainer := utils.SetupTestContainerWithoutAgent(t)

exitCode, osReleaseFileContent, err := testContainer.Exec(context.Background(), []string{"cat", osReleasePath})
assert.NoError(t, err)
osReleaseContent, err := io.ReadAll(osReleaseFileContent)
assert.NoError(t, err)
assert.Equal(t, 0, exitCode)
assert.NotEmpty(t, osReleaseContent, "os release file empty")

expectedInstallLogMsgs := map[string]string{
"InstallFoundNginxAgent": "Found nginx-agent /usr/bin/nginx-agent",
"InstallAgentToRunAs": "nginx-agent will be configured to run as same user",
"InstallAgentSuccess": "NGINX Agent package has been successfully installed.",
"InstallAgentStartCmd": "sudo systemctl start nginx-agent",
}
Expand All @@ -62,6 +50,19 @@ func TestAgentManualInstallUninstall(t *testing.T) {
"AgentDynamicConfigFile": "/etc/nginx-agent/agent-dynamic.conf",
}

// Check the environment variable $PACKAGE_NAME is set
require.NotEmpty(t, AGENT_PACKAGE_FILENAME, "Environment variable $PACKAGE_NAME not set")

testContainer := utils.SetupTestContainerWithoutAgent(t)

ctx := context.Background()
exitCode, osReleaseFileContent, err := testContainer.Exec(ctx, []string{"cat", osReleasePath})
assert.NoError(t, err)
osReleaseContent, err := io.ReadAll(osReleaseFileContent)
assert.NoError(t, err)
assert.Equal(t, 0, exitCode)
assert.NotEmpty(t, osReleaseContent, "os release file empty")

// Check the file size is less than or equal 20MB
absLocalAgentPkgDirPath, err := filepath.Abs("../../../build/")
assert.NoError(t, err, "Error finding local agent package build dir")
Expand All @@ -72,27 +73,30 @@ func TestAgentManualInstallUninstall(t *testing.T) {

// Install Agent inside container and record installation time/install output
containerAgentPackagePath := getPackagePath(absContainerAgentPackageDir, string(osReleaseContent))
installTime, installLog := installAgent(t, testContainer, containerAgentPackagePath, string(osReleaseContent))
installTime, installLog, err := installAgent(ctx, testContainer, containerAgentPackagePath, string(osReleaseContent))
require.NoError(t, err)

// Check the install time under 30s
assert.LessOrEqual(t, installTime, maxInstallTime)

// Check install output
for log, logMsg := range expectedInstallLogMsgs {
if log == "InstallAgentToRunAs" && !nginxIsRunning() {
continue // only expected if nginx is installed and running
}
if nginxIsRunning(ctx, testContainer) {
expectedInstallLogMsgs["InstallAgentToRunAs"] = "nginx-agent will be configured to run as same user"
}

for _, logMsg := range expectedInstallLogMsgs {
assert.Contains(t, installLog, logMsg)
}

// Check nginx-agent config files were created.
for _, path := range expectedAgentPaths {
_, err = testContainer.CopyFileFromContainer(context.Background(), path)
_, err = testContainer.CopyFileFromContainer(ctx, path)
assert.NoError(t, err)
}

// Uninstall the agent package
uninstallLog := uninstallAgent(t, testContainer, string(osReleaseContent))
uninstallLog, err := uninstallAgent(ctx, testContainer, string(osReleaseContent))
require.NoError(t, err)

// Check uninstall output
if strings.HasSuffix(containerAgentPackagePath, "rpm") {
Expand All @@ -105,45 +109,48 @@ func TestAgentManualInstallUninstall(t *testing.T) {

// Check nginx-agent config files were removed.
for path := range expectedAgentPaths {
_, err = testContainer.CopyFileFromContainer(context.Background(), path)
_, err = testContainer.CopyFileFromContainer(ctx, path)
assert.Error(t, err)
}
}

// installAgent installs the agent returning total install time and install output
func installAgent(t *testing.T, container *testcontainers.DockerContainer, agentPackageFilePath, osReleaseContent string) (time.Duration, string) {
func installAgent(ctx context.Context, container *testcontainers.DockerContainer, agentPackageFilePath, osReleaseContent string) (time.Duration, string, error) {
// Get OS to create install cmd
installCmd := createInstallCommand(agentPackageFilePath, osReleaseContent)

// Start install timer
start := time.Now()

// Start agent installation and capture install output
exitCode, cmdOut, err := container.Exec(context.Background(), installCmd)
assert.NoError(t, err)
assert.Equal(t, 0, exitCode, "expected exit code of 0")
exitCode, cmdOut, err := container.Exec(ctx, installCmd)
if err != nil {
return time.Since(start), "", err
}
if exitCode != 0 {
return time.Since(start), "", errors.New("expected exit code of 0")
}

stdoutStderr, err := io.ReadAll(cmdOut)
assert.NoError(t, err)

elapsed := time.Since(start)

return elapsed, string(stdoutStderr)
return time.Since(start), string(stdoutStderr), err
}

// uninstallAgent uninstall the agent returning output
func uninstallAgent(t *testing.T, container *testcontainers.DockerContainer, osReleaseContent string) string {
func uninstallAgent(ctx context.Context, container *testcontainers.DockerContainer, osReleaseContent string) (string, error) {
// Get OS to create uninstall cmd
uninstallCmd := createUninstallCommand(osReleaseContent)

// Start agent uninstall and capture uninstall output
exitCode, cmdOut, err := container.Exec(context.Background(), uninstallCmd)
assert.NoError(t, err)
assert.Equal(t, 0, exitCode)
exitCode, cmdOut, err := container.Exec(ctx, uninstallCmd)
if err != nil {
return "", err
}
if exitCode != 0 {
return "", errors.New("expected exit code of 0")
}

stdoutStderr, err := io.ReadAll(cmdOut)
assert.NoError(t, err)
return string(stdoutStderr)
return string(stdoutStderr), err
}

func createInstallCommand(agentPackageFilePath, osReleaseContent string) []string {
Expand All @@ -162,17 +169,12 @@ func createUninstallCommand(osReleaseContent string) []string {
}
}

func nginxIsRunning() bool {
processes, _ := process.Processes()

for _, process := range processes {
name, _ := process.Name()
if name == "nginx" {
return true
}
func nginxIsRunning(ctx context.Context, container *testcontainers.DockerContainer) bool {
exitCode, _, err := container.Exec(ctx, []string{"pgrep", "nginx"})
if err != nil || exitCode != 0 {
return false
}

return false
return true
}

func getPackagePath(pkgDir, osReleaseContent string) string {
Expand Down