mirror of
https://github.com/containerd/containerd.git
synced 2026-06-30 19:58:29 +00:00
Adds a new diff plugin that can import image layers in the block CIM format using the new block CIM layer writer added in hcsshim repo. This commit also makes another important change in the way a diff is applied when using CimFS based layer writers. Currently, the diff plugins call archive.Apply to apply a diff and pass a function (that can actually apply the diff) as an argument (via archive.ApplyOptions). This allows the callers to call archive.Apply with either a custom applier function or if the caller doesn't pass such a function archive.Apply uses the default naive diff applier. However, there is drawback to this approach. The applier function passed to the `archive.Apply` call needs to follow a specific signature. This signature expects it that all parent layers are represented as an array of strings. In cases like CimFS, we can't easily represent a set of layers as strings (unless we encode extra data in those strings in a hacky way). To get around this problem, the diff plugins for CimFS based layers, skip the archive.Apply call and directly call the layer writer instead. Signed-off-by: Amit Barve <ambarve@microsoft.com>
80 lines
3.0 KiB
Go
80 lines
3.0 KiB
Go
/*
|
|
Copyright The containerd Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package archive
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
|
|
"github.com/Microsoft/go-winio"
|
|
"github.com/Microsoft/hcsshim/pkg/ociwclayer"
|
|
)
|
|
|
|
// applyWindowsLayer applies a tar stream of an OCI style diff tar of a Windows layer
|
|
// See https://github.com/opencontainers/image-spec/blob/main/layer.md#applying-changesets
|
|
func applyWindowsLayer(ctx context.Context, root string, r io.Reader, options ApplyOptions) (size int64, err error) {
|
|
// It seems that in certain situations, like having the containerd root and state on a file system hosted on a
|
|
// mounted VHDX, we need SeSecurityPrivilege when opening a file with winio.ACCESS_SYSTEM_SECURITY. This happens
|
|
// in the base layer writer in hcsshim when adding a new file.
|
|
err = winio.RunWithPrivileges([]string{winio.SeSecurityPrivilege}, func() error {
|
|
var innerErr error
|
|
size, innerErr = ociwclayer.ImportLayerFromTar(ctx, r, root, options.Parents)
|
|
return innerErr
|
|
})
|
|
return
|
|
}
|
|
|
|
// AsWindowsContainerLayer indicates that the tar stream to apply is that of
|
|
// a Windows Container Layer. The caller must be holding SeBackupPrivilege and
|
|
// SeRestorePrivilege.
|
|
func AsWindowsContainerLayer() ApplyOpt {
|
|
return func(options *ApplyOptions) error {
|
|
options.applyFunc = applyWindowsLayer
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// writeDiffWindowsLayers writes a tar stream of the computed difference between the
|
|
// provided Windows layers
|
|
//
|
|
// Produces a tar using OCI style file markers for deletions. Deleted
|
|
// files will be prepended with the prefix ".wh.". This style is
|
|
// based off AUFS whiteouts.
|
|
// See https://github.com/opencontainers/image-spec/blob/main/layer.md
|
|
func writeDiffWindowsLayers(ctx context.Context, w io.Writer, _, layer string, options WriteDiffOptions) error {
|
|
return ociwclayer.ExportLayerToTar(ctx, w, layer, options.ParentLayers)
|
|
}
|
|
|
|
// AsWindowsContainerLayerPair indicates that the paths to diff are a pair of
|
|
// Windows Container Layers. The caller must be holding SeBackupPrivilege.
|
|
func AsWindowsContainerLayerPair() WriteDiffOpt {
|
|
return func(options *WriteDiffOptions) error {
|
|
options.writeDiffFunc = writeDiffWindowsLayers
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithParentLayers provides the Windows Container Layers that are the parents
|
|
// of the target (right-hand, "upper") layer, if any. The source (left-hand, "lower")
|
|
// layer passed to WriteDiff should be "" in this case.
|
|
func WithParentLayers(p []string) WriteDiffOpt {
|
|
return func(options *WriteDiffOptions) error {
|
|
options.ParentLayers = p
|
|
return nil
|
|
}
|
|
}
|