vendor: update buildkit to master@d5c1d785b042

Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
Justin Chadwell
2023-10-23 14:34:59 +01:00
parent 7838ade9f3
commit adc839aa40
214 changed files with 10527 additions and 4796 deletions

View File

@ -25,11 +25,10 @@ import (
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"time"
"unsafe"
securejoin "github.com/cyphar/filepath-securejoin"
)
var (
@ -389,11 +388,11 @@ func (f *ConsumeFuzzer) GetUint16() (uint16, error) {
}
func (f *ConsumeFuzzer) GetUint32() (uint32, error) {
i, err := f.GetInt()
u32, err := f.GetNBytes(4)
if err != nil {
return uint32(0), err
return 0, err
}
return uint32(i), nil
return binary.BigEndian.Uint32(u32), nil
}
func (f *ConsumeFuzzer) GetUint64() (uint64, error) {
@ -412,26 +411,27 @@ func (f *ConsumeFuzzer) GetUint64() (uint64, error) {
}
func (f *ConsumeFuzzer) GetBytes() ([]byte, error) {
if f.position >= f.dataTotal {
return nil, errors.New("not enough bytes to create byte array")
}
length, err := f.GetUint32()
var length uint32
var err error
length, err = f.GetUint32()
if err != nil {
return nil, errors.New("not enough bytes to create byte array")
}
if f.position+length > MaxTotalLen {
return nil, errors.New("created too large a string")
}
byteBegin := f.position - 1
if byteBegin >= f.dataTotal {
return nil, errors.New("not enough bytes to create byte array")
}
if length == 0 {
return nil, errors.New("zero-length is not supported")
length = 30
}
if byteBegin+length >= f.dataTotal {
bytesLeft := f.dataTotal - f.position
if bytesLeft <= 0 {
return nil, errors.New("not enough bytes to create byte array")
}
// If the length is the same as bytes left, we will not overflow
// the remaining bytes.
if length != bytesLeft {
length = length % bytesLeft
}
byteBegin := f.position
if byteBegin+length < byteBegin {
return nil, errors.New("numbers overflow")
}
@ -482,6 +482,7 @@ func (f *ConsumeFuzzer) FuzzMap(m interface{}) error {
}
func returnTarBytes(buf []byte) ([]byte, error) {
return buf, nil
// Count files
var fileCounter int
tr := tar.NewReader(bytes.NewReader(buf))
@ -504,7 +505,8 @@ func returnTarBytes(buf []byte) ([]byte, error) {
func setTarHeaderFormat(hdr *tar.Header, f *ConsumeFuzzer) error {
ind, err := f.GetInt()
if err != nil {
return err
hdr.Format = tar.FormatGNU
//return nil
}
switch ind % 4 {
case 0:
@ -565,71 +567,17 @@ func setTarHeaderTypeflag(hdr *tar.Header, f *ConsumeFuzzer) error {
return nil
}
func tooSmallFileBody(length uint32) bool {
if length < 2 {
return true
}
if length < 4 {
return true
}
if length < 10 {
return true
}
if length < 100 {
return true
}
if length < 500 {
return true
}
if length < 1000 {
return true
}
if length < 2000 {
return true
}
if length < 4000 {
return true
}
if length < 8000 {
return true
}
if length < 16000 {
return true
}
if length < 32000 {
return true
}
if length < 64000 {
return true
}
if length < 128000 {
return true
}
if length < 264000 {
return true
}
return false
}
func (f *ConsumeFuzzer) createTarFileBody() ([]byte, error) {
length, err := f.GetUint32()
return f.GetBytes()
/*length, err := f.GetUint32()
if err != nil {
return nil, errors.New("not enough bytes to create byte array")
}
shouldUseLargeFileBody, err := f.GetBool()
if err != nil {
return nil, errors.New("not enough bytes to check long file body")
}
if shouldUseLargeFileBody && tooSmallFileBody(length) {
return nil, errors.New("File body was too small")
}
// A bit of optimization to attempt to create a file body
// when we don't have as many bytes left as "length"
remainingBytes := f.dataTotal - f.position
if remainingBytes == 0 {
if remainingBytes <= 0 {
return nil, errors.New("created too large a string")
}
if f.position+length > MaxTotalLen {
@ -649,14 +597,15 @@ func (f *ConsumeFuzzer) createTarFileBody() ([]byte, error) {
return nil, errors.New("numbers overflow")
}
f.position = byteBegin + length
return f.data[byteBegin:f.position], nil
return f.data[byteBegin:f.position], nil*/
}
// getTarFileName is similar to GetString(), but creates string based
// on the length of f.data to reduce the likelihood of overflowing
// f.data.
func (f *ConsumeFuzzer) getTarFilename() (string, error) {
length, err := f.GetUint32()
return f.GetString()
/*length, err := f.GetUint32()
if err != nil {
return "nil", errors.New("not enough bytes to create string")
}
@ -664,14 +613,9 @@ func (f *ConsumeFuzzer) getTarFilename() (string, error) {
// A bit of optimization to attempt to create a file name
// when we don't have as many bytes left as "length"
remainingBytes := f.dataTotal - f.position
if remainingBytes == 0 {
if remainingBytes <= 0 {
return "nil", errors.New("created too large a string")
}
if remainingBytes < 50 {
length = length % remainingBytes
} else if f.dataTotal < 500 {
length = length % f.dataTotal
}
if f.position > MaxTotalLen {
return "nil", errors.New("created too large a string")
}
@ -686,7 +630,12 @@ func (f *ConsumeFuzzer) getTarFilename() (string, error) {
return "nil", errors.New("numbers overflow")
}
f.position = byteBegin + length
return string(f.data[byteBegin:f.position]), nil
return string(f.data[byteBegin:f.position]), nil*/
}
type TarFile struct {
Hdr *tar.Header
Body []byte
}
// TarBytes returns valid bytes for a tar archive
@ -695,28 +644,38 @@ func (f *ConsumeFuzzer) TarBytes() ([]byte, error) {
if err != nil {
return nil, err
}
var tarFiles []*TarFile
tarFiles = make([]*TarFile, 0)
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
defer tw.Close()
const maxNoOfFiles = 1000
const maxNoOfFiles = 100
for i := 0; i < numberOfFiles%maxNoOfFiles; i++ {
filename, err := f.getTarFilename()
var filename string
var filebody []byte
var sec, nsec int
var err error
filename, err = f.getTarFilename()
if err != nil {
return returnTarBytes(buf.Bytes())
var sb strings.Builder
sb.WriteString("file-")
sb.WriteString(strconv.Itoa(i))
filename = sb.String()
}
filebody, err := f.createTarFileBody()
filebody, err = f.createTarFileBody()
if err != nil {
return returnTarBytes(buf.Bytes())
var sb strings.Builder
sb.WriteString("filebody-")
sb.WriteString(strconv.Itoa(i))
filebody = []byte(sb.String())
}
sec, err := f.GetInt()
sec, err = f.GetInt()
if err != nil {
return returnTarBytes(buf.Bytes())
sec = 1672531200 // beginning of 2023
}
nsec, err := f.GetInt()
nsec, err = f.GetInt()
if err != nil {
return returnTarBytes(buf.Bytes())
nsec = 1703980800 // end of 2023
}
hdr := &tar.Header{
@ -726,21 +685,83 @@ func (f *ConsumeFuzzer) TarBytes() ([]byte, error) {
ModTime: time.Unix(int64(sec), int64(nsec)),
}
if err := setTarHeaderTypeflag(hdr, f); err != nil {
return returnTarBytes(buf.Bytes())
return []byte(""), err
}
if err := setTarHeaderFormat(hdr, f); err != nil {
return returnTarBytes(buf.Bytes())
return []byte(""), err
}
if err := tw.WriteHeader(hdr); err != nil {
return returnTarBytes(buf.Bytes())
}
if _, err := tw.Write(filebody); err != nil {
return returnTarBytes(buf.Bytes())
tf := &TarFile{
Hdr: hdr,
Body: filebody,
}
tarFiles = append(tarFiles, tf)
}
var buf bytes.Buffer
tw := tar.NewWriter(&buf)
defer tw.Close()
for _, tf := range tarFiles {
tw.WriteHeader(tf.Hdr)
tw.Write(tf.Body)
}
return buf.Bytes(), nil
}
// This is similar to TarBytes, but it returns a series of
// files instead of raw tar bytes. The advantage of this
// api is that it is cheaper in terms of cpu power to
// modify or check the files in the fuzzer with TarFiles()
// because it avoids creating a tar reader.
func (f *ConsumeFuzzer) TarFiles() ([]*TarFile, error) {
numberOfFiles, err := f.GetInt()
if err != nil {
return nil, err
}
var tarFiles []*TarFile
tarFiles = make([]*TarFile, 0)
const maxNoOfFiles = 100
for i := 0; i < numberOfFiles%maxNoOfFiles; i++ {
filename, err := f.getTarFilename()
if err != nil {
return tarFiles, err
}
filebody, err := f.createTarFileBody()
if err != nil {
return tarFiles, err
}
sec, err := f.GetInt()
if err != nil {
return tarFiles, err
}
nsec, err := f.GetInt()
if err != nil {
return tarFiles, err
}
hdr := &tar.Header{
Name: filename,
Size: int64(len(filebody)),
Mode: 0o600,
ModTime: time.Unix(int64(sec), int64(nsec)),
}
if err := setTarHeaderTypeflag(hdr, f); err != nil {
hdr.Typeflag = tar.TypeReg
}
if err := setTarHeaderFormat(hdr, f); err != nil {
return tarFiles, err // should not happend
}
tf := &TarFile{
Hdr: hdr,
Body: filebody,
}
tarFiles = append(tarFiles, tf)
}
return tarFiles, nil
}
// CreateFiles creates pseudo-random files in rootDir.
// It creates subdirs and places the files there.
// It is the callers responsibility to ensure that
@ -767,10 +788,10 @@ func (f *ConsumeFuzzer) CreateFiles(rootDir string) error {
return errors.New("could not get fileName")
}
}
fullFilePath, err := securejoin.SecureJoin(rootDir, fileName)
if err != nil {
return err
if strings.Contains(fileName, "..") || (len(fileName) > 0 && fileName[0] == 47) || strings.Contains(fileName, "\\") {
continue
}
fullFilePath := filepath.Join(rootDir, fileName)
// Find the subdirectory of the file
if subDir := filepath.Dir(fileName); subDir != "" && subDir != "." {
@ -778,20 +799,14 @@ func (f *ConsumeFuzzer) CreateFiles(rootDir string) error {
if strings.Contains(subDir, "../") || (len(subDir) > 0 && subDir[0] == 47) || strings.Contains(subDir, "\\") {
continue
}
dirPath, err := securejoin.SecureJoin(rootDir, subDir)
if err != nil {
continue
}
dirPath := filepath.Join(rootDir, subDir)
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
err2 := os.MkdirAll(dirPath, 0o777)
if err2 != nil {
continue
}
}
fullFilePath, err = securejoin.SecureJoin(dirPath, fileName)
if err != nil {
continue
}
fullFilePath = filepath.Join(dirPath, fileName)
} else {
// Create symlink
createSymlink, err := f.GetBool()

21
vendor/github.com/Microsoft/hcsshim/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,59 @@
package osversion
import (
"fmt"
"sync"
"golang.org/x/sys/windows"
)
// OSVersion is a wrapper for Windows version information
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
type OSVersion struct {
Version uint32
MajorVersion uint8
MinorVersion uint8
Build uint16
}
var (
osv OSVersion
once sync.Once
)
// Get gets the operating system version on Windows.
// The calling application must be manifested to get the correct version information.
func Get() OSVersion {
once.Do(func() {
var err error
osv = OSVersion{}
osv.Version, err = windows.GetVersion()
if err != nil {
// GetVersion never fails.
panic(err)
}
osv.MajorVersion = uint8(osv.Version & 0xFF)
osv.MinorVersion = uint8(osv.Version >> 8 & 0xFF)
osv.Build = uint16(osv.Version >> 16)
})
return osv
}
// Build gets the build-number on Windows
// The calling application must be manifested to get the correct version information.
func Build() uint16 {
return Get().Build
}
// String returns the OSVersion formatted as a string. It implements the
// [fmt.Stringer] interface.
func (osv OSVersion) String() string {
return fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.Build)
}
// ToString returns the OSVersion formatted as a string.
//
// Deprecated: use [OSVersion.String].
func (osv OSVersion) ToString() string {
return osv.String()
}

View File

@ -0,0 +1,35 @@
package osversion
// List of stable ABI compliant ltsc releases
// Note: List must be sorted in ascending order
var compatLTSCReleases = []uint16{
V21H2Server,
}
// CheckHostAndContainerCompat checks if given host and container
// OS versions are compatible.
// It includes support for stable ABI compliant versions as well.
// Every release after WS 2022 will support the previous ltsc
// container image. Stable ABI is in preview mode for windows 11 client.
// Refer: https://learn.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-2022%2Cwindows-10#windows-server-host-os-compatibility
func CheckHostAndContainerCompat(host, ctr OSVersion) bool {
// check major minor versions of host and guest
if host.MajorVersion != ctr.MajorVersion ||
host.MinorVersion != ctr.MinorVersion {
return false
}
// If host is < WS 2022, exact version match is required
if host.Build < V21H2Server {
return host.Build == ctr.Build
}
var supportedLtscRelease uint16
for i := len(compatLTSCReleases) - 1; i >= 0; i-- {
if host.Build >= compatLTSCReleases[i] {
supportedLtscRelease = compatLTSCReleases[i]
break
}
}
return ctr.Build >= supportedLtscRelease && ctr.Build <= host.Build
}

View File

@ -0,0 +1,84 @@
package osversion
// Windows Client and Server build numbers.
//
// See:
// https://learn.microsoft.com/en-us/windows/release-health/release-information
// https://learn.microsoft.com/en-us/windows/release-health/windows-server-release-info
// https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information
const (
// RS1 (version 1607, codename "Redstone 1") corresponds to Windows Server
// 2016 (ltsc2016) and Windows 10 (Anniversary Update).
RS1 = 14393
// V1607 (version 1607, codename "Redstone 1") is an alias for [RS1].
V1607 = RS1
// LTSC2016 (Windows Server 2016) is an alias for [RS1].
LTSC2016 = RS1
// RS2 (version 1703, codename "Redstone 2") was a client-only update, and
// corresponds to Windows 10 (Creators Update).
RS2 = 15063
// V1703 (version 1703, codename "Redstone 2") is an alias for [RS2].
V1703 = RS2
// RS3 (version 1709, codename "Redstone 3") corresponds to Windows Server
// 1709 (Semi-Annual Channel (SAC)), and Windows 10 (Fall Creators Update).
RS3 = 16299
// V1709 (version 1709, codename "Redstone 3") is an alias for [RS3].
V1709 = RS3
// RS4 (version 1803, codename "Redstone 4") corresponds to Windows Server
// 1803 (Semi-Annual Channel (SAC)), and Windows 10 (April 2018 Update).
RS4 = 17134
// V1803 (version 1803, codename "Redstone 4") is an alias for [RS4].
V1803 = RS4
// RS5 (version 1809, codename "Redstone 5") corresponds to Windows Server
// 2019 (ltsc2019), and Windows 10 (October 2018 Update).
RS5 = 17763
// V1809 (version 1809, codename "Redstone 5") is an alias for [RS5].
V1809 = RS5
// LTSC2019 (Windows Server 2019) is an alias for [RS5].
LTSC2019 = RS5
// V19H1 (version 1903, codename 19H1) corresponds to Windows Server 1903 (semi-annual
// channel).
V19H1 = 18362
// V1903 (version 1903) is an alias for [V19H1].
V1903 = V19H1
// V19H2 (version 1909, codename 19H2) corresponds to Windows Server 1909 (semi-annual
// channel).
V19H2 = 18363
// V1909 (version 1909) is an alias for [V19H2].
V1909 = V19H2
// V20H1 (version 2004, codename 20H1) corresponds to Windows Server 2004 (semi-annual
// channel).
V20H1 = 19041
// V2004 (version 2004) is an alias for [V20H1].
V2004 = V20H1
// V20H2 corresponds to Windows Server 20H2 (semi-annual channel).
V20H2 = 19042
// V21H1 corresponds to Windows Server 21H1 (semi-annual channel).
V21H1 = 19043
// V21H2Win10 corresponds to Windows 10 (November 2021 Update).
V21H2Win10 = 19044
// V21H2Server corresponds to Windows Server 2022 (ltsc2022).
V21H2Server = 20348
// LTSC2022 (Windows Server 2022) is an alias for [V21H2Server]
LTSC2022 = V21H2Server
// V21H2Win11 corresponds to Windows 11 (original release).
V21H2Win11 = 22000
// V22H2Win10 corresponds to Windows 10 (2022 Update).
V22H2Win10 = 19045
// V22H2Win11 corresponds to Windows 11 (2022 Update).
V22H2Win11 = 22621
)

View File

@ -87,9 +87,6 @@ type IngestManager interface {
}
// Info holds content specific information
//
// TODO(stevvooe): Consider a very different name for this struct. Info is way
// to general. It also reads very weird in certain context, like pluralization.
type Info struct {
Digest digest.Digest
Size int64
@ -111,12 +108,17 @@ type Status struct {
// WalkFunc defines the callback for a blob walk.
type WalkFunc func(Info) error
// Manager provides methods for inspecting, listing and removing content.
type Manager interface {
// InfoProvider provides info for content inspection.
type InfoProvider interface {
// Info will return metadata about content available in the content store.
//
// If the content is not present, ErrNotFound will be returned.
Info(ctx context.Context, dgst digest.Digest) (Info, error)
}
// Manager provides methods for inspecting, listing and removing content.
type Manager interface {
InfoProvider
// Update updates mutable information related to content.
// If one or more fieldpaths are provided, only those

View File

@ -1,72 +0,0 @@
/*
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 log
import (
"context"
"github.com/sirupsen/logrus"
)
var (
// G is an alias for GetLogger.
//
// We may want to define this locally to a package to get package tagged log
// messages.
G = GetLogger
// L is an alias for the standard logger.
L = logrus.NewEntry(logrus.StandardLogger())
)
type (
loggerKey struct{}
// Fields type to pass to `WithFields`, alias from `logrus`.
Fields = logrus.Fields
)
const (
// RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to
// ensure the formatted time is always the same number of characters.
RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
// TextFormat represents the text logging format
TextFormat = "text"
// JSONFormat represents the JSON logging format
JSONFormat = "json"
)
// WithLogger returns a new context with the provided logger. Use in
// combination with logger.WithField(s) for great effect.
func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context {
e := logger.WithContext(ctx)
return context.WithValue(ctx, loggerKey{}, e)
}
// GetLogger retrieves the current logger from the context. If no logger is
// available, the default logger is returned.
func GetLogger(ctx context.Context) *logrus.Entry {
logger := ctx.Value(loggerKey{})
if logger == nil {
return L.WithContext(ctx)
}
return logger.(*logrus.Entry)
}

View File

@ -0,0 +1,149 @@
/*
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 log
import (
"context"
"github.com/containerd/log"
)
// G is a shorthand for [GetLogger].
//
// Deprecated: use [log.G].
var G = log.G
// L is an alias for the standard logger.
//
// Deprecated: use [log.L].
var L = log.L
// Fields type to pass to "WithFields".
//
// Deprecated: use [log.Fields].
type Fields = log.Fields
// Entry is a logging entry.
//
// Deprecated: use [log.Entry].
type Entry = log.Entry
// RFC3339NanoFixed is [time.RFC3339Nano] with nanoseconds padded using
// zeros to ensure the formatted time is always the same number of
// characters.
//
// Deprecated: use [log.RFC3339NanoFixed].
const RFC3339NanoFixed = log.RFC3339NanoFixed
// Level is a logging level.
//
// Deprecated: use [log.Level].
type Level = log.Level
// Supported log levels.
const (
// TraceLevel level.
//
// Deprecated: use [log.TraceLevel].
TraceLevel Level = log.TraceLevel
// DebugLevel level.
//
// Deprecated: use [log.DebugLevel].
DebugLevel Level = log.DebugLevel
// InfoLevel level.
//
// Deprecated: use [log.InfoLevel].
InfoLevel Level = log.InfoLevel
// WarnLevel level.
//
// Deprecated: use [log.WarnLevel].
WarnLevel Level = log.WarnLevel
// ErrorLevel level
//
// Deprecated: use [log.ErrorLevel].
ErrorLevel Level = log.ErrorLevel
// FatalLevel level.
//
// Deprecated: use [log.FatalLevel].
FatalLevel Level = log.FatalLevel
// PanicLevel level.
//
// Deprecated: use [log.PanicLevel].
PanicLevel Level = log.PanicLevel
)
// SetLevel sets log level globally. It returns an error if the given
// level is not supported.
//
// Deprecated: use [log.SetLevel].
func SetLevel(level string) error {
return log.SetLevel(level)
}
// GetLevel returns the current log level.
//
// Deprecated: use [log.GetLevel].
func GetLevel() log.Level {
return log.GetLevel()
}
// OutputFormat specifies a log output format.
//
// Deprecated: use [log.OutputFormat].
type OutputFormat = log.OutputFormat
// Supported log output formats.
const (
// TextFormat represents the text logging format.
//
// Deprecated: use [log.TextFormat].
TextFormat log.OutputFormat = "text"
// JSONFormat represents the JSON logging format.
//
// Deprecated: use [log.JSONFormat].
JSONFormat log.OutputFormat = "json"
)
// SetFormat sets the log output format.
//
// Deprecated: use [log.SetFormat].
func SetFormat(format OutputFormat) error {
return log.SetFormat(format)
}
// WithLogger returns a new context with the provided logger. Use in
// combination with logger.WithField(s) for great effect.
//
// Deprecated: use [log.WithLogger].
func WithLogger(ctx context.Context, logger *log.Entry) context.Context {
return log.WithLogger(ctx, logger)
}
// GetLogger retrieves the current logger from the context. If no logger is
// available, the default logger is returned.
//
// Deprecated: use [log.GetLogger].
func GetLogger(ctx context.Context) *log.Entry {
return log.GetLogger(ctx)
}

View File

@ -22,6 +22,7 @@ import (
"strconv"
"strings"
"github.com/Microsoft/hcsshim/osversion"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/sys/windows"
)
@ -50,15 +51,36 @@ func (m windowsmatcher) Match(p specs.Platform) bool {
match := m.defaultMatcher.Match(p)
if match && m.OS == "windows" {
if strings.HasPrefix(p.OSVersion, m.osVersionPrefix) {
// HPC containers do not have OS version filled
if p.OSVersion == "" {
return true
}
return p.OSVersion == ""
hostOsVersion := GetOsVersion(m.osVersionPrefix)
ctrOsVersion := GetOsVersion(p.OSVersion)
return osversion.CheckHostAndContainerCompat(hostOsVersion, ctrOsVersion)
}
return match
}
func GetOsVersion(osVersionPrefix string) osversion.OSVersion {
parts := strings.Split(osVersionPrefix, ".")
if len(parts) < 3 {
return osversion.OSVersion{}
}
majorVersion, _ := strconv.Atoi(parts[0])
minorVersion, _ := strconv.Atoi(parts[1])
buildNumber, _ := strconv.Atoi(parts[2])
return osversion.OSVersion{
MajorVersion: uint8(majorVersion),
MinorVersion: uint8(minorVersion),
Build: uint16(buildNumber),
}
}
// Less sorts matched platforms in front of other platforms.
// For matched platforms, it puts platforms with larger revision
// number in front.

View File

@ -196,6 +196,10 @@ func Parse(specifier string) (specs.Platform, error) {
p.Variant = cpuVariant()
}
if p.OS == "windows" {
p.OSVersion = GetWindowsOsVersion()
}
return p, nil
}
@ -218,6 +222,10 @@ func Parse(specifier string) (specs.Platform, error) {
p.Variant = ""
}
if p.OS == "windows" {
p.OSVersion = GetWindowsOsVersion()
}
return p, nil
case 3:
// we have a fully specified variant, this is rare
@ -227,6 +235,10 @@ func Parse(specifier string) (specs.Platform, error) {
p.Variant = "v8"
}
if p.OS == "windows" {
p.OSVersion = GetWindowsOsVersion()
}
return p, nil
}

View File

@ -28,3 +28,7 @@ func newDefaultMatcher(platform specs.Platform) Matcher {
Platform: Normalize(platform),
}
}
func GetWindowsOsVersion() string {
return ""
}

View File

@ -17,7 +17,10 @@
package platforms
import (
"fmt"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/sys/windows"
)
// NewMatcher returns a Windows matcher that will match on osVersionPrefix if
@ -32,3 +35,8 @@ func newDefaultMatcher(platform specs.Platform) Matcher {
},
}
}
func GetWindowsOsVersion() string {
major, minor, build := windows.RtlGetNtVersionNumbers()
return fmt.Sprintf("%d.%d.%d", major, minor, build)
}

View File

@ -23,6 +23,7 @@ import (
"io"
"net/http"
"net/url"
"path"
"strings"
"sync"
"time"
@ -137,6 +138,9 @@ func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref str
if exists {
p.tracker.SetStatus(ref, Status{
Committed: true,
PushStatus: PushStatus{
Exists: true,
},
Status: content.Status{
Ref: ref,
Total: desc.Size,
@ -164,6 +168,7 @@ func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref str
// Start upload request
req = p.request(host, http.MethodPost, "blobs", "uploads/")
mountedFrom := ""
var resp *http.Response
if fromRepo := selectRepositoryMountCandidate(p.refspec, desc.Annotations); fromRepo != "" {
preq := requestWithMountFrom(req, desc.Digest.String(), fromRepo)
@ -180,11 +185,14 @@ func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref str
return nil, err
}
if resp.StatusCode == http.StatusUnauthorized {
switch resp.StatusCode {
case http.StatusUnauthorized:
log.G(ctx).Debugf("failed to mount from repository %s", fromRepo)
resp.Body.Close()
resp = nil
case http.StatusCreated:
mountedFrom = path.Join(p.refspec.Hostname(), fromRepo)
}
}
@ -204,6 +212,9 @@ func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref str
case http.StatusCreated:
p.tracker.SetStatus(ref, Status{
Committed: true,
PushStatus: PushStatus{
MountedFrom: mountedFrom,
},
Status: content.Status{
Ref: ref,
Total: desc.Size,

View File

@ -18,6 +18,7 @@ package docker
import (
"context"
"crypto/tls"
"errors"
"fmt"
"io"
@ -148,6 +149,9 @@ func NewResolver(options ResolverOptions) remotes.Resolver {
if options.Headers == nil {
options.Headers = make(http.Header)
} else {
// make a copy of the headers to avoid race due to concurrent map write
options.Headers = options.Headers.Clone()
}
if _, ok := options.Headers["User-Agent"]; !ok {
options.Headers.Set("User-Agent", "containerd/"+version.Version)
@ -543,9 +547,10 @@ func (r *request) do(ctx context.Context) (*http.Response, error) {
if err != nil {
return nil, err
}
req.Header = http.Header{} // headers need to be copied to avoid concurrent map access
for k, v := range r.header {
req.Header[k] = v
if r.header == nil {
req.Header = http.Header{}
} else {
req.Header = r.header.Clone() // headers need to be copied to avoid concurrent map access
}
if r.body != nil {
body, err := r.body()
@ -669,7 +674,7 @@ func requestFields(req *http.Request) log.Fields {
}
}
return log.Fields(fields)
return fields
}
func responseFields(resp *http.Response) log.Fields {
@ -687,7 +692,7 @@ func responseFields(resp *http.Response) log.Fields {
}
}
return log.Fields(fields)
return fields
}
// IsLocalhost checks if the registry host is local.
@ -703,3 +708,27 @@ func IsLocalhost(host string) bool {
ip := net.ParseIP(host)
return ip.IsLoopback()
}
// HTTPFallback is an http.RoundTripper which allows fallback from https to http
// for registry endpoints with configurations for both http and TLS, such as
// defaulted localhost endpoints.
type HTTPFallback struct {
http.RoundTripper
}
func (f HTTPFallback) RoundTrip(r *http.Request) (*http.Response, error) {
resp, err := f.RoundTripper.RoundTrip(r)
var tlsErr tls.RecordHeaderError
if errors.As(err, &tlsErr) && string(tlsErr.RecordHeader[:]) == "HTTP/" {
// server gave HTTP response to HTTPS client
plainHTTPUrl := *r.URL
plainHTTPUrl.Scheme = "http"
plainHTTPRequest := *r
plainHTTPRequest.URL = &plainHTTPUrl
return f.RoundTripper.RoundTrip(&plainHTTPRequest)
}
return resp, err
}

View File

@ -36,6 +36,17 @@ type Status struct {
// UploadUUID is used by the Docker registry to reference blob uploads
UploadUUID string
// PushStatus contains status related to push.
PushStatus
}
type PushStatus struct {
// MountedFrom is the source content was cross-repo mounted from (empty if no cross-repo mount was performed).
MountedFrom string
// Exists indicates whether content already exists in the repository and wasn't uploaded.
Exists bool
}
// StatusTracker to track status of operations

View File

@ -204,8 +204,9 @@ func push(ctx context.Context, provider content.Provider, pusher Pusher, desc oc
// Base handlers can be provided which will be called before any push specific
// handlers.
//
// If the passed in content.Provider is also a content.Manager then this will
// also annotate the distribution sources in the manager.
// If the passed in content.Provider is also a content.InfoProvider (such as
// content.Manager) then this will also annotate the distribution sources using
// labels prefixed with "containerd.io/distribution.source".
func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Provider, limiter *semaphore.Weighted, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {
var m sync.Mutex
@ -234,7 +235,7 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st
platformFilterhandler := images.FilterPlatforms(images.ChildrenHandler(store), platform)
var handler images.Handler
if m, ok := store.(content.Manager); ok {
if m, ok := store.(content.InfoProvider); ok {
annotateHandler := annotateDistributionSourceHandler(platformFilterhandler, m)
handler = images.Handlers(annotateHandler, filterHandler, pushHandler)
} else {
@ -344,14 +345,15 @@ func FilterManifestByPlatformHandler(f images.HandlerFunc, m platforms.Matcher)
// annotateDistributionSourceHandler add distribution source label into
// annotation of config or blob descriptor.
func annotateDistributionSourceHandler(f images.HandlerFunc, manager content.Manager) images.HandlerFunc {
func annotateDistributionSourceHandler(f images.HandlerFunc, provider content.InfoProvider) images.HandlerFunc {
return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
children, err := f(ctx, desc)
if err != nil {
return nil, err
}
// only add distribution source for the config or blob data descriptor
// Distribution source is only used for config or blob but may be inherited from
// a manifest or manifest list
switch desc.MediaType {
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest,
images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
@ -359,12 +361,28 @@ func annotateDistributionSourceHandler(f images.HandlerFunc, manager content.Man
return children, nil
}
// parentInfo can be used to inherit info for non-existent blobs
var parentInfo *content.Info
for i := range children {
child := children[i]
info, err := manager.Info(ctx, child.Digest)
info, err := provider.Info(ctx, child.Digest)
if err != nil {
return nil, err
if !errdefs.IsNotFound(err) {
return nil, err
}
if parentInfo == nil {
pi, err := provider.Info(ctx, desc.Digest)
if err != nil {
return nil, err
}
parentInfo = &pi
}
// Blob may not exist locally, annotate with parent labels for cross repo
// mount or fetch. Parent sources may apply to all children since most
// registries enforce that children exist before the manifests.
info = *parentInfo
}
for k, v := range info.Labels {

View File

@ -23,7 +23,7 @@ var (
Package = "github.com/containerd/containerd"
// Version holds the complete version number. Filled in at linking time.
Version = "1.7.2+unknown"
Version = "1.7.7+unknown"
// Revision is filled with the VCS (e.g. git) revision being used to build
// the program at linking time.

View File

@ -1,5 +1,5 @@
//go:build freebsd
// +build freebsd
//go:build freebsd || dragonfly
// +build freebsd dragonfly
/*
Copyright The containerd Authors.

View File

@ -1,5 +1,5 @@
//go:build darwin || freebsd || netbsd || openbsd || solaris
// +build darwin freebsd netbsd openbsd solaris
//go:build darwin || freebsd || netbsd || openbsd || dragonfly || solaris
// +build darwin freebsd netbsd openbsd dragonfly solaris
/*
Copyright The containerd Authors.

View File

@ -18,20 +18,13 @@ package fs
import (
"fmt"
"io"
"os"
"path/filepath"
"sync"
"github.com/sirupsen/logrus"
)
var bufferPool = &sync.Pool{
New: func() interface{} {
buffer := make([]byte, 32*1024)
return &buffer
},
}
// XAttrErrorHandler transform a non-nil xattr error.
// Return nil to ignore an error.
// xattrKey can be empty for listxattr operation.
@ -199,5 +192,6 @@ func openAndCopyFile(target, source string) error {
}
defer tgt.Close()
return copyFileContent(tgt, src)
_, err = io.Copy(tgt, src)
return err
}

View File

@ -18,7 +18,6 @@ package fs
import (
"fmt"
"io"
"os"
"syscall"
@ -62,51 +61,6 @@ func copyFileInfo(fi os.FileInfo, src, name string) error {
return nil
}
const maxSSizeT = int64(^uint(0) >> 1)
func copyFileContent(dst, src *os.File) error {
st, err := src.Stat()
if err != nil {
return fmt.Errorf("unable to stat source: %w", err)
}
size := st.Size()
first := true
srcFd := int(src.Fd())
dstFd := int(dst.Fd())
for size > 0 {
// Ensure that we are never trying to copy more than SSIZE_MAX at a
// time and at the same time avoids overflows when the file is larger
// than 4GB on 32-bit systems.
var copySize int
if size > maxSSizeT {
copySize = int(maxSSizeT)
} else {
copySize = int(size)
}
n, err := unix.CopyFileRange(srcFd, nil, dstFd, nil, copySize, 0)
if err != nil {
if (err != unix.ENOSYS && err != unix.EXDEV) || !first {
return fmt.Errorf("copy file range failed: %w", err)
}
buf := bufferPool.Get().(*[]byte)
_, err = io.CopyBuffer(dst, src, *buf)
bufferPool.Put(buf)
if err != nil {
return fmt.Errorf("userspace copy failed: %w", err)
}
return nil
}
first = false
size -= int64(n)
}
return nil
}
func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error {
xattrKeys, err := sysx.LListxattr(src)
if err != nil {

View File

@ -1,5 +1,5 @@
//go:build darwin || freebsd || openbsd || netbsd || solaris
// +build darwin freebsd openbsd netbsd solaris
//go:build darwin || freebsd || openbsd || netbsd || dragonfly || solaris
// +build darwin freebsd openbsd netbsd dragonfly solaris
/*
Copyright The containerd Authors.
@ -21,7 +21,6 @@ package fs
import (
"fmt"
"io"
"os"
"runtime"
"syscall"
@ -61,14 +60,6 @@ func copyFileInfo(fi os.FileInfo, src, name string) error {
return nil
}
func copyFileContent(dst, src *os.File) error {
buf := bufferPool.Get().(*[]byte)
_, err := io.CopyBuffer(dst, src, *buf)
bufferPool.Put(buf)
return err
}
func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error {
xattrKeys, err := sysx.LListxattr(src)
if err != nil {

View File

@ -19,7 +19,6 @@ package fs
import (
"errors"
"fmt"
"io"
"os"
winio "github.com/Microsoft/go-winio"
@ -72,13 +71,6 @@ func copyFileInfo(fi os.FileInfo, src, name string) error {
return nil
}
func copyFileContent(dst, src *os.File) error {
buf := bufferPool.Get().(*[]byte)
_, err := io.CopyBuffer(dst, src, *buf)
bufferPool.Put(buf)
return err
}
func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error {
return nil
}

View File

@ -65,7 +65,12 @@ func writeFileStream(name string, stream func() io.Reader, perm os.FileMode) App
return err
}
defer func() {
err := f.Close()
err := f.Sync()
if err != nil && retErr == nil {
retErr = err
}
err = f.Close()
if err != nil && retErr == nil {
retErr = err
}

View File

@ -1,5 +1,5 @@
//go:build linux || openbsd || solaris
// +build linux openbsd solaris
//go:build linux || openbsd || dragonfly || solaris
// +build linux openbsd dragonfly solaris
/*
Copyright The containerd Authors.

30
vendor/github.com/containerd/log/.golangci.yml generated vendored Normal file
View File

@ -0,0 +1,30 @@
linters:
enable:
- exportloopref # Checks for pointers to enclosing loop variables
- gofmt
- goimports
- gosec
- ineffassign
- misspell
- nolintlint
- revive
- staticcheck
- tenv # Detects using os.Setenv instead of t.Setenv since Go 1.17
- unconvert
- unused
- vet
- dupword # Checks for duplicate words in the source code
disable:
- errcheck
run:
timeout: 5m
skip-dirs:
- api
- cluster
- design
- docs
- docs/man
- releases
- reports
- test # e2e scripts

191
vendor/github.com/containerd/log/LICENSE generated vendored Normal file
View File

@ -0,0 +1,191 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
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
https://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.

17
vendor/github.com/containerd/log/README.md generated vendored Normal file
View File

@ -0,0 +1,17 @@
# log
A Go package providing a common logging interface across containerd repositories and a way for clients to use and configure logging in containerd packages.
This package is not intended to be used as a standalone logging package outside of the containerd ecosystem and is intended as an interface wrapper around a logging implementation.
In the future this package may be replaced with a common go logging interface.
## Project details
**log** is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
As a containerd sub-project, you will find the:
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
* [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
information in our [`containerd/project`](https://github.com/containerd/project) repository.

182
vendor/github.com/containerd/log/context.go generated vendored Normal file
View File

@ -0,0 +1,182 @@
/*
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 log provides types and functions related to logging, passing
// loggers through a context, and attaching context to the logger.
//
// # Transitional types
//
// This package contains various types that are aliases for types in [logrus].
// These aliases are intended for transitioning away from hard-coding logrus
// as logging implementation. Consumers of this package are encouraged to use
// the type-aliases from this package instead of directly using their logrus
// equivalent.
//
// The intent is to replace these aliases with locally defined types and
// interfaces once all consumers are no longer directly importing logrus
// types.
//
// IMPORTANT: due to the transitional purpose of this package, it is not
// guaranteed for the full logrus API to be provided in the future. As
// outlined, these aliases are provided as a step to transition away from
// a specific implementation which, as a result, exposes the full logrus API.
// While no decisions have been made on the ultimate design and interface
// provided by this package, we do not expect carrying "less common" features.
package log
import (
"context"
"fmt"
"github.com/sirupsen/logrus"
)
// G is a shorthand for [GetLogger].
//
// We may want to define this locally to a package to get package tagged log
// messages.
var G = GetLogger
// L is an alias for the standard logger.
var L = &Entry{
Logger: logrus.StandardLogger(),
// Default is three fields plus a little extra room.
Data: make(Fields, 6),
}
type loggerKey struct{}
// Fields type to pass to "WithFields".
type Fields = map[string]any
// Entry is a logging entry. It contains all the fields passed with
// [Entry.WithFields]. It's finally logged when Trace, Debug, Info, Warn,
// Error, Fatal or Panic is called on it. These objects can be reused and
// passed around as much as you wish to avoid field duplication.
//
// Entry is a transitional type, and currently an alias for [logrus.Entry].
type Entry = logrus.Entry
// RFC3339NanoFixed is [time.RFC3339Nano] with nanoseconds padded using
// zeros to ensure the formatted time is always the same number of
// characters.
const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
// Level is a logging level.
type Level = logrus.Level
// Supported log levels.
const (
// TraceLevel level. Designates finer-grained informational events
// than [DebugLevel].
TraceLevel Level = logrus.TraceLevel
// DebugLevel level. Usually only enabled when debugging. Very verbose
// logging.
DebugLevel Level = logrus.DebugLevel
// InfoLevel level. General operational entries about what's going on
// inside the application.
InfoLevel Level = logrus.InfoLevel
// WarnLevel level. Non-critical entries that deserve eyes.
WarnLevel Level = logrus.WarnLevel
// ErrorLevel level. Logs errors that should definitely be noted.
// Commonly used for hooks to send errors to an error tracking service.
ErrorLevel Level = logrus.ErrorLevel
// FatalLevel level. Logs and then calls "logger.Exit(1)". It exits
// even if the logging level is set to Panic.
FatalLevel Level = logrus.FatalLevel
// PanicLevel level. This is the highest level of severity. Logs and
// then calls panic with the message passed to Debug, Info, ...
PanicLevel Level = logrus.PanicLevel
)
// SetLevel sets log level globally. It returns an error if the given
// level is not supported.
//
// level can be one of:
//
// - "trace" ([TraceLevel])
// - "debug" ([DebugLevel])
// - "info" ([InfoLevel])
// - "warn" ([WarnLevel])
// - "error" ([ErrorLevel])
// - "fatal" ([FatalLevel])
// - "panic" ([PanicLevel])
func SetLevel(level string) error {
lvl, err := logrus.ParseLevel(level)
if err != nil {
return err
}
L.Logger.SetLevel(lvl)
return nil
}
// GetLevel returns the current log level.
func GetLevel() Level {
return L.Logger.GetLevel()
}
// OutputFormat specifies a log output format.
type OutputFormat string
// Supported log output formats.
const (
// TextFormat represents the text logging format.
TextFormat OutputFormat = "text"
// JSONFormat represents the JSON logging format.
JSONFormat OutputFormat = "json"
)
// SetFormat sets the log output format ([TextFormat] or [JSONFormat]).
func SetFormat(format OutputFormat) error {
switch format {
case TextFormat:
L.Logger.SetFormatter(&logrus.TextFormatter{
TimestampFormat: RFC3339NanoFixed,
FullTimestamp: true,
})
return nil
case JSONFormat:
L.Logger.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: RFC3339NanoFixed,
})
return nil
default:
return fmt.Errorf("unknown log format: %s", format)
}
}
// WithLogger returns a new context with the provided logger. Use in
// combination with logger.WithField(s) for great effect.
func WithLogger(ctx context.Context, logger *Entry) context.Context {
return context.WithValue(ctx, loggerKey{}, logger.WithContext(ctx))
}
// GetLogger retrieves the current logger from the context. If no logger is
// available, the default logger is returned.
func GetLogger(ctx context.Context) *Entry {
if logger := ctx.Value(loggerKey{}); logger != nil {
return logger.(*Entry)
}
return L.WithContext(ctx)
}

View File

@ -1,21 +0,0 @@
# Copyright (C) 2017 SUSE LLC. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
language: go
go:
- 1.13.x
- 1.16.x
- tip
arch:
- AMD64
- ppc64le
os:
- linux
- osx
script:
- go test -cover -v ./...
notifications:
email: false

View File

@ -1,28 +0,0 @@
Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved.
Copyright (C) 2017 SUSE LLC. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,79 +0,0 @@
## `filepath-securejoin` ##
[![Build Status](https://travis-ci.org/cyphar/filepath-securejoin.svg?branch=master)](https://travis-ci.org/cyphar/filepath-securejoin)
An implementation of `SecureJoin`, a [candidate for inclusion in the Go
standard library][go#20126]. The purpose of this function is to be a "secure"
alternative to `filepath.Join`, and in particular it provides certain
guarantees that are not provided by `filepath.Join`.
> **NOTE**: This code is *only* safe if you are not at risk of other processes
> modifying path components after you've used `SecureJoin`. If it is possible
> for a malicious process to modify path components of the resolved path, then
> you will be vulnerable to some fairly trivial TOCTOU race conditions. [There
> are some Linux kernel patches I'm working on which might allow for a better
> solution.][lwn-obeneath]
>
> In addition, with a slightly modified API it might be possible to use
> `O_PATH` and verify that the opened path is actually the resolved one -- but
> I have not done that yet. I might add it in the future as a helper function
> to help users verify the path (we can't just return `/proc/self/fd/<foo>`
> because that doesn't always work transparently for all users).
This is the function prototype:
```go
func SecureJoin(root, unsafePath string) (string, error)
```
This library **guarantees** the following:
* If no error is set, the resulting string **must** be a child path of
`root` and will not contain any symlink path components (they will all be
expanded).
* When expanding symlinks, all symlink path components **must** be resolved
relative to the provided root. In particular, this can be considered a
userspace implementation of how `chroot(2)` operates on file paths. Note that
these symlinks will **not** be expanded lexically (`filepath.Clean` is not
called on the input before processing).
* Non-existent path components are unaffected by `SecureJoin` (similar to
`filepath.EvalSymlinks`'s semantics).
* The returned path will always be `filepath.Clean`ed and thus not contain any
`..` components.
A (trivial) implementation of this function on GNU/Linux systems could be done
with the following (note that this requires root privileges and is far more
opaque than the implementation in this library, and also requires that
`readlink` is inside the `root` path):
```go
package securejoin
import (
"os/exec"
"path/filepath"
)
func SecureJoin(root, unsafePath string) (string, error) {
unsafePath = string(filepath.Separator) + unsafePath
cmd := exec.Command("chroot", root,
"readlink", "--canonicalize-missing", "--no-newline", unsafePath)
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
expanded := string(output)
return filepath.Join(root, expanded), nil
}
```
[lwn-obeneath]: https://lwn.net/Articles/767547/
[go#20126]: https://github.com/golang/go/issues/20126
### License ###
The license of this project is the same as Go, which is a BSD 3-clause license
available in the `LICENSE` file.

View File

@ -1 +0,0 @@
0.2.3

View File

@ -1,115 +0,0 @@
// Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved.
// Copyright (C) 2017 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package securejoin is an implementation of the hopefully-soon-to-be-included
// SecureJoin helper that is meant to be part of the "path/filepath" package.
// The purpose of this project is to provide a PoC implementation to make the
// SecureJoin proposal (https://github.com/golang/go/issues/20126) more
// tangible.
package securejoin
import (
"bytes"
"errors"
"os"
"path/filepath"
"strings"
"syscall"
)
// IsNotExist tells you if err is an error that implies that either the path
// accessed does not exist (or path components don't exist). This is
// effectively a more broad version of os.IsNotExist.
func IsNotExist(err error) bool {
// Check that it's not actually an ENOTDIR, which in some cases is a more
// convoluted case of ENOENT (usually involving weird paths).
return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT)
}
// SecureJoinVFS joins the two given path components (similar to Join) except
// that the returned path is guaranteed to be scoped inside the provided root
// path (when evaluated). Any symbolic links in the path are evaluated with the
// given root treated as the root of the filesystem, similar to a chroot. The
// filesystem state is evaluated through the given VFS interface (if nil, the
// standard os.* family of functions are used).
//
// Note that the guarantees provided by this function only apply if the path
// components in the returned string are not modified (in other words are not
// replaced with symlinks on the filesystem) after this function has returned.
// Such a symlink race is necessarily out-of-scope of SecureJoin.
func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) {
// Use the os.* VFS implementation if none was specified.
if vfs == nil {
vfs = osVFS{}
}
var path bytes.Buffer
n := 0
for unsafePath != "" {
if n > 255 {
return "", &os.PathError{Op: "SecureJoin", Path: root + "/" + unsafePath, Err: syscall.ELOOP}
}
// Next path component, p.
i := strings.IndexRune(unsafePath, filepath.Separator)
var p string
if i == -1 {
p, unsafePath = unsafePath, ""
} else {
p, unsafePath = unsafePath[:i], unsafePath[i+1:]
}
// Create a cleaned path, using the lexical semantics of /../a, to
// create a "scoped" path component which can safely be joined to fullP
// for evaluation. At this point, path.String() doesn't contain any
// symlink components.
cleanP := filepath.Clean(string(filepath.Separator) + path.String() + p)
if cleanP == string(filepath.Separator) {
path.Reset()
continue
}
fullP := filepath.Clean(root + cleanP)
// Figure out whether the path is a symlink.
fi, err := vfs.Lstat(fullP)
if err != nil && !IsNotExist(err) {
return "", err
}
// Treat non-existent path components the same as non-symlinks (we
// can't do any better here).
if IsNotExist(err) || fi.Mode()&os.ModeSymlink == 0 {
path.WriteString(p)
path.WriteRune(filepath.Separator)
continue
}
// Only increment when we actually dereference a link.
n++
// It's a symlink, expand it by prepending it to the yet-unparsed path.
dest, err := vfs.Readlink(fullP)
if err != nil {
return "", err
}
// Absolute symlinks reset any work we've already done.
if filepath.IsAbs(dest) {
path.Reset()
}
unsafePath = dest + string(filepath.Separator) + unsafePath
}
// We have to clean path.String() here because it may contain '..'
// components that are entirely lexical, but would be misleading otherwise.
// And finally do a final clean to ensure that root is also lexically
// clean.
fullP := filepath.Clean(string(filepath.Separator) + path.String())
return filepath.Clean(root + fullP), nil
}
// SecureJoin is a wrapper around SecureJoinVFS that just uses the os.* library
// of functions as the VFS. If in doubt, use this function over SecureJoinVFS.
func SecureJoin(root, unsafePath string) (string, error) {
return SecureJoinVFS(root, unsafePath, nil)
}

View File

@ -1,41 +0,0 @@
// Copyright (C) 2017 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import "os"
// In future this should be moved into a separate package, because now there
// are several projects (umoci and go-mtree) that are using this sort of
// interface.
// VFS is the minimal interface necessary to use SecureJoinVFS. A nil VFS is
// equivalent to using the standard os.* family of functions. This is mainly
// used for the purposes of mock testing, but also can be used to otherwise use
// SecureJoin with VFS-like system.
type VFS interface {
// Lstat returns a FileInfo describing the named file. If the file is a
// symbolic link, the returned FileInfo describes the symbolic link. Lstat
// makes no attempt to follow the link. These semantics are identical to
// os.Lstat.
Lstat(name string) (os.FileInfo, error)
// Readlink returns the destination of the named symbolic link. These
// semantics are identical to os.Readlink.
Readlink(name string) (string, error)
}
// osVFS is the "nil" VFS, in that it just passes everything through to the os
// module.
type osVFS struct{}
// Lstat returns a FileInfo describing the named file. If the file is a
// symbolic link, the returned FileInfo describes the symbolic link. Lstat
// makes no attempt to follow the link. These semantics are identical to
// os.Lstat.
func (o osVFS) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) }
// Readlink returns the destination of the named symbolic link. These
// semantics are identical to os.Readlink.
func (o osVFS) Readlink(name string) (string, error) { return os.Readlink(name) }

View File

@ -245,8 +245,7 @@ func Git(url, ref string, opts ...GitOption) State {
remote, err = gitutil.ParseURL(url)
}
if remote != nil {
remote.Fragment = ""
url = remote.String()
url = remote.Remote
}
var id string

View File

@ -12,9 +12,6 @@ import (
)
const (
// indexFile is the name of the index file
indexFile = "index.json"
// lockFileSuffix is the suffix of the lock file
lockFileSuffix = ".lock"
)
@ -26,7 +23,7 @@ type StoreIndex struct {
}
func NewStoreIndex(storePath string) StoreIndex {
indexPath := path.Join(storePath, indexFile)
indexPath := path.Join(storePath, ocispecs.ImageIndexFile)
layoutPath := path.Join(storePath, ocispecs.ImageLayoutFile)
return StoreIndex{
indexPath: indexPath,

View File

@ -4,7 +4,7 @@ import (
"context"
"runtime/debug"
"github.com/containerd/containerd/log"
"github.com/containerd/log"
"github.com/sirupsen/logrus"
"go.opentelemetry.io/otel/trace"
)

View File

@ -53,17 +53,17 @@ func ParseGitRef(ref string) (*GitRef, error) {
res := &GitRef{}
var (
remote *url.URL
remote *GitURL
err error
)
if strings.HasPrefix(ref, "github.com/") {
res.IndistinguishableFromLocal = true // Deprecated
remote = &url.URL{
remote = fromURL(&url.URL{
Scheme: "https",
Host: "github.com",
Path: strings.TrimPrefix(ref, "github.com/"),
}
})
} else {
remote, err = ParseURL(ref)
if errors.Is(err, ErrUnknownProtocol) {
@ -87,13 +87,13 @@ func ParseGitRef(ref string) (*GitRef, error) {
}
}
res.Commit, res.SubDir = SplitGitFragment(remote.Fragment)
remote.Fragment = ""
res.Remote = remote.String()
res.Remote = remote.Remote
if res.IndistinguishableFromLocal {
_, res.Remote, _ = strings.Cut(res.Remote, "://")
}
if remote.Fragment != nil {
res.Commit, res.SubDir = remote.Fragment.Ref, remote.Fragment.Subdir
}
repoSplitBySlash := strings.Split(res.Remote, "/")
res.ShortName = strings.TrimSuffix(repoSplitBySlash[len(repoSplitBySlash)-1], ".git")

View File

@ -30,42 +30,94 @@ var supportedProtos = map[string]struct{}{
var protoRegexp = regexp.MustCompile(`^[a-zA-Z0-9]+://`)
// ParseURL parses a git URL and returns a parsed URL object.
// URL is a custom URL type that points to a remote Git repository.
//
// ParseURL understands implicit ssh URLs such as "git@host:repo", and
// returns the same response as if the URL were "ssh://git@host/repo".
func ParseURL(remote string) (*url.URL, error) {
// URLs can be parsed from both standard URLs (e.g.
// "https://github.com/moby/buildkit.git"), as well as SCP-like URLs (e.g.
// "git@github.com:moby/buildkit.git").
//
// See https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols
type GitURL struct {
// Scheme is the protocol over which the git repo can be accessed
Scheme string
// Host is the remote host that hosts the git repo
Host string
// Path is the path on the host to access the repo
Path string
// User is the username/password to access the host
User *url.Userinfo
// Fragment can contain additional metadata
Fragment *GitURLFragment
// Remote is a valid URL remote to pass into the Git CLI tooling (i.e.
// without the fragment metadata)
Remote string
}
// GitURLFragment is the buildkit-specific metadata extracted from the fragment
// of a remote URL.
type GitURLFragment struct {
// Ref is the git reference
Ref string
// Subdir is the sub-directory inside the git repository to use
Subdir string
}
// splitGitFragment splits a git URL fragment into its respective git
// reference and subdirectory components.
func splitGitFragment(fragment string) *GitURLFragment {
if fragment == "" {
return nil
}
ref, subdir, _ := strings.Cut(fragment, ":")
return &GitURLFragment{Ref: ref, Subdir: subdir}
}
// ParseURL parses a BuildKit-style Git URL (that may contain additional
// fragment metadata) and returns a parsed GitURL object.
func ParseURL(remote string) (*GitURL, error) {
if proto := protoRegexp.FindString(remote); proto != "" {
proto = strings.ToLower(strings.TrimSuffix(proto, "://"))
if _, ok := supportedProtos[proto]; !ok {
return nil, errors.Wrap(ErrInvalidProtocol, proto)
}
return url.Parse(remote)
url, err := url.Parse(remote)
if err != nil {
return nil, err
}
return fromURL(url), nil
}
if sshutil.IsImplicitSSHTransport(remote) {
remote, fragment, _ := strings.Cut(remote, "#")
remote, path, _ := strings.Cut(remote, ":")
user, host, _ := strings.Cut(remote, "@")
if !strings.HasPrefix(path, "/") {
path = "/" + path
}
return &url.URL{
Scheme: SSHProtocol,
User: url.User(user),
Host: host,
Path: path,
Fragment: fragment,
}, nil
if url, err := sshutil.ParseSCPStyleURL(remote); err == nil {
return fromSCPStyleURL(url), nil
}
return nil, ErrUnknownProtocol
}
// SplitGitFragments splits a git URL fragment into its respective git
// reference and subdirectory components.
func SplitGitFragment(fragment string) (ref string, subdir string) {
ref, subdir, _ = strings.Cut(fragment, ":")
return ref, subdir
func fromURL(url *url.URL) *GitURL {
withoutFragment := *url
withoutFragment.Fragment = ""
return &GitURL{
Scheme: url.Scheme,
User: url.User,
Host: url.Host,
Path: url.Path,
Fragment: splitGitFragment(url.Fragment),
Remote: withoutFragment.String(),
}
}
func fromSCPStyleURL(url *sshutil.SCPStyleURL) *GitURL {
withoutFragment := *url
withoutFragment.Fragment = ""
return &GitURL{
Scheme: SSHProtocol,
User: url.User,
Host: url.Host,
Path: url.Path,
Fragment: splitGitFragment(url.Fragment),
Remote: withoutFragment.String(),
}
}

View File

@ -156,6 +156,7 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, cache Co
}
children := childrenConfigHandler(cache, platform)
children = images.LimitManifests(children, platform, 1)
dslHandler, err := docker.AppendDistributionSourceLabel(cache, ref.String())
if err != nil {

View File

@ -310,7 +310,6 @@ func (d *rawJSONDisplay) done() {
// No actions needed.
}
const termHeight = 6
const termPad = 10
type displayInfo struct {

View File

@ -3,6 +3,7 @@ package progressui
import (
"os"
"runtime"
"strconv"
"github.com/morikuni/aec"
)
@ -12,6 +13,8 @@ var colorCancel aec.ANSI
var colorWarning aec.ANSI
var colorError aec.ANSI
var termHeight = 6
func init() {
// As recommended on https://no-color.org/
if v := os.Getenv("NO_COLOR"); v != "" {
@ -34,4 +37,13 @@ func init() {
envColorString := os.Getenv("BUILDKIT_COLORS")
setUserDefinedTermColors(envColorString)
}
// Make the terminal height configurable at runtime.
termHeightStr := os.Getenv("BUILDKIT_TTY_LOG_LINES")
if termHeightStr != "" {
termHeightVal, err := strconv.Atoi(termHeightStr)
if err == nil && termHeightVal > 0 {
termHeight = termHeightVal
}
}
}

43
vendor/github.com/moby/buildkit/util/sshutil/scpurl.go generated vendored Normal file
View File

@ -0,0 +1,43 @@
package sshutil
import (
"errors"
"fmt"
"net/url"
"regexp"
)
var gitSSHRegex = regexp.MustCompile("^([a-zA-Z0-9-_]+)@([a-zA-Z0-9-.]+):(.*?)(?:#(.*))?$")
func IsImplicitSSHTransport(s string) bool {
return gitSSHRegex.MatchString(s)
}
type SCPStyleURL struct {
User *url.Userinfo
Host string
Path string
Fragment string
}
func ParseSCPStyleURL(raw string) (*SCPStyleURL, error) {
matches := gitSSHRegex.FindStringSubmatch(raw)
if matches == nil {
return nil, errors.New("invalid scp-style url")
}
return &SCPStyleURL{
User: url.User(matches[1]),
Host: matches[2],
Path: matches[3],
Fragment: matches[4],
}, nil
}
func (url *SCPStyleURL) String() string {
base := fmt.Sprintf("%s@%s:%s", url.User.String(), url.Host, url.Path)
if url.Fragment == "" {
return base
}
return base + "#" + url.Fragment
}

View File

@ -1,11 +0,0 @@
package sshutil
import (
"regexp"
)
var gitSSHRegex = regexp.MustCompile("^[a-zA-Z0-9-_]+@[a-zA-Z0-9-.]+:.*$")
func IsImplicitSSHTransport(s string) bool {
return gitSSHRegex.MatchString(s)
}

View File

@ -59,10 +59,4 @@ const (
// AnnotationBaseImageName is the annotation key for the image reference of the image's base image.
AnnotationBaseImageName = "org.opencontainers.image.base.name"
// AnnotationArtifactCreated is the annotation key for the date and time on which the artifact was built, conforming to RFC 3339.
AnnotationArtifactCreated = "org.opencontainers.artifact.created"
// AnnotationArtifactDescription is the annotation key for the human readable description for the artifact.
AnnotationArtifactDescription = "org.opencontainers.artifact.description"
)

View File

@ -21,7 +21,7 @@ import digest "github.com/opencontainers/go-digest"
// when marshalled to JSON.
type Descriptor struct {
// MediaType is the media type of the object this schema refers to.
MediaType string `json:"mediaType,omitempty"`
MediaType string `json:"mediaType"`
// Digest is the digest of the targeted content.
Digest digest.Digest `json:"digest"`
@ -52,7 +52,7 @@ type Descriptor struct {
// Platform describes the platform which the image in the manifest runs on.
type Platform struct {
// Architecture field specifies the CPU architecture, for example
// `amd64` or `ppc64`.
// `amd64` or `ppc64le`.
Architecture string `json:"architecture"`
// OS specifies the operating system, for example `linux` or `windows`.
@ -70,3 +70,11 @@ type Platform struct {
// example `v7` to specify ARMv7 when architecture is `arm`.
Variant string `json:"variant,omitempty"`
}
// DescriptorEmptyJSON is the descriptor of a blob with content of `{}`.
var DescriptorEmptyJSON = Descriptor{
MediaType: MediaTypeEmptyJSON,
Digest: `sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a`,
Size: 2,
Data: []byte(`{}`),
}

View File

@ -24,9 +24,15 @@ type Index struct {
// MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json`
MediaType string `json:"mediaType,omitempty"`
// ArtifactType specifies the IANA media type of artifact when the manifest is used for an artifact.
ArtifactType string `json:"artifactType,omitempty"`
// Manifests references platform specific manifests.
Manifests []Descriptor `json:"manifests"`
// Subject is an optional link from the image manifest to another manifest forming an association between the image manifest and the other manifest.
Subject *Descriptor `json:"subject,omitempty"`
// Annotations contains arbitrary metadata for the image index.
Annotations map[string]string `json:"annotations,omitempty"`
}

View File

@ -15,10 +15,14 @@
package v1
const (
// ImageLayoutFile is the file name of oci image layout file
// ImageLayoutFile is the file name containing ImageLayout in an OCI Image Layout
ImageLayoutFile = "oci-layout"
// ImageLayoutVersion is the version of ImageLayout
ImageLayoutVersion = "1.0.0"
// ImageIndexFile is the file name of the entry point for references and descriptors in an OCI Image Layout
ImageIndexFile = "index.json"
// ImageBlobsDir is the directory name containing content addressable blobs in an OCI Image Layout
ImageBlobsDir = "blobs"
)
// ImageLayout is the structure in the "oci-layout" file, found in the root

View File

@ -39,11 +39,3 @@ type Manifest struct {
// Annotations contains arbitrary metadata for the image manifest.
Annotations map[string]string `json:"annotations,omitempty"`
}
// ScratchDescriptor is the descriptor of a blob with content of `{}`.
var ScratchDescriptor = Descriptor{
MediaType: MediaTypeScratch,
Digest: `sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a`,
Size: 2,
Data: []byte(`{}`),
}

View File

@ -70,6 +70,6 @@ const (
// MediaTypeImageConfig specifies the media type for the image configuration.
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
// MediaTypeScratch specifies the media type for an unused blob containing the value `{}`
MediaTypeScratch = "application/vnd.oci.scratch.v1+json"
// MediaTypeEmptyJSON specifies the media type for an unused blob containing the value `{}`
MediaTypeEmptyJSON = "application/vnd.oci.empty.v1+json"
)

View File

@ -25,7 +25,7 @@ const (
VersionPatch = 0
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = "-rc.3"
VersionDev = "-rc.5"
)
// Version is the specification version that the package types support.