Merge pull request #1135 from Random-Liu/update-containerd

Update containerd
This commit is contained in:
Lantao Liu 2019-04-12 16:07:12 -07:00 committed by GitHub
commit a7021d687a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 2775 additions and 466 deletions

View File

@ -158,6 +158,8 @@ fi
log_level="${CONTAINERD_LOG_LEVEL:-"info"}" log_level="${CONTAINERD_LOG_LEVEL:-"info"}"
max_container_log_line="${CONTAINERD_MAX_CONTAINER_LOG_LINE:-16384}" max_container_log_line="${CONTAINERD_MAX_CONTAINER_LOG_LINE:-16384}"
cat > ${config_path} <<EOF cat > ${config_path} <<EOF
# Kubernetes requires the cri plugin.
required_plugins = ["cri"]
# Kubernetes doesn't use containerd restart manager. # Kubernetes doesn't use containerd restart manager.
disabled_plugins = ["restart"] disabled_plugins = ["restart"]

View File

@ -1,8 +1,8 @@
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 github.com/BurntSushi/toml v0.3.1
github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1 github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1
github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
github.com/containerd/containerd 591e52c504b23a89096bd7d3091a32fcfa2e92fc github.com/containerd/containerd 32e788a8be3ab4418265693d9e742c30495fdd4c
github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4 github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
github.com/containerd/go-cni 891c2a41e18144b2d7921f971d6c9789a68046b2 github.com/containerd/go-cni 891c2a41e18144b2d7921f971d6c9789a68046b2
@ -21,7 +21,7 @@ github.com/docker/go-units v0.3.1
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528 github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
github.com/emicklei/go-restful v2.2.1 github.com/emicklei/go-restful v2.2.1
github.com/godbus/dbus v3 github.com/godbus/dbus v3
github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef github.com/gogo/googleapis v1.2.0
github.com/gogo/protobuf v1.2.1 github.com/gogo/protobuf v1.2.1
github.com/golang/protobuf v1.2.0 github.com/golang/protobuf v1.2.0
github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c
@ -37,7 +37,7 @@ github.com/opencontainers/image-spec v1.0.1
github.com/opencontainers/runc 029124da7af7360afa781a0234d1b083550f797c github.com/opencontainers/runc 029124da7af7360afa781a0234d1b083550f797c
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4
github.com/opencontainers/selinux v1.2.1 github.com/opencontainers/selinux v1.2.1
github.com/pkg/errors v0.8.0 github.com/pkg/errors v0.8.1
github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib v1.0.0
github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823 github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823
github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c

View File

@ -0,0 +1,18 @@
/*
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 events defines the event pushing and subscription service.
package events

View File

@ -0,0 +1,778 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: github.com/containerd/containerd/api/services/ttrpc/events/v1/events.proto
package events
import (
context "context"
fmt "fmt"
github_com_containerd_ttrpc "github.com/containerd/ttrpc"
github_com_containerd_typeurl "github.com/containerd/typeurl"
proto "github.com/gogo/protobuf/proto"
github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
types "github.com/gogo/protobuf/types"
io "io"
math "math"
reflect "reflect"
strings "strings"
time "time"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
var _ = time.Kitchen
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type ForwardRequest struct {
Envelope *Envelope `protobuf:"bytes,1,opt,name=envelope,proto3" json:"envelope,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ForwardRequest) Reset() { *m = ForwardRequest{} }
func (*ForwardRequest) ProtoMessage() {}
func (*ForwardRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_19f98672016720b5, []int{0}
}
func (m *ForwardRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ForwardRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ForwardRequest.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ForwardRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ForwardRequest.Merge(m, src)
}
func (m *ForwardRequest) XXX_Size() int {
return m.Size()
}
func (m *ForwardRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ForwardRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ForwardRequest proto.InternalMessageInfo
type Envelope struct {
Timestamp time.Time `protobuf:"bytes,1,opt,name=timestamp,proto3,stdtime" json:"timestamp"`
Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"`
Topic string `protobuf:"bytes,3,opt,name=topic,proto3" json:"topic,omitempty"`
Event *types.Any `protobuf:"bytes,4,opt,name=event,proto3" json:"event,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Envelope) Reset() { *m = Envelope{} }
func (*Envelope) ProtoMessage() {}
func (*Envelope) Descriptor() ([]byte, []int) {
return fileDescriptor_19f98672016720b5, []int{1}
}
func (m *Envelope) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Envelope) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Envelope.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Envelope) XXX_Merge(src proto.Message) {
xxx_messageInfo_Envelope.Merge(m, src)
}
func (m *Envelope) XXX_Size() int {
return m.Size()
}
func (m *Envelope) XXX_DiscardUnknown() {
xxx_messageInfo_Envelope.DiscardUnknown(m)
}
var xxx_messageInfo_Envelope proto.InternalMessageInfo
func init() {
proto.RegisterType((*ForwardRequest)(nil), "containerd.services.events.ttrpc.v1.ForwardRequest")
proto.RegisterType((*Envelope)(nil), "containerd.services.events.ttrpc.v1.Envelope")
}
func init() {
proto.RegisterFile("github.com/containerd/containerd/api/services/ttrpc/events/v1/events.proto", fileDescriptor_19f98672016720b5)
}
var fileDescriptor_19f98672016720b5 = []byte{
// 396 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x52, 0xc1, 0x8e, 0xd3, 0x30,
0x10, 0x8d, 0x61, 0x77, 0x69, 0x8d, 0xc4, 0xc1, 0xaa, 0x50, 0x08, 0x28, 0x59, 0x2d, 0x97, 0x15,
0x12, 0xb6, 0x76, 0xf7, 0x06, 0x17, 0xa8, 0x28, 0x12, 0x1c, 0x23, 0x84, 0x2a, 0x90, 0x10, 0x6e,
0x3a, 0x4d, 0x2d, 0x25, 0xb6, 0x49, 0x9c, 0xa0, 0xde, 0xfa, 0x09, 0x7c, 0x0c, 0x17, 0xfe, 0xa0,
0x47, 0x8e, 0x9c, 0x80, 0xe6, 0x4b, 0x50, 0x9d, 0xa4, 0x81, 0xf6, 0x40, 0xa5, 0xbd, 0xbd, 0xcc,
0x7b, 0x6f, 0xde, 0xcc, 0xc4, 0xf8, 0x75, 0x2c, 0xcc, 0xbc, 0x98, 0xd0, 0x48, 0xa5, 0x2c, 0x52,
0xd2, 0x70, 0x21, 0x21, 0x9b, 0xfe, 0x0d, 0xb9, 0x16, 0x2c, 0x87, 0xac, 0x14, 0x11, 0xe4, 0xcc,
0x98, 0x4c, 0x47, 0x0c, 0x4a, 0x90, 0x26, 0x67, 0xe5, 0x45, 0x83, 0xa8, 0xce, 0x94, 0x51, 0xe4,
0x61, 0xe7, 0xa2, 0xad, 0x83, 0x36, 0x0a, 0x6b, 0xa4, 0xe5, 0x85, 0xf7, 0xec, 0xbf, 0x81, 0xb6,
0xd9, 0xa4, 0x98, 0x31, 0x9d, 0x14, 0xb1, 0x90, 0x6c, 0x26, 0x20, 0x99, 0x6a, 0x6e, 0xe6, 0x75,
0x8c, 0x37, 0x88, 0x55, 0xac, 0x2c, 0x64, 0x1b, 0xd4, 0x54, 0xef, 0xc5, 0x4a, 0xc5, 0x09, 0x74,
0x6e, 0x2e, 0x17, 0x0d, 0x75, 0x7f, 0x97, 0x82, 0x54, 0x9b, 0x96, 0x0c, 0x76, 0x49, 0x23, 0x52,
0xc8, 0x0d, 0x4f, 0x75, 0x2d, 0x38, 0x7b, 0x8f, 0xef, 0xbc, 0x54, 0xd9, 0x67, 0x9e, 0x4d, 0x43,
0xf8, 0x54, 0x40, 0x6e, 0xc8, 0x2b, 0xdc, 0x03, 0x59, 0x42, 0xa2, 0x34, 0xb8, 0xe8, 0x14, 0x9d,
0xdf, 0xbe, 0x7c, 0x4c, 0x0f, 0x58, 0x9d, 0x8e, 0x1a, 0x53, 0xb8, 0xb5, 0x9f, 0x7d, 0x45, 0xb8,
0xd7, 0x96, 0xc9, 0x10, 0xf7, 0xb7, 0xe1, 0x4d, 0x63, 0x8f, 0xd6, 0xe3, 0xd1, 0x76, 0x3c, 0xfa,
0xa6, 0x55, 0x0c, 0x7b, 0xab, 0x9f, 0x81, 0xf3, 0xe5, 0x57, 0x80, 0xc2, 0xce, 0x46, 0x1e, 0xe0,
0xbe, 0xe4, 0x29, 0xe4, 0x9a, 0x47, 0xe0, 0xde, 0x38, 0x45, 0xe7, 0xfd, 0xb0, 0x2b, 0x90, 0x01,
0x3e, 0x36, 0x4a, 0x8b, 0xc8, 0xbd, 0x69, 0x99, 0xfa, 0x83, 0x3c, 0xc2, 0xc7, 0x76, 0x54, 0xf7,
0xc8, 0x66, 0x0e, 0xf6, 0x32, 0x9f, 0xcb, 0x45, 0x58, 0x4b, 0x9e, 0x1c, 0x2d, 0xbf, 0x05, 0xe8,
0xf2, 0x23, 0x3e, 0x19, 0xd9, 0xe5, 0xc8, 0x5b, 0x7c, 0xab, 0xb9, 0x0e, 0xb9, 0x3a, 0xe8, 0x08,
0xff, 0xde, 0xd2, 0xbb, 0xbb, 0x17, 0x36, 0xda, 0xfc, 0x9c, 0xe1, 0x87, 0xd5, 0xda, 0x77, 0x7e,
0xac, 0x7d, 0x67, 0x59, 0xf9, 0x68, 0x55, 0xf9, 0xe8, 0x7b, 0xe5, 0xa3, 0xdf, 0x95, 0x8f, 0xde,
0xbd, 0xb8, 0xd6, 0x8b, 0x7d, 0x5a, 0xa3, 0xb1, 0x33, 0x46, 0x93, 0x13, 0x9b, 0x79, 0xf5, 0x27,
0x00, 0x00, 0xff, 0xff, 0xd4, 0x90, 0xbd, 0x09, 0x04, 0x03, 0x00, 0x00,
}
// Field returns the value for the given fieldpath as a string, if defined.
// If the value is not defined, the second value will be false.
func (m *Envelope) Field(fieldpath []string) (string, bool) {
if len(fieldpath) == 0 {
return "", false
}
switch fieldpath[0] {
// unhandled: timestamp
case "namespace":
return string(m.Namespace), len(m.Namespace) > 0
case "topic":
return string(m.Topic), len(m.Topic) > 0
case "event":
decoded, err := github_com_containerd_typeurl.UnmarshalAny(m.Event)
if err != nil {
return "", false
}
adaptor, ok := decoded.(interface{ Field([]string) (string, bool) })
if !ok {
return "", false
}
return adaptor.Field(fieldpath[1:])
}
return "", false
}
func (m *ForwardRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ForwardRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Envelope != nil {
dAtA[i] = 0xa
i++
i = encodeVarintEvents(dAtA, i, uint64(m.Envelope.Size()))
n1, err := m.Envelope.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n1
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
return i, nil
}
func (m *Envelope) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Envelope) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
dAtA[i] = 0xa
i++
i = encodeVarintEvents(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)))
n2, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i:])
if err != nil {
return 0, err
}
i += n2
if len(m.Namespace) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintEvents(dAtA, i, uint64(len(m.Namespace)))
i += copy(dAtA[i:], m.Namespace)
}
if len(m.Topic) > 0 {
dAtA[i] = 0x1a
i++
i = encodeVarintEvents(dAtA, i, uint64(len(m.Topic)))
i += copy(dAtA[i:], m.Topic)
}
if m.Event != nil {
dAtA[i] = 0x22
i++
i = encodeVarintEvents(dAtA, i, uint64(m.Event.Size()))
n3, err := m.Event.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n3
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
return i, nil
}
func encodeVarintEvents(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *ForwardRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Envelope != nil {
l = m.Envelope.Size()
n += 1 + l + sovEvents(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *Envelope) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp)
n += 1 + l + sovEvents(uint64(l))
l = len(m.Namespace)
if l > 0 {
n += 1 + l + sovEvents(uint64(l))
}
l = len(m.Topic)
if l > 0 {
n += 1 + l + sovEvents(uint64(l))
}
if m.Event != nil {
l = m.Event.Size()
n += 1 + l + sovEvents(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovEvents(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozEvents(x uint64) (n int) {
return sovEvents(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *ForwardRequest) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&ForwardRequest{`,
`Envelope:` + strings.Replace(fmt.Sprintf("%v", this.Envelope), "Envelope", "Envelope", 1) + `,`,
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
`}`,
}, "")
return s
}
func (this *Envelope) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&Envelope{`,
`Timestamp:` + strings.Replace(strings.Replace(this.Timestamp.String(), "Timestamp", "types.Timestamp", 1), `&`, ``, 1) + `,`,
`Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`,
`Topic:` + fmt.Sprintf("%v", this.Topic) + `,`,
`Event:` + strings.Replace(fmt.Sprintf("%v", this.Event), "Any", "types.Any", 1) + `,`,
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
`}`,
}, "")
return s
}
func valueToStringEvents(v interface{}) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
type EventsService interface {
Forward(ctx context.Context, req *ForwardRequest) (*types.Empty, error)
}
func RegisterEventsService(srv *github_com_containerd_ttrpc.Server, svc EventsService) {
srv.Register("containerd.services.events.ttrpc.v1.Events", map[string]github_com_containerd_ttrpc.Method{
"Forward": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
var req ForwardRequest
if err := unmarshal(&req); err != nil {
return nil, err
}
return svc.Forward(ctx, &req)
},
})
}
type eventsClient struct {
client *github_com_containerd_ttrpc.Client
}
func NewEventsClient(client *github_com_containerd_ttrpc.Client) EventsService {
return &eventsClient{
client: client,
}
}
func (c *eventsClient) Forward(ctx context.Context, req *ForwardRequest) (*types.Empty, error) {
var resp types.Empty
if err := c.client.Call(ctx, "containerd.services.events.ttrpc.v1.Events", "Forward", req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
func (m *ForwardRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ForwardRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ForwardRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Envelope", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthEvents
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthEvents
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Envelope == nil {
m.Envelope = &Envelope{}
}
if err := m.Envelope.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipEvents(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthEvents
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthEvents
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Envelope) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Envelope: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Envelope: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthEvents
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthEvents
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Namespace", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvents
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthEvents
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Namespace = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Topic", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthEvents
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthEvents
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Topic = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Event", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowEvents
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthEvents
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthEvents
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Event == nil {
m.Event = &types.Any{}
}
if err := m.Event.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipEvents(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthEvents
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthEvents
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipEvents(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowEvents
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowEvents
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowEvents
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthEvents
}
iNdEx += length
if iNdEx < 0 {
return 0, ErrInvalidLengthEvents
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowEvents
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipEvents(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
if iNdEx < 0 {
return 0, ErrInvalidLengthEvents
}
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthEvents = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowEvents = fmt.Errorf("proto: integer overflow")
)

View File

@ -0,0 +1,32 @@
syntax = "proto3";
package containerd.services.events.ttrpc.v1;
import weak "github.com/containerd/containerd/protobuf/plugin/fieldpath.proto";
import weak "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
option go_package = "github.com/containerd/containerd/api/services/ttrpc/events/v1;events";
service Events {
// Forward sends an event that has already been packaged into an envelope
// with a timestamp and namespace.
//
// This is useful if earlier timestamping is required or when forwarding on
// behalf of another component, namespace or publisher.
rpc Forward(ForwardRequest) returns (google.protobuf.Empty);
}
message ForwardRequest {
Envelope envelope = 1;
}
message Envelope {
option (containerd.plugin.fieldpath) = true;
google.protobuf.Timestamp timestamp = 1 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
string namespace = 2;
string topic = 3;
google.protobuf.Any event = 4;
}

View File

@ -30,5 +30,7 @@ func defaultConfig() *srvconfig.Config {
MaxRecvMsgSize: defaults.DefaultMaxRecvMsgSize, MaxRecvMsgSize: defaults.DefaultMaxRecvMsgSize,
MaxSendMsgSize: defaults.DefaultMaxSendMsgSize, MaxSendMsgSize: defaults.DefaultMaxSendMsgSize,
}, },
DisabledPlugins: []string{},
RequiredPlugins: []string{},
} }
} }

View File

@ -34,5 +34,7 @@ func defaultConfig() *srvconfig.Config {
Level: "info", Level: "info",
Address: defaults.DefaultDebugAddress, Address: defaults.DefaultDebugAddress,
}, },
DisabledPlugins: []string{},
RequiredPlugins: []string{},
} }
} }

View File

@ -30,5 +30,7 @@ func defaultConfig() *srvconfig.Config {
MaxRecvMsgSize: defaults.DefaultMaxRecvMsgSize, MaxRecvMsgSize: defaults.DefaultMaxRecvMsgSize,
MaxSendMsgSize: defaults.DefaultMaxSendMsgSize, MaxSendMsgSize: defaults.DefaultMaxSendMsgSize,
}, },
DisabledPlugins: []string{},
RequiredPlugins: []string{},
} }
} }

View File

@ -147,7 +147,10 @@ func App() *cli.App {
for _, w := range warnings { for _, w := range warnings {
log.G(ctx).WithError(w).Warn("cleanup temp mount") log.G(ctx).WithError(w).Warn("cleanup temp mount")
} }
address := config.GRPC.Address var (
address = config.GRPC.Address
ttrpcAddress = fmt.Sprintf("%s.ttrpc", config.GRPC.Address)
)
if address == "" { if address == "" {
return errors.New("grpc address cannot be empty") return errors.New("grpc address cannot be empty")
} }
@ -188,7 +191,21 @@ func App() *cli.App {
} }
serve(ctx, l, server.ServeMetrics) serve(ctx, l, server.ServeMetrics)
} }
// setup the ttrpc endpoint
tl, err := sys.GetLocalListener(ttrpcAddress, config.GRPC.UID, config.GRPC.GID)
if err != nil {
return errors.Wrapf(err, "failed to get listener for main ttrpc endpoint")
}
serve(ctx, tl, server.ServeTTRPC)
if config.GRPC.TCPAddress != "" {
l, err := net.Listen("tcp", config.GRPC.TCPAddress)
if err != nil {
return errors.Wrapf(err, "failed to get listener for TCP grpc endpoint")
}
serve(ctx, l, server.ServeTCP)
}
// setup the main grpc endpoint
l, err := sys.GetLocalListener(address, config.GRPC.UID, config.GRPC.GID) l, err := sys.GetLocalListener(address, config.GRPC.UID, config.GRPC.GID)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to get listener for main endpoint") return errors.Wrapf(err, "failed to get listener for main endpoint")

View File

@ -33,6 +33,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/filters" "github.com/containerd/containerd/filters"
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
"github.com/sirupsen/logrus"
"github.com/containerd/continuity" "github.com/containerd/continuity"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
@ -477,6 +478,35 @@ func (s *store) Writer(ctx context.Context, opts ...content.WriterOpt) (content.
return w, nil // lock is now held by w. return w, nil // lock is now held by w.
} }
func (s *store) resumeStatus(ref string, total int64, digester digest.Digester) (content.Status, error) {
path, _, data := s.ingestPaths(ref)
status, err := s.status(path)
if err != nil {
return status, errors.Wrap(err, "failed reading status of resume write")
}
if ref != status.Ref {
// NOTE(stevvooe): This is fairly catastrophic. Either we have some
// layout corruption or a hash collision for the ref key.
return status, errors.Wrapf(err, "ref key does not match: %v != %v", ref, status.Ref)
}
if total > 0 && status.Total > 0 && total != status.Total {
return status, errors.Errorf("provided total differs from status: %v != %v", total, status.Total)
}
// TODO(stevvooe): slow slow slow!!, send to goroutine or use resumable hashes
fp, err := os.Open(data)
if err != nil {
return status, err
}
p := bufPool.Get().(*[]byte)
status.Offset, err = io.CopyBuffer(digester.Hash(), fp, *p)
bufPool.Put(p)
fp.Close()
return status, err
}
// writer provides the main implementation of the Writer method. The caller // writer provides the main implementation of the Writer method. The caller
// must hold the lock correctly and release on error if there is a problem. // must hold the lock correctly and release on error if there is a problem.
func (s *store) writer(ctx context.Context, ref string, total int64, expected digest.Digest) (content.Writer, error) { func (s *store) writer(ctx context.Context, ref string, total int64, expected digest.Digest) (content.Writer, error) {
@ -498,45 +528,25 @@ func (s *store) writer(ctx context.Context, ref string, total int64, expected di
updatedAt time.Time updatedAt time.Time
) )
foundValidIngest := false
// ensure that the ingest path has been created. // ensure that the ingest path has been created.
if err := os.Mkdir(path, 0755); err != nil { if err := os.Mkdir(path, 0755); err != nil {
if !os.IsExist(err) { if !os.IsExist(err) {
return nil, err return nil, err
} }
status, err := s.resumeStatus(ref, total, digester)
status, err := s.status(path) if err == nil {
if err != nil { foundValidIngest = true
return nil, errors.Wrap(err, "failed reading status of resume write") updatedAt = status.UpdatedAt
startedAt = status.StartedAt
total = status.Total
offset = status.Offset
} else {
logrus.Infof("failed to resume the status from path %s: %s. will recreate them", path, err.Error())
} }
}
if ref != status.Ref { if !foundValidIngest {
// NOTE(stevvooe): This is fairly catastrophic. Either we have some
// layout corruption or a hash collision for the ref key.
return nil, errors.Wrapf(err, "ref key does not match: %v != %v", ref, status.Ref)
}
if total > 0 && status.Total > 0 && total != status.Total {
return nil, errors.Errorf("provided total differs from status: %v != %v", total, status.Total)
}
// TODO(stevvooe): slow slow slow!!, send to goroutine or use resumable hashes
fp, err := os.Open(data)
if err != nil {
return nil, err
}
p := bufPool.Get().(*[]byte)
offset, err = io.CopyBuffer(digester.Hash(), fp, *p)
bufPool.Put(p)
fp.Close()
if err != nil {
return nil, err
}
updatedAt = status.UpdatedAt
startedAt = status.StartedAt
total = status.Total
} else {
startedAt = time.Now() startedAt = time.Now()
updatedAt = startedAt updatedAt = startedAt
@ -546,11 +556,11 @@ func (s *store) writer(ctx context.Context, ref string, total int64, expected di
return nil, err return nil, err
} }
if writeTimestampFile(filepath.Join(path, "startedat"), startedAt); err != nil { if err := writeTimestampFile(filepath.Join(path, "startedat"), startedAt); err != nil {
return nil, err return nil, err
} }
if writeTimestampFile(filepath.Join(path, "updatedat"), startedAt); err != nil { if err := writeTimestampFile(filepath.Join(path, "updatedat"), startedAt); err != nil {
return nil, err return nil, err
} }

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"sync" "sync"
"github.com/containerd/ttrpc"
"github.com/pkg/errors" "github.com/pkg/errors"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
@ -123,6 +124,16 @@ type Service interface {
Register(*grpc.Server) error Register(*grpc.Server) error
} }
// TTRPCService allows TTRPC services to be registered with the underlying server
type TTRPCService interface {
RegisterTTRPC(*ttrpc.Server) error
}
// TCPService allows GRPC services to be registered with the underlying tcp server
type TCPService interface {
RegisterTCP(*grpc.Server) error
}
var register = struct { var register = struct {
sync.RWMutex sync.RWMutex
r []*Registration r []*Registration

View File

@ -0,0 +1,87 @@
/*
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 shim
import (
"net"
"sync"
v1 "github.com/containerd/containerd/api/services/ttrpc/events/v1"
"github.com/containerd/ttrpc"
"github.com/pkg/errors"
)
type dialConnect func() (net.Conn, error)
var errDialerClosed = errors.New("events dialer is closed")
func newDialier(newFn dialConnect) *dialer {
return &dialer{
newFn: newFn,
}
}
type dialer struct {
mu sync.Mutex
newFn dialConnect
service v1.EventsService
conn net.Conn
closed bool
}
func (d *dialer) Get() (v1.EventsService, error) {
d.mu.Lock()
defer d.mu.Unlock()
if d.closed {
return nil, errDialerClosed
}
if d.service == nil {
conn, err := d.newFn()
if err != nil {
return nil, err
}
d.conn = conn
d.service = v1.NewEventsClient(ttrpc.NewClient(conn))
}
return d.service, nil
}
func (d *dialer) Put(err error) {
if err != nil {
d.mu.Lock()
d.conn.Close()
d.service = nil
d.mu.Unlock()
}
}
func (d *dialer) Close() (err error) {
d.mu.Lock()
if d.closed {
return errDialerClosed
}
if d.conn != nil {
err = d.conn.Close()
}
d.service = nil
d.closed = true
d.mu.Unlock()
return err
}

View File

@ -0,0 +1,145 @@
/*
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 shim
import (
"context"
"net"
"sync"
"time"
v1 "github.com/containerd/containerd/api/services/ttrpc/events/v1"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/typeurl"
"github.com/sirupsen/logrus"
)
const (
queueSize = 2048
maxRequeue = 5
)
type item struct {
ev *v1.Envelope
ctx context.Context
count int
}
func newPublisher(address string) *remoteEventsPublisher {
l := &remoteEventsPublisher{
dialer: newDialier(func() (net.Conn, error) {
return connect(address, dial)
}),
closed: make(chan struct{}),
requeue: make(chan *item, queueSize),
}
go l.processQueue()
return l
}
type remoteEventsPublisher struct {
dialer *dialer
closed chan struct{}
closer sync.Once
requeue chan *item
}
func (l *remoteEventsPublisher) Done() <-chan struct{} {
return l.closed
}
func (l *remoteEventsPublisher) Close() (err error) {
err = l.dialer.Close()
l.closer.Do(func() {
close(l.closed)
})
return err
}
func (l *remoteEventsPublisher) processQueue() {
for i := range l.requeue {
if i.count > maxRequeue {
logrus.Errorf("evicting %s from queue because of retry count", i.ev.Topic)
// drop the event
continue
}
client, err := l.dialer.Get()
if err != nil {
l.dialer.Put(err)
l.queue(i)
logrus.WithError(err).Error("get events client")
continue
}
if _, err := client.Forward(i.ctx, &v1.ForwardRequest{
Envelope: i.ev,
}); err != nil {
l.dialer.Put(err)
logrus.WithError(err).Error("forward event")
l.queue(i)
}
}
}
func (l *remoteEventsPublisher) queue(i *item) {
go func() {
i.count++
// re-queue after a short delay
time.Sleep(time.Duration(1*i.count) * time.Second)
l.requeue <- i
}()
}
func (l *remoteEventsPublisher) Publish(ctx context.Context, topic string, event events.Event) error {
ns, err := namespaces.NamespaceRequired(ctx)
if err != nil {
return err
}
any, err := typeurl.MarshalAny(event)
if err != nil {
return err
}
i := &item{
ev: &v1.Envelope{
Timestamp: time.Now(),
Namespace: ns,
Topic: topic,
Event: any,
},
ctx: ctx,
}
client, err := l.dialer.Get()
if err != nil {
l.dialer.Put(err)
l.queue(i)
return err
}
if _, err := client.Forward(i.ctx, &v1.ForwardRequest{
Envelope: i.ev,
}); err != nil {
l.dialer.Put(err)
l.queue(i)
return err
}
return nil
}
func connect(address string, d func(string, time.Duration) (net.Conn, error)) (net.Conn, error) {
return d(address, 5*time.Second)
}

View File

@ -20,6 +20,7 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"io"
"os" "os"
"runtime" "runtime"
"runtime/debug" "runtime/debug"
@ -43,8 +44,14 @@ type Client struct {
signals chan os.Signal signals chan os.Signal
} }
// Publisher for events
type Publisher interface {
events.Publisher
io.Closer
}
// Init func for the creation of a shim server // Init func for the creation of a shim server
type Init func(context.Context, string, events.Publisher) (Shim, error) type Init func(context.Context, string, Publisher, func()) (Shim, error)
// Shim server interface // Shim server interface
type Shim interface { type Shim interface {
@ -153,19 +160,20 @@ func run(id string, initFunc Init, config Config) error {
return err return err
} }
} }
publisher := &remoteEventsPublisher{ address := fmt.Sprintf("%s.ttrpc", addressFlag)
address: addressFlag,
containerdBinaryPath: containerdBinaryFlag, publisher := newPublisher(address)
noReaper: config.NoReaper, defer publisher.Close()
}
if namespaceFlag == "" { if namespaceFlag == "" {
return fmt.Errorf("shim namespace cannot be empty") return fmt.Errorf("shim namespace cannot be empty")
} }
ctx := namespaces.WithNamespace(context.Background(), namespaceFlag) ctx := namespaces.WithNamespace(context.Background(), namespaceFlag)
ctx = context.WithValue(ctx, OptsKey{}, Opts{BundlePath: bundlePath, Debug: debugFlag}) ctx = context.WithValue(ctx, OptsKey{}, Opts{BundlePath: bundlePath, Debug: debugFlag})
ctx = log.WithLogger(ctx, log.G(ctx).WithField("runtime", id)) ctx = log.WithLogger(ctx, log.G(ctx).WithField("runtime", id))
ctx, cancel := context.WithCancel(ctx)
service, err := initFunc(ctx, idFlag, publisher) service, err := initFunc(ctx, idFlag, publisher, cancel)
if err != nil { if err != nil {
return err return err
} }
@ -175,7 +183,7 @@ func run(id string, initFunc Init, config Config) error {
"pid": os.Getpid(), "pid": os.Getpid(),
"namespace": namespaceFlag, "namespace": namespaceFlag,
}) })
go handleSignals(logger, signals) go handleSignals(ctx, logger, signals)
response, err := service.Cleanup(ctx) response, err := service.Cleanup(ctx)
if err != nil { if err != nil {
return err return err
@ -202,7 +210,17 @@ func run(id string, initFunc Init, config Config) error {
return err return err
} }
client := NewShimClient(ctx, service, signals) client := NewShimClient(ctx, service, signals)
return client.Serve() if err := client.Serve(); err != nil {
if err != context.Canceled {
return err
}
}
select {
case <-publisher.Done():
return nil
case <-time.After(5 * time.Second):
return errors.New("publisher not closed")
}
} }
} }
@ -246,7 +264,7 @@ func (s *Client) Serve() error {
dumpStacks(logger) dumpStacks(logger)
} }
}() }()
return handleSignals(logger, s.signals) return handleSignals(s.context, logger, s.signals)
} }
// serve serves the ttrpc API over a unix socket at the provided path // serve serves the ttrpc API over a unix socket at the provided path
@ -280,9 +298,3 @@ func dumpStacks(logger *logrus.Entry) {
buf = buf[:stackSize] buf = buf[:stackSize]
logger.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf) logger.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf)
} }
type remoteEventsPublisher struct {
address string
containerdBinaryPath string
noReaper bool
}

View File

@ -19,31 +19,21 @@
package shim package shim
import ( import (
"bytes"
"context" "context"
"io" "io"
"net" "net"
"os" "os"
"os/exec"
"os/signal" "os/signal"
"sync" "strings"
"syscall" "syscall"
"time"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/fifo" "github.com/containerd/fifo"
"github.com/containerd/typeurl"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
var bufPool = sync.Pool{
New: func() interface{} {
return bytes.NewBuffer(nil)
},
}
// setupSignals creates a new signal handler for all signals and sets the shim as a // setupSignals creates a new signal handler for all signals and sets the shim as a
// sub-reaper so that the container processes are reparented // sub-reaper so that the container processes are reparented
func setupSignals(config Config) (chan os.Signal, error) { func setupSignals(config Config) (chan os.Signal, error) {
@ -81,11 +71,14 @@ func serveListener(path string) (net.Listener, error) {
return l, nil return l, nil
} }
func handleSignals(logger *logrus.Entry, signals chan os.Signal) error { func handleSignals(ctx context.Context, logger *logrus.Entry, signals chan os.Signal) error {
logger.Info("starting signal loop") logger.Info("starting signal loop")
for { for {
for s := range signals { select {
case <-ctx.Done():
return ctx.Err()
case s := <-signals:
switch s { switch s {
case unix.SIGCHLD: case unix.SIGCHLD:
if err := Reap(); err != nil { if err := Reap(); err != nil {
@ -101,41 +94,7 @@ func openLog(ctx context.Context, _ string) (io.Writer, error) {
return fifo.OpenFifo(ctx, "log", unix.O_WRONLY, 0700) return fifo.OpenFifo(ctx, "log", unix.O_WRONLY, 0700)
} }
func (l *remoteEventsPublisher) Publish(ctx context.Context, topic string, event events.Event) error { func dial(address string, timeout time.Duration) (net.Conn, error) {
ns, _ := namespaces.Namespace(ctx) address = strings.TrimPrefix(address, "unix://")
encoded, err := typeurl.MarshalAny(event) return net.DialTimeout("unix", address, timeout)
if err != nil {
return err
}
data, err := encoded.Marshal()
if err != nil {
return err
}
cmd := exec.CommandContext(ctx, l.containerdBinaryPath, "--address", l.address, "publish", "--topic", topic, "--namespace", ns)
cmd.Stdin = bytes.NewReader(data)
b := bufPool.Get().(*bytes.Buffer)
defer bufPool.Put(b)
cmd.Stdout = b
cmd.Stderr = b
if l.noReaper {
if err := cmd.Start(); err != nil {
return err
}
if err := cmd.Wait(); err != nil {
return errors.Wrapf(err, "failed to publish event: %s", b.String())
}
return nil
}
c, err := Default.Start(cmd)
if err != nil {
return err
}
status, err := Default.Wait(cmd, c)
if err != nil {
return errors.Wrapf(err, "failed to publish event: %s", b.String())
}
if status != 0 {
return errors.Errorf("failed to publish event: %s", b.String())
}
return nil
} }

View File

@ -25,15 +25,13 @@ import (
"io" "io"
"net" "net"
"os" "os"
"os/exec"
"sync" "sync"
"time"
"unsafe" "unsafe"
winio "github.com/Microsoft/go-winio" winio "github.com/Microsoft/go-winio"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/ttrpc" "github.com/containerd/ttrpc"
"github.com/containerd/typeurl"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
@ -106,11 +104,14 @@ func serveListener(path string) (net.Listener, error) {
return l, nil return l, nil
} }
func handleSignals(logger *logrus.Entry, signals chan os.Signal) error { func handleSignals(ctx context.Context, logger *logrus.Entry, signals chan os.Signal) error {
logger.Info("starting signal loop") logger.Info("starting signal loop")
for { for {
for s := range signals { select {
case <-ctx.Done():
return ctx.Err()
case s := <-signals:
switch s { switch s {
case os.Interrupt: case os.Interrupt:
return nil return nil
@ -286,17 +287,34 @@ func openLog(ctx context.Context, id string) (io.Writer, error) {
return dswl, nil return dswl, nil
} }
func (l *remoteEventsPublisher) Publish(ctx context.Context, topic string, event events.Event) error { func dial(address string, timeout time.Duration) (net.Conn, error) {
ns, _ := namespaces.Namespace(ctx) var c net.Conn
encoded, err := typeurl.MarshalAny(event) var lastError error
if err != nil { timedOutError := errors.Errorf("timed out waiting for npipe %s", address)
return err start := time.Now()
for {
remaining := timeout - time.Since(start)
if remaining <= 0 {
lastError = timedOutError
break
}
c, lastError = winio.DialPipe(address, &remaining)
if lastError == nil {
break
}
if !os.IsNotExist(lastError) {
break
}
// There is nobody serving the pipe. We limit the timeout for this case
// to 5 seconds because any shim that would serve this endpoint should
// serve it within 5 seconds. We use the passed in timeout for the
// `DialPipe` timeout if the pipe exists however to give the pipe time
// to `Accept` the connection.
if time.Since(start) >= 5*time.Second {
lastError = timedOutError
break
}
time.Sleep(10 * time.Millisecond)
} }
data, err := encoded.Marshal() return c, lastError
if err != nil {
return err
}
cmd := exec.CommandContext(ctx, l.containerdBinaryPath, "--address", l.address, "publish", "--topic", topic, "--namespace", ns)
cmd.Stdin = bytes.NewReader(data)
return cmd.Run()
} }

View File

@ -20,10 +20,12 @@ import (
"context" "context"
api "github.com/containerd/containerd/api/services/events/v1" api "github.com/containerd/containerd/api/services/events/v1"
apittrpc "github.com/containerd/containerd/api/services/ttrpc/events/v1"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/events" "github.com/containerd/containerd/events"
"github.com/containerd/containerd/events/exchange" "github.com/containerd/containerd/events/exchange"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/ttrpc"
ptypes "github.com/gogo/protobuf/types" ptypes "github.com/gogo/protobuf/types"
"github.com/pkg/errors" "github.com/pkg/errors"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -40,12 +42,18 @@ func init() {
} }
type service struct { type service struct {
events *exchange.Exchange ttService *ttrpcService
events *exchange.Exchange
} }
// NewService returns the GRPC events server // NewService returns the GRPC events server
func NewService(events *exchange.Exchange) api.EventsServer { func NewService(events *exchange.Exchange) api.EventsServer {
return &service{events: events} return &service{
ttService: &ttrpcService{
events: events,
},
events: events,
}
} }
func (s *service) Register(server *grpc.Server) error { func (s *service) Register(server *grpc.Server) error {
@ -53,6 +61,11 @@ func (s *service) Register(server *grpc.Server) error {
return nil return nil
} }
func (s *service) RegisterTTRPC(server *ttrpc.Server) error {
apittrpc.RegisterEventsService(server, s.ttService)
return nil
}
func (s *service) Publish(ctx context.Context, r *api.PublishRequest) (*ptypes.Empty, error) { func (s *service) Publish(ctx context.Context, r *api.PublishRequest) (*ptypes.Empty, error) {
if err := s.events.Publish(ctx, r.Topic, r.Event); err != nil { if err := s.events.Publish(ctx, r.Topic, r.Event); err != nil {
return nil, errdefs.ToGRPC(err) return nil, errdefs.ToGRPC(err)

View File

@ -0,0 +1,48 @@
/*
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 events
import (
"context"
api "github.com/containerd/containerd/api/services/ttrpc/events/v1"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/events/exchange"
ptypes "github.com/gogo/protobuf/types"
)
type ttrpcService struct {
events *exchange.Exchange
}
func (s *ttrpcService) Forward(ctx context.Context, r *api.ForwardRequest) (*ptypes.Empty, error) {
if err := s.events.Forward(ctx, fromTProto(r.Envelope)); err != nil {
return nil, errdefs.ToGRPC(err)
}
return &ptypes.Empty{}, nil
}
func fromTProto(env *api.Envelope) *events.Envelope {
return &events.Envelope{
Timestamp: env.Timestamp,
Namespace: env.Namespace,
Topic: env.Topic,
Event: env.Event,
}
}

View File

@ -39,6 +39,9 @@ type Config struct {
// DisabledPlugins are IDs of plugins to disable. Disabled plugins won't be // DisabledPlugins are IDs of plugins to disable. Disabled plugins won't be
// initialized and started. // initialized and started.
DisabledPlugins []string `toml:"disabled_plugins"` DisabledPlugins []string `toml:"disabled_plugins"`
// RequiredPlugins are IDs of required plugins. Containerd exits if any
// required plugin doesn't exist or fails to be initialized or started.
RequiredPlugins []string `toml:"required_plugins"`
// Plugins provides plugin specific configuration for the initialization of a plugin // Plugins provides plugin specific configuration for the initialization of a plugin
Plugins map[string]toml.Primitive `toml:"plugins"` Plugins map[string]toml.Primitive `toml:"plugins"`
// OOMScore adjust the containerd's oom score // OOMScore adjust the containerd's oom score
@ -54,6 +57,9 @@ type Config struct {
// GRPCConfig provides GRPC configuration for the socket // GRPCConfig provides GRPC configuration for the socket
type GRPCConfig struct { type GRPCConfig struct {
Address string `toml:"address"` Address string `toml:"address"`
TCPAddress string `toml:"tcp_address"`
TCPTLSCert string `toml:"tcp_tls_cert"`
TCPTLSKey string `toml:"tcp_tls_key"`
UID int `toml:"uid"` UID int `toml:"uid"`
GID int `toml:"gid"` GID int `toml:"gid"`
MaxRecvMsgSize int `toml:"max_recv_message_size"` MaxRecvMsgSize int `toml:"max_recv_message_size"`

View File

@ -44,11 +44,13 @@ import (
"github.com/containerd/containerd/snapshots" "github.com/containerd/containerd/snapshots"
ssproxy "github.com/containerd/containerd/snapshots/proxy" ssproxy "github.com/containerd/containerd/snapshots/proxy"
"github.com/containerd/containerd/sys" "github.com/containerd/containerd/sys"
"github.com/containerd/ttrpc"
metrics "github.com/docker/go-metrics" metrics "github.com/docker/go-metrics"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/pkg/errors" "github.com/pkg/errors"
bolt "go.etcd.io/bbolt" bolt "go.etcd.io/bbolt"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
) )
// CreateTopLevelDirectories creates the top-level root and state directories. // CreateTopLevelDirectories creates the top-level root and state directories.
@ -80,7 +82,6 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
serverOpts := []grpc.ServerOption{ serverOpts := []grpc.ServerOption{
grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor), grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor),
grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor), grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor),
@ -91,16 +92,40 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
if config.GRPC.MaxSendMsgSize > 0 { if config.GRPC.MaxSendMsgSize > 0 {
serverOpts = append(serverOpts, grpc.MaxSendMsgSize(config.GRPC.MaxSendMsgSize)) serverOpts = append(serverOpts, grpc.MaxSendMsgSize(config.GRPC.MaxSendMsgSize))
} }
rpc := grpc.NewServer(serverOpts...) ttrpcServer, err := newTTRPCServer()
if err != nil {
return nil, err
}
tcpServerOpts := serverOpts
if config.GRPC.TCPTLSCert != "" {
log.G(ctx).Info("setting up tls on tcp GRPC services...")
creds, err := credentials.NewServerTLSFromFile(config.GRPC.TCPTLSCert, config.GRPC.TCPTLSKey)
if err != nil {
return nil, err
}
tcpServerOpts = append(tcpServerOpts, grpc.Creds(creds))
}
var ( var (
services []plugin.Service grpcServer = grpc.NewServer(serverOpts...)
s = &Server{ tcpServer = grpc.NewServer(tcpServerOpts...)
rpc: rpc,
events: exchange.NewExchange(), grpcServices []plugin.Service
config: config, tcpServices []plugin.TCPService
ttrpcServices []plugin.TTRPCService
s = &Server{
grpcServer: grpcServer,
tcpServer: tcpServer,
ttrpcServer: ttrpcServer,
events: exchange.NewExchange(),
config: config,
} }
initialized = plugin.NewPluginSet() initialized = plugin.NewPluginSet()
required = make(map[string]struct{})
) )
for _, r := range config.RequiredPlugins {
required[r] = struct{}{}
}
for _, p := range plugins { for _, p := range plugins {
id := p.URI() id := p.URI()
log.G(ctx).WithField("type", p.Type).Infof("loading plugin %q...", id) log.G(ctx).WithField("type", p.Type).Infof("loading plugin %q...", id)
@ -135,17 +160,46 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
} else { } else {
log.G(ctx).WithError(err).Warnf("failed to load plugin %s", id) log.G(ctx).WithError(err).Warnf("failed to load plugin %s", id)
} }
if _, ok := required[p.ID]; ok {
return nil, errors.Wrapf(err, "load required plugin %s", id)
}
continue continue
} }
delete(required, p.ID)
// check for grpc services that should be registered with the server // check for grpc services that should be registered with the server
if service, ok := instance.(plugin.Service); ok { if src, ok := instance.(plugin.Service); ok {
services = append(services, service) grpcServices = append(grpcServices, src)
} }
if src, ok := instance.(plugin.TTRPCService); ok {
ttrpcServices = append(ttrpcServices, src)
}
if service, ok := instance.(plugin.TCPService); ok {
tcpServices = append(tcpServices, service)
}
s.plugins = append(s.plugins, result) s.plugins = append(s.plugins, result)
} }
if len(required) != 0 {
var missing []string
for id := range required {
missing = append(missing, id)
}
return nil, errors.Errorf("required plugin %s not included", missing)
}
// register services after all plugins have been initialized // register services after all plugins have been initialized
for _, service := range services { for _, service := range grpcServices {
if err := service.Register(rpc); err != nil { if err := service.Register(grpcServer); err != nil {
return nil, err
}
}
for _, service := range ttrpcServices {
if err := service.RegisterTTRPC(ttrpcServer); err != nil {
return nil, err
}
}
for _, service := range tcpServices {
if err := service.RegisterTCP(tcpServer); err != nil {
return nil, err return nil, err
} }
} }
@ -154,10 +208,12 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
// Server is the containerd main daemon // Server is the containerd main daemon
type Server struct { type Server struct {
rpc *grpc.Server grpcServer *grpc.Server
events *exchange.Exchange ttrpcServer *ttrpc.Server
config *srvconfig.Config tcpServer *grpc.Server
plugins []*plugin.Plugin events *exchange.Exchange
config *srvconfig.Config
plugins []*plugin.Plugin
} }
// ServeGRPC provides the containerd grpc APIs on the provided listener // ServeGRPC provides the containerd grpc APIs on the provided listener
@ -169,8 +225,13 @@ func (s *Server) ServeGRPC(l net.Listener) error {
// before we start serving the grpc API register the grpc_prometheus metrics // before we start serving the grpc API register the grpc_prometheus metrics
// handler. This needs to be the last service registered so that it can collect // handler. This needs to be the last service registered so that it can collect
// metrics for every other service // metrics for every other service
grpc_prometheus.Register(s.rpc) grpc_prometheus.Register(s.grpcServer)
return trapClosedConnErr(s.rpc.Serve(l)) return trapClosedConnErr(s.grpcServer.Serve(l))
}
// ServeTTRPC provides the containerd ttrpc APIs on the provided listener
func (s *Server) ServeTTRPC(l net.Listener) error {
return trapClosedConnErr(s.ttrpcServer.Serve(context.Background(), l))
} }
// ServeMetrics provides a prometheus endpoint for exposing metrics // ServeMetrics provides a prometheus endpoint for exposing metrics
@ -180,6 +241,12 @@ func (s *Server) ServeMetrics(l net.Listener) error {
return trapClosedConnErr(http.Serve(l, m)) return trapClosedConnErr(http.Serve(l, m))
} }
// ServeTCP allows services to serve over tcp
func (s *Server) ServeTCP(l net.Listener) error {
grpc_prometheus.Register(s.tcpServer)
return trapClosedConnErr(s.tcpServer.Serve(l))
}
// ServeDebug provides a debug endpoint // ServeDebug provides a debug endpoint
func (s *Server) ServeDebug(l net.Listener) error { func (s *Server) ServeDebug(l net.Listener) error {
// don't use the default http server mux to make sure nothing gets registered // don't use the default http server mux to make sure nothing gets registered
@ -196,7 +263,7 @@ func (s *Server) ServeDebug(l net.Listener) error {
// Stop the containerd server canceling any open connections // Stop the containerd server canceling any open connections
func (s *Server) Stop() { func (s *Server) Stop() {
s.rpc.Stop() s.grpcServer.Stop()
for i := len(s.plugins) - 1; i >= 0; i-- { for i := len(s.plugins) - 1; i >= 0; i-- {
p := s.plugins[i] p := s.plugins[i]
instance, err := p.Instance() instance, err := p.Instance()

View File

@ -24,6 +24,7 @@ import (
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
srvconfig "github.com/containerd/containerd/services/server/config" srvconfig "github.com/containerd/containerd/services/server/config"
"github.com/containerd/containerd/sys" "github.com/containerd/containerd/sys"
"github.com/containerd/ttrpc"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
) )
@ -53,3 +54,7 @@ func apply(ctx context.Context, config *srvconfig.Config) error {
} }
return nil return nil
} }
func newTTRPCServer() (*ttrpc.Server, error) {
return ttrpc.NewServer(ttrpc.WithServerHandshaker(ttrpc.UnixSocketRequireSameUser()))
}

View File

@ -22,8 +22,13 @@ import (
"context" "context"
srvconfig "github.com/containerd/containerd/services/server/config" srvconfig "github.com/containerd/containerd/services/server/config"
"github.com/containerd/ttrpc"
) )
func apply(_ context.Context, _ *srvconfig.Config) error { func apply(_ context.Context, _ *srvconfig.Config) error {
return nil return nil
} }
func newTTRPCServer() (*ttrpc.Server, error) {
return ttrpc.NewServer()
}

View File

@ -22,8 +22,13 @@ import (
"context" "context"
srvconfig "github.com/containerd/containerd/services/server/config" srvconfig "github.com/containerd/containerd/services/server/config"
"github.com/containerd/ttrpc"
) )
func apply(_ context.Context, _ *srvconfig.Config) error { func apply(_ context.Context, _ *srvconfig.Config) error {
return nil return nil
} }
func newTTRPCServer() (*ttrpc.Server, error) {
return ttrpc.NewServer()
}

View File

@ -20,8 +20,10 @@ package sys
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"strconv" "strconv"
"strings"
"github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/runc/libcontainer/system"
) )
@ -45,3 +47,13 @@ func SetOOMScore(pid, score int) error {
} }
return nil return nil
} }
// GetOOMScoreAdj gets the oom score for a process
func GetOOMScoreAdj(pid int) (int, error) {
path := fmt.Sprintf("/proc/%d/oom_score_adj", pid)
data, err := ioutil.ReadFile(path)
if err != nil {
return 0, err
}
return strconv.Atoi(strings.TrimSpace(string(data)))
}

View File

@ -22,3 +22,10 @@ package sys
func SetOOMScore(pid, score int) error { func SetOOMScore(pid, score int) error {
return nil return nil
} }
// GetOOMScoreAdj gets the oom score for a process
//
// Not implemented on Windows
func GetOOMScoreAdj(pid int) (int, error) {
return 0, nil
}

View File

@ -3,7 +3,7 @@ github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1 github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244 github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4 github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6 github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098 github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
@ -17,7 +17,7 @@ github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
github.com/matttproud/golang_protobuf_extensions v1.0.1 github.com/matttproud/golang_protobuf_extensions v1.0.1
github.com/gogo/protobuf v1.2.1 github.com/gogo/protobuf v1.2.1
github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef github.com/gogo/googleapis v1.2.0
github.com/golang/protobuf v1.2.0 github.com/golang/protobuf v1.2.0
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
github.com/opencontainers/runc 029124da7af7360afa781a0234d1b083550f797c github.com/opencontainers/runc 029124da7af7360afa781a0234d1b083550f797c
@ -26,12 +26,12 @@ github.com/sirupsen/logrus v1.4.1
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
google.golang.org/grpc v1.12.0 google.golang.org/grpc v1.12.0
github.com/pkg/errors v0.8.0 github.com/pkg/errors v0.8.1
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7 github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
golang.org/x/sys d455e41777fca6e8a5a79e34a14b8368bc11d9ba https://github.com/golang/sys golang.org/x/sys d455e41777fca6e8a5a79e34a14b8368bc11d9ba https://github.com/golang/sys
github.com/opencontainers/image-spec v1.0.1 github.com/opencontainers/image-spec v1.0.1
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 github.com/BurntSushi/toml v0.3.1
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0 github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
github.com/Microsoft/go-winio c599b533b43b1363d7d7c6cfda5ede70ed73ff13 github.com/Microsoft/go-winio c599b533b43b1363d7d7c6cfda5ede70ed73ff13
github.com/Microsoft/hcsshim 8abdbb8205e4192c68b5f84c31197156f31be517 github.com/Microsoft/hcsshim 8abdbb8205e4192c68b5f84c31197156f31be517
@ -39,8 +39,8 @@ google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
github.com/containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6 github.com/containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
gotest.tools v2.1.0 gotest.tools v2.3.0
github.com/google/go-cmp v0.1.0 github.com/google/go-cmp v0.2.0
go.etcd.io/bbolt v1.3.2 go.etcd.io/bbolt v1.3.2
# cri dependencies # cri dependencies
@ -77,9 +77,10 @@ k8s.io/utils c2654d5206da6b7b6ace12841e8f359bb89b443c
sigs.k8s.io/yaml v1.1.0 sigs.k8s.io/yaml v1.1.0
# zfs dependencies # zfs dependencies
github.com/containerd/zfs 9f6ef3b1fe5144bd91fe5855b4eba81bc0d17d03 github.com/containerd/zfs 31af176f2ae84fe142ef2655bf7bb2aa618b3b1f
github.com/mistifyio/go-zfs 166add352731e515512690329794ee593f1aaff2 github.com/mistifyio/go-zfs d5b163290a48f624cbf244ebe4e89ce38653064c
github.com/pborman/uuid c65b2f87fee37d1c7854c9164a450713c28d50cd github.com/pborman/uuid v1.2.0
github.com/google/uuid v1.1.1
# aufs dependencies # aufs dependencies
github.com/containerd/aufs da3cf16bfbe68ba8f114f1536a05c01528a25434 github.com/containerd/aufs f894a800659b6e11c1a13084abd1712f346e349c

203
vendor/github.com/gogo/googleapis/LICENSE generated vendored Normal file
View File

@ -0,0 +1,203 @@
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 2015, Google Inc
Copyright 2018, GoGo 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.

View File

@ -3,17 +3,24 @@
package rpc package rpc
import proto "github.com/gogo/protobuf/proto" import (
import fmt "fmt" fmt "fmt"
import math "math" proto "github.com/gogo/protobuf/proto"
math "math"
import strconv "strconv" strconv "strconv"
)
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
var _ = fmt.Errorf var _ = fmt.Errorf
var _ = math.Inf var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// The canonical error codes for Google APIs. // The canonical error codes for Google APIs.
// //
// //
@ -181,6 +188,7 @@ var Code_name = map[int32]string{
14: "UNAVAILABLE", 14: "UNAVAILABLE",
15: "DATA_LOSS", 15: "DATA_LOSS",
} }
var Code_value = map[string]int32{ var Code_value = map[string]int32{
"OK": 0, "OK": 0,
"CANCELLED": 1, "CANCELLED": 1,
@ -201,22 +209,17 @@ var Code_value = map[string]int32{
"DATA_LOSS": 15, "DATA_LOSS": 15,
} }
func (Code) EnumDescriptor() ([]byte, []int) { return fileDescriptorCode, []int{0} } func (Code) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_fe593a732623ccf0, []int{0}
}
func init() { func init() {
proto.RegisterEnum("google.rpc.Code", Code_name, Code_value) proto.RegisterEnum("google.rpc.Code", Code_name, Code_value)
} }
func (x Code) String() string {
s, ok := Code_name[int32(x)]
if ok {
return s
}
return strconv.Itoa(int(x))
}
func init() { proto.RegisterFile("google/rpc/code.proto", fileDescriptorCode) } func init() { proto.RegisterFile("google/rpc/code.proto", fileDescriptor_fe593a732623ccf0) }
var fileDescriptorCode = []byte{ var fileDescriptor_fe593a732623ccf0 = []byte{
// 393 bytes of a gzipped FileDescriptorProto // 393 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x3d, 0x6e, 0x13, 0x41, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x3d, 0x6e, 0x13, 0x41,
0x14, 0xc7, 0x3d, 0x76, 0x70, 0xe2, 0xf1, 0xd7, 0xcb, 0x84, 0x40, 0x37, 0x07, 0xa0, 0x70, 0x0a, 0x14, 0xc7, 0x3d, 0x76, 0x70, 0xe2, 0xf1, 0xd7, 0xcb, 0x84, 0x40, 0x37, 0x07, 0xa0, 0x70, 0x0a,
@ -244,3 +247,11 @@ var fileDescriptorCode = []byte{
0xf3, 0xb5, 0x3f, 0x08, 0x65, 0xf1, 0x61, 0xf8, 0xb7, 0xaa, 0xd7, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xf3, 0xb5, 0x3f, 0x08, 0x65, 0xf1, 0x61, 0xf8, 0xb7, 0xaa, 0xd7, 0x7f, 0x02, 0x00, 0x00, 0xff,
0xff, 0x03, 0xd4, 0x27, 0xff, 0xc3, 0x01, 0x00, 0x00, 0xff, 0x03, 0xd4, 0x27, 0xff, 0xc3, 0x01, 0x00, 0x00,
} }
func (x Code) String() string {
s, ok := Code_name[int32(x)]
if ok {
return s
}
return strconv.Itoa(int(x))
}

View File

@ -22,7 +22,6 @@ option java_outer_classname = "CodeProto";
option java_package = "com.google.rpc"; option java_package = "com.google.rpc";
option objc_class_prefix = "RPC"; option objc_class_prefix = "RPC";
// The canonical error codes for Google APIs. // The canonical error codes for Google APIs.
// //
// //

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,6 @@ option java_outer_classname = "ErrorDetailsProto";
option java_package = "com.google.rpc"; option java_package = "com.google.rpc";
option objc_class_prefix = "RPC"; option objc_class_prefix = "RPC";
// Describes when the clients can retry a failed request. Clients could ignore // Describes when the clients can retry a failed request. Clients could ignore
// the recommendation here or retry when this information is missing from error // the recommendation here or retry when this information is missing from error
// responses. // responses.
@ -154,7 +153,8 @@ message ResourceInfo {
// The name of the resource being accessed. For example, a shared calendar // The name of the resource being accessed. For example, a shared calendar
// name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current // name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current
// error is [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED]. // error is
// [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED].
string resource_name = 2; string resource_name = 2;
// The owner of the resource (optional). // The owner of the resource (optional).

View File

@ -1,37 +1,18 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT. // Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: google/rpc/status.proto // source: google/rpc/status.proto
/*
Package rpc is a generated protocol buffer package.
It is generated from these files:
google/rpc/status.proto
google/rpc/error_details.proto
google/rpc/code.proto
It has these top-level messages:
Status
RetryInfo
DebugInfo
QuotaFailure
PreconditionFailure
BadRequest
RequestInfo
ResourceInfo
Help
LocalizedMessage
*/
package rpc package rpc
import proto "github.com/gogo/protobuf/proto" import (
import fmt "fmt" bytes "bytes"
import math "math" fmt "fmt"
import google_protobuf "github.com/gogo/protobuf/types" proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
import strings "strings" io "io"
import reflect "reflect" math "math"
reflect "reflect"
import io "io" strings "strings"
)
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
@ -44,24 +25,25 @@ var _ = math.Inf
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// The `Status` type defines a logical error model that is suitable for different // The `Status` type defines a logical error model that is suitable for
// programming environments, including REST APIs and RPC APIs. It is used by // different programming environments, including REST APIs and RPC APIs. It is
// [gRPC](https://github.com/grpc). The error model is designed to be: // used by [gRPC](https://github.com/grpc). The error model is designed to be:
// //
// - Simple to use and understand for most users // - Simple to use and understand for most users
// - Flexible enough to meet unexpected needs // - Flexible enough to meet unexpected needs
// //
// # Overview // # Overview
// //
// The `Status` message contains three pieces of data: error code, error message, // The `Status` message contains three pieces of data: error code, error
// and error details. The error code should be an enum value of // message, and error details. The error code should be an enum value of
// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The // [google.rpc.Code][google.rpc.Code], but it may accept additional error codes
// error message should be a developer-facing English message that helps // if needed. The error message should be a developer-facing English message
// developers *understand* and *resolve* the error. If a localized user-facing // that helps developers *understand* and *resolve* the error. If a localized
// error message is needed, put the localized message in the error details or // user-facing error message is needed, put the localized message in the error
// localize it in the client. The optional error details may contain arbitrary // details or localize it in the client. The optional error details may contain
// information about the error. There is a predefined set of error detail types // arbitrary information about the error. There is a predefined set of error
// in the package `google.rpc` that can be used for common error conditions. // detail types in the package `google.rpc` that can be used for common error
// conditions.
// //
// # Language mapping // # Language mapping
// //
@ -97,20 +79,53 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// - Logging. If some API errors are stored in logs, the message `Status` could // - Logging. If some API errors are stored in logs, the message `Status` could
// be used directly after any stripping needed for security/privacy reasons. // be used directly after any stripping needed for security/privacy reasons.
type Status struct { type Status struct {
// The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. // The status code, which should be an enum value of
// [google.rpc.Code][google.rpc.Code].
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
// A developer-facing error message, which should be in English. Any // A developer-facing error message, which should be in English. Any
// user-facing error message should be localized and sent in the // user-facing error message should be localized and sent in the
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. // [google.rpc.Status.details][google.rpc.Status.details] field, or localized
// by the client.
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
// A list of messages that carry the error details. There is a common set of // A list of messages that carry the error details. There is a common set of
// message types for APIs to use. // message types for APIs to use.
Details []*google_protobuf.Any `protobuf:"bytes,3,rep,name=details" json:"details,omitempty"` Details []*types.Any `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *Status) Reset() { *m = Status{} } func (m *Status) Reset() { *m = Status{} }
func (*Status) ProtoMessage() {} func (*Status) ProtoMessage() {}
func (*Status) Descriptor() ([]byte, []int) { return fileDescriptorStatus, []int{0} } func (*Status) Descriptor() ([]byte, []int) {
return fileDescriptor_24d244abaf643bfe, []int{0}
}
func (m *Status) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Status.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Status) XXX_Merge(src proto.Message) {
xxx_messageInfo_Status.Merge(m, src)
}
func (m *Status) XXX_Size() int {
return m.Size()
}
func (m *Status) XXX_DiscardUnknown() {
xxx_messageInfo_Status.DiscardUnknown(m)
}
var xxx_messageInfo_Status proto.InternalMessageInfo
func (m *Status) GetCode() int32 { func (m *Status) GetCode() int32 {
if m != nil { if m != nil {
@ -126,7 +141,7 @@ func (m *Status) GetMessage() string {
return "" return ""
} }
func (m *Status) GetDetails() []*google_protobuf.Any { func (m *Status) GetDetails() []*types.Any {
if m != nil { if m != nil {
return m.Details return m.Details
} }
@ -139,6 +154,28 @@ func (*Status) XXX_MessageName() string {
func init() { func init() {
proto.RegisterType((*Status)(nil), "google.rpc.Status") proto.RegisterType((*Status)(nil), "google.rpc.Status")
} }
func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptor_24d244abaf643bfe) }
var fileDescriptor_24d244abaf643bfe = []byte{
// 235 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81,
0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1,
0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83,
0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05,
0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7,
0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7,
0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0xb8, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94, 0x63, 0xf8,
0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31,
0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9,
0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0x3c, 0xf1, 0x58, 0x8e, 0x91, 0x8b, 0x2f, 0x39, 0x3f,
0x57, 0x0f, 0xe1, 0x11, 0x27, 0x6e, 0x88, 0x5b, 0x03, 0x40, 0x56, 0x04, 0x30, 0x46, 0x31, 0x17,
0x15, 0x24, 0x2f, 0x62, 0x62, 0x0e, 0x0a, 0x70, 0x4e, 0x62, 0x03, 0x5b, 0x6b, 0x0c, 0x08, 0x00,
0x00, 0xff, 0xff, 0xaa, 0x06, 0xa1, 0xaa, 0x10, 0x01, 0x00, 0x00,
}
func (this *Status) Compare(that interface{}) int { func (this *Status) Compare(that interface{}) int {
if that == nil { if that == nil {
if this == nil { if this == nil {
@ -187,6 +224,9 @@ func (this *Status) Compare(that interface{}) int {
return c return c
} }
} }
if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 {
return c
}
return 0 return 0
} }
func (this *Status) Equal(that interface{}) bool { func (this *Status) Equal(that interface{}) bool {
@ -222,6 +262,9 @@ func (this *Status) Equal(that interface{}) bool {
return false return false
} }
} }
if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
return false
}
return true return true
} }
func (this *Status) GoString() string { func (this *Status) GoString() string {
@ -235,6 +278,9 @@ func (this *Status) GoString() string {
if this.Details != nil { if this.Details != nil {
s = append(s, "Details: "+fmt.Sprintf("%#v", this.Details)+",\n") s = append(s, "Details: "+fmt.Sprintf("%#v", this.Details)+",\n")
} }
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}") s = append(s, "}")
return strings.Join(s, "") return strings.Join(s, "")
} }
@ -284,6 +330,9 @@ func (m *Status) MarshalTo(dAtA []byte) (int, error) {
i += n i += n
} }
} }
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
return i, nil return i, nil
} }
@ -305,12 +354,13 @@ func NewPopulatedStatus(r randyStatus, easy bool) *Status {
this.Message = string(randStringStatus(r)) this.Message = string(randStringStatus(r))
if r.Intn(10) != 0 { if r.Intn(10) != 0 {
v1 := r.Intn(5) v1 := r.Intn(5)
this.Details = make([]*google_protobuf.Any, v1) this.Details = make([]*types.Any, v1)
for i := 0; i < v1; i++ { for i := 0; i < v1; i++ {
this.Details[i] = google_protobuf.NewPopulatedAny(r, easy) this.Details[i] = types.NewPopulatedAny(r, easy)
} }
} }
if !easy && r.Intn(10) != 0 { if !easy && r.Intn(10) != 0 {
this.XXX_unrecognized = randUnrecognizedStatus(r, 4)
} }
return this return this
} }
@ -388,6 +438,9 @@ func encodeVarintPopulateStatus(dAtA []byte, v uint64) []byte {
return dAtA return dAtA
} }
func (m *Status) Size() (n int) { func (m *Status) Size() (n int) {
if m == nil {
return 0
}
var l int var l int
_ = l _ = l
if m.Code != 0 { if m.Code != 0 {
@ -403,6 +456,9 @@ func (m *Status) Size() (n int) {
n += 1 + l + sovStatus(uint64(l)) n += 1 + l + sovStatus(uint64(l))
} }
} }
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n return n
} }
@ -426,7 +482,8 @@ func (this *Status) String() string {
s := strings.Join([]string{`&Status{`, s := strings.Join([]string{`&Status{`,
`Code:` + fmt.Sprintf("%v", this.Code) + `,`, `Code:` + fmt.Sprintf("%v", this.Code) + `,`,
`Message:` + fmt.Sprintf("%v", this.Message) + `,`, `Message:` + fmt.Sprintf("%v", this.Message) + `,`,
`Details:` + strings.Replace(fmt.Sprintf("%v", this.Details), "Any", "google_protobuf.Any", 1) + `,`, `Details:` + strings.Replace(fmt.Sprintf("%v", this.Details), "Any", "types.Any", 1) + `,`,
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -454,7 +511,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
wire |= (uint64(b) & 0x7F) << shift wire |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -482,7 +539,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
m.Code |= (int32(b) & 0x7F) << shift m.Code |= int32(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -501,7 +558,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift stringLen |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -511,6 +568,9 @@ func (m *Status) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthStatus return ErrInvalidLengthStatus
} }
postIndex := iNdEx + intStringLen postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthStatus
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -530,7 +590,7 @@ func (m *Status) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
msglen |= (int(b) & 0x7F) << shift msglen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -539,10 +599,13 @@ func (m *Status) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthStatus return ErrInvalidLengthStatus
} }
postIndex := iNdEx + msglen postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthStatus
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Details = append(m.Details, &google_protobuf.Any{}) m.Details = append(m.Details, &types.Any{})
if err := m.Details[len(m.Details)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { if err := m.Details[len(m.Details)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err return err
} }
@ -556,9 +619,13 @@ func (m *Status) Unmarshal(dAtA []byte) error {
if skippy < 0 { if skippy < 0 {
return ErrInvalidLengthStatus return ErrInvalidLengthStatus
} }
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthStatus
}
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy iNdEx += skippy
} }
} }
@ -622,10 +689,13 @@ func skipStatus(dAtA []byte) (n int, err error) {
break break
} }
} }
iNdEx += length
if length < 0 { if length < 0 {
return 0, ErrInvalidLengthStatus return 0, ErrInvalidLengthStatus
} }
iNdEx += length
if iNdEx < 0 {
return 0, ErrInvalidLengthStatus
}
return iNdEx, nil return iNdEx, nil
case 3: case 3:
for { for {
@ -654,6 +724,9 @@ func skipStatus(dAtA []byte) (n int, err error) {
return 0, err return 0, err
} }
iNdEx = start + next iNdEx = start + next
if iNdEx < 0 {
return 0, ErrInvalidLengthStatus
}
} }
return iNdEx, nil return iNdEx, nil
case 4: case 4:
@ -672,24 +745,3 @@ var (
ErrInvalidLengthStatus = fmt.Errorf("proto: negative length found during unmarshaling") ErrInvalidLengthStatus = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowStatus = fmt.Errorf("proto: integer overflow") ErrIntOverflowStatus = fmt.Errorf("proto: integer overflow")
) )
func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptorStatus) }
var fileDescriptorStatus = []byte{
// 235 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81,
0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1,
0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83,
0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05,
0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7,
0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7,
0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0xb8, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94, 0x63, 0xf8,
0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31,
0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9,
0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0x3c, 0xf1, 0x58, 0x8e, 0x91, 0x8b, 0x2f, 0x39, 0x3f,
0x57, 0x0f, 0xe1, 0x11, 0x27, 0x6e, 0x88, 0x5b, 0x03, 0x40, 0x56, 0x04, 0x30, 0x46, 0x31, 0x17,
0x15, 0x24, 0x2f, 0x62, 0x62, 0x0e, 0x0a, 0x70, 0x4e, 0x62, 0x03, 0x5b, 0x6b, 0x0c, 0x08, 0x00,
0x00, 0xff, 0xff, 0xaa, 0x06, 0xa1, 0xaa, 0x10, 0x01, 0x00, 0x00,
}

View File

@ -24,25 +24,25 @@ option java_outer_classname = "StatusProto";
option java_package = "com.google.rpc"; option java_package = "com.google.rpc";
option objc_class_prefix = "RPC"; option objc_class_prefix = "RPC";
// The `Status` type defines a logical error model that is suitable for
// The `Status` type defines a logical error model that is suitable for different // different programming environments, including REST APIs and RPC APIs. It is
// programming environments, including REST APIs and RPC APIs. It is used by // used by [gRPC](https://github.com/grpc). The error model is designed to be:
// [gRPC](https://github.com/grpc). The error model is designed to be:
// //
// - Simple to use and understand for most users // - Simple to use and understand for most users
// - Flexible enough to meet unexpected needs // - Flexible enough to meet unexpected needs
// //
// # Overview // # Overview
// //
// The `Status` message contains three pieces of data: error code, error message, // The `Status` message contains three pieces of data: error code, error
// and error details. The error code should be an enum value of // message, and error details. The error code should be an enum value of
// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The // [google.rpc.Code][google.rpc.Code], but it may accept additional error codes
// error message should be a developer-facing English message that helps // if needed. The error message should be a developer-facing English message
// developers *understand* and *resolve* the error. If a localized user-facing // that helps developers *understand* and *resolve* the error. If a localized
// error message is needed, put the localized message in the error details or // user-facing error message is needed, put the localized message in the error
// localize it in the client. The optional error details may contain arbitrary // details or localize it in the client. The optional error details may contain
// information about the error. There is a predefined set of error detail types // arbitrary information about the error. There is a predefined set of error
// in the package `google.rpc` that can be used for common error conditions. // detail types in the package `google.rpc` that can be used for common error
// conditions.
// //
// # Language mapping // # Language mapping
// //
@ -78,12 +78,14 @@ option objc_class_prefix = "RPC";
// - Logging. If some API errors are stored in logs, the message `Status` could // - Logging. If some API errors are stored in logs, the message `Status` could
// be used directly after any stripping needed for security/privacy reasons. // be used directly after any stripping needed for security/privacy reasons.
message Status { message Status {
// The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. // The status code, which should be an enum value of
// [google.rpc.Code][google.rpc.Code].
int32 code = 1; int32 code = 1;
// A developer-facing error message, which should be in English. Any // A developer-facing error message, which should be in English. Any
// user-facing error message should be localized and sent in the // user-facing error message should be localized and sent in the
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. // [google.rpc.Status.details][google.rpc.Status.details] field, or localized
// by the client.
string message = 2; string message = 2;
// A list of messages that carry the error details. There is a common set of // A list of messages that carry the error details. There is a common set of

View File

@ -1,4 +1,4 @@
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) # errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
Package errors provides simple error handling primitives. Package errors provides simple error handling primitives.
@ -47,6 +47,6 @@ We welcome pull requests, bug fixes and issue reports. With that said, the bar f
Before proposing a change, please discuss your change by raising an issue. Before proposing a change, please discuss your change by raising an issue.
## Licence ## License
BSD-2-Clause BSD-2-Clause

View File

@ -6,7 +6,7 @@
// return err // return err
// } // }
// //
// which applied recursively up the call stack results in error reports // which when applied recursively up the call stack results in error reports
// without context or debugging information. The errors package allows // without context or debugging information. The errors package allows
// programmers to add context to the failure path in their code in a way // programmers to add context to the failure path in their code in a way
// that does not destroy the original value of the error. // that does not destroy the original value of the error.
@ -15,16 +15,17 @@
// //
// The errors.Wrap function returns a new error that adds context to the // The errors.Wrap function returns a new error that adds context to the
// original error by recording a stack trace at the point Wrap is called, // original error by recording a stack trace at the point Wrap is called,
// and the supplied message. For example // together with the supplied message. For example
// //
// _, err := ioutil.ReadAll(r) // _, err := ioutil.ReadAll(r)
// if err != nil { // if err != nil {
// return errors.Wrap(err, "read failed") // return errors.Wrap(err, "read failed")
// } // }
// //
// If additional control is required the errors.WithStack and errors.WithMessage // If additional control is required, the errors.WithStack and
// functions destructure errors.Wrap into its component operations of annotating // errors.WithMessage functions destructure errors.Wrap into its component
// an error with a stack trace and an a message, respectively. // operations: annotating an error with a stack trace and with a message,
// respectively.
// //
// Retrieving the cause of an error // Retrieving the cause of an error
// //
@ -38,7 +39,7 @@
// } // }
// //
// can be inspected by errors.Cause. errors.Cause will recursively retrieve // can be inspected by errors.Cause. errors.Cause will recursively retrieve
// the topmost error which does not implement causer, which is assumed to be // the topmost error that does not implement causer, which is assumed to be
// the original cause. For example: // the original cause. For example:
// //
// switch err := errors.Cause(err).(type) { // switch err := errors.Cause(err).(type) {
@ -48,16 +49,16 @@
// // unknown error // // unknown error
// } // }
// //
// causer interface is not exported by this package, but is considered a part // Although the causer interface is not exported by this package, it is
// of stable public API. // considered a part of its stable public interface.
// //
// Formatted printing of errors // Formatted printing of errors
// //
// All error values returned from this package implement fmt.Formatter and can // All error values returned from this package implement fmt.Formatter and can
// be formatted by the fmt package. The following verbs are supported // be formatted by the fmt package. The following verbs are supported:
// //
// %s print the error. If the error has a Cause it will be // %s print the error. If the error has a Cause it will be
// printed recursively // printed recursively.
// %v see %s // %v see %s
// %+v extended format. Each Frame of the error's StackTrace will // %+v extended format. Each Frame of the error's StackTrace will
// be printed in detail. // be printed in detail.
@ -65,13 +66,13 @@
// Retrieving the stack trace of an error or wrapper // Retrieving the stack trace of an error or wrapper
// //
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are // New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
// invoked. This information can be retrieved with the following interface. // invoked. This information can be retrieved with the following interface:
// //
// type stackTracer interface { // type stackTracer interface {
// StackTrace() errors.StackTrace // StackTrace() errors.StackTrace
// } // }
// //
// Where errors.StackTrace is defined as // The returned errors.StackTrace type is defined as
// //
// type StackTrace []Frame // type StackTrace []Frame
// //
@ -85,8 +86,8 @@
// } // }
// } // }
// //
// stackTracer interface is not exported by this package, but is considered a part // Although the stackTracer interface is not exported by this package, it is
// of stable public API. // considered a part of its stable public interface.
// //
// See the documentation for Frame.Format for more details. // See the documentation for Frame.Format for more details.
package errors package errors
@ -192,7 +193,7 @@ func Wrap(err error, message string) error {
} }
// Wrapf returns an error annotating err with a stack trace // Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is call, and the format specifier. // at the point Wrapf is called, and the format specifier.
// If err is nil, Wrapf returns nil. // If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error { func Wrapf(err error, format string, args ...interface{}) error {
if err == nil { if err == nil {
@ -220,6 +221,18 @@ func WithMessage(err error, message string) error {
} }
} }
// WithMessagef annotates err with the format specifier.
// If err is nil, WithMessagef returns nil.
func WithMessagef(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
}
}
type withMessage struct { type withMessage struct {
cause error cause error
msg string msg string

View File

@ -46,7 +46,8 @@ func (f Frame) line() int {
// //
// Format accepts flags that alter the printing of some verbs, as follows: // Format accepts flags that alter the printing of some verbs, as follows:
// //
// %+s path of source file relative to the compile time GOPATH // %+s function name and path of source file relative to the compile time
// GOPATH separated by \n\t (<funcname>\n\t<path>)
// %+v equivalent to %+s:%d // %+v equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) { func (f Frame) Format(s fmt.State, verb rune) {
switch verb { switch verb {
@ -79,6 +80,14 @@ func (f Frame) Format(s fmt.State, verb rune) {
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). // StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame type StackTrace []Frame
// Format formats the stack of Frames according to the fmt.Formatter interface.
//
// %s lists source files for each Frame in the stack
// %v lists the source file and line number for each Frame in the stack
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+v Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) { func (st StackTrace) Format(s fmt.State, verb rune) {
switch verb { switch verb {
case 'v': case 'v':
@ -136,43 +145,3 @@ func funcname(name string) string {
i = strings.Index(name, ".") i = strings.Index(name, ".")
return name[i+1:] return name[i+1:]
} }
func trimGOPATH(name, file string) string {
// Here we want to get the source file path relative to the compile time
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
// GOPATH at runtime, but we can infer the number of path segments in the
// GOPATH. We note that fn.Name() returns the function name qualified by
// the import path, which does not include the GOPATH. Thus we can trim
// segments from the beginning of the file path until the number of path
// separators remaining is one more than the number of path separators in
// the function name. For example, given:
//
// GOPATH /home/user
// file /home/user/src/pkg/sub/file.go
// fn.Name() pkg/sub.Type.Method
//
// We want to produce:
//
// pkg/sub/file.go
//
// From this we can easily see that fn.Name() has one less path separator
// than our desired output. We count separators from the end of the file
// path until it finds two more than in the function name and then move
// one character forward to preserve the initial path segment without a
// leading separator.
const sep = "/"
goal := strings.Count(name, sep) + 2
i := len(file)
for n := 0; n < goal; n++ {
i = strings.LastIndex(file[:i], sep)
if i == -1 {
// not enough separators found, set i so that the slice expression
// below leaves file unmodified
i = -len(sep)
break
}
}
// get back to 0 or trim the leading separator
file = file[i+len(sep):]
return file
}