From e4d45e3433bda81a7ba941fe20fb6facdb0dae69 Mon Sep 17 00:00:00 2001 From: Sven Nierlein Date: Sun, 24 Mar 2024 23:58:36 +0100 Subject: [PATCH] tests: add pkg/deb installation/uninstall to integration tests --- .github/workflows/builds.yml | 29 ++++- t/40_e2e_deb_linux_test.go | 104 ++++++++++++++++++ ...st.go => 41_e2e_build_msi_windows_test.go} | 28 ++--- t/42_e2e_pkg_osx_darwin_test.go | 97 ++++++++++++++++ t/utils.go | 24 +++- 5 files changed, 257 insertions(+), 25 deletions(-) create mode 100644 t/40_e2e_deb_linux_test.go rename t/{40_build_msi_windows_test.go => 41_e2e_build_msi_windows_test.go} (92%) create mode 100644 t/42_e2e_pkg_osx_darwin_test.go diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 7143547..93c42ce 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -390,31 +390,51 @@ jobs: integration-test-linux: + strategy: + matrix: + go-os: [linux] + go-arch: [x86_64] runs-on: ubuntu-latest - needs: [pkg-deb,pkg-rpm] + needs: [get-version,pkg-deb] + env: + BIN: "snclient-${{needs.get-version.outputs.version}}-${{ matrix.go-os }}-${{ matrix.go-arch }}" steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: ${{ env.GOVERSION }} + - uses: actions/download-artifact@v4 + with: + name: "${{ env.BIN }}.deb" - name: "Linux Integration Tests" run: | + mv ${{ env.BIN }}.deb t/snclient.deb cd t - go test -v + SNCLIENT_INSTALL_TEST=1 go test -v integration-test-osx: + strategy: + matrix: + go-os: [darwin] + go-arch: [x86_64] runs-on: macos-latest - needs: [pkg-osx] + needs: [get-version,pkg-osx] + env: + BIN: "snclient-${{needs.get-version.outputs.version}}-osx-${{ matrix.go-arch }}" steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: ${{ env.GOVERSION }} + - uses: actions/download-artifact@v4 + with: + name: "${{ env.BIN }}.pkg" - name: "OSX Integration Tests" run: | + mv ${{ env.BIN }}.pkg t/snclient.pkg cd t - go test -v + SNCLIENT_INSTALL_TEST=1 sudo go test -v integration-test-windows: @@ -447,6 +467,7 @@ jobs: Move-Item -Path ${{ env.BIN }}.msi -Destination .\t\snclient.msi Copy-Item .\windist\windows_exporter-amd64.exe .\windist\windows_exporter.exe cd t + $env:SNCLIENT_INSTALL_TEST = 1 go test -v ; if ($LASTEXITCODE -ne 0) { exit 1 } shell: powershell diff --git a/t/40_e2e_deb_linux_test.go b/t/40_e2e_deb_linux_test.go new file mode 100644 index 0000000..44d2256 --- /dev/null +++ b/t/40_e2e_deb_linux_test.go @@ -0,0 +1,104 @@ +package main + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const ( + localDEBINIPath = `/etc/snclient/snclient_local.ini` +) + +var localDEBINI = ` +[/modules] +CheckBuiltinPlugins = enabled +CheckExternalScripts = enabled + +[/settings/default] +password = test +` + +// this test requires: +// - snclient.deb +// it tries a installation and removes it afterwards +func TestDEBinstaller(t *testing.T) { + // skip test unless requested, it will uninstall existing installations + if os.Getenv("SNCLIENT_INSTALL_TEST") != "1" { + t.Skipf("SKIPPED: pkg installer test requires env SNCLIENT_INSTALL_TEST=1") + + return + } + + bin := getBinary() + require.FileExistsf(t, "snclient.deb", "snclient.deb binary must exist") + + // install deb file + runCmd(t, &cmd{ + Cmd: "sudo", + Args: []string{"apt-get", "install", "-y", "./snclient.deb"}, + }) + + requiredFiles := []string{ + "/usr/bin/snclient", + "/usr/local/bin/node_exporter", + "/etc/snclient/snclient.ini", + "/etc/snclient/cacert.pem", + "/etc/snclient/server.key", + "/etc/snclient/server.crt", + "/etc/logrotate/snclient", + } + for _, file := range requiredFiles { + require.FileExistsf(t, file, file+" has been installed") + } + + // add custom .ini + runCmd(t, &cmd{ + Cmd: "sudo", + Args: []string{"touch", localDEBINIPath}, + }) + runCmd(t, &cmd{ + Cmd: "sudo", + Args: []string{"chmod", "666", localDEBINIPath}, + }) + writeFile(t, localDEBINIPath, localDEBINI) + + waitUntilResponse(t, bin) + + // verify response + runCmd(t, &cmd{ + Cmd: bin, + Args: []string{"run", "check_nsc_web", "-k", "-p", "test", "-u", "https://localhost:8443", "check_snclient_version"}, + Like: []string{`^SNClient\+ v`}, + }) + + runCmd(t, &cmd{ + Cmd: bin, + Args: []string{"run", "check_nsc_web", "-k", "-p", "test", "-u", "https://localhost:8443", "check_uptime", "crit=uptime<2s", "warn=uptime<1s"}, + Like: []string{"OK - uptime"}, + }) + + runCmd(t, &cmd{ + Cmd: bin, + Args: []string{"run", "check_nsc_web", "-k", "-p", "test", "-u", "https://localhost:8443", "check_cpu", "crit=load>101", "warn=load>101"}, + Like: []string{"OK - CPU load is ok."}, + }) + + // cleanup + os.Remove(localDEBINIPath) + + // uninstall pkg file + runCmd(t, &cmd{ + Cmd: "sudo", + Args: []string{"apt-get", "remove", "-y", "--purge", "snclient"}, + }) + + for _, file := range requiredFiles { + assert.NoFileExistsf(t, file, file+" has been removed") + } + + // remove remaining files + os.Remove("snclient.ini") +} diff --git a/t/40_build_msi_windows_test.go b/t/41_e2e_build_msi_windows_test.go similarity index 92% rename from t/40_build_msi_windows_test.go rename to t/41_e2e_build_msi_windows_test.go index 3ef0788..a9d9255 100644 --- a/t/40_build_msi_windows_test.go +++ b/t/41_e2e_build_msi_windows_test.go @@ -49,6 +49,13 @@ check_win_snclient_test5 = & Write-Host "testpattern"; exit 3 // - windist folder to build new msi (incl. snclient.exe and windows_exporter.exe) // it builds the msi file, tries a installation and removes it afterwards func TestMSIinstaller(t *testing.T) { + // skip test unless requested, it will uninstall existing installations + if os.Getenv("SNCLIENT_INSTALL_TEST") != "1" { + t.Skipf("SKIPPED: pkg installer test requires env SNCLIENT_INSTALL_TEST=1") + + return + } + bin := getBinary() require.FileExistsf(t, bin, "snclient binary must exist") require.FileExistsf(t, "snclient.msi", "snclient.msi binary must exist") @@ -84,24 +91,7 @@ func TestMSIinstaller(t *testing.T) { runCmd(t, &cmd{Cmd: "net", Args: []string{"start", "snclient"}}) // wait a couple of seconds till daemon answers - waitUntilResponse := func() { - waitStart := time.Now() - waitUntil := time.Now().Add(10 * time.Second) - for time.Now().Before(waitUntil) { - res := runCmd(t, &cmd{ - Cmd: bin, - Args: []string{"run", "check_nsc_web", "-k", "-p", "test", "-u", "https://localhost:8443", "check_snclient_version"}, - Exit: -1, - }) - if res.ExitCode == 0 { - t.Logf("daemon responded after %s", time.Since(waitStart)) - - break - } - time.Sleep(100 * time.Millisecond) - } - } - waitUntilResponse() + waitUntilResponse(t, bin) // verify response runCmd(t, &cmd{ @@ -136,7 +126,7 @@ func TestMSIinstaller(t *testing.T) { require.FileExistsf(t, `C:\Program Files\snclient\`+file, file+" still exists") } - waitUntilResponse() + waitUntilResponse(t, bin) // verify response runCmd(t, &cmd{ diff --git a/t/42_e2e_pkg_osx_darwin_test.go b/t/42_e2e_pkg_osx_darwin_test.go new file mode 100644 index 0000000..cfc63de --- /dev/null +++ b/t/42_e2e_pkg_osx_darwin_test.go @@ -0,0 +1,97 @@ +package main + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const ( + localOSXINIPath = `/etc/snclient/snclient_local.ini` +) + +var localOSXINI = ` +[/modules] +CheckBuiltinPlugins = enabled +CheckExternalScripts = enabled + +[/settings/default] +password = test +` + +// this test requires: +// - snclient.pkg +// it tries a installation and removes it afterwards +func TestOSXinstaller(t *testing.T) { + // skip test unless requested, it will uninstall existing installations + if os.Getenv("SNCLIENT_INSTALL_TEST") != "1" { + t.Skipf("SKIPPED: pkg installer test requires env SNCLIENT_INSTALL_TEST=1") + + return + } + + bin := getBinary() + require.FileExistsf(t, "snclient.pkg", "snclient.pkg binary must exist") + + // install pkg file + runCmd(t, &cmd{ + Cmd: "/usr/sbin/installer", + Args: []string{"-pkg", "snclient.pkg", "-target", "/"}, + }) + + requiredFiles := []string{ + "/usr/local/bin/snclient", + "/usr/local/bin/snclient_uninstall.sh", + "/usr/local/bin/node_exporter", + "/etc/snclient/snclient.ini", + "/etc/snclient/cacert.pem", + "/etc/snclient/server.key", + "/etc/snclient/server.crt", + "/Library/LaunchDaemons/com.snclient.snclient.plist", + } + for _, file := range requiredFiles { + require.FileExistsf(t, file, file+" has been installed") + } + + // add custom .ini + writeFile(t, localOSXINIPath, localOSXINI) + + waitUntilResponse(t, bin) + + // verify response + runCmd(t, &cmd{ + Cmd: bin, + Args: []string{"run", "check_nsc_web", "-k", "-p", "test", "-u", "https://localhost:8443", "check_snclient_version"}, + Like: []string{`^SNClient\+ v`}, + }) + + runCmd(t, &cmd{ + Cmd: bin, + Args: []string{"run", "check_nsc_web", "-k", "-p", "test", "-u", "https://localhost:8443", "check_uptime", "crit=uptime<2s", "warn=uptime<1s"}, + Like: []string{"OK - uptime"}, + }) + + runCmd(t, &cmd{ + Cmd: bin, + Args: []string{"run", "check_nsc_web", "-k", "-p", "test", "-u", "https://localhost:8443", "check_cpu", "crit=load>101", "warn=load>101"}, + Like: []string{"OK - CPU load is ok."}, + }) + + // cleanup + os.Remove(localOSXINIPath) + + // uninstall pkg file + runCmd(t, &cmd{ + Cmd: "/usr/local/bin/snclient_uninstall.sh", + Args: []string{}, + }) + + for _, file := range requiredFiles { + assert.NoFileExistsf(t, file, file+" has been removed") + } + + // remove remaining files + os.Remove("snclient.ini") +} diff --git a/t/utils.go b/t/utils.go index 089dbea..0f9a8b8 100644 --- a/t/utils.go +++ b/t/utils.go @@ -8,13 +8,12 @@ import ( "os" "os/exec" "path/filepath" + "pkg/utils" "runtime" "syscall" "testing" "time" - "pkg/utils" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -199,6 +198,27 @@ func writeFile(t *testing.T, path, content string) { require.NoErrorf(t, err, fmt.Sprintf("writing file %s succeeded", path)) } +// wait a couple of seconds till daemon answers +func waitUntilResponse(t *testing.T, bin string) { + t.Helper() + + waitStart := time.Now() + waitUntil := time.Now().Add(10 * time.Second) + for time.Now().Before(waitUntil) { + res := runCmd(t, &cmd{ + Cmd: bin, + Args: []string{"run", "check_nsc_web", "-k", "-p", "test", "-u", "https://localhost:8443", "check_snclient_version"}, + Exit: -1, + }) + if res.ExitCode == 0 { + t.Logf("daemon responded after %s", time.Since(waitStart)) + + break + } + time.Sleep(100 * time.Millisecond) + } +} + var ( daemonPid = 0 daemonPidFile = "snclient.lock"