Skip to content

Commit

Permalink
test: add test for packager source (#2525)
Browse files Browse the repository at this point in the history
## Description

This change adds tests for packager source which tests all
implementations.

## Related Issue

Relates to #2512 

## Checklist before merging

- [x] Test, docs, adr added or updated as needed
- [x] [Contributor Guide
Steps](https://github.com/defenseunicorns/zarf/blob/main/.github/CONTRIBUTING.md#developer-workflow)
followed

---------

Co-authored-by: Lucas Rodriguez <lucas.rodriguez@defenseunicorns.com>
  • Loading branch information
phillebaba and Lucas Rodriguez authored May 23, 2024
1 parent f003c94 commit a69c44f
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 33 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ zarf-sbom/
test-*.txt
__debug_bin
.netlify
!**/testdata/**
coverage.out
196 changes: 164 additions & 32 deletions src/pkg/packager/sources/new_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,181 @@
package sources

import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"

"github.com/defenseunicorns/zarf/src/types"
"github.com/stretchr/testify/require"

"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/packager/filters"
"github.com/defenseunicorns/zarf/src/types"
)

var ociS *OCISource
var urlS *URLSource
var tarballS *TarballSource
var splitS *SplitTarballSource
var packageS *PackageSource
func TestNewPackageSource(t *testing.T) {
t.Parallel()

type source struct {
pkgSrc string
srcType string
source PackageSource
}
tests := []struct {
name string
src string
expectedIdentify string
expectedType PackageSource
}{
{
name: "oci",
src: "oci://ghcr.io/defenseunicorns/packages/init:1.0.0",
expectedIdentify: "oci",
expectedType: &OCISource{},
},
{
name: "sget with sub path",
src: "sget://github.com/defenseunicorns/zarf-hello-world:x86",
expectedIdentify: "sget",
expectedType: &URLSource{},
},
{
name: "sget without host",
src: "sget://defenseunicorns/zarf-hello-world:x86_64",
expectedIdentify: "sget",
expectedType: &URLSource{},
},
{
name: "https",
src: "https://github.com/defenseunicorns/zarf/releases/download/v1.0.0/zarf-init-amd64-v1.0.0.tar.zst",
expectedIdentify: "https",
expectedType: &URLSource{},
},
{
name: "http",
src: "http://github.com/defenseunicorns/zarf/releases/download/v1.0.0/zarf-init-amd64-v1.0.0.tar.zst",
expectedIdentify: "http",
expectedType: &URLSource{},
},
{
name: "local tar init zst",
src: "zarf-init-amd64-v1.0.0.tar.zst",
expectedIdentify: "tarball",
expectedType: &TarballSource{},
},
{
name: "local tar",
src: "zarf-package-manifests-amd64-v1.0.0.tar",
expectedIdentify: "tarball",
expectedType: &TarballSource{},
},
{
name: "local tar manifest zst",
src: "zarf-package-manifests-amd64-v1.0.0.tar.zst",
expectedIdentify: "tarball",
expectedType: &TarballSource{},
},
{
name: "local tar split",
src: "testdata/.part000",
expectedIdentify: "split",
expectedType: &SplitTarballSource{},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

var sources = []source{
{pkgSrc: "oci://ghcr.io/defenseunicorns/packages/init:1.0.0", srcType: "oci", source: ociS},
{pkgSrc: "sget://github.com/defenseunicorns/zarf-hello-world:x86", srcType: "sget", source: urlS},
{pkgSrc: "sget://defenseunicorns/zarf-hello-world:x86_64", srcType: "sget", source: urlS},
{pkgSrc: "https://github.com/defenseunicorns/zarf/releases/download/v1.0.0/zarf-init-amd64-v1.0.0.tar.zst", srcType: "https", source: urlS},
{pkgSrc: "http://github.com/defenseunicorns/zarf/releases/download/v1.0.0/zarf-init-amd64-v1.0.0.tar.zst", srcType: "http", source: urlS},
{pkgSrc: "zarf-init-amd64-v1.0.0.tar.zst", srcType: "tarball", source: tarballS},
{pkgSrc: "zarf-package-manifests-amd64-v1.0.0.tar", srcType: "tarball", source: tarballS},
{pkgSrc: "zarf-package-manifests-amd64-v1.0.0.tar.zst", srcType: "tarball", source: tarballS},
{pkgSrc: "some-dir/.part000", srcType: "split", source: splitS},
require.Equal(t, tt.expectedIdentify, Identify(tt.src))
ps, err := New(&types.ZarfPackageOptions{PackageSource: tt.src})
require.NoError(t, err)
require.IsType(t, tt.expectedType, ps)
})
}
}

func Test_identifySourceType(t *testing.T) {
for _, source := range sources {
actual := Identify(source.pkgSrc)
require.Equalf(t, source.srcType, actual, fmt.Sprintf("source: %s", source))
func TestPackageSource(t *testing.T) {
t.Parallel()

// Copy tar to a temp directory, otherwise Collect will delete it.
tarName := "zarf-package-wordpress-amd64-16.0.4.tar.zst"
testDir := t.TempDir()
src, err := os.Open(filepath.Join("testdata", tarName))
require.NoError(t, err)
tarPath := filepath.Join(testDir, tarName)
dst, err := os.Create(tarPath)
require.NoError(t, err)
_, err = io.Copy(dst, src)
require.NoError(t, err)
src.Close()
dst.Close()

b, err := os.ReadFile("./testdata/expected-pkg.json")
require.NoError(t, err)
expectedPkg := types.ZarfPackage{}
err = json.Unmarshal(b, &expectedPkg)
require.NoError(t, err)

ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
_, fp := filepath.Split(req.URL.Path)
f, err := os.Open(filepath.Join("testdata", fp))
if err != nil {
rw.WriteHeader(http.StatusNotFound)
return
}
defer f.Close()
io.Copy(rw, f)
}))

tests := []struct {
name string
src string
shasum string
}{
{
name: "local",
src: tarPath,
},
{
name: "http",
src: fmt.Sprintf("%s/zarf-package-wordpress-amd64-16.0.4.tar.zst", ts.URL),
shasum: "835b06fc509e639497fb45f45d432e5c4cbd5d84212db5357b16bc69724b0e26",
},
}
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

opts := &types.ZarfPackageOptions{
PackageSource: tt.src,
Shasum: tt.shasum,
}

ps, err := New(opts)
require.NoError(t, err)
packageDir := t.TempDir()
pkgLayout := layout.New(packageDir)
pkg, warnings, err := ps.LoadPackage(pkgLayout, filters.Empty(), false)
require.NoError(t, err)
require.Empty(t, warnings)
require.Equal(t, expectedPkg, pkg)

ps, err = New(opts)
require.NoError(t, err)
metadataDir := t.TempDir()
metadataLayout := layout.New(metadataDir)
metadata, warnings, err := ps.LoadPackageMetadata(metadataLayout, true, false)
require.NoError(t, err)
require.Empty(t, warnings)
require.Equal(t, expectedPkg, metadata)

func TestNew(t *testing.T) {
for _, source := range sources {
actual, err := New(&types.ZarfPackageOptions{PackageSource: source.pkgSrc})
require.NoError(t, err)
require.IsType(t, source.source, actual)
require.Implements(t, packageS, actual)
ps, err = New(opts)
require.NoError(t, err)
collectDir := t.TempDir()
fp, err := ps.Collect(collectDir)
require.NoError(t, err)
require.Equal(t, filepath.Join(collectDir, filepath.Base(tt.src)), fp)
})
}
}
31 changes: 30 additions & 1 deletion src/pkg/packager/sources/tarball.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,5 +204,34 @@ func (s *TarballSource) LoadPackageMetadata(dst *layout.PackagePaths, wantSBOM b
// Collect for the TarballSource is essentially an `mv`
func (s *TarballSource) Collect(dir string) (string, error) {
dst := filepath.Join(dir, filepath.Base(s.PackageSource))
return dst, os.Rename(s.PackageSource, dst)
err := os.Rename(s.PackageSource, dst)
linkErr := &os.LinkError{}
isLinkErr := errors.As(err, &linkErr)
if err != nil && !isLinkErr {
return "", err
}
if err == nil {
return dst, nil
}

// Copy file if rename is not possible due to existing on different partitions.
srcFile, err := os.Open(linkErr.Old)
if err != nil {
return "", err
}
defer srcFile.Close()
dstFile, err := os.Create(linkErr.New)
if err != nil {
return "", err
}
defer dstFile.Close()
_, err = io.Copy(dstFile, srcFile)
if err != nil {
return "", err
}
err = os.Remove(linkErr.Old)
if err != nil {
return "", err
}
return dst, nil
}
23 changes: 23 additions & 0 deletions src/pkg/packager/sources/testdata/expected-pkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"kind": "ZarfPackageConfig",
"metadata": {
"name": "wordpress",
"description": "\"A Zarf Package that deploys the WordPress blogging and content management platform\"\n",
"version": "16.0.4",
"architecture": "amd64",
"aggregateChecksum": "cd6cc0c238c45982d80b55d3dd3d27497d4f3b264e0f037a37c464be34a3640e"
},
"build": {
"terminal": "control-center",
"user": "philip",
"architecture": "amd64",
"timestamp": "Wed, 22 May 2024 10:16:55 +0200",
"version": "v0.33.1",
"migrations": [
"scripts-to-actions",
"pluralize-set-variable"
],
"lastNonBreakingVersion": "v0.27.0"
},
"components": []
}
Binary file not shown.
6 changes: 6 additions & 0 deletions src/pkg/packager/sources/testdata/zarf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: ZarfPackageConfig
metadata:
name: wordpress
version: 16.0.4
description: |
"A Zarf Package that deploys the WordPress blogging and content management platform"

0 comments on commit a69c44f

Please sign in to comment.