Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ linters-settings:
- gopkg.in/yaml.v3
- github.com/compose-spec/compose-go/v2
- github.com/github/go-spdx/v2
- github.com/opencontainers/image-spec/specs-go/v1
- oras.land/oras-go/v2
exhaustive:
# Switch statements are to be considered exhaustive if a 'default' case is
# present, even if all enum members aren't listed in the switch.
Expand Down
114 changes: 114 additions & 0 deletions build/rofl/oci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package rofl

import (
"context"
"fmt"
"os"
"path/filepath"

v1 "github.com/opencontainers/image-spec/specs-go/v1"
oras "oras.land/oras-go/v2"
Copy link
Copy Markdown
Member

@matevz matevz Mar 27, 2025

Choose a reason for hiding this comment

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

Will you need to add oras.land dependency to oasis-sdk the scheduler too in order to fetch .orc files on the node? Or there you could simply use HTTP GET?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, but the corresponding Rust package (as the scheduler is written in Rust).

"oras.land/oras-go/v2/content/file"
"oras.land/oras-go/v2/registry/remote"
"oras.land/oras-go/v2/registry/remote/auth"
"oras.land/oras-go/v2/registry/remote/credentials"
"oras.land/oras-go/v2/registry/remote/retry"

"github.com/oasisprotocol/oasis-core/go/runtime/bundle"
)

const (
ociTypeOrcConfig = "application/vnd.oasis.orc.config.v1+json"
ociTypeOrcLayer = "application/vnd.oasis.orc.layer.v1"
ociTypeOrcArtifact = "application/vnd.oasis.orc"
)

// PushBundleToOciRepository pushes an ORC bundle to the given remote OCI repository.
func PushBundleToOciRepository(bundleFn, dst, tag string) error {
ctx := context.Background()

// Open the bundle.
bnd, err := bundle.Open(bundleFn)
if err != nil {
return fmt.Errorf("failed to open bundle: %w", err)
}
defer bnd.Close()

// Create a temporary file store to build the OCI layers.
tmpDir, err := os.MkdirTemp("", "oasis-orc2oci")
if err != nil {
return fmt.Errorf("failed to create temporary directory: %w", err)
}
defer os.RemoveAll(tmpDir)

storeDir := filepath.Join(tmpDir, "oci")
store, err := file.New(storeDir)
if err != nil {
return fmt.Errorf("failed to create temporary OCI store: %w", err)
}
defer store.Close()

bundleDir := filepath.Join(tmpDir, "bundle")
if err = bnd.WriteExploded(bundleDir); err != nil {
return fmt.Errorf("failed to explode bundle: %w", err)
}

// Generate the config object from the manifest.
const manifestName = "META-INF/MANIFEST.MF"
configDsc, err := store.Add(ctx, manifestName, ociTypeOrcConfig, filepath.Join(bundleDir, manifestName))
if err != nil {
return fmt.Errorf("failed to add config object from manifest: %w", err)
}

// Add other files as layers.
layers := make([]v1.Descriptor, 0, len(bnd.Data)-1)
for fn := range bnd.Data {
if fn == manifestName {
continue
}

layerDsc, err := store.Add(ctx, fn, ociTypeOrcLayer, filepath.Join(bundleDir, fn))

Check failure on line 70 in build/rofl/oci.go

View workflow job for this annotation

GitHub Actions / lint

shadow: declaration of "err" shadows declaration at line 31 (govet)
if err != nil {
return fmt.Errorf("failed to add OCI layer: %w", err)
}

layers = append(layers, layerDsc)
}

// Pack the OCI manifest.
opts := oras.PackManifestOptions{
Layers: layers,
ConfigDescriptor: &configDsc,
}
manifestDescriptor, err := oras.PackManifest(ctx, store, oras.PackManifestVersion1_1, ociTypeOrcArtifact, opts)
if err != nil {
return fmt.Errorf("failed to pack OCI manifest: %w", err)
}

// Tag the manifest.
if err = store.Tag(ctx, manifestDescriptor, tag); err != nil {
return fmt.Errorf("failed to tag OCI manifest: %w", err)
}

// Connect to remote repository.
repo, err := remote.NewRepository(dst)
if err != nil {
return fmt.Errorf("failed to init remote OCI repository: %w", err)
}
creds, err := credentials.NewStoreFromDocker(credentials.StoreOptions{})
if err != nil {
return fmt.Errorf("failed to init OCI credential store: %w", err)
}
repo.Client = &auth.Client{
Client: retry.DefaultClient,
Cache: auth.NewCache(),
Credential: credentials.Credential(creds),
}

// Push to remote repository.
if _, err = oras.Copy(ctx, store, tag, repo, tag, oras.DefaultCopyOptions); err != nil {
return fmt.Errorf("failed to push to remote OCI repository: %w", err)
}

return nil
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ require (
github.com/oasisprotocol/oasis-core/go v0.2500.0
github.com/oasisprotocol/oasis-sdk/client-sdk/go v0.12.2
github.com/olekukonko/tablewriter v0.0.5
github.com/opencontainers/image-spec v1.1.0
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.6
github.com/spf13/viper v1.19.0
Expand All @@ -36,6 +37,7 @@ require (
golang.org/x/sys v0.31.0
golang.org/x/text v0.23.0
gopkg.in/yaml.v3 v3.0.1
oras.land/oras-go/v2 v2.5.0
)

require (
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@ github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
Expand Down Expand Up @@ -975,6 +977,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=
oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
Loading