Skip to content

Commit

Permalink
feat: linux package support
Browse files Browse the repository at this point in the history
Signed-off-by: Justin Kolberg <[email protected]>
  • Loading branch information
amdprophet committed Aug 15, 2023
1 parent 79b3f24 commit a829a6a
Show file tree
Hide file tree
Showing 13 changed files with 2,226 additions and 656 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/pull_requests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,16 @@ jobs:
test-install-script:
name: Test Install Script
runs-on: ${{ matrix.runs_on }}
container:
image: ${{ inputs.container-image }}
strategy:
matrix:
include:
- arch_os: linux_amd64
runs_on: ubuntu-20.04
- arch_os: linux_amd64
runs_on: ubuntu-20.04
container-image: rocky:9
- arch_os: darwin_amd64
runs_on: macos-latest
- arch_os: windows_amd64
Expand Down
34 changes: 34 additions & 0 deletions pkg/scripts_test/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Include any files or directories that you don't want to be copied to your
# container here (e.g., local build artifacts, temporary files, etc.).
#
# For more help, visit the .dockerignore file reference guide at
# https://docs.docker.com/engine/reference/builder/#dockerignore-file

**/.DS_Store
**/__pycache__
**/.venv
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
71 changes: 66 additions & 5 deletions pkg/scripts_test/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@ func checkRun(c check) {
}

func checkConfigDirectoryOwnershipAndPermissions(c check) {
PathHasOwner(c.test, etcPath, rootUser, rootGroup)
ownerUser := systemUser
ownerGroup := systemGroup
if !c.installOptions.useNativePackaging {
ownerUser = rootUser
ownerGroup = rootGroup
}
PathHasOwner(c.test, etcPath, ownerUser, ownerGroup)
PathHasPermissions(c.test, etcPath, etcPathPermissions)
}

Expand Down Expand Up @@ -144,6 +150,54 @@ func checkAbortedDueToNoToken(c check) {
require.Contains(c.test, c.output[len(c.output)-1], "You can ignore this requirement by adding '--skip-installation-token argument.")
}

func preActionInstallPackage(c check) {
c.installOptions.installToken = installToken
c.installOptions.uninstall = false
c.installOptions.purge = false
c.installOptions.apiBaseURL = mockAPIBaseURL
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionInstallPackageWithOptions(o installOptions) checkFunc {
return func(c check) {
c.installOptions = o
c.code, c.output, c.errorOutput, c.err = runScript(c)
}
}

func preActionInstallPackageWithDifferentAPIBaseURL(c check) {
c.installOptions.apiBaseURL = "different" + c.installOptions.apiBaseURL
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionInstallPackageWithDifferentTags(c check) {
c.installOptions.tags = map[string]string{
"some": "tag",
}
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionInstallPackageWithNoAPIBaseURL(c check) {
c.installOptions.apiBaseURL = ""
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionInstallPackageWithNoTags(c check) {
c.installOptions.tags = nil
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionInstallPackageVersion(version string) checkFunc {
return func(c check) {
c.installOptions.installToken = installToken
c.installOptions.uninstall = false
c.installOptions.purge = false
c.installOptions.version = version
c.installOptions.apiBaseURL = mockAPIBaseURL
c.code, c.output, c.errorOutput, c.err = runScript(c)
}
}

func preActionMockConfig(c check) {
err := os.MkdirAll(etcPath, fs.FileMode(etcPathPermissions))
require.NoError(c.test, err)
Expand Down Expand Up @@ -199,10 +253,7 @@ func preActionWriteDifferentTagsToUserConfig(c check) {
}

func preActionWriteEmptyUserConfig(c check) {
conf, err := getConfig(userConfigPath)
require.NoError(c.test, err)

err = saveConfig(userConfigPath, conf)
err := saveConfig(userConfigPath, config{})
require.NoError(c.test, err)
}

Expand Down Expand Up @@ -232,6 +283,16 @@ func checkAbortedDueToDifferentTags(c check) {
require.Contains(c.test, c.output[len(c.output)-1], "You are trying to install with different tags than in your configuration file!")
}

func checkAbortedDueToMissingInstallationToken(c check) {
require.Greater(c.test, len(c.output), 0)
require.Contains(c.test, c.output[len(c.output)-1], "failed to create extension \"sumologic\": access credentials not provided: need installation_token")
}

func checkAbortedDueToSkipConfigUnsupported(c check) {
require.Greater(c.test, len(c.output), 0)
require.Contains(c.test, c.output[len(c.output)-1], "SKIP_CONFIG is not supported")
}

func PathHasPermissions(t *testing.T, path string, perms uint32) {
info, err := os.Stat(path)
require.NoError(t, err)
Expand Down
28 changes: 1 addition & 27 deletions pkg/scripts_test/check_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func checkLaunchdConfigNotCreated(c check) {
}

func checkPackageCreated(c check) {
re, err := regexp.Compile("Package downloaded to: .*/otelcol-sumo.pkg")
re, err := regexp.Compile(`^Package downloaded to: .*/otelcol\-sumo\_\d+\.\d+\.\d+\-\d+\-.*\.pkg$`)
require.NoError(c.test, err)

matchedLine := ""
Expand Down Expand Up @@ -118,32 +118,6 @@ func checkUserNotExists(c check) {
require.False(c.test, exists, "user has been created")
}

func preActionInstallPackage(c check) {
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionInstallPackageWithDifferentAPIBaseURL(c check) {
c.installOptions.apiBaseURL = "different" + c.installOptions.apiBaseURL
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionInstallPackageWithDifferentTags(c check) {
c.installOptions.tags = map[string]string{
"some": "tag",
}
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionInstallPackageWithNoAPIBaseURL(c check) {
c.installOptions.apiBaseURL = ""
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionInstallPackageWithNoTags(c check) {
c.installOptions.tags = nil
c.code, c.output, c.errorOutput, c.err = runScript(c)
}

func preActionMockLaunchdConfig(c check) {
f, err := os.Create(launchdPath)
require.NoError(c.test, err)
Expand Down
59 changes: 57 additions & 2 deletions pkg/scripts_test/check_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os/exec"
"os/user"
"path/filepath"
"regexp"
"strconv"
"strings"
"testing"
Expand Down Expand Up @@ -35,7 +36,20 @@ func checkConfigFilesOwnershipAndPermissions(ownerName string, ownerGroup string
if info.IsDir() {
permissions = configPathDirPermissions
} else {
permissions = configPathFilePermissions
switch path {
case configPath:
// /etc/otelcol-sumo/sumologic.yaml
permissions = configPathFilePermissions
case userConfigPath:
// /etc/otelcol-sumo/conf.d/common.yaml
permissions = commonConfigPathFilePermissions
case tokenEnvFilePath:
// /etc/otelcol-sumo/env/token.env
permissions = commonConfigPathFilePermissions
default:
// /etc/otelcol-sumo/conf.d/**/
permissions = confDPathFilePermissions
}
}
PathHasPermissions(c.test, path, permissions)
PathHasOwner(c.test, configPath, ownerName, ownerGroup)
Expand All @@ -45,6 +59,14 @@ func checkConfigFilesOwnershipAndPermissions(ownerName string, ownerGroup string
}
}

func checkDeprecatedSystemdConfigCreated(c check) {
require.FileExists(c.test, deprecatedSystemdPath, "deprecated systemd configuration has not been created properly")
}

func checkDeprecatedSystemdConfigNotCreated(c check) {
require.NoFileExists(c.test, deprecatedSystemdPath, "deprecated systemd configuration has been created")
}

func checkDeprecatedTokenInConfig(c check) {
require.NotEmpty(c.test, c.installOptions.deprecatedInstallToken, "installation token has not been provided")

Expand Down Expand Up @@ -80,10 +102,20 @@ func checkDownloadTimeout(c check) {
require.Equal(c.test, 6, count)
}

func checkGroupExists(c check) {
_, err := user.LookupGroup(systemGroup)
require.NoError(c.test, err, "group has not been created")
}

func checkGroupNotExists(c check) {
_, err := user.LookupGroup(systemGroup)
require.Error(c.test, err, "group has been created")
}

func checkHostmetricsOwnershipAndPermissions(ownerName string, ownerGroup string) func(c check) {
return func(c check) {
PathHasOwner(c.test, hostmetricsConfigPath, ownerName, ownerGroup)
PathHasPermissions(c.test, hostmetricsConfigPath, configPathFilePermissions)
PathHasPermissions(c.test, hostmetricsConfigPath, confDPathFilePermissions)
}
}

Expand All @@ -95,6 +127,22 @@ func checkOutputUserAddWarnings(c check) {
require.NotContains(c.test, errOutput, "useradd", "unexpected useradd output")
}

func checkPackageCreated(c check) {
re, err := regexp.Compile(`^Package downloaded to: .*/otelcol\-sumo\-\d+\.\d+\.\d+\-\d+\..*\.(deb|rpm)$`)
require.NoError(c.test, err)

matchedLine := ""
for _, line := range c.output {
if re.MatchString(line) {
matchedLine = line
}
}
require.NotEmpty(c.test, matchedLine, "package path not in output")

packagePath := strings.TrimPrefix(matchedLine, "Package downloaded to: ")
require.FileExists(c.test, packagePath, "package has not been created")
}

func checkSystemdAvailability(c check) bool {
return assert.DirExists(&testing.T{}, systemdDirectoryPath, "systemd is not supported")
}
Expand Down Expand Up @@ -202,6 +250,13 @@ func preActionMockConfigs(c check) {
preActionMockUserConfig(c)
}

func preActionMockDeprecatedSystemdStructure(c check) {
preActionMockStructure(c)

_, err := os.Create(deprecatedSystemdPath)
require.NoError(c.test, err)
}

func preActionMockEnvFiles(c check) {
err := os.MkdirAll(envDirectoryPath, fs.FileMode(etcPathPermissions))
require.NoError(c.test, err)
Expand Down
15 changes: 15 additions & 0 deletions pkg/scripts_test/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ type installOptions struct {
dontKeepDownloads bool
installHostmetrics bool
timeout float64
useNativePackaging bool
version string
}

func (io *installOptions) string() []string {
Expand Down Expand Up @@ -96,6 +98,14 @@ func (io *installOptions) string() []string {
opts = append(opts, "--download-timeout", fmt.Sprintf("%f", io.timeout))
}

if io.useNativePackaging {
opts = append(opts, "--use-native-packaging")
}

if io.version != "" {
opts = append(opts, "--version", io.version)
}

return opts
}

Expand All @@ -114,6 +124,11 @@ func (io *installOptions) buildEnvs() []string {
e = append(e, fmt.Sprintf("%s=%s", deprecatedInstallTokenEnv, io.deprecatedInstallToken))
}

// Enable non-interactive deb package installation & force default config
// conflict resolution
e = append(e, "DEBIAN_FRONTEND=noninteractive")
e = append(e, "DPKG_FORCE=confdef")

return e
}

Expand Down
23 changes: 23 additions & 0 deletions pkg/scripts_test/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
package sumologic_scripts_tests

import (
"context"
"io"
"net/http"
"os"
"testing"

Expand Down Expand Up @@ -43,6 +46,25 @@ func runTest(t *testing.T, spec *testSpec) {

defer tearDown(t)

t.Log("Starting HTTP server")
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "200 OK\n")
})
httpServer := &http.Server{
Addr: ":3333",
Handler: mux,
}
go func() {
err := httpServer.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
require.NoError(t, err)
}
}()
defer func() {
require.NoError(t, httpServer.Shutdown(context.Background()))
}()

t.Log("Running pre actions")
for _, a := range spec.preActions {
a(ch)
Expand All @@ -53,6 +75,7 @@ func runTest(t *testing.T, spec *testSpec) {
c(ch)
}

t.Log("Running install script")
ch.code, ch.output, ch.errorOutput, ch.err = runScript(ch)

// Remove cache in case of curl issue
Expand Down
12 changes: 12 additions & 0 deletions pkg/scripts_test/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ const (
installTokenEnv string = "SUMOLOGIC_INSTALLATION_TOKEN"
deprecatedInstallTokenEnv string = "SUMOLOGIC_INSTALL_TOKEN"
apiBaseURL string = "https://open-collectors.sumologic.com"
mockAPIBaseURL string = "http://127.0.0.1:3333"

// previousVersion specifies a previous version to test upgrades from. It is
// necessary to upgrade from an older version as same-version package
// upgrades can behave differently than proper upgrades.
previousVersion string = "0.79.0-453"

curlTimeoutErrorCode int = 28

commonConfigPathFilePermissions uint32 = 0660
configPathDirPermissions uint32 = 0770
configPathFilePermissions uint32 = 0640
confDPathFilePermissions uint32 = 0644
etcPathPermissions uint32 = 0751
)
Loading

0 comments on commit a829a6a

Please sign in to comment.