Skip to content

Commit

Permalink
add test during packaging to make sure Docker images run
Browse files Browse the repository at this point in the history
  • Loading branch information
leehinman committed Dec 16, 2024
1 parent 4ee171d commit 3a7b776
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 15 deletions.
7 changes: 2 additions & 5 deletions dev-tools/mage/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ func prepareIronbankBuild() error {
}
return nil
})

if err != nil {
return fmt.Errorf("cannot create templates for the IronBank: %w", err)
}
Expand Down Expand Up @@ -206,7 +205,7 @@ func saveIronbank() error {

distributionsDir := "build/distributions"
if _, err := os.Stat(distributionsDir); os.IsNotExist(err) {
err := os.MkdirAll(distributionsDir, 0750)
err := os.MkdirAll(distributionsDir, 0o750)
if err != nil {
return fmt.Errorf("cannot create folder for docker artifacts: %w", err)
}
Expand Down Expand Up @@ -348,9 +347,7 @@ func TestPackages(options ...TestPackagesOption) error {
args = append(args, "-files", MustExpand("{{.PWD}}/build/distributions/*"))

if out, err := goTest(args...); err != nil {
if !mg.Verbose() {
fmt.Println(out)
}
fmt.Println(out)
return err
}

Expand Down
113 changes: 103 additions & 10 deletions dev-tools/packaging/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import (
"bufio"
"bytes"
"compress/gzip"
"context"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
Expand All @@ -36,18 +38,19 @@ import (
"slices"
"strings"
"testing"

"errors"
"time"

"github.com/blakesmith/ar"
rpm "github.com/cavaliergopher/rpm"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
)

const (
expectedConfigMode = os.FileMode(0600)
expectedManifestMode = os.FileMode(0644)
expectedConfigMode = os.FileMode(0o600)
expectedManifestMode = os.FileMode(0o644)
expectedModuleFileMode = expectedManifestMode
expectedModuleDirMode = os.FileMode(0755)
expectedModuleDirMode = os.FileMode(0o755)
)

var (
Expand Down Expand Up @@ -234,15 +237,15 @@ func checkDocker(t *testing.T, file string) {
t.Errorf("error reading file %v: %v", file, err)
return
}

checkDockerEntryPoint(t, p, info)
checkDockerLabels(t, p, info, file)
checkDockerUser(t, p, info, *rootUserContainer)
checkConfigPermissionsWithMode(t, p, os.FileMode(0644))
checkManifestPermissionsWithMode(t, p, os.FileMode(0644))
checkConfigPermissionsWithMode(t, p, os.FileMode(0o644))
checkManifestPermissionsWithMode(t, p, os.FileMode(0o644))
checkModulesPresent(t, "", p)
checkModulesDPresent(t, "", p)
checkLicensesPresent(t, "licenses/", p)
checkDockerImageRun(t, p, file)
}

// Verify that the main configuration file is installed with a 0600 file mode.
Expand Down Expand Up @@ -356,7 +359,7 @@ func checkModulesOwner(t *testing.T, p *packageFile, expectRoot bool) {
// Verify that the systemd unit file has a mode of 0644. It should not be
// executable.
func checkSystemdUnitPermissions(t *testing.T, p *packageFile) {
const expectedMode = os.FileMode(0644)
const expectedMode = os.FileMode(0o644)
t.Run(p.Name+" systemd unit file permissions", func(t *testing.T) {
for _, entry := range p.Contents {
if systemdUnitFilePattern.MatchString(entry.File) {
Expand Down Expand Up @@ -443,7 +446,7 @@ func checkLicensesPresent(t *testing.T, prefix string, p *packageFile) {
}

func checkDockerEntryPoint(t *testing.T, p *packageFile, info *dockerInfo) {
expectedMode := os.FileMode(0755)
expectedMode := os.FileMode(0o755)

t.Run(fmt.Sprintf("%s entrypoint", p.Name), func(t *testing.T) {
if len(info.Config.Entrypoint) == 0 {
Expand Down Expand Up @@ -511,6 +514,96 @@ func checkDockerUser(t *testing.T, p *packageFile, info *dockerInfo, expectRoot
})
}

func checkDockerImageRun(t *testing.T, p *packageFile, imagePath string) {
t.Run(fmt.Sprintf("%s check docker images runs", p.Name), func(t *testing.T) {
f, err := os.Open(imagePath)
if err != nil {
t.Errorf("failed to open docker image %q: %s", imagePath, err)
}
defer f.Close()

c, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Errorf("failed to get a Docker client: %s", err)
}

loadResp, err := c.ImageLoad(context.Background(), f, true)
if err != nil {
t.Errorf("error loading docker image: %s", err)
}

loadRespBody, err := io.ReadAll(loadResp.Body)
if err != nil {
t.Errorf("failed to read image load response: %s", err)
}
loadResp.Body.Close()

_, after, found := strings.Cut(string(loadRespBody), "Loaded image: ")
if !found {
t.Errorf("image load response was unexpected: %s", string(loadRespBody))
}
imageId := strings.TrimRight(after, "\\n\"}\r\n")

createResp, err := c.ContainerCreate(context.Background(),
&container.Config{
Image: imageId,
},
nil,
nil,
nil,
"")
if err != nil {
t.Logf("error creating container from image: %s", err)
}
defer func() {
err := c.ContainerRemove(context.Background(), createResp.ID, container.RemoveOptions{Force: true})
if err != nil {
t.Errorf("error removing container: %s", err)
}
}()

err = c.ContainerStart(context.Background(), createResp.ID, container.StartOptions{})
if err != nil {
t.Errorf("failed to start container: %s", err)
}
defer func() {
err := c.ContainerStop(context.Background(), createResp.ID, container.StopOptions{})
if err != nil {
t.Errorf("error stopping container: %s", err)
}
}()

timer := time.NewTimer(15 * time.Second)
defer timer.Stop()
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()

var logs []byte
sentinelLog := "Beat ID: "
for {
select {
case <-timer.C:
t.Logf("logs were %s", string(logs))
t.Errorf("never saw %q within timeout", sentinelLog)
goto done
case <-ticker.C:
out, err := c.ContainerLogs(context.Background(), createResp.ID, container.LogsOptions{ShowStdout: true, ShowStderr: true})
if err != nil {
t.Errorf("could not get logs: %s", err)
}
logs, err = io.ReadAll(out)
if err != nil {
t.Errorf("error reading logs: %s", err)
}
if bytes.Contains(logs, []byte(sentinelLog)) {
goto done
}
}
}
done:
})
}

// ensureNoBuildIDLinks checks for regressions related to
// https://github.com/elastic/beats/issues/12956.
func ensureNoBuildIDLinks(t *testing.T, p *packageFile) {
Expand Down

0 comments on commit 3a7b776

Please sign in to comment.