Skip to content

Commit

Permalink
Update cimfs snapshotter & differ for new hcsshim interface
Browse files Browse the repository at this point in the history
hcsshim recently [updated](microsoft/hcsshim@1d406d0)
the interface of APIs that are used for importing OCI layers. Plus, it now expects that the CimFS snapshotter mounts contain the full cim paths for parent layers. This change updates the cimfs differ & snapshotter to use that new interface.

Signed-off-by: Amit Barve <ambarve@microsoft.com>
  • Loading branch information
ambarve committed Apr 4, 2024
1 parent 0807efb commit e0f787b
Show file tree
Hide file tree
Showing 52 changed files with 10,739 additions and 909 deletions.
52 changes: 49 additions & 3 deletions core/mount/mount_windows.go
Expand Up @@ -112,9 +112,20 @@ func (m *Mount) mount(target string) (retErr error) {
return nil
}

// ParentLayerPathsFlag is the options flag used to represent the JSON encoded
// list of parent layers required to use the layer
const ParentLayerPathsFlag = "parentLayerPaths="
const (
// ParentLayerPathsFlag is the options flag used to represent the JSON encoded
// list of parent layers required to use the layer
ParentLayerPathsFlag = "parentLayerPaths="

// LayerCimPathFlag is the option flag used to represent the path at which a layer CIM must be stored. This
// flag is only included if an image layer is being extracted onto the snapshot i.e the snapshot key has an
// UnpackKeyPrefix.
LayerCimPathFlag = "cimpath="

// Similar to ParentLayerPathsFlag this is the optinos flag used to represent the JSON encoded list of
// parent layer CIMs
ParentLayerCimPathsFlag = "parentCimPaths="
)

// GetParentPaths of the mount
func (m *Mount) GetParentPaths() ([]string, error) {
Expand All @@ -130,6 +141,41 @@ func (m *Mount) GetParentPaths() ([]string, error) {
return parentLayerPaths, nil
}

// gets the paths of the parent cims of this mount
func (m *Mount) GetParentCimPaths() ([]string, error) {
if m.Type != "CimFS" {
return nil, fmt.Errorf("invalid windows mount type: '%s'", m.Type)
}
var parentLayerCimPaths []string
for _, option := range m.Options {
if strings.HasPrefix(option, ParentLayerCimPathsFlag) {
err := json.Unmarshal([]byte(option[len(ParentLayerCimPathsFlag):]), &parentLayerCimPaths)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal parent layer cim paths from mount: %w", err)
}
}
}
return parentLayerCimPaths, nil
}

// Only applies to a snapshot created for image extraction, for such a snapshot provides the
// path to a cim in which image layer will be extracted.
func (m *Mount) GetCimPath() (string, error) {
if m.Type != "CimFS" {
return "", fmt.Errorf("invalid windows mount type: '%s'", m.Type)
}
cimPath := ""
for _, option := range m.Options {
if strings.HasPrefix(option, LayerCimPathFlag) {
cimPath = option[len(LayerCimPathFlag):]
}
}
if cimPath == "" {
return "", fmt.Errorf("cim path not found")
}
return cimPath, nil
}

// Unmount the mount at the provided path
func Unmount(mount string, flags int) error {
mount = filepath.Clean(mount)
Expand Down
10 changes: 5 additions & 5 deletions go.mod
Expand Up @@ -7,7 +7,7 @@ require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0
github.com/Microsoft/go-winio v0.6.1
github.com/Microsoft/hcsshim v0.12.2
github.com/Microsoft/hcsshim v0.12.1-0.20240326215926-1d406d0eac55
github.com/checkpoint-restore/checkpointctl v1.1.0
github.com/checkpoint-restore/go-criu/v7 v7.1.0
github.com/containerd/btrfs/v2 v2.0.0
Expand Down Expand Up @@ -88,7 +88,7 @@ require (
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cilium/ebpf v0.11.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
Expand Down Expand Up @@ -122,9 +122,9 @@ require (
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/oauth2 v0.16.0 // indirect
golang.org/x/term v0.17.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.17.0 // indirect
Expand All @@ -137,6 +137,6 @@ require (
k8s.io/apiserver v0.29.2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
tags.cncf.io/container-device-interface/specs-go v0.6.0 // indirect
)
20 changes: 10 additions & 10 deletions go.sum
Expand Up @@ -41,8 +41,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Microsoft/hcsshim v0.12.2 h1:AcXy+yfRvrx20g9v7qYaJv5Rh+8GaHOS6b8G6Wx/nKs=
github.com/Microsoft/hcsshim v0.12.2/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g=
github.com/Microsoft/hcsshim v0.12.1-0.20240326215926-1d406d0eac55 h1:OUP7yfGXZtKiCjRAx4q4/yMB9LkAXfK/2fm+HuTOfaA=
github.com/Microsoft/hcsshim v0.12.1-0.20240326215926-1d406d0eac55/go.mod h1:puKXmBgyNxp1EYsdGOyN0Pe0nIMTBWkJJ6Mzl79kYLQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
Expand Down Expand Up @@ -104,8 +104,8 @@ github.com/containernetworking/plugins v1.4.1 h1:+sJRRv8PKhLkXIl6tH1D7RMi+CbbHut
github.com/containernetworking/plugins v1.4.1/go.mod h1:n6FFGKcaY4o2o5msgu/UImtoC+fpQXM3076VHfHbj60=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -525,8 +525,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -598,8 +598,8 @@ golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down Expand Up @@ -811,8 +811,8 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMm
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
tags.cncf.io/container-device-interface v0.6.2 h1:dThE6dtp/93ZDGhqaED2Pu374SOeUkBfuvkLuiTdwzg=
tags.cncf.io/container-device-interface v0.6.2/go.mod h1:Shusyhjs1A5Na/kqPVLL0KqnHQHuunol9LFeUNkuGVE=
tags.cncf.io/container-device-interface/specs-go v0.6.0 h1:V+tJJN6dqu8Vym6p+Ru+K5mJ49WL6Aoc5SJFSY0RLsQ=
Expand Down
10 changes: 6 additions & 4 deletions pkg/archive/tar_opts_windows.go
Expand Up @@ -79,15 +79,17 @@ func WithParentLayers(p []string) WriteDiffOpt {
}
}

func applyWindowsCimLayer(ctx context.Context, root string, r io.Reader, options ApplyOptions) (size int64, err error) {
return ocicimlayer.ImportCimLayerFromTar(ctx, r, root, options.Parents)
func applyWindowsCimLayer(cimPath string, parentLayerCimPaths []string) func(context.Context, string, io.Reader, ApplyOptions) (int64, error) {
return func(ctx context.Context, root string, r io.Reader, options ApplyOptions) (int64, error) {
return ocicimlayer.ImportCimLayerFromTar(ctx, r, root, cimPath, options.Parents, parentLayerCimPaths)
}
}

// AsCimContainerLayer indicates that the tar stream to apply is that of a Windows container Layer written in
// the cim format.
func AsCimContainerLayer() ApplyOpt {
func AsCimContainerLayer(cimPath string, parentLayerCimPaths []string) ApplyOpt {
return func(options *ApplyOptions) error {
options.applyFunc = applyWindowsCimLayer
options.applyFunc = applyWindowsCimLayer(cimPath, parentLayerCimPaths)
return nil
}
}
40 changes: 18 additions & 22 deletions plugins/diff/windows/cimfs.go
Expand Up @@ -77,11 +77,26 @@ func NewCimDiff(store content.Store) (CompareApplier, error) {
// provided mounts. Archive content will be extracted and decompressed if
// necessary.
func (c cimDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount, opts ...diff.ApplyOpt) (d ocispec.Descriptor, err error) {
layer, parentLayerPaths, err := cimMountsToLayerAndParents(mounts)
if len(mounts) != 1 {
return ocispec.Descriptor{}, fmt.Errorf("%w: number of mounts should always be 1 for Windows layers", errdefs.ErrInvalidArgument)
} else if mounts[0].Type != "CimFS" {
return ocispec.Descriptor{}, fmt.Errorf("windowsDiff does not support layer type %s: %w", mounts[0].Type, errdefs.ErrNotImplemented)
}

m := mounts[0]
parentLayerPaths, err := m.GetParentPaths()
if err != nil {
return ocispec.Descriptor{}, err
}
parentLayerCimPaths, err := m.GetParentCimPaths()
if err != nil {
return ocispec.Descriptor{}, err
}
cimPath, err := m.GetCimPath()
if err != nil {
return emptyDesc, err
return ocispec.Descriptor{}, err
}
return applyDiffCommon(ctx, c.store, desc, layer, parentLayerPaths, archive.AsCimContainerLayer(), opts...)
return applyDiffCommon(ctx, c.store, desc, m.Source, parentLayerPaths, archive.AsCimContainerLayer(cimPath, parentLayerCimPaths), opts...)
}

// Compare creates a diff between the given mounts and uploads the result
Expand All @@ -90,22 +105,3 @@ func (c cimDiff) Compare(ctx context.Context, lower, upper []mount.Mount, opts .
// support for generating layer diff of cimfs layers will be added later.
return emptyDesc, errdefs.ErrNotImplemented
}

func cimMountsToLayerAndParents(mounts []mount.Mount) (string, []string, error) {
if len(mounts) != 1 {
return "", nil, fmt.Errorf("%w: number of mounts should always be 1 for Windows layers", errdefs.ErrInvalidArgument)
}
mnt := mounts[0]
if mnt.Type != "CimFS" {
// This is a special case error. When this is received the diff service
// will attempt the next differ in the chain.
return "", nil, errdefs.ErrNotImplemented
}

parentLayerPaths, err := mnt.GetParentPaths()
if err != nil {
return "", nil, err
}

return mnt.Source, parentLayerPaths, nil
}
54 changes: 28 additions & 26 deletions plugins/snapshots/windows/cimfs.go
Expand Up @@ -33,7 +33,6 @@ import (
"github.com/Microsoft/hcsshim"
"github.com/Microsoft/hcsshim/computestorage"
"github.com/Microsoft/hcsshim/pkg/cimfs"
cimlayer "github.com/Microsoft/hcsshim/pkg/ociwclayer/cim"
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/containerd/v2/core/snapshots"
"github.com/containerd/containerd/v2/core/snapshots/storage"
Expand Down Expand Up @@ -95,35 +94,29 @@ func NewCimFSSnapshotter(root string) (snapshots.Snapshotter, error) {
return nil, fmt.Errorf("failed to init base scratch VHD: %w", err)
}

if err = os.MkdirAll(filepath.Join(baseSn.info.HomeDir, "cim-layers"), 0755); err != nil {
return nil, err
}

return &cimFSSnapshotter{
windowsBaseSnapshotter: baseSn,
cimDir: filepath.Join(baseSn.info.HomeDir, "cim-layers"),
}, nil
}

// getCimLayerPath returns the path of the cim file for the given snapshot. Note that this function doesn't
// getLayerCimPath returns the path of the cim file for the given snapshot. Note that this function doesn't
// actually check if the cim layer exists it simply does string manipulation to generate the path isCimLayer
// can be used to verify if it is actually a cim layer.
func getCimLayerPath(cimDir, snID string) string {
return filepath.Join(cimDir, (snID + ".cim"))
func (s *cimFSSnapshotter) getLayerCimPath(snID string) string {
return filepath.Join(s.cimDir, (snID + ".cim"))
}

// isCimLayer checks if the snapshot referred by the given key is actually a cim layer. With CimFS
// snapshotter all the read-only (i.e image) layers are stored in the cim format while we still use VHDs for
// scratch layers.
func (s *cimFSSnapshotter) isCimLayer(ctx context.Context, key string) (bool, error) {
id, _, _, err := storage.GetInfo(ctx, key)
if err != nil {
return false, fmt.Errorf("get snapshot info: %w", err)
}
snCimPath := getCimLayerPath(s.cimDir, id)
if _, err := os.Stat(snCimPath); err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
func (s *cimFSSnapshotter) parentIDsToCimPaths(parentIDs []string) []string {
cimPaths := []string{}
for _, ID := range parentIDs {
cimPaths = append(cimPaths, s.getLayerCimPath(ID))
}
return true, nil
return cimPaths
}

func (s *cimFSSnapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) {
Expand All @@ -138,15 +131,14 @@ func (s *cimFSSnapshotter) Usage(ctx context.Context, key string) (snapshots.Usa
}
defer t.Rollback()

id, _, _, err := storage.GetInfo(ctx, key)
id, info, _, err := storage.GetInfo(ctx, key)
if err != nil {
return snapshots.Usage{}, fmt.Errorf("failed to get snapshot info: %w", err)
}

if ok, err := s.isCimLayer(ctx, key); err != nil {
return snapshots.Usage{}, err
} else if ok {
cimUsage, err := cimfs.GetCimUsage(ctx, getCimLayerPath(s.cimDir, id))
if info.Kind == snapshots.KindCommitted {
// Committed MUST to be a cimfs layer
cimUsage, err := cimfs.GetCimUsage(ctx, s.getLayerCimPath(id))
if err != nil {
return snapshots.Usage{}, err
}
Expand Down Expand Up @@ -219,7 +211,7 @@ func (s *cimFSSnapshotter) Remove(ctx context.Context, key string) error {
return fmt.Errorf("%w: %s", errdefs.ErrFailedPrecondition, err)
}

if err := cimlayer.DestroyCimLayer(s.getSnapshotDir(ID)); err != nil {
if err := cimfs.DestroyCim(ctx, s.getLayerCimPath(ID)); err != nil {
// Must be cleaned up, any "rm-*" could be removed if no active transactions
log.G(ctx).WithError(err).WithField("ID", ID).Warnf("failed to cleanup cim files")
}
Expand Down Expand Up @@ -327,27 +319,37 @@ func (s *cimFSSnapshotter) mounts(sn storage.Snapshot, key string) []mount.Mount

source := s.getSnapshotDir(sn.ID)
parentLayerPaths := s.parentIDsToParentPaths(sn.ParentIDs)
layerCimPaths := s.parentIDsToCimPaths(sn.ParentIDs)

mountType := "CimFS"

// error is not checked here, as a string array will never fail to Marshal
parentLayersJSON, _ := json.Marshal(parentLayerPaths)
parentLayersOption := mount.ParentLayerPathsFlag + string(parentLayersJSON)
parentCimLayersJSON, _ := json.Marshal(layerCimPaths)
parentCimLayersOption := mount.ParentLayerCimPathsFlag + string(parentCimLayersJSON)

options := []string{
roFlag,
}
if len(sn.ParentIDs) != 0 {
options = append(options, parentLayersOption)
options = append(options, parentCimLayersOption)
}
// if this is an image layer being extracted include a cim path in which the layer
// will be extracted.
if strings.Contains(key, snapshots.UnpackKeyPrefix) {
cimPathOption := s.getLayerCimPath(sn.ID)
options = append(options, mount.LayerCimPathFlag+cimPathOption)
}

mounts := []mount.Mount{
{
Source: source,
Type: mountType,
Options: options,
},
}

return mounts
}

Expand Down
2 changes: 1 addition & 1 deletion script/setup/runhcs-version
@@ -1 +1 @@
v0.12.0
1d406d0eac5573287ba7b46a04a58275410137ac
5 changes: 3 additions & 2 deletions vendor/github.com/Microsoft/hcsshim/Makefile

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions vendor/github.com/Microsoft/hcsshim/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e0f787b

Please sign in to comment.