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

feat: create manifest.wall #142

Merged
merged 88 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 73 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
5e21a18
feat: create manifest.wall
letFunny Jul 1, 2024
07ca4d7
address review comments
letFunny Jul 2, 2024
af60a6f
feat: parse generate property in sdf
letFunny Jul 2, 2024
55bd81d
redo manifest package to not unmarshall everything
letFunny Jul 2, 2024
e96e87b
feat: internal manifest package
letFunny Jul 2, 2024
26022fd
fix slicer tests
letFunny Jul 2, 2024
dfba7b3
lint errors
letFunny Jul 2, 2024
1ea56d1
remove unnecessary constants
letFunny Jul 2, 2024
1f1177a
do not aggregate manifest twice for tests
letFunny Jul 3, 2024
fe51371
minor rename
letFunny Jul 5, 2024
655b17a
add generate to README
letFunny Jul 5, 2024
401c86e
make validate optional and use structs for prefixes
letFunny Jul 9, 2024
8600db6
indent manifest jsonwall in tests
letFunny Jul 9, 2024
e2c2645
address review comments
letFunny Jul 10, 2024
140ab91
change maps for structs with omitempty, jsonwall iterator
letFunny Jul 10, 2024
3faa139
move path specification to function
letFunny Jul 10, 2024
94ff54a
remove redundant comment
letFunny Jul 10, 2024
131472b
conflict resolution works properly with generate and solve bugfix
letFunny Jul 10, 2024
b8f91bf
make GetGeneratePath private and change name
letFunny Jul 10, 2024
426ca94
remove incomplete error messages
letFunny Jul 10, 2024
e16eb2e
performance optimization
letFunny Jul 10, 2024
eff44b1
remove redundant check that could never occur
letFunny Jul 10, 2024
01f01f2
avoid using slices.Concat which is not in Go 1.21
letFunny Jul 10, 2024
2ee0286
refactor manifest iteration with generic helper
letFunny Jul 12, 2024
a0200f1
restrict generic with interface union type
letFunny Jul 12, 2024
cdaf78d
feat: add IterateContents
letFunny Jul 26, 2024
efa9b44
feat: use higher level API internally in manifest.Validate
letFunny Jul 26, 2024
e6f38d9
validate schema when reading manifest
letFunny Jul 26, 2024
7e19d3f
reword comment per PR suggestion
letFunny Jul 26, 2024
f41c82b
TODO
letFunny Aug 5, 2024
48d58ee
duplication is not an error
letFunny Aug 5, 2024
101c3d4
duplication is ub, not allowed
letFunny Aug 6, 2024
89174b4
Merge branch 'main' into chisel-db-manifest-package
letFunny Aug 6, 2024
301f506
Merge branch 'main' into chisel-db-parse-generate
letFunny Aug 6, 2024
49950a0
documentation and move code for better readability
letFunny Aug 8, 2024
597e3ad
Merge branch 'chisel-db-manifest-package' into chisel-db-create-manifest
letFunny Aug 12, 2024
c4aa806
validate manifest entry, TODO
letFunny Aug 13, 2024
481f69f
pass by pointer instead of value
letFunny Aug 19, 2024
56dd49c
use double quotes
letFunny Aug 19, 2024
8dfcd2b
Read takes io.Reader
letFunny Aug 19, 2024
4e0e33b
remove unnecessary zstd for manifest_test
letFunny Aug 19, 2024
58531e9
address other review comments
letFunny Aug 19, 2024
8fa3b3d
rework algorithm to avoid all the copying into slices
letFunny Aug 19, 2024
b06fdd1
last version of the conflict resolution algorithm
letFunny Aug 20, 2024
1cd1fe1
make failure string order deterministic
letFunny Aug 21, 2024
659218f
remove unnecessary comment and add note about transitiveness
letFunny Aug 27, 2024
53c0785
address review comments
letFunny Aug 28, 2024
e84a5d7
Merge branch 'chisel-db-parse-generate' into chisel-db-create-manifest
letFunny Aug 29, 2024
14850bf
Merge branch 'chisel-db-manifest-package' into chisel-db-create-manifest
letFunny Aug 29, 2024
391119e
working
letFunny Aug 29, 2024
154697b
test mode of manifest
letFunny Aug 29, 2024
cc5b6de
simplify removing extra type
letFunny Aug 29, 2024
6ad27a1
typo
letFunny Aug 29, 2024
475a2c5
simplify
letFunny Aug 29, 2024
c7e9693
remove redundant comments
letFunny Aug 29, 2024
ac59f75
Merge branch 'main' into chisel-db-create-manifest
letFunny Aug 30, 2024
c6f925d
lint
letFunny Aug 30, 2024
9e2ecfb
simplify
letFunny Aug 30, 2024
ee83c93
bugfix: proper until calculation for content created outside packages
letFunny Aug 30, 2024
cb3db41
remove redundant comments
letFunny Aug 30, 2024
93a2218
Merge branch 'main' into chisel-db-create-manifest
letFunny Sep 16, 2024
a9528bd
tidy up
letFunny Sep 16, 2024
3fb0904
move reading manifest to auxiliary function
letFunny Sep 17, 2024
f123d37
testutil.Archive pkgs -> packages
letFunny Sep 17, 2024
d6e048b
make manifest.{FileMode,FileName} private
letFunny Sep 23, 2024
687b21e
archive.Fetch returns PackageInfo
letFunny Sep 23, 2024
212eb46
test for slicer not generating a manifest
letFunny Sep 25, 2024
a662826
rename Hash -> SHA256
letFunny Sep 23, 2024
8a64032
reword comment
letFunny Sep 25, 2024
293fd06
move manifest creation to small functions
letFunny Sep 25, 2024
9b03b95
make LocateManifestSlices public and tested
letFunny Sep 26, 2024
962566a
lint: remove unused variable
letFunny Sep 26, 2024
aaf70b1
add comment to clarify conflict resolution
letFunny Sep 26, 2024
189a3bf
move info logic into helper function
letFunny Sep 27, 2024
7fa6ee9
move report and generateManifest to manifest package
letFunny Sep 27, 2024
07a0549
lint: check error of WalkDir function
letFunny Sep 27, 2024
573427c
manifest.Write interface accepts a Writer
letFunny Sep 27, 2024
f9d1aaf
lint: check error in tests
letFunny Sep 30, 2024
dad0ed7
create report entries for the manifest files to unify logic
letFunny Sep 30, 2024
087d09d
rename LocateManifestSlices to FindPaths
letFunny Sep 30, 2024
a0920b5
manifestAddReport now takes Report
letFunny Sep 30, 2024
2a0371c
better root handling report
letFunny Sep 30, 2024
86c6e7b
Hash -> SHA256
letFunny Sep 30, 2024
e070332
move manifest generation to auxiliary function
letFunny Sep 30, 2024
b39cfe7
better comment
letFunny Sep 30, 2024
8445042
default manifest filename for FindPaths
letFunny Sep 30, 2024
a9ee6ac
remove unused ManifestSlices
letFunny Sep 30, 2024
88a11fa
report cannot be null when writing manifest
letFunny Sep 30, 2024
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
2 changes: 1 addition & 1 deletion cmd/chisel/cmd_cut.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (cmd *cmdCut) Execute(args []string) error {
archives[archiveName] = openArchive
}

_, err = slicer.Run(&slicer.RunOptions{
err = slicer.Run(&slicer.RunOptions{
Selection: selection,
Archives: archives,
TargetDir: cmd.RootDir,
Expand Down
36 changes: 32 additions & 4 deletions internal/archive/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,16 @@ import (

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

type PackageInfo struct {
Name string
Version string
Arch string
SHA256 string
}

type Options struct {
Expand Down Expand Up @@ -112,18 +120,38 @@ func (a *ubuntuArchive) selectPackage(pkg string) (control.Section, *ubuntuIndex
return selectedSection, selectedIndex, nil
}

func (a *ubuntuArchive) Fetch(pkg string) (io.ReadCloser, error) {
func (a *ubuntuArchive) Fetch(pkg string) (io.ReadCloser, *PackageInfo, error) {
section, index, err := a.selectPackage(pkg)
if err != nil {
return nil, err
return nil, nil, err
}
suffix := section.Get("Filename")
logf("Fetching %s...", suffix)
reader, err := index.fetch("../../"+suffix, section.Get("SHA256"), fetchBulk)
if err != nil {
return nil, nil, err
}
info := &PackageInfo{
Name: section.Get("Package"),
Version: section.Get("Version"),
Arch: section.Get("Architecture"),
SHA256: section.Get("SHA256"),
}
return reader, info, nil
letFunny marked this conversation as resolved.
Show resolved Hide resolved
}

func (a *ubuntuArchive) Info(pkg string) (*PackageInfo, error) {
section, _, err := a.selectPackage(pkg)
if err != nil {
return nil, err
}
return reader, nil
info := &PackageInfo{
Name: section.Get("Package"),
Version: section.Get("Version"),
Arch: section.Get("Architecture"),
SHA256: section.Get("SHA256"),
}
return info, nil
}

const ubuntuURL = "http://archive.ubuntu.com/ubuntu/"
Expand Down
107 changes: 96 additions & 11 deletions internal/archive/archive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,17 +205,29 @@ func (s *httpSuite) TestFetchPackage(c *C) {
PubKeys: []*packet.PublicKey{s.pubKey},
}

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

// First on component main.
pkg, err := archive.Fetch("mypkg1")
pkg, info, err := testArchive.Fetch("mypkg1")
c.Assert(err, IsNil)
c.Assert(info, DeepEquals, &archive.PackageInfo{
Name: "mypkg1",
Version: "1.1",
Arch: "amd64",
SHA256: "1f08ef04cfe7a8087ee38a1ea35fa1810246648136c3c42d5a61ad6503d85e05",
})
c.Assert(read(pkg), Equals, "mypkg1 1.1 data")

// Last on component universe.
pkg, err = archive.Fetch("mypkg4")
pkg, info, err = testArchive.Fetch("mypkg4")
c.Assert(err, IsNil)
c.Assert(info, DeepEquals, &archive.PackageInfo{
Name: "mypkg4",
Version: "1.4",
Arch: "amd64",
SHA256: "54af70097b30b33cfcbb6911ad3d0df86c2d458928169e348fa7873e4fc678e4",
})
c.Assert(read(pkg), Equals, "mypkg4 1.4 data")
}

Expand All @@ -235,17 +247,29 @@ func (s *httpSuite) TestFetchPortsPackage(c *C) {
PubKeys: []*packet.PublicKey{s.pubKey},
}

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

// First on component main.
pkg, err := archive.Fetch("mypkg1")
pkg, info, err := testArchive.Fetch("mypkg1")
c.Assert(err, IsNil)
c.Assert(info, DeepEquals, &archive.PackageInfo{
Name: "mypkg1",
Version: "1.1",
Arch: "arm64",
SHA256: "1f08ef04cfe7a8087ee38a1ea35fa1810246648136c3c42d5a61ad6503d85e05",
})
c.Assert(read(pkg), Equals, "mypkg1 1.1 data")

// Last on component universe.
pkg, err = archive.Fetch("mypkg4")
pkg, info, err = testArchive.Fetch("mypkg4")
c.Assert(err, IsNil)
c.Assert(info, DeepEquals, &archive.PackageInfo{
Name: "mypkg4",
Version: "1.4",
Arch: "arm64",
SHA256: "54af70097b30b33cfcbb6911ad3d0df86c2d458928169e348fa7873e4fc678e4",
})
c.Assert(read(pkg), Equals, "mypkg4 1.4 data")
}

Expand Down Expand Up @@ -273,15 +297,27 @@ func (s *httpSuite) TestFetchSecurityPackage(c *C) {
PubKeys: []*packet.PublicKey{s.pubKey},
}

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

pkg, err := archive.Fetch("mypkg1")
pkg, info, err := testArchive.Fetch("mypkg1")
c.Assert(err, IsNil)
c.Assert(info, DeepEquals, &archive.PackageInfo{
Name: "mypkg1",
Version: "1.1.2.2",
Arch: "amd64",
SHA256: "5448585bdd916e5023eff2bc1bc3b30bcc6ee9db9c03e531375a6a11ddf0913c",
})
c.Assert(read(pkg), Equals, "package from jammy-security")

pkg, err = archive.Fetch("mypkg2")
pkg, info, err = testArchive.Fetch("mypkg2")
c.Assert(err, IsNil)
c.Assert(info, DeepEquals, &archive.PackageInfo{
Name: "mypkg2",
Version: "1.2",
Arch: "amd64",
SHA256: "a4b4f3f3a8fa09b69e3ba23c60a41a1f8144691fd371a2455812572fd02e6f79",
})
c.Assert(read(pkg), Equals, "mypkg2 1.2 data")
}

Expand Down Expand Up @@ -399,6 +435,53 @@ func (s *httpSuite) TestVerifyArchiveRelease(c *C) {
}
}

var packageInfoTests = []struct {
summary string
pkg string
info *archive.PackageInfo
error string
}{{
summary: "Basic",
pkg: "mypkg1",
info: &archive.PackageInfo{
Name: "mypkg1",
Version: "1.1",
Arch: "amd64",
SHA256: "1f08ef04cfe7a8087ee38a1ea35fa1810246648136c3c42d5a61ad6503d85e05",
},
}, {
summary: "Package not found in archive",
pkg: "mypkg99",
error: `cannot find package "mypkg99" in archive`,
}}

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(),
PubKeys: []*packet.PublicKey{s.pubKey},
}

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

for _, test := range packageInfoTests {
info, err := testArchive.Info(test.pkg)
if test.error != "" {
c.Assert(err, ErrorMatches, test.error)
continue
}
c.Assert(err, IsNil)
c.Assert(info, DeepEquals, test.info)
}
}

func read(r io.Reader) string {
data, err := io.ReadAll(r)
if err != nil {
Expand Down Expand Up @@ -481,13 +564,15 @@ func (s *S) testOpenArchiveArch(c *C, release ubuntuRelease, arch string) {
PubKeys: release.archivePubKeys,
}

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

extractDir := c.MkDir()

pkg, err := archive.Fetch("hostname")
pkg, info, err := testArchive.Fetch("hostname")
c.Assert(err, IsNil)
c.Assert(info.Name, DeepEquals, "hostname")
c.Assert(info.Arch, DeepEquals, arch)

err = deb.Extract(pkg, &deb.ExtractOptions{
Package: "hostname",
Expand Down
22 changes: 20 additions & 2 deletions internal/manifest/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package manifest
import (
"fmt"
"io"
"path/filepath"
"slices"
"strings"

"github.com/canonical/chisel/internal/jsonwall"
"github.com/canonical/chisel/internal/setup"
)

const schema = "1.0"
const Schema = "1.0"

type Package struct {
Kind string `json:"kind"`
Expand Down Expand Up @@ -59,7 +61,7 @@ func Read(reader io.Reader) (manifest *Manifest, err error) {
return nil, err
}
mfestSchema := db.Schema()
if mfestSchema != schema {
if mfestSchema != Schema {
return nil, fmt.Errorf("unknown schema version %q", mfestSchema)
}

Expand Down Expand Up @@ -158,6 +160,22 @@ func Validate(manifest *Manifest) (err error) {
return nil
}

// LocateManifestSlices finds the paths marked with "generate:manifest" and
// returns a map from the manifest path to all the slices that declare it.
func LocateManifestSlices(slices []*setup.Slice, manifestFileName string) map[string][]*setup.Slice {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's please rename this function to manifest.FindPaths (per docs), and have it taking the slices as its single argument. The manifest filename should be in this package since the slicer has no use for it given this function is the one pointing to the targets.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done in 087d09d.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The remaining part about the manifestFileName I wonder whether you should be able to customize it. If I want to write it to somewhere that is not manifest.wall then I should still be able to use this function. Maybe instead of taking manifestFileName we could return the directory and the caller is the one expected to concatenate the filename.

Copy link
Contributor

Choose a reason for hiding this comment

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

This function is pointing out what is the standard path given the following slices. We can write manifests anywhere using manifest.Write.

Do I misunderstand the issue?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, just that I thought the helper should be more generic and that in our previous conversations we said to move the manifest filename to slicer and keep manifest generic. I will move it back here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done in 8445042.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the conversation was about moving the function itself to slicer, for reasons related to what we've been discussing in this iteration. The comment now was about the fact we chose not to move the function out of manifest, and yet the filename is still there.

manifestSlices := make(map[string][]*setup.Slice)
for _, slice := range slices {
for path, info := range slice.Contents {
if info.Generate == setup.GenerateManifest {
dir := strings.TrimSuffix(path, "**")
path = filepath.Join(dir, manifestFileName)
manifestSlices[path] = append(manifestSlices[path], slice)
}
}
}
return manifestSlices
}

type prefixable interface {
Path | Content | Package | Slice
}
Expand Down
Loading
Loading