Skip to content

Commit

Permalink
Merge pull request #365 from tri-adam/set-blob-digest
Browse files Browse the repository at this point in the history
feat: add SetOCIBlobDigest
  • Loading branch information
tri-adam authored Jun 19, 2024
2 parents 3c091b8 + b85400b commit d63ee14
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 4 deletions.
6 changes: 4 additions & 2 deletions pkg/sif/descriptor.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023, Sylabs Inc. All rights reserved.
// Copyright (c) 2018-2024, Sylabs Inc. All rights reserved.
// Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
// Copyright (c) 2017, Yannick Cote <[email protected]> All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
Expand Down Expand Up @@ -92,7 +92,9 @@ func newOCIBlobDigest() *ociBlob {

// MarshalBinary encodes ob into binary format.
func (ob *ociBlob) MarshalBinary() ([]byte, error) {
ob.digest.Hex = hex.EncodeToString(ob.hasher.Sum(nil))
if ob.digest.Hex == "" {
ob.digest.Hex = hex.EncodeToString(ob.hasher.Sum(nil))
}

return ob.digest.MarshalText()
}
Expand Down
53 changes: 52 additions & 1 deletion pkg/sif/set.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023, Sylabs Inc. All rights reserved.
// Copyright (c) 2018-2024, Sylabs Inc. All rights reserved.
// Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
// Copyright (c) 2017, Yannick Cote <[email protected]> All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
Expand All @@ -12,6 +12,8 @@ import (
"errors"
"fmt"
"time"

v1 "github.com/google/go-containerregistry/pkg/v1"
)

// setOpts accumulates object set options.
Expand Down Expand Up @@ -167,3 +169,52 @@ func (f *FileImage) SetMetadata(id uint32, md encoding.BinaryMarshaler, opts ...

return nil
}

// SetOCIBlobDigest updates the digest of the OCI blob object with id to h, according to opts.
//
// By default, the image/object modification times are set to the current time for
// non-deterministic images, and unset otherwise. To override this, consider using
// OptSetDeterministic or OptSetWithTime.
func (f *FileImage) SetOCIBlobDigest(id uint32, h v1.Hash, opts ...SetOpt) error {
rd, err := f.getDescriptor(WithID(id))
if err != nil {
return fmt.Errorf("%w", err)
}

if got := rd.DataType; got != DataOCIRootIndex && got != DataOCIBlob {
return &unexpectedDataTypeError{got, []DataType{DataOCIRootIndex, DataOCIBlob}}
}

so := setOpts{}

if !f.isDeterministic() {
so.t = time.Now()
}

for _, opt := range opts {
if err := opt(&so); err != nil {
return fmt.Errorf("%w", err)
}
}

md := &ociBlob{
digest: h,
}
if err := rd.setExtra(md); err != nil {
return fmt.Errorf("%w", err)
}

rd.ModifiedAt = so.t.Unix()

if err := f.writeDescriptors(); err != nil {
return fmt.Errorf("%w", err)
}

f.h.ModifiedAt = so.t.Unix()

if err := f.writeHeader(); err != nil {
return fmt.Errorf("%w", err)
}

return nil
}
118 changes: 117 additions & 1 deletion pkg/sif/set_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2018-2023, Sylabs Inc. All rights reserved.
// Copyright (c) 2018-2024, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE file distributed with the sources of this project regarding your
// rights to use or distribute this software.
Expand All @@ -10,6 +10,7 @@ import (
"testing"
"time"

v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/sebdah/goldie/v2"
)

Expand Down Expand Up @@ -195,3 +196,118 @@ func TestSetMetadata(t *testing.T) {
})
}
}

func TestFileImage_SetOCIBlobDigest(t *testing.T) {
tests := []struct {
name string
createOpts []CreateOpt
id uint32
h v1.Hash
opts []SetOpt
wantErr error
}{
{
name: "UnexpectedDataType",
createOpts: []CreateOpt{
OptCreateDeterministic(),
OptCreateWithDescriptors(
getDescriptorInput(t, DataGeneric, []byte{0xfa, 0xce}),
),
},
id: 1,
h: v1.Hash{
Algorithm: "sha256",
Hex: "93a6ab73f77ce27501f74bb35af9b4da5b964c62f96175a1bc0e8ba2ae0dec08",
},
wantErr: &unexpectedDataTypeError{DataGeneric, []DataType{DataOCIBlob, DataOCIRootIndex}},
},
{
name: "Deterministic",
createOpts: []CreateOpt{
OptCreateWithID("de170c43-36ab-44a8-bca9-1ea1a070a274"),
OptCreateWithDescriptors(
getDescriptorInput(t, DataOCIBlob, []byte{0xfa, 0xce}),
),
OptCreateWithTime(time.Unix(946702800, 0)),
},
id: 1,
h: v1.Hash{
Algorithm: "sha256",
Hex: "93a6ab73f77ce27501f74bb35af9b4da5b964c62f96175a1bc0e8ba2ae0dec08",
},
opts: []SetOpt{
OptSetDeterministic(),
},
},
{
name: "WithTime",
createOpts: []CreateOpt{
OptCreateDeterministic(),
OptCreateWithDescriptors(
getDescriptorInput(t, DataOCIBlob, []byte{0xfa, 0xce}),
),
},
id: 1,
h: v1.Hash{
Algorithm: "sha256",
Hex: "93a6ab73f77ce27501f74bb35af9b4da5b964c62f96175a1bc0e8ba2ae0dec08",
},
opts: []SetOpt{
OptSetWithTime(time.Unix(946702800, 0)),
},
},
{
name: "One",
createOpts: []CreateOpt{
OptCreateDeterministic(),
OptCreateWithDescriptors(
getDescriptorInput(t, DataOCIBlob, []byte{0xfa, 0xce}),
),
},
id: 1,
h: v1.Hash{
Algorithm: "sha256",
Hex: "93a6ab73f77ce27501f74bb35af9b4da5b964c62f96175a1bc0e8ba2ae0dec08",
},
},
{
name: "Two",
createOpts: []CreateOpt{
OptCreateDeterministic(),
OptCreateWithDescriptors(
getDescriptorInput(t, DataOCIBlob, []byte{0xfa, 0xce}),
getDescriptorInput(t, DataOCIBlob, []byte{0xfe, 0xed}),
),
},
id: 2,
h: v1.Hash{
Algorithm: "sha256",
Hex: "93a6ab73f77ce27501f74bb35af9b4da5b964c62f96175a1bc0e8ba2ae0dec08",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var b Buffer

f, err := CreateContainer(&b, tt.createOpts...)
if err != nil {
t.Fatal(err)
}

if got, want := f.SetOCIBlobDigest(tt.id, tt.h, tt.opts...), tt.wantErr; !errors.Is(got, want) {
t.Errorf("got error %v, want %v", got, want)
}

if err := f.UnloadContainer(); err != nil {
t.Error(err)
}

if tt.wantErr == nil {
g := goldie.New(t, goldie.WithTestNameForDir(true))
g.Assert(t, tt.name, b.Bytes())
}
})
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit d63ee14

Please sign in to comment.