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

Test framework #28

Merged
merged 5 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Tests
on:
push:
pull_request:
branches:
- main

jobs:
test:
name: Build and run all tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: build
run: docker compose --env-file=test/compose/.env.test -f test/compose/docker-compose.yml run composectl make
- name: test
run: docker compose --env-file=test/compose/.env.test -f test/compose/docker-compose.yml run composectl make test-e2e
- name: teardown test env
run: docker compose --env-file=test/compose/.env.test -f test/compose/docker-compose.yml down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea
bin/
.cache
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,10 @@ check: format

tidy-mod:
go mod tidy -go=$(MODVER)

preload-images:
test/fixtures/preload-images.sh

# target should be run only in the dev container
test-e2e: $(exe) preload-images
go test -v ./...
25 changes: 15 additions & 10 deletions cmd/composectl/cmd/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,24 @@ type (
CheckInstall bool
}

checkAppResult struct {
CheckAppResult struct {
MissingBlobs map[digest.Digest]compose.BlobInfo `json:"missing_blobs"`
TotalPullSize int64 `json:"total_pull_size"`
TotalStoreSize int64 `json:"total_store_size"`
TotalRuntimeSize int64 `json:"total_runtime_size"`
}

CheckAndInstallResult struct {
FetchCheck *CheckAppResult `json:"fetch_check"`
InstallCheck *InstallCheckResult `json:"install_check"`
}

appInstallCheckResult struct {
AppName string `json:"app_name"`
MissingImages []string `json:"missing_images"`
}

installCheckResult map[string]*appInstallCheckResult
InstallCheckResult map[string]*appInstallCheckResult
)

const (
Expand Down Expand Up @@ -90,7 +95,7 @@ func checkAppsCmd(cmd *cobra.Command, args []string, opts *checkOptions) {
quietCheck = true
}
cr, ui, _ := checkApps(cmd.Context(), args, *opts.UsageWatermark, *opts.SrcStorePath, quietCheck)
var ir installCheckResult
var ir InstallCheckResult
var err error
if opts.CheckInstall {
ir, err = checkIfInstalled(cmd.Context(), args, *opts.SrcStorePath, config.DockerHost)
Expand All @@ -99,8 +104,8 @@ func checkAppsCmd(cmd *cobra.Command, args []string, opts *checkOptions) {
if opts.Format == "json" {
aggregatedCheckRes :=
struct {
FetchCheck *checkAppResult `json:"fetch_check"`
InstallCheck *installCheckResult `json:"install_check"`
FetchCheck *CheckAppResult `json:"fetch_check"`
InstallCheck *InstallCheckResult `json:"install_check"`
}{
FetchCheck: cr,
InstallCheck: &ir,
Expand Down Expand Up @@ -128,7 +133,7 @@ func checkAppsCmd(cmd *cobra.Command, args []string, opts *checkOptions) {
}
}

func checkApps(ctx context.Context, appRefs []string, usageWatermark uint, srcStorePath string, quiet bool) (*checkAppResult, *compose.UsageInfo, []compose.App) {
func checkApps(ctx context.Context, appRefs []string, usageWatermark uint, srcStorePath string, quiet bool) (*CheckAppResult, *compose.UsageInfo, []compose.App) {
if usageWatermark < MinUsageWatermark {
DieNotNil(fmt.Errorf("the specified usage watermark is lower than the minimum allowed; %d < %d", usageWatermark, MinUsageWatermark))
}
Expand All @@ -151,7 +156,7 @@ func checkApps(ctx context.Context, appRefs []string, usageWatermark uint, srcSt

var apps []compose.App
blobsToPull := map[digest.Digest]compose.BlobInfo{}
checkRes := checkAppResult{MissingBlobs: blobsToPull}
checkRes := CheckAppResult{MissingBlobs: blobsToPull}

for _, appRef := range appRefs {
if !quiet {
Expand Down Expand Up @@ -229,12 +234,12 @@ func checkApps(ctx context.Context, appRefs []string, usageWatermark uint, srcSt
return &checkRes, ui, apps
}

func (cr *checkAppResult) print() {
func (cr *CheckAppResult) print() {
fmt.Printf("%d blobs to pull; total download size: %s, total store size: %s, total runtime size of missing blobs: %s, total required: %s\n",
len(cr.MissingBlobs), units.BytesSize(float64(cr.TotalPullSize)), units.BytesSize(float64(cr.TotalStoreSize)), units.BytesSize(float64(cr.TotalRuntimeSize)), units.BytesSize(float64(cr.TotalStoreSize+cr.TotalRuntimeSize)))
}

func checkIfInstalled(ctx context.Context, appRefs []string, srcStorePath string, dockerHost string) (installCheckResult, error) {
func checkIfInstalled(ctx context.Context, appRefs []string, srcStorePath string, dockerHost string) (InstallCheckResult, error) {
cli, err := compose.GetDockerClient(dockerHost)
if err != nil {
return nil, err
Expand All @@ -254,7 +259,7 @@ func checkIfInstalled(ctx context.Context, appRefs []string, srcStorePath string
}
}

checkResult := installCheckResult{}
checkResult := InstallCheckResult{}
blobProvider := compose.NewStoreBlobProvider(path.Join(srcStorePath, "blobs", "sha256"))
for _, appRef := range appRefs {
app, _, err := v1.NewAppLoader().LoadAppTree(ctx, blobProvider, platforms.OnlyStrict(config.Platform), appRef)
Expand Down
6 changes: 3 additions & 3 deletions cmd/composectl/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type (
listOptions struct {
Format string
}
appJsonOutput struct {
AppJsonOutput struct {
Name string `json:"name"`
URI string `json:"uri"`
}
Expand All @@ -42,9 +42,9 @@ func listApps(cmd *cobra.Command, args []string, opts *listOptions) {
apps, err := cs.ListApps(cmd.Context())
DieNotNil(err)
if opts.Format == "json" {
var lsOutput []appJsonOutput
var lsOutput []AppJsonOutput
for _, app := range apps {
lsOutput = append(lsOutput, appJsonOutput{
lsOutput = append(lsOutput, AppJsonOutput{
Name: app.Name,
URI: app.String(),
})
Expand Down
9 changes: 9 additions & 0 deletions dev-shell.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
down() {
docker compose --env-file=test/compose/.env.test -f test/compose/docker-compose.yml down --remove-orphans
# remove the docker runtime and compose app store volumes
docker volume rm compose_docker-runtime compose_reset-apps
}

trap down EXIT

docker compose --env-file=test/compose/.env.test -f test/compose/docker-compose.yml run composectl $@
9 changes: 9 additions & 0 deletions test/compose/.env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
SRC_DIR=$PWD
BIN_DIR=$SRC_DIR/bin
TEST_DIR=$SRC_DIR/test
CPS_DIR=$TEST_DIR/compose

REG_DIR=$CPS_DIR/registry
REG_CERT_DIR=$REG_DIR/certs
# This must be relative to SRC_DIR path
REG_CERT=test/compose/registry/certs/registry.crt
13 changes: 13 additions & 0 deletions test/compose/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM golang:1.22-alpine

ARG REG_CERT=test/compose/registry/certs/registry.crt
ARG SRC_DIR=$PWD

RUN apk add make curl docker docker-compose git

COPY $REG_CERT /etc/ssl/certs/registry.crt
RUN cat /etc/ssl/certs/registry.crt >> /etc/ssl/certs/ca-certificates.crt
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
RUN git config --global --add safe.directory $SRC_DIR
42 changes: 42 additions & 0 deletions test/compose/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
services:
registry:
image: ghcr.io/foundriesio/docker-distribution:2.8.3-fio
volumes:
- ${REG_CERT_DIR}:/certs
- ${REG_DIR}/config.yml:/etc/docker/registry/config.yml

dockerd:
image: ghcr.io/foundriesio/moby:25.0.3_fio
command: ["dockerd", "-D", "-H", "unix:///var/run/docker/docker.sock"]
privileged: true
volumes:
- docker-runtime:/var/run/docker
- ${REG_DIR}/daemon.json:/etc/docker/daemon.json:ro
- reset-apps:/var/sota/reset-apps

composectl:
build:
context: ${SRC_DIR}
dockerfile: ${CPS_DIR}/Dockerfile
args:
REG_CERT: ${REG_CERT}
SRC_DIR: ${SRC_DIR}
volumes:
- ${SRC_DIR}:${SRC_DIR}
- ${BIN_DIR}:${SRC_DIR}/bin
- docker-runtime:/var/run/docker
- reset-apps:/var/sota/reset-apps
working_dir: ${SRC_DIR}
depends_on:
- registry
- dockerd
environment:
- GOCACHE=${SRC_DIR}/.cache
- DOCKER_HOST=unix:///var/run/docker/docker.sock
- COMPOSECTL_EXE=${BIN_DIR}/composectl
- SRC_DIR=${SRC_DIR}
- STOREROOT=/var/sota/reset-apps

volumes:
docker-runtime:
reset-apps:
3 changes: 3 additions & 0 deletions test/compose/registry/certs/gen-certs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

openssl req -new -x509 -nodes -days 36500 -config openssl.cnf -keyout registry.key -out registry.crt
25 changes: 25 additions & 0 deletions test/compose/registry/certs/openssl.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_req
prompt = no

[ req_distinguished_name ]
C = US
ST = State
L = City
O = Organization
CN = registry

[ req_ext ]
subjectAltName = @alt_names

[ v3_req ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = registry
DNS.2 = localhost
IP.1 = 127.0.0.1

31 changes: 31 additions & 0 deletions test/compose/registry/certs/registry.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might include the script to generate this. You have the conf file. I remember using something like this from moby once and losing 15 minutes needing to generate a cert.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MIIFZDCCA0ygAwIBAgIUD6KzUJQJR7CPdPYnPZxOiAyNdckwDQYJKoZIhvcNAQEL
BQAwVjELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5
MRUwEwYDVQQKDAxPcmdhbml6YXRpb24xETAPBgNVBAMMCHJlZ2lzdHJ5MCAXDTI0
MDkxOTA5NTYyM1oYDzIxMjQwODI2MDk1NjIzWjBWMQswCQYDVQQGEwJVUzEOMAwG
A1UECAwFU3RhdGUxDTALBgNVBAcMBENpdHkxFTATBgNVBAoMDE9yZ2FuaXphdGlv
bjERMA8GA1UEAwwIcmVnaXN0cnkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQC7U1ouHJ/2wJt2q19gzt/rfCStH74Elwti0hQ0+Bpg97P2ooD2GixYzWHx
Y5oeVoAAswVA8A0RWTOLw9qIijdWTsG32CUBSaAjdnD6TeawxsayUwUq9xZYweQJ
rGUYzsGs6fBMRjriPGLVcOw9TArEPmXMucd2W7qRrWBMrLvCXzcaETFy57uM5AQG
mEBnvXcGdOlEjN4VNv/gretSkVVX93f/Efw8MWrN+ABXXthEoKAv+iriPrfeU0JW
kx6tFr3SS7/Xg6XbRAHNWhxSfkSY8SGTv+1qeDpSv3YUBkzPcxbWWej1FCaonwmR
xIk8x1ysFJLVg8MPnvZS9TZisKajBziwoVZufKm0DrD2BVAlDlGmsqRlwwNEGg31
fRdEayqYZm8LVoOuHSPudsXRHZaLZcbiPUmucxS48EofUVrdwiGtW17vDdweEyLh
nnILtlvsSHJWN13vkxqyBlx83kGaeGFdncoQHGZLd+GaZdP4pjywLra5a/SX0qQv
qkzlOIGUhdMXE0XNpBHo8k25DLfYiTtgrZdJuWpJzqFsW0FPtgGdaJ6+8VwGSmo4
r1JM+/T5FDQWt9j/d2QQYYfpSvkxOFOb2x6Z7NuTI6eHqtWPGfDAxFv79wF7XJ8K
ZvXq29iVgXCkC0IdMLKq9HfDJ49IzTH3ozt9g3MDCUfj29oRpQIDAQABoygwJjAk
BgNVHREEHTAbgghyZWdpc3RyeYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3DQEB
CwUAA4ICAQCJMp0ia0ko27uWSELbla0rz7GBj5FBj96SlEmeAFlJum/oJiWxAdyR
ih+NzwoZoA1YszEihETVByAcevCqA0KexanS6bbJhDVh+EGJW0PQo5H/eXsrOwPF
2v932vg7occmaHyOxJQyulLv9i+NNc2Upilv49nEUCQaqrF0Ts5JS1Qe+w0ENtfR
NoB6Qmgqs5rHDDJNPsjCLvmnb3trbRzlS5VbrC30iMvcCfslcXsbl/gcCZbcJh3h
y0Ju4xP26o4xK+mW1mbCBXZJ6rByzs3B8Pn1l5K9dbKxvb6c4yw/GuTDuzzHkgG+
wBTfoqkxk/nnU4l+jgl2qT4DjCZBnonk4Abj9UP4ZPB0qLCrR7h/lfex1rOZ5Het
7Wl2aJtA19zuIAE4qMuQfgtcB8NLTrj6dWUCCmfJdhKjad+dA8uKgXYmT/NYYuvp
wr/g/Kjf7DaPs8SN+zP+MXEX6rXPCxYi5NQfpJ8bEC8o3TWLTrfWNAdkJNYS4vCf
P/QXl40YeIhjtMkyyY3LH1+yLRMc6uWd+YG9H6t7mP6+pYnIZ8uCgR2yXQQcDYDt
q4seLCcyvkOrt0eDqth4VDS1SweDyIodYPDMA9mwsBjY3AT5m0nbvhZf4vGwxDhK
elQdZQYmUjzxgz9kKjyzDPYscTZXGQramIBsskcmAsYuByYND7Nvow==
-----END CERTIFICATE-----
52 changes: 52 additions & 0 deletions test/compose/registry/certs/registry.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
cz11Y7m1L6FbApCu066rZJn9BmA2Hw==
-----END PRIVATE KEY-----
14 changes: 14 additions & 0 deletions test/compose/registry/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
version: 0.1
log:
level: debug
fields:
service: registry
environment: development
storage:
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
tls:
certificate: /certs/registry.crt
key: /certs/registry.key
3 changes: 3 additions & 0 deletions test/compose/registry/daemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"insecure-registries": ["registry:5000"]
}
Loading
Loading