Skip to content

Commit

Permalink
feat: Add ability to specify modes and owners in create-layer
Browse files Browse the repository at this point in the history
  • Loading branch information
bcmyers committed Jan 31, 2025
1 parent 045a79e commit b29a6f9
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 9 deletions.
94 changes: 86 additions & 8 deletions go/cmd/ocitool/createlayer_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (
"os"
"path"
"path/filepath"
"strconv"
"strings"

"github.com/DataDog/rules_oci/go/internal/flagutil"
"github.com/DataDog/rules_oci/go/internal/tarutil"
"github.com/DataDog/rules_oci/go/pkg/ociutil"
"github.com/DataDog/rules_oci/go/pkg/layer"
"github.com/DataDog/rules_oci/go/pkg/ociutil"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/urfave/cli/v2"
Expand Down Expand Up @@ -43,25 +45,63 @@ func CreateLayerCmd(c *cli.Context) error {
defer tw.Close()

for _, filePath := range files {
err = tarutil.AppendFileToTarWriter(filePath, filepath.Join(dir, filepath.Base(filePath)), tw)
storePath := filepath.Join(dir, filepath.Base(filePath))

mode := config.mode(storePath)
uname := config.uname(storePath)
gname := config.gname(storePath)

err = tarutil.AppendFileToTarWriter(
/* filePath */ filePath,
/* loc */ storePath,
/* mode */ mode,
/* uname */ uname,
/* gname */ gname,
/* tw */ tw,
)

if err != nil {
return err
}
}

for filePath, storePath := range config.FileMapping {
err = tarutil.AppendFileToTarWriter(filePath, storePath, tw)
mode := config.mode(storePath)
uname := config.uname(storePath)
gname := config.gname(storePath)

err = tarutil.AppendFileToTarWriter(
/* filePath */ filePath,
/* loc */ storePath,
/* mode */ mode,
/* uname */ uname,
/* gname */ gname,
/* tw */ tw,
)

if err != nil {
return err
}
}

for k, v := range config.SymlinkMapping {
err = tw.WriteHeader(&tar.Header{
header := &tar.Header{
Typeflag: tar.TypeSymlink,
Name: k,
Linkname: v,
})
}

if mode := config.mode(k); mode != nil {
header.Mode = *mode
}
if uname := config.uname(k); uname != nil {
header.Uname = *uname
}
if gname := config.gname(k); gname != nil {
header.Gname = *gname
}

err = tw.WriteHeader(header)
if err != nil {
return fmt.Errorf("failed to create symlink: %w", err)
}
Expand Down Expand Up @@ -98,20 +138,32 @@ type createLayerConfig struct {
BazelLabel string `json:"bazel-label" toml:"bazel-label" yaml:"bazel-label"`
Descriptor string `json:"outd" toml:"outd" yaml:"outd"`
Directory string `json:"dir" toml:"dir" yaml:"dir"`
Files []string `json:"file" toml:"file" yaml:"file"`
FileMapping map[string]string `json:"file-map" toml:"file-map" yaml:"file-map"`
Files []string `json:"file" toml:"file" yaml:"file"`
ModeMapping map[string]int64 `json:"mode-map" toml:"mode-map" yaml:"mode-map"`
OutputLayer string `json:"out" toml:"out" yaml:"out"`
OwnerMapping map[string]string `json:"owner-map" toml:"owner-map" yaml:"owner-map"`
SymlinkMapping map[string]string `json:"symlink" toml:"symlink" yaml:"symlink"`
}

func newCreateLayerConfig(c *cli.Context) *createLayerConfig {
modeMapping := make(map[string]int64)
for k, v := range c.Generic("mode-map").(*flagutil.KeyValueFlag).Map {
i, err := strconv.ParseInt(v, 10, 64)
if err != nil {
continue
}
modeMapping[k] = i
}
return &createLayerConfig{
BazelLabel: c.String("bazel-label"),
Descriptor: c.String("outd"),
Directory: c.String("dir"),
Files: c.StringSlice("file"),
FileMapping: c.Generic("file-map").(*flagutil.KeyValueFlag).Map,
Files: c.StringSlice("file"),
ModeMapping: modeMapping,
OutputLayer: c.String("out"),
Descriptor: c.String("outd"),
OwnerMapping: c.Generic("owner-map").(*flagutil.KeyValueFlag).Map,
SymlinkMapping: c.Generic("symlink").(*flagutil.KeyValueFlag).Map,
}
}
Expand All @@ -135,3 +187,29 @@ func parseConfig(c *cli.Context) (*createLayerConfig, error) {

return &config, nil
}

func (c *createLayerConfig) mode(path string) *int64 {
if i, exists := c.ModeMapping[path]; exists {
return &i
}
return nil
}

func (c *createLayerConfig) uname(path string) *string {
if s, exists := c.OwnerMapping[path]; exists {
uname := strings.SplitN(s, ":", 2)[0]
return &uname
}
return nil
}

func (c *createLayerConfig) gname(path string) *string {
if s, exists := c.OwnerMapping[path]; exists {
parts := strings.SplitN(s, ":", 2)
if len(parts) > 1 {
gname := parts[1]
return &gname
}
}
return nil
}
21 changes: 20 additions & 1 deletion go/internal/tarutil/tarappend.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ import (

// AppendFileToTarWriter appends a file (given as a filepath) to a tarfile
// through the tarfile interface.
func AppendFileToTarWriter(filePath string, loc string, tw *tar.Writer) error {
func AppendFileToTarWriter(
filePath string,
loc string,
mode *int64,
uname,
gname *string,
tw *tar.Writer,
) error {
f, err := os.Open(filePath)
if err != nil {
return err
Expand All @@ -30,6 +37,18 @@ func AppendFileToTarWriter(filePath string, loc string, tw *tar.Writer) error {
hdr.ModTime = time.Time{}
hdr.AccessTime = time.Time{}

if mode != nil {
hdr.Mode = *mode
}

if uname != nil {
hdr.Uname = *uname
}

if gname != nil {
hdr.Gname = *gname
}

hdr.Name = loc

if err := tw.WriteHeader(hdr); err != nil {
Expand Down

0 comments on commit b29a6f9

Please sign in to comment.