Skip to content

Commit 018649b

Browse files
Add option for zstd compression to rules_oci (#98)
Add zstd compression
1 parent 0c7dd51 commit 018649b

16 files changed

Lines changed: 275 additions & 57 deletions

File tree

.bazelrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ test:ci --keep_going
66
# Only show failing test targets to avoid scrolling past a long list of
77
# successful tests in order to see error logs.
88
test:ci --test_summary=terse
9+
10+
build:linux --sandbox_add_mount_pair=/tmp
11+
build:macos --sandbox_add_mount_pair=/var/tmp
12+
build:windows --sandbox_add_mount_pair=C:\Temp

MODULE.bazel

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use_repo(
2424
"com_github_blakesmith_ar",
2525
"com_github_containerd_containerd",
2626
"com_github_containerd_log",
27+
"com_github_datadog_zstd",
2728
"com_github_docker_docker_credential_helpers",
2829
"com_github_mitchellh_go_homedir",
2930
"com_github_opencontainers_go_digest",
@@ -56,3 +57,13 @@ oci_pull(
5657
register_toolchains(
5758
"@com_github_datadog_rules_oci//:oci_local_toolchain",
5859
)
60+
61+
bazel_dep(name = "hermetic_cc_toolchain", version = "3.1.0")
62+
63+
toolchains = use_extension("@hermetic_cc_toolchain//toolchain:ext.bzl", "toolchains")
64+
use_repo(toolchains, "zig_sdk")
65+
66+
register_toolchains(
67+
"@zig_sdk//libc_aware/toolchain:linux_amd64_gnu.2.28",
68+
"@zig_sdk//libc_aware/toolchain:linux_arm64_gnu.2.28",
69+
)

MODULE.bazel.lock

Lines changed: 51 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/docs.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ The config file named after the rule, os, and arch
173173
<pre>
174174
load("@rules_oci//oci:defs.bzl", "oci_image_layer")
175175

176-
oci_image_layer(<a href="#oci_image_layer-name">name</a>, <a href="#oci_image_layer-directory">directory</a>, <a href="#oci_image_layer-files">files</a>, <a href="#oci_image_layer-file_map">file_map</a>, <a href="#oci_image_layer-mode_map">mode_map</a>, <a href="#oci_image_layer-owner_map">owner_map</a>, <a href="#oci_image_layer-symlinks">symlinks</a>, <a href="#oci_image_layer-kwargs">kwargs</a>)
176+
oci_image_layer(<a href="#oci_image_layer-name">name</a>, <a href="#oci_image_layer-directory">directory</a>, <a href="#oci_image_layer-files">files</a>, <a href="#oci_image_layer-file_map">file_map</a>, <a href="#oci_image_layer-mode_map">mode_map</a>, <a href="#oci_image_layer-owner_map">owner_map</a>, <a href="#oci_image_layer-symlinks">symlinks</a>, <a href="#oci_image_layer-compression_method">compression_method</a>,
177+
<a href="#oci_image_layer-kwargs">kwargs</a>)
177178
</pre>
178179

179180
Creates a tarball and an OCI descriptor for it
@@ -190,6 +191,7 @@ Creates a tarball and an OCI descriptor for it
190191
| <a id="oci_image_layer-mode_map"></a>mode_map | Dictionary of file location in tarball -> mode int (e.g. 0o755) | `None` |
191192
| <a id="oci_image_layer-owner_map"></a>owner_map | Dictionary of file location in tarball -> owner:group string (e.g. '501:501') | `None` |
192193
| <a id="oci_image_layer-symlinks"></a>symlinks | Dictionary of symlink -> target entries to place in the tarball | `None` |
194+
| <a id="oci_image_layer-compression_method"></a>compression_method | A string, currently supports "gzip" and "zstd", defaults to "gzip" | `"gzip"` |
193195
| <a id="oci_image_layer-kwargs"></a>kwargs | Additional arguments to pass to the rule, e.g. tags or visibility | none |
194196

195197

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.22.9
55
toolchain go1.24.2
66

77
require (
8+
github.com/DataDog/zstd v1.5.7
89
github.com/bazelbuild/bazel-gazelle v0.43.0
910
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
1011
github.com/containerd/containerd v1.7.20

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
22
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
3+
github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE=
4+
github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
35
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
46
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
57
github.com/Microsoft/hcsshim v0.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIlxE0=

go/cmd/ocitool/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ go_library(
3131
"@com_github_containerd_containerd//images:go_default_library",
3232
"@com_github_containerd_containerd//platforms:go_default_library",
3333
"@com_github_containerd_log//:go_default_library",
34+
"@com_github_datadog_zstd//:go_default_library",
3435
"@com_github_opencontainers_go_digest//:go_default_library",
3536
"@com_github_opencontainers_image_spec//specs-go:go_default_library",
3637
"@com_github_opencontainers_image_spec//specs-go/v1:go_default_library",

go/cmd/ocitool/createlayer_cmd.go

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/DataDog/rules_oci/go/internal/tarutil"
1818
"github.com/DataDog/rules_oci/go/pkg/layer"
1919
"github.com/DataDog/rules_oci/go/pkg/ociutil"
20+
"github.com/DataDog/zstd"
2021
"github.com/opencontainers/go-digest"
2122
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
2223
"github.com/urfave/cli/v2"
@@ -32,14 +33,36 @@ func CreateLayerCmd(c *cli.Context) error {
3233
if err != nil {
3334
return fmt.Errorf("failed to create file at %s: %w", config.OutputLayer, err)
3435
}
36+
defer out.Close()
3537

3638
digester := digest.SHA256.Digester()
3739
wc := ociutil.NewWriterCounter(io.MultiWriter(out, digester.Hash()))
38-
gw := gzip.NewWriter(wc)
39-
gw.Name = path.Base(out.Name())
40-
defer gw.Close()
4140

42-
tw := tar.NewWriter(gw)
41+
var compressWriter io.Writer
42+
var compressCloser io.Closer
43+
var mediaType string
44+
switch config.CompressionMethod {
45+
case "gzip":
46+
gzipWriter := gzip.NewWriter(wc)
47+
gzipWriter.Name = path.Base(out.Name())
48+
compressWriter = gzipWriter
49+
compressCloser = gzipWriter
50+
mediaType = ocispec.MediaTypeImageLayerGzip
51+
case "zstd":
52+
zstdWriter := zstd.NewWriter(wc)
53+
compressWriter = zstdWriter
54+
compressCloser = zstdWriter
55+
mediaType = ocispec.MediaTypeImageLayerZstd
56+
default:
57+
return fmt.Errorf("uknown compress method %s", config.CompressionMethod)
58+
}
59+
defer func() {
60+
if compressCloser != nil {
61+
compressCloser.Close()
62+
}
63+
}()
64+
65+
tw := tar.NewWriter(compressWriter)
4366
defer tw.Close()
4467

4568
slices.Sort(config.Files)
@@ -136,14 +159,14 @@ func CreateLayerCmd(c *cli.Context) error {
136159

137160
}
138161

139-
// Need to flush before we count bytes and digest, might as well close since
140-
// it's not needed anymore.
162+
// Need to flush before we count bytes and digest
141163
tw.Close()
142-
gw.Close()
164+
compressCloser.Close()
165+
compressCloser = nil
143166

144167
desc := ocispec.Descriptor{
145168
Digest: digester.Digest(),
146-
MediaType: ocispec.MediaTypeImageLayerGzip,
169+
MediaType: mediaType,
147170
Size: int64(wc.Count()),
148171
}
149172

@@ -164,15 +187,16 @@ func CreateLayerCmd(c *cli.Context) error {
164187
}
165188

166189
type createLayerConfig struct {
167-
BazelLabel string `json:"bazel-label" toml:"bazel-label" yaml:"bazel-label"`
168-
Descriptor string `json:"outd" toml:"outd" yaml:"outd"`
169-
Directory string `json:"dir" toml:"dir" yaml:"dir"`
170-
FileMapping map[string]string `json:"file-map" toml:"file-map" yaml:"file-map"`
171-
Files []string `json:"file" toml:"file" yaml:"file"`
172-
ModeMapping map[string]int64 `json:"mode-map" toml:"mode-map" yaml:"mode-map"`
173-
OutputLayer string `json:"out" toml:"out" yaml:"out"`
174-
OwnerMapping map[string]string `json:"owner-map" toml:"owner-map" yaml:"owner-map"`
175-
SymlinkMapping map[string]string `json:"symlink" toml:"symlink" yaml:"symlink"`
190+
BazelLabel string `json:"bazel-label" toml:"bazel-label" yaml:"bazel-label"`
191+
Descriptor string `json:"outd" toml:"outd" yaml:"outd"`
192+
Directory string `json:"dir" toml:"dir" yaml:"dir"`
193+
FileMapping map[string]string `json:"file-map" toml:"file-map" yaml:"file-map"`
194+
Files []string `json:"file" toml:"file" yaml:"file"`
195+
ModeMapping map[string]int64 `json:"mode-map" toml:"mode-map" yaml:"mode-map"`
196+
OutputLayer string `json:"out" toml:"out" yaml:"out"`
197+
OwnerMapping map[string]string `json:"owner-map" toml:"owner-map" yaml:"owner-map"`
198+
SymlinkMapping map[string]string `json:"symlink" toml:"symlink" yaml:"symlink"`
199+
CompressionMethod string `json:"compression-method" toml:"compression-method" yaml:"compression-method"`
176200
}
177201

178202
func newCreateLayerConfig(c *cli.Context) (*createLayerConfig, error) {
@@ -184,16 +208,23 @@ func newCreateLayerConfig(c *cli.Context) (*createLayerConfig, error) {
184208
}
185209
modeMapping[path] = mode
186210
}
211+
212+
compressionMethod := c.String("compression-method")
213+
if compressionMethod == "" {
214+
compressionMethod = "gzip"
215+
}
216+
187217
return &createLayerConfig{
188-
BazelLabel: c.String("bazel-label"),
189-
Descriptor: c.String("outd"),
190-
Directory: c.String("dir"),
191-
FileMapping: c.Generic("file-map").(*flagutil.KeyValueFlag).Map,
192-
Files: c.StringSlice("file"),
193-
ModeMapping: modeMapping,
194-
OutputLayer: c.String("out"),
195-
OwnerMapping: c.Generic("owner-map").(*flagutil.KeyValueFlag).Map,
196-
SymlinkMapping: c.Generic("symlink").(*flagutil.KeyValueFlag).Map,
218+
BazelLabel: c.String("bazel-label"),
219+
Descriptor: c.String("outd"),
220+
Directory: c.String("dir"),
221+
FileMapping: c.Generic("file-map").(*flagutil.KeyValueFlag).Map,
222+
Files: c.StringSlice("file"),
223+
ModeMapping: modeMapping,
224+
OutputLayer: c.String("out"),
225+
OwnerMapping: c.Generic("owner-map").(*flagutil.KeyValueFlag).Map,
226+
SymlinkMapping: c.Generic("symlink").(*flagutil.KeyValueFlag).Map,
227+
CompressionMethod: compressionMethod,
197228
}, nil
198229
}
199230

go/cmd/ocitool/main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ var app = &cli.App{
7878
Name: "mode-map",
7979
Value: &flagutil.KeyValueFlag{},
8080
},
81+
&cli.StringFlag{
82+
Name: "compression-method",
83+
},
8184
},
8285
},
8386
{

go/pkg/ociutil/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ go_library(
3535
"@com_github_containerd_containerd//reference/docker:go_default_library",
3636
"@com_github_containerd_containerd//remotes:go_default_library",
3737
"@com_github_containerd_containerd//remotes/docker:go_default_library",
38+
"@com_github_datadog_zstd//:go_default_library",
3839
"@com_github_opencontainers_go_digest//:go_default_library",
3940
"@com_github_opencontainers_image_spec//specs-go/v1:go_default_library",
4041
"@com_github_sethvargo_go_retry//:go_default_library",

0 commit comments

Comments
 (0)