github.com/containerd/nerdctl@v1.7.7/pkg/imgutil/snapshotter.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package imgutil
    18  
    19  import (
    20  	"strings"
    21  
    22  	socisource "github.com/awslabs/soci-snapshotter/fs/source"
    23  	"github.com/containerd/containerd"
    24  	"github.com/containerd/containerd/images"
    25  	ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters"
    26  	"github.com/containerd/log"
    27  	"github.com/containerd/nerdctl/pkg/imgutil/pull"
    28  	"github.com/containerd/stargz-snapshotter/fs/source"
    29  )
    30  
    31  const (
    32  	snapshotterNameOverlaybd = "overlaybd"
    33  	snapshotterNameStargz    = "stargz"
    34  	snapshotterNameNydus     = "nydus"
    35  	snapshotterNameSoci      = "soci"
    36  	snapshotterNameCvmfs     = "cvmfs-snapshotter"
    37  
    38  	// prefetch size for stargz
    39  	prefetchSize = 10 * 1024 * 1024
    40  )
    41  
    42  // remote snapshotters explicitly handled by nerdctl
    43  var builtinRemoteSnapshotterOpts = map[string]snapshotterOpts{
    44  	snapshotterNameOverlaybd: &remoteSnapshotterOpts{snapshotter: "overlaybd"},
    45  	snapshotterNameStargz:    &remoteSnapshotterOpts{snapshotter: "stargz", extraLabels: stargzExtraLabels},
    46  	snapshotterNameNydus:     &remoteSnapshotterOpts{snapshotter: "nydus"},
    47  	snapshotterNameSoci:      &remoteSnapshotterOpts{snapshotter: "soci", extraLabels: sociExtraLabels},
    48  	snapshotterNameCvmfs:     &remoteSnapshotterOpts{snapshotter: "cvmfs-snapshotter"},
    49  }
    50  
    51  type RemoteSnapshotterFlags struct {
    52  	SociIndexDigest string
    53  }
    54  
    55  // snapshotterOpts is used to update pull config
    56  // for different snapshotters
    57  type snapshotterOpts interface {
    58  	apply(config *pull.Config, ref string, rFlags RemoteSnapshotterFlags)
    59  	isRemote() bool
    60  }
    61  
    62  // getSnapshotterOpts get snapshotter opts by fuzzy matching of the snapshotter name
    63  func getSnapshotterOpts(snapshotter string) snapshotterOpts {
    64  	for sn, sno := range builtinRemoteSnapshotterOpts {
    65  		if strings.Contains(snapshotter, sn) {
    66  			if snapshotter != sn {
    67  				log.L.Debugf("assuming %s to be a %s-compatible snapshotter", snapshotter, sn)
    68  			}
    69  			return sno
    70  		}
    71  	}
    72  
    73  	return &defaultSnapshotterOpts{snapshotter: snapshotter}
    74  }
    75  
    76  // remoteSnapshotterOpts is used as a remote snapshotter implementation for
    77  // interface `snapshotterOpts.isRemote()` function
    78  type remoteSnapshotterOpts struct {
    79  	snapshotter string
    80  	extraLabels func(func(images.Handler) images.Handler, RemoteSnapshotterFlags) func(images.Handler) images.Handler
    81  }
    82  
    83  func (rs *remoteSnapshotterOpts) isRemote() bool {
    84  	return true
    85  }
    86  
    87  func (rs *remoteSnapshotterOpts) apply(config *pull.Config, ref string, rFlags RemoteSnapshotterFlags) {
    88  	h := ctdsnapshotters.AppendInfoHandlerWrapper(ref)
    89  	if rs.extraLabels != nil {
    90  		h = rs.extraLabels(h, rFlags)
    91  	}
    92  	config.RemoteOpts = append(
    93  		config.RemoteOpts,
    94  		containerd.WithImageHandlerWrapper(h),
    95  		containerd.WithPullSnapshotter(rs.snapshotter),
    96  	)
    97  }
    98  
    99  // defaultSnapshotterOpts is for snapshotters that
   100  // not handled separately
   101  type defaultSnapshotterOpts struct {
   102  	snapshotter string
   103  }
   104  
   105  func (dsn *defaultSnapshotterOpts) apply(config *pull.Config, _ref string, rFlags RemoteSnapshotterFlags) {
   106  	config.RemoteOpts = append(
   107  		config.RemoteOpts,
   108  		containerd.WithPullSnapshotter(dsn.snapshotter))
   109  }
   110  
   111  // defaultSnapshotterOpts is not a remote snapshotter
   112  func (dsn *defaultSnapshotterOpts) isRemote() bool {
   113  	return false
   114  }
   115  
   116  func stargzExtraLabels(f func(images.Handler) images.Handler, rFlags RemoteSnapshotterFlags) func(images.Handler) images.Handler {
   117  	return source.AppendExtraLabelsHandler(prefetchSize, f)
   118  }
   119  
   120  func sociExtraLabels(f func(images.Handler) images.Handler, rFlags RemoteSnapshotterFlags) func(images.Handler) images.Handler {
   121  	return socisource.AppendDefaultLabelsHandlerWrapper(rFlags.SociIndexDigest, f)
   122  }