Skip to content
Merged
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
106 changes: 52 additions & 54 deletions fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,76 +298,29 @@ func NewFilesystem(ctx context.Context, root string, cfg config.FSConfig, opts .

type sociContext struct {
cachedErr error
cachedErrMu sync.RWMutex
bgFetchPauseOnce sync.Once
fetchOnce sync.Once
sociIndex *soci.Index
imageLayerToSociDesc map[string]ocispec.Descriptor
fuseOperationCounter *layer.FuseOperationCounter
}

func (c *sociContext) Init(fsCtx context.Context, ctx context.Context, imageRef, indexDigest, imageManifestDigest string, store store.Store, fuseOpEmitWaitDuration time.Duration, client *http.Client) error {
var retErr error
func (c *sociContext) Init(ctx context.Context, fs *filesystem, imageRef, indexDigest, imageManifestDigest string, client *http.Client) error {
c.fetchOnce.Do(func() {
defer func() {
if retErr != nil {
c.cachedErrMu.Lock()
c.cachedErr = retErr
c.cachedErrMu.Unlock()
}
}()

refspec, err := reference.Parse(imageRef)
if err != nil {
retErr = err
return
}

remoteStore, err := newRemoteStore(refspec, client)
index, err := fs.fetchSociIndex(ctx, imageRef, indexDigest, imageManifestDigest, client)
if err != nil {
retErr = err
return
}

client := NewOCIArtifactClient(remoteStore)
indexDesc := ocispec.Descriptor{
Digest: digest.Digest(indexDigest),
}

if indexDigest == "" {
log.G(ctx).Info("index digest not provided, making a Referrers API call to fetch list of indices")
imgDigest, err := digest.Parse(imageManifestDigest)
if err != nil {
retErr = fmt.Errorf("unable to parse image digest: %w", err)
}

desc, err := client.SelectReferrer(ctx, ocispec.Descriptor{Digest: imgDigest}, defaultIndexSelectionPolicy)
if err != nil {
retErr = fmt.Errorf("%w: cannot fetch list of referrers: %w", snapshot.ErrNoIndex, err)
return
}
indexDesc = desc
}

log.G(ctx).WithField("digest", indexDesc.Digest.String()).Infof("fetching SOCI artifacts using index descriptor")

index, err := FetchSociArtifacts(ctx, refspec, indexDesc, store, remoteStore)
if err != nil {
retErr = fmt.Errorf("%w: error trying to fetch SOCI artifacts: %w", snapshot.ErrNoIndex, err)
c.cachedErr = err
return
}
c.sociIndex = index
c.populateImageLayerToSociMapping(index)

// Create the FUSE operation counter.
// Metrics are emitted after a wait time of fuseOpEmitWaitDuration.
c.fuseOperationCounter = layer.NewFuseOperationCounter(digest.Digest(imageManifestDigest), fuseOpEmitWaitDuration)
go c.fuseOperationCounter.Run(fsCtx)
c.fuseOperationCounter = layer.NewFuseOperationCounter(digest.Digest(imageManifestDigest), fs.fuseMetricsEmitWaitDuration)
go c.fuseOperationCounter.Run(fs.ctx)
})
c.cachedErrMu.RLock()
retErr = c.cachedErr
c.cachedErrMu.RUnlock()
return retErr
return c.cachedErr
}

func (c *sociContext) populateImageLayerToSociMapping(sociIndex *soci.Index) {
Expand Down Expand Up @@ -442,10 +395,55 @@ func (fs *filesystem) getSociContext(ctx context.Context, imageRef, indexDigest,
if !ok {
return nil, fmt.Errorf("could not load index: fs soci context is invalid type for %s", indexDigest)
}
err := c.Init(fs.ctx, ctx, imageRef, indexDigest, imageManifestDigest, fs.contentStore, fs.fuseMetricsEmitWaitDuration, client)
err := c.Init(ctx, fs, imageRef, indexDigest, imageManifestDigest, client)
return c, err
}

func (fs *filesystem) fetchSociIndex(ctx context.Context, imageRef, indexDigest, imageManifestDigest string, client *http.Client) (*soci.Index, error) {
refspec, err := reference.Parse(imageRef)
if err != nil {
return nil, err
}

remoteStore, err := newRemoteStore(refspec, client)
if err != nil {
return nil, err
}

var indexDesc ocispec.Descriptor
if indexDigest == "" {
log.G(ctx).Info("index digest not provided, making a Referrers API call to fetch list of indices")
imgDigest, err := digest.Parse(imageManifestDigest)
if err != nil {
return nil, fmt.Errorf("unable to parse image digest: %w", err)
}

artifactClient := NewOCIArtifactClient(remoteStore)

desc, err := artifactClient.SelectReferrer(ctx, ocispec.Descriptor{Digest: imgDigest}, defaultIndexSelectionPolicy)
if err != nil {
return nil, fmt.Errorf("%w: cannot fetch list of referrers: %w", snapshot.ErrNoIndex, err)
}
indexDesc = desc
} else {
dg, err := digest.Parse(indexDigest)
if err != nil {
return nil, fmt.Errorf("%w: unable to parse SOCI index digest: %w", snapshot.ErrNoIndex, err)
}
indexDesc = ocispec.Descriptor{
Digest: dg,
}
}

log.G(ctx).WithField("digest", indexDesc.Digest.String()).Infof("fetching SOCI artifacts using index descriptor")

index, err := FetchSociArtifacts(ctx, refspec, indexDesc, fs.contentStore, remoteStore)
if err != nil {
return nil, fmt.Errorf("%w: error trying to fetch SOCI artifacts: %w", snapshot.ErrNoIndex, err)
}
return index, nil
}

func getIDMappedMountpoint(mountpoint, activeLayerID string) string {
d := filepath.Dir(mountpoint)
return filepath.Join(fmt.Sprintf("%s_%s", d, activeLayerID), "fs")
Expand Down