Skip to content

Commit

Permalink
Merge branch 'pub/archive-package-info' into pub/slicer-cdb-record-sl…
Browse files Browse the repository at this point in the history
…ices
  • Loading branch information
woky committed Jun 22, 2023
2 parents 4b28717 + 107c2b7 commit 06f0a4a
Show file tree
Hide file tree
Showing 5 changed files with 342 additions and 15 deletions.
25 changes: 25 additions & 0 deletions internal/archive/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,17 @@ import (
"github.com/canonical/chisel/internal/deb"
)

type PackageInfo interface {
Name() string
Version() string
Arch() string
SHA256() string
}

type Archive interface {
Options() *Options
Fetch(pkg string) (io.ReadCloser, error)
Info(pkg string) PackageInfo
Exists(pkg string) bool
}

Expand Down Expand Up @@ -79,6 +87,23 @@ func (a *ubuntuArchive) Exists(pkg string) bool {
return err == nil
}

type pkgInfo struct{ control.Section }

var _ PackageInfo = pkgInfo{}

func (info pkgInfo) Name() string { return info.Get("Package") }
func (info pkgInfo) Version() string { return info.Get("Version") }
func (info pkgInfo) Arch() string { return info.Get("Architecture") }
func (info pkgInfo) SHA256() string { return info.Get("SHA256") }

func (a *ubuntuArchive) Info(pkg string) (info PackageInfo) {
section, _, _ := a.selectPackage(pkg)
if section != nil {
info = &pkgInfo{section}
}
return
}

func (a *ubuntuArchive) selectPackage(pkg string) (control.Section, *ubuntuIndex, error) {
var selectedVersion string
var selectedSection control.Section
Expand Down
33 changes: 33 additions & 0 deletions internal/archive/archive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,39 @@ func (s *httpSuite) TestFetchSecurityPackage(c *C) {
c.Assert(read(pkg), Equals, "mypkg2 1.2 data")
}

func (s *httpSuite) TestPackageInfo(c *C) {
s.prepareArchive("jammy", "22.04", "amd64", []string{"main", "universe"})

options := archive.Options{
Label: "ubuntu",
Version: "22.04",
Arch: "amd64",
Suites: []string{"jammy"},
Components: []string{"main", "universe"},
CacheDir: c.MkDir(),
}

archive, err := archive.Open(&options)
c.Assert(err, IsNil)

info1 := archive.Info("mypkg1")
c.Assert(info1, NotNil)
c.Assert(info1.Name(), Equals, "mypkg1")
c.Assert(info1.Version(), Equals, "1.1")
c.Assert(info1.Arch(), Equals, "amd64")
c.Assert(info1.SHA256(), Equals, "1f08ef04cfe7a8087ee38a1ea35fa1810246648136c3c42d5a61ad6503d85e05")

info3 := archive.Info("mypkg3")
c.Assert(info3, NotNil)
c.Assert(info3.Name(), Equals, "mypkg3")
c.Assert(info3.Version(), Equals, "1.3")
c.Assert(info3.Arch(), Equals, "amd64")
c.Assert(info3.SHA256(), Equals, "fe377bf13ba1a5cb287cb4e037e6e7321281c929405ae39a72358ef0f5d179aa")

info99 := archive.Info("mypkg99")
c.Assert(info99, IsNil)
}

func read(r io.Reader) string {
data, err := ioutil.ReadAll(r)
if err != nil {
Expand Down
190 changes: 176 additions & 14 deletions internal/slicer/slicer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,21 @@ import (
"github.com/canonical/chisel/internal/testutil"
)

var (
REG = testutil.REG
DIR = testutil.DIR
LNK = testutil.LNK
)

type testPackage struct {
info map[string]string
content []byte
}

type slicerTest struct {
summary string
arch string
pkgs map[string]map[string]testPackage
release map[string]string
slices []setup.SliceKey
hackopt func(c *C, opts *slicer.RunOptions)
Expand Down Expand Up @@ -487,6 +499,106 @@ var slicerTests = []slicerTest{{
`,
},
error: `slice base-files_myslice: content is not a file: /x/y`,
}, {
summary: "Non-default archive",
slices: []setup.SliceKey{{"base-files", "myslice"}},
release: map[string]string{
"chisel.yaml": `
format: chisel-v1
archives:
foo:
version: 22.04
components: [main, universe]
default: true
bar:
version: 22.04
components: [main]
`,
"slices/mydir/base-files.yaml": `
package: base-files
archive: bar
slices:
myslice:
contents:
/usr/bin/hello:
`,
},
result: map[string]string{
"/usr/": "dir 0755",
"/usr/bin/": "dir 0755",
"/usr/bin/hello": "file 0775 eaf29575",
},
}, {
summary: "Custom archives with custom packages",
pkgs: map[string]map[string]testPackage{
"leptons": {
"electron": testPackage{
content: testutil.MakeTestDeb([]testutil.TarEntry{
DIR(0755, "./"),
DIR(0755, "./mass/"),
REG(0644, "./mass/electron", "9.1093837015E−31 kg\n"),
DIR(0755, "./usr/"),
DIR(0755, "./usr/share/"),
DIR(0755, "./usr/share/doc/"),
DIR(0755, "./usr/share/doc/electron/"),
REG(0644, "./usr/share/doc/electron/copyright", ""),
}),
},
},
"hadrons": {
"proton": testPackage{
content: testutil.MakeTestDeb([]testutil.TarEntry{
DIR(0755, "./"),
DIR(0755, "./mass/"),
REG(0644, "./mass/proton", "1.67262192369E−27 kg\n"),
}),
},
},
},
release: map[string]string{
"chisel.yaml": `
format: chisel-v1
archives:
leptons:
version: 1
suites: [main]
components: [main, universe]
default: true
hadrons:
version: 1
suites: [main]
components: [main]
`,
"slices/mydir/electron.yaml": `
package: electron
slices:
mass:
contents:
/mass/electron:
`,
"slices/mydir/proton.yaml": `
package: proton
archive: hadrons
slices:
mass:
contents:
/mass/proton:
`,
},
slices: []setup.SliceKey{
{"electron", "mass"},
{"proton", "mass"},
},
result: map[string]string{
"/mass/": "dir 0755",
"/mass/electron": "file 0644 a1258e30",
"/mass/proton": "file 0644 a2390d10",
"/usr/": "dir 0755",
"/usr/share/": "dir 0755",
"/usr/share/doc/": "dir 0755",
"/usr/share/doc/electron/": "dir 0755",
"/usr/share/doc/electron/copyright": "file 0644 empty",
},
}}

const defaultChiselYaml = `
Expand All @@ -497,18 +609,34 @@ const defaultChiselYaml = `
components: [main, universe]
`

type testPackageInfo map[string]string

var _ archive.PackageInfo = (testPackageInfo)(nil)

func (info testPackageInfo) Name() string { return info["Package"] }
func (info testPackageInfo) Version() string { return info["Version"] }
func (info testPackageInfo) Arch() string { return info["Architecture"] }
func (info testPackageInfo) SHA256() string { return info["SHA256"] }

func (s testPackageInfo) Get(key string) (value string) {
if s != nil {
value = s[key]
}
return
}

type testArchive struct {
arch string
pkgs map[string][]byte
options archive.Options
pkgs map[string]testPackage
}

func (a *testArchive) Options() *archive.Options {
return &archive.Options{Arch: a.arch}
return &a.options
}

func (a *testArchive) Fetch(pkg string) (io.ReadCloser, error) {
if data, ok := a.pkgs[pkg]; ok {
return ioutil.NopCloser(bytes.NewBuffer(data)), nil
return ioutil.NopCloser(bytes.NewBuffer(data.content)), nil
}
return nil, fmt.Errorf("attempted to open %q package", pkg)
}
Expand All @@ -518,6 +646,18 @@ func (a *testArchive) Exists(pkg string) bool {
return ok
}

func (a *testArchive) Info(pkg string) archive.PackageInfo {
var info map[string]string
if pkgData, ok := a.pkgs[pkg]; ok {
if info = pkgData.info; info == nil {
info = map[string]string{
"Version": "1.0",
}
}
}
return testPackageInfo(info)
}

func (s *S) TestRun(c *C) {
for _, test := range slicerTests {
c.Logf("Summary: %s", test.summary)
Expand All @@ -541,19 +681,34 @@ func (s *S) TestRun(c *C) {
selection, err := setup.Select(release, test.slices)
c.Assert(err, IsNil)

pkgs := map[string][]byte{
"base-files": testutil.PackageData["base-files"],
pkgs := map[string]testPackage{
"base-files": testPackage{content: testutil.PackageData["base-files"]},
}
for name, entries := range packageEntries {
deb, err := testutil.MakeDeb(entries)
c.Assert(err, IsNil)
pkgs[name] = deb
pkgs[name] = testPackage{content: deb}
}
archives := map[string]archive.Archive{
"ubuntu": &testArchive{
arch: test.arch,
pkgs: pkgs,
},
archives := map[string]archive.Archive{}
for name, setupArchive := range release.Archives {
var archivePkgs map[string]testPackage
if test.pkgs != nil {
archivePkgs = test.pkgs[name]
}
if archivePkgs == nil {
archivePkgs = pkgs
}
archive := &testArchive{
options: archive.Options{
Label: setupArchive.Name,
Version: setupArchive.Version,
Suites: setupArchive.Suites,
Components: setupArchive.Components,
Arch: test.arch,
},
pkgs: archivePkgs,
}
archives[name] = archive
}

targetDir := c.MkDir()
Expand All @@ -575,8 +730,15 @@ func (s *S) TestRun(c *C) {

if test.result != nil {
result := make(map[string]string, len(copyrightEntries)+len(test.result))
for k, v := range copyrightEntries {
result[k] = v
if test.pkgs == nil {
// This was added in order to not specify copyright entries for each
// existing test. These tests use only the base-files embedded
// package. Custom packages may not include copyright entries
// though. So if a test defines any custom packages, it must include
// copyright entries explicitly in the results.
for k, v := range copyrightEntries {
result[k] = v
}
}
for k, v := range test.result {
result[k] = v
Expand Down
43 changes: 42 additions & 1 deletion internal/testutil/pkgdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"archive/tar"
"bytes"
"encoding/base64"
"strings"
"time"

"github.com/blakesmith/ar"
Expand Down Expand Up @@ -174,7 +175,7 @@ func fixupTarEntry(entry *TarEntry) {
if hdr.Typeflag == 0 {
if hdr.Linkname != "" {
hdr.Typeflag = tar.TypeSymlink
} else if hdr.Name[len(hdr.Name)-1] == '/' {
} else if strings.HasSuffix(hdr.Name, "/") {
hdr.Typeflag = tar.TypeDir
} else {
hdr.Typeflag = tar.TypeReg
Expand Down Expand Up @@ -265,3 +266,43 @@ func MakeDeb(entries []TarEntry) ([]byte, error) {
}
return buf.Bytes(), nil
}

func MakeTestDeb(entries []TarEntry) []byte {
data, err := MakeDeb(entries)
if err != nil {
panic(err)
}
return data
}

func REG(mode int64, path, content string) TarEntry {
return TarEntry{
Header: tar.Header{
Typeflag: tar.TypeReg,
Name: path,
Mode: mode,
},
Content: []byte(content),
}
}

func DIR(mode int64, path string) TarEntry {
return TarEntry{
Header: tar.Header{
Typeflag: tar.TypeDir,
Name: path,
Mode: mode,
},
}
}

func LNK(mode int64, path, target string) TarEntry {
return TarEntry{
Header: tar.Header{
Typeflag: tar.TypeSymlink,
Name: path,
Mode: mode,
Linkname: target,
},
}
}
Loading

0 comments on commit 06f0a4a

Please sign in to comment.