Skip to content

Commit

Permalink
Merge pull request containerd#499 from jiangliu/tarfs
Browse files Browse the repository at this point in the history
Refine tarfs overall design and implementation details
  • Loading branch information
changweige authored Aug 31, 2023
2 parents 33bca86 + f3c1541 commit 9a2575b
Show file tree
Hide file tree
Showing 18 changed files with 1,599 additions and 248 deletions.
12 changes: 10 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,16 @@ const (
)

type Experimental struct {
EnableStargz bool `toml:"enable_stargz"`
EnableReferrerDetect bool `toml:"enable_referrer_detect"`
EnableStargz bool `toml:"enable_stargz"`
EnableReferrerDetect bool `toml:"enable_referrer_detect"`
TarfsConfig TarfsConfig `toml:"tarfs"`
}

type TarfsConfig struct {
EnableTarfs bool `toml:"enable_tarfs"`
TarfsHint bool `toml:"tarfs_hint"`
MaxConcurrentProc int `toml:"max_concurrent_proc"`
ExportMode string `toml:"export_mode"`
}

type CgroupConfig struct {
Expand Down
43 changes: 43 additions & 0 deletions config/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,49 @@ func GetDaemonProfileCPUDuration() int64 {
return globalConfig.origin.SystemControllerConfig.DebugConfig.ProfileDuration
}

const (
TarfsLayerVerityOnly string = "layer_verity_only"
TarfsImageVerityOnly string = "image_verity_only"
TarfsLayerBlockDevice string = "layer_block"
TarfsImageBlockDevice string = "image_block"
TarfsLayerBlockWithVerity string = "layer_block_with_verity"
TarfsImageBlockWithVerity string = "image_block_with_verity"
)

func GetTarfsExportEnabled() bool {
switch globalConfig.origin.Experimental.TarfsConfig.ExportMode {
case TarfsLayerVerityOnly, TarfsLayerBlockDevice, TarfsLayerBlockWithVerity:
return true
case TarfsImageVerityOnly, TarfsImageBlockDevice, TarfsImageBlockWithVerity:
return true
default:
return false
}
}

// Returns (wholeImage, generateBlockImage, withVerityInfo)
// wholeImage: generate tarfs for the whole image instead of of a specific layer.
// generateBlockImage: generate a block image file.
// withVerityInfo: generate disk verity information.
func GetTarfsExportFlags() (bool, bool, bool) {
switch globalConfig.origin.Experimental.TarfsConfig.ExportMode {
case "layer_verity_only":
return false, false, true
case "image_verity_only":
return true, false, true
case "layer_block":
return false, true, false
case "image_block":
return true, true, false
case "layer_block_with_verity":
return false, true, true
case "image_block_with_verity":
return true, true, true
default:
return false, false, false
}
}

func ProcessConfigurations(c *SnapshotterConfig) error {
if c.LoggingConfig.LogDir == "" {
c.LoggingConfig.LogDir = filepath.Join(c.Root, logging.DefaultLogDirName)
Expand Down
175 changes: 175 additions & 0 deletions docs/tarfs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Nydus Tarfs Mode

`Nydus Tarfs Mode` or `Tarfs` is a working mode for Nydus Image, which uses tar files as Nydus data blobs instead of generating native Nydus data blobs.

### Enable Tarfs
`Nydus Tarfs Mode` is still an experiment feature, please edit the snapshotter configuration file to enable the feature:
```
[experimental.tarfs]
enable_tarfs = true
```

### Generate Raw Disk Image for Each Layer of a Container Image
`Tarfs` supports generating a raw disk image for each layer of a container image, which can be directly mounted as EROFS filesystem through loopdev. Please edit the snapshotter configuration file to enable this submode:
```
[experimental.tarfs]
enable_tarfs = true
export_mode = "layer_block"
```

This is an example to generate and verify raw disk image for each layer of a container image:
```
$ containerd-nydus-grpc --config /etc/nydus/config.toml &
$ nerdctl run --snapshotter nydus --rm nginx
# Show mounted rootfs a container
$ mount
/dev/loop17 on /var/lib/containerd-nydus/snapshots/7/mnt type erofs (ro,relatime,user_xattr,acl,cache_strategy=readaround)
# Show loop devices used to mount layers and bootstrap for a container image
$ losetup
NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC
/dev/loop11 0 0 0 0 /var/lib/containerd-nydus/cache/fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa 0 512
/dev/loop12 0 0 0 0 /var/lib/containerd-nydus/cache/055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3 0 512
/dev/loop13 0 0 0 0 /var/lib/containerd-nydus/cache/96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd 0 512
/dev/loop14 0 0 0 0 /var/lib/containerd-nydus/cache/a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4 0 512
/dev/loop15 0 0 0 0 /var/lib/containerd-nydus/cache/e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665 0 512
/dev/loop16 0 0 0 0 /var/lib/containerd-nydus/cache/da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75 0 512
/dev/loop17 0 0 0 0 /var/lib/containerd-nydus/snapshots/7/fs/image/image.boot 0 512
# Files without suffix are tar files, files with suffix `layer.disk` are raw disk image for container image layers
$ ls -l /var/lib/containerd-nydus/cache/
total 376800
-rw-r--r-- 1 root root 3584 Aug 30 23:18 055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3
-rw-r--r-- 1 root root 527872 Aug 30 23:18 055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3.layer.disk
-rw-r--r-- 1 root root 77814784 Aug 30 23:18 52d2b7f179e32b4cbd579ee3c4958027988f9a8274850ab0c7c24661e3adaac5
-rw-r--r-- 1 root root 78863360 Aug 30 23:18 52d2b7f179e32b4cbd579ee3c4958027988f9a8274850ab0c7c24661e3adaac5.layer.disk
-rw-r--r-- 1 root root 4608 Aug 30 23:18 96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd
-rw-r--r-- 1 root root 528896 Aug 30 23:18 96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd.layer.disk
-rw-r--r-- 1 root root 2560 Aug 30 23:18 a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4
-rw-r--r-- 1 root root 526848 Aug 30 23:18 a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4.layer.disk
-rw-r--r-- 1 root root 7168 Aug 30 23:18 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75
-rw-r--r-- 1 root root 531456 Aug 30 23:18 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.layer.disk
-rw-r--r-- 1 root root 5120 Aug 30 23:18 e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665
-rw-r--r-- 1 root root 529408 Aug 30 23:18 e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665.layer.disk
-rw-r--r-- 1 root root 112968704 Aug 30 23:18 fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa
-rw-r--r-- 1 root root 113492992 Aug 30 23:18 fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa.layer.disk
$ file /var/lib/containerd-nydus/cache/055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3
/var/lib/containerd-nydus/cache/055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3: POSIX tar archive
# Mount the raw disk image for a container image layer
$ losetup /dev/loop100 /var/lib/containerd-nydus/cache/055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3.layer.disk
$ mount -t erofs /dev/loop100 ./mnt/
$ mount
tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=1544836k,nr_inodes=386209,mode=700,inode64)
/dev/loop17 on /var/lib/containerd-nydus/snapshots/7/mnt type erofs (ro,relatime,user_xattr,acl,cache_strategy=readaround)
/dev/loop100 on /root/ws/nydus-snapshotter.git/mnt type erofs (ro,relatime,user_xattr,acl,cache_strategy=readaround)
```

### Generate Raw Disk Image for a Container Image
`Tarfs` supports generating a raw disk image a container image, which can be directly mounted as EROFS filesystem through loopdev. Please edit the snapshotter configuration file to enable this submode:
```
[experimental.tarfs]
enable_tarfs = true
export_mode = "image_block"
```

This is an example to generate and verify raw disk image for a container image:
```
$ containerd-nydus-grpc --config /etc/nydus/config.toml &
$ nerdctl run --snapshotter nydus --rm nginx
# Files without suffix are tar files, files with suffix `image.disk` are raw disk image for a container image
$ ls -l /var/lib/containerd-nydus/cache/
total 376320
-rw-r--r-- 1 root root 3584 Aug 30 23:35 055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3
-rw-r--r-- 1 root root 77814784 Aug 30 23:35 52d2b7f179e32b4cbd579ee3c4958027988f9a8274850ab0c7c24661e3adaac5
-rw-r--r-- 1 root root 4608 Aug 30 23:35 96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd
-rw-r--r-- 1 root root 2560 Aug 30 23:35 a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4
-rw-r--r-- 1 root root 7168 Aug 30 23:35 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75
-rw-r--r-- 1 root root 194518016 Aug 30 23:36 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk
-rw-r--r-- 1 root root 5120 Aug 30 23:35 e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665
-rw-r--r-- 1 root root 112968704 Aug 30 23:36 fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa
```

### Generate Raw Disk Image with dm-verity Information
`Tarfs` supports generating raw disk images with dm-verity information, to enable runtime data integrity validation. Please change `export_mode` in snapshotter configuration file to `layer_block_with_verity` or `image_block_with_verity`.

```
[experimental.tarfs]
enable_tarfs = true
export_mode = "image_block_with_verity"
```

This is an example to generate and verify raw disk image for a container image with dm-verity information:
```
$ containerd-nydus-grpc --config /etc/nydus/config.toml &
$ nerdctl run --snapshotter nydus --rm nginx
# Files without suffix are tar files, files with suffix `image.disk` are raw disk image for a container image
$ ls -l /var/lib/containerd-nydus/cache/
total 388296
-rw-r--r-- 1 root root 3584 Aug 30 23:45 055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3
-rw-r--r-- 1 root root 77814784 Aug 30 23:46 52d2b7f179e32b4cbd579ee3c4958027988f9a8274850ab0c7c24661e3adaac5
-rw-r--r-- 1 root root 4608 Aug 30 23:45 96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd
-rw-r--r-- 1 root root 2560 Aug 30 23:45 a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4
-rw-r--r-- 1 root root 7168 Aug 30 23:45 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75
-rw-r--r-- 1 root root 206782464 Aug 30 23:46 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk
-rw-r--r-- 1 root root 5120 Aug 30 23:45 e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665
-rw-r--r-- 1 root root 112968704 Aug 30 23:46 fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa
$ losetup /dev/loop100 /var/lib/containerd-nydus/cache/da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk
$ veritysetup open --no-superblock --format=1 -s "" --hash=sha256 --data-block-size=512 --hash-block-size=4096 --data-blocks 379918 --hash-offset 194519040 /dev/loop100 image1 /dev/loop100 8113799aaf9a5d14feca1eadc3b7e6ea98bdaf61e3a2e4a8ef8c24e26a551efd
$ lsblk
loop100 7:100 0 197.2M 0 loop
└─dm-0 252:0 0 185.5M 1 crypt
$ veritysetup status dm-0
/dev/mapper/dm-0 is active and is in use.
type: VERITY
status: verified
hash type: 1
data block: 512
hash block: 4096
hash name: sha256
salt: -
data device: /dev/loop100
data loop: /var/lib/containerd-nydus/cache/da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk
size: 379918 sectors
mode: readonly
hash device: /dev/loop100
hash loop: /var/lib/containerd-nydus/cache/da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk
hash offset: 379920 sectors
root hash: 8113799aaf9a5d14feca1eadc3b7e6ea98bdaf61e3a2e4a8ef8c24e26a551efd
$ mount -t erofs /dev/dm-0 ./mnt/
mount: /root/ws/nydus-snapshotter.git/mnt: WARNING: source write-protected, mounted read-only.
$ ls -l mnt/
total 14
lrwxrwxrwx 1 root root 7 Aug 14 08:00 bin -> usr/bin
drwxr-xr-x 2 root root 27 Jul 15 00:00 boot
drwxr-xr-x 2 root root 27 Aug 14 08:00 dev
drwxr-xr-x 2 root root 184 Aug 16 17:50 docker-entrypoint.d
-rwxrwxr-x 1 root root 1620 Aug 16 17:50 docker-entrypoint.sh
drwxr-xr-x 34 root root 1524 Aug 16 17:50 etc
drwxr-xr-x 2 root root 27 Jul 15 00:00 home
lrwxrwxrwx 1 root root 7 Aug 14 08:00 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Aug 14 08:00 lib32 -> usr/lib32
lrwxrwxrwx 1 root root 9 Aug 14 08:00 lib64 -> usr/lib64
lrwxrwxrwx 1 root root 10 Aug 14 08:00 libx32 -> usr/libx32
drwxr-xr-x 2 root root 27 Aug 14 08:00 media
drwxr-xr-x 2 root root 27 Aug 14 08:00 mnt
drwxr-xr-x 2 root root 27 Aug 14 08:00 opt
drwxr-xr-x 2 root root 27 Jul 15 00:00 proc
drwx------ 2 root root 66 Aug 14 08:00 root
drwxr-xr-x 3 root root 43 Aug 14 08:00 run
lrwxrwxrwx 1 root root 8 Aug 14 08:00 sbin -> usr/sbin
drwxr-xr-x 2 root root 27 Aug 14 08:00 srv
drwxr-xr-x 2 root root 27 Jul 15 00:00 sys
drwxrwxrwt 2 root root 27 Aug 16 17:50 tmp
drwxr-xr-x 14 root root 229 Aug 14 08:00 usr
drwxr-xr-x 11 root root 204 Aug 14 08:00 var
```
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ require (
k8s.io/cri-api v0.27.0-alpha.3
)

require github.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db // indirect

require (
github.com/cilium/ebpf v0.9.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db h1:StM6A9LvaVrFS2chAGcfRVDoBB6rHYPIGJ3GknpB25c=
github.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db/go.mod h1:pwuQfHWn6j2Fpl2AWw/bPLlKfojHxIIEa5TeKIgDFW4=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
Expand Down
18 changes: 18 additions & 0 deletions misc/snapshotter/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,21 @@ enable_stargz = false
# The option enables trying to fetch the Nydus image associated with the OCI image and run it.
# Also see https://github.com/opencontainers/distribution-spec/blob/main/spec.md#listing-referrers
enable_referrer_detect = false
[experimental.tarfs]
# Whether to enable nydus tarfs mode. Tarfs is supported by:
# - The EROFS filesystem driver since Linux 6.4
# - Nydus Image Service release v2.3
enable_tarfs = false
# Only enable nydus tarfs mode for images with `tarfs hint` label when true
tarfs_hint = false
# Maximum of concurrence to converting OCIv1 images to tarfs, 0 means default
max_concurrent_proc = 0
# Mode to export tarfs images:
# - "none" or "": do not export tarfs
# - "layer_verity_only": only generate disk verity information for a layer blob
# - "image_verity_only": only generate disk verity information for all blobs of an image
# - "layer_block": generate a raw block disk image with tarfs for a layer
# - "image_block": generate a raw block disk image with tarfs for an image
# - "layer_block_with_verity": generate a raw block disk image with tarfs for a layer with dm-verity info
# - "image_block_with_verity": generate a raw block disk image with tarfs for an image with dm-verity info
export_mode = ""
14 changes: 10 additions & 4 deletions pkg/cache/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import (
)

const (
chunkMapFileSuffix = ".chunk_map"
metaFileSuffix = ".blob.meta"
imageDiskFileSuffix = ".image.disk"
layerDiskFileSuffix = ".layer.disk"
chunkMapFileSuffix = ".chunk_map"
metaFileSuffix = ".blob.meta"
// Blob cache is suffixed after nydus v2.1
dataFileSuffix = ".blob.data"
)
Expand Down Expand Up @@ -72,8 +74,10 @@ func (m *Manager) CacheUsage(ctx context.Context, blobID string) (snapshots.Usag
blobCacheSuffixedPath := path.Join(m.cacheDir, blobID+dataFileSuffix)
blobChunkMap := path.Join(m.cacheDir, blobID+chunkMapFileSuffix)
blobMeta := path.Join(m.cacheDir, blobID+metaFileSuffix)
imageDisk := path.Join(m.cacheDir, blobID+imageDiskFileSuffix)
layerDisk := path.Join(m.cacheDir, blobID+layerDiskFileSuffix)

stuffs := []string{blobCachePath, blobCacheSuffixedPath, blobChunkMap, blobMeta}
stuffs := []string{blobCachePath, blobCacheSuffixedPath, blobChunkMap, blobMeta, imageDisk, layerDisk}

for _, f := range stuffs {
du, err := fs.DiskUsage(ctx, f)
Expand All @@ -95,9 +99,11 @@ func (m *Manager) RemoveBlobCache(blobID string) error {
blobCacheSuffixedPath := path.Join(m.cacheDir, blobID+dataFileSuffix)
blobChunkMap := path.Join(m.cacheDir, blobID+chunkMapFileSuffix)
blobMeta := path.Join(m.cacheDir, blobID+metaFileSuffix)
imageDisk := path.Join(m.cacheDir, blobID+imageDiskFileSuffix)
layerDisk := path.Join(m.cacheDir, blobID+layerDiskFileSuffix)

// NOTE: Delete chunk bitmap file before data blob
stuffs := []string{blobChunkMap, blobMeta, blobCachePath, blobCacheSuffixedPath}
stuffs := []string{blobChunkMap, blobMeta, blobCachePath, blobCacheSuffixedPath, imageDisk, layerDisk}

for _, f := range stuffs {
err := os.Remove(f)
Expand Down
31 changes: 21 additions & 10 deletions pkg/filesystem/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/containerd/nydus-snapshotter/pkg/referrer"
"github.com/containerd/nydus-snapshotter/pkg/signature"
"github.com/containerd/nydus-snapshotter/pkg/stargz"
"github.com/containerd/nydus-snapshotter/pkg/tarfs"
"github.com/pkg/errors"
)

Expand All @@ -28,18 +29,18 @@ func WithNydusImageBinaryPath(p string) NewFSOpt {

func WithManager(pm *manager.Manager) NewFSOpt {
return func(fs *Filesystem) error {
if pm == nil {
return errors.New("process manager cannot be nil")
if pm != nil {
switch pm.FsDriver {
case config.FsDriverBlockdev:
fs.blockdevManager = pm
case config.FsDriverFscache:
fs.fscacheManager = pm
case config.FsDriverFusedev:
fs.fusedevManager = pm
}
fs.enabledManagers = append(fs.enabledManagers, pm)
}

if pm.FsDriver == config.FsDriverFusedev {
fs.fusedevManager = pm
} else if pm.FsDriver == config.FsDriverFscache {
fs.fscacheManager = pm
}

fs.enabledManagers = append(fs.enabledManagers, pm)

return nil
}
}
Expand All @@ -66,6 +67,16 @@ func WithReferrerManager(rm *referrer.Manager) NewFSOpt {
}
}

func WithTarfsManager(tm *tarfs.Manager) NewFSOpt {
return func(fs *Filesystem) error {
if tm == nil {
return errors.New("tarfs manager cannot be nil")
}
fs.tarfsMgr = tm
return nil
}
}

func WithVerifier(verifier *signature.Verifier) NewFSOpt {
return func(fs *Filesystem) error {
fs.verifier = verifier
Expand Down
Loading

0 comments on commit 9a2575b

Please sign in to comment.