Merge pull request #51482 from thaJeztah/vendor_containerd_2.2.0

vendor: github.com/containerd/containerd/v2 v2.2.0
This commit is contained in:
Sebastiaan van Stijn
2025-11-11 17:35:23 +01:00
committed by GitHub
100 changed files with 3854 additions and 10790 deletions

12
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/moby/moby/v2
go 1.24.0
go 1.24.3
require (
cloud.google.com/go/compute/metadata v0.8.0
@@ -21,8 +21,8 @@ require (
github.com/aws/smithy-go v1.23.1
github.com/cloudflare/cfssl v1.6.4
github.com/containerd/cgroups/v3 v3.1.0
github.com/containerd/containerd/api v1.9.0
github.com/containerd/containerd/v2 v2.1.5
github.com/containerd/containerd/api v1.10.0
github.com/containerd/containerd/v2 v2.2.0
github.com/containerd/continuity v0.4.5
github.com/containerd/errdefs v1.0.0
github.com/containerd/fifo v1.1.0
@@ -148,14 +148,14 @@ require (
github.com/containerd/accelerated-container-image v1.3.0 // indirect
github.com/containerd/console v1.0.5 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/go-cni v1.1.12 // indirect
github.com/containerd/go-cni v1.1.13 // indirect
github.com/containerd/go-runc v1.1.0 // indirect
github.com/containerd/nydus-snapshotter v0.15.2 // indirect
github.com/containerd/plugin v1.0.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containernetworking/cni v1.3.0 // indirect
github.com/containernetworking/plugins v1.7.1 // indirect
github.com/containernetworking/plugins v1.8.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/cyphar/filepath-securejoin v0.6.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
@@ -246,6 +246,6 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
tags.cncf.io/container-device-interface/specs-go v1.0.0 // indirect
)

35
go.sum
View File

@@ -40,6 +40,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Graylog2/go-gelf v0.0.0-20191017102106-1550ee647df0 h1:cOjLyhBhe91glgZZNbQUg9BJC57l6BiSKov0Ivv7k0U=
github.com/Graylog2/go-gelf v0.0.0-20191017102106-1550ee647df0/go.mod h1:fBaQWrftOD5CrVCUfoYGHs4X4VViTuGOXA8WloCjTY0=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.14.0-rc.1 h1:qAPXKwGOkVn8LlqgBN8GS0bxZ83hOJpcjxzmlQKxKsQ=
@@ -129,10 +131,10 @@ github.com/containerd/cgroups/v3 v3.1.0 h1:azxYVj+91ZgSnIBp2eI3k9y2iYQSR/ZQIgh9v
github.com/containerd/cgroups/v3 v3.1.0/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
github.com/containerd/containerd/v2 v2.1.5 h1:pWSmPxUszaLZKQPvOx27iD4iH+aM6o0BoN9+hg77cro=
github.com/containerd/containerd/v2 v2.1.5/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o=
github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM=
github.com/containerd/containerd/v2 v2.2.0 h1:K7TqcXy+LnFmZaui2DgHsnp2gAHhVNWYaHlx7HXfys8=
github.com/containerd/containerd/v2 v2.2.0/go.mod h1:YCMjKjA4ZA7egdHNi3/93bJR1+2oniYlnS+c0N62HdE=
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
@@ -141,8 +143,8 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
github.com/containerd/go-cni v1.1.12 h1:wm/5VD/i255hjM4uIZjBRiEQ7y98W9ACy/mHeLi4+94=
github.com/containerd/go-cni v1.1.12/go.mod h1:+jaqRBdtW5faJxj2Qwg1Of7GsV66xcvnCx4mSJtUlxU=
github.com/containerd/go-cni v1.1.13 h1:eFSGOKlhoYNxpJ51KRIMHZNlg5UgocXEIEBGkY7Hnis=
github.com/containerd/go-cni v1.1.13/go.mod h1:nTieub0XDRmvCZ9VI/SBG6PyqT95N4FIhxsauF1vSBI=
github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA=
github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
@@ -161,8 +163,8 @@ github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo=
github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4=
github.com/containernetworking/plugins v1.7.1 h1:CNAR0jviDj6FS5Vg85NTgKWLDzZPfi/lj+VJfhMDTIs=
github.com/containernetworking/plugins v1.7.1/go.mod h1:xuMdjuio+a1oVQsHKjr/mgzuZ24leAsqUYRnzGoXHy0=
github.com/containernetworking/plugins v1.8.0 h1:WjGbV/0UQyo8A4qBsAh6GaDAtu1hevxVxsEuqtBqUFk=
github.com/containernetworking/plugins v1.8.0/go.mod h1:JG3BxoJifxxHBhG3hFyxyhid7JgRVBu/wtooGEvWf1c=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
@@ -285,8 +287,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250423184734-337e5dd93bb4 h1:gD0vax+4I+mAj+jEChEf25Ia07Jq7kYOFO5PPhAxFl4=
github.com/google/pprof v0.0.0-20250423184734-337e5dd93bb4/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY=
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
@@ -470,10 +472,10 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY=
github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
github.com/onsi/gomega v1.38.1 h1:FaLA8GlcpXDwsb7m0h2A9ew2aTk3vnZMlzFgg5tz/pk=
github.com/onsi/gomega v1.38.1/go.mod h1:LfcV8wZLvwcYRwPiJysphKAEsmcFnLMK/9c+PjvlX8g=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/cgroups v0.0.5 h1:DRITAqcOnY0uSBzIpt1RYWLjh5DPDiqUs4fY6Y0ktls=
github.com/opencontainers/cgroups v0.0.5/go.mod h1:oWVzJsKK0gG9SCRBfTpnn16WcGEqDI8PAcpMGbqWxcs=
@@ -688,6 +690,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -856,8 +860,9 @@ pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=
pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
resenje.org/singleflight v0.4.3 h1:l7foFYg8X/VEHPxWs1K/Pw77807RMVzvXgWGb0J1sdM=
resenje.org/singleflight v0.4.3/go.mod h1:lAgQK7VfjG6/pgredbQfmV0RvG/uVhKo6vSuZ0vCWfk=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
tags.cncf.io/container-device-interface v1.0.1 h1:KqQDr4vIlxwfYh0Ed/uJGVgX+CHAkahrgabg6Q8GYxc=
tags.cncf.io/container-device-interface v1.0.1/go.mod h1:JojJIOeW3hNbcnOH2q0NrWNha/JuHoDZcmYxAZwb2i0=
tags.cncf.io/container-device-interface/specs-go v1.0.0 h1:8gLw29hH1ZQP9K1YtAzpvkHCjjyIxHZYzBAvlQ+0vD8=

View File

@@ -0,0 +1,17 @@
/*
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 mounts

View File

@@ -0,0 +1,789 @@
//
//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.
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.20.1
// source: github.com/containerd/containerd/api/services/mounts/v1/mounts.proto
package mounts
import (
types "github.com/containerd/containerd/api/types"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type ActivateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Mounts []*types.Mount `protobuf:"bytes,2,rep,name=mounts,proto3" json:"mounts,omitempty"`
Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Temporary bool `protobuf:"varint,4,opt,name=temporary,proto3" json:"temporary,omitempty"`
}
func (x *ActivateRequest) Reset() {
*x = ActivateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ActivateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActivateRequest) ProtoMessage() {}
func (x *ActivateRequest) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActivateRequest.ProtoReflect.Descriptor instead.
func (*ActivateRequest) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP(), []int{0}
}
func (x *ActivateRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *ActivateRequest) GetMounts() []*types.Mount {
if x != nil {
return x.Mounts
}
return nil
}
func (x *ActivateRequest) GetLabels() map[string]string {
if x != nil {
return x.Labels
}
return nil
}
func (x *ActivateRequest) GetTemporary() bool {
if x != nil {
return x.Temporary
}
return false
}
type ActivateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Info *types.ActivationInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
}
func (x *ActivateResponse) Reset() {
*x = ActivateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ActivateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActivateResponse) ProtoMessage() {}
func (x *ActivateResponse) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActivateResponse.ProtoReflect.Descriptor instead.
func (*ActivateResponse) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP(), []int{1}
}
func (x *ActivateResponse) GetInfo() *types.ActivationInfo {
if x != nil {
return x.Info
}
return nil
}
type DeactivateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *DeactivateRequest) Reset() {
*x = DeactivateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeactivateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeactivateRequest) ProtoMessage() {}
func (x *DeactivateRequest) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeactivateRequest.ProtoReflect.Descriptor instead.
func (*DeactivateRequest) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP(), []int{2}
}
func (x *DeactivateRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type InfoRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *InfoRequest) Reset() {
*x = InfoRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *InfoRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*InfoRequest) ProtoMessage() {}
func (x *InfoRequest) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use InfoRequest.ProtoReflect.Descriptor instead.
func (*InfoRequest) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP(), []int{3}
}
func (x *InfoRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type InfoResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Info *types.ActivationInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
}
func (x *InfoResponse) Reset() {
*x = InfoResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *InfoResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*InfoResponse) ProtoMessage() {}
func (x *InfoResponse) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use InfoResponse.ProtoReflect.Descriptor instead.
func (*InfoResponse) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP(), []int{4}
}
func (x *InfoResponse) GetInfo() *types.ActivationInfo {
if x != nil {
return x.Info
}
return nil
}
type UpdateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Info *types.ActivationInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"`
}
func (x *UpdateRequest) Reset() {
*x = UpdateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UpdateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UpdateRequest) ProtoMessage() {}
func (x *UpdateRequest) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UpdateRequest.ProtoReflect.Descriptor instead.
func (*UpdateRequest) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP(), []int{5}
}
func (x *UpdateRequest) GetInfo() *types.ActivationInfo {
if x != nil {
return x.Info
}
return nil
}
func (x *UpdateRequest) GetUpdateMask() *fieldmaskpb.FieldMask {
if x != nil {
return x.UpdateMask
}
return nil
}
type UpdateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Info *types.ActivationInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
}
func (x *UpdateResponse) Reset() {
*x = UpdateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UpdateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UpdateResponse) ProtoMessage() {}
func (x *UpdateResponse) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UpdateResponse.ProtoReflect.Descriptor instead.
func (*UpdateResponse) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP(), []int{6}
}
func (x *UpdateResponse) GetInfo() *types.ActivationInfo {
if x != nil {
return x.Info
}
return nil
}
type ListRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Filters []string `protobuf:"bytes,1,rep,name=filters,proto3" json:"filters,omitempty"`
}
func (x *ListRequest) Reset() {
*x = ListRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListRequest) ProtoMessage() {}
func (x *ListRequest) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListRequest.ProtoReflect.Descriptor instead.
func (*ListRequest) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP(), []int{7}
}
func (x *ListRequest) GetFilters() []string {
if x != nil {
return x.Filters
}
return nil
}
type ListMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Info *types.ActivationInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
}
func (x *ListMessage) Reset() {
*x = ListMessage{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ListMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListMessage) ProtoMessage() {}
func (x *ListMessage) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListMessage.ProtoReflect.Descriptor instead.
func (*ListMessage) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP(), []int{8}
}
func (x *ListMessage) GetInfo() *types.ActivationInfo {
if x != nil {
return x.Info
}
return nil
}
var File_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto protoreflect.FileDescriptor
var file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDesc = []byte{
0x0a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e,
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
0x72, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f,
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e,
0x74, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74,
0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73,
0x2f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x83, 0x02, 0x0a,
0x0f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x02,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x64, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x6d,
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x52, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18,
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e,
0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x65, 0x6d,
0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, 0x65,
0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c,
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x22, 0x48, 0x0a, 0x10, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x64, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x27, 0x0a, 0x11,
0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x21, 0x0a, 0x0b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x44, 0x0a, 0x0c, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x64, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x82,
0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x34, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x74, 0x79, 0x70, 0x65,
0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d,
0x61, 0x73, 0x6b, 0x22, 0x46, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64,
0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x27, 0x0a, 0x0b, 0x4c,
0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x69,
0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x66, 0x69, 0x6c,
0x74, 0x65, 0x72, 0x73, 0x22, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x74,
0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x32, 0xf7, 0x03, 0x0a, 0x06, 0x4d, 0x6f,
0x75, 0x6e, 0x74, 0x73, 0x12, 0x6b, 0x0a, 0x08, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x56, 0x0a, 0x0a, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12,
0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x5f, 0x0a, 0x04, 0x49, 0x6e, 0x66,
0x6f, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e,
0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x06, 0x55, 0x70,
0x64, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x60, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x6d, 0x6f, 0x75, 0x6e,
0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x30, 0x01, 0x42, 0x40, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e,
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x6d,
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescOnce sync.Once
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescData = file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDesc
)
func file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescGZIP() []byte {
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescOnce.Do(func() {
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescData)
})
return file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDescData
}
var file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_goTypes = []interface{}{
(*ActivateRequest)(nil), // 0: containerd.services.mounts.v1.ActivateRequest
(*ActivateResponse)(nil), // 1: containerd.services.mounts.v1.ActivateResponse
(*DeactivateRequest)(nil), // 2: containerd.services.mounts.v1.DeactivateRequest
(*InfoRequest)(nil), // 3: containerd.services.mounts.v1.InfoRequest
(*InfoResponse)(nil), // 4: containerd.services.mounts.v1.InfoResponse
(*UpdateRequest)(nil), // 5: containerd.services.mounts.v1.UpdateRequest
(*UpdateResponse)(nil), // 6: containerd.services.mounts.v1.UpdateResponse
(*ListRequest)(nil), // 7: containerd.services.mounts.v1.ListRequest
(*ListMessage)(nil), // 8: containerd.services.mounts.v1.ListMessage
nil, // 9: containerd.services.mounts.v1.ActivateRequest.LabelsEntry
(*types.Mount)(nil), // 10: containerd.types.Mount
(*types.ActivationInfo)(nil), // 11: containerd.types.ActivationInfo
(*fieldmaskpb.FieldMask)(nil), // 12: google.protobuf.FieldMask
(*emptypb.Empty)(nil), // 13: google.protobuf.Empty
}
var file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_depIdxs = []int32{
10, // 0: containerd.services.mounts.v1.ActivateRequest.mounts:type_name -> containerd.types.Mount
9, // 1: containerd.services.mounts.v1.ActivateRequest.labels:type_name -> containerd.services.mounts.v1.ActivateRequest.LabelsEntry
11, // 2: containerd.services.mounts.v1.ActivateResponse.info:type_name -> containerd.types.ActivationInfo
11, // 3: containerd.services.mounts.v1.InfoResponse.info:type_name -> containerd.types.ActivationInfo
11, // 4: containerd.services.mounts.v1.UpdateRequest.info:type_name -> containerd.types.ActivationInfo
12, // 5: containerd.services.mounts.v1.UpdateRequest.update_mask:type_name -> google.protobuf.FieldMask
11, // 6: containerd.services.mounts.v1.UpdateResponse.info:type_name -> containerd.types.ActivationInfo
11, // 7: containerd.services.mounts.v1.ListMessage.info:type_name -> containerd.types.ActivationInfo
0, // 8: containerd.services.mounts.v1.Mounts.Activate:input_type -> containerd.services.mounts.v1.ActivateRequest
2, // 9: containerd.services.mounts.v1.Mounts.Deactivate:input_type -> containerd.services.mounts.v1.DeactivateRequest
3, // 10: containerd.services.mounts.v1.Mounts.Info:input_type -> containerd.services.mounts.v1.InfoRequest
5, // 11: containerd.services.mounts.v1.Mounts.Update:input_type -> containerd.services.mounts.v1.UpdateRequest
7, // 12: containerd.services.mounts.v1.Mounts.List:input_type -> containerd.services.mounts.v1.ListRequest
1, // 13: containerd.services.mounts.v1.Mounts.Activate:output_type -> containerd.services.mounts.v1.ActivateResponse
13, // 14: containerd.services.mounts.v1.Mounts.Deactivate:output_type -> google.protobuf.Empty
4, // 15: containerd.services.mounts.v1.Mounts.Info:output_type -> containerd.services.mounts.v1.InfoResponse
6, // 16: containerd.services.mounts.v1.Mounts.Update:output_type -> containerd.services.mounts.v1.UpdateResponse
8, // 17: containerd.services.mounts.v1.Mounts.List:output_type -> containerd.services.mounts.v1.ListMessage
13, // [13:18] is the sub-list for method output_type
8, // [8:13] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_init() }
func file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_init() {
if File_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ActivateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ActivateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeactivateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*InfoRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*InfoResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListMessage); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDesc,
NumEnums: 0,
NumMessages: 10,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_goTypes,
DependencyIndexes: file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_depIdxs,
MessageInfos: file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_msgTypes,
}.Build()
File_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto = out.File
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_rawDesc = nil
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_goTypes = nil
file_github_com_containerd_containerd_api_services_mounts_v1_mounts_proto_depIdxs = nil
}

View File

@@ -0,0 +1,78 @@
/*
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.
*/
syntax = "proto3";
package containerd.services.mounts.v1;
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "github.com/containerd/containerd/api/types/mount.proto";
option go_package = "github.com/containerd/containerd/api/services/mounts/v1;mounts";
// Mounts service manages mounts
service Mounts {
rpc Activate(ActivateRequest) returns (ActivateResponse);
rpc Deactivate(DeactivateRequest) returns (google.protobuf.Empty);
rpc Info(InfoRequest) returns (InfoResponse);
rpc Update(UpdateRequest) returns (UpdateResponse);
rpc List(ListRequest) returns (stream ListMessage);
}
message ActivateRequest {
string name = 1;
repeated containerd.types.Mount mounts = 2;
map<string, string> labels = 3;
bool temporary = 4;
}
message ActivateResponse {
containerd.types.ActivationInfo info = 1;
}
message DeactivateRequest {
string name = 1;
}
message InfoRequest {
string name = 1;
}
message InfoResponse {
containerd.types.ActivationInfo info = 1;
}
message UpdateRequest {
containerd.types.ActivationInfo info = 1;
google.protobuf.FieldMask update_mask = 2;
}
message UpdateResponse {
containerd.types.ActivationInfo info = 1;
}
message ListRequest {
repeated string filters = 1;
}
message ListMessage {
containerd.types.ActivationInfo info = 1;
}

View File

@@ -0,0 +1,280 @@
//go:build !no_grpc
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc v3.20.1
// source: github.com/containerd/containerd/api/services/mounts/v1/mounts.proto
package mounts
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// MountsClient is the client API for Mounts service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type MountsClient interface {
Activate(ctx context.Context, in *ActivateRequest, opts ...grpc.CallOption) (*ActivateResponse, error)
Deactivate(ctx context.Context, in *DeactivateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error)
Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error)
List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (Mounts_ListClient, error)
}
type mountsClient struct {
cc grpc.ClientConnInterface
}
func NewMountsClient(cc grpc.ClientConnInterface) MountsClient {
return &mountsClient{cc}
}
func (c *mountsClient) Activate(ctx context.Context, in *ActivateRequest, opts ...grpc.CallOption) (*ActivateResponse, error) {
out := new(ActivateResponse)
err := c.cc.Invoke(ctx, "/containerd.services.mounts.v1.Mounts/Activate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *mountsClient) Deactivate(ctx context.Context, in *DeactivateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, "/containerd.services.mounts.v1.Mounts/Deactivate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *mountsClient) Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error) {
out := new(InfoResponse)
err := c.cc.Invoke(ctx, "/containerd.services.mounts.v1.Mounts/Info", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *mountsClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) {
out := new(UpdateResponse)
err := c.cc.Invoke(ctx, "/containerd.services.mounts.v1.Mounts/Update", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *mountsClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (Mounts_ListClient, error) {
stream, err := c.cc.NewStream(ctx, &Mounts_ServiceDesc.Streams[0], "/containerd.services.mounts.v1.Mounts/List", opts...)
if err != nil {
return nil, err
}
x := &mountsListClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type Mounts_ListClient interface {
Recv() (*ListMessage, error)
grpc.ClientStream
}
type mountsListClient struct {
grpc.ClientStream
}
func (x *mountsListClient) Recv() (*ListMessage, error) {
m := new(ListMessage)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// MountsServer is the server API for Mounts service.
// All implementations must embed UnimplementedMountsServer
// for forward compatibility
type MountsServer interface {
Activate(context.Context, *ActivateRequest) (*ActivateResponse, error)
Deactivate(context.Context, *DeactivateRequest) (*emptypb.Empty, error)
Info(context.Context, *InfoRequest) (*InfoResponse, error)
Update(context.Context, *UpdateRequest) (*UpdateResponse, error)
List(*ListRequest, Mounts_ListServer) error
mustEmbedUnimplementedMountsServer()
}
// UnimplementedMountsServer must be embedded to have forward compatible implementations.
type UnimplementedMountsServer struct {
}
func (UnimplementedMountsServer) Activate(context.Context, *ActivateRequest) (*ActivateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Activate not implemented")
}
func (UnimplementedMountsServer) Deactivate(context.Context, *DeactivateRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method Deactivate not implemented")
}
func (UnimplementedMountsServer) Info(context.Context, *InfoRequest) (*InfoResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Info not implemented")
}
func (UnimplementedMountsServer) Update(context.Context, *UpdateRequest) (*UpdateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Update not implemented")
}
func (UnimplementedMountsServer) List(*ListRequest, Mounts_ListServer) error {
return status.Errorf(codes.Unimplemented, "method List not implemented")
}
func (UnimplementedMountsServer) mustEmbedUnimplementedMountsServer() {}
// UnsafeMountsServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to MountsServer will
// result in compilation errors.
type UnsafeMountsServer interface {
mustEmbedUnimplementedMountsServer()
}
func RegisterMountsServer(s grpc.ServiceRegistrar, srv MountsServer) {
s.RegisterService(&Mounts_ServiceDesc, srv)
}
func _Mounts_Activate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ActivateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MountsServer).Activate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/containerd.services.mounts.v1.Mounts/Activate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MountsServer).Activate(ctx, req.(*ActivateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Mounts_Deactivate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeactivateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MountsServer).Deactivate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/containerd.services.mounts.v1.Mounts/Deactivate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MountsServer).Deactivate(ctx, req.(*DeactivateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Mounts_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(InfoRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MountsServer).Info(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/containerd.services.mounts.v1.Mounts/Info",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MountsServer).Info(ctx, req.(*InfoRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Mounts_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MountsServer).Update(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/containerd.services.mounts.v1.Mounts/Update",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MountsServer).Update(ctx, req.(*UpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Mounts_List_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(ListRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(MountsServer).List(m, &mountsListServer{stream})
}
type Mounts_ListServer interface {
Send(*ListMessage) error
grpc.ServerStream
}
type mountsListServer struct {
grpc.ServerStream
}
func (x *mountsListServer) Send(m *ListMessage) error {
return x.ServerStream.SendMsg(m)
}
// Mounts_ServiceDesc is the grpc.ServiceDesc for Mounts service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Mounts_ServiceDesc = grpc.ServiceDesc{
ServiceName: "containerd.services.mounts.v1.Mounts",
HandlerType: (*MountsServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Activate",
Handler: _Mounts_Activate_Handler,
},
{
MethodName: "Deactivate",
Handler: _Mounts_Deactivate_Handler,
},
{
MethodName: "Info",
Handler: _Mounts_Info_Handler,
},
{
MethodName: "Update",
Handler: _Mounts_Update_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "List",
Handler: _Mounts_List_Handler,
ServerStreams: true,
},
},
Metadata: "github.com/containerd/containerd/api/services/mounts/v1/mounts.proto",
}

View File

@@ -0,0 +1,157 @@
// Code generated by protoc-gen-go-ttrpc. DO NOT EDIT.
// source: github.com/containerd/containerd/api/services/mounts/v1/mounts.proto
package mounts
import (
context "context"
ttrpc "github.com/containerd/ttrpc"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
type TTRPCMountsService interface {
Activate(context.Context, *ActivateRequest) (*ActivateResponse, error)
Deactivate(context.Context, *DeactivateRequest) (*emptypb.Empty, error)
Info(context.Context, *InfoRequest) (*InfoResponse, error)
Update(context.Context, *UpdateRequest) (*UpdateResponse, error)
List(context.Context, *ListRequest, TTRPCMounts_ListServer) error
}
type TTRPCMounts_ListServer interface {
Send(*ListMessage) error
ttrpc.StreamServer
}
type ttrpcmountsListServer struct {
ttrpc.StreamServer
}
func (x *ttrpcmountsListServer) Send(m *ListMessage) error {
return x.StreamServer.SendMsg(m)
}
func RegisterTTRPCMountsService(srv *ttrpc.Server, svc TTRPCMountsService) {
srv.RegisterService("containerd.services.mounts.v1.Mounts", &ttrpc.ServiceDesc{
Methods: map[string]ttrpc.Method{
"Activate": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
var req ActivateRequest
if err := unmarshal(&req); err != nil {
return nil, err
}
return svc.Activate(ctx, &req)
},
"Deactivate": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
var req DeactivateRequest
if err := unmarshal(&req); err != nil {
return nil, err
}
return svc.Deactivate(ctx, &req)
},
"Info": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
var req InfoRequest
if err := unmarshal(&req); err != nil {
return nil, err
}
return svc.Info(ctx, &req)
},
"Update": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
var req UpdateRequest
if err := unmarshal(&req); err != nil {
return nil, err
}
return svc.Update(ctx, &req)
},
},
Streams: map[string]ttrpc.Stream{
"List": {
Handler: func(ctx context.Context, stream ttrpc.StreamServer) (interface{}, error) {
m := new(ListRequest)
if err := stream.RecvMsg(m); err != nil {
return nil, err
}
return nil, svc.List(ctx, m, &ttrpcmountsListServer{stream})
},
StreamingClient: false,
StreamingServer: true,
},
},
})
}
type TTRPCMountsClient interface {
Activate(context.Context, *ActivateRequest) (*ActivateResponse, error)
Deactivate(context.Context, *DeactivateRequest) (*emptypb.Empty, error)
Info(context.Context, *InfoRequest) (*InfoResponse, error)
Update(context.Context, *UpdateRequest) (*UpdateResponse, error)
List(context.Context, *ListRequest) (TTRPCMounts_ListClient, error)
}
type ttrpcmountsClient struct {
client *ttrpc.Client
}
func NewTTRPCMountsClient(client *ttrpc.Client) TTRPCMountsClient {
return &ttrpcmountsClient{
client: client,
}
}
func (c *ttrpcmountsClient) Activate(ctx context.Context, req *ActivateRequest) (*ActivateResponse, error) {
var resp ActivateResponse
if err := c.client.Call(ctx, "containerd.services.mounts.v1.Mounts", "Activate", req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
func (c *ttrpcmountsClient) Deactivate(ctx context.Context, req *DeactivateRequest) (*emptypb.Empty, error) {
var resp emptypb.Empty
if err := c.client.Call(ctx, "containerd.services.mounts.v1.Mounts", "Deactivate", req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
func (c *ttrpcmountsClient) Info(ctx context.Context, req *InfoRequest) (*InfoResponse, error) {
var resp InfoResponse
if err := c.client.Call(ctx, "containerd.services.mounts.v1.Mounts", "Info", req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
func (c *ttrpcmountsClient) Update(ctx context.Context, req *UpdateRequest) (*UpdateResponse, error) {
var resp UpdateResponse
if err := c.client.Call(ctx, "containerd.services.mounts.v1.Mounts", "Update", req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
func (c *ttrpcmountsClient) List(ctx context.Context, req *ListRequest) (TTRPCMounts_ListClient, error) {
stream, err := c.client.NewStream(ctx, &ttrpc.StreamDesc{
StreamingClient: false,
StreamingServer: true,
}, "containerd.services.mounts.v1.Mounts", "List", req)
if err != nil {
return nil, err
}
x := &ttrpcmountsListClient{stream}
return x, nil
}
type TTRPCMounts_ListClient interface {
Recv() (*ListMessage, error)
ttrpc.ClientStream
}
type ttrpcmountsListClient struct {
ttrpc.ClientStream
}
func (x *ttrpcmountsListClient) Recv() (*ListMessage, error) {
m := new(ListMessage)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}

View File

@@ -502,6 +502,7 @@ type CommitSnapshotRequest struct {
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
Labels map[string]string `protobuf:"bytes,4,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Parent string `protobuf:"bytes,5,opt,name=parent,proto3" json:"parent,omitempty"`
}
func (x *CommitSnapshotRequest) Reset() {
@@ -564,6 +565,13 @@ func (x *CommitSnapshotRequest) GetLabels() map[string]string {
return nil
}
func (x *CommitSnapshotRequest) GetParent() string {
if x != nil {
return x.Parent
}
return ""
}
type StatSnapshotRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1216,7 +1224,7 @@ var file_github_com_containerd_containerd_api_services_snapshots_v1_snapshots_pr
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61,
0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xf7, 0x01, 0x0a, 0x15, 0x43,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x8f, 0x02, 0x0a, 0x15, 0x43,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73,
@@ -1228,160 +1236,162 @@ var file_github_com_containerd_containerd_api_services_snapshots_v1_snapshots_pr
0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62,
0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x3a, 0x02, 0x38, 0x01, 0x22, 0x49, 0x0a, 0x13, 0x53, 0x74, 0x61, 0x74, 0x53, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x73,
0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a,
0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22,
0xeb, 0x02, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06,
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61,
0x72, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64,
0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75,
0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x4a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73,
0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61,
0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c,
0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65,
0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x52, 0x0a,
0x14, 0x53, 0x74, 0x61, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20,
0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e,
0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x49, 0x0a, 0x13,
0x53, 0x74, 0x61, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74,
0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xeb, 0x02, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x04,
0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69,
0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61,
0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x4a,
0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74,
0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61,
0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x52, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x74, 0x53, 0x6e, 0x61,
0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a,
0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0xb2, 0x01, 0x0a, 0x15, 0x55, 0x70,
0x64, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74,
0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66,
0x6f, 0x22, 0xb2, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x73,
0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a,
0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f,
0x6f, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61,
0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x54,
0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61,
0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04,
0x69, 0x6e, 0x66, 0x6f, 0x22, 0x52, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b,
0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x12, 0x18,
0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0x53, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74,
0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x3a, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x42, 0x0a,
0x0c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a,
0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x12,
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x79, 0x22, 0x3b, 0x0a, 0x0d, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x73,
0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x32,
0x0a, 0x0e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x20, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74,
0x65, 0x72, 0x2a, 0x38, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e,
0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x56, 0x49, 0x45, 0x57, 0x10,
0x01, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x0d, 0x0a,
0x09, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x54, 0x45, 0x44, 0x10, 0x03, 0x32, 0xd3, 0x08, 0x0a,
0x09, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x12, 0x7e, 0x0a, 0x07, 0x50, 0x72,
0x65, 0x70, 0x61, 0x72, 0x65, 0x12, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65,
0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x39, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x04, 0x56, 0x69,
0x65, 0x77, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e,
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x65, 0x77, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e,
0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x65,
0x77, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x6b, 0x0a, 0x06, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x2f, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x54, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x3a, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26,
0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d,
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59,
0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61,
0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73,
0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
0x69, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x59, 0x0a, 0x06, 0x52, 0x65, 0x6d,
0x6f, 0x76, 0x65, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x6e, 0x61,
0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
0x6d, 0x70, 0x74, 0x79, 0x12, 0x75, 0x0a, 0x04, 0x53, 0x74, 0x61, 0x74, 0x12, 0x35, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x53, 0x74, 0x61, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73,
0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x06, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53,
0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76,
0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x52, 0x0a, 0x14,
0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73,
0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73,
0x22, 0x53, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x04, 0x69, 0x6e, 0x66,
0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e,
0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52,
0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x42, 0x0a, 0x0c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
0x74, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x3b, 0x0a, 0x0d, 0x55, 0x73, 0x61,
0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69,
0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x16,
0x0a, 0x06, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
0x69, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x32, 0x0a, 0x0e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75,
0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73,
0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x65, 0x72, 0x2a, 0x38, 0x0a, 0x04, 0x4b, 0x69,
0x6e, 0x64, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12,
0x08, 0x0a, 0x04, 0x56, 0x49, 0x45, 0x57, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54,
0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x54,
0x45, 0x44, 0x10, 0x03, 0x32, 0xd3, 0x08, 0x0a, 0x09, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
0x74, 0x73, 0x12, 0x7e, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x12, 0x38, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e,
0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61,
0x72, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x75, 0x0a, 0x04, 0x56, 0x69, 0x65, 0x77, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69,
0x65, 0x77, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x65, 0x77, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x06, 0x4d, 0x6f, 0x75,
0x6e, 0x74, 0x73, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64,
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73,
0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68,
0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x12, 0x59, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x37, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x75, 0x0a, 0x04,
0x53, 0x74, 0x61, 0x74, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73,
0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x53, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53,
0x74, 0x61, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x37, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61,
0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x79, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61,
0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73,
0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65,
0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74,
0x12, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x68, 0x0a, 0x05, 0x55,
0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73,
0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73,
0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x07, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70,
0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x46, 0x5a, 0x44, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x6e, 0x61, 0x70,
0x73, 0x68, 0x6f, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f,
0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61,
0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73,
0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x30, 0x01, 0x12, 0x68, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63,
0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x73, 0x2e, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a,
0x07, 0x43, 0x6c, 0x65, 0x61, 0x6e, 0x75, 0x70, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61,
0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x73,
0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x65, 0x61,
0x6e, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x42, 0x46, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74,
0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x2f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x2f, 0x76, 0x31,
0x3b, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (

View File

@@ -92,6 +92,8 @@ message CommitSnapshotRequest {
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
map<string, string> labels = 4;
string parent = 5;
}
message StatSnapshotRequest {

View File

@@ -24,6 +24,7 @@ package types
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
@@ -118,6 +119,148 @@ func (x *Mount) GetOptions() []string {
return nil
}
type ActiveMount struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Mount *Mount `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
MountedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=mounted_at,json=mountedAt,proto3" json:"mounted_at,omitempty"`
MountPoint string `protobuf:"bytes,3,opt,name=mount_point,json=mountPoint,proto3" json:"mount_point,omitempty"`
Data map[string]string `protobuf:"bytes,4,rep,name=data,proto3" json:"data,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
func (x *ActiveMount) Reset() {
*x = ActiveMount{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_types_mount_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ActiveMount) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActiveMount) ProtoMessage() {}
func (x *ActiveMount) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_types_mount_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActiveMount.ProtoReflect.Descriptor instead.
func (*ActiveMount) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_types_mount_proto_rawDescGZIP(), []int{1}
}
func (x *ActiveMount) GetMount() *Mount {
if x != nil {
return x.Mount
}
return nil
}
func (x *ActiveMount) GetMountedAt() *timestamppb.Timestamp {
if x != nil {
return x.MountedAt
}
return nil
}
func (x *ActiveMount) GetMountPoint() string {
if x != nil {
return x.MountPoint
}
return ""
}
func (x *ActiveMount) GetData() map[string]string {
if x != nil {
return x.Data
}
return nil
}
type ActivationInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Active []*ActiveMount `protobuf:"bytes,2,rep,name=active,proto3" json:"active,omitempty"`
System []*Mount `protobuf:"bytes,3,rep,name=system,proto3" json:"system,omitempty"`
Labels map[string]string `protobuf:"bytes,4,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
}
func (x *ActivationInfo) Reset() {
*x = ActivationInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_containerd_api_types_mount_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ActivationInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActivationInfo) ProtoMessage() {}
func (x *ActivationInfo) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_containerd_api_types_mount_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActivationInfo.ProtoReflect.Descriptor instead.
func (*ActivationInfo) Descriptor() ([]byte, []int) {
return file_github_com_containerd_containerd_api_types_mount_proto_rawDescGZIP(), []int{2}
}
func (x *ActivationInfo) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *ActivationInfo) GetActive() []*ActiveMount {
if x != nil {
return x.Active
}
return nil
}
func (x *ActivationInfo) GetSystem() []*Mount {
if x != nil {
return x.System
}
return nil
}
func (x *ActivationInfo) GetLabels() map[string]string {
if x != nil {
return x.Labels
}
return nil
}
var File_github_com_containerd_containerd_api_types_mount_proto protoreflect.FileDescriptor
var file_github_com_containerd_containerd_api_types_mount_proto_rawDesc = []byte{
@@ -125,17 +268,53 @@ var file_github_com_containerd_containerd_api_types_mount_proto_rawDesc = []byte
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
0x72, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x6d, 0x6f, 0x75,
0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
0x6e, 0x65, 0x72, 0x64, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x22, 0x65, 0x0a, 0x05, 0x4d, 0x6f,
0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12,
0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61,
0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x3b,
0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6e, 0x65, 0x72, 0x64, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x65, 0x0a, 0x05, 0x4d,
0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72,
0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x22, 0x8e, 0x02, 0x0a, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x6f, 0x75,
0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x74,
0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x05, 0x6d, 0x6f, 0x75, 0x6e,
0x74, 0x12, 0x39, 0x0a, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
0x70, 0x52, 0x09, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1f, 0x0a, 0x0b,
0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3b, 0x0a,
0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41,
0x63, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x44, 0x61,
0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
0x02, 0x38, 0x01, 0x22, 0x8d, 0x02, 0x0a, 0x0e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x61, 0x63,
0x74, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x63,
0x74, 0x69, 0x76, 0x65, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x76,
0x65, 0x12, 0x2f, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e, 0x74,
0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74,
0x65, 0x6d, 0x12, 0x44, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2e,
0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65,
0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
0x02, 0x38, 0x01, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e,
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x79, 0x70, 0x65,
0x73, 0x3b, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -150,16 +329,27 @@ func file_github_com_containerd_containerd_api_types_mount_proto_rawDescGZIP() [
return file_github_com_containerd_containerd_api_types_mount_proto_rawDescData
}
var file_github_com_containerd_containerd_api_types_mount_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_github_com_containerd_containerd_api_types_mount_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_github_com_containerd_containerd_api_types_mount_proto_goTypes = []interface{}{
(*Mount)(nil), // 0: containerd.types.Mount
(*Mount)(nil), // 0: containerd.types.Mount
(*ActiveMount)(nil), // 1: containerd.types.ActiveMount
(*ActivationInfo)(nil), // 2: containerd.types.ActivationInfo
nil, // 3: containerd.types.ActiveMount.DataEntry
nil, // 4: containerd.types.ActivationInfo.LabelsEntry
(*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp
}
var file_github_com_containerd_containerd_api_types_mount_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
0, // 0: containerd.types.ActiveMount.mount:type_name -> containerd.types.Mount
5, // 1: containerd.types.ActiveMount.mounted_at:type_name -> google.protobuf.Timestamp
3, // 2: containerd.types.ActiveMount.data:type_name -> containerd.types.ActiveMount.DataEntry
1, // 3: containerd.types.ActivationInfo.active:type_name -> containerd.types.ActiveMount
0, // 4: containerd.types.ActivationInfo.system:type_name -> containerd.types.Mount
4, // 5: containerd.types.ActivationInfo.labels:type_name -> containerd.types.ActivationInfo.LabelsEntry
6, // [6:6] is the sub-list for method output_type
6, // [6:6] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_github_com_containerd_containerd_api_types_mount_proto_init() }
@@ -180,6 +370,30 @@ func file_github_com_containerd_containerd_api_types_mount_proto_init() {
return nil
}
}
file_github_com_containerd_containerd_api_types_mount_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ActiveMount); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_containerd_api_types_mount_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ActivationInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -187,7 +401,7 @@ func file_github_com_containerd_containerd_api_types_mount_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_github_com_containerd_containerd_api_types_mount_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumMessages: 5,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -18,6 +18,8 @@ syntax = "proto3";
package containerd.types;
import "google/protobuf/timestamp.proto";
option go_package = "github.com/containerd/containerd/api/types;types";
// Mount describes mounts for a container.
@@ -41,3 +43,23 @@ message Mount {
// Options specifies zero or more fstab style mount options.
repeated string options = 4;
}
message ActiveMount {
Mount mount = 1;
google.protobuf.Timestamp mounted_at = 2;
string mount_point = 3;
map<string, string> data = 4;
}
message ActivationInfo {
string name = 1;
repeated ActiveMount active = 2;
repeated Mount system = 3;
map<string, string> labels = 4;
}

View File

@@ -40,6 +40,18 @@ import (
transferapi "github.com/containerd/containerd/api/services/transfer/v1"
versionservice "github.com/containerd/containerd/api/services/version/v1"
apitypes "github.com/containerd/containerd/api/types"
"github.com/containerd/errdefs"
"github.com/containerd/platforms"
"github.com/containerd/typeurl/v2"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-spec/specs-go/features"
"golang.org/x/sync/semaphore"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/health/grpc_health_v1"
"github.com/containerd/containerd/v2/core/containers"
"github.com/containerd/containerd/v2/core/content"
contentproxy "github.com/containerd/containerd/v2/core/content/proxy"
@@ -50,6 +62,8 @@ import (
introspectionproxy "github.com/containerd/containerd/v2/core/introspection/proxy"
"github.com/containerd/containerd/v2/core/leases"
leasesproxy "github.com/containerd/containerd/v2/core/leases/proxy"
"github.com/containerd/containerd/v2/core/mount"
mountproxy "github.com/containerd/containerd/v2/core/mount/proxy"
"github.com/containerd/containerd/v2/core/remotes"
"github.com/containerd/containerd/v2/core/remotes/docker"
"github.com/containerd/containerd/v2/core/sandbox"
@@ -64,17 +78,6 @@ import (
ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types"
"github.com/containerd/containerd/v2/pkg/tracing"
"github.com/containerd/containerd/v2/plugins"
"github.com/containerd/errdefs"
"github.com/containerd/platforms"
"github.com/containerd/typeurl/v2"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-spec/specs-go/features"
"golang.org/x/sync/semaphore"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/health/grpc_health_v1"
)
func init() {
@@ -114,7 +117,11 @@ func New(address string, opts ...Opt) (*Client, error) {
}
if copts.defaultRuntime != "" {
c.runtime.value = copts.defaultRuntime
c.defaults.runtime = copts.defaultRuntime
}
if copts.defaultSandboxer != "" {
c.defaults.sandboxer = copts.defaultSandboxer
}
if copts.defaultPlatform != nil {
@@ -190,7 +197,11 @@ func NewWithConn(conn *grpc.ClientConn, opts ...Opt) (*Client, error) {
}
if copts.defaultRuntime != "" {
c.runtime.value = copts.defaultRuntime
c.defaults.runtime = copts.defaultRuntime
}
if copts.defaultSandboxer != "" {
c.defaults.sandboxer = copts.defaultSandboxer
}
if copts.defaultPlatform != nil {
@@ -215,10 +226,11 @@ type Client struct {
platform platforms.MatchComparer
connector func() (*grpc.ClientConn, error)
// this should only be accessed via defaultRuntime()
runtime struct {
value string
mut sync.Mutex
// this should only be accessed via default*() functions
defaults struct {
runtime string
sandboxer string
mut sync.Mutex
}
}
@@ -245,11 +257,11 @@ func (c *Client) Runtime() string {
}
func (c *Client) defaultRuntime(ctx context.Context) (string, error) {
c.runtime.mut.Lock()
defer c.runtime.mut.Unlock()
c.defaults.mut.Lock()
defer c.defaults.mut.Unlock()
if c.runtime.value != "" {
return c.runtime.value, nil
if c.defaults.runtime != "" {
return c.defaults.runtime, nil
}
if c.defaultns != "" {
@@ -259,12 +271,35 @@ func (c *Client) defaultRuntime(ctx context.Context) (string, error) {
return defaults.DefaultRuntime, fmt.Errorf("failed to get default runtime label: %w", err)
}
if label != "" {
c.runtime.value = label
c.defaults.runtime = label
return label, nil
}
}
c.runtime.value = defaults.DefaultRuntime
return c.runtime.value, nil
c.defaults.runtime = defaults.DefaultRuntime
return c.defaults.runtime, nil
}
func (c *Client) defaultSandboxer(ctx context.Context) (string, error) {
c.defaults.mut.Lock()
defer c.defaults.mut.Unlock()
if c.defaults.sandboxer != "" {
return c.defaults.sandboxer, nil
}
if c.defaultns != "" {
label, err := c.GetLabel(ctx, defaults.DefaultSandboxerNSLabel)
if err != nil {
// Don't set the sandboxer value if there's an error
return defaults.DefaultSandboxer, fmt.Errorf("failed to get default sandboxer label: %w", err)
}
if label != "" {
c.defaults.sandboxer = label
return label, nil
}
}
c.defaults.sandboxer = defaults.DefaultSandboxer
return c.defaults.sandboxer, nil
}
// IsServing returns true if the client can successfully connect to the
@@ -431,6 +466,10 @@ type RemoteContext struct {
// ChildLabelMap sets the labels used to reference child objects in the content
// store. By default, all GC reference labels will be set for all fetched content.
ChildLabelMap func(ocispec.Descriptor) []string
// ReferrersProvider provides a way to lookup additional referrers for a given
// descriptor. For example pulling them with remotes.ReferrerFetcher.
ReferrersProvider content.ReferrersProvider
}
func defaultRemoteContext() *RemoteContext {
@@ -793,6 +832,16 @@ func (c *Client) TransferService() transfer.Transferrer {
return transferproxy.NewTransferrer(transferapi.NewTransferClient(c.conn), c.streamCreator())
}
// MountManager returns the underlying mount manager client
func (c *Client) MountManager() mount.Manager {
if c.mountManager != nil {
return c.mountManager
}
c.connMu.Lock()
defer c.connMu.Unlock()
return mountproxy.NewMountManager(c.conn)
}
// VersionService returns the underlying VersionClient
func (c *Client) VersionService() versionservice.VersionClient {
c.connMu.Lock()

View File

@@ -19,25 +19,26 @@ package client
import (
"time"
"github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/core/images"
"github.com/containerd/containerd/v2/core/remotes"
"github.com/containerd/containerd/v2/core/snapshots"
"github.com/containerd/platforms"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/sync/semaphore"
"google.golang.org/grpc"
)
type clientOpts struct {
defaultns string
defaultRuntime string
defaultPlatform platforms.MatchComparer
services *services
dialOptions []grpc.DialOption
extraDialOpts []grpc.DialOption
callOptions []grpc.CallOption
timeout time.Duration
defaultns string
defaultRuntime string
defaultSandboxer string
defaultPlatform platforms.MatchComparer
services *services
dialOptions []grpc.DialOption
extraDialOpts []grpc.DialOption
callOptions []grpc.CallOption
timeout time.Duration
}
// Opt allows callers to set options on the containerd client
@@ -62,6 +63,14 @@ func WithDefaultRuntime(rt string) Opt {
}
}
// WithDefaultSandboxer sets the default sandboxer on the client
func WithDefaultSandboxer(sb string) Opt {
return func(c *clientOpts) error {
c.defaultSandboxer = sb
return nil
}
}
// WithDefaultPlatform sets the default platform matcher on the client
func WithDefaultPlatform(platform platforms.MatchComparer) Opt {
return func(c *clientOpts) error {
@@ -275,3 +284,11 @@ func WithAllMetadata() RemoteOpt {
return nil
}
}
// WithReferrersProvider sets a referrers provider to resolve referrer objects.
func WithReferrersProvider(r content.ReferrersProvider) RemoteOpt {
return func(_ *Client, c *RemoteContext) error {
c.ReferrersProvider = r
return nil
}
}

View File

@@ -36,6 +36,7 @@ import (
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/sync/semaphore"
)
// Image describes an image used by containers
@@ -258,6 +259,8 @@ type UnpackConfig struct {
// in-flight fetch request or unpack handler for a given descriptor's
// digest or chain ID.
DuplicationSuppressor kmutex.KeyedLocker
// Limiter is used to limit concurrent unpacks
Limiter *semaphore.Weighted
}
// UnpackOpt provides configuration for unpack
@@ -287,6 +290,14 @@ func WithUnpackApplyOpts(opts ...diff.ApplyOpt) UnpackOpt {
}
}
// WithUnpackLimiter sets a semaphore to limit concurrent unpacks.
func WithUnpackLimiter(limiter *semaphore.Weighted) UnpackOpt {
return func(ctx context.Context, uc *UnpackConfig) error {
uc.Limiter = limiter
return nil
}
}
func (i *image) Unpack(ctx context.Context, snapshotterName string, opts ...UnpackOpt) error {
ctx, done, err := i.client.WithLease(ctx)
if err != nil {

View File

@@ -20,6 +20,7 @@ import (
"context"
"io"
"github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/core/images"
"github.com/containerd/containerd/v2/core/images/archive"
"github.com/containerd/errdefs"
@@ -39,6 +40,7 @@ type importOpts struct {
discardLayers bool
skipMissing bool
imageLabels map[string]string
referrers content.ReferrersProvider
}
// ImportOpt allows the caller to specify import specific options
@@ -132,6 +134,15 @@ func WithSkipMissing() ImportOpt {
}
}
// WithImportReferrers allows to set a custom referrers provider
// for setting referrer objects during import.
func WithImportReferrers(r content.ReferrersProvider) ImportOpt {
return func(c *importOpts) error {
c.referrers = r
return nil
}
}
// Import imports an image from a Tar stream using reader.
// Caller needs to specify importer. Future version may use oci.v1 as the default.
// Note that unreferenced blobs may be imported to the content store as well.
@@ -202,6 +213,10 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
Target: m,
})
}
// don't create images for referrer descriptors
if _, ok := m.Annotations[images.AnnotationManifestSubject]; ok {
continue
}
if iopts.skipDgstRef != nil {
if iopts.skipDgstRef(name) {
continue
@@ -222,6 +237,9 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
}
handler = images.FilterPlatforms(handler, platformMatcher)
if iopts.referrers != nil {
handler = images.SetReferrers(iopts.referrers, handler)
}
if iopts.discardLayers {
handler = images.SetChildrenMappedLabels(cs, handler, images.ChildGCLabelsFilterLayers)
} else {

View File

@@ -97,6 +97,12 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
return nil, fmt.Errorf("unable to resolve snapshotter: %w", err)
}
span.SetAttributes(tracing.Attribute("snapshotter.name", snapshotterName))
snCapabilities, err := c.GetSnapshotterCapabilities(ctx, snapshotterName)
if err != nil {
return nil, fmt.Errorf("unable to get snapshotter capabilities: %w", err)
}
var uconfig UnpackConfig
for _, opt := range pullCtx.UnpackOpts {
if err := opt(ctx, &uconfig); err != nil {
@@ -110,17 +116,21 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
// Check client Unpack config
platform := unpack.Platform{
Platform: platformMatcher,
SnapshotterKey: snapshotterName,
Snapshotter: c.SnapshotService(snapshotterName),
SnapshotOpts: append(pullCtx.SnapshotterOpts, uconfig.SnapshotOpts...),
Applier: c.DiffService(),
ApplyOpts: uconfig.ApplyOpts,
Platform: platformMatcher,
SnapshotterKey: snapshotterName,
Snapshotter: c.SnapshotService(snapshotterName),
SnapshotOpts: append(pullCtx.SnapshotterOpts, uconfig.SnapshotOpts...),
Applier: c.DiffService(),
ApplyOpts: uconfig.ApplyOpts,
SnapshotterCapabilities: snCapabilities,
}
uopts := []unpack.UnpackerOpt{unpack.WithUnpackPlatform(platform)}
if uconfig.DuplicationSuppressor != nil {
uopts = append(uopts, unpack.WithDuplicationSuppressor(uconfig.DuplicationSuppressor))
}
if uconfig.Limiter != nil {
uopts = append(uopts, unpack.WithUnpackLimiter(uconfig.Limiter))
}
unpacker, err = unpack.NewUnpacker(ctx, c.ContentStore(), uopts...)
if err != nil {
return nil, fmt.Errorf("unable to initialize unpacker: %w", err)
@@ -207,6 +217,9 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
}
// Get all the children for a descriptor
childrenHandler := images.ChildrenHandler(store)
if rCtx.ReferrersProvider != nil {
childrenHandler = images.SetReferrers(rCtx.ReferrersProvider, childrenHandler)
}
// Set any children labels for that content
childrenHandler = images.SetChildrenMappedLabels(store, childrenHandler, rCtx.ChildLabelMap)
if rCtx.AllMetadata {

View File

@@ -114,7 +114,7 @@ func (s *sandboxClient) Stop(ctx context.Context) error {
}
func (s *sandboxClient) Shutdown(ctx context.Context) error {
if err := s.client.SandboxController(s.metadata.Sandboxer).Shutdown(ctx, s.ID()); err != nil && errdefs.IsNotFound(err) {
if err := s.client.SandboxController(s.metadata.Sandboxer).Shutdown(ctx, s.ID()); err != nil && !errdefs.IsNotFound(err) {
return fmt.Errorf("failed to shutdown sandbox: %w", err)
}
@@ -131,10 +131,15 @@ func (c *Client) NewSandbox(ctx context.Context, sandboxID string, opts ...NewSa
return nil, errors.New("sandbox ID must be specified")
}
sandboxer, err := c.defaultSandboxer(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get default sandboxer: %w", err)
}
newSandbox := api.Sandbox{
ID: sandboxID,
CreatedAt: time.Now().UTC(),
UpdatedAt: time.Now().UTC(),
Sandboxer: sandboxer,
}
for _, opt := range opts {
@@ -148,6 +153,10 @@ func (c *Client) NewSandbox(ctx context.Context, sandboxID string, opts ...NewSa
return nil, err
}
if err := c.SandboxController(sandboxer).Create(ctx, newSandbox); err != nil {
return nil, fmt.Errorf("failed to create sandbox with %s sandboxer: %w", sandboxer, err)
}
return &sandboxClient{
client: c,
metadata: metadata,

View File

@@ -24,18 +24,20 @@ import (
imagesapi "github.com/containerd/containerd/api/services/images/v1"
namespacesapi "github.com/containerd/containerd/api/services/namespaces/v1"
"github.com/containerd/containerd/api/services/tasks/v1"
"github.com/containerd/plugin"
"github.com/containerd/containerd/v2/core/containers"
"github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/core/images"
"github.com/containerd/containerd/v2/core/introspection"
"github.com/containerd/containerd/v2/core/leases"
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/containerd/v2/core/sandbox"
"github.com/containerd/containerd/v2/core/snapshots"
"github.com/containerd/containerd/v2/core/transfer"
"github.com/containerd/containerd/v2/pkg/namespaces"
"github.com/containerd/containerd/v2/plugins"
srv "github.com/containerd/containerd/v2/plugins/services"
"github.com/containerd/plugin"
)
type services struct {
@@ -52,6 +54,7 @@ type services struct {
sandboxStore sandbox.Store
sandboxers map[string]sandbox.Controller
transferService transfer.Transferrer
mountManager mount.Manager
}
// ServicesOpt allows callers to set options on the services
@@ -172,6 +175,13 @@ func WithTransferService(tr transfer.Transferrer) ServicesOpt {
}
}
// WithMountManager sets the mount manager.
func WithMountManager(mm mount.Manager) ServicesOpt {
return func(s *services) {
s.mountManager = mm
}
}
// WithInMemoryServices is suitable for cases when there is need to use containerd's client from
// another (in-memory) containerd plugin (such as CRI).
func WithInMemoryServices(ic *plugin.InitContext) Opt {
@@ -190,6 +200,9 @@ func WithInMemoryServices(ic *plugin.InitContext) Opt {
plugins.TransferPlugin: func(i interface{}) ServicesOpt {
return WithTransferService(i.(transfer.Transferrer))
},
plugins.MountManagerPlugin: func(i interface{}) ServicesOpt {
return WithMountManager(i.(mount.Manager))
},
} {
i, err := ic.GetSingle(t)
if err != nil {

View File

@@ -213,6 +213,7 @@ type GRPCConfig struct {
GID int `toml:"gid"`
MaxRecvMsgSize int `toml:"max_recv_message_size"`
MaxSendMsgSize int `toml:"max_send_message_size"`
TCPTLSCName string `toml:"tcp_tls_common_name"`
}
// TTRPCConfig provides TTRPC configuration for the socket

View File

@@ -170,6 +170,11 @@ type Syncer interface {
Sync() error
}
// ReferrersProvider handles looking up additional referrer objects for a given descriptor.
type ReferrersProvider interface {
Referrers(context.Context, ocispec.Descriptor) ([]ocispec.Descriptor, error)
}
// Opt is used to alter the mutable properties of content
type Opt func(*Info) error

View File

@@ -69,6 +69,8 @@ type ApplyConfig struct {
ProcessorPayloads map[string]typeurl.Any
// SyncFs is to synchronize the underlying filesystem containing files
SyncFs bool
// Progress is a function which reports status of processed read data
Progress func(int64)
}
// ApplyOpt is used to configure an Apply operation
@@ -135,6 +137,18 @@ func WithSyncFs(sync bool) ApplyOpt {
}
}
// WithProgress is used to indicate process of the apply operation, should
// atleast expect a progress of 0 and of the final size. It is up to the applier
// how much progress it reports in between.
func WithProgress(f func(ocispec.Descriptor, int64)) ApplyOpt {
return func(_ context.Context, desc ocispec.Descriptor, c *ApplyConfig) error {
c.Progress = func(state int64) {
f(desc, state)
}
return nil
}
}
// WithSourceDateEpoch specifies the timestamp used to provide control for reproducibility.
// See also https://reproducible-builds.org/docs/source-date-epoch/ .
//

View File

@@ -56,7 +56,9 @@ func (r *diffRemote) Apply(ctx context.Context, desc ocispec.Descriptor, mounts
for k, v := range config.ProcessorPayloads {
payloads[k] = typeurl.MarshalProto(v)
}
if config.Progress != nil {
config.Progress(0)
}
req := &diffapi.ApplyRequest{
Diff: oci.DescriptorToProto(desc),
Mounts: mount.ToProto(mounts),
@@ -67,6 +69,9 @@ func (r *diffRemote) Apply(ctx context.Context, desc ocispec.Descriptor, mounts
if err != nil {
return ocispec.Descriptor{}, errgrpc.ToNative(err)
}
if config.Progress != nil {
config.Progress(desc.Size)
}
return oci.DescriptorFromProto(resp.Applied), nil
}

View File

@@ -20,4 +20,10 @@ const (
// AnnotationImageName is an annotation on a Descriptor in an index.json
// containing the `Name` value as used by an `Image` struct
AnnotationImageName = "io.containerd.image.name"
// AnnotationManifestSubject is an annotation on a Descriptor that means
// that current descriptor is a referrer to the subject manifest.
// If descriptor in image.json has this annotation, it will not create
// a new image.
AnnotationManifestSubject = "io.containerd.manifest.subject"
)

View File

@@ -23,6 +23,7 @@ import (
"fmt"
"io"
"path"
"slices"
"sort"
"strings"
@@ -43,6 +44,7 @@ type exportOptions struct {
allPlatforms bool
skipDockerManifest bool
blobRecordOptions blobRecordOptions
referrers content.ReferrersProvider
}
// ExportOpt defines options for configuring exported descriptors
@@ -143,6 +145,15 @@ func WithSkipNonDistributableBlobs() ExportOpt {
return WithBlobFilter(f)
}
// WithReferrersProvider sets a referrers provider to resolve referrer objects
// that are included in the exported archive.
func WithReferrersProvider(p content.ReferrersProvider) ExportOpt {
return func(ctx context.Context, o *exportOptions) error {
o.referrers = p
return nil
}
}
// WithSkipMissing excludes blobs referenced by manifests if not all blobs
// would be included in the archive.
// The manifest itself is excluded only if it's not present locally.
@@ -242,7 +253,7 @@ func Export(ctx context.Context, store content.InfoReaderProvider, writer io.Wri
mt, ok := dManifests[desc.Digest]
if !ok {
// TODO(containerd): Skip if already added
r, err := getRecords(ctx, store, desc, algorithms, &eo.blobRecordOptions)
r, err := getRecords(ctx, store, desc, algorithms, &eo.blobRecordOptions, eo.referrers)
if err != nil {
return err
}
@@ -286,7 +297,7 @@ func Export(ctx context.Context, store content.InfoReaderProvider, writer io.Wri
}
}
r, err := getRecords(ctx, store, m, algorithms, &eo.blobRecordOptions)
r, err := getRecords(ctx, store, m, algorithms, &eo.blobRecordOptions, eo.referrers)
if err != nil {
return err
}
@@ -327,7 +338,7 @@ func Export(ctx context.Context, store content.InfoReaderProvider, writer io.Wri
}
}
records = append(records, ociIndexRecord(manifests))
records = append(records, ociIndexRecord(slices.Concat(manifests, filterReferrers(records))))
if !eo.skipDockerManifest && len(dManifests) > 0 {
tr, err := manifestsRecord(ctx, store, dManifests)
@@ -350,7 +361,7 @@ func Export(ctx context.Context, store content.InfoReaderProvider, writer io.Wri
return writeTar(ctx, tw, records)
}
func getRecords(ctx context.Context, store content.Provider, desc ocispec.Descriptor, algorithms map[string]struct{}, brOpts *blobRecordOptions) ([]tarRecord, error) {
func getRecords(ctx context.Context, store content.Provider, desc ocispec.Descriptor, algorithms map[string]struct{}, brOpts *blobRecordOptions, referrers content.ReferrersProvider) ([]tarRecord, error) {
var records []tarRecord
exportHandler := func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
if err := desc.Digest.Validate(); err != nil {
@@ -366,6 +377,36 @@ func getRecords(ctx context.Context, store content.Provider, desc ocispec.Descri
childrenHandler = images.ChildrenHandler(store)
}
if referrers != nil {
ch := childrenHandler
childrenHandler = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
children, err := ch(ctx, desc)
if err != nil {
return nil, err
}
if !images.IsManifestType(desc.MediaType) && !images.IsIndexType(desc.MediaType) {
return children, nil
}
refs, err := referrers.Referrers(ctx, desc)
if err != nil {
if errdefs.IsNotFound(err) {
return children, nil
}
return nil, err
}
for _, r := range refs {
if r.Annotations == nil {
r.Annotations = map[string]string{}
}
r.Annotations[images.AnnotationManifestSubject] = desc.Digest.String()
children = append(children, r)
}
return children, nil
}
}
handlers := images.Handlers(
childrenHandler,
images.HandlerFunc(exportHandler),
@@ -380,9 +421,38 @@ func getRecords(ctx context.Context, store content.Provider, desc ocispec.Descri
return records, nil
}
// filterReferrers filters records with referrer annotations that are not
// exported in another way already
func filterReferrers(records []tarRecord) []ocispec.Descriptor {
inTree := map[digest.Digest]struct{}{}
referrersMap := map[digest.Digest]ocispec.Descriptor{}
for _, r := range records {
if r.Descriptor != nil {
if _, ok := r.Descriptor.Annotations[images.AnnotationManifestSubject]; ok {
referrersMap[r.Descriptor.Digest] = *r.Descriptor
} else {
inTree[r.Descriptor.Digest] = struct{}{}
}
}
}
var referrers []ocispec.Descriptor
for dgst, desc := range referrersMap {
if _, ok := inTree[dgst]; ok {
continue
}
referrers = append(referrers, desc)
}
slices.SortFunc(referrers, func(a, b ocispec.Descriptor) int {
return strings.Compare(a.Digest.String(), b.Digest.String())
})
return referrers
}
type tarRecord struct {
Header *tar.Header
CopyTo func(context.Context, io.Writer) (int64, error)
Header *tar.Header
CopyTo func(context.Context, io.Writer) (int64, error)
Descriptor *ocispec.Descriptor
}
type blobRecordOptions struct {
@@ -395,6 +465,7 @@ func blobRecord(cs content.Provider, desc ocispec.Descriptor, opts *blobRecordOp
return tarRecord{}
}
return tarRecord{
Descriptor: &desc,
Header: &tar.Header{
Name: path.Join(ocispec.ImageBlobsDir, desc.Digest.Algorithm().String(), desc.Digest.Encoded()),
Mode: 0444,

View File

@@ -104,15 +104,16 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader, opt
}
hdrName := path.Clean(hdr.Name)
if hdrName == ocispec.ImageLayoutFile {
switch hdrName {
case ocispec.ImageLayoutFile:
if err = onUntarJSON(tr, &ociLayout); err != nil {
return ocispec.Descriptor{}, fmt.Errorf("untar oci layout %q: %w", hdr.Name, err)
}
} else if hdrName == "manifest.json" {
case "manifest.json":
if err = onUntarJSON(tr, &mfsts); err != nil {
return ocispec.Descriptor{}, fmt.Errorf("untar manifest %q: %w", hdr.Name, err)
}
} else {
default:
dgst, err := onUntarBlob(ctx, tr, store, hdr.Size, "tar-"+hdrName)
if err != nil {
return ocispec.Descriptor{}, fmt.Errorf("failed to ingest %q: %w", hdr.Name, err)

View File

@@ -20,7 +20,9 @@ import (
"context"
"errors"
"fmt"
"slices"
"sort"
"strings"
"github.com/containerd/containerd/v2/core/content"
"github.com/containerd/errdefs"
@@ -198,6 +200,35 @@ func ChildrenHandler(provider content.Provider) HandlerFunc {
}
}
// SetReferrers is a handler wrapper which adds referrer descriptors
// from the provided ReferrersProvider and adds them to the children
// returned by the handler. The referrers will have a container-specific
// annotation added to indicate the subject descriptor.
func SetReferrers(refProvider content.ReferrersProvider, f HandlerFunc) HandlerFunc {
return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
children, err := f(ctx, desc)
if err != nil {
return children, err
}
if !IsManifestType(desc.MediaType) && !IsIndexType(desc.MediaType) {
return children, nil
}
refs, err := refProvider.Referrers(ctx, desc)
if err != nil {
return children, err
}
children = slices.Grow(children, len(refs))
for _, ref := range refs {
if ref.Annotations == nil {
ref.Annotations = map[string]string{}
}
ref.Annotations[AnnotationManifestSubject] = desc.Digest.String()
children = append(children, ref)
}
return children, nil
}
}
// SetChildrenLabels is a handler wrapper which sets labels for the content on
// the children returned by the handler and passes through the children.
// Must follow a handler that returns the children to be labeled.
@@ -235,7 +266,9 @@ func SetChildrenMappedLabels(manager content.Manager, f HandlerFunc, labelMap fu
for _, key := range labelKeys {
idx := keys[key]
keys[key] = idx + 1
if idx > 0 || key[len(key)-1] == '.' {
if strings.HasSuffix(key, ".sha256.") {
key = fmt.Sprintf("%s%s", key, ch.Digest.Hex()[:12])
} else if idx > 0 || key[len(key)-1] == '.' {
key = fmt.Sprintf("%s%d", key, idx)
}

View File

@@ -208,6 +208,9 @@ func IsAttestationType(mt string) bool {
// ChildGCLabels returns the label for a given descriptor to reference it
func ChildGCLabels(desc ocispec.Descriptor) []string {
if _, ok := desc.Annotations[AnnotationManifestSubject]; ok {
return []string{"containerd.io/gc.ref.content.referrer.sha256."}
}
mt := desc.MediaType
if IsKnownConfig(mt) {
return []string{"containerd.io/gc.ref.content.config"}

View File

@@ -22,18 +22,10 @@ import (
bolt "go.etcd.io/bbolt"
errbolt "go.etcd.io/bbolt/errors"
"github.com/containerd/containerd/v2/core/metadata/boltutil"
)
type transactionKey struct{}
// WithTransactionContext returns a new context holding the provided
// bolt transaction. Functions which require a bolt transaction will
// first check to see if a transaction is already created on the
// context before creating their own.
func WithTransactionContext(ctx context.Context, tx *bolt.Tx) context.Context {
return context.WithValue(ctx, transactionKey{}, tx)
}
// Transactor is the database interface for running transactions
type Transactor interface {
View(fn func(*bolt.Tx) error) error
@@ -43,7 +35,7 @@ type Transactor interface {
// view gets a bolt db transaction either from the context
// or starts a new one with the provided bolt database.
func view(ctx context.Context, db Transactor, fn func(*bolt.Tx) error) error {
tx, ok := ctx.Value(transactionKey{}).(*bolt.Tx)
tx, ok := boltutil.Transaction(ctx)
if !ok {
return db.View(fn)
}
@@ -53,7 +45,7 @@ func view(ctx context.Context, db Transactor, fn func(*bolt.Tx) error) error {
// update gets a writable bolt db transaction either from the context
// or starts a new one with the provided bolt database.
func update(ctx context.Context, db Transactor, fn func(*bolt.Tx) error) error {
tx, ok := ctx.Value(transactionKey{}).(*bolt.Tx)
tx, ok := boltutil.Transaction(ctx)
if !ok {
return db.Update(fn)
} else if !tx.Writable() {

View File

@@ -0,0 +1,40 @@
/*
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 boltutil
import (
"context"
bolt "go.etcd.io/bbolt"
)
type transactionKey struct{}
// WithTransaction returns a new context holding the provided
// bolt transaction. Functions which require a bolt transaction will
// first check to see if a transaction is already created on the
// context before creating their own.
func WithTransaction(ctx context.Context, tx *bolt.Tx) context.Context {
return context.WithValue(ctx, transactionKey{}, tx)
}
// Transaction returns the transaction from the context
// if it has one.
func Transaction(ctx context.Context) (tx *bolt.Tx, ok bool) {
tx, ok = ctx.Value(transactionKey{}).(*bolt.Tx)
return
}

View File

@@ -32,8 +32,8 @@ import (
"github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/core/events"
"github.com/containerd/containerd/v2/core/metadata/boltutil"
"github.com/containerd/containerd/v2/core/snapshots"
"github.com/containerd/containerd/v2/internal/cleanup"
"github.com/containerd/containerd/v2/pkg/gc"
"github.com/containerd/containerd/v2/pkg/namespaces"
)
@@ -274,7 +274,7 @@ func (m *DB) Update(fn func(*bolt.Tx) error) error {
// Publisher returns an event publisher if one is configured
// and the current context is not inside a transaction.
func (m *DB) Publisher(ctx context.Context) events.Publisher {
_, ok := ctx.Value(transactionKey{}).(*bolt.Tx)
_, ok := boltutil.Transaction(ctx)
if ok {
// Do no publish events within a transaction
return nil
@@ -390,12 +390,13 @@ func (m *DB) GarbageCollect(ctx context.Context) (gc.Stats, error) {
return nil
}
if n.Type == ResourceSnapshot {
switch n.Type {
case ResourceSnapshot:
if idx := strings.IndexRune(n.Key, '/'); idx > 0 {
m.dirtySS[n.Key[:idx]] = struct{}{}
}
// queue event to publish after successful commit
} else if n.Type == ResourceContent || n.Type == ResourceIngest {
case ResourceContent, ResourceIngest:
m.dirtyCS = true
}
@@ -467,11 +468,11 @@ func (m *DB) GarbageCollect(ctx context.Context) (gc.Stats, error) {
m.dirtyCS = false
}
c.finish(ctx, &wg)
stats.MetaD = time.Since(t1)
m.wlock.Unlock()
c.finish(ctx)
wg.Wait()
return stats, err
@@ -527,7 +528,7 @@ func (m *DB) getMarked(ctx context.Context, c *gcContext) (map[gc.Node]struct{},
}
func (m *DB) cleanupSnapshotter(ctx context.Context, name string) (time.Duration, error) {
ctx = cleanup.Background(ctx)
ctx = context.WithoutCancel(ctx)
sn, ok := m.ss[name]
if !ok {
return 0, nil
@@ -544,7 +545,7 @@ func (m *DB) cleanupSnapshotter(ctx context.Context, name string) (time.Duration
}
func (m *DB) cleanupContent(ctx context.Context) (time.Duration, error) {
ctx = cleanup.Background(ctx)
ctx = context.WithoutCancel(ctx)
if m.cs == nil {
return 0, nil
}

View File

@@ -22,12 +22,14 @@ import (
"fmt"
"sort"
"strings"
"sync"
"time"
eventstypes "github.com/containerd/containerd/api/events"
"github.com/containerd/containerd/v2/pkg/gc"
"github.com/containerd/log"
bolt "go.etcd.io/bbolt"
"github.com/containerd/containerd/v2/pkg/gc"
)
const (
@@ -51,6 +53,8 @@ const (
resourceEnd
// ResourceStream specifies a stream
ResourceStream
// ResourceMount specifies a mount
ResourceMount
)
const (
@@ -60,12 +64,27 @@ const (
)
var (
labelGCRoot = []byte("containerd.io/gc.root")
labelGCRoot = []byte("containerd.io/gc.root")
// Reference labels are used to directly establish a connection
// from a parent object to a child object. The child object will
// remain referred to for the lifecycle of the parent object.
labelGCRef = []byte("containerd.io/gc.ref.")
labelGCSnapRef = []byte("containerd.io/gc.ref.snapshot.")
labelGCContentRef = []byte("containerd.io/gc.ref.content")
labelGCImageRef = []byte("containerd.io/gc.ref.image")
// Back reference labels are used to establish a reference relationship
// directly from a child object to a parent object. It allows a child
// object to attach itself to the lifecycle of a parent without updating
// the parent object or requiring the parent already exists.
labelGCContainerBackRef = []byte("containerd.io/gc.bref.container")
labelGCContentBackRef = []byte("containerd.io/gc.bref.content")
labelGCImageBackRef = []byte("containerd.io/gc.bref.image")
labelGCSnapBackRef = []byte("containerd.io/gc.bref.snapshot.")
// labelGCExpire indicates that an object is collectible after the
// provided time. For image objects, this makes them available to
// garbage collect when expired, when not provided, image objects
@@ -110,6 +129,10 @@ type CollectionContext interface {
Finish() error
}
type collectionWithBackRefs interface {
ActiveWithBackRefs(namespace string, fn func(gc.Node), bref func(gc.Node, gc.Node))
}
// Collector is an interface to manage resource collection for any collectible
// resource registered for garbage collection.
type Collector interface {
@@ -121,16 +144,70 @@ type Collector interface {
type gcContext struct {
labelHandlers []referenceLabelHandler
contexts map[gc.ResourceType]CollectionContext
backRefs map[gc.Node][]gc.Node
}
type referenceLabelHandler struct {
key []byte
fn func(string, []byte, []byte, func(gc.Node))
// functions to handle reference labels, only one may be set, if none are set
// the label is triggers the root callback
fn func(string, []byte, []byte, func(gc.Node))
bref func(string, []byte, []byte, func(gc.Node))
}
func startGCContext(ctx context.Context, collectors map[gc.ResourceType]Collector) *gcContext {
var contexts map[gc.ResourceType]CollectionContext
labelHandlers := []referenceLabelHandler{
{
key: labelGCContainerBackRef,
bref: func(ns string, k, v []byte, fn func(gc.Node)) {
if ks := string(k); ks != string(labelGCContainerBackRef) {
// Allow reference naming separated by . or /, ignore names
if ks[len(labelGCContainerBackRef)] != '.' && ks[len(labelGCContainerBackRef)] != '/' {
return
}
}
fn(gcnode(ResourceContainer, ns, string(v)))
},
},
{
key: labelGCContentBackRef,
bref: func(ns string, k, v []byte, fn func(gc.Node)) {
if ks := string(k); ks != string(labelGCContentBackRef) {
// Allow reference naming separated by . or /, ignore names
if ks[len(labelGCContentBackRef)] != '.' && ks[len(labelGCContentBackRef)] != '/' {
return
}
}
fn(gcnode(ResourceContent, ns, string(v)))
},
},
{
key: labelGCImageBackRef,
bref: func(ns string, k, v []byte, fn func(gc.Node)) {
if ks := string(k); ks != string(labelGCImageBackRef) {
// Allow reference naming separated by . or /, ignore names
if ks[len(labelGCImageBackRef)] != '.' && ks[len(labelGCImageBackRef)] != '/' {
return
}
}
fn(gcnode(ResourceImage, ns, string(v)))
},
},
{
key: labelGCSnapBackRef,
bref: func(ns string, k, v []byte, fn func(gc.Node)) {
snapshotter := k[len(labelGCSnapBackRef):]
if i := bytes.IndexByte(snapshotter, '/'); i >= 0 {
snapshotter = snapshotter[:i]
}
fn(gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", snapshotter, v)))
},
},
{
key: labelGCContentRef,
fn: func(ns string, k, v []byte, fn func(gc.Node)) {
@@ -144,16 +221,6 @@ func startGCContext(ctx context.Context, collectors map[gc.ResourceType]Collecto
fn(gcnode(ResourceContent, ns, string(v)))
},
},
{
key: labelGCSnapRef,
fn: func(ns string, k, v []byte, fn func(gc.Node)) {
snapshotter := k[len(labelGCSnapRef):]
if i := bytes.IndexByte(snapshotter, '/'); i >= 0 {
snapshotter = snapshotter[:i]
}
fn(gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", snapshotter, v)))
},
},
{
key: labelGCImageRef,
fn: func(ns string, k, v []byte, fn func(gc.Node)) {
@@ -167,6 +234,19 @@ func startGCContext(ctx context.Context, collectors map[gc.ResourceType]Collecto
fn(gcnode(ResourceImage, ns, string(v)))
},
},
{
key: labelGCSnapRef,
fn: func(ns string, k, v []byte, fn func(gc.Node)) {
snapshotter := k[len(labelGCSnapRef):]
if i := bytes.IndexByte(snapshotter, '/'); i >= 0 {
snapshotter = snapshotter[:i]
}
fn(gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", snapshotter, v)))
},
},
{
key: labelGCRoot,
},
}
if len(collectors) > 0 {
contexts = map[gc.ResourceType]CollectionContext{}
@@ -203,6 +283,7 @@ func startGCContext(ctx context.Context, collectors map[gc.ResourceType]Collecto
return &gcContext{
labelHandlers: labelHandlers,
contexts: contexts,
backRefs: make(map[gc.Node][]gc.Node),
}
}
@@ -212,9 +293,15 @@ func (c *gcContext) all(fn func(gc.Node)) {
}
}
func (c *gcContext) active(namespace string, fn func(gc.Node)) {
func (c *gcContext) active(namespace string, fn func(gc.Node), bref func(gc.Node, gc.Node)) {
for _, gctx := range c.contexts {
gctx.Active(namespace, fn)
if cc, ok := gctx.(collectionWithBackRefs); ok {
// If the context supports back references, use it
cc.ActiveWithBackRefs(namespace, fn, bref)
} else {
// Check if supports back references, if so, add
gctx.Active(namespace, fn)
}
}
}
@@ -225,18 +312,22 @@ func (c *gcContext) leased(namespace, lease string, fn func(gc.Node)) {
}
func (c *gcContext) cancel(ctx context.Context) {
for _, gctx := range c.contexts {
for t, gctx := range c.contexts {
if err := gctx.Cancel(); err != nil {
log.G(ctx).WithError(err).Error("failed to cancel collection context")
log.G(ctx).WithField("type", t).WithError(err).Error("failed to cancel collection context")
}
}
}
func (c *gcContext) finish(ctx context.Context) {
for _, gctx := range c.contexts {
if err := gctx.Finish(); err != nil {
log.G(ctx).WithError(err).Error("failed to finish collection context")
}
func (c *gcContext) finish(ctx context.Context, wg *sync.WaitGroup) {
wg.Add(len(c.contexts))
for t, gctx := range c.contexts {
go func() {
if err := gctx.Finish(); err != nil {
log.G(ctx).WithField("type", t).WithError(err).Error("failed to finish collection context")
}
wg.Done()
}()
}
}
@@ -265,6 +356,14 @@ func (c *gcContext) scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Nod
}
}
bref := func(n gc.Node, ref gc.Node) {
if _, ok := c.backRefs[n]; !ok {
c.backRefs[n] = []gc.Node{ref}
} else {
c.backRefs[n] = append(c.backRefs[n], ref)
}
}
for k, v := v1c.First(); k != nil; k, v = v1c.Next() {
if v != nil {
continue
@@ -385,8 +484,18 @@ func (c *gcContext) scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Nod
if !isExpiredImage(ctx, k, ibkt.Bucket(k), expThreshold) {
fn(gcnode(ResourceImage, ns, string(k)))
} else {
// If the image is expired, still allow it to be referenced from
// other resources, the back references are not relevant if the object
// is not expired since it is already a root object.
return c.sendLabelRefs(ns, ibkt.Bucket(k), nil, func(n gc.Node) {
bref(n, gcnode(ResourceImage, ns, string(k)))
}, nil)
}
return nil
}); err != nil {
return err
}
@@ -420,11 +529,11 @@ func (c *gcContext) scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Nod
return nil
}
if isRootRef(cbkt.Bucket(k)) {
return c.sendLabelRefs(ns, cbkt.Bucket(k), nil, func(n gc.Node) {
bref(n, gcnode(ResourceContent, ns, string(k)))
}, func() {
fn(gcnode(ResourceContent, ns, string(k)))
}
return nil
})
}); err != nil {
return err
}
@@ -438,14 +547,12 @@ func (c *gcContext) scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Nod
return nil
}
cibkt := cbkt.Bucket(k)
snapshotter := string(cibkt.Get(bucketKeySnapshotter))
if snapshotter != "" {
ss := string(cibkt.Get(bucketKeySnapshotKey))
fn(gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", snapshotter, ss)))
}
fn(gcnode(ResourceContainer, ns, string(k)))
return c.sendLabelRefs(ns, cibkt, fn)
return c.sendLabelRefs(ns, cbkt.Bucket(k), nil, func(n gc.Node) {
bref(n, gcnode(ResourceContainer, ns, string(k)))
}, nil)
}); err != nil {
return err
}
@@ -463,10 +570,12 @@ func (c *gcContext) scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Nod
if v != nil {
return nil
}
if isRootRef(snbkt.Bucket(k)) {
return c.sendLabelRefs(ns, snbkt.Bucket(k), nil, func(n gc.Node) {
bref(n, gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", sk, k)))
}, func() {
fn(gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", sk, k)))
}
return nil
})
})
}); err != nil {
return err
@@ -481,19 +590,26 @@ func (c *gcContext) scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Nod
}
sbbkt := bbkt.Bucket(k)
return c.sendLabelRefs(ns, sbbkt, fn)
return c.sendLabelRefs(ns, sbbkt, fn, nil, nil)
}); err != nil {
return err
}
}
c.active(ns, fn)
c.active(ns, fn, bref)
}
return cerr
}
// references finds the resources that are reachable from the given node.
func (c *gcContext) references(ctx context.Context, tx *bolt.Tx, node gc.Node, fn func(gc.Node)) error {
if refs, ok := c.backRefs[node]; ok {
// If we have back references, send them first
for _, ref := range refs {
fn(ref)
}
}
switch node.Type {
case ResourceContent:
bkt := getBucket(tx, bucketKeyVersion, []byte(node.Namespace), bucketKeyObjectContent, bucketKeyObjectBlob, []byte(node.Key))
@@ -502,7 +618,7 @@ func (c *gcContext) references(ctx context.Context, tx *bolt.Tx, node gc.Node, f
return nil
}
return c.sendLabelRefs(node.Namespace, bkt, fn)
return c.sendLabelRefs(node.Namespace, bkt, fn, nil, nil)
case ResourceSnapshot, resourceSnapshotFlat:
ss, name, ok := strings.Cut(node.Key, "/")
if !ok {
@@ -523,7 +639,7 @@ func (c *gcContext) references(ctx context.Context, tx *bolt.Tx, node gc.Node, f
return nil
}
return c.sendLabelRefs(node.Namespace, bkt, fn)
return c.sendLabelRefs(node.Namespace, bkt, fn, nil, nil)
case ResourceImage, resourceImageFlat:
bkt := getBucket(tx, bucketKeyVersion, []byte(node.Namespace), bucketKeyObjectImages, []byte(node.Key))
@@ -547,7 +663,7 @@ func (c *gcContext) references(ctx context.Context, tx *bolt.Tx, node gc.Node, f
return nil
}
return c.sendLabelRefs(node.Namespace, bkt, fn)
return c.sendLabelRefs(node.Namespace, bkt, fn, nil, nil)
case ResourceIngest:
// Send expected value
@@ -562,6 +678,21 @@ func (c *gcContext) references(ctx context.Context, tx *bolt.Tx, node gc.Node, f
fn(gcnode(ResourceContent, node.Namespace, string(expected)))
}
return nil
case ResourceContainer:
bkt := getBucket(tx, bucketKeyVersion, []byte(node.Namespace), bucketKeyObjectContainers, []byte(node.Key))
if bkt == nil {
// Node may be created from dead edge
return nil
}
snapshotter := string(bkt.Get(bucketKeySnapshotter))
if snapshotter != "" {
ss := string(bkt.Get(bucketKeySnapshotKey))
fn(gcnode(ResourceSnapshot, node.Namespace, fmt.Sprintf("%s/%s", snapshotter, ss)))
}
return c.sendLabelRefs(node.Namespace, bkt, fn, nil, nil)
}
return nil
@@ -741,32 +872,28 @@ func (c *gcContext) remove(ctx context.Context, tx *bolt.Tx, node gc.Node) (inte
}
// sendLabelRefs sends all snapshot and content references referred to by the labels in the bkt
func (c *gcContext) sendLabelRefs(ns string, bkt *bolt.Bucket, fn func(gc.Node)) error {
func (c *gcContext) sendLabelRefs(ns string, bkt *bolt.Bucket, fn func(gc.Node), bref func(gc.Node), root func()) error {
lbkt := bkt.Bucket(bucketKeyObjectLabels)
if lbkt != nil {
lc := lbkt.Cursor()
for i := range c.labelHandlers {
labelRef := string(c.labelHandlers[i].key)
for k, v := lc.Seek(c.labelHandlers[i].key); k != nil && strings.HasPrefix(string(k), labelRef); k, v = lc.Next() {
c.labelHandlers[i].fn(ns, k, v, fn)
if (bref == nil && c.labelHandlers[i].bref != nil) || (fn == nil && c.labelHandlers[i].fn != nil) {
continue
}
for k, v := lc.Seek(c.labelHandlers[i].key); k != nil && bytes.HasPrefix(k, c.labelHandlers[i].key); k, v = lc.Next() {
if c.labelHandlers[i].fn != nil {
c.labelHandlers[i].fn(ns, k, v, fn)
} else if c.labelHandlers[i].bref != nil {
c.labelHandlers[i].bref(ns, k, v, bref)
} else if root != nil {
root()
}
}
}
}
return nil
}
func isRootRef(bkt *bolt.Bucket) bool {
lbkt := bkt.Bucket(bucketKeyObjectLabels)
if lbkt != nil {
rv := lbkt.Get(labelGCRoot)
if rv != nil {
// TODO: interpret rv as a timestamp and skip if expired
return true
}
}
return false
}
func isExpiredImage(ctx context.Context, k []byte, bkt *bolt.Bucket, expTheshold time.Time) bool {
lbkt := bkt.Bucket(bucketKeyObjectLabels)
if lbkt != nil {

View File

@@ -540,8 +540,10 @@ func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
}
var (
bname string
rerr error
bname string
bparent string
rebase bool
rerr error
)
if err := update(ctx, s.db, func(tx *bolt.Tx) error {
bkt := getSnapshotterBucket(tx, ns, s.name)
@@ -581,6 +583,13 @@ func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
}
parent := obkt.Get(bucketKeyParent)
if len(parent) == 0 && len(base.Parent) > 0 {
parent = []byte(base.Parent)
if err = obkt.Put(bucketKeyParent, parent); err != nil {
return err
}
rebase = true
}
if len(parent) > 0 {
pbkt := bkt.Bucket(parent)
if pbkt == nil {
@@ -601,6 +610,8 @@ func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
if err := bbkt.Put(bucketKeyParent, parent); err != nil {
return err
}
bparent = string(pbkt.Get(bucketKeyName))
}
ts := time.Now().UTC()
if err := boltutil.WriteTimestamps(bbkt, ts, ts); err != nil {
@@ -617,7 +628,12 @@ func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
return err
}
inheritedOpt := snapshots.WithLabels(snapshots.FilterInheritedLabels(base.Labels))
inheritedOpt := []snapshots.Opt{
snapshots.WithLabels(snapshots.FilterInheritedLabels(base.Labels)),
}
if rebase {
inheritedOpt = append(inheritedOpt, snapshots.WithParent(bparent))
}
// NOTE: Backend snapshotters should commit fast and reliably to
// prevent metadata store locking and minimizing rollbacks.
@@ -625,7 +641,7 @@ func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
// risk of the committed keys becoming out of sync. If this operation
// succeed and the overall transaction fails then the risk of out of
// sync data is higher and may require manual cleanup.
if err := s.Snapshotter.Commit(ctx, nameKey, bkey, inheritedOpt); err != nil {
if err := s.Snapshotter.Commit(ctx, nameKey, bkey, inheritedOpt...); err != nil {
if errdefs.IsNotFound(err) {
log.G(ctx).WithField("snapshotter", s.name).WithField("key", key).WithError(err).Error("uncommittable snapshot: missing in backend, snapshot should be removed")
}

View File

@@ -0,0 +1,103 @@
/*
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 mount
import (
"context"
"os"
"time"
"github.com/containerd/errdefs"
"github.com/containerd/log"
)
func LoopbackHandler() Handler {
return loopbackHandler{}
}
type loopbackHandler struct {
}
func (loopbackHandler) Mount(ctx context.Context, m Mount, mp string, _ []ActiveMount) (ActiveMount, error) {
if m.Type != "loop" {
return ActiveMount{}, errdefs.ErrNotImplemented
}
params := LoopParams{
Autoclear: true,
}
// TODO: Handle readonly
// TODO: Handle direct io
t := time.Now()
loop, err := SetupLoop(m.Source, params)
if err != nil {
return ActiveMount{}, err
}
defer loop.Close()
if err := os.Symlink(loop.Name(), mp); err != nil {
return ActiveMount{}, err
}
if err := setLoopAutoclear(loop, false); err != nil {
return ActiveMount{}, err
}
return ActiveMount{
Mount: m,
MountedAt: &t,
MountPoint: mp,
}, nil
}
func (loopbackHandler) Unmount(ctx context.Context, path string) error {
loopdev, err := os.Readlink(path)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
loop, err := os.Open(loopdev)
if err != nil {
return err
}
defer loop.Close()
if err := setLoopAutoclear(loop, true); err != nil {
return err
}
if err := os.Remove(path); err != nil {
if os.IsNotExist(err) {
return nil
}
// if removal of the symlink has failed, its possible for the loop device to get cleaned
// up and re-used. Leave the loop device around to prevent re-use and let a retry of
// Unmount clear it.`
if err := setLoopAutoclear(loop, false); err != nil {
// Very unlikely but log to track in case there is a problem with
// the loop being cleared and re-used.
log.G(ctx).WithError(err).Errorf("Failed to unset auto clear flag on symlink removal failure, loopback %q may be cleaned up while still being tracked", loopdev)
}
return err
}
return nil
}

View File

@@ -23,9 +23,10 @@ import (
"strings"
"time"
"golang.org/x/sys/unix"
"github.com/containerd/containerd/v2/internal/randutil"
kernel "github.com/containerd/containerd/v2/pkg/kernelversion"
"golang.org/x/sys/unix"
)
const (
@@ -44,6 +45,7 @@ type LoopParams struct {
Autoclear bool
// Use direct IO to access the loop backing file
Direct bool
// TODO: Support block size, offset, sizelimit
}
func getFreeLoopDev() (uint32, error) {
@@ -149,7 +151,7 @@ func setupLoopDev(backingFile, loopDev string, param LoopParams) (_ *os.File, re
return loop, nil
}
// setupLoop looks for (and possibly creates) a free loop device, and
// SetupLoop looks for (and possibly creates) a free loop device, and
// then attaches backingFile to it.
//
// When autoclear is true, caller should take care to close it when
@@ -163,7 +165,7 @@ func setupLoopDev(backingFile, loopDev string, param LoopParams) (_ *os.File, re
// the loop device when done with it.
//
// Upon success, the file handle to the loop device is returned.
func setupLoop(backingFile string, param LoopParams) (*os.File, error) {
func SetupLoop(backingFile string, param LoopParams) (*os.File, error) {
for retry := 1; retry < 100; retry++ {
num, err := getFreeLoopDev()
if err != nil {
@@ -190,6 +192,29 @@ func setupLoop(backingFile string, param LoopParams) (*os.File, error) {
return nil, errors.New("timeout creating new loopback device")
}
func setLoopAutoclear(loop *os.File, autoclear bool) error {
info, err := unix.IoctlLoopGetStatus64(int(loop.Fd()))
if err != nil {
return fmt.Errorf("failed to get loop device info: %w", err)
}
flags := info.Flags
if autoclear {
flags |= unix.LO_FLAGS_AUTOCLEAR
} else {
flags &= ^uint32(unix.LO_FLAGS_AUTOCLEAR)
}
if flags != info.Flags {
info.Flags = flags
err = unix.IoctlLoopSetStatus64(int(loop.Fd()), info)
if err != nil {
return fmt.Errorf("failed to set loop device info: %w", err)
}
}
return nil
}
func removeLoop(loopdev string) error {
file, err := os.Open(loopdev)
if err != nil {
@@ -202,7 +227,7 @@ func removeLoop(loopdev string) error {
// AttachLoopDevice attaches a specified backing file to a loop device
func AttachLoopDevice(backingFile string) (string, error) {
file, err := setupLoop(backingFile, LoopParams{})
file, err := SetupLoop(backingFile, LoopParams{})
if err != nil {
return "", err
}

View File

@@ -0,0 +1,137 @@
/*
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 mount
import (
"context"
"time"
)
// Manager handles activating a mount array to be mounted by the
// system. It supports custom mount types that can be handled by
// plugins and don't need to be directly mountable. For example, this
// can be used to do device activation and setting up process or
// sockets such as for fuse or tcmu.
// The returned activation info will contain the remaining mounts
// which must be performed by the system, likely in a container's
// mount namespace. Any mounts or devices activated by the mount
// manager will be done outside the container's namespace.
type Manager interface {
Activate(context.Context, string, []Mount, ...ActivateOpt) (ActivationInfo, error)
Deactivate(context.Context, string) error
Info(context.Context, string) (ActivationInfo, error)
Update(context.Context, ActivationInfo, ...string) (ActivationInfo, error)
List(context.Context, ...string) ([]ActivationInfo, error)
}
// Handler is an interface for plugins to perform a mount which is managed
// by a MountManager. The MountManager will be responsible for associating
// mount types to MountHandlers and determining what the plugin should be used.
// The Handler interface is intended to be used for custom mount plugins
// and does not replace the mount calls for system mounts.
type Handler interface {
Mount(context.Context, Mount, string, []ActiveMount) (ActiveMount, error)
Unmount(context.Context, string) error
}
// Transformer is an interface that can make changes to the mount based on
// the previous mount state. This can be used to update the values of the
// mount, such as with formatting, or for mount initialization that do not
// require runtime state, such as device formatting.
type Transformer interface {
Transform(context.Context, Mount, []ActiveMount) (Mount, error)
}
// ActivateOptions are used to modify activation behavior. Activate may be
// performed differently based on the different scenarios, such as mounting
// to view a filesystem or preparing a filesystem for a container that may
// have specific runtime requirements. The runtime for a container may also
// have different capabilities that would allow it to handle mounts which
// would not need to be handled by the mount manager.
type ActivateOptions struct {
// Labels are the labels to use for the activation
Labels map[string]string
// Temporary specifies that the mount will be used temporarily
// and all mounts should be performed
Temporary bool
// AllowMountTypes indicates that the caller will handle the specified
// mount types and should not be handled by the mount manager even if
// there is a configured handler for the type.
// Use "/*" suffix to match prepare mount types, such as "format/*".
AllowMountTypes []string
}
// ActivateOpt is a function option for Activate
type ActivateOpt func(*ActivateOptions)
// WithTemporary indicates that the activation is for temporary access
// of the mounts. All mounts should be performed and a single bind
// mount is returned to access to the mounted filesystem.
func WithTemporary(o *ActivateOptions) {
o.Temporary = true
}
// WithLabels specifies the labels to use for the stored activation info.
func WithLabels(labels map[string]string) ActivateOpt {
return func(o *ActivateOptions) {
o.Labels = labels
}
}
// WithAllowMountType indicates the mount types that the peformer
// of the mounts will support. Even if there is a custom handler
// registered for the mount type to the mount handler, these mounts
// should not performed unless required to support subsequent mounts.
// For prepare mount types, use "/*" suffix to match all prepare types,
// such as "format/*".
func WithAllowMountType(mountType string) ActivateOpt {
return func(o *ActivateOptions) {
o.AllowMountTypes = append(o.AllowMountTypes, mountType)
}
}
// ActiveMount represents a mount which has been mounted by a
// MountHandler or directly mounted by a mount manager.
type ActiveMount struct {
Mount
MountedAt *time.Time
// MountPoint is the filesystem mount location
MountPoint string
// MountData is metadata used by the mount type which can also be used by
// subsequent mounts.
MountData map[string]string
}
// ActivationInfo represents the state of an active set of mounts being managed by a
// mount manager. The Name is unique and can be used to reference the activation
// from other resources.
type ActivationInfo struct {
Name string
// Active are the mounts which was successfully mounted on activate
Active []ActiveMount
// System is the list of system mounts to access the filesystem root
// This will always be non-empty and a bind mount will be created
// and filled in here when all mounts are performed
System []Mount
Labels map[string]string
}

View File

@@ -95,16 +95,16 @@ func IDMapMountWithAttrs(source, target string, usernsFd int, attrSet uint64, at
dFd, err := unix.OpenTree(-int(unix.EBADF), source, uint(unix.OPEN_TREE_CLONE|unix.OPEN_TREE_CLOEXEC|unix.AT_EMPTY_PATH))
if err != nil {
return fmt.Errorf("Unable to open tree for %s: %w", target, err)
return fmt.Errorf("unable to open tree for %s: %w", target, err)
}
defer unix.Close(dFd)
if err = unix.MountSetattr(dFd, "", unix.AT_EMPTY_PATH, &attr); err != nil {
return fmt.Errorf("Unable to shift GID/UID or set mount attrs for %s: %w", target, err)
return fmt.Errorf("unable to shift GID/UID or set mount attrs for %s: %w", target, err)
}
if err = unix.MoveMount(dFd, "", -int(unix.EBADF), target, unix.MOVE_MOUNT_F_EMPTY_PATH); err != nil {
return fmt.Errorf("Unable to attach mount tree to %s: %w", target, err)
return fmt.Errorf("unable to attach mount tree to %s: %w", target, err)
}
return nil
}

View File

@@ -1,5 +1,3 @@
//go:build go1.23 && linux
/*
Copyright The containerd Authors.
@@ -29,18 +27,14 @@ import (
)
// getUsernsFD returns pinnable user namespace's file descriptor.
//
// NOTE: The GO runtime uses pidfd to handle subprocess since go1.23. However,
// it has double close issue tracked by [1]. We can't use pidfd directly and
// the GO runtime doesn't export interface to show if it's using pidfd or not.
// So, we call `sys.SupportsPidFD` first and then use `os.Process` directly.
//
// [1]: https://github.com/golang/go/issues/68984
func getUsernsFD(uidMaps, gidMaps []syscall.SysProcIDMap) (_ *os.File, retErr error) {
if !sys.SupportsPidFD() {
return nil, fmt.Errorf("failed to prevent pid reused issue because pidfd isn't supported")
return nil, fmt.Errorf("kernel doesn't support pidfd")
}
var pidfd int
proc, err := os.StartProcess("/proc/self/exe", []string{"containerd[getUsernsFD]"}, &os.ProcAttr{
Sys: &syscall.SysProcAttr{
Cloneflags: unix.CLONE_NEWUSER,
@@ -50,15 +44,26 @@ func getUsernsFD(uidMaps, gidMaps []syscall.SysProcIDMap) (_ *os.File, retErr er
// be in PTRACE_TRACEME mode before performing execve.
Ptrace: true,
Pdeathsig: syscall.SIGKILL,
PidFD: &pidfd,
},
})
if err != nil {
return nil, fmt.Errorf("failed to start noop process for unshare: %w", err)
}
defer func() {
if pidfd == -1 {
proc.Kill()
proc.Wait()
return nil, fmt.Errorf("failed to prevent pid reused issue because pidfd isn't supported")
}
pidFD := os.NewFile(uintptr(pidfd), "pidfd")
defer func() {
unix.PidfdSendSignal(int(pidFD.Fd()), unix.SIGKILL, nil, 0)
pidfdWaitid(pidFD)
pidFD.Close()
}()
// NOTE:
@@ -78,8 +83,14 @@ func getUsernsFD(uidMaps, gidMaps []syscall.SysProcIDMap) (_ *os.File, retErr er
// Ensure the child process is still alive. If the err is ESRCH, we
// should return error because we can't guarantee the usernsFD and
// u[g]idmapFile are valid. It's safe to return error and retry.
if err := proc.Signal(syscall.Signal(0)); err != nil {
if err := unix.PidfdSendSignal(int(pidFD.Fd()), 0, nil, 0); err != nil {
return nil, fmt.Errorf("failed to ensure child process is alive: %w", err)
}
return usernsFD, nil
}
func pidfdWaitid(pidFD *os.File) error {
return sys.IgnoringEINTR(func() error {
return unix.Waitid(unix.P_PIDFD, int(pidFD.Fd()), nil, unix.WEXITED, nil)
})
}

View File

@@ -1,93 +0,0 @@
//go:build !go1.23 && linux
/*
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 mount
import (
"fmt"
"os"
"syscall"
"github.com/containerd/containerd/v2/pkg/sys"
"golang.org/x/sys/unix"
)
// getUsernsFD returns pinnable user namespace's file descriptor.
func getUsernsFD(uidMaps, gidMaps []syscall.SysProcIDMap) (_ *os.File, retErr error) {
var pidfd int
proc, err := os.StartProcess("/proc/self/exe", []string{"containerd[getUsernsFD]"}, &os.ProcAttr{
Sys: &syscall.SysProcAttr{
Cloneflags: unix.CLONE_NEWUSER,
UidMappings: uidMaps,
GidMappings: gidMaps,
// NOTE: It's reexec but it's not heavy because subprocess
// be in PTRACE_TRACEME mode before performing execve.
Ptrace: true,
Pdeathsig: syscall.SIGKILL,
PidFD: &pidfd,
},
})
if err != nil {
return nil, fmt.Errorf("failed to start noop process for unshare: %w", err)
}
if pidfd == -1 || !sys.SupportsPidFD() {
proc.Kill()
proc.Wait()
return nil, fmt.Errorf("failed to prevent pid reused issue because pidfd isn't supported")
}
pidFD := os.NewFile(uintptr(pidfd), "pidfd")
defer func() {
unix.PidfdSendSignal(int(pidFD.Fd()), unix.SIGKILL, nil, 0)
pidfdWaitid(pidFD)
pidFD.Close()
}()
// NOTE:
//
// The usernsFD will hold the userns reference in kernel. Even if the
// child process is reaped, the usernsFD is still valid.
usernsFD, err := os.Open(fmt.Sprintf("/proc/%d/ns/user", proc.Pid))
if err != nil {
return nil, fmt.Errorf("failed to get userns file descriptor for /proc/%d/user/ns: %w", proc.Pid, err)
}
defer func() {
if retErr != nil {
usernsFD.Close()
}
}()
// Ensure the child process is still alive. If the err is ESRCH, we
// should return error because we can't guarantee the usernsFD and
// u[g]idmapFile are valid. It's safe to return error and retry.
if err := unix.PidfdSendSignal(int(pidFD.Fd()), 0, nil, 0); err != nil {
return nil, fmt.Errorf("failed to ensure child process is alive: %w", err)
}
return usernsFD, nil
}
func pidfdWaitid(pidFD *os.File) error {
return sys.IgnoringEINTR(func() error {
return unix.Waitid(unix.P_PIDFD, int(pidFD.Fd()), nil, unix.WEXITED, nil)
})
}

View File

@@ -159,7 +159,7 @@ func (m *Mount) mount(target string) (err error) {
// or remount with changed data
source := m.Source
if opt.losetup {
loFile, err := setupLoop(m.Source, loopParams)
loFile, err := SetupLoop(m.Source, loopParams)
if err != nil {
return err
}

View File

@@ -183,3 +183,93 @@ func UnmountAll(mount string, flags int) error {
func UnmountRecursive(mount string, flags int) error {
return UnmountAll(mount, flags)
}
// CimFS specific constants
const (
// LayerCimPathFlag is the option flag used to represent the path at which a layer
// CIM must be stored. This flag only applies if an image layer is being extracted
// onto the snapshot i.e the snapshot key has an UnpackKeyPrefix. For all other
// snapshots, this MUST be ignored.
LayerCimPathFlag = "cimpath="
// Similar to ParentLayerPathsFlag this is the optinos flag used to represent the JSON encoded list of
// parent layer CIMs
ParentLayerCimPathsFlag = "parentCimPaths="
// string to specify the standard cimfs type of mount
CimFSMountType string = "CimFS"
// flag that specifies what kind of a block CIM is being used in the snapshot
BlockCIMTypeFlag string = "blockCIMType="
// "file" type of block CIM that will usually be used in snapshots
BlockCIMTypeFile string = "file"
// flag that specifies the path of a merged block CIM.
MergedCIMPathFlag string = "mergedCIMPath="
// a block CIM snapshotter mount type
BlockCIMMountType string = "BlockCIM"
// flag that enables layer integrity for block CIMs
EnableLayerIntegrityFlag string = "enable_layer_integrity"
// flag that enables VHD footer for block CIMs
AppendVHDFooterFlag string = "append_vhd_footer"
)
// getOptionByPrefix finds an option that has the provided prefix, cuts the prefix from
// that option string and return the remaining string. Boolean return is set to true if an
// option is found with the given prefix. It is set to false otherwise.
func getOptionByPrefix(m *Mount, prefix string) (string, bool) {
for _, option := range m.Options {
val, found := strings.CutPrefix(option, prefix)
if found {
return val, true
}
}
return "", false
}
// gets the paths of the parent cims of this mount
func GetParentCimPaths(m *Mount) ([]string, error) {
if m.Type != CimFSMountType {
return nil, fmt.Errorf("invalid mount type: '%s'", m.Type)
}
var parentCimPaths []string
val, found := getOptionByPrefix(m, ParentLayerCimPathsFlag)
if !found {
return parentCimPaths, nil
}
err := json.Unmarshal([]byte(val), &parentCimPaths)
return parentCimPaths, err
}
// 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 GetCimPath(m *Mount) (string, error) {
if m.Type != CimFSMountType {
return "", fmt.Errorf("invalid mount type: '%s'", m.Type)
}
cimPath, found := getOptionByPrefix(m, LayerCimPathFlag)
if !found {
return "", fmt.Errorf("cim path not found")
}
return cimPath, nil
}
// GetEnableLayerIntegrity checks if the enableLayerIntegrity flag is present in mount options
func GetEnableLayerIntegrity(m *Mount) bool {
for _, option := range m.Options {
if option == EnableLayerIntegrityFlag {
return true
}
}
return false
}
// GetAppendVHDFooter checks if the appendVHDFooter flag is present in mount options
func GetAppendVHDFooter(m *Mount) bool {
for _, option := range m.Options {
if option == AppendVHDFooterFlag {
return true
}
}
return false
}

View File

@@ -0,0 +1,100 @@
/*
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 proxy
import (
"time"
"github.com/containerd/containerd/api/types"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
"github.com/containerd/containerd/v2/core/mount"
)
func ActivationInfoToProto(a mount.ActivationInfo) *types.ActivationInfo {
return &types.ActivationInfo{
Name: a.Name,
Active: ActiveMountToProto(a.Active),
System: mount.ToProto(a.System),
Labels: a.Labels,
}
}
func ActivationInfoFromProto(a *types.ActivationInfo) mount.ActivationInfo {
if a == nil {
return mount.ActivationInfo{}
}
return mount.ActivationInfo{
Name: a.Name,
Active: ActiveMountFromProto(a.Active),
System: mount.FromProto(a.System),
Labels: a.Labels,
}
}
func ActiveMountToProto(a []mount.ActiveMount) []*types.ActiveMount {
c := make([]*types.ActiveMount, len(a))
for i, m := range a {
c[i] = &types.ActiveMount{
Mount: &types.Mount{
Type: m.Type,
Source: m.Source,
Target: m.Target,
Options: m.Options,
},
MountedAt: toTimestamp(m.MountedAt),
MountPoint: m.MountPoint,
Data: m.MountData,
}
}
return c
}
func ActiveMountFromProto(a []*types.ActiveMount) []mount.ActiveMount {
c := make([]mount.ActiveMount, len(a))
for i, m := range a {
c[i] = mount.ActiveMount{
Mount: mount.Mount{
Type: m.Mount.Type,
Source: m.Mount.Source,
Target: m.Mount.Target,
Options: m.Mount.Options,
},
MountedAt: fromTimestamp(m.MountedAt),
MountPoint: m.MountPoint,
MountData: m.Data,
}
}
return c
}
func toTimestamp(from *time.Time) *timestamppb.Timestamp {
if from == nil {
return nil
}
return timestamppb.New(*from)
}
func fromTimestamp(from *timestamppb.Timestamp) *time.Time {
if from == nil {
return nil
}
t := from.AsTime()
return &t
}

View File

@@ -0,0 +1,165 @@
/*
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 proxy
import (
"context"
"fmt"
"io"
"github.com/containerd/containerd/api/services/mounts/v1"
"github.com/containerd/errdefs"
"github.com/containerd/errdefs/pkg/errgrpc"
"github.com/containerd/ttrpc"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/emptypb"
"github.com/containerd/containerd/v2/core/mount"
ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types"
)
type proxyMounts struct {
// client is the rpc mounts client
// NOTE: ttrpc is used because it is the smaller interface shared with grpc
client mounts.TTRPCMountsClient
}
// NewMountManager returns a new mount manager which communicates over a GRPC
// connection using the containerd mounts GRPC or ttrpc API.
func NewMountManager(client any) mount.Manager {
switch c := client.(type) {
case mounts.MountsClient:
return &proxyMounts{
client: convertClient{c},
}
case grpc.ClientConnInterface:
return &proxyMounts{
client: convertClient{mounts.NewMountsClient(c)},
}
case mounts.TTRPCMountsClient:
return &proxyMounts{
client: c,
}
case *ttrpc.Client:
return &proxyMounts{
client: mounts.NewTTRPCMountsClient(c),
}
default:
panic(fmt.Errorf("unsupported content client %T: %w", client, errdefs.ErrNotImplemented))
}
}
func (pm *proxyMounts) Activate(ctx context.Context, name string, all []mount.Mount, opts ...mount.ActivateOpt) (mount.ActivationInfo, error) {
var options mount.ActivateOptions
for _, o := range opts {
o(&options)
}
req := &mounts.ActivateRequest{
Name: name,
Mounts: mount.ToProto(all),
Labels: options.Labels,
Temporary: options.Temporary,
}
a, err := pm.client.Activate(ctx, req)
if err != nil {
return mount.ActivationInfo{}, errgrpc.ToNative(err)
}
return ActivationInfoFromProto(a.Info), nil
}
func (pm *proxyMounts) Deactivate(ctx context.Context, name string) error {
_, err := pm.client.Deactivate(ctx, &mounts.DeactivateRequest{
Name: name,
})
return errgrpc.ToNative(err)
}
func (pm *proxyMounts) Info(ctx context.Context, name string) (mount.ActivationInfo, error) {
a, err := pm.client.Info(ctx, &mounts.InfoRequest{
Name: name,
})
if err != nil {
return mount.ActivationInfo{}, errgrpc.ToNative(err)
}
return ActivationInfoFromProto(a.Info), nil
}
func (pm *proxyMounts) Update(ctx context.Context, info mount.ActivationInfo, fieldpaths ...string) (mount.ActivationInfo, error) {
var updateMask *ptypes.FieldMask
if len(fieldpaths) > 0 {
updateMask = &ptypes.FieldMask{
Paths: fieldpaths,
}
}
a, err := pm.client.Update(ctx, &mounts.UpdateRequest{
Info: ActivationInfoToProto(info),
UpdateMask: updateMask,
})
if err != nil {
return mount.ActivationInfo{}, errgrpc.ToNative(err)
}
return ActivationInfoFromProto(a.Info), nil
}
func (pm *proxyMounts) List(ctx context.Context, filters ...string) ([]mount.ActivationInfo, error) {
l, err := pm.client.List(ctx, &mounts.ListRequest{
Filters: filters,
})
if err != nil {
return nil, errgrpc.ToNative(err)
}
var infos []mount.ActivationInfo
for {
a, err := l.Recv()
if err != nil {
if err == io.EOF {
break
}
return nil, errgrpc.ToNative(err)
}
infos = append(infos, ActivationInfoFromProto(a.Info))
}
return infos, nil
}
type convertClient struct {
mounts.MountsClient
}
func (cc convertClient) Activate(ctx context.Context, req *mounts.ActivateRequest) (*mounts.ActivateResponse, error) {
return cc.MountsClient.Activate(ctx, req)
}
func (cc convertClient) Deactivate(ctx context.Context, req *mounts.DeactivateRequest) (*emptypb.Empty, error) {
return cc.MountsClient.Deactivate(ctx, req)
}
func (cc convertClient) Info(ctx context.Context, req *mounts.InfoRequest) (*mounts.InfoResponse, error) {
return cc.MountsClient.Info(ctx, req)
}
func (cc convertClient) Update(ctx context.Context, req *mounts.UpdateRequest) (*mounts.UpdateResponse, error) {
return cc.MountsClient.Update(ctx, req)
}
func (cc convertClient) List(ctx context.Context, req *mounts.ListRequest) (mounts.TTRPCMounts_ListClient, error) {
return cc.MountsClient.List(ctx, req)
}

View File

@@ -25,11 +25,11 @@ import (
func hostPaths(root, host string) (hosts []string) {
ch := hostDirectory(host)
if ch != host {
hosts = append(hosts, filepath.Join(root, strings.Replace(ch, ":", "", -1)))
hosts = append(hosts, filepath.Join(root, strings.ReplaceAll(ch, ":", "")))
}
hosts = append(hosts,
filepath.Join(root, strings.Replace(host, ":", "", -1)),
filepath.Join(root, strings.ReplaceAll(host, ":", "")),
filepath.Join(root, "_default"),
)

View File

@@ -131,7 +131,7 @@ func ConfigureHosts(ctx context.Context, options HostOptions) docker.RegistryHos
}
}
hosts[len(hosts)-1].path = "/v2"
hosts[len(hosts)-1].capabilities = docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush
hosts[len(hosts)-1].capabilities = docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush | docker.HostCapabilityReferrers
}
// tlsConfigured indicates that TLS was configured and HTTP endpoints should
@@ -458,12 +458,14 @@ func parseHostConfig(server string, baseDir string, config hostFileConfig) (host
result.capabilities |= docker.HostCapabilityResolve
case "push":
result.capabilities |= docker.HostCapabilityPush
case "referrers":
result.capabilities |= docker.HostCapabilityReferrers
default:
return hostConfig{}, fmt.Errorf("unknown capability %v", c)
}
}
} else {
result.capabilities = docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush
result.capabilities = docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush | docker.HostCapabilityReferrers
}
if config.CACert != nil {

View File

@@ -46,7 +46,7 @@ func (ec ErrorCode) ErrorCode() ErrorCode {
// Error returns the ID/Value
func (ec ErrorCode) Error() string {
// NOTE(stevvooe): Cannot use message here since it may have unpopulated args.
return strings.ToLower(strings.Replace(ec.String(), "_", " ", -1))
return strings.ToLower(strings.ReplaceAll(ec.String(), "_", " "))
}
// Descriptor returns the descriptor for the error code.

View File

@@ -26,7 +26,6 @@ import (
"io"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
@@ -260,7 +259,7 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
req.path = req.path + "?" + u.RawQuery
}
rc, err := r.open(ctx, req, desc.MediaType, offset, false)
rc, _, err := r.open(ctx, req, desc.MediaType, offset, false)
if err != nil {
if errdefs.IsNotFound(err) {
continue // try one of the other urls.
@@ -282,7 +281,7 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
return nil, err
}
rc, err := r.open(ctx, req, desc.MediaType, offset, i == len(r.hosts)-1)
rc, _, err := r.open(ctx, req, desc.MediaType, offset, i == len(r.hosts)-1)
if err != nil {
// Store the error for referencing later
if firstErr == nil {
@@ -305,7 +304,7 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
return nil, err
}
rc, err := r.open(ctx, req, desc.MediaType, offset, i == len(r.hosts)-1)
rc, _, err := r.open(ctx, req, desc.MediaType, offset, i == len(r.hosts)-1)
if err != nil {
// Store the error for referencing later
if firstErr == nil {
@@ -419,8 +418,9 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest, op
return nil, desc, firstErr
}
seeker, err := newHTTPReadSeeker(sz, func(offset int64) (io.ReadCloser, error) {
return r.open(ctx, getReq, config.Mediatype, offset, true)
seeker, err := newHTTPReadSeeker(sz, func(offset int64) (rc io.ReadCloser, err error) {
rc, _, err = r.open(ctx, getReq, config.Mediatype, offset, true)
return
})
if err != nil {
return nil, desc, err
@@ -437,7 +437,7 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest, op
return seeker, desc, nil
}
func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, offset int64, lastHost bool) (_ io.ReadCloser, retErr error) {
func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, offset int64, lastHost bool) (_ io.ReadCloser, _ int64, retErr error) {
const minChunkSize = 512
chunkSize := int64(r.performances.ConcurrentLayerFetchBuffer)
@@ -457,21 +457,24 @@ func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string,
}
if err := r.Acquire(ctx, 1); err != nil {
return nil, err
return nil, 0, err
}
var remaining int64
resp, err := req.doWithRetries(ctx, lastHost, withErrorCheck, withOffsetCheck(offset, parallelism))
switch err {
case nil:
// all good
remaining = resp.ContentLength
case errContentRangeIgnored:
if parallelism != 1 {
log.G(ctx).WithError(err).Info("remote host ignored content range, forcing parallelism to 1")
parallelism = 1
}
remaining = resp.ContentLength - offset
default:
log.G(ctx).WithError(err).Debug("fetch failed")
r.Release(1)
return nil, err
return nil, 0, err
}
body := &fnOnClose{
@@ -490,7 +493,6 @@ func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string,
return r == ' ' || r == '\t' || r == ','
})
remaining, _ := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 0)
if remaining <= chunkSize {
parallelism = 1
}
@@ -589,13 +591,13 @@ func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string,
zstd.WithDecoderLowmem(false),
)
if err != nil {
return nil, err
return nil, 0, err
}
body.ReadCloser = r.IOReadCloser()
case "gzip":
r, err := gzip.NewReader(body.ReadCloser)
if err != nil {
return nil, err
return nil, 0, err
}
body.ReadCloser = r
case "deflate":
@@ -603,11 +605,11 @@ func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string,
case "identity", "":
// no content-encoding applied, use raw body
default:
return nil, errors.New("unsupported Content-Encoding algorithm: " + algorithm)
return nil, 0, errors.New("unsupported Content-Encoding algorithm: " + algorithm)
}
}
return body, nil
return body, remaining, nil
}
type fnOnClose struct {

View File

@@ -59,7 +59,8 @@ func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) {
if n > 0 || err == nil {
hrs.errsWithNoProgress = 0
}
if err == io.ErrUnexpectedEOF {
switch err {
case io.ErrUnexpectedEOF:
// connection closed unexpectedly. try reconnecting.
if n == 0 {
hrs.errsWithNoProgress++
@@ -76,7 +77,7 @@ func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) {
if _, err2 := hrs.reader(); err2 == nil {
return n, nil
}
} else if err == io.EOF {
case io.EOF:
// The CRI's imagePullProgressTimeout relies on responseBody.Close to
// update the process monitor's status. If the err is io.EOF, close
// the connection since there is no more available data.
@@ -102,6 +103,36 @@ func (hrs *httpReadSeeker) Close() error {
return nil
}
func (hrs *httpReadSeeker) ReadAt(p []byte, offset int64) (n int, err error) {
if hrs.closed {
return 0, fmt.Errorf("httpReadSeeker.ReadAt: closed: %w", errdefs.ErrUnavailable)
}
if offset < 0 {
return 0, fmt.Errorf("httpReadSeeker.ReadAt: negative offset: %w", errdefs.ErrInvalidArgument)
}
if hrs.size != -1 && offset >= hrs.size {
return 0, io.EOF
}
if hrs.open == nil {
return 0, fmt.Errorf("httpReadSeeker.ReadAt: cannot open: %w", errdefs.ErrNotImplemented)
}
rc, err := hrs.open(offset)
if err != nil {
return 0, fmt.Errorf("httpReadSeeker.ReadAt: failed to open at offset %d: %w", offset, err)
}
defer func() {
if closeErr := rc.Close(); closeErr != nil {
log.L.WithError(closeErr).Error("httpReadSeeker.ReadAt: failed to close ReadCloser")
}
}()
return io.ReadFull(rc, p)
}
func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) {
if hrs.closed {
return 0, fmt.Errorf("Fetcher.Seek: closed: %w", errdefs.ErrUnavailable)

View File

@@ -526,15 +526,21 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
if expected == "" {
expected = status.Expected
} else if expected != status.Expected {
return fmt.Errorf("unexpected digest received: got %q, expected %q", status.Expected, expected)
}
actual, err := digest.Parse(resp.Header.Get("Docker-Content-Digest"))
if err != nil {
return fmt.Errorf("invalid content digest in response: %w", err)
}
if dgstHdr := resp.Header.Get("Docker-Content-Digest"); dgstHdr != "" {
actual, err := digest.Parse(dgstHdr)
if err != nil {
return fmt.Errorf("invalid content digest in response: %w", err)
}
if actual != expected {
return fmt.Errorf("got digest %s, expected %s", actual, expected)
if actual != expected {
return fmt.Errorf("got digest %s, expected %s", actual, expected)
}
} else {
log.G(ctx).Info("registry did not send a Docker-Content-Digest header")
}
status.Committed = true

View File

@@ -0,0 +1,158 @@
/*
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 docker
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"
"github.com/containerd/containerd/v2/core/remotes"
"github.com/containerd/errdefs"
"github.com/containerd/log"
digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
func (r dockerFetcher) FetchReferrers(ctx context.Context, dgst digest.Digest, opts ...remotes.FetchReferrersOpt) ([]ocispec.Descriptor, error) {
var config remotes.FetchReferrersConfig
for _, opt := range opts {
opt(ctx, &config)
}
rc, size, err := r.openReferrers(ctx, dgst, config)
if err != nil {
if errdefs.IsNotFound(err) {
return []ocispec.Descriptor{}, nil
}
return nil, err
}
defer rc.Close()
if size < 0 {
size = MaxManifestSize
} else if size > MaxManifestSize {
return nil, fmt.Errorf("referrers index size %d exceeds maximum allowed %d: %w", size, MaxManifestSize, errdefs.ErrNotFound)
}
var index ocispec.Index
dec := json.NewDecoder(io.LimitReader(rc, size))
if err := dec.Decode(&index); err != nil {
return nil, fmt.Errorf("failed to decode referrers index: %w", err)
}
if _, err := dec.Token(); !errors.Is(err, io.EOF) {
return nil, fmt.Errorf("unexpected data after JSON object")
}
if len(config.ArtifactTypes) == 0 {
return index.Manifests, nil
}
var referrers []ocispec.Descriptor
tFilter := map[string]struct{}{}
for _, t := range config.ArtifactTypes {
tFilter[t] = struct{}{}
}
for _, desc := range index.Manifests {
if _, ok := tFilter[desc.ArtifactType]; ok {
referrers = append(referrers, desc)
}
}
return referrers, nil
}
func (r dockerFetcher) openReferrers(ctx context.Context, dgst digest.Digest, config remotes.FetchReferrersConfig) (io.ReadCloser, int64, error) {
mediaType := ocispec.MediaTypeImageIndex
ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", dgst))
hosts := r.filterHosts(HostCapabilityReferrers)
var fallbackHosts []RegistryHost
if len(hosts) == 0 {
fallbackHosts = r.filterHosts(HostCapabilityResolve)
if len(fallbackHosts) == 0 {
return nil, 0, fmt.Errorf("no referrers hosts: %w", errdefs.ErrNotFound)
}
} else {
// If referrers are defined, use same hosts for fallback
fallbackHosts = hosts
}
ctx, err := ContextWithRepositoryScope(ctx, r.refspec, false)
if err != nil {
return nil, 0, err
}
var firstErr error
for i, host := range hosts {
req := r.request(host, http.MethodGet, "referrers", dgst.String())
for _, artifactType := range config.ArtifactTypes {
if err := req.addQuery("artifactType", artifactType); err != nil {
return nil, 0, err
}
}
for k, vs := range config.QueryFilters {
for _, v := range vs {
if err := req.addQuery(k, v); err != nil {
return nil, 0, err
}
}
}
if err := req.addNamespace(r.refspec.Hostname()); err != nil {
return nil, 0, err
}
rc, cl, err := r.open(ctx, req, mediaType, 0, i == len(hosts)-1)
if err != nil {
if !errdefs.IsNotFound(err) {
log.G(ctx).WithError(err).WithField("host", host.Host).Debug("error fetching referrers")
if firstErr == nil {
firstErr = err
}
}
} else {
return rc, cl, nil
}
}
for i, host := range fallbackHosts {
req := r.request(host, http.MethodGet, "manifests", strings.Replace(dgst.String(), ":", "-", 1))
if err := req.addNamespace(r.refspec.Hostname()); err != nil {
return nil, 0, err
}
rc, cl, err := r.open(ctx, req, mediaType, 0, i == len(fallbackHosts)-1)
if err != nil {
if errdefs.IsNotFound(err) {
// Equivalent to empty referrers list
firstErr = err
break
}
log.G(ctx).WithError(err).WithField("host", host.Host).Debug("error fetching referrers via fallback")
if firstErr == nil {
firstErr = err
}
} else {
return rc, cl, nil
}
}
if firstErr == nil {
firstErr = fmt.Errorf("could not be found at any host: %w", errdefs.ErrNotFound)
}
return nil, 0, firstErr
}

View File

@@ -57,6 +57,10 @@ const (
// manifests
HostCapabilityPush
// HostCapabilityReferrers represents the capability to generate a
// list of referrers using the OCI Distribution referrers endpoint.
HostCapabilityReferrers
// Reserved for future capabilities (i.e. search, catalog, remove)
)
@@ -168,7 +172,7 @@ func ConfigureDefaultRegistries(ropts ...RegistryOpt) RegistryHosts {
Host: host,
Scheme: "https",
Path: "/v2",
Capabilities: HostCapabilityPull | HostCapabilityResolve | HostCapabilityPush,
Capabilities: HostCapabilityPull | HostCapabilityResolve | HostCapabilityPush | HostCapabilityReferrers,
}
if config.Client == nil {
@@ -212,10 +216,10 @@ func MatchAllHosts(string) (bool, error) {
// Note: this does not handle matching of ip addresses in octal,
// decimal or hex form.
func MatchLocalhost(host string) (bool, error) {
switch {
case host == "::1":
switch host {
case "::1":
return true, nil
case host == "[::1]":
case "[::1]":
return true, nil
}
h, p, err := net.SplitHostPort(host)

View File

@@ -551,29 +551,33 @@ func (r *request) authorize(ctx context.Context, req *http.Request) error {
return nil
}
func (r *request) addNamespace(ns string) (err error) {
if !r.host.isProxy(ns) {
return nil
}
func (r *request) addQuery(key, value string) (err error) {
var q url.Values
// Parse query
if i := strings.IndexByte(r.path, '?'); i > 0 {
r.path = r.path[:i+1]
q, err = url.ParseQuery(r.path[i+1:])
if p, query, ok := strings.Cut(r.path, "?"); ok {
q, err = url.ParseQuery(query)
if err != nil {
return
}
r.path = p + "?"
} else {
r.path = r.path + "?"
q = url.Values{}
}
q.Add("ns", ns)
q.Add(key, value)
r.path = r.path + q.Encode()
return
}
func (r *request) addNamespace(ns string) error {
if !r.host.isProxy(ns) {
return nil
}
return r.addQuery("ns", ns)
}
type request struct {
method string
path string

View File

@@ -19,6 +19,7 @@ package remotes
import (
"context"
"io"
"net/url"
"github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/core/transfer"
@@ -75,6 +76,10 @@ type FetcherByDigest interface {
FetchByDigest(ctx context.Context, dgst digest.Digest, opts ...FetchByDigestOpts) (io.ReadCloser, ocispec.Descriptor, error)
}
type ReferrersFetcher interface {
FetchReferrers(ctx context.Context, dgst digest.Digest, opts ...FetchReferrersOpt) ([]ocispec.Descriptor, error)
}
// Pusher pushes content
type Pusher interface {
// Push returns a content writer for the given resource identified
@@ -116,3 +121,32 @@ func WithMediaType(mediatype string) FetchByDigestOpts {
return nil
}
}
type FetchReferrersConfig struct {
// ArtifactTypes specifies the artifact types to filter referrers, this can be
// applied to registry queries or filtering the results after fetching.
ArtifactTypes []string
// QueryFilters specifies additional filters which may get sent as query parameters
QueryFilters url.Values
}
type FetchReferrersOpt func(context.Context, *FetchReferrersConfig) error
// WithReferrerArtifactTypes sets the artifact types to filter referrers
func WithReferrerArtifactTypes(artifactTypes ...string) FetchReferrersOpt {
return func(ctx context.Context, cfg *FetchReferrersConfig) error {
cfg.ArtifactTypes = artifactTypes
return nil
}
}
// WithReferrerQueryFilter sets additional query filters for referrer fetching
func WithReferrerQueryFilter(param, value string) FetchReferrersOpt {
return func(ctx context.Context, cfg *FetchReferrersConfig) error {
if cfg.QueryFilters == nil {
cfg.QueryFilters = url.Values{}
}
cfg.QueryFilters.Add(param, value)
return nil
}
}

View File

@@ -140,6 +140,7 @@ func (p *proxySnapshotter) Commit(ctx context.Context, name, key string, opts ..
Snapshotter: p.snapshotterName,
Name: name,
Key: key,
Parent: local.Parent,
Labels: local.Labels,
})
return errgrpc.ToNative(err)

View File

@@ -395,3 +395,11 @@ func FilterInheritedLabels(labels map[string]string) map[string]string {
}
return filtered
}
// WithParent sets the parent of a snapshot
func WithParent(parent string) Opt {
return func(info *Info) error {
info.Parent = parent
return nil
}
}

View File

@@ -23,6 +23,7 @@ import (
"encoding/json"
"errors"
"fmt"
"slices"
"strconv"
"sync"
"sync/atomic"
@@ -35,7 +36,6 @@ import (
"github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/sync/errgroup"
"golang.org/x/sync/semaphore"
"github.com/containerd/containerd/v2/core/content"
"github.com/containerd/containerd/v2/core/diff"
@@ -63,8 +63,10 @@ type unpackerConfig struct {
content content.Store
limiter *semaphore.Weighted
duplicationSuppressor kmutex.KeyedLocker
limiter Limiter
duplicationSuppressor KeyedLocker
unpackLimiter Limiter
}
// Platform represents a platform-specific unpack configuration which includes
@@ -72,10 +74,11 @@ type unpackerConfig struct {
type Platform struct {
Platform platforms.Matcher
SnapshotterKey string
Snapshotter snapshots.Snapshotter
SnapshotOpts []snapshots.Opt
SnapshotterExports map[string]string
SnapshotterKey string
Snapshotter snapshots.Snapshotter
SnapshotOpts []snapshots.Opt
SnapshotterExports map[string]string
SnapshotterCapabilities []string
Applier diff.Applier
ApplyOpts []diff.ApplyOpt
@@ -89,6 +92,20 @@ type Platform struct {
LayerTypes []string
}
// KeyedLocker is an interface for managing job duplication by
// locking on a given key.
type KeyedLocker interface {
Lock(ctx context.Context, key string) error
Unlock(key string)
}
// Limiter interface is used to restrict the number of concurrent operations by
// requiring operations to first acquire from the limiter and release when complete.
type Limiter interface {
Acquire(context.Context, int64) error
Release(int64)
}
type UnpackerOpt func(*unpackerConfig) error
func WithUnpackPlatform(u Platform) UnpackerOpt {
@@ -116,20 +133,27 @@ func WithUnpackPlatform(u Platform) UnpackerOpt {
})
}
func WithLimiter(l *semaphore.Weighted) UnpackerOpt {
func WithLimiter(l Limiter) UnpackerOpt {
return UnpackerOpt(func(c *unpackerConfig) error {
c.limiter = l
return nil
})
}
func WithDuplicationSuppressor(d kmutex.KeyedLocker) UnpackerOpt {
func WithDuplicationSuppressor(d KeyedLocker) UnpackerOpt {
return UnpackerOpt(func(c *unpackerConfig) error {
c.duplicationSuppressor = d
return nil
})
}
func WithUnpackLimiter(l Limiter) UnpackerOpt {
return UnpackerOpt(func(c *unpackerConfig) error {
c.unpackLimiter = l
return nil
})
}
// Unpacker unpacks images by hooking into the image handler process.
// Unpacks happen in the backgrounds and waited on to complete.
type Unpacker struct {
@@ -267,6 +291,14 @@ type unpackConfig struct {
RootFS ocispec.RootFS `json:"rootfs"`
}
type unpackStatus struct {
err error
desc ocispec.Descriptor
bottomF func(bool) error
span *tracing.Span
startAt time.Time
}
func (u *Unpacker) unpack(
h images.Handler,
config ocispec.Descriptor,
@@ -323,7 +355,9 @@ func (u *Unpacker) unpack(
fetchOffset int
fetchC []chan struct{}
fetchErr chan error
fetchErr []chan error
parallel = u.supportParallel(unpack)
)
// If there is an early return, ensure any ongoing
@@ -336,18 +370,26 @@ func (u *Unpacker) unpack(
copy(chainIDs, diffIDs)
chainIDs = identity.ChainIDs(chainIDs)
doUnpackFn := func(i int, desc ocispec.Descriptor) error {
var parent string
if i > 0 {
topHalf := func(i int, desc ocispec.Descriptor, span *tracing.Span, startAt time.Time) (<-chan *unpackStatus, error) {
var (
err error
parent string
chainID string
)
if i > 0 && !parallel {
parent = chainIDs[i-1].String()
}
chainID := chainIDs[i].String()
chainID = chainIDs[i].String()
unlock, err := u.lockSnChainID(ctx, chainID, unpack.SnapshotterKey)
if err != nil {
return err
return nil, err
}
defer unlock()
defer func() {
if err != nil {
unlock()
}
}()
// inherits annotations which are provided as snapshot labels.
snapshotLabels := snapshots.FilterInheritedLabels(desc.Annotations)
@@ -370,23 +412,23 @@ func (u *Unpacker) unpack(
if errdefs.IsAlreadyExists(err) {
if _, err := sn.Stat(ctx, chainID); err != nil {
if !errdefs.IsNotFound(err) {
return fmt.Errorf("failed to stat snapshot %s: %w", chainID, err)
return nil, fmt.Errorf("failed to stat snapshot %s: %w", chainID, err)
}
// Try again, this should be rare, log it
log.G(ctx).WithField("key", key).WithField("chainid", chainID).Debug("extraction snapshot already exists, chain id not found")
} else {
// no need to handle, snapshot now found with chain id
return nil
return nil, nil
}
} else {
return fmt.Errorf("failed to prepare extraction snapshot %q: %w", key, err)
return nil, fmt.Errorf("failed to prepare extraction snapshot %q: %w", key, err)
}
} else {
break
}
}
if err != nil {
return fmt.Errorf("unable to prepare extraction snapshot: %w", err)
return nil, fmt.Errorf("unable to prepare extraction snapshot: %w", err)
}
// Abort the snapshot if commit does not happen
@@ -397,66 +439,137 @@ func (u *Unpacker) unpack(
}
if fetchErr == nil {
fetchErr = make(chan error, 1)
fetchOffset = i
fetchC = make([]chan struct{}, len(layers)-fetchOffset)
for i := range fetchC {
n := len(layers) - fetchOffset
fetchErr = make([]chan error, n)
fetchC = make([]chan struct{}, n)
for i := range n {
fetchC[i] = make(chan struct{})
fetchErr[i] = make(chan error, 1)
}
go func(i int) {
err := u.fetch(ctx, h, layers[i:], fetchC)
if err != nil {
fetchErr <- err
for _, fc := range fetchErr {
fc <- err
close(fc)
}
}
close(fetchErr)
}(i)
}
select {
case <-ctx.Done():
if err = u.acquire(ctx, u.unpackLimiter); err != nil {
cleanup.Do(ctx, abort)
return ctx.Err()
case err := <-fetchErr:
return nil, err
}
resCh := make(chan *unpackStatus, 1)
go func() {
defer func() {
u.release(u.unpackLimiter)
close(resCh)
}()
status := &unpackStatus{
desc: desc,
span: span,
startAt: startAt,
bottomF: func(shouldAbort bool) error {
defer unlock()
if shouldAbort {
cleanup.Do(ctx, abort)
return nil
}
if i > 0 && parallel {
parent = chainIDs[i-1].String()
opts = append(opts, snapshots.WithParent(parent))
}
if err = sn.Commit(ctx, chainID, key, opts...); err != nil {
cleanup.Do(ctx, abort)
if errdefs.IsAlreadyExists(err) {
return nil
}
return fmt.Errorf("failed to commit snapshot %s: %w", key, err)
}
// Set the uncompressed label after the uncompressed
// digest has been verified through apply.
cinfo := content.Info{
Digest: desc.Digest,
Labels: map[string]string{
labels.LabelUncompressed: diffIDs[i].String(),
},
}
if _, err := cs.Update(ctx, cinfo, "labels."+labels.LabelUncompressed); err != nil {
return err
}
return nil
},
}
select {
case <-ctx.Done():
cleanup.Do(ctx, abort)
status.err = ctx.Err()
resCh <- status
return
case err := <-fetchErr[i-fetchOffset]:
if err != nil {
cleanup.Do(ctx, abort)
status.err = err
resCh <- status
return
}
case <-fetchC[i-fetchOffset]:
}
diff, err := a.Apply(ctx, desc, mounts, unpack.ApplyOpts...)
if err != nil {
cleanup.Do(ctx, abort)
return err
status.err = fmt.Errorf("failed to extract layer (%s %s) to %s as %q: %w", desc.MediaType, desc.Digest, unpack.SnapshotterKey, key, err)
resCh <- status
return
}
case <-fetchC[i-fetchOffset]:
}
diff, err := a.Apply(ctx, desc, mounts, unpack.ApplyOpts...)
if err != nil {
cleanup.Do(ctx, abort)
return fmt.Errorf("failed to extract layer (%s %s) to %s as %q: %w", desc.MediaType, desc.Digest, unpack.SnapshotterKey, key, err)
}
if diff.Digest != diffIDs[i] {
cleanup.Do(ctx, abort)
return fmt.Errorf("wrong diff id calculated on extraction %q", diffIDs[i])
}
if err = sn.Commit(ctx, chainID, key, opts...); err != nil {
cleanup.Do(ctx, abort)
if errdefs.IsAlreadyExists(err) {
return nil
if diff.Digest != diffIDs[i] {
cleanup.Do(ctx, abort)
status.err = fmt.Errorf("wrong diff id %q calculated on extraction %q, desc %q", diff.Digest, diffIDs[i], desc.Digest)
resCh <- status
return
}
return fmt.Errorf("failed to commit snapshot %s: %w", key, err)
}
// Set the uncompressed label after the uncompressed
// digest has been verified through apply.
cinfo := content.Info{
Digest: desc.Digest,
Labels: map[string]string{
labels.LabelUncompressed: diff.Digest.String(),
},
}
if _, err := cs.Update(ctx, cinfo, "labels."+labels.LabelUncompressed); err != nil {
return err
}
return nil
resCh <- status
}()
return resCh, nil
}
bottomHalf := func(s *unpackStatus, prevErrs error) error {
var err error
if s.err != nil {
s.bottomF(true)
err = s.err
} else if prevErrs != nil {
s.bottomF(true)
err = fmt.Errorf("aborted")
} else {
err = s.bottomF(false)
}
s.span.SetStatus(err)
s.span.End()
if err == nil {
log.G(ctx).WithFields(log.Fields{
"layer": s.desc.Digest,
"duration": time.Since(s.startAt),
}).Debug("layer unpacked")
}
return err
}
var statusChans []<-chan *unpackStatus
for i, desc := range layers {
_, layerSpan := tracing.StartSpan(ctx, tracing.Name(unpackSpanPrefix, "unpackLayer"))
unpackLayerStart := time.Now()
@@ -465,16 +578,41 @@ func (u *Unpacker) unpack(
tracing.Attribute("layer.media.size", desc.Size),
tracing.Attribute("layer.media.digest", desc.Digest.String()),
)
if err := doUnpackFn(i, desc); err != nil {
layerSpan.SetStatus(err)
layerSpan.End()
return err
statusCh, err := topHalf(i, desc, layerSpan, unpackLayerStart)
if err != nil {
if parallel {
break
} else {
layerSpan.SetStatus(err)
layerSpan.End()
return err
}
}
if statusCh == nil {
// nothing to do, already exists
layerSpan.End()
continue
}
if parallel {
statusChans = append(statusChans, statusCh)
} else {
if err = bottomHalf(<-statusCh, nil); err != nil {
return err
}
}
}
// In parallel mode, snapshots still need to be committed and rebased sequentially
if parallel {
var errs error
for _, sc := range statusChans {
if err := bottomHalf(<-sc, errs); err != nil {
errs = errors.Join(errs, err)
}
}
if errs != nil {
return errs
}
layerSpan.End()
log.G(ctx).WithFields(log.Fields{
"layer": desc.Digest,
"duration": time.Since(unpackLayerStart),
}).Debug("layer unpacked")
}
var chainID string
@@ -494,6 +632,7 @@ func (u *Unpacker) unpack(
log.G(ctx).WithFields(log.Fields{
"config": config.Digest,
"chainID": chainID,
"parallel": parallel,
"duration": time.Since(unpackStart),
}).Debug("image unpacked")
@@ -514,7 +653,7 @@ func (u *Unpacker) fetch(ctx context.Context, h images.Handler, layers []ocispec
ch = done[i]
}
if err := u.acquire(ctx); err != nil {
if err := u.acquire(ctx, u.limiter); err != nil {
return err
}
@@ -523,14 +662,14 @@ func (u *Unpacker) fetch(ctx context.Context, h images.Handler, layers []ocispec
unlock, err := u.lockBlobDescriptor(ctx2, desc)
if err != nil {
u.release()
u.release(u.limiter)
return err
}
_, err = h.Handle(ctx2, desc)
unlock()
u.release()
u.release(u.limiter)
if err != nil && !errors.Is(err, images.ErrSkipDesc) {
return err
@@ -546,18 +685,18 @@ func (u *Unpacker) fetch(ctx context.Context, h images.Handler, layers []ocispec
return eg.Wait()
}
func (u *Unpacker) acquire(ctx context.Context) error {
if u.limiter == nil {
func (u *Unpacker) acquire(ctx context.Context, l Limiter) error {
if l == nil {
return nil
}
return u.limiter.Acquire(ctx, 1)
return l.Acquire(ctx, 1)
}
func (u *Unpacker) release() {
if u.limiter == nil {
func (u *Unpacker) release(l Limiter) {
if l == nil {
return
}
u.limiter.Release(1)
l.Release(1)
}
func (u *Unpacker) lockSnChainID(ctx context.Context, chainID, snapshotter string) (func(), error) {
@@ -590,6 +729,17 @@ func (u *Unpacker) makeBlobDescriptorKey(desc ocispec.Descriptor) string {
return fmt.Sprintf("blob://%v", desc.Digest)
}
func (u *Unpacker) supportParallel(unpack *Platform) bool {
if u.unpackLimiter == nil {
return false
}
if !slices.Contains(unpack.SnapshotterCapabilities, "rebase") {
log.L.Infof("snapshotter does not support rebase capability, unpacking will be sequential")
return false
}
return true
}
func uniquePart() string {
t := time.Now()
var b [3]byte

View File

@@ -29,4 +29,9 @@ const (
// DefaultSnapshotterNSLabel defines the namespace label to check for the
// default snapshotter
DefaultSnapshotterNSLabel = "containerd.io/defaults/snapshotter"
// DefaultSandboxerNSLabel defines the namespace label to check for the
// default sandboxcr
DefaultSandboxerNSLabel = "containerd.io/defaults/sandboxer"
// DefaultSandboxer defines the default sandboxer to use for creating sandboxes.
DefaultSandboxer = "shim"
)

View File

@@ -17,6 +17,23 @@
package defaults
const (
// DefaultRuntime would be a multiple of choices, thus empty
DefaultRuntime = ""
// DefaultRuntime is the default darwin runtime for running containers
DefaultRuntime = "io.containerd.nerdbox.v1"
// DefaultAddress is the default unix socket address
DefaultAddress = "/var/run/containerd/containerd.sock"
// DefaultDebugAddress is the default unix socket address for pprof data
DefaultDebugAddress = "/var/run/containerd/debug.sock"
// DefaultFIFODir is the default location used by client-side cio library
// to store FIFOs.
DefaultFIFODir = "/var/run/containerd/fifo"
// DefaultSnapshotter will set the default snapshotter for the platform.
// Since mounts are not supported on Darwin, use erofs as the default
// which does not require mount support.
DefaultSnapshotter = "erofs"
// DefaultStateDir is the default location used by containerd to store
// transient data
DefaultStateDir = "/var/run/containerd"
// DefaultDiffer will set the default differ for the platform, use the
// erofs differ which does not require mount support.
DefaultDiffer = "erofs"
)

View File

@@ -24,4 +24,7 @@ const (
// DefaultRootDir is the default location used by containerd to store
// persistent data
DefaultRootDir = "/var/lib/containerd"
// DefaultConfigIncludePattern is the default location for drop-in configuration files.
DefaultConfigIncludePattern = "/etc/containerd/conf.d/*.toml"
)

View File

@@ -1,4 +1,4 @@
//go:build unix && !linux
//go:build unix && !linux && !darwin
/*
Copyright The containerd Authors.

View File

@@ -31,6 +31,9 @@ var (
// DefaultConfigDir is the default location for config files.
DefaultConfigDir = filepath.Join(os.Getenv("programfiles"), "containerd")
// DefaultConfigIncludePattern is the default location for drop-in configuration files.
DefaultConfigIncludePattern = filepath.Join(os.Getenv("programfiles"), "containerd\\conf.d\\*.toml")
)
const (

View File

@@ -14,7 +14,7 @@
limitations under the License.
*/
// Package providing utilies to help cleanup
// Package cleanup provides utilies to help cleanup.
package cleanup
import (
@@ -22,31 +22,10 @@ import (
"time"
)
type clearCancel struct {
context.Context
}
func (cc clearCancel) Deadline() (deadline time.Time, ok bool) {
return
}
func (cc clearCancel) Done() <-chan struct{} {
return nil
}
func (cc clearCancel) Err() error {
return nil
}
// Background creates a new context which clears out the parent errors
func Background(ctx context.Context) context.Context {
return clearCancel{ctx}
}
// Do runs the provided function with a context in which the
// errors are cleared out and will timeout after 10 seconds.
func Do(ctx context.Context, do func(context.Context)) {
ctx, cancel := context.WithTimeout(clearCancel{ctx}, 10*time.Second)
ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 10*time.Second)
do(ctx)
cancel()
}

View File

@@ -35,7 +35,7 @@ var invalidUser = User{Uid: invalidID, Gid: invalidID}
// User is a Uid and Gid pair of a user
//
//nolint:revive
//nolint:revive,staticcheck // ST1003: struct field Uid should be UID (staticcheck)
type User struct {
Uid uint32
Gid uint32
@@ -43,7 +43,7 @@ type User struct {
// IDMap contains the mappings of Uids and Gids.
//
//nolint:revive
//nolint:revive,staticcheck // ST1003: struct field Uid should be UID (staticcheck)
type IDMap struct {
UidMap []specs.LinuxIDMapping `json:"UidMap"`
GidMap []specs.LinuxIDMapping `json:"GidMap"`

View File

@@ -292,7 +292,7 @@ func applyNaive(ctx context.Context, root string, r io.Reader, options ApplyOpti
// the layer is also a directory. Then we want to merge them (i.e.
// just apply the metadata from the layer).
if fi, err := os.Lstat(path); err == nil {
if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) {
if !fi.IsDir() || hdr.Typeflag != tar.TypeDir {
if err := os.RemoveAll(path); err != nil {
return 0, err
}
@@ -337,7 +337,7 @@ func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header
case tar.TypeDir:
// Create directory unless it exists as a directory already.
// In that case we just want to merge the two
if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
if fi, err := os.Lstat(path); err != nil || !fi.IsDir() {
if err := mkdir(path, hdrInfo.Mode()); err != nil {
return err
}

View File

@@ -18,6 +18,7 @@ package cio
import (
"context"
"errors"
"fmt"
"io"
"net/url"
@@ -205,16 +206,16 @@ func (c *cio) Wait() {
}
func (c *cio) Close() error {
var lastErr error
var errs []error
for _, closer := range c.closers {
if closer == nil {
continue
}
if err := closer.Close(); err != nil {
lastErr = err
errs = append(errs, err)
}
}
return lastErr
return errors.Join(errs...)
}
func (c *cio) Cancel() {

View File

@@ -19,7 +19,7 @@
package oci
import (
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-spec/specs-go"
)
func defaultMounts() []specs.Mount {

View File

@@ -17,7 +17,7 @@
package oci
import (
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-spec/specs-go"
)
func defaultMounts() []specs.Mount {

View File

@@ -19,17 +19,21 @@ package oci
import (
"bufio"
"context"
"crypto/rand"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io/fs"
"math"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
"github.com/containerd/continuity/fs"
"github.com/containerd/errdefs"
"github.com/containerd/platforms"
"github.com/moby/sys/user"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
@@ -653,18 +657,18 @@ func WithUser(userstr string) SpecOpts {
s.Process.User.UID, s.Process.User.GID = uid, gid
return nil
}
f := func(root string) error {
f := func(root fs.FS) error {
if username != "" {
user, err := UserFromPath(root, func(u user.User) bool {
usr, err := UserFromFS(root, func(u user.User) bool {
return u.Name == username
})
if err != nil {
return err
}
uid = uint32(user.Uid)
uid = uint32(usr.Uid)
}
if groupname != "" {
gid, err = GIDFromPath(root, func(g user.Group) bool {
gid, err = GIDFromFS(root, func(g user.Group) bool {
return g.Name == groupname
})
if err != nil {
@@ -678,7 +682,12 @@ func WithUser(userstr string) SpecOpts {
if !isRootfsAbs(s.Root.Path) {
return errors.New("rootfs absolute path is required")
}
return f(s.Root.Path)
rootfs, err := os.OpenRoot(s.Root.Path)
if err != nil {
return err
}
defer rootfs.Close()
return f(rootfs.FS())
}
if c.Snapshotter == "" {
return errors.New("no snapshotter set for container")
@@ -696,7 +705,7 @@ func WithUser(userstr string) SpecOpts {
// from the container's rootfs. Since the option does read operation
// only, we append ReadOnly mount option to prevent the Linux kernel
// from syncing whole filesystem in umount syscall.
return mount.WithReadonlyTempMount(ctx, mounts, f)
return withReadonlyFS(ctx, client, mounts, f)
default:
return fmt.Errorf("invalid USER value %s", userstr)
}
@@ -724,25 +733,30 @@ func WithUserID(uid uint32) SpecOpts {
defer ensureAdditionalGids(s)
setProcess(s)
s.Process.User.AdditionalGids = nil
setUser := func(root string) error {
user, err := UserFromPath(root, func(u user.User) bool {
setUser := func(root fs.FS) error {
usr, err := UserFromFS(root, func(u user.User) bool {
return u.Uid == int(uid)
})
if err != nil {
if os.IsNotExist(err) || err == ErrNoUsersFound {
if os.IsNotExist(err) || errors.Is(err, ErrNoUsersFound) {
s.Process.User.UID, s.Process.User.GID = uid, 0
return nil
}
return err
}
s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid)
s.Process.User.UID, s.Process.User.GID = uint32(usr.Uid), uint32(usr.Gid)
return nil
}
if c.Snapshotter == "" && c.SnapshotKey == "" {
if !isRootfsAbs(s.Root.Path) {
return errors.New("rootfs absolute path is required")
}
return setUser(s.Root.Path)
rootfs, err := os.OpenRoot(s.Root.Path)
if err != nil {
return err
}
defer rootfs.Close()
return setUser(rootfs.FS())
}
if c.Snapshotter == "" {
return errors.New("no snapshotter set for container")
@@ -760,7 +774,7 @@ func WithUserID(uid uint32) SpecOpts {
// from the container's rootfs. Since the option does read operation
// only, we append ReadOnly mount option to prevent the Linux kernel
// from syncing whole filesystem in umount syscall.
return mount.WithReadonlyTempMount(ctx, mounts, setUser)
return withReadonlyFS(ctx, client, mounts, setUser)
}
}
@@ -776,21 +790,26 @@ func WithUsername(username string) SpecOpts {
setProcess(s)
s.Process.User.AdditionalGids = nil
if s.Linux != nil {
setUser := func(root string) error {
user, err := UserFromPath(root, func(u user.User) bool {
setUser := func(root fs.FS) error {
usr, err := UserFromFS(root, func(u user.User) bool {
return u.Name == username
})
if err != nil {
return err
}
s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid)
s.Process.User.UID, s.Process.User.GID = uint32(usr.Uid), uint32(usr.Gid)
return nil
}
if c.Snapshotter == "" && c.SnapshotKey == "" {
if !isRootfsAbs(s.Root.Path) {
return errors.New("rootfs absolute path is required")
}
return setUser(s.Root.Path)
rootfs, err := os.OpenRoot(s.Root.Path)
if err != nil {
return err
}
defer rootfs.Close()
return setUser(rootfs.FS())
}
if c.Snapshotter == "" {
return errors.New("no snapshotter set for container")
@@ -808,7 +827,7 @@ func WithUsername(username string) SpecOpts {
// from the container's rootfs. Since the option does read operation
// only, we append ReadOnly mount option to prevent the Linux kernel
// from syncing whole filesystem in umount syscall.
return mount.WithReadonlyTempMount(ctx, mounts, setUser)
return withReadonlyFS(ctx, client, mounts, setUser)
} else if s.Windows != nil {
s.Process.User.Username = username
} else {
@@ -829,25 +848,25 @@ func WithAdditionalGIDs(userstr string) SpecOpts {
}
setProcess(s)
s.Process.User.AdditionalGids = nil
setAdditionalGids := func(root string) error {
setAdditionalGids := func(root fs.FS) error {
defer ensureAdditionalGids(s)
var username string
uid, err := strconv.Atoi(userstr)
if err == nil {
user, err := UserFromPath(root, func(u user.User) bool {
usr, err := UserFromFS(root, func(u user.User) bool {
return u.Uid == uid
})
if err != nil {
if os.IsNotExist(err) || err == ErrNoUsersFound {
if os.IsNotExist(err) || errors.Is(err, ErrNoUsersFound) {
return nil
}
return err
}
username = user.Name
username = usr.Name
} else {
username = userstr
}
gids, err := getSupplementalGroupsFromPath(root, func(g user.Group) bool {
gids, err := getSupplementalGroupsFromFS(root, func(g user.Group) bool {
// we only want supplemental groups
if g.Name == username {
return false
@@ -872,7 +891,12 @@ func WithAdditionalGIDs(userstr string) SpecOpts {
if !isRootfsAbs(s.Root.Path) {
return errors.New("rootfs absolute path is required")
}
return setAdditionalGids(s.Root.Path)
rootfs, err := os.OpenRoot(s.Root.Path)
if err != nil {
return err
}
defer rootfs.Close()
return setAdditionalGids(rootfs.FS())
}
if c.Snapshotter == "" {
return errors.New("no snapshotter set for container")
@@ -890,10 +914,42 @@ func WithAdditionalGIDs(userstr string) SpecOpts {
// from the container's rootfs. Since the option does read operation
// only, we append ReadOnly mount option to prevent the Linux kernel
// from syncing whole filesystem in umount syscall.
return mount.WithReadonlyTempMount(ctx, mounts, setAdditionalGids)
return withReadonlyFS(ctx, client, mounts, setAdditionalGids)
}
}
func withReadonlyFS(ctx context.Context, client Client, mounts []mount.Mount, fn func(fs.FS) error) error {
var mm mount.Manager
if cwm, ok := client.(interface{ MountManager() mount.Manager }); ok {
mm = cwm.MountManager()
}
if mm != nil {
t := time.Now()
var b [3]byte
// Ignore read failures, just decreases uniqueness
rand.Read(b[:])
id := fmt.Sprintf("readonly-fs-%d-%s", t.Nanosecond(), base64.URLEncoding.EncodeToString(b[:]))
// TODO: Use temporary once the read only can be optimized for single bind mounts
active, err := mm.Activate(ctx, id, mounts)
if err == nil {
defer mm.Deactivate(ctx, id)
mounts = active.System
} else if !errors.Is(err, errdefs.ErrNotImplemented) {
return fmt.Errorf("failed to activate mounts: %w", err)
}
}
return mount.WithReadonlyTempMount(ctx, mounts, func(root string) error {
rootfs, err := os.OpenRoot(root)
if err != nil {
return err
}
defer rootfs.Close()
return fn(rootfs.FS())
})
}
// WithAppendAdditionalGroups append additional groups within the container.
// The passed in groups can be either a gid or a groupname.
func WithAppendAdditionalGroups(groups ...string) SpecOpts {
@@ -903,16 +959,21 @@ func WithAppendAdditionalGroups(groups ...string) SpecOpts {
return nil
}
setProcess(s)
setAdditionalGids := func(root string) error {
setAdditionalGids := func(root fs.FS) error {
defer ensureAdditionalGids(s)
gpath, err := fs.RootPath(root, "/etc/group")
if err != nil {
return err
}
ugroups, groupErr := user.ParseGroupFile(gpath)
if groupErr != nil && !os.IsNotExist(groupErr) {
var ugroups []user.Group
f, groupErr := root.Open("etc/group")
if groupErr == nil {
defer f.Close()
ugroups, groupErr = user.ParseGroup(f)
if groupErr != nil {
return groupErr
}
} else if !os.IsNotExist(groupErr) {
return groupErr
}
groupMap := make(map[string]user.Group)
for _, group := range ugroups {
groupMap[group.Name] = group
@@ -940,7 +1001,12 @@ func WithAppendAdditionalGroups(groups ...string) SpecOpts {
if !filepath.IsAbs(s.Root.Path) {
return errors.New("rootfs absolute path is required")
}
return setAdditionalGids(s.Root.Path)
rootfs, err := os.OpenRoot(s.Root.Path)
if err != nil {
return err
}
defer rootfs.Close()
return setAdditionalGids(rootfs.FS())
}
if c.Snapshotter == "" {
return errors.New("no snapshotter set for container")
@@ -958,7 +1024,7 @@ func WithAppendAdditionalGroups(groups ...string) SpecOpts {
// from the container's rootfs. Since the option does read operation
// only, we append ReadOnly mount option to prevent the Linux kernel
// from syncing whole filesystem in umount syscall.
return mount.WithReadonlyTempMount(ctx, mounts, setAdditionalGids)
return withReadonlyFS(ctx, client, mounts, setAdditionalGids)
}
}
@@ -1065,11 +1131,23 @@ var ErrNoUsersFound = errors.New("no users found")
// UserFromPath inspects the user object using /etc/passwd in the specified rootfs.
// filter can be nil.
func UserFromPath(root string, filter func(user.User) bool) (user.User, error) {
ppath, err := fs.RootPath(root, "/etc/passwd")
r, err := os.OpenRoot(root)
if err != nil {
return user.User{}, err
}
users, err := user.ParsePasswdFileFilter(ppath, filter)
defer r.Close()
return UserFromFS(r.FS(), filter)
}
// UserFromFS inspects the user object using /etc/passwd in the specified fs.FS.
// filter can be nil.
func UserFromFS(root fs.FS, filter func(user.User) bool) (user.User, error) {
f, err := root.Open("etc/passwd")
if err != nil {
return user.User{}, err
}
defer f.Close()
users, err := user.ParsePasswdFilter(f, filter)
if err != nil {
return user.User{}, err
}
@@ -1085,11 +1163,23 @@ var ErrNoGroupsFound = errors.New("no groups found")
// GIDFromPath inspects the GID using /etc/group in the specified rootfs.
// filter can be nil.
func GIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err error) {
gpath, err := fs.RootPath(root, "/etc/group")
r, err := os.OpenRoot(root)
if err != nil {
return 0, err
}
groups, err := user.ParseGroupFileFilter(gpath, filter)
defer r.Close()
return GIDFromFS(r.FS(), filter)
}
// GIDFromFS inspects the GID using /etc/group in the specified fs.FS.
// filter can be nil.
func GIDFromFS(root fs.FS, filter func(user.Group) bool) (gid uint32, err error) {
f, err := root.Open("etc/group")
if err != nil {
return 0, err
}
defer f.Close()
groups, err := user.ParseGroupFilter(f, filter)
if err != nil {
return 0, err
}
@@ -1100,12 +1190,13 @@ func GIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err err
return uint32(g.Gid), nil
}
func getSupplementalGroupsFromPath(root string, filter func(user.Group) bool) ([]uint32, error) {
gpath, err := fs.RootPath(root, "/etc/group")
func getSupplementalGroupsFromFS(root fs.FS, filter func(user.Group) bool) ([]uint32, error) {
f, err := root.Open("etc/group")
if err != nil {
return []uint32{}, err
}
groups, err := user.ParseGroupFileFilter(gpath, filter)
defer f.Close()
groups, err := user.ParseGroupFilter(f, filter)
if err != nil {
return []uint32{}, err
}
@@ -1308,16 +1399,18 @@ func WithDefaultUnixDevices(_ context.Context, _ Client, _ *containers.Container
}
// WithPrivileged sets up options for a privileged container
var WithPrivileged = Compose(
WithAllCurrentCapabilities,
WithMaskedPaths(nil),
WithReadonlyPaths(nil),
WithWriteableSysfs,
WithWriteableCgroupfs,
WithSelinuxLabel(""),
WithApparmorProfile(""),
WithSeccompUnconfined,
)
func WithPrivileged(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
return Compose(
WithAllCurrentCapabilities,
WithMaskedPaths(nil),
WithReadonlyPaths(nil),
WithWriteableSysfs,
WithWriteableCgroupfs,
WithSelinuxLabel(""),
WithApparmorProfile(""),
WithSeccompUnconfined,
)(ctx, client, c, s)
}
// WithWindowsHyperV sets the Windows.HyperV section for HyperV isolation of containers.
func WithWindowsHyperV(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
@@ -1483,9 +1576,12 @@ func WithWindowsDevice(idType, id string) SpecOpts {
}
}
// WithMemorySwap sets the container's swap in bytes
// WithMemorySwap sets the container's swap in bytes. It is a no-op on non-Linux specs.
func WithMemorySwap(swap int64) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if s.Linux == nil {
return nil
}
setResources(s)
if s.Linux.Resources.Memory == nil {
s.Linux.Resources.Memory = &specs.LinuxMemory{}
@@ -1495,9 +1591,12 @@ func WithMemorySwap(swap int64) SpecOpts {
}
}
// WithPidsLimit sets the container's pid limit or maximum
// WithPidsLimit sets the container's pid limit or maximum. It is a no-op on non-Linux specs.
func WithPidsLimit(limit int64) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if s.Linux == nil {
return nil
}
setResources(s)
if s.Linux.Resources.Pids == nil {
s.Linux.Resources.Pids = &specs.LinuxPids{}
@@ -1507,45 +1606,61 @@ func WithPidsLimit(limit int64) SpecOpts {
}
}
// WithBlockIO sets the container's blkio parameters
// WithBlockIO sets the container's blkio parameters. It is a no-op on non-Linux specs.
func WithBlockIO(blockio *specs.LinuxBlockIO) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if s.Linux == nil {
return nil
}
setResources(s)
s.Linux.Resources.BlockIO = blockio
return nil
}
}
// WithCPUShares sets the container's cpu shares
// WithCPUShares sets the container's cpu shares. It is a no-op on non-Linux specs.
func WithCPUShares(shares uint64) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if s.Linux == nil {
return nil
}
setCPU(s)
s.Linux.Resources.CPU.Shares = &shares
return nil
}
}
// WithCPUs sets the container's cpus/cores for use by the container
// WithCPUs sets the container's cpus/cores for use by the container. It is a no-op on non-Linux specs.
func WithCPUs(cpus string) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if s.Linux == nil {
return nil
}
setCPU(s)
s.Linux.Resources.CPU.Cpus = cpus
return nil
}
}
// WithCPUsMems sets the container's cpu mems for use by the container
// WithCPUsMems sets the container's cpu mems for use by the container. It is a no-op on non-Linux specs.
func WithCPUsMems(mems string) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if s.Linux == nil {
return nil
}
setCPU(s)
s.Linux.Resources.CPU.Mems = mems
return nil
}
}
// WithCPUCFS sets the container's Completely fair scheduling (CFS) quota and period
// WithCPUCFS sets the container's Completely fair scheduling (CFS) quota and period.
// It is a no-op on non-Linux specs.
func WithCPUCFS(quota int64, period uint64) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if s.Linux == nil {
return nil
}
setCPU(s)
s.Linux.Resources.CPU.Quota = &quota
s.Linux.Resources.CPU.Period = &period
@@ -1553,9 +1668,12 @@ func WithCPUCFS(quota int64, period uint64) SpecOpts {
}
}
// WithCPUBurst sets the container's cpu burst
// WithCPUBurst sets the container's cpu burst. It is a no-op on non-Linux specs.
func WithCPUBurst(burst uint64) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if s.Linux == nil {
return nil
}
setCPU(s)
s.Linux.Resources.CPU.Burst = &burst
return nil
@@ -1563,8 +1681,12 @@ func WithCPUBurst(burst uint64) SpecOpts {
}
// WithCPURT sets the container's realtime scheduling (RT) runtime and period.
// It is a no-op on non-Linux specs.
func WithCPURT(runtime int64, period uint64) SpecOpts {
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
if s.Linux == nil {
return nil
}
setCPU(s)
s.Linux.Resources.CPU.RealtimeRuntime = &runtime
s.Linux.Resources.CPU.RealtimePeriod = &period
@@ -1590,9 +1712,12 @@ func WithRdt(closID, l3CacheSchema, memBwSchema string) SpecOpts {
}
// WithWindowsCPUCount sets the `Windows.Resources.CPU.Count` section to the
// `count` specified.
// `count` specified. It is a no-op for non-Windows specs.
func WithWindowsCPUCount(count uint64) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
if s.Windows == nil {
return nil
}
setCPUWindows(s)
s.Windows.Resources.CPU.Count = &count
return nil
@@ -1600,9 +1725,12 @@ func WithWindowsCPUCount(count uint64) SpecOpts {
}
// WithWindowsCPUShares sets the `Windows.Resources.CPU.Shares` section to the
// `shares` specified.
// `shares` specified. It is a no-op for non-Windows specs.
func WithWindowsCPUShares(shares uint16) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
if s.Windows == nil {
return nil
}
setCPUWindows(s)
s.Windows.Resources.CPU.Shares = &shares
return nil
@@ -1610,9 +1738,12 @@ func WithWindowsCPUShares(shares uint16) SpecOpts {
}
// WithWindowsCPUMaximum sets the `Windows.Resources.CPU.Maximum` section to the
// `max` specified.
// `max` specified. It is a no-op for non-Windows specs.
func WithWindowsCPUMaximum(max uint16) SpecOpts {
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
if s.Windows == nil {
return nil
}
setCPUWindows(s)
s.Windows.Resources.CPU.Maximum = &max
return nil

View File

@@ -61,8 +61,8 @@ func WithDevices(devicePath, containerPath, permissions string) SpecOpts {
}
// WithAllCurrentCapabilities propagates the effective capabilities of the caller process to the container process.
// The capability set may differ from WithAllKnownCapabilities when running in a container.
var WithAllCurrentCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
// The capability set may differ from [WithAllKnownCapabilities] when running in a container.
func WithAllCurrentCapabilities(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
caps, err := cap.Current()
if err != nil {
return err
@@ -70,12 +70,11 @@ var WithAllCurrentCapabilities = func(ctx context.Context, client Client, c *con
return WithCapabilities(caps)(ctx, client, c, s)
}
// WithAllKnownCapabilities sets all the known linux capabilities for the container process
var WithAllKnownCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
caps := cap.Known()
return WithCapabilities(caps)(ctx, client, c, s)
// WithAllKnownCapabilities sets all the known linux capabilities for the container process.
func WithAllKnownCapabilities(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
return WithCapabilities(cap.Known())(ctx, client, c, s)
}
func escapeAndCombineArgs(args []string) string {
func escapeAndCombineArgs([]string) string {
panic("not supported")
}

View File

@@ -25,12 +25,12 @@ import (
)
// WithAllCurrentCapabilities propagates the effective capabilities of the caller process to the container process.
// The capability set may differ from WithAllKnownCapabilities when running in a container.
var WithAllCurrentCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
// The capability set may differ from [WithAllKnownCapabilities] when running in a container.
func WithAllCurrentCapabilities(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
return WithCapabilities(nil)(ctx, client, c, s)
}
// WithAllKnownCapabilities sets all the known linux capabilities for the container process
var WithAllKnownCapabilities = func(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
// WithAllKnownCapabilities sets all the known linux capabilities for the container process.
func WithAllKnownCapabilities(ctx context.Context, client Client, c *containers.Container, s *Spec) error {
return WithCapabilities(nil)(ctx, client, c, s)
}

View File

@@ -25,7 +25,7 @@ import (
"path/filepath"
"github.com/moby/sys/userns"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
)
@@ -55,7 +55,7 @@ func getDevices(path, containerPath string) ([]specs.LinuxDevice, error) {
dev, err := DeviceFromPath(path)
if err != nil {
// wrap error with detailed path and container path when it is ErrNotADevice
if err == ErrNotADevice {
if errors.Is(err, ErrNotADevice) {
return nil, fmt.Errorf("get device path: %q containerPath: %q error: %w", path, containerPath, err)
}
return nil, err
@@ -103,7 +103,7 @@ func getDevices(path, containerPath string) ([]specs.LinuxDevice, error) {
default:
device, err := DeviceFromPath(filepath.Join(path, f.Name()))
if err != nil {
if err == ErrNotADevice {
if errors.Is(err, ErrNotADevice) {
continue
}
if os.IsNotExist(err) {

View File

@@ -20,7 +20,6 @@ import (
"errors"
"fmt"
"os"
"runtime"
"strconv"
"strings"
"syscall"
@@ -75,21 +74,6 @@ func UnshareAfterEnterUserns(uidMap, gidMap string, unshareFlags uintptr, f func
return fmt.Errorf("kernel doesn't support CLONE_PIDFD")
}
// Since go1.23.{0,1} has double close issue, we should dup it before using it.
//
// References:
// - https://github.com/golang/go/issues/68984
// - https://github.com/golang/go/milestone/371
if goVer := runtime.Version(); goVer == "go1.23.0" || goVer == "go1.23.1" {
dupPidfd, err := unix.FcntlInt(uintptr(pidfd), syscall.F_DUPFD_CLOEXEC, 0)
if err != nil {
proc.Kill()
proc.Wait()
return fmt.Errorf("failed to dupfd: %w", err)
}
pidfd = dupPidfd
}
defer unix.Close(pidfd)
defer func() {

View File

@@ -139,6 +139,9 @@ func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest,
return err
}
if err := syncDir(filepath.Dir(target)); err != nil {
return err
}
// Enable content blob integrity verification if supported
if w.s.integritySupported {

View File

@@ -0,0 +1,37 @@
//go:build !windows
/*
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 local
import (
"fmt"
"os"
)
func syncDir(dir string) error {
dirF, err := os.Open(dir)
if err != nil {
return fmt.Errorf("failed to open dir %s: %w", dir, err)
}
err = dirF.Sync()
dirF.Close()
if err != nil {
return fmt.Errorf("failed to sync dir %s: %w", dir, err)
}
return nil
}

View File

@@ -0,0 +1,22 @@
/*
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 local
// sync dir doesn't support in windows
func syncDir(dir string) error {
return nil
}

View File

@@ -77,6 +77,10 @@ const (
ShimPlugin plugin.Type = "io.containerd.shim.v1"
// HTTPHandler implements an http handler
HTTPHandler plugin.Type = "io.containerd.http.v1"
// MountManagerPlugin implements the mount manager interface
MountManagerPlugin plugin.Type = "io.containerd.mount-manager.v1"
// MountHandlerPlugin implements the mount handler interface
MountHandlerPlugin plugin.Type = "io.containerd.mount-handler.v1"
)
const (

View File

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

View File

@@ -11,7 +11,13 @@ linters:
- misspell
disable:
- errcheck
# Continue supporting deprecated CNI conf formats (ref: https://github.com/containernetworking/cni/pull/1052#issuecomment-1922233640)
exclusions:
rules:
- path: opts.go
linters:
- staticcheck
text: "SA1019:"
# FIXME: re-enable after fixing GoDoc in this repository
#issues:
# include:

View File

@@ -66,9 +66,9 @@ func WithPluginConfDir(dir string) Opt {
// WithPluginMaxConfNum can be used to configure the
// max cni plugin config file num.
func WithPluginMaxConfNum(max int) Opt {
func WithPluginMaxConfNum(maxConfigs int) Opt {
return func(c *libcni) error {
c.pluginMaxConfNum = max
c.pluginMaxConfNum = maxConfigs
return nil
}
}
@@ -209,7 +209,7 @@ func WithAllConf(c *libcni) error {
// loadFromConfDir detects network config files from the
// configured cni config directory and load them. max is
// the maximum network config to load (max i<= 0 means no limit).
func loadFromConfDir(c *libcni, max int) error {
func loadFromConfDir(c *libcni, maxConfigs int) error {
files, err := cnilibrary.ConfFiles(c.pluginConfDir, []string{".conf", ".conflist", ".json"})
switch {
case err != nil:
@@ -245,7 +245,6 @@ func loadFromConfDir(c *libcni, max int) error {
if conf.Network.Type == "" {
return fmt.Errorf("network type not found in %s: %w", confFile, ErrInvalidConfig)
}
confList, err = cnilibrary.ConfListFromConf(conf)
if err != nil {
return fmt.Errorf("failed to convert CNI config file %s to CNI config list: %v: %w", confFile, err, ErrInvalidConfig)
@@ -261,7 +260,7 @@ func loadFromConfDir(c *libcni, max int) error {
ifName: getIfName(c.prefix, i),
})
i++
if i == max {
if i == maxConfigs {
break
}
}

19
vendor/modules.txt vendored
View File

@@ -325,7 +325,7 @@ github.com/containerd/cgroups/v3/cgroup2/stats
# github.com/containerd/console v1.0.5
## explicit; go 1.13
github.com/containerd/console
# github.com/containerd/containerd/api v1.9.0
# github.com/containerd/containerd/api v1.10.0
## explicit; go 1.23.0
github.com/containerd/containerd/api/events
github.com/containerd/containerd/api/runtime/sandbox/v1
@@ -336,6 +336,7 @@ github.com/containerd/containerd/api/services/events/v1
github.com/containerd/containerd/api/services/images/v1
github.com/containerd/containerd/api/services/introspection/v1
github.com/containerd/containerd/api/services/leases/v1
github.com/containerd/containerd/api/services/mounts/v1
github.com/containerd/containerd/api/services/namespaces/v1
github.com/containerd/containerd/api/services/sandbox/v1
github.com/containerd/containerd/api/services/snapshots/v1
@@ -348,8 +349,8 @@ github.com/containerd/containerd/api/types/runc/options
github.com/containerd/containerd/api/types/runtimeoptions/v1
github.com/containerd/containerd/api/types/task
github.com/containerd/containerd/api/types/transfer
# github.com/containerd/containerd/v2 v2.1.5
## explicit; go 1.23.0
# github.com/containerd/containerd/v2 v2.2.0
## explicit; go 1.24.3
github.com/containerd/containerd/v2/client
github.com/containerd/containerd/v2/cmd/containerd/server/config
github.com/containerd/containerd/v2/contrib/nvidia
@@ -371,6 +372,7 @@ github.com/containerd/containerd/v2/core/leases/proxy
github.com/containerd/containerd/v2/core/metadata
github.com/containerd/containerd/v2/core/metadata/boltutil
github.com/containerd/containerd/v2/core/mount
github.com/containerd/containerd/v2/core/mount/proxy
github.com/containerd/containerd/v2/core/remotes
github.com/containerd/containerd/v2/core/remotes/docker
github.com/containerd/containerd/v2/core/remotes/docker/auth
@@ -442,7 +444,7 @@ github.com/containerd/errdefs/pkg/internal/types
# github.com/containerd/fifo v1.1.0
## explicit; go 1.18
github.com/containerd/fifo
# github.com/containerd/go-cni v1.1.12
# github.com/containerd/go-cni v1.1.13
## explicit; go 1.21
github.com/containerd/go-cni
# github.com/containerd/go-runc v1.1.0
@@ -485,8 +487,8 @@ github.com/containernetworking/cni/pkg/types/create
github.com/containernetworking/cni/pkg/types/internal
github.com/containernetworking/cni/pkg/utils
github.com/containernetworking/cni/pkg/version
# github.com/containernetworking/plugins v1.7.1
## explicit; go 1.23.0
# github.com/containernetworking/plugins v1.8.0
## explicit; go 1.24.2
github.com/containernetworking/plugins/pkg/ns
# github.com/coreos/go-semver v0.3.1
## explicit; go 1.8
@@ -1791,10 +1793,9 @@ pgregory.net/rapid
# resenje.org/singleflight v0.4.3
## explicit; go 1.18
resenje.org/singleflight
# sigs.k8s.io/yaml v1.4.0
## explicit; go 1.12
# sigs.k8s.io/yaml v1.6.0
## explicit; go 1.22
sigs.k8s.io/yaml
sigs.k8s.io/yaml/goyaml.v2
# tags.cncf.io/container-device-interface v1.0.1
## explicit; go 1.20
tags.cncf.io/container-device-interface/internal/validation

12
vendor/sigs.k8s.io/yaml/.travis.yml generated vendored
View File

@@ -1,12 +0,0 @@
language: go
arch: arm64
dist: focal
go: 1.15.x
script:
- diff -u <(echo -n) <(gofmt -d *.go)
- diff -u <(echo -n) <(golint $(go list -e ./...) | grep -v YAMLToJSON)
- GO111MODULE=on go vet .
- GO111MODULE=on go test -v -race ./...
- git diff --exit-code
install:
- GO111MODULE=off go get golang.org/x/lint/golint

View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://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
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.

View File

@@ -1,31 +0,0 @@
The following files were ported to Go from C files of libyaml, and thus
are still covered by their original copyright and license:
apic.go
emitterc.go
parserc.go
readerc.go
scannerc.go
writerc.go
yamlh.go
yamlprivateh.go
Copyright (c) 2006 Kirill Simonov
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

@@ -1,13 +0,0 @@
Copyright 2011-2016 Canonical Ltd.
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.

View File

@@ -1,24 +0,0 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- dims
- jpbetz
- smarterclayton
- deads2k
- sttts
- liggitt
- natasha41575
- knverey
reviewers:
- dims
- thockin
- jpbetz
- smarterclayton
- deads2k
- derekwaynecarr
- mikedanese
- liggitt
- sttts
- tallclair
labels:
- sig/api-machinery

View File

@@ -1,143 +0,0 @@
# go-yaml fork
This package is a fork of the go-yaml library and is intended solely for consumption
by kubernetes projects. In this fork, we plan to support only critical changes required for
kubernetes, such as small bug fixes and regressions. Larger, general-purpose feature requests
should be made in the upstream go-yaml library, and we will reject such changes in this fork
unless we are pulling them from upstream.
This fork is based on v2.4.0: https://github.com/go-yaml/yaml/releases/tag/v2.4.0
# YAML support for the Go language
Introduction
------------
The yaml package enables Go programs to comfortably encode and decode YAML
values. It was developed within [Canonical](https://www.canonical.com) as
part of the [juju](https://juju.ubuntu.com) project, and is based on a
pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
C library to parse and generate YAML data quickly and reliably.
Compatibility
-------------
The yaml package supports most of YAML 1.1 and 1.2, including support for
anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
implemented, and base-60 floats from YAML 1.1 are purposefully not
supported since they're a poor design and are gone in YAML 1.2.
Installation and usage
----------------------
The import path for the package is *gopkg.in/yaml.v2*.
To install it, run:
go get gopkg.in/yaml.v2
API documentation
-----------------
If opened in a browser, the import path itself leads to the API documentation:
* [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
API stability
-------------
The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
License
-------
The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details.
Example
-------
```Go
package main
import (
"fmt"
"log"
"gopkg.in/yaml.v2"
)
var data = `
a: Easy!
b:
c: 2
d: [3, 4]
`
// Note: struct fields must be public in order for unmarshal to
// correctly populate the data.
type T struct {
A string
B struct {
RenamedC int `yaml:"c"`
D []int `yaml:",flow"`
}
}
func main() {
t := T{}
err := yaml.Unmarshal([]byte(data), &t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t:\n%v\n\n", t)
d, err := yaml.Marshal(&t)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- t dump:\n%s\n\n", string(d))
m := make(map[interface{}]interface{})
err = yaml.Unmarshal([]byte(data), &m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m:\n%v\n\n", m)
d, err = yaml.Marshal(&m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m dump:\n%s\n\n", string(d))
}
```
This example will generate the following output:
```
--- t:
{Easy! {2 [3 4]}}
--- t dump:
a: Easy!
b:
c: 2
d: [3, 4]
--- m:
map[a:Easy! b:map[c:2 d:[3 4]]]
--- m dump:
a: Easy!
b:
c: 2
d:
- 3
- 4
```

View File

@@ -1,744 +0,0 @@
package yaml
import (
"io"
)
func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
//fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
// Check if we can move the queue at the beginning of the buffer.
if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
if parser.tokens_head != len(parser.tokens) {
copy(parser.tokens, parser.tokens[parser.tokens_head:])
}
parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
parser.tokens_head = 0
}
parser.tokens = append(parser.tokens, *token)
if pos < 0 {
return
}
copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
parser.tokens[parser.tokens_head+pos] = *token
}
// Create a new parser object.
func yaml_parser_initialize(parser *yaml_parser_t) bool {
*parser = yaml_parser_t{
raw_buffer: make([]byte, 0, input_raw_buffer_size),
buffer: make([]byte, 0, input_buffer_size),
}
return true
}
// Destroy a parser object.
func yaml_parser_delete(parser *yaml_parser_t) {
*parser = yaml_parser_t{}
}
// String read handler.
func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
if parser.input_pos == len(parser.input) {
return 0, io.EOF
}
n = copy(buffer, parser.input[parser.input_pos:])
parser.input_pos += n
return n, nil
}
// Reader read handler.
func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
return parser.input_reader.Read(buffer)
}
// Set a string input.
func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
if parser.read_handler != nil {
panic("must set the input source only once")
}
parser.read_handler = yaml_string_read_handler
parser.input = input
parser.input_pos = 0
}
// Set a file input.
func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
if parser.read_handler != nil {
panic("must set the input source only once")
}
parser.read_handler = yaml_reader_read_handler
parser.input_reader = r
}
// Set the source encoding.
func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
if parser.encoding != yaml_ANY_ENCODING {
panic("must set the encoding only once")
}
parser.encoding = encoding
}
var disableLineWrapping = false
// Create a new emitter object.
func yaml_emitter_initialize(emitter *yaml_emitter_t) {
*emitter = yaml_emitter_t{
buffer: make([]byte, output_buffer_size),
raw_buffer: make([]byte, 0, output_raw_buffer_size),
states: make([]yaml_emitter_state_t, 0, initial_stack_size),
events: make([]yaml_event_t, 0, initial_queue_size),
}
if disableLineWrapping {
emitter.best_width = -1
}
}
// Destroy an emitter object.
func yaml_emitter_delete(emitter *yaml_emitter_t) {
*emitter = yaml_emitter_t{}
}
// String write handler.
func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
*emitter.output_buffer = append(*emitter.output_buffer, buffer...)
return nil
}
// yaml_writer_write_handler uses emitter.output_writer to write the
// emitted text.
func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
_, err := emitter.output_writer.Write(buffer)
return err
}
// Set a string output.
func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
if emitter.write_handler != nil {
panic("must set the output target only once")
}
emitter.write_handler = yaml_string_write_handler
emitter.output_buffer = output_buffer
}
// Set a file output.
func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
if emitter.write_handler != nil {
panic("must set the output target only once")
}
emitter.write_handler = yaml_writer_write_handler
emitter.output_writer = w
}
// Set the output encoding.
func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
if emitter.encoding != yaml_ANY_ENCODING {
panic("must set the output encoding only once")
}
emitter.encoding = encoding
}
// Set the canonical output style.
func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
emitter.canonical = canonical
}
//// Set the indentation increment.
func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
if indent < 2 || indent > 9 {
indent = 2
}
emitter.best_indent = indent
}
// Set the preferred line width.
func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
if width < 0 {
width = -1
}
emitter.best_width = width
}
// Set if unescaped non-ASCII characters are allowed.
func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
emitter.unicode = unicode
}
// Set the preferred line break character.
func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
emitter.line_break = line_break
}
///*
// * Destroy a token object.
// */
//
//YAML_DECLARE(void)
//yaml_token_delete(yaml_token_t *token)
//{
// assert(token); // Non-NULL token object expected.
//
// switch (token.type)
// {
// case YAML_TAG_DIRECTIVE_TOKEN:
// yaml_free(token.data.tag_directive.handle);
// yaml_free(token.data.tag_directive.prefix);
// break;
//
// case YAML_ALIAS_TOKEN:
// yaml_free(token.data.alias.value);
// break;
//
// case YAML_ANCHOR_TOKEN:
// yaml_free(token.data.anchor.value);
// break;
//
// case YAML_TAG_TOKEN:
// yaml_free(token.data.tag.handle);
// yaml_free(token.data.tag.suffix);
// break;
//
// case YAML_SCALAR_TOKEN:
// yaml_free(token.data.scalar.value);
// break;
//
// default:
// break;
// }
//
// memset(token, 0, sizeof(yaml_token_t));
//}
//
///*
// * Check if a string is a valid UTF-8 sequence.
// *
// * Check 'reader.c' for more details on UTF-8 encoding.
// */
//
//static int
//yaml_check_utf8(yaml_char_t *start, size_t length)
//{
// yaml_char_t *end = start+length;
// yaml_char_t *pointer = start;
//
// while (pointer < end) {
// unsigned char octet;
// unsigned int width;
// unsigned int value;
// size_t k;
//
// octet = pointer[0];
// width = (octet & 0x80) == 0x00 ? 1 :
// (octet & 0xE0) == 0xC0 ? 2 :
// (octet & 0xF0) == 0xE0 ? 3 :
// (octet & 0xF8) == 0xF0 ? 4 : 0;
// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
// if (!width) return 0;
// if (pointer+width > end) return 0;
// for (k = 1; k < width; k ++) {
// octet = pointer[k];
// if ((octet & 0xC0) != 0x80) return 0;
// value = (value << 6) + (octet & 0x3F);
// }
// if (!((width == 1) ||
// (width == 2 && value >= 0x80) ||
// (width == 3 && value >= 0x800) ||
// (width == 4 && value >= 0x10000))) return 0;
//
// pointer += width;
// }
//
// return 1;
//}
//
// Create STREAM-START.
func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
*event = yaml_event_t{
typ: yaml_STREAM_START_EVENT,
encoding: encoding,
}
}
// Create STREAM-END.
func yaml_stream_end_event_initialize(event *yaml_event_t) {
*event = yaml_event_t{
typ: yaml_STREAM_END_EVENT,
}
}
// Create DOCUMENT-START.
func yaml_document_start_event_initialize(
event *yaml_event_t,
version_directive *yaml_version_directive_t,
tag_directives []yaml_tag_directive_t,
implicit bool,
) {
*event = yaml_event_t{
typ: yaml_DOCUMENT_START_EVENT,
version_directive: version_directive,
tag_directives: tag_directives,
implicit: implicit,
}
}
// Create DOCUMENT-END.
func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
*event = yaml_event_t{
typ: yaml_DOCUMENT_END_EVENT,
implicit: implicit,
}
}
///*
// * Create ALIAS.
// */
//
//YAML_DECLARE(int)
//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t)
//{
// mark yaml_mark_t = { 0, 0, 0 }
// anchor_copy *yaml_char_t = NULL
//
// assert(event) // Non-NULL event object is expected.
// assert(anchor) // Non-NULL anchor is expected.
//
// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0
//
// anchor_copy = yaml_strdup(anchor)
// if (!anchor_copy)
// return 0
//
// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark)
//
// return 1
//}
// Create SCALAR.
func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
*event = yaml_event_t{
typ: yaml_SCALAR_EVENT,
anchor: anchor,
tag: tag,
value: value,
implicit: plain_implicit,
quoted_implicit: quoted_implicit,
style: yaml_style_t(style),
}
return true
}
// Create SEQUENCE-START.
func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
*event = yaml_event_t{
typ: yaml_SEQUENCE_START_EVENT,
anchor: anchor,
tag: tag,
implicit: implicit,
style: yaml_style_t(style),
}
return true
}
// Create SEQUENCE-END.
func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
*event = yaml_event_t{
typ: yaml_SEQUENCE_END_EVENT,
}
return true
}
// Create MAPPING-START.
func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
*event = yaml_event_t{
typ: yaml_MAPPING_START_EVENT,
anchor: anchor,
tag: tag,
implicit: implicit,
style: yaml_style_t(style),
}
}
// Create MAPPING-END.
func yaml_mapping_end_event_initialize(event *yaml_event_t) {
*event = yaml_event_t{
typ: yaml_MAPPING_END_EVENT,
}
}
// Destroy an event object.
func yaml_event_delete(event *yaml_event_t) {
*event = yaml_event_t{}
}
///*
// * Create a document object.
// */
//
//YAML_DECLARE(int)
//yaml_document_initialize(document *yaml_document_t,
// version_directive *yaml_version_directive_t,
// tag_directives_start *yaml_tag_directive_t,
// tag_directives_end *yaml_tag_directive_t,
// start_implicit int, end_implicit int)
//{
// struct {
// error yaml_error_type_t
// } context
// struct {
// start *yaml_node_t
// end *yaml_node_t
// top *yaml_node_t
// } nodes = { NULL, NULL, NULL }
// version_directive_copy *yaml_version_directive_t = NULL
// struct {
// start *yaml_tag_directive_t
// end *yaml_tag_directive_t
// top *yaml_tag_directive_t
// } tag_directives_copy = { NULL, NULL, NULL }
// value yaml_tag_directive_t = { NULL, NULL }
// mark yaml_mark_t = { 0, 0, 0 }
//
// assert(document) // Non-NULL document object is expected.
// assert((tag_directives_start && tag_directives_end) ||
// (tag_directives_start == tag_directives_end))
// // Valid tag directives are expected.
//
// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
//
// if (version_directive) {
// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
// if (!version_directive_copy) goto error
// version_directive_copy.major = version_directive.major
// version_directive_copy.minor = version_directive.minor
// }
//
// if (tag_directives_start != tag_directives_end) {
// tag_directive *yaml_tag_directive_t
// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
// goto error
// for (tag_directive = tag_directives_start
// tag_directive != tag_directives_end; tag_directive ++) {
// assert(tag_directive.handle)
// assert(tag_directive.prefix)
// if (!yaml_check_utf8(tag_directive.handle,
// strlen((char *)tag_directive.handle)))
// goto error
// if (!yaml_check_utf8(tag_directive.prefix,
// strlen((char *)tag_directive.prefix)))
// goto error
// value.handle = yaml_strdup(tag_directive.handle)
// value.prefix = yaml_strdup(tag_directive.prefix)
// if (!value.handle || !value.prefix) goto error
// if (!PUSH(&context, tag_directives_copy, value))
// goto error
// value.handle = NULL
// value.prefix = NULL
// }
// }
//
// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
// tag_directives_copy.start, tag_directives_copy.top,
// start_implicit, end_implicit, mark, mark)
//
// return 1
//
//error:
// STACK_DEL(&context, nodes)
// yaml_free(version_directive_copy)
// while (!STACK_EMPTY(&context, tag_directives_copy)) {
// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
// yaml_free(value.handle)
// yaml_free(value.prefix)
// }
// STACK_DEL(&context, tag_directives_copy)
// yaml_free(value.handle)
// yaml_free(value.prefix)
//
// return 0
//}
//
///*
// * Destroy a document object.
// */
//
//YAML_DECLARE(void)
//yaml_document_delete(document *yaml_document_t)
//{
// struct {
// error yaml_error_type_t
// } context
// tag_directive *yaml_tag_directive_t
//
// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
//
// assert(document) // Non-NULL document object is expected.
//
// while (!STACK_EMPTY(&context, document.nodes)) {
// node yaml_node_t = POP(&context, document.nodes)
// yaml_free(node.tag)
// switch (node.type) {
// case YAML_SCALAR_NODE:
// yaml_free(node.data.scalar.value)
// break
// case YAML_SEQUENCE_NODE:
// STACK_DEL(&context, node.data.sequence.items)
// break
// case YAML_MAPPING_NODE:
// STACK_DEL(&context, node.data.mapping.pairs)
// break
// default:
// assert(0) // Should not happen.
// }
// }
// STACK_DEL(&context, document.nodes)
//
// yaml_free(document.version_directive)
// for (tag_directive = document.tag_directives.start
// tag_directive != document.tag_directives.end
// tag_directive++) {
// yaml_free(tag_directive.handle)
// yaml_free(tag_directive.prefix)
// }
// yaml_free(document.tag_directives.start)
//
// memset(document, 0, sizeof(yaml_document_t))
//}
//
///**
// * Get a document node.
// */
//
//YAML_DECLARE(yaml_node_t *)
//yaml_document_get_node(document *yaml_document_t, index int)
//{
// assert(document) // Non-NULL document object is expected.
//
// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
// return document.nodes.start + index - 1
// }
// return NULL
//}
//
///**
// * Get the root object.
// */
//
//YAML_DECLARE(yaml_node_t *)
//yaml_document_get_root_node(document *yaml_document_t)
//{
// assert(document) // Non-NULL document object is expected.
//
// if (document.nodes.top != document.nodes.start) {
// return document.nodes.start
// }
// return NULL
//}
//
///*
// * Add a scalar node to a document.
// */
//
//YAML_DECLARE(int)
//yaml_document_add_scalar(document *yaml_document_t,
// tag *yaml_char_t, value *yaml_char_t, length int,
// style yaml_scalar_style_t)
//{
// struct {
// error yaml_error_type_t
// } context
// mark yaml_mark_t = { 0, 0, 0 }
// tag_copy *yaml_char_t = NULL
// value_copy *yaml_char_t = NULL
// node yaml_node_t
//
// assert(document) // Non-NULL document object is expected.
// assert(value) // Non-NULL value is expected.
//
// if (!tag) {
// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
// }
//
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
// tag_copy = yaml_strdup(tag)
// if (!tag_copy) goto error
//
// if (length < 0) {
// length = strlen((char *)value)
// }
//
// if (!yaml_check_utf8(value, length)) goto error
// value_copy = yaml_malloc(length+1)
// if (!value_copy) goto error
// memcpy(value_copy, value, length)
// value_copy[length] = '\0'
//
// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
// if (!PUSH(&context, document.nodes, node)) goto error
//
// return document.nodes.top - document.nodes.start
//
//error:
// yaml_free(tag_copy)
// yaml_free(value_copy)
//
// return 0
//}
//
///*
// * Add a sequence node to a document.
// */
//
//YAML_DECLARE(int)
//yaml_document_add_sequence(document *yaml_document_t,
// tag *yaml_char_t, style yaml_sequence_style_t)
//{
// struct {
// error yaml_error_type_t
// } context
// mark yaml_mark_t = { 0, 0, 0 }
// tag_copy *yaml_char_t = NULL
// struct {
// start *yaml_node_item_t
// end *yaml_node_item_t
// top *yaml_node_item_t
// } items = { NULL, NULL, NULL }
// node yaml_node_t
//
// assert(document) // Non-NULL document object is expected.
//
// if (!tag) {
// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
// }
//
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
// tag_copy = yaml_strdup(tag)
// if (!tag_copy) goto error
//
// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
//
// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
// style, mark, mark)
// if (!PUSH(&context, document.nodes, node)) goto error
//
// return document.nodes.top - document.nodes.start
//
//error:
// STACK_DEL(&context, items)
// yaml_free(tag_copy)
//
// return 0
//}
//
///*
// * Add a mapping node to a document.
// */
//
//YAML_DECLARE(int)
//yaml_document_add_mapping(document *yaml_document_t,
// tag *yaml_char_t, style yaml_mapping_style_t)
//{
// struct {
// error yaml_error_type_t
// } context
// mark yaml_mark_t = { 0, 0, 0 }
// tag_copy *yaml_char_t = NULL
// struct {
// start *yaml_node_pair_t
// end *yaml_node_pair_t
// top *yaml_node_pair_t
// } pairs = { NULL, NULL, NULL }
// node yaml_node_t
//
// assert(document) // Non-NULL document object is expected.
//
// if (!tag) {
// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
// }
//
// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
// tag_copy = yaml_strdup(tag)
// if (!tag_copy) goto error
//
// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
//
// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
// style, mark, mark)
// if (!PUSH(&context, document.nodes, node)) goto error
//
// return document.nodes.top - document.nodes.start
//
//error:
// STACK_DEL(&context, pairs)
// yaml_free(tag_copy)
//
// return 0
//}
//
///*
// * Append an item to a sequence node.
// */
//
//YAML_DECLARE(int)
//yaml_document_append_sequence_item(document *yaml_document_t,
// sequence int, item int)
//{
// struct {
// error yaml_error_type_t
// } context
//
// assert(document) // Non-NULL document is required.
// assert(sequence > 0
// && document.nodes.start + sequence <= document.nodes.top)
// // Valid sequence id is required.
// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
// // A sequence node is required.
// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
// // Valid item id is required.
//
// if (!PUSH(&context,
// document.nodes.start[sequence-1].data.sequence.items, item))
// return 0
//
// return 1
//}
//
///*
// * Append a pair of a key and a value to a mapping node.
// */
//
//YAML_DECLARE(int)
//yaml_document_append_mapping_pair(document *yaml_document_t,
// mapping int, key int, value int)
//{
// struct {
// error yaml_error_type_t
// } context
//
// pair yaml_node_pair_t
//
// assert(document) // Non-NULL document is required.
// assert(mapping > 0
// && document.nodes.start + mapping <= document.nodes.top)
// // Valid mapping id is required.
// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
// // A mapping node is required.
// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
// // Valid key id is required.
// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
// // Valid value id is required.
//
// pair.key = key
// pair.value = value
//
// if (!PUSH(&context,
// document.nodes.start[mapping-1].data.mapping.pairs, pair))
// return 0
//
// return 1
//}
//
//

View File

@@ -1,815 +0,0 @@
package yaml
import (
"encoding"
"encoding/base64"
"fmt"
"io"
"math"
"reflect"
"strconv"
"time"
)
const (
documentNode = 1 << iota
mappingNode
sequenceNode
scalarNode
aliasNode
)
type node struct {
kind int
line, column int
tag string
// For an alias node, alias holds the resolved alias.
alias *node
value string
implicit bool
children []*node
anchors map[string]*node
}
// ----------------------------------------------------------------------------
// Parser, produces a node tree out of a libyaml event stream.
type parser struct {
parser yaml_parser_t
event yaml_event_t
doc *node
doneInit bool
}
func newParser(b []byte) *parser {
p := parser{}
if !yaml_parser_initialize(&p.parser) {
panic("failed to initialize YAML emitter")
}
if len(b) == 0 {
b = []byte{'\n'}
}
yaml_parser_set_input_string(&p.parser, b)
return &p
}
func newParserFromReader(r io.Reader) *parser {
p := parser{}
if !yaml_parser_initialize(&p.parser) {
panic("failed to initialize YAML emitter")
}
yaml_parser_set_input_reader(&p.parser, r)
return &p
}
func (p *parser) init() {
if p.doneInit {
return
}
p.expect(yaml_STREAM_START_EVENT)
p.doneInit = true
}
func (p *parser) destroy() {
if p.event.typ != yaml_NO_EVENT {
yaml_event_delete(&p.event)
}
yaml_parser_delete(&p.parser)
}
// expect consumes an event from the event stream and
// checks that it's of the expected type.
func (p *parser) expect(e yaml_event_type_t) {
if p.event.typ == yaml_NO_EVENT {
if !yaml_parser_parse(&p.parser, &p.event) {
p.fail()
}
}
if p.event.typ == yaml_STREAM_END_EVENT {
failf("attempted to go past the end of stream; corrupted value?")
}
if p.event.typ != e {
p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
p.fail()
}
yaml_event_delete(&p.event)
p.event.typ = yaml_NO_EVENT
}
// peek peeks at the next event in the event stream,
// puts the results into p.event and returns the event type.
func (p *parser) peek() yaml_event_type_t {
if p.event.typ != yaml_NO_EVENT {
return p.event.typ
}
if !yaml_parser_parse(&p.parser, &p.event) {
p.fail()
}
return p.event.typ
}
func (p *parser) fail() {
var where string
var line int
if p.parser.problem_mark.line != 0 {
line = p.parser.problem_mark.line
// Scanner errors don't iterate line before returning error
if p.parser.error == yaml_SCANNER_ERROR {
line++
}
} else if p.parser.context_mark.line != 0 {
line = p.parser.context_mark.line
}
if line != 0 {
where = "line " + strconv.Itoa(line) + ": "
}
var msg string
if len(p.parser.problem) > 0 {
msg = p.parser.problem
} else {
msg = "unknown problem parsing YAML content"
}
failf("%s%s", where, msg)
}
func (p *parser) anchor(n *node, anchor []byte) {
if anchor != nil {
p.doc.anchors[string(anchor)] = n
}
}
func (p *parser) parse() *node {
p.init()
switch p.peek() {
case yaml_SCALAR_EVENT:
return p.scalar()
case yaml_ALIAS_EVENT:
return p.alias()
case yaml_MAPPING_START_EVENT:
return p.mapping()
case yaml_SEQUENCE_START_EVENT:
return p.sequence()
case yaml_DOCUMENT_START_EVENT:
return p.document()
case yaml_STREAM_END_EVENT:
// Happens when attempting to decode an empty buffer.
return nil
default:
panic("attempted to parse unknown event: " + p.event.typ.String())
}
}
func (p *parser) node(kind int) *node {
return &node{
kind: kind,
line: p.event.start_mark.line,
column: p.event.start_mark.column,
}
}
func (p *parser) document() *node {
n := p.node(documentNode)
n.anchors = make(map[string]*node)
p.doc = n
p.expect(yaml_DOCUMENT_START_EVENT)
n.children = append(n.children, p.parse())
p.expect(yaml_DOCUMENT_END_EVENT)
return n
}
func (p *parser) alias() *node {
n := p.node(aliasNode)
n.value = string(p.event.anchor)
n.alias = p.doc.anchors[n.value]
if n.alias == nil {
failf("unknown anchor '%s' referenced", n.value)
}
p.expect(yaml_ALIAS_EVENT)
return n
}
func (p *parser) scalar() *node {
n := p.node(scalarNode)
n.value = string(p.event.value)
n.tag = string(p.event.tag)
n.implicit = p.event.implicit
p.anchor(n, p.event.anchor)
p.expect(yaml_SCALAR_EVENT)
return n
}
func (p *parser) sequence() *node {
n := p.node(sequenceNode)
p.anchor(n, p.event.anchor)
p.expect(yaml_SEQUENCE_START_EVENT)
for p.peek() != yaml_SEQUENCE_END_EVENT {
n.children = append(n.children, p.parse())
}
p.expect(yaml_SEQUENCE_END_EVENT)
return n
}
func (p *parser) mapping() *node {
n := p.node(mappingNode)
p.anchor(n, p.event.anchor)
p.expect(yaml_MAPPING_START_EVENT)
for p.peek() != yaml_MAPPING_END_EVENT {
n.children = append(n.children, p.parse(), p.parse())
}
p.expect(yaml_MAPPING_END_EVENT)
return n
}
// ----------------------------------------------------------------------------
// Decoder, unmarshals a node into a provided value.
type decoder struct {
doc *node
aliases map[*node]bool
mapType reflect.Type
terrors []string
strict bool
decodeCount int
aliasCount int
aliasDepth int
}
var (
mapItemType = reflect.TypeOf(MapItem{})
durationType = reflect.TypeOf(time.Duration(0))
defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
ifaceType = defaultMapType.Elem()
timeType = reflect.TypeOf(time.Time{})
ptrTimeType = reflect.TypeOf(&time.Time{})
)
func newDecoder(strict bool) *decoder {
d := &decoder{mapType: defaultMapType, strict: strict}
d.aliases = make(map[*node]bool)
return d
}
func (d *decoder) terror(n *node, tag string, out reflect.Value) {
if n.tag != "" {
tag = n.tag
}
value := n.value
if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG {
if len(value) > 10 {
value = " `" + value[:7] + "...`"
} else {
value = " `" + value + "`"
}
}
d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type()))
}
func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
terrlen := len(d.terrors)
err := u.UnmarshalYAML(func(v interface{}) (err error) {
defer handleErr(&err)
d.unmarshal(n, reflect.ValueOf(v))
if len(d.terrors) > terrlen {
issues := d.terrors[terrlen:]
d.terrors = d.terrors[:terrlen]
return &TypeError{issues}
}
return nil
})
if e, ok := err.(*TypeError); ok {
d.terrors = append(d.terrors, e.Errors...)
return false
}
if err != nil {
fail(err)
}
return true
}
// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
// if a value is found to implement it.
// It returns the initialized and dereferenced out value, whether
// unmarshalling was already done by UnmarshalYAML, and if so whether
// its types unmarshalled appropriately.
//
// If n holds a null value, prepare returns before doing anything.
func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
return out, false, false
}
again := true
for again {
again = false
if out.Kind() == reflect.Ptr {
if out.IsNil() {
out.Set(reflect.New(out.Type().Elem()))
}
out = out.Elem()
again = true
}
if out.CanAddr() {
if u, ok := out.Addr().Interface().(Unmarshaler); ok {
good = d.callUnmarshaler(n, u)
return out, true, good
}
}
}
return out, false, false
}
const (
// 400,000 decode operations is ~500kb of dense object declarations, or
// ~5kb of dense object declarations with 10000% alias expansion
alias_ratio_range_low = 400000
// 4,000,000 decode operations is ~5MB of dense object declarations, or
// ~4.5MB of dense object declarations with 10% alias expansion
alias_ratio_range_high = 4000000
// alias_ratio_range is the range over which we scale allowed alias ratios
alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
)
func allowedAliasRatio(decodeCount int) float64 {
switch {
case decodeCount <= alias_ratio_range_low:
// allow 99% to come from alias expansion for small-to-medium documents
return 0.99
case decodeCount >= alias_ratio_range_high:
// allow 10% to come from alias expansion for very large documents
return 0.10
default:
// scale smoothly from 99% down to 10% over the range.
// this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
// 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
}
}
func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
d.decodeCount++
if d.aliasDepth > 0 {
d.aliasCount++
}
if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
failf("document contains excessive aliasing")
}
switch n.kind {
case documentNode:
return d.document(n, out)
case aliasNode:
return d.alias(n, out)
}
out, unmarshaled, good := d.prepare(n, out)
if unmarshaled {
return good
}
switch n.kind {
case scalarNode:
good = d.scalar(n, out)
case mappingNode:
good = d.mapping(n, out)
case sequenceNode:
good = d.sequence(n, out)
default:
panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
}
return good
}
func (d *decoder) document(n *node, out reflect.Value) (good bool) {
if len(n.children) == 1 {
d.doc = n
d.unmarshal(n.children[0], out)
return true
}
return false
}
func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
if d.aliases[n] {
// TODO this could actually be allowed in some circumstances.
failf("anchor '%s' value contains itself", n.value)
}
d.aliases[n] = true
d.aliasDepth++
good = d.unmarshal(n.alias, out)
d.aliasDepth--
delete(d.aliases, n)
return good
}
var zeroValue reflect.Value
func resetMap(out reflect.Value) {
for _, k := range out.MapKeys() {
out.SetMapIndex(k, zeroValue)
}
}
func (d *decoder) scalar(n *node, out reflect.Value) bool {
var tag string
var resolved interface{}
if n.tag == "" && !n.implicit {
tag = yaml_STR_TAG
resolved = n.value
} else {
tag, resolved = resolve(n.tag, n.value)
if tag == yaml_BINARY_TAG {
data, err := base64.StdEncoding.DecodeString(resolved.(string))
if err != nil {
failf("!!binary value contains invalid base64 data")
}
resolved = string(data)
}
}
if resolved == nil {
if out.Kind() == reflect.Map && !out.CanAddr() {
resetMap(out)
} else {
out.Set(reflect.Zero(out.Type()))
}
return true
}
if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
// We've resolved to exactly the type we want, so use that.
out.Set(resolvedv)
return true
}
// Perhaps we can use the value as a TextUnmarshaler to
// set its value.
if out.CanAddr() {
u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
if ok {
var text []byte
if tag == yaml_BINARY_TAG {
text = []byte(resolved.(string))
} else {
// We let any value be unmarshaled into TextUnmarshaler.
// That might be more lax than we'd like, but the
// TextUnmarshaler itself should bowl out any dubious values.
text = []byte(n.value)
}
err := u.UnmarshalText(text)
if err != nil {
fail(err)
}
return true
}
}
switch out.Kind() {
case reflect.String:
if tag == yaml_BINARY_TAG {
out.SetString(resolved.(string))
return true
}
if resolved != nil {
out.SetString(n.value)
return true
}
case reflect.Interface:
if resolved == nil {
out.Set(reflect.Zero(out.Type()))
} else if tag == yaml_TIMESTAMP_TAG {
// It looks like a timestamp but for backward compatibility
// reasons we set it as a string, so that code that unmarshals
// timestamp-like values into interface{} will continue to
// see a string and not a time.Time.
// TODO(v3) Drop this.
out.Set(reflect.ValueOf(n.value))
} else {
out.Set(reflect.ValueOf(resolved))
}
return true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
switch resolved := resolved.(type) {
case int:
if !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
return true
}
case int64:
if !out.OverflowInt(resolved) {
out.SetInt(resolved)
return true
}
case uint64:
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
return true
}
case float64:
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
return true
}
case string:
if out.Type() == durationType {
d, err := time.ParseDuration(resolved)
if err == nil {
out.SetInt(int64(d))
return true
}
}
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
switch resolved := resolved.(type) {
case int:
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved))
return true
}
case int64:
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved))
return true
}
case uint64:
if !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved))
return true
}
case float64:
if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved))
return true
}
}
case reflect.Bool:
switch resolved := resolved.(type) {
case bool:
out.SetBool(resolved)
return true
}
case reflect.Float32, reflect.Float64:
switch resolved := resolved.(type) {
case int:
out.SetFloat(float64(resolved))
return true
case int64:
out.SetFloat(float64(resolved))
return true
case uint64:
out.SetFloat(float64(resolved))
return true
case float64:
out.SetFloat(resolved)
return true
}
case reflect.Struct:
if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
out.Set(resolvedv)
return true
}
case reflect.Ptr:
if out.Type().Elem() == reflect.TypeOf(resolved) {
// TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
elem := reflect.New(out.Type().Elem())
elem.Elem().Set(reflect.ValueOf(resolved))
out.Set(elem)
return true
}
}
d.terror(n, tag, out)
return false
}
func settableValueOf(i interface{}) reflect.Value {
v := reflect.ValueOf(i)
sv := reflect.New(v.Type()).Elem()
sv.Set(v)
return sv
}
func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
l := len(n.children)
var iface reflect.Value
switch out.Kind() {
case reflect.Slice:
out.Set(reflect.MakeSlice(out.Type(), l, l))
case reflect.Array:
if l != out.Len() {
failf("invalid array: want %d elements but got %d", out.Len(), l)
}
case reflect.Interface:
// No type hints. Will have to use a generic sequence.
iface = out
out = settableValueOf(make([]interface{}, l))
default:
d.terror(n, yaml_SEQ_TAG, out)
return false
}
et := out.Type().Elem()
j := 0
for i := 0; i < l; i++ {
e := reflect.New(et).Elem()
if ok := d.unmarshal(n.children[i], e); ok {
out.Index(j).Set(e)
j++
}
}
if out.Kind() != reflect.Array {
out.Set(out.Slice(0, j))
}
if iface.IsValid() {
iface.Set(out)
}
return true
}
func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
switch out.Kind() {
case reflect.Struct:
return d.mappingStruct(n, out)
case reflect.Slice:
return d.mappingSlice(n, out)
case reflect.Map:
// okay
case reflect.Interface:
if d.mapType.Kind() == reflect.Map {
iface := out
out = reflect.MakeMap(d.mapType)
iface.Set(out)
} else {
slicev := reflect.New(d.mapType).Elem()
if !d.mappingSlice(n, slicev) {
return false
}
out.Set(slicev)
return true
}
default:
d.terror(n, yaml_MAP_TAG, out)
return false
}
outt := out.Type()
kt := outt.Key()
et := outt.Elem()
mapType := d.mapType
if outt.Key() == ifaceType && outt.Elem() == ifaceType {
d.mapType = outt
}
if out.IsNil() {
out.Set(reflect.MakeMap(outt))
}
l := len(n.children)
for i := 0; i < l; i += 2 {
if isMerge(n.children[i]) {
d.merge(n.children[i+1], out)
continue
}
k := reflect.New(kt).Elem()
if d.unmarshal(n.children[i], k) {
kkind := k.Kind()
if kkind == reflect.Interface {
kkind = k.Elem().Kind()
}
if kkind == reflect.Map || kkind == reflect.Slice {
failf("invalid map key: %#v", k.Interface())
}
e := reflect.New(et).Elem()
if d.unmarshal(n.children[i+1], e) {
d.setMapIndex(n.children[i+1], out, k, e)
}
}
}
d.mapType = mapType
return true
}
func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
if d.strict && out.MapIndex(k) != zeroValue {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
return
}
out.SetMapIndex(k, v)
}
func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
outt := out.Type()
if outt.Elem() != mapItemType {
d.terror(n, yaml_MAP_TAG, out)
return false
}
mapType := d.mapType
d.mapType = outt
var slice []MapItem
var l = len(n.children)
for i := 0; i < l; i += 2 {
if isMerge(n.children[i]) {
d.merge(n.children[i+1], out)
continue
}
item := MapItem{}
k := reflect.ValueOf(&item.Key).Elem()
if d.unmarshal(n.children[i], k) {
v := reflect.ValueOf(&item.Value).Elem()
if d.unmarshal(n.children[i+1], v) {
slice = append(slice, item)
}
}
}
out.Set(reflect.ValueOf(slice))
d.mapType = mapType
return true
}
func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
sinfo, err := getStructInfo(out.Type())
if err != nil {
panic(err)
}
name := settableValueOf("")
l := len(n.children)
var inlineMap reflect.Value
var elemType reflect.Type
if sinfo.InlineMap != -1 {
inlineMap = out.Field(sinfo.InlineMap)
inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
elemType = inlineMap.Type().Elem()
}
var doneFields []bool
if d.strict {
doneFields = make([]bool, len(sinfo.FieldsList))
}
for i := 0; i < l; i += 2 {
ni := n.children[i]
if isMerge(ni) {
d.merge(n.children[i+1], out)
continue
}
if !d.unmarshal(ni, name) {
continue
}
if info, ok := sinfo.FieldsMap[name.String()]; ok {
if d.strict {
if doneFields[info.Id] {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
continue
}
doneFields[info.Id] = true
}
var field reflect.Value
if info.Inline == nil {
field = out.Field(info.Num)
} else {
field = out.FieldByIndex(info.Inline)
}
d.unmarshal(n.children[i+1], field)
} else if sinfo.InlineMap != -1 {
if inlineMap.IsNil() {
inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
}
value := reflect.New(elemType).Elem()
d.unmarshal(n.children[i+1], value)
d.setMapIndex(n.children[i+1], inlineMap, name, value)
} else if d.strict {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
}
}
return true
}
func failWantMap() {
failf("map merge requires map or sequence of maps as the value")
}
func (d *decoder) merge(n *node, out reflect.Value) {
switch n.kind {
case mappingNode:
d.unmarshal(n, out)
case aliasNode:
if n.alias != nil && n.alias.kind != mappingNode {
failWantMap()
}
d.unmarshal(n, out)
case sequenceNode:
// Step backwards as earlier nodes take precedence.
for i := len(n.children) - 1; i >= 0; i-- {
ni := n.children[i]
if ni.kind == aliasNode {
if ni.alias != nil && ni.alias.kind != mappingNode {
failWantMap()
}
} else if ni.kind != mappingNode {
failWantMap()
}
d.unmarshal(ni, out)
}
default:
failWantMap()
}
}
func isMerge(n *node) bool {
return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,390 +0,0 @@
package yaml
import (
"encoding"
"fmt"
"io"
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"time"
"unicode/utf8"
)
// jsonNumber is the interface of the encoding/json.Number datatype.
// Repeating the interface here avoids a dependency on encoding/json, and also
// supports other libraries like jsoniter, which use a similar datatype with
// the same interface. Detecting this interface is useful when dealing with
// structures containing json.Number, which is a string under the hood. The
// encoder should prefer the use of Int64(), Float64() and string(), in that
// order, when encoding this type.
type jsonNumber interface {
Float64() (float64, error)
Int64() (int64, error)
String() string
}
type encoder struct {
emitter yaml_emitter_t
event yaml_event_t
out []byte
flow bool
// doneInit holds whether the initial stream_start_event has been
// emitted.
doneInit bool
}
func newEncoder() *encoder {
e := &encoder{}
yaml_emitter_initialize(&e.emitter)
yaml_emitter_set_output_string(&e.emitter, &e.out)
yaml_emitter_set_unicode(&e.emitter, true)
return e
}
func newEncoderWithWriter(w io.Writer) *encoder {
e := &encoder{}
yaml_emitter_initialize(&e.emitter)
yaml_emitter_set_output_writer(&e.emitter, w)
yaml_emitter_set_unicode(&e.emitter, true)
return e
}
func (e *encoder) init() {
if e.doneInit {
return
}
yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
e.emit()
e.doneInit = true
}
func (e *encoder) finish() {
e.emitter.open_ended = false
yaml_stream_end_event_initialize(&e.event)
e.emit()
}
func (e *encoder) destroy() {
yaml_emitter_delete(&e.emitter)
}
func (e *encoder) emit() {
// This will internally delete the e.event value.
e.must(yaml_emitter_emit(&e.emitter, &e.event))
}
func (e *encoder) must(ok bool) {
if !ok {
msg := e.emitter.problem
if msg == "" {
msg = "unknown problem generating YAML content"
}
failf("%s", msg)
}
}
func (e *encoder) marshalDoc(tag string, in reflect.Value) {
e.init()
yaml_document_start_event_initialize(&e.event, nil, nil, true)
e.emit()
e.marshal(tag, in)
yaml_document_end_event_initialize(&e.event, true)
e.emit()
}
func (e *encoder) marshal(tag string, in reflect.Value) {
if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
e.nilv()
return
}
iface := in.Interface()
switch m := iface.(type) {
case jsonNumber:
integer, err := m.Int64()
if err == nil {
// In this case the json.Number is a valid int64
in = reflect.ValueOf(integer)
break
}
float, err := m.Float64()
if err == nil {
// In this case the json.Number is a valid float64
in = reflect.ValueOf(float)
break
}
// fallback case - no number could be obtained
in = reflect.ValueOf(m.String())
case time.Time, *time.Time:
// Although time.Time implements TextMarshaler,
// we don't want to treat it as a string for YAML
// purposes because YAML has special support for
// timestamps.
case Marshaler:
v, err := m.MarshalYAML()
if err != nil {
fail(err)
}
if v == nil {
e.nilv()
return
}
in = reflect.ValueOf(v)
case encoding.TextMarshaler:
text, err := m.MarshalText()
if err != nil {
fail(err)
}
in = reflect.ValueOf(string(text))
case nil:
e.nilv()
return
}
switch in.Kind() {
case reflect.Interface:
e.marshal(tag, in.Elem())
case reflect.Map:
e.mapv(tag, in)
case reflect.Ptr:
if in.Type() == ptrTimeType {
e.timev(tag, in.Elem())
} else {
e.marshal(tag, in.Elem())
}
case reflect.Struct:
if in.Type() == timeType {
e.timev(tag, in)
} else {
e.structv(tag, in)
}
case reflect.Slice, reflect.Array:
if in.Type().Elem() == mapItemType {
e.itemsv(tag, in)
} else {
e.slicev(tag, in)
}
case reflect.String:
e.stringv(tag, in)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if in.Type() == durationType {
e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String()))
} else {
e.intv(tag, in)
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
e.uintv(tag, in)
case reflect.Float32, reflect.Float64:
e.floatv(tag, in)
case reflect.Bool:
e.boolv(tag, in)
default:
panic("cannot marshal type: " + in.Type().String())
}
}
func (e *encoder) mapv(tag string, in reflect.Value) {
e.mappingv(tag, func() {
keys := keyList(in.MapKeys())
sort.Sort(keys)
for _, k := range keys {
e.marshal("", k)
e.marshal("", in.MapIndex(k))
}
})
}
func (e *encoder) itemsv(tag string, in reflect.Value) {
e.mappingv(tag, func() {
slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
for _, item := range slice {
e.marshal("", reflect.ValueOf(item.Key))
e.marshal("", reflect.ValueOf(item.Value))
}
})
}
func (e *encoder) structv(tag string, in reflect.Value) {
sinfo, err := getStructInfo(in.Type())
if err != nil {
panic(err)
}
e.mappingv(tag, func() {
for _, info := range sinfo.FieldsList {
var value reflect.Value
if info.Inline == nil {
value = in.Field(info.Num)
} else {
value = in.FieldByIndex(info.Inline)
}
if info.OmitEmpty && isZero(value) {
continue
}
e.marshal("", reflect.ValueOf(info.Key))
e.flow = info.Flow
e.marshal("", value)
}
if sinfo.InlineMap >= 0 {
m := in.Field(sinfo.InlineMap)
if m.Len() > 0 {
e.flow = false
keys := keyList(m.MapKeys())
sort.Sort(keys)
for _, k := range keys {
if _, found := sinfo.FieldsMap[k.String()]; found {
panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String()))
}
e.marshal("", k)
e.flow = false
e.marshal("", m.MapIndex(k))
}
}
}
})
}
func (e *encoder) mappingv(tag string, f func()) {
implicit := tag == ""
style := yaml_BLOCK_MAPPING_STYLE
if e.flow {
e.flow = false
style = yaml_FLOW_MAPPING_STYLE
}
yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
e.emit()
f()
yaml_mapping_end_event_initialize(&e.event)
e.emit()
}
func (e *encoder) slicev(tag string, in reflect.Value) {
implicit := tag == ""
style := yaml_BLOCK_SEQUENCE_STYLE
if e.flow {
e.flow = false
style = yaml_FLOW_SEQUENCE_STYLE
}
e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
e.emit()
n := in.Len()
for i := 0; i < n; i++ {
e.marshal("", in.Index(i))
}
e.must(yaml_sequence_end_event_initialize(&e.event))
e.emit()
}
// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
//
// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
// in YAML 1.2 and by this package, but these should be marshalled quoted for
// the time being for compatibility with other parsers.
func isBase60Float(s string) (result bool) {
// Fast path.
if s == "" {
return false
}
c := s[0]
if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
return false
}
// Do the full match.
return base60float.MatchString(s)
}
// From http://yaml.org/type/float.html, except the regular expression there
// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
func (e *encoder) stringv(tag string, in reflect.Value) {
var style yaml_scalar_style_t
s := in.String()
canUsePlain := true
switch {
case !utf8.ValidString(s):
if tag == yaml_BINARY_TAG {
failf("explicitly tagged !!binary data must be base64-encoded")
}
if tag != "" {
failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
}
// It can't be encoded directly as YAML so use a binary tag
// and encode it as base64.
tag = yaml_BINARY_TAG
s = encodeBase64(s)
case tag == "":
// Check to see if it would resolve to a specific
// tag when encoded unquoted. If it doesn't,
// there's no need to quote it.
rtag, _ := resolve("", s)
canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s)
}
// Note: it's possible for user code to emit invalid YAML
// if they explicitly specify a tag and a string containing
// text that's incompatible with that tag.
switch {
case strings.Contains(s, "\n"):
style = yaml_LITERAL_SCALAR_STYLE
case canUsePlain:
style = yaml_PLAIN_SCALAR_STYLE
default:
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
}
e.emitScalar(s, "", tag, style)
}
func (e *encoder) boolv(tag string, in reflect.Value) {
var s string
if in.Bool() {
s = "true"
} else {
s = "false"
}
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
}
func (e *encoder) intv(tag string, in reflect.Value) {
s := strconv.FormatInt(in.Int(), 10)
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
}
func (e *encoder) uintv(tag string, in reflect.Value) {
s := strconv.FormatUint(in.Uint(), 10)
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
}
func (e *encoder) timev(tag string, in reflect.Value) {
t := in.Interface().(time.Time)
s := t.Format(time.RFC3339Nano)
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
}
func (e *encoder) floatv(tag string, in reflect.Value) {
// Issue #352: When formatting, use the precision of the underlying value
precision := 64
if in.Kind() == reflect.Float32 {
precision = 32
}
s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
switch s {
case "+Inf":
s = ".inf"
case "-Inf":
s = "-.inf"
case "NaN":
s = ".nan"
}
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
}
func (e *encoder) nilv() {
e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
}
func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
implicit := tag == ""
e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
e.emit()
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,412 +0,0 @@
package yaml
import (
"io"
)
// Set the reader error and return 0.
func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool {
parser.error = yaml_READER_ERROR
parser.problem = problem
parser.problem_offset = offset
parser.problem_value = value
return false
}
// Byte order marks.
const (
bom_UTF8 = "\xef\xbb\xbf"
bom_UTF16LE = "\xff\xfe"
bom_UTF16BE = "\xfe\xff"
)
// Determine the input stream encoding by checking the BOM symbol. If no BOM is
// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
// Ensure that we had enough bytes in the raw buffer.
for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 {
if !yaml_parser_update_raw_buffer(parser) {
return false
}
}
// Determine the encoding.
buf := parser.raw_buffer
pos := parser.raw_buffer_pos
avail := len(buf) - pos
if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] {
parser.encoding = yaml_UTF16LE_ENCODING
parser.raw_buffer_pos += 2
parser.offset += 2
} else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] {
parser.encoding = yaml_UTF16BE_ENCODING
parser.raw_buffer_pos += 2
parser.offset += 2
} else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] {
parser.encoding = yaml_UTF8_ENCODING
parser.raw_buffer_pos += 3
parser.offset += 3
} else {
parser.encoding = yaml_UTF8_ENCODING
}
return true
}
// Update the raw buffer.
func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
size_read := 0
// Return if the raw buffer is full.
if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) {
return true
}
// Return on EOF.
if parser.eof {
return true
}
// Move the remaining bytes in the raw buffer to the beginning.
if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) {
copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:])
}
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos]
parser.raw_buffer_pos = 0
// Call the read handler to fill the buffer.
size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)])
parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read]
if err == io.EOF {
parser.eof = true
} else if err != nil {
return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1)
}
return true
}
// Ensure that the buffer contains at least `length` characters.
// Return true on success, false on failure.
//
// The length is supposed to be significantly less that the buffer size.
func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
if parser.read_handler == nil {
panic("read handler must be set")
}
// [Go] This function was changed to guarantee the requested length size at EOF.
// The fact we need to do this is pretty awful, but the description above implies
// for that to be the case, and there are tests
// If the EOF flag is set and the raw buffer is empty, do nothing.
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
// [Go] ACTUALLY! Read the documentation of this function above.
// This is just broken. To return true, we need to have the
// given length in the buffer. Not doing that means every single
// check that calls this function to make sure the buffer has a
// given length is Go) panicking; or C) accessing invalid memory.
//return true
}
// Return if the buffer contains enough characters.
if parser.unread >= length {
return true
}
// Determine the input encoding if it is not known yet.
if parser.encoding == yaml_ANY_ENCODING {
if !yaml_parser_determine_encoding(parser) {
return false
}
}
// Move the unread characters to the beginning of the buffer.
buffer_len := len(parser.buffer)
if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len {
copy(parser.buffer, parser.buffer[parser.buffer_pos:])
buffer_len -= parser.buffer_pos
parser.buffer_pos = 0
} else if parser.buffer_pos == buffer_len {
buffer_len = 0
parser.buffer_pos = 0
}
// Open the whole buffer for writing, and cut it before returning.
parser.buffer = parser.buffer[:cap(parser.buffer)]
// Fill the buffer until it has enough characters.
first := true
for parser.unread < length {
// Fill the raw buffer if necessary.
if !first || parser.raw_buffer_pos == len(parser.raw_buffer) {
if !yaml_parser_update_raw_buffer(parser) {
parser.buffer = parser.buffer[:buffer_len]
return false
}
}
first = false
// Decode the raw buffer.
inner:
for parser.raw_buffer_pos != len(parser.raw_buffer) {
var value rune
var width int
raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos
// Decode the next character.
switch parser.encoding {
case yaml_UTF8_ENCODING:
// Decode a UTF-8 character. Check RFC 3629
// (http://www.ietf.org/rfc/rfc3629.txt) for more details.
//
// The following table (taken from the RFC) is used for
// decoding.
//
// Char. number range | UTF-8 octet sequence
// (hexadecimal) | (binary)
// --------------------+------------------------------------
// 0000 0000-0000 007F | 0xxxxxxx
// 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
// 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
// 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
//
// Additionally, the characters in the range 0xD800-0xDFFF
// are prohibited as they are reserved for use with UTF-16
// surrogate pairs.
// Determine the length of the UTF-8 sequence.
octet := parser.raw_buffer[parser.raw_buffer_pos]
switch {
case octet&0x80 == 0x00:
width = 1
case octet&0xE0 == 0xC0:
width = 2
case octet&0xF0 == 0xE0:
width = 3
case octet&0xF8 == 0xF0:
width = 4
default:
// The leading octet is invalid.
return yaml_parser_set_reader_error(parser,
"invalid leading UTF-8 octet",
parser.offset, int(octet))
}
// Check if the raw buffer contains an incomplete character.
if width > raw_unread {
if parser.eof {
return yaml_parser_set_reader_error(parser,
"incomplete UTF-8 octet sequence",
parser.offset, -1)
}
break inner
}
// Decode the leading octet.
switch {
case octet&0x80 == 0x00:
value = rune(octet & 0x7F)
case octet&0xE0 == 0xC0:
value = rune(octet & 0x1F)
case octet&0xF0 == 0xE0:
value = rune(octet & 0x0F)
case octet&0xF8 == 0xF0:
value = rune(octet & 0x07)
default:
value = 0
}
// Check and decode the trailing octets.
for k := 1; k < width; k++ {
octet = parser.raw_buffer[parser.raw_buffer_pos+k]
// Check if the octet is valid.
if (octet & 0xC0) != 0x80 {
return yaml_parser_set_reader_error(parser,
"invalid trailing UTF-8 octet",
parser.offset+k, int(octet))
}
// Decode the octet.
value = (value << 6) + rune(octet&0x3F)
}
// Check the length of the sequence against the value.
switch {
case width == 1:
case width == 2 && value >= 0x80:
case width == 3 && value >= 0x800:
case width == 4 && value >= 0x10000:
default:
return yaml_parser_set_reader_error(parser,
"invalid length of a UTF-8 sequence",
parser.offset, -1)
}
// Check the range of the value.
if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF {
return yaml_parser_set_reader_error(parser,
"invalid Unicode character",
parser.offset, int(value))
}
case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING:
var low, high int
if parser.encoding == yaml_UTF16LE_ENCODING {
low, high = 0, 1
} else {
low, high = 1, 0
}
// The UTF-16 encoding is not as simple as one might
// naively think. Check RFC 2781
// (http://www.ietf.org/rfc/rfc2781.txt).
//
// Normally, two subsequent bytes describe a Unicode
// character. However a special technique (called a
// surrogate pair) is used for specifying character
// values larger than 0xFFFF.
//
// A surrogate pair consists of two pseudo-characters:
// high surrogate area (0xD800-0xDBFF)
// low surrogate area (0xDC00-0xDFFF)
//
// The following formulas are used for decoding
// and encoding characters using surrogate pairs:
//
// U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
// U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
// W1 = 110110yyyyyyyyyy
// W2 = 110111xxxxxxxxxx
//
// where U is the character value, W1 is the high surrogate
// area, W2 is the low surrogate area.
// Check for incomplete UTF-16 character.
if raw_unread < 2 {
if parser.eof {
return yaml_parser_set_reader_error(parser,
"incomplete UTF-16 character",
parser.offset, -1)
}
break inner
}
// Get the character.
value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) +
(rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8)
// Check for unexpected low surrogate area.
if value&0xFC00 == 0xDC00 {
return yaml_parser_set_reader_error(parser,
"unexpected low surrogate area",
parser.offset, int(value))
}
// Check for a high surrogate area.
if value&0xFC00 == 0xD800 {
width = 4
// Check for incomplete surrogate pair.
if raw_unread < 4 {
if parser.eof {
return yaml_parser_set_reader_error(parser,
"incomplete UTF-16 surrogate pair",
parser.offset, -1)
}
break inner
}
// Get the next character.
value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) +
(rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8)
// Check for a low surrogate area.
if value2&0xFC00 != 0xDC00 {
return yaml_parser_set_reader_error(parser,
"expected low surrogate area",
parser.offset+2, int(value2))
}
// Generate the value of the surrogate pair.
value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF)
} else {
width = 2
}
default:
panic("impossible")
}
// Check if the character is in the allowed range:
// #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
// | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
// | [#x10000-#x10FFFF] (32 bit)
switch {
case value == 0x09:
case value == 0x0A:
case value == 0x0D:
case value >= 0x20 && value <= 0x7E:
case value == 0x85:
case value >= 0xA0 && value <= 0xD7FF:
case value >= 0xE000 && value <= 0xFFFD:
case value >= 0x10000 && value <= 0x10FFFF:
default:
return yaml_parser_set_reader_error(parser,
"control characters are not allowed",
parser.offset, int(value))
}
// Move the raw pointers.
parser.raw_buffer_pos += width
parser.offset += width
// Finally put the character into the buffer.
if value <= 0x7F {
// 0000 0000-0000 007F . 0xxxxxxx
parser.buffer[buffer_len+0] = byte(value)
buffer_len += 1
} else if value <= 0x7FF {
// 0000 0080-0000 07FF . 110xxxxx 10xxxxxx
parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6))
parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F))
buffer_len += 2
} else if value <= 0xFFFF {
// 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx
parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12))
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F))
parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F))
buffer_len += 3
} else {
// 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18))
parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F))
parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F))
parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F))
buffer_len += 4
}
parser.unread++
}
// On EOF, put NUL into the buffer and return.
if parser.eof {
parser.buffer[buffer_len] = 0
buffer_len++
parser.unread++
break
}
}
// [Go] Read the documentation of this function above. To return true,
// we need to have the given length in the buffer. Not doing that means
// every single check that calls this function to make sure the buffer
// has a given length is Go) panicking; or C) accessing invalid memory.
// This happens here due to the EOF above breaking early.
for buffer_len < length {
parser.buffer[buffer_len] = 0
buffer_len++
}
parser.buffer = parser.buffer[:buffer_len]
return true
}

View File

@@ -1,258 +0,0 @@
package yaml
import (
"encoding/base64"
"math"
"regexp"
"strconv"
"strings"
"time"
)
type resolveMapItem struct {
value interface{}
tag string
}
var resolveTable = make([]byte, 256)
var resolveMap = make(map[string]resolveMapItem)
func init() {
t := resolveTable
t[int('+')] = 'S' // Sign
t[int('-')] = 'S'
for _, c := range "0123456789" {
t[int(c)] = 'D' // Digit
}
for _, c := range "yYnNtTfFoO~" {
t[int(c)] = 'M' // In map
}
t[int('.')] = '.' // Float (potentially in map)
var resolveMapList = []struct {
v interface{}
tag string
l []string
}{
{true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}},
{true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}},
{true, yaml_BOOL_TAG, []string{"on", "On", "ON"}},
{false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}},
{false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}},
{false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}},
{nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}},
{math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}},
{math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}},
{math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}},
{math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}},
{"<<", yaml_MERGE_TAG, []string{"<<"}},
}
m := resolveMap
for _, item := range resolveMapList {
for _, s := range item.l {
m[s] = resolveMapItem{item.v, item.tag}
}
}
}
const longTagPrefix = "tag:yaml.org,2002:"
func shortTag(tag string) string {
// TODO This can easily be made faster and produce less garbage.
if strings.HasPrefix(tag, longTagPrefix) {
return "!!" + tag[len(longTagPrefix):]
}
return tag
}
func longTag(tag string) string {
if strings.HasPrefix(tag, "!!") {
return longTagPrefix + tag[2:]
}
return tag
}
func resolvableTag(tag string) bool {
switch tag {
case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG:
return true
}
return false
}
var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
func resolve(tag string, in string) (rtag string, out interface{}) {
if !resolvableTag(tag) {
return tag, in
}
defer func() {
switch tag {
case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
return
case yaml_FLOAT_TAG:
if rtag == yaml_INT_TAG {
switch v := out.(type) {
case int64:
rtag = yaml_FLOAT_TAG
out = float64(v)
return
case int:
rtag = yaml_FLOAT_TAG
out = float64(v)
return
}
}
}
failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
}()
// Any data is accepted as a !!str or !!binary.
// Otherwise, the prefix is enough of a hint about what it might be.
hint := byte('N')
if in != "" {
hint = resolveTable[in[0]]
}
if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG {
// Handle things we can lookup in a map.
if item, ok := resolveMap[in]; ok {
return item.tag, item.value
}
// Base 60 floats are a bad idea, were dropped in YAML 1.2, and
// are purposefully unsupported here. They're still quoted on
// the way out for compatibility with other parser, though.
switch hint {
case 'M':
// We've already checked the map above.
case '.':
// Not in the map, so maybe a normal float.
floatv, err := strconv.ParseFloat(in, 64)
if err == nil {
return yaml_FLOAT_TAG, floatv
}
case 'D', 'S':
// Int, float, or timestamp.
// Only try values as a timestamp if the value is unquoted or there's an explicit
// !!timestamp tag.
if tag == "" || tag == yaml_TIMESTAMP_TAG {
t, ok := parseTimestamp(in)
if ok {
return yaml_TIMESTAMP_TAG, t
}
}
plain := strings.Replace(in, "_", "", -1)
intv, err := strconv.ParseInt(plain, 0, 64)
if err == nil {
if intv == int64(int(intv)) {
return yaml_INT_TAG, int(intv)
} else {
return yaml_INT_TAG, intv
}
}
uintv, err := strconv.ParseUint(plain, 0, 64)
if err == nil {
return yaml_INT_TAG, uintv
}
if yamlStyleFloat.MatchString(plain) {
floatv, err := strconv.ParseFloat(plain, 64)
if err == nil {
return yaml_FLOAT_TAG, floatv
}
}
if strings.HasPrefix(plain, "0b") {
intv, err := strconv.ParseInt(plain[2:], 2, 64)
if err == nil {
if intv == int64(int(intv)) {
return yaml_INT_TAG, int(intv)
} else {
return yaml_INT_TAG, intv
}
}
uintv, err := strconv.ParseUint(plain[2:], 2, 64)
if err == nil {
return yaml_INT_TAG, uintv
}
} else if strings.HasPrefix(plain, "-0b") {
intv, err := strconv.ParseInt("-" + plain[3:], 2, 64)
if err == nil {
if true || intv == int64(int(intv)) {
return yaml_INT_TAG, int(intv)
} else {
return yaml_INT_TAG, intv
}
}
}
default:
panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
}
}
return yaml_STR_TAG, in
}
// encodeBase64 encodes s as base64 that is broken up into multiple lines
// as appropriate for the resulting length.
func encodeBase64(s string) string {
const lineLen = 70
encLen := base64.StdEncoding.EncodedLen(len(s))
lines := encLen/lineLen + 1
buf := make([]byte, encLen*2+lines)
in := buf[0:encLen]
out := buf[encLen:]
base64.StdEncoding.Encode(in, []byte(s))
k := 0
for i := 0; i < len(in); i += lineLen {
j := i + lineLen
if j > len(in) {
j = len(in)
}
k += copy(out[k:], in[i:j])
if lines > 1 {
out[k] = '\n'
k++
}
}
return string(out[:k])
}
// This is a subset of the formats allowed by the regular expression
// defined at http://yaml.org/type/timestamp.html.
var allowedTimestampFormats = []string{
"2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
"2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
"2006-1-2 15:4:5.999999999", // space separated with no time zone
"2006-1-2", // date only
// Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
// from the set of examples.
}
// parseTimestamp parses s as a timestamp string and
// returns the timestamp and reports whether it succeeded.
// Timestamp formats are defined at http://yaml.org/type/timestamp.html
func parseTimestamp(s string) (time.Time, bool) {
// TODO write code to check all the formats supported by
// http://yaml.org/type/timestamp.html instead of using time.Parse.
// Quick check: all date formats start with YYYY-.
i := 0
for ; i < len(s); i++ {
if c := s[i]; c < '0' || c > '9' {
break
}
}
if i != 4 || i == len(s) || s[i] != '-' {
return time.Time{}, false
}
for _, format := range allowedTimestampFormats {
if t, err := time.Parse(format, s); err == nil {
return t, true
}
}
return time.Time{}, false
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,113 +0,0 @@
package yaml
import (
"reflect"
"unicode"
)
type keyList []reflect.Value
func (l keyList) Len() int { return len(l) }
func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l keyList) Less(i, j int) bool {
a := l[i]
b := l[j]
ak := a.Kind()
bk := b.Kind()
for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
a = a.Elem()
ak = a.Kind()
}
for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
b = b.Elem()
bk = b.Kind()
}
af, aok := keyFloat(a)
bf, bok := keyFloat(b)
if aok && bok {
if af != bf {
return af < bf
}
if ak != bk {
return ak < bk
}
return numLess(a, b)
}
if ak != reflect.String || bk != reflect.String {
return ak < bk
}
ar, br := []rune(a.String()), []rune(b.String())
for i := 0; i < len(ar) && i < len(br); i++ {
if ar[i] == br[i] {
continue
}
al := unicode.IsLetter(ar[i])
bl := unicode.IsLetter(br[i])
if al && bl {
return ar[i] < br[i]
}
if al || bl {
return bl
}
var ai, bi int
var an, bn int64
if ar[i] == '0' || br[i] == '0' {
for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
if ar[j] != '0' {
an = 1
bn = 1
break
}
}
}
for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
an = an*10 + int64(ar[ai]-'0')
}
for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
bn = bn*10 + int64(br[bi]-'0')
}
if an != bn {
return an < bn
}
if ai != bi {
return ai < bi
}
return ar[i] < br[i]
}
return len(ar) < len(br)
}
// keyFloat returns a float value for v if it is a number/bool
// and whether it is a number/bool or not.
func keyFloat(v reflect.Value) (f float64, ok bool) {
switch v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return float64(v.Int()), true
case reflect.Float32, reflect.Float64:
return v.Float(), true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return float64(v.Uint()), true
case reflect.Bool:
if v.Bool() {
return 1, true
}
return 0, true
}
return 0, false
}
// numLess returns whether a < b.
// a and b must necessarily have the same kind.
func numLess(a, b reflect.Value) bool {
switch a.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return a.Int() < b.Int()
case reflect.Float32, reflect.Float64:
return a.Float() < b.Float()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return a.Uint() < b.Uint()
case reflect.Bool:
return !a.Bool() && b.Bool()
}
panic("not a number")
}

View File

@@ -1,26 +0,0 @@
package yaml
// Set the writer error and return false.
func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
emitter.error = yaml_WRITER_ERROR
emitter.problem = problem
return false
}
// Flush the output buffer.
func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
if emitter.write_handler == nil {
panic("write handler not set")
}
// Check if the buffer is empty.
if emitter.buffer_pos == 0 {
return true
}
if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
}
emitter.buffer_pos = 0
return true
}

View File

@@ -1,478 +0,0 @@
// Package yaml implements YAML support for the Go language.
//
// Source code and other details for the project are available at GitHub:
//
// https://github.com/go-yaml/yaml
//
package yaml
import (
"errors"
"fmt"
"io"
"reflect"
"strings"
"sync"
)
// MapSlice encodes and decodes as a YAML map.
// The order of keys is preserved when encoding and decoding.
type MapSlice []MapItem
// MapItem is an item in a MapSlice.
type MapItem struct {
Key, Value interface{}
}
// The Unmarshaler interface may be implemented by types to customize their
// behavior when being unmarshaled from a YAML document. The UnmarshalYAML
// method receives a function that may be called to unmarshal the original
// YAML value into a field or variable. It is safe to call the unmarshal
// function parameter more than once if necessary.
type Unmarshaler interface {
UnmarshalYAML(unmarshal func(interface{}) error) error
}
// The Marshaler interface may be implemented by types to customize their
// behavior when being marshaled into a YAML document. The returned value
// is marshaled in place of the original value implementing Marshaler.
//
// If an error is returned by MarshalYAML, the marshaling procedure stops
// and returns with the provided error.
type Marshaler interface {
MarshalYAML() (interface{}, error)
}
// Unmarshal decodes the first document found within the in byte slice
// and assigns decoded values into the out value.
//
// Maps and pointers (to a struct, string, int, etc) are accepted as out
// values. If an internal pointer within a struct is not initialized,
// the yaml package will initialize it if necessary for unmarshalling
// the provided data. The out parameter must not be nil.
//
// The type of the decoded values should be compatible with the respective
// values in out. If one or more values cannot be decoded due to a type
// mismatches, decoding continues partially until the end of the YAML
// content, and a *yaml.TypeError is returned with details for all
// missed values.
//
// Struct fields are only unmarshalled if they are exported (have an
// upper case first letter), and are unmarshalled using the field name
// lowercased as the default key. Custom keys may be defined via the
// "yaml" name in the field tag: the content preceding the first comma
// is used as the key, and the following comma-separated options are
// used to tweak the marshalling process (see Marshal).
// Conflicting names result in a runtime error.
//
// For example:
//
// type T struct {
// F int `yaml:"a,omitempty"`
// B int
// }
// var t T
// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t)
//
// See the documentation of Marshal for the format of tags and a list of
// supported tag options.
//
func Unmarshal(in []byte, out interface{}) (err error) {
return unmarshal(in, out, false)
}
// UnmarshalStrict is like Unmarshal except that any fields that are found
// in the data that do not have corresponding struct members, or mapping
// keys that are duplicates, will result in
// an error.
func UnmarshalStrict(in []byte, out interface{}) (err error) {
return unmarshal(in, out, true)
}
// A Decoder reads and decodes YAML values from an input stream.
type Decoder struct {
strict bool
parser *parser
}
// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may read
// data from r beyond the YAML values requested.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{
parser: newParserFromReader(r),
}
}
// SetStrict sets whether strict decoding behaviour is enabled when
// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict.
func (dec *Decoder) SetStrict(strict bool) {
dec.strict = strict
}
// Decode reads the next YAML-encoded value from its input
// and stores it in the value pointed to by v.
//
// See the documentation for Unmarshal for details about the
// conversion of YAML into a Go value.
func (dec *Decoder) Decode(v interface{}) (err error) {
d := newDecoder(dec.strict)
defer handleErr(&err)
node := dec.parser.parse()
if node == nil {
return io.EOF
}
out := reflect.ValueOf(v)
if out.Kind() == reflect.Ptr && !out.IsNil() {
out = out.Elem()
}
d.unmarshal(node, out)
if len(d.terrors) > 0 {
return &TypeError{d.terrors}
}
return nil
}
func unmarshal(in []byte, out interface{}, strict bool) (err error) {
defer handleErr(&err)
d := newDecoder(strict)
p := newParser(in)
defer p.destroy()
node := p.parse()
if node != nil {
v := reflect.ValueOf(out)
if v.Kind() == reflect.Ptr && !v.IsNil() {
v = v.Elem()
}
d.unmarshal(node, v)
}
if len(d.terrors) > 0 {
return &TypeError{d.terrors}
}
return nil
}
// Marshal serializes the value provided into a YAML document. The structure
// of the generated document will reflect the structure of the value itself.
// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
//
// Struct fields are only marshalled if they are exported (have an upper case
// first letter), and are marshalled using the field name lowercased as the
// default key. Custom keys may be defined via the "yaml" name in the field
// tag: the content preceding the first comma is used as the key, and the
// following comma-separated options are used to tweak the marshalling process.
// Conflicting names result in a runtime error.
//
// The field tag format accepted is:
//
// `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
//
// The following flags are currently supported:
//
// omitempty Only include the field if it's not set to the zero
// value for the type or to empty slices or maps.
// Zero valued structs will be omitted if all their public
// fields are zero, unless they implement an IsZero
// method (see the IsZeroer interface type), in which
// case the field will be excluded if IsZero returns true.
//
// flow Marshal using a flow style (useful for structs,
// sequences and maps).
//
// inline Inline the field, which must be a struct or a map,
// causing all of its fields or keys to be processed as if
// they were part of the outer struct. For maps, keys must
// not conflict with the yaml keys of other struct fields.
//
// In addition, if the key is "-", the field is ignored.
//
// For example:
//
// type T struct {
// F int `yaml:"a,omitempty"`
// B int
// }
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
//
func Marshal(in interface{}) (out []byte, err error) {
defer handleErr(&err)
e := newEncoder()
defer e.destroy()
e.marshalDoc("", reflect.ValueOf(in))
e.finish()
out = e.out
return
}
// An Encoder writes YAML values to an output stream.
type Encoder struct {
encoder *encoder
}
// NewEncoder returns a new encoder that writes to w.
// The Encoder should be closed after use to flush all data
// to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{
encoder: newEncoderWithWriter(w),
}
}
// Encode writes the YAML encoding of v to the stream.
// If multiple items are encoded to the stream, the
// second and subsequent document will be preceded
// with a "---" document separator, but the first will not.
//
// See the documentation for Marshal for details about the conversion of Go
// values to YAML.
func (e *Encoder) Encode(v interface{}) (err error) {
defer handleErr(&err)
e.encoder.marshalDoc("", reflect.ValueOf(v))
return nil
}
// Close closes the encoder by writing any remaining data.
// It does not write a stream terminating string "...".
func (e *Encoder) Close() (err error) {
defer handleErr(&err)
e.encoder.finish()
return nil
}
func handleErr(err *error) {
if v := recover(); v != nil {
if e, ok := v.(yamlError); ok {
*err = e.err
} else {
panic(v)
}
}
}
type yamlError struct {
err error
}
func fail(err error) {
panic(yamlError{err})
}
func failf(format string, args ...interface{}) {
panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
}
// A TypeError is returned by Unmarshal when one or more fields in
// the YAML document cannot be properly decoded into the requested
// types. When this error is returned, the value is still
// unmarshaled partially.
type TypeError struct {
Errors []string
}
func (e *TypeError) Error() string {
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
}
// --------------------------------------------------------------------------
// Maintain a mapping of keys to structure field indexes
// The code in this section was copied from mgo/bson.
// structInfo holds details for the serialization of fields of
// a given struct.
type structInfo struct {
FieldsMap map[string]fieldInfo
FieldsList []fieldInfo
// InlineMap is the number of the field in the struct that
// contains an ,inline map, or -1 if there's none.
InlineMap int
}
type fieldInfo struct {
Key string
Num int
OmitEmpty bool
Flow bool
// Id holds the unique field identifier, so we can cheaply
// check for field duplicates without maintaining an extra map.
Id int
// Inline holds the field index if the field is part of an inlined struct.
Inline []int
}
var structMap = make(map[reflect.Type]*structInfo)
var fieldMapMutex sync.RWMutex
func getStructInfo(st reflect.Type) (*structInfo, error) {
fieldMapMutex.RLock()
sinfo, found := structMap[st]
fieldMapMutex.RUnlock()
if found {
return sinfo, nil
}
n := st.NumField()
fieldsMap := make(map[string]fieldInfo)
fieldsList := make([]fieldInfo, 0, n)
inlineMap := -1
for i := 0; i != n; i++ {
field := st.Field(i)
if field.PkgPath != "" && !field.Anonymous {
continue // Private field
}
info := fieldInfo{Num: i}
tag := field.Tag.Get("yaml")
if tag == "" && strings.Index(string(field.Tag), ":") < 0 {
tag = string(field.Tag)
}
if tag == "-" {
continue
}
inline := false
fields := strings.Split(tag, ",")
if len(fields) > 1 {
for _, flag := range fields[1:] {
switch flag {
case "omitempty":
info.OmitEmpty = true
case "flow":
info.Flow = true
case "inline":
inline = true
default:
return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st))
}
}
tag = fields[0]
}
if inline {
switch field.Type.Kind() {
case reflect.Map:
if inlineMap >= 0 {
return nil, errors.New("Multiple ,inline maps in struct " + st.String())
}
if field.Type.Key() != reflect.TypeOf("") {
return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String())
}
inlineMap = info.Num
case reflect.Struct:
sinfo, err := getStructInfo(field.Type)
if err != nil {
return nil, err
}
for _, finfo := range sinfo.FieldsList {
if _, found := fieldsMap[finfo.Key]; found {
msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String()
return nil, errors.New(msg)
}
if finfo.Inline == nil {
finfo.Inline = []int{i, finfo.Num}
} else {
finfo.Inline = append([]int{i}, finfo.Inline...)
}
finfo.Id = len(fieldsList)
fieldsMap[finfo.Key] = finfo
fieldsList = append(fieldsList, finfo)
}
default:
//return nil, errors.New("Option ,inline needs a struct value or map field")
return nil, errors.New("Option ,inline needs a struct value field")
}
continue
}
if tag != "" {
info.Key = tag
} else {
info.Key = strings.ToLower(field.Name)
}
if _, found = fieldsMap[info.Key]; found {
msg := "Duplicated key '" + info.Key + "' in struct " + st.String()
return nil, errors.New(msg)
}
info.Id = len(fieldsList)
fieldsList = append(fieldsList, info)
fieldsMap[info.Key] = info
}
sinfo = &structInfo{
FieldsMap: fieldsMap,
FieldsList: fieldsList,
InlineMap: inlineMap,
}
fieldMapMutex.Lock()
structMap[st] = sinfo
fieldMapMutex.Unlock()
return sinfo, nil
}
// IsZeroer is used to check whether an object is zero to
// determine whether it should be omitted when marshaling
// with the omitempty flag. One notable implementation
// is time.Time.
type IsZeroer interface {
IsZero() bool
}
func isZero(v reflect.Value) bool {
kind := v.Kind()
if z, ok := v.Interface().(IsZeroer); ok {
if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
return true
}
return z.IsZero()
}
switch kind {
case reflect.String:
return len(v.String()) == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
case reflect.Slice:
return v.Len() == 0
case reflect.Map:
return v.Len() == 0
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Struct:
vt := v.Type()
for i := v.NumField() - 1; i >= 0; i-- {
if vt.Field(i).PkgPath != "" {
continue // Private field
}
if !isZero(v.Field(i)) {
return false
}
}
return true
}
return false
}
// FutureLineWrap globally disables line wrapping when encoding long strings.
// This is a temporary and thus deprecated method introduced to faciliate
// migration towards v3, which offers more control of line lengths on
// individual encodings, and has a default matching the behavior introduced
// by this function.
//
// The default formatting of v2 was erroneously changed in v2.3.0 and reverted
// in v2.4.0, at which point this function was introduced to help migration.
func FutureLineWrap() {
disableLineWrapping = true
}

View File

@@ -1,739 +0,0 @@
package yaml
import (
"fmt"
"io"
)
// The version directive data.
type yaml_version_directive_t struct {
major int8 // The major version number.
minor int8 // The minor version number.
}
// The tag directive data.
type yaml_tag_directive_t struct {
handle []byte // The tag handle.
prefix []byte // The tag prefix.
}
type yaml_encoding_t int
// The stream encoding.
const (
// Let the parser choose the encoding.
yaml_ANY_ENCODING yaml_encoding_t = iota
yaml_UTF8_ENCODING // The default UTF-8 encoding.
yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM.
yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM.
)
type yaml_break_t int
// Line break types.
const (
// Let the parser choose the break type.
yaml_ANY_BREAK yaml_break_t = iota
yaml_CR_BREAK // Use CR for line breaks (Mac style).
yaml_LN_BREAK // Use LN for line breaks (Unix style).
yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style).
)
type yaml_error_type_t int
// Many bad things could happen with the parser and emitter.
const (
// No error is produced.
yaml_NO_ERROR yaml_error_type_t = iota
yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory.
yaml_READER_ERROR // Cannot read or decode the input stream.
yaml_SCANNER_ERROR // Cannot scan the input stream.
yaml_PARSER_ERROR // Cannot parse the input stream.
yaml_COMPOSER_ERROR // Cannot compose a YAML document.
yaml_WRITER_ERROR // Cannot write to the output stream.
yaml_EMITTER_ERROR // Cannot emit a YAML stream.
)
// The pointer position.
type yaml_mark_t struct {
index int // The position index.
line int // The position line.
column int // The position column.
}
// Node Styles
type yaml_style_t int8
type yaml_scalar_style_t yaml_style_t
// Scalar styles.
const (
// Let the emitter choose the style.
yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
yaml_PLAIN_SCALAR_STYLE // The plain scalar style.
yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style.
yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style.
yaml_LITERAL_SCALAR_STYLE // The literal scalar style.
yaml_FOLDED_SCALAR_STYLE // The folded scalar style.
)
type yaml_sequence_style_t yaml_style_t
// Sequence styles.
const (
// Let the emitter choose the style.
yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
yaml_BLOCK_SEQUENCE_STYLE // The block sequence style.
yaml_FLOW_SEQUENCE_STYLE // The flow sequence style.
)
type yaml_mapping_style_t yaml_style_t
// Mapping styles.
const (
// Let the emitter choose the style.
yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
yaml_BLOCK_MAPPING_STYLE // The block mapping style.
yaml_FLOW_MAPPING_STYLE // The flow mapping style.
)
// Tokens
type yaml_token_type_t int
// Token types.
const (
// An empty token.
yaml_NO_TOKEN yaml_token_type_t = iota
yaml_STREAM_START_TOKEN // A STREAM-START token.
yaml_STREAM_END_TOKEN // A STREAM-END token.
yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token.
yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token.
yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token.
yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token.
yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token.
yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token.
yaml_BLOCK_END_TOKEN // A BLOCK-END token.
yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token.
yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token.
yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token.
yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token.
yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token.
yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token.
yaml_KEY_TOKEN // A KEY token.
yaml_VALUE_TOKEN // A VALUE token.
yaml_ALIAS_TOKEN // An ALIAS token.
yaml_ANCHOR_TOKEN // An ANCHOR token.
yaml_TAG_TOKEN // A TAG token.
yaml_SCALAR_TOKEN // A SCALAR token.
)
func (tt yaml_token_type_t) String() string {
switch tt {
case yaml_NO_TOKEN:
return "yaml_NO_TOKEN"
case yaml_STREAM_START_TOKEN:
return "yaml_STREAM_START_TOKEN"
case yaml_STREAM_END_TOKEN:
return "yaml_STREAM_END_TOKEN"
case yaml_VERSION_DIRECTIVE_TOKEN:
return "yaml_VERSION_DIRECTIVE_TOKEN"
case yaml_TAG_DIRECTIVE_TOKEN:
return "yaml_TAG_DIRECTIVE_TOKEN"
case yaml_DOCUMENT_START_TOKEN:
return "yaml_DOCUMENT_START_TOKEN"
case yaml_DOCUMENT_END_TOKEN:
return "yaml_DOCUMENT_END_TOKEN"
case yaml_BLOCK_SEQUENCE_START_TOKEN:
return "yaml_BLOCK_SEQUENCE_START_TOKEN"
case yaml_BLOCK_MAPPING_START_TOKEN:
return "yaml_BLOCK_MAPPING_START_TOKEN"
case yaml_BLOCK_END_TOKEN:
return "yaml_BLOCK_END_TOKEN"
case yaml_FLOW_SEQUENCE_START_TOKEN:
return "yaml_FLOW_SEQUENCE_START_TOKEN"
case yaml_FLOW_SEQUENCE_END_TOKEN:
return "yaml_FLOW_SEQUENCE_END_TOKEN"
case yaml_FLOW_MAPPING_START_TOKEN:
return "yaml_FLOW_MAPPING_START_TOKEN"
case yaml_FLOW_MAPPING_END_TOKEN:
return "yaml_FLOW_MAPPING_END_TOKEN"
case yaml_BLOCK_ENTRY_TOKEN:
return "yaml_BLOCK_ENTRY_TOKEN"
case yaml_FLOW_ENTRY_TOKEN:
return "yaml_FLOW_ENTRY_TOKEN"
case yaml_KEY_TOKEN:
return "yaml_KEY_TOKEN"
case yaml_VALUE_TOKEN:
return "yaml_VALUE_TOKEN"
case yaml_ALIAS_TOKEN:
return "yaml_ALIAS_TOKEN"
case yaml_ANCHOR_TOKEN:
return "yaml_ANCHOR_TOKEN"
case yaml_TAG_TOKEN:
return "yaml_TAG_TOKEN"
case yaml_SCALAR_TOKEN:
return "yaml_SCALAR_TOKEN"
}
return "<unknown token>"
}
// The token structure.
type yaml_token_t struct {
// The token type.
typ yaml_token_type_t
// The start/end of the token.
start_mark, end_mark yaml_mark_t
// The stream encoding (for yaml_STREAM_START_TOKEN).
encoding yaml_encoding_t
// The alias/anchor/scalar value or tag/tag directive handle
// (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN).
value []byte
// The tag suffix (for yaml_TAG_TOKEN).
suffix []byte
// The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN).
prefix []byte
// The scalar style (for yaml_SCALAR_TOKEN).
style yaml_scalar_style_t
// The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN).
major, minor int8
}
// Events
type yaml_event_type_t int8
// Event types.
const (
// An empty event.
yaml_NO_EVENT yaml_event_type_t = iota
yaml_STREAM_START_EVENT // A STREAM-START event.
yaml_STREAM_END_EVENT // A STREAM-END event.
yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event.
yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event.
yaml_ALIAS_EVENT // An ALIAS event.
yaml_SCALAR_EVENT // A SCALAR event.
yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event.
yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event.
yaml_MAPPING_START_EVENT // A MAPPING-START event.
yaml_MAPPING_END_EVENT // A MAPPING-END event.
)
var eventStrings = []string{
yaml_NO_EVENT: "none",
yaml_STREAM_START_EVENT: "stream start",
yaml_STREAM_END_EVENT: "stream end",
yaml_DOCUMENT_START_EVENT: "document start",
yaml_DOCUMENT_END_EVENT: "document end",
yaml_ALIAS_EVENT: "alias",
yaml_SCALAR_EVENT: "scalar",
yaml_SEQUENCE_START_EVENT: "sequence start",
yaml_SEQUENCE_END_EVENT: "sequence end",
yaml_MAPPING_START_EVENT: "mapping start",
yaml_MAPPING_END_EVENT: "mapping end",
}
func (e yaml_event_type_t) String() string {
if e < 0 || int(e) >= len(eventStrings) {
return fmt.Sprintf("unknown event %d", e)
}
return eventStrings[e]
}
// The event structure.
type yaml_event_t struct {
// The event type.
typ yaml_event_type_t
// The start and end of the event.
start_mark, end_mark yaml_mark_t
// The document encoding (for yaml_STREAM_START_EVENT).
encoding yaml_encoding_t
// The version directive (for yaml_DOCUMENT_START_EVENT).
version_directive *yaml_version_directive_t
// The list of tag directives (for yaml_DOCUMENT_START_EVENT).
tag_directives []yaml_tag_directive_t
// The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT).
anchor []byte
// The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
tag []byte
// The scalar value (for yaml_SCALAR_EVENT).
value []byte
// Is the document start/end indicator implicit, or the tag optional?
// (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT).
implicit bool
// Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT).
quoted_implicit bool
// The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT).
style yaml_style_t
}
func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) }
func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) }
func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) }
// Nodes
const (
yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null.
yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false.
yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values.
yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values.
yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values.
yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values.
yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences.
yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping.
// Not in original libyaml.
yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str.
yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq.
yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map.
)
type yaml_node_type_t int
// Node types.
const (
// An empty node.
yaml_NO_NODE yaml_node_type_t = iota
yaml_SCALAR_NODE // A scalar node.
yaml_SEQUENCE_NODE // A sequence node.
yaml_MAPPING_NODE // A mapping node.
)
// An element of a sequence node.
type yaml_node_item_t int
// An element of a mapping node.
type yaml_node_pair_t struct {
key int // The key of the element.
value int // The value of the element.
}
// The node structure.
type yaml_node_t struct {
typ yaml_node_type_t // The node type.
tag []byte // The node tag.
// The node data.
// The scalar parameters (for yaml_SCALAR_NODE).
scalar struct {
value []byte // The scalar value.
length int // The length of the scalar value.
style yaml_scalar_style_t // The scalar style.
}
// The sequence parameters (for YAML_SEQUENCE_NODE).
sequence struct {
items_data []yaml_node_item_t // The stack of sequence items.
style yaml_sequence_style_t // The sequence style.
}
// The mapping parameters (for yaml_MAPPING_NODE).
mapping struct {
pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value).
pairs_start *yaml_node_pair_t // The beginning of the stack.
pairs_end *yaml_node_pair_t // The end of the stack.
pairs_top *yaml_node_pair_t // The top of the stack.
style yaml_mapping_style_t // The mapping style.
}
start_mark yaml_mark_t // The beginning of the node.
end_mark yaml_mark_t // The end of the node.
}
// The document structure.
type yaml_document_t struct {
// The document nodes.
nodes []yaml_node_t
// The version directive.
version_directive *yaml_version_directive_t
// The list of tag directives.
tag_directives_data []yaml_tag_directive_t
tag_directives_start int // The beginning of the tag directives list.
tag_directives_end int // The end of the tag directives list.
start_implicit int // Is the document start indicator implicit?
end_implicit int // Is the document end indicator implicit?
// The start/end of the document.
start_mark, end_mark yaml_mark_t
}
// The prototype of a read handler.
//
// The read handler is called when the parser needs to read more bytes from the
// source. The handler should write not more than size bytes to the buffer.
// The number of written bytes should be set to the size_read variable.
//
// [in,out] data A pointer to an application data specified by
// yaml_parser_set_input().
// [out] buffer The buffer to write the data from the source.
// [in] size The size of the buffer.
// [out] size_read The actual number of bytes read from the source.
//
// On success, the handler should return 1. If the handler failed,
// the returned value should be 0. On EOF, the handler should set the
// size_read to 0 and return 1.
type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
// This structure holds information about a potential simple key.
type yaml_simple_key_t struct {
possible bool // Is a simple key possible?
required bool // Is a simple key required?
token_number int // The number of the token.
mark yaml_mark_t // The position mark.
}
// The states of the parser.
type yaml_parser_state_t int
const (
yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document.
yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START.
yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document.
yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END.
yaml_PARSE_BLOCK_NODE_STATE // Expect a block node.
yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence.
yaml_PARSE_FLOW_NODE_STATE // Expect a flow node.
yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence.
yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence.
yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence.
yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key.
yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value.
yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence.
yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence.
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping.
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping.
yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry.
yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping.
yaml_PARSE_END_STATE // Expect nothing.
)
func (ps yaml_parser_state_t) String() string {
switch ps {
case yaml_PARSE_STREAM_START_STATE:
return "yaml_PARSE_STREAM_START_STATE"
case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE:
return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE"
case yaml_PARSE_DOCUMENT_START_STATE:
return "yaml_PARSE_DOCUMENT_START_STATE"
case yaml_PARSE_DOCUMENT_CONTENT_STATE:
return "yaml_PARSE_DOCUMENT_CONTENT_STATE"
case yaml_PARSE_DOCUMENT_END_STATE:
return "yaml_PARSE_DOCUMENT_END_STATE"
case yaml_PARSE_BLOCK_NODE_STATE:
return "yaml_PARSE_BLOCK_NODE_STATE"
case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE:
return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE"
case yaml_PARSE_FLOW_NODE_STATE:
return "yaml_PARSE_FLOW_NODE_STATE"
case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE:
return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE"
case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE:
return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE"
case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE:
return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE"
case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE:
return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE"
case yaml_PARSE_BLOCK_MAPPING_KEY_STATE:
return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE"
case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE:
return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE"
case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE:
return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE"
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE:
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE"
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE:
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE"
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE:
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE"
case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE:
return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE"
case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE:
return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE"
case yaml_PARSE_FLOW_MAPPING_KEY_STATE:
return "yaml_PARSE_FLOW_MAPPING_KEY_STATE"
case yaml_PARSE_FLOW_MAPPING_VALUE_STATE:
return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE"
case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE:
return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE"
case yaml_PARSE_END_STATE:
return "yaml_PARSE_END_STATE"
}
return "<unknown parser state>"
}
// This structure holds aliases data.
type yaml_alias_data_t struct {
anchor []byte // The anchor.
index int // The node id.
mark yaml_mark_t // The anchor mark.
}
// The parser structure.
//
// All members are internal. Manage the structure using the
// yaml_parser_ family of functions.
type yaml_parser_t struct {
// Error handling
error yaml_error_type_t // Error type.
problem string // Error description.
// The byte about which the problem occurred.
problem_offset int
problem_value int
problem_mark yaml_mark_t
// The error context.
context string
context_mark yaml_mark_t
// Reader stuff
read_handler yaml_read_handler_t // Read handler.
input_reader io.Reader // File input data.
input []byte // String input data.
input_pos int
eof bool // EOF flag
buffer []byte // The working buffer.
buffer_pos int // The current position of the buffer.
unread int // The number of unread characters in the buffer.
raw_buffer []byte // The raw buffer.
raw_buffer_pos int // The current position of the buffer.
encoding yaml_encoding_t // The input encoding.
offset int // The offset of the current position (in bytes).
mark yaml_mark_t // The mark of the current position.
// Scanner stuff
stream_start_produced bool // Have we started to scan the input stream?
stream_end_produced bool // Have we reached the end of the input stream?
flow_level int // The number of unclosed '[' and '{' indicators.
tokens []yaml_token_t // The tokens queue.
tokens_head int // The head of the tokens queue.
tokens_parsed int // The number of tokens fetched from the queue.
token_available bool // Does the tokens queue contain a token ready for dequeueing.
indent int // The current indentation level.
indents []int // The indentation levels stack.
simple_key_allowed bool // May a simple key occur at the current position?
simple_keys []yaml_simple_key_t // The stack of simple keys.
simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number
// Parser stuff
state yaml_parser_state_t // The current parser state.
states []yaml_parser_state_t // The parser states stack.
marks []yaml_mark_t // The stack of marks.
tag_directives []yaml_tag_directive_t // The list of TAG directives.
// Dumper stuff
aliases []yaml_alias_data_t // The alias data.
document *yaml_document_t // The currently parsed document.
}
// Emitter Definitions
// The prototype of a write handler.
//
// The write handler is called when the emitter needs to flush the accumulated
// characters to the output. The handler should write @a size bytes of the
// @a buffer to the output.
//
// @param[in,out] data A pointer to an application data specified by
// yaml_emitter_set_output().
// @param[in] buffer The buffer with bytes to be written.
// @param[in] size The size of the buffer.
//
// @returns On success, the handler should return @c 1. If the handler failed,
// the returned value should be @c 0.
//
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
type yaml_emitter_state_t int
// The emitter states.
const (
// Expect STREAM-START.
yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END.
yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END.
yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document.
yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END.
yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence.
yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence.
yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping.
yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping.
yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping.
yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping.
yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence.
yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence.
yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping.
yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping.
yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping.
yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping.
yaml_EMIT_END_STATE // Expect nothing.
)
// The emitter structure.
//
// All members are internal. Manage the structure using the @c yaml_emitter_
// family of functions.
type yaml_emitter_t struct {
// Error handling
error yaml_error_type_t // Error type.
problem string // Error description.
// Writer stuff
write_handler yaml_write_handler_t // Write handler.
output_buffer *[]byte // String output data.
output_writer io.Writer // File output data.
buffer []byte // The working buffer.
buffer_pos int // The current position of the buffer.
raw_buffer []byte // The raw buffer.
raw_buffer_pos int // The current position of the buffer.
encoding yaml_encoding_t // The stream encoding.
// Emitter stuff
canonical bool // If the output is in the canonical style?
best_indent int // The number of indentation spaces.
best_width int // The preferred width of the output lines.
unicode bool // Allow unescaped non-ASCII characters?
line_break yaml_break_t // The preferred line break.
state yaml_emitter_state_t // The current emitter state.
states []yaml_emitter_state_t // The stack of states.
events []yaml_event_t // The event queue.
events_head int // The head of the event queue.
indents []int // The stack of indentation levels.
tag_directives []yaml_tag_directive_t // The list of tag directives.
indent int // The current indentation level.
flow_level int // The current flow level.
root_context bool // Is it the document root context?
sequence_context bool // Is it a sequence context?
mapping_context bool // Is it a mapping context?
simple_key_context bool // Is it a simple mapping key context?
line int // The current line.
column int // The current column.
whitespace bool // If the last character was a whitespace?
indention bool // If the last character was an indentation character (' ', '-', '?', ':')?
open_ended bool // If an explicit document end is required?
// Anchor analysis.
anchor_data struct {
anchor []byte // The anchor value.
alias bool // Is it an alias?
}
// Tag analysis.
tag_data struct {
handle []byte // The tag handle.
suffix []byte // The tag suffix.
}
// Scalar analysis.
scalar_data struct {
value []byte // The scalar value.
multiline bool // Does the scalar contain line breaks?
flow_plain_allowed bool // Can the scalar be expessed in the flow plain style?
block_plain_allowed bool // Can the scalar be expressed in the block plain style?
single_quoted_allowed bool // Can the scalar be expressed in the single quoted style?
block_allowed bool // Can the scalar be expressed in the literal or folded styles?
style yaml_scalar_style_t // The output style.
}
// Dumper stuff
opened bool // If the stream was already opened?
closed bool // If the stream was already closed?
// The information associated with the document nodes.
anchors *struct {
references int // The number of references.
anchor int // The anchor id.
serialized bool // If the node has been emitted?
}
last_anchor_id int // The last assigned anchor id.
document *yaml_document_t // The currently emitted document.
}

View File

@@ -1,173 +0,0 @@
package yaml
const (
// The size of the input raw buffer.
input_raw_buffer_size = 512
// The size of the input buffer.
// It should be possible to decode the whole raw buffer.
input_buffer_size = input_raw_buffer_size * 3
// The size of the output buffer.
output_buffer_size = 128
// The size of the output raw buffer.
// It should be possible to encode the whole output buffer.
output_raw_buffer_size = (output_buffer_size*2 + 2)
// The size of other stacks and queues.
initial_stack_size = 16
initial_queue_size = 16
initial_string_size = 16
)
// Check if the character at the specified position is an alphabetical
// character, a digit, '_', or '-'.
func is_alpha(b []byte, i int) bool {
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-'
}
// Check if the character at the specified position is a digit.
func is_digit(b []byte, i int) bool {
return b[i] >= '0' && b[i] <= '9'
}
// Get the value of a digit.
func as_digit(b []byte, i int) int {
return int(b[i]) - '0'
}
// Check if the character at the specified position is a hex-digit.
func is_hex(b []byte, i int) bool {
return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f'
}
// Get the value of a hex-digit.
func as_hex(b []byte, i int) int {
bi := b[i]
if bi >= 'A' && bi <= 'F' {
return int(bi) - 'A' + 10
}
if bi >= 'a' && bi <= 'f' {
return int(bi) - 'a' + 10
}
return int(bi) - '0'
}
// Check if the character is ASCII.
func is_ascii(b []byte, i int) bool {
return b[i] <= 0x7F
}
// Check if the character at the start of the buffer can be printed unescaped.
func is_printable(b []byte, i int) bool {
return ((b[i] == 0x0A) || // . == #x0A
(b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E
(b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF
(b[i] > 0xC2 && b[i] < 0xED) ||
(b[i] == 0xED && b[i+1] < 0xA0) ||
(b[i] == 0xEE) ||
(b[i] == 0xEF && // #xE000 <= . <= #xFFFD
!(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF
!(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF))))
}
// Check if the character at the specified position is NUL.
func is_z(b []byte, i int) bool {
return b[i] == 0x00
}
// Check if the beginning of the buffer is a BOM.
func is_bom(b []byte, i int) bool {
return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
}
// Check if the character at the specified position is space.
func is_space(b []byte, i int) bool {
return b[i] == ' '
}
// Check if the character at the specified position is tab.
func is_tab(b []byte, i int) bool {
return b[i] == '\t'
}
// Check if the character at the specified position is blank (space or tab).
func is_blank(b []byte, i int) bool {
//return is_space(b, i) || is_tab(b, i)
return b[i] == ' ' || b[i] == '\t'
}
// Check if the character at the specified position is a line break.
func is_break(b []byte, i int) bool {
return (b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029)
}
func is_crlf(b []byte, i int) bool {
return b[i] == '\r' && b[i+1] == '\n'
}
// Check if the character is a line break or NUL.
func is_breakz(b []byte, i int) bool {
//return is_break(b, i) || is_z(b, i)
return ( // is_break:
b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
// is_z:
b[i] == 0)
}
// Check if the character is a line break, space, or NUL.
func is_spacez(b []byte, i int) bool {
//return is_space(b, i) || is_breakz(b, i)
return ( // is_space:
b[i] == ' ' ||
// is_breakz:
b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
b[i] == 0)
}
// Check if the character is a line break, space, tab, or NUL.
func is_blankz(b []byte, i int) bool {
//return is_blank(b, i) || is_breakz(b, i)
return ( // is_blank:
b[i] == ' ' || b[i] == '\t' ||
// is_breakz:
b[i] == '\r' || // CR (#xD)
b[i] == '\n' || // LF (#xA)
b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028)
b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029)
b[i] == 0)
}
// Determine the width of the character.
func width(b byte) int {
// Don't replace these by a switch without first
// confirming that it is being inlined.
if b&0x80 == 0x00 {
return 1
}
if b&0xE0 == 0xC0 {
return 2
}
if b&0xF0 == 0xE0 {
return 3
}
if b&0xF8 == 0xF0 {
return 4
}
return 0
}

11
vendor/sigs.k8s.io/yaml/yaml.go generated vendored
View File

@@ -24,7 +24,7 @@ import (
"reflect"
"strconv"
"sigs.k8s.io/yaml/goyaml.v2"
"go.yaml.in/yaml/v2"
)
// Marshal marshals obj into JSON using stdlib json.Marshal, and then converts JSON to YAML using JSONToYAML (see that method for more reference)
@@ -92,7 +92,7 @@ func jsonUnmarshal(reader io.Reader, obj interface{}, opts ...JSONOpt) error {
d = opt(d)
}
if err := d.Decode(&obj); err != nil {
return fmt.Errorf("while decoding JSON: %v", err)
return fmt.Errorf("while decoding JSON: %w", err)
}
return nil
}
@@ -417,3 +417,10 @@ func jsonToYAMLValue(j interface{}) interface{} {
}
return j
}
// DisallowUnknownFields configures the JSON decoder to error out if unknown
// fields come along, instead of dropping them by default.
func DisallowUnknownFields(d *json.Decoder) *json.Decoder {
d.DisallowUnknownFields()
return d
}

View File

@@ -1,31 +0,0 @@
// This file contains changes that are only compatible with go 1.10 and onwards.
//go:build go1.10
// +build go1.10
/*
Copyright 2021 The Kubernetes 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 yaml
import "encoding/json"
// DisallowUnknownFields configures the JSON decoder to error out if unknown
// fields come along, instead of dropping them by default.
func DisallowUnknownFields(d *json.Decoder) *json.Decoder {
d.DisallowUnknownFields()
return d
}